[sundials] 01/02: New upstream version 3.1.0+dfsg

Dima Kogan dima at secretsauce.net
Wed Nov 22 08:38:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

dkogan pushed a commit to branch master
in repository sundials.

commit 7b9915c396a36d7b6dc9536a93ce717a16bd99cc
Author: Dima Kogan <dima at secretsauce.net>
Date:   Wed Nov 22 00:37:08 2017 -0800

    New upstream version 3.1.0+dfsg
---
 CMakeLists.txt                                     | 1487 ++++---
 README                                             |    8 +-
 config/FindHypre.cmake                             |    5 +-
 config/FindKLU.cmake                               |    4 +-
 config/FindMPI.cmake                               |   11 +
 config/FindPETSc.cmake                             |    3 -
 config/FindSUPERLUMT.cmake                         |   76 +-
 config/SundialsAddTest.cmake                       |  135 +-
 config/SundialsBlas.cmake                          |  101 +
 config/SundialsCMakeMacros.cmake                   |  118 +
 config/SundialsCXX.cmake                           |   49 +-
 config/SundialsDeprecated.cmake                    |   40 +
 config/SundialsFortran.cmake                       |   72 +-
 config/SundialsFortran90.cmake                     |   67 +-
 config/SundialsHypre.cmake                         |    4 +-
 config/SundialsKLU.cmake                           |   10 +-
 config/SundialsLapack.cmake                        |   46 +-
 config/SundialsMPIC.cmake                          |   15 +-
 config/SundialsMPICXX.cmake                        |   12 +-
 config/SundialsMPIF.cmake                          |   10 +-
 config/SundialsMPIF90.cmake                        |   12 +-
 config/SundialsPETSc.cmake                         |    4 +-
 config/SundialsSuperLUMT.cmake                     |   24 +-
 config/SundialsXSDK.cmake                          |  314 ++
 examples/arkode/CXX_parallel/CMakeLists.txt        |   99 +-
 examples/arkode/CXX_parallel/README                |    7 +-
 examples/arkode/CXX_parallel/ark_heat2D.cpp        |   90 +-
 examples/arkode/CXX_parallel/ark_heat2D.out        |    8 +-
 examples/arkode/CXX_serial/CMakeLists.txt          |  246 +-
 examples/arkode/CXX_serial/README                  |    7 +-
 examples/arkode/CXX_serial/ark_analytic_sys.cpp    |  177 +-
 examples/arkode/CXX_serial/ark_analytic_sys.out    |   30 +-
 examples/arkode/C_openmp/CMakeLists.txt            |  108 +-
 examples/arkode/C_openmp/README                    |    7 +-
 examples/arkode/C_openmp/ark_brusselator1D_omp.c   |  165 +-
 examples/arkode/C_parallel/CMakeLists.txt          |  100 +-
 examples/arkode/C_parallel/README                  |    7 +-
 examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c |   98 +-
 .../arkode/C_parallel/ark_diurnal_kry_bbd_p.out    |    8 +-
 examples/arkode/C_parallel/ark_diurnal_kry_p.c     |  104 +-
 examples/arkode/C_parallel/ark_diurnal_kry_p.out   |    2 +-
 examples/arkode/C_parhyp/CMakeLists.txt            |  102 +-
 examples/arkode/C_parhyp/README                    |    7 +-
 examples/arkode/C_parhyp/ark_diurnal_kry_ph.c      |   95 +-
 examples/arkode/C_parhyp/ark_diurnal_kry_ph.out    |    2 +-
 examples/arkode/C_serial/CMakeLists.txt            |  283 +-
 examples/arkode/C_serial/README                    |    7 +-
 examples/arkode/C_serial/ark_KrylovDemo_prec.c     |  118 +-
 examples/arkode/C_serial/ark_KrylovDemo_prec.out   |   32 +-
 examples/arkode/C_serial/ark_analytic.c            |  106 +-
 examples/arkode/C_serial/ark_analytic_nonlin.c     |   24 +-
 examples/arkode/C_serial/ark_brusselator.c         |   87 +-
 examples/arkode/C_serial/ark_brusselator1D.c       |  168 +-
 .../arkode/C_serial/ark_brusselator1D_FEM_slu.c    |  331 +-
 .../arkode/C_serial/ark_brusselator1D_FEM_slu.out  |    2 +
 examples/arkode/C_serial/ark_brusselator1D_klu.c   |  182 +-
 examples/arkode/C_serial/ark_brusselator_fp.c      |   26 +-
 examples/arkode/C_serial/ark_heat1D.c              |   77 +-
 examples/arkode/C_serial/ark_heat1D.out            |   10 +-
 examples/arkode/C_serial/ark_heat1D_adapt.c        |  134 +-
 examples/arkode/C_serial/ark_heat1D_adapt.out      |  246 +-
 examples/arkode/C_serial/ark_robertson.c           |  141 +-
 examples/arkode/C_serial/ark_robertson_root.c      |   88 +-
 examples/arkode/F77_parallel/CMakeLists.txt        |  112 +-
 examples/arkode/F77_parallel/README                |    7 +-
 examples/arkode/F77_parallel/fark_diag_kry_bbd_p.f |   36 +-
 .../arkode/F77_parallel/fark_diag_kry_bbd_p.out    |    8 +-
 examples/arkode/F77_parallel/fark_diag_non_p.f     |  108 +-
 examples/arkode/F77_serial/CMakeLists.txt          |  294 +-
 examples/arkode/F77_serial/README                  |    7 +-
 examples/arkode/F77_serial/fark_diurnal_kry_bp.f   |   37 +-
 examples/arkode/F77_serial/fark_diurnal_kry_bp.out |    4 +-
 examples/arkode/F77_serial/fark_roberts_dnsL.f     |   56 +-
 examples/arkode/F90_parallel/CMakeLists.txt        |  104 +-
 examples/arkode/F90_parallel/README                |    7 +-
 examples/arkode/F90_parallel/fark_heat2D.f90       |  108 +-
 examples/arkode/F90_parallel/fark_heat2D.out       |   14 +-
 examples/arkode/F90_serial/CMakeLists.txt          |  302 +-
 examples/arkode/F90_serial/README                  |    7 +-
 examples/arkode/F90_serial/ark_bruss.f90           |   64 +-
 examples/arkode/F90_serial/ark_bruss1D_FEM_klu.f90 |  119 +-
 examples/arkode/F90_serial/ark_bruss1D_FEM_klu.out |    2 +-
 examples/cvode/C_openmp/CMakeLists.txt             |   80 +-
 examples/cvode/C_openmp/README                     |    7 +-
 examples/cvode/C_openmp/cvAdvDiff_bnd_omp.c        |  103 +-
 examples/cvode/cuda/CMakeLists.txt                 |  124 +
 examples/cvode/cuda/README                         |    3 +
 examples/cvode/cuda/cvAdvDiff_kry_cuda.cu          |  496 +++
 examples/cvode/cuda/cvAdvDiff_kry_cuda.out         |   29 +
 examples/cvode/fcmix_parallel/CMakeLists.txt       |  114 +-
 examples/cvode/fcmix_parallel/README               |    7 +-
 examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f  |   75 +-
 .../cvode/fcmix_parallel/fcvDiag_kry_bbd_p.out     |   84 +-
 examples/cvode/fcmix_parallel/fcvDiag_kry_p.f      |  182 +-
 examples/cvode/fcmix_parallel/fcvDiag_kry_p.out    |   68 +-
 examples/cvode/fcmix_parallel/fcvDiag_non_p.f      |  117 +-
 examples/cvode/fcmix_parallel/fcvDiag_non_p.out    |   32 +-
 examples/cvode/fcmix_serial/CMakeLists.txt         |  293 +-
 examples/cvode/fcmix_serial/README                 |    9 +-
 examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f       |   60 +-
 examples/cvode/fcmix_serial/fcvDiurnal_kry.f       |  107 +-
 examples/cvode/fcmix_serial/fcvDiurnal_kry.out     |   58 +-
 examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f    |  115 +-
 examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out  |    4 +-
 examples/cvode/fcmix_serial/fcvRoberts_dns.f       |  144 +-
 examples/cvode/fcmix_serial/fcvRoberts_dns.out     |   32 +-
 examples/cvode/fcmix_serial/fcvRoberts_dnsL.f      |  147 +-
 examples/cvode/fcmix_serial/fcvRoberts_dnsL.out    |   32 +-
 examples/cvode/fcmix_serial/fcvRoberts_klu.f       |  433 +-
 examples/cvode/fcmix_serial/fcvRoberts_klu.out     |    8 +-
 examples/cvode/fcmix_serial/fcvRoberts_sps.f       |  429 +-
 examples/cvode/fcmix_serial/fcvRoberts_sps.out     |    4 +-
 examples/cvode/parallel/CMakeLists.txt             |  110 +-
 examples/cvode/parallel/README                     |    7 +-
 examples/cvode/parallel/cvAdvDiff_diag_p.c         |   57 +-
 examples/cvode/parallel/cvAdvDiff_non_p.c          |   50 +-
 examples/cvode/parallel/cvAdvDiff_non_p.out        |   18 +-
 examples/cvode/parallel/cvDiurnal_kry_bbd_p.c      |  114 +-
 examples/cvode/parallel/cvDiurnal_kry_bbd_p.out    |  120 +-
 examples/cvode/parallel/cvDiurnal_kry_p.c          |  106 +-
 examples/cvode/parallel/cvDiurnal_kry_p.out        |   60 +-
 examples/cvode/parhyp/CMakeLists.txt               |  109 +-
 examples/cvode/parhyp/README                       |   14 +-
 examples/cvode/parhyp/cvAdvDiff_non_ph.c           |   13 +-
 examples/cvode/raja/CMakeLists.txt                 |  124 +
 examples/cvode/raja/README                         |    3 +
 .../cvAdvDiff_bnd.c => raja/cvAdvDiff_kry_raja.cu} |  385 +-
 examples/cvode/raja/cvAdvDiff_kry_raja.out         |   29 +
 examples/cvode/serial/CMakeLists.txt               |  288 +-
 examples/cvode/serial/README                       |    7 +-
 examples/cvode/serial/cvAdvDiff_bnd.c              |  114 +-
 examples/cvode/serial/cvAdvDiff_bndL.c             |   86 +-
 examples/cvode/serial/cvDirectDemo_ls.c            |  251 +-
 examples/cvode/serial/cvDirectDemo_ls.out          |  122 +-
 examples/cvode/serial/cvDiurnal_kry.c              |  123 +-
 examples/cvode/serial/cvDiurnal_kry.out            |   44 +-
 examples/cvode/serial/cvDiurnal_kry_bp.c           |   89 +-
 examples/cvode/serial/cvDiurnal_kry_bp.out         |  102 +-
 examples/cvode/serial/cvKrylovDemo_ls.c            |  124 +-
 examples/cvode/serial/cvKrylovDemo_ls.out          |  132 +-
 examples/cvode/serial/cvKrylovDemo_prec.c          |  141 +-
 examples/cvode/serial/cvKrylovDemo_prec.out        |  320 +-
 examples/cvode/serial/cvRoberts_dns.c              |  136 +-
 examples/cvode/serial/cvRoberts_dns.out            |   26 +-
 examples/cvode/serial/cvRoberts_dnsL.c             |   80 +-
 examples/cvode/serial/cvRoberts_dnsL.out           |   26 +-
 examples/cvode/serial/cvRoberts_dns_uw.c           |   85 +-
 examples/cvode/serial/cvRoberts_dns_uw.out         |   26 +-
 examples/cvode/serial/cvRoberts_klu.c              |   93 +-
 examples/cvode/serial/cvRoberts_klu.out            |   30 +-
 examples/cvode/serial/cvRoberts_sps.c              |  109 +-
 examples/cvodes/C_openmp/CMakeLists.txt            |  114 +-
 examples/cvodes/C_openmp/README                    |    7 +-
 examples/cvodes/C_openmp/cvsAdvDiff_bnd_omp.c      |   96 +-
 examples/cvodes/parallel/CMakeLists.txt            |  155 +-
 examples/cvodes/parallel/README                    |    7 +-
 examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c   |   43 +-
 examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out |   51 +-
 examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c    |   25 +-
 ...p.out => cvsAdvDiff_FSA_non_p_-sensi_sim_t.out} |   64 +-
 .../parallel/cvsAdvDiff_FSA_non_p_-sensi_stg_t.out |   71 +
 examples/cvodes/parallel/cvsAdvDiff_non_p.c        |   16 +-
 examples/cvodes/parallel/cvsAdvDiff_non_p.out      |   18 +-
 .../cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c    |   81 +-
 .../cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out  |    4 +-
 examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c    |  136 +-
 ...p.out => cvsDiurnal_FSA_kry_p_-sensi_sim_t.out} |   90 +-
 ...p.out => cvsDiurnal_FSA_kry_p_-sensi_stg_t.out} |  108 +-
 examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c    |  106 +-
 examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out  |  120 +-
 examples/cvodes/parallel/cvsDiurnal_kry_p.c        |  109 +-
 examples/cvodes/parallel/cvsDiurnal_kry_p.out      |   60 +-
 examples/cvodes/serial/CMakeLists.txt              |  430 +-
 examples/cvodes/serial/README                      |   16 +-
 examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c       |  138 +-
 examples/cvodes/serial/cvsAdvDiff_FSA_non.c        |   35 +-
 ...non.out => cvsAdvDiff_FSA_non_-sensi_sim_t.out} |   62 +-
 .../serial/cvsAdvDiff_FSA_non_-sensi_stg_t.out     |   69 +
 examples/cvodes/serial/cvsAdvDiff_bnd.c            |   86 +-
 examples/cvodes/serial/cvsAdvDiff_bndL.c           |   78 +-
 examples/cvodes/serial/cvsDirectDemo_ls.c          |  250 +-
 examples/cvodes/serial/cvsDirectDemo_ls.out        |  116 +-
 examples/cvodes/serial/cvsDiurnal_FSA_kry.c        |  103 +-
 ...kry.out => cvsDiurnal_FSA_kry_-sensi_sim_t.out} |   92 +-
 ...kry.out => cvsDiurnal_FSA_kry_-sensi_stg_t.out} |  100 +-
 examples/cvodes/serial/cvsDiurnal_kry.c            |   97 +-
 examples/cvodes/serial/cvsDiurnal_kry.out          |   44 +-
 examples/cvodes/serial/cvsDiurnal_kry_bp.c         |   71 +-
 examples/cvodes/serial/cvsDiurnal_kry_bp.out       |   98 +-
 examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c       |  154 +-
 examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out     |   16 +-
 examples/cvodes/serial/cvsFoodWeb_ASAp_kry.c       |  145 +-
 examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out     |   20 +-
 examples/cvodes/serial/cvsHessian_ASA_FSA.c        |  334 +-
 examples/cvodes/serial/cvsKrylovDemo_ls.c          |  123 +-
 examples/cvodes/serial/cvsKrylovDemo_ls.out        |  132 +-
 examples/cvodes/serial/cvsKrylovDemo_prec.c        |  143 +-
 examples/cvodes/serial/cvsKrylovDemo_prec.out      |  180 +-
 examples/cvodes/serial/cvsRoberts_ASAi_dns.c       |  177 +-
 examples/cvodes/serial/cvsRoberts_ASAi_dns.out     |   16 +-
 examples/cvodes/serial/cvsRoberts_ASAi_klu.c       |  218 +-
 examples/cvodes/serial/cvsRoberts_ASAi_sps.c       |  238 +-
 examples/cvodes/serial/cvsRoberts_FSA_dns.c        |  119 +-
 ...dns.out => cvsRoberts_FSA_dns_-sensi_sim_t.out} |    0
 .../serial/cvsRoberts_FSA_dns_-sensi_stg1_t.out    |   93 +
 examples/cvodes/serial/cvsRoberts_FSA_klu.c        |  167 +-
 ...lu.out => cvsRoberts_FSA_klu_-sensi_stg1_t.out} |    0
 examples/cvodes/serial/cvsRoberts_FSA_sps.c        |  174 +-
 ...ps.out => cvsRoberts_FSA_sps_-sensi_stg1_t.out} |    0
 examples/cvodes/serial/cvsRoberts_dns.c            |  137 +-
 examples/cvodes/serial/cvsRoberts_dns.out          |   26 +-
 examples/cvodes/serial/cvsRoberts_dnsL.c           |   77 +-
 examples/cvodes/serial/cvsRoberts_dnsL.out         |   26 +-
 examples/cvodes/serial/cvsRoberts_dns_uw.c         |   85 +-
 examples/cvodes/serial/cvsRoberts_dns_uw.out       |   26 +-
 examples/cvodes/serial/cvsRoberts_klu.c            |   93 +-
 examples/cvodes/serial/cvsRoberts_klu.out          |   30 +-
 examples/cvodes/serial/cvsRoberts_sps.c            |  109 +-
 examples/ida/C_openmp/CMakeLists.txt               |  149 +-
 examples/ida/C_openmp/README                       |    7 +-
 examples/ida/C_openmp/idaFoodWeb_bnd_omp.c         |  125 +-
 examples/ida/C_openmp/idaFoodWeb_bnd_omp.out       |    2 +-
 examples/ida/C_openmp/idaFoodWeb_kry_omp.c         |  159 +-
 examples/ida/fcmix_openmp/CMakeLists.txt           |  130 +-
 examples/ida/fcmix_openmp/README                   |    7 +-
 examples/ida/fcmix_openmp/fidaRoberts_dns_openmp.f |   61 +-
 examples/ida/fcmix_parallel/CMakeLists.txt         |  103 +-
 examples/ida/fcmix_parallel/README                 |    7 +-
 examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f |  160 +-
 .../ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out    |   26 +-
 examples/ida/fcmix_pthreads/CMakeLists.txt         |  125 +-
 examples/ida/fcmix_pthreads/README                 |    7 +-
 .../ida/fcmix_pthreads/fidaRoberts_dns_pthreads.f  |   61 +-
 examples/ida/fcmix_serial/CMakeLists.txt           |  121 +-
 examples/ida/fcmix_serial/README                   |    7 +-
 examples/ida/fcmix_serial/fidaRoberts_dns.f        |   50 +-
 examples/ida/parallel/CMakeLists.txt               |  108 +-
 examples/ida/parallel/README                       |    7 +-
 examples/ida/parallel/idaFoodWeb_kry_bbd_p.c       |  133 +-
 examples/ida/parallel/idaFoodWeb_kry_bbd_p.out     |   46 +-
 examples/ida/parallel/idaFoodWeb_kry_p.c           |  166 +-
 examples/ida/parallel/idaFoodWeb_kry_p.out         |   18 +-
 examples/ida/parallel/idaHeat2D_kry_bbd_p.c        |  136 +-
 examples/ida/parallel/idaHeat2D_kry_bbd_p.out      |   31 +-
 examples/ida/parallel/idaHeat2D_kry_p.c            |  203 +-
 examples/ida/parallel/idaHeat2D_kry_p.out          |   10 +-
 examples/ida/petsc/CMakeLists.txt                  |  100 +-
 examples/ida/petsc/README                          |   11 +-
 examples/ida/petsc/idaHeat2D_kry_petsc.c           |  136 +-
 examples/ida/petsc/idaHeat2D_kry_petsc.out         |   14 +-
 examples/ida/serial/CMakeLists.txt                 |  323 +-
 examples/ida/serial/README                         |    9 +-
 examples/ida/serial/idaFoodWeb_bnd.c               |   85 +-
 examples/ida/serial/idaFoodWeb_bnd.out             |    2 +-
 examples/ida/serial/idaFoodWeb_kry.c               |  107 +-
 examples/ida/serial/idaFoodWeb_kry.out             |    2 +-
 examples/ida/serial/idaHeat2D_bnd.c                |   77 +-
 examples/ida/serial/idaHeat2D_bnd.out              |   26 +-
 examples/ida/serial/idaHeat2D_klu.c                |  153 +-
 examples/ida/serial/idaHeat2D_klu.out              |    2 +-
 examples/ida/serial/idaHeat2D_kry.c                |   94 +-
 examples/ida/serial/idaHeat2D_kry.out              |   20 +-
 examples/ida/serial/idaKrylovDemo_ls.c             |  116 +-
 examples/ida/serial/idaKrylovDemo_ls.out           |   28 +-
 examples/ida/serial/idaRoberts_dns.c               |  145 +-
 examples/ida/serial/idaRoberts_dns.out             |   42 +-
 examples/ida/serial/idaRoberts_klu.c               |  146 +-
 examples/ida/serial/idaRoberts_klu.out             |    2 +-
 examples/ida/serial/idaRoberts_sps.c               |  135 +-
 examples/ida/serial/idaRoberts_sps.out             |   26 +-
 examples/ida/serial/idaSlCrank_dns.c               |  106 +-
 examples/ida/serial/idaSlCrank_dns.out             |    4 +-
 examples/idas/C_openmp/CMakeLists.txt              |  120 +-
 examples/idas/C_openmp/README                      |    7 +-
 examples/idas/C_openmp/idasFoodWeb_bnd_omp.c       |  125 +-
 examples/idas/C_openmp/idasFoodWeb_bnd_omp.out     |    2 +-
 examples/idas/C_openmp/idasFoodWeb_kry_omp.c       |  161 +-
 examples/idas/parallel/CMakeLists.txt              |  149 +-
 examples/idas/parallel/README                      |    7 +-
 examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c  |  185 +-
 .../idas/parallel/idasBruss_ASAp_kry_bbd_p.out     |    8 +-
 examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c   |  176 +-
 examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out |    9 +-
 examples/idas/parallel/idasBruss_kry_bbd_p.c       |  179 +-
 examples/idas/parallel/idasBruss_kry_bbd_p.out     |    3 +-
 examples/idas/parallel/idasFoodWeb_kry_bbd_p.c     |  138 +-
 examples/idas/parallel/idasFoodWeb_kry_bbd_p.out   |   27 +-
 examples/idas/parallel/idasFoodWeb_kry_p.c         |  167 +-
 examples/idas/parallel/idasFoodWeb_kry_p.out       |   19 +-
 examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c  |  159 +-
 .../idas/parallel/idasHeat2D_FSA_kry_bbd_p.out     |   57 -
 .../idasHeat2D_FSA_kry_bbd_p_-sensi_stg_t.out      |   58 +
 examples/idas/parallel/idasHeat2D_kry_bbd_p.c      |  134 +-
 examples/idas/parallel/idasHeat2D_kry_bbd_p.out    |   32 +-
 examples/idas/parallel/idasHeat2D_kry_p.c          |  203 +-
 examples/idas/parallel/idasHeat2D_kry_p.out        |   18 +-
 examples/idas/serial/CMakeLists.txt                |  433 +-
 examples/idas/serial/README                        |   13 +-
 examples/idas/serial/idasAkzoNob_ASAi_dns.c        |  115 +-
 examples/idas/serial/idasAkzoNob_dns.c             |   99 +-
 examples/idas/serial/idasAkzoNob_dns.out           |    4 +-
 examples/idas/serial/idasFoodWeb_bnd.c             |   89 +-
 examples/idas/serial/idasFoodWeb_bnd.out           |    2 +-
 examples/idas/serial/idasHeat2D_bnd.c              |   77 +-
 examples/idas/serial/idasHeat2D_bnd.out            |   26 +-
 examples/idas/serial/idasHeat2D_kry.c              |   98 +-
 examples/idas/serial/idasHeat2D_kry.out            |   20 +-
 examples/idas/serial/idasHessian_ASA_FSA.c         |  200 +-
 examples/idas/serial/idasKrylovDemo_ls.c           |  119 +-
 examples/idas/serial/idasKrylovDemo_ls.out         |   28 +-
 examples/idas/serial/idasRoberts_ASAi_dns.c        |  108 +-
 examples/idas/serial/idasRoberts_ASAi_dns.out      |   11 +-
 examples/idas/serial/idasRoberts_ASAi_klu.c        |  192 +-
 examples/idas/serial/idasRoberts_ASAi_sps.c        |  194 +-
 examples/idas/serial/idasRoberts_FSA_dns.c         |  111 +-
 ...ns.out => idasRoberts_FSA_dns_-sensi_stg_t.out} |  100 +-
 examples/idas/serial/idasRoberts_FSA_klu.c         |  166 +-
 ...lu.out => idasRoberts_FSA_klu_-sensi_stg_t.out} |    0
 examples/idas/serial/idasRoberts_FSA_sps.c         |  168 +-
 ...ps.out => idasRoberts_FSA_sps_-sensi_stg_t.out} |    0
 examples/idas/serial/idasRoberts_dns.c             |  147 +-
 examples/idas/serial/idasRoberts_dns.out           |   12 +-
 examples/idas/serial/idasRoberts_klu.c             |  123 +-
 examples/idas/serial/idasRoberts_klu.out           |    2 +-
 examples/idas/serial/idasRoberts_sps.c             |  133 +-
 examples/idas/serial/idasRoberts_sps.out           |   26 +-
 examples/idas/serial/idasSlCrank_FSA_dns.c         |  104 +-
 examples/idas/serial/idasSlCrank_FSA_dns.out       |   14 +-
 examples/idas/serial/idasSlCrank_dns.c             |  113 +-
 examples/idas/serial/idasSlCrank_dns.out           |    4 +-
 examples/kinsol/C_openmp/CMakeLists.txt            |   82 +-
 examples/kinsol/C_openmp/README                    |    7 +-
 examples/kinsol/C_openmp/kinFoodWeb_kry_omp.c      |  138 +-
 examples/kinsol/fcmix_parallel/CMakeLists.txt      |   87 +-
 examples/kinsol/fcmix_parallel/README              |    7 +-
 examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f  |  160 +-
 examples/kinsol/fcmix_serial/CMakeLists.txt        |   95 +-
 examples/kinsol/fcmix_serial/README                |    7 +-
 examples/kinsol/fcmix_serial/fkinDiagon_kry.f      |   83 +-
 examples/kinsol/parallel/CMakeLists.txt            |  102 +-
 examples/kinsol/parallel/README                    |    7 +-
 examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c    |  175 +-
 examples/kinsol/parallel/kinFoodWeb_kry_p.c        |  217 +-
 examples/kinsol/serial/CMakeLists.txt              |  285 +-
 examples/kinsol/serial/README                      |    8 +-
 examples/kinsol/serial/kinFerTron_dns.c            |   54 +-
 examples/kinsol/serial/kinFerTron_klu.c            |  140 +-
 examples/kinsol/serial/kinFoodWeb_kry.c            |  120 +-
 examples/kinsol/serial/kinFoodWeb_kry.out          |    6 +-
 examples/kinsol/serial/kinKrylovDemo_ls.c          |  130 +-
 examples/kinsol/serial/kinKrylovDemo_ls.out        |    8 +-
 examples/kinsol/serial/kinLaplace_bnd.c            |   52 +-
 examples/kinsol/serial/kinLaplace_bnd.out          |    4 +-
 examples/kinsol/serial/kinLaplace_picard_bnd.c     |   94 +-
 examples/kinsol/serial/kinLaplace_picard_bnd.out   |    2 +-
 examples/kinsol/serial/kinRoberts_fp.c             |   71 +-
 examples/kinsol/serial/kinRoboKin_dns.c            |   56 +-
 examples/kinsol/serial/kinRoboKin_slu.c            |  183 +-
 examples/nvector/C_openmp/CMakeLists.txt           |  104 +-
 examples/nvector/C_openmp/test_nvector_openmp.c    |   37 +-
 examples/nvector/cuda/CMakeLists.txt               |  151 +
 .../test_nvector_cuda.cu}                          |  118 +-
 examples/nvector/parallel/CMakeLists.txt           |  125 +-
 examples/nvector/parallel/test_nvector_mpi.c       |   39 +-
 examples/nvector/parhyp/CMakeLists.txt             |  129 +-
 examples/nvector/parhyp/test_nvector_parhyp.c      |   51 +-
 examples/nvector/petsc/CMakeLists.txt              |  128 +-
 examples/nvector/petsc/test_nvector_petsc.c        |   43 +-
 examples/nvector/pthreads/CMakeLists.txt           |  113 +-
 examples/nvector/pthreads/test_nvector_pthreads.c  |   36 +-
 examples/nvector/raja/CMakeLists.txt               |  149 +
 .../test_nvector_raja.cu}                          |  119 +-
 examples/nvector/serial/CMakeLists.txt             |  100 +-
 examples/nvector/serial/test_nvector_serial.c      |   29 +-
 examples/nvector/test_nvector.c                    |   84 +-
 examples/nvector/test_nvector.h                    |   54 +-
 examples/sunlinsol/band/CMakeLists.txt             |  171 +
 examples/sunlinsol/band/test_sunlinsol_band.c      |  184 +
 examples/sunlinsol/dense/CMakeLists.txt            |  170 +
 examples/sunlinsol/dense/test_sunlinsol_dense.c    |  181 +
 examples/sunlinsol/klu/CMakeLists.txt              |  175 +
 examples/sunlinsol/klu/test_sunlinsol_klu.c        |  183 +
 examples/sunlinsol/lapackband/CMakeLists.txt       |  177 +
 .../lapackband/test_sunlinsol_lapackband.c         |  184 +
 examples/sunlinsol/lapackdense/CMakeLists.txt      |  177 +
 .../lapackdense/test_sunlinsol_lapackdense.c       |  181 +
 examples/sunlinsol/pcg/serial/CMakeLists.txt       |  158 +
 .../pcg/serial/test_sunlinsol_pcg_serial.c         |  444 ++
 examples/sunlinsol/spbcgs/parallel/CMakeLists.txt  |  174 +
 .../parallel/test_sunlinsol_spbcgs_parallel.c      |  590 +++
 examples/sunlinsol/spbcgs/serial/CMakeLists.txt    |  159 +
 .../spbcgs/serial/test_sunlinsol_spbcgs_serial.c   |  519 +++
 examples/sunlinsol/spfgmr/parallel/CMakeLists.txt  |  174 +
 .../parallel/test_sunlinsol_spfgmr_parallel.c      |  593 +++
 examples/sunlinsol/spfgmr/serial/CMakeLists.txt    |  159 +
 .../spfgmr/serial/test_sunlinsol_spfgmr_serial.c   |  522 +++
 examples/sunlinsol/spgmr/parallel/CMakeLists.txt   |  176 +
 .../spgmr/parallel/test_sunlinsol_spgmr_parallel.c |  600 +++
 examples/sunlinsol/spgmr/serial/CMakeLists.txt     |  161 +
 .../spgmr/serial/test_sunlinsol_spgmr_serial.c     |  529 +++
 examples/sunlinsol/sptfqmr/parallel/CMakeLists.txt |  174 +
 .../parallel/test_sunlinsol_sptfqmr_parallel.c     |  592 +++
 examples/sunlinsol/sptfqmr/serial/CMakeLists.txt   |  159 +
 .../sptfqmr/serial/test_sunlinsol_sptfqmr_serial.c |  524 +++
 examples/sunlinsol/superlumt/CMakeLists.txt        |  182 +
 .../sunlinsol/superlumt/test_sunlinsol_superlumt.c |  189 +
 examples/sunlinsol/test_sunlinsol.c                |  429 ++
 examples/sunlinsol/test_sunlinsol.h                |   67 +
 examples/sunmatrix/band/CMakeLists.txt             |  161 +
 examples/sunmatrix/band/test_sunmatrix_band.c      |  264 ++
 examples/sunmatrix/dense/CMakeLists.txt            |  160 +
 examples/sunmatrix/dense/test_sunmatrix_dense.c    |  263 ++
 examples/sunmatrix/sparse/CMakeLists.txt           |  172 +
 examples/sunmatrix/sparse/test_sunmatrix_sparse.c  |  509 +++
 examples/sunmatrix/test_sunmatrix.c                |  557 +++
 examples/sunmatrix/test_sunmatrix.h                |   66 +
 ...pthreads_C_ex.in => cmakelists_cuda_CUDA_ex.in} |   57 +-
 examples/templates/cmakelists_openmp_C_ex.in       |  161 +-
 examples/templates/cmakelists_openmp_F77_ex.in     |  196 +-
 examples/templates/cmakelists_parallel_CXX_ex.in   |   51 +-
 examples/templates/cmakelists_parallel_C_ex.in     |   52 +-
 examples/templates/cmakelists_parallel_F77_ex.in   |   72 +-
 examples/templates/cmakelists_parallel_F90_ex.in   |   65 +-
 examples/templates/cmakelists_parhyp_C_ex.in       |   60 +-
 examples/templates/cmakelists_petsc_C_ex.in        |   59 +-
 examples/templates/cmakelists_pthreads_C_ex.in     |  149 +-
 examples/templates/cmakelists_pthreads_F77_ex.in   |  189 +-
 ...pthreads_C_ex.in => cmakelists_raja_CUDA_ex.in} |   61 +-
 examples/templates/cmakelists_serial_CXX_ex.in     |  147 +-
 examples/templates/cmakelists_serial_C_ex.in       |  162 +-
 examples/templates/cmakelists_serial_F77_ex.in     |  191 +-
 examples/templates/cmakelists_serial_F90_ex.in     |  182 +-
 examples/templates/makefile_cuda_CUDA_ex.in        |   81 +
 examples/templates/makefile_openmp_C_ex.in         |  116 +-
 examples/templates/makefile_openmp_F77_ex.in       |  103 +-
 examples/templates/makefile_parallel_CXX_ex.in     |   48 +-
 examples/templates/makefile_parallel_C_ex.in       |   37 +-
 examples/templates/makefile_parallel_F77_ex.in     |   40 +-
 examples/templates/makefile_parallel_F90_ex.in     |   49 +-
 examples/templates/makefile_parhyp_C_ex.in         |   66 +-
 examples/templates/makefile_petsc_C_ex.in          |   74 +-
 examples/templates/makefile_pthreads_C_ex.in       |  114 +-
 examples/templates/makefile_pthreads_F77_ex.in     |  103 +-
 examples/templates/makefile_raja_CUDA_ex.in        |   83 +
 examples/templates/makefile_serial_CXX_ex.in       |  105 +-
 examples/templates/makefile_serial_C_ex.in         |  114 +-
 examples/templates/makefile_serial_F77_ex.in       |   97 +-
 examples/templates/makefile_serial_F90_ex.in       |  102 +-
 include/arkode/arkode.h                            |   19 +-
 include/arkode/arkode_band.h                       |   94 -
 include/arkode/arkode_bandpre.h                    |   65 +-
 include/arkode/arkode_bbdpre.h                     |  123 +-
 include/arkode/arkode_dense.h                      |   77 -
 include/arkode/arkode_direct.h                     |  325 +-
 include/arkode/arkode_klu.h                        |  195 -
 include/arkode/arkode_lapack.h                     |  134 -
 include/arkode/arkode_pcg.h                        |  116 -
 include/arkode/arkode_sparse.h                     |  216 -
 include/arkode/arkode_spbcgs.h                     |  106 -
 include/arkode/arkode_spfgmr.h                     |  115 -
 include/arkode/arkode_spgmr.h                      |  109 -
 include/arkode/arkode_spils.h                      |  350 +-
 include/arkode/arkode_sptfqmr.h                    |  104 -
 include/arkode/arkode_superlumt.h                  |  138 -
 include/cvode/cvode.h                              |    8 +-
 include/cvode/cvode_band.h                         |   66 -
 include/cvode/cvode_bandpre.h                      |  247 +-
 include/cvode/cvode_bbdpre.h                       |  488 +--
 include/cvode/cvode_dense.h                        |   59 -
 include/cvode/cvode_diag.h                         |    3 -
 include/cvode/cvode_direct.h                       |  399 +-
 include/cvode/cvode_klu.h                          |  111 -
 include/cvode/cvode_lapack.h                       |   91 -
 include/cvode/cvode_sparse.h                       |  182 -
 include/cvode/cvode_spbcgs.h                       |   72 -
 include/cvode/cvode_spgmr.h                        |   74 -
 include/cvode/cvode_spils.h                        |  652 +--
 include/cvode/cvode_sptfqmr.h                      |   72 -
 include/cvode/cvode_superlumt.h                    |   84 -
 include/cvodes/cvodes.h                            |   14 +-
 include/cvodes/cvodes_band.h                       |   78 -
 include/cvodes/cvodes_bandpre.h                    |  291 +-
 include/cvodes/cvodes_bbdpre.h                     |  570 +--
 include/cvodes/cvodes_dense.h                      |   70 -
 include/cvodes/cvodes_diag.h                       |    3 -
 include/cvodes/cvodes_direct.h                     |  587 +--
 include/cvodes/cvodes_klu.h                        |  156 -
 include/cvodes/cvodes_lapack.h                     |  110 -
 include/cvodes/cvodes_sparse.h                     |  255 --
 include/cvodes/cvodes_spbcgs.h                     |  102 -
 include/cvodes/cvodes_spgmr.h                      |  103 -
 include/cvodes/cvodes_spils.h                      |  892 ++--
 include/cvodes/cvodes_sptfqmr.h                    |  103 -
 include/cvodes/cvodes_superlumt.h                  |  111 -
 include/ida/ida.h                                  |   20 +-
 include/ida/ida_band.h                             |   64 -
 include/ida/ida_bbdpre.h                           |   93 +-
 include/ida/ida_dense.h                            |   63 -
 include/ida/ida_direct.h                           |  423 +-
 include/ida/ida_klu.h                              |  122 -
 include/ida/ida_lapack.h                           |   85 -
 include/ida/ida_sparse.h                           |  268 --
 include/ida/ida_spbcgs.h                           |   64 -
 include/ida/ida_spgmr.h                            |   65 -
 include/ida/ida_spils.h                            |  583 +--
 include/ida/ida_sptfqmr.h                          |   64 -
 include/ida/ida_superlumt.h                        |   99 -
 include/idas/idas.h                                |   24 +-
 include/idas/idas_band.h                           |   86 -
 include/idas/idas_bbdpre.h                         |  561 ++-
 include/idas/idas_dense.h                          |   75 -
 include/idas/idas_direct.h                         |  600 +--
 include/idas/idas_klu.h                            |  157 -
 include/idas/idas_lapack.h                         |  110 -
 include/idas/idas_sparse.h                         |  269 --
 include/idas/idas_spbcgs.h                         |   94 -
 include/idas/idas_spgmr.h                          |   95 -
 include/idas/idas_spils.h                          |  857 ++--
 include/idas/idas_sptfqmr.h                        |   94 -
 include/idas/idas_superlumt.h                      |  112 -
 include/kinsol/kinsol.h                            |   26 +-
 include/kinsol/kinsol_band.h                       |   62 -
 include/kinsol/kinsol_bbdpre.h                     |   88 +-
 include/kinsol/kinsol_dense.h                      |   59 -
 include/kinsol/kinsol_direct.h                     |  204 +-
 include/kinsol/kinsol_klu.h                        |  111 -
 include/kinsol/kinsol_lapack.h                     |   89 -
 include/kinsol/kinsol_sparse.h                     |  165 -
 include/kinsol/kinsol_spbcgs.h                     |   94 -
 include/kinsol/kinsol_spfgmr.h                     |   90 -
 include/kinsol/kinsol_spgmr.h                      |   91 -
 include/kinsol/kinsol_spils.h                      |  527 ++-
 include/kinsol/kinsol_sptfqmr.h                    |   95 -
 include/kinsol/kinsol_superlumt.h                  |   87 -
 include/nvector/cuda/ThreadPartitioning.hpp        |  178 +
 include/nvector/cuda/Vector.hpp                    |  190 +
 include/nvector/cuda/VectorKernels.cuh             | 1083 +++++
 include/nvector/nvector_cuda.h                     |  265 ++
 include/nvector/nvector_openmp.h                   |   34 +-
 include/nvector/nvector_parallel.h                 |   67 +-
 include/nvector/nvector_parhyp.h                   |   47 +-
 include/nvector/nvector_petsc.h                    |   50 +-
 include/nvector/nvector_pthreads.h                 |   38 +-
 include/nvector/nvector_raja.h                     |  266 ++
 include/nvector/nvector_serial.h                   |   34 +-
 include/nvector/raja/Vector.hpp                    |  157 +
 include/sundials/sundials_band.h                   |   32 +-
 include/sundials/sundials_config.in                |   27 +-
 include/sundials/sundials_dense.h                  |   30 +-
 include/sundials/sundials_direct.h                 |   53 +-
 include/sundials/sundials_fconfig.in               |   56 +
 include/sundials/sundials_fnvector.h               |    4 +-
 include/sundials/sundials_iterative.h              |   30 +-
 include/sundials/sundials_klu_impl.h               |    4 +-
 include/sundials/sundials_lapack.h                 |   82 +-
 include/sundials/sundials_linearsolver.h           |  364 ++
 include/sundials/sundials_math.h                   |    4 +-
 include/sundials/sundials_matrix.h                 |  196 +
 include/sundials/sundials_mpi_types.h              |   36 +
 include/sundials/sundials_nvector.h                |   20 +-
 include/sundials/sundials_sparse.h                 |    4 +-
 include/sundials/sundials_spbcgs.h                 |    4 +-
 include/sundials/sundials_spgmr.h                  |    4 +-
 include/sundials/sundials_sptfqmr.h                |    4 +-
 include/sundials/sundials_superlumt_impl.h         |    4 +-
 include/sundials/sundials_types.h                  |   93 +-
 include/sundials/sundials_version.h                |   66 +
 include/sunlinsol/sunlinsol_band.h                 |  105 +
 include/sunlinsol/sunlinsol_dense.h                |  111 +
 include/sunlinsol/sunlinsol_klu.h                  |  197 +
 include/sunlinsol/sunlinsol_lapackband.h           |  123 +
 include/sunlinsol/sunlinsol_lapackdense.h          |  123 +
 include/sunlinsol/sunlinsol_pcg.h                  |  218 +
 include/sunlinsol/sunlinsol_spbcgs.h               |  234 ++
 include/sunlinsol/sunlinsol_spfgmr.h               |  253 ++
 include/sunlinsol/sunlinsol_spgmr.h                |  254 ++
 include/sunlinsol/sunlinsol_sptfqmr.h              |  229 ++
 include/sunlinsol/sunlinsol_superlumt.h            |  169 +
 include/sunmatrix/sunmatrix_band.h                 |  334 ++
 include/sunmatrix/sunmatrix_dense.h                |  263 ++
 include/sunmatrix/sunmatrix_sparse.h               |  355 ++
 src/arkode/CMakeLists.txt                          |  100 +-
 src/arkode/README                                  |    5 +-
 src/arkode/arkode.c                                |  832 ++--
 src/arkode/arkode_band.c                           |  637 ---
 src/arkode/arkode_bandpre.c                        |  312 +-
 src/arkode/arkode_bandpre_impl.h                   |   22 +-
 src/arkode/arkode_bbdpre.c                         |  393 +-
 src/arkode/arkode_bbdpre_impl.h                    |   22 +-
 src/arkode/arkode_butcher.c                        |   70 +-
 src/arkode/arkode_dense.c                          |  613 ---
 src/arkode/arkode_direct.c                         | 1161 +++++-
 src/arkode/arkode_direct_impl.h                    |  126 +-
 src/arkode/arkode_impl.h                           |  140 +-
 src/arkode/arkode_io.c                             |  191 +-
 src/arkode/arkode_klu.c                            | 1275 ------
 src/arkode/arkode_lapack.c                         | 1270 ------
 src/arkode/arkode_pcg.c                            |  772 ----
 src/arkode/arkode_sparse.c                         |  268 --
 src/arkode/arkode_sparse_impl.h                    |  127 -
 src/arkode/arkode_spbcgs.c                         |  766 ----
 src/arkode/arkode_spfgmr.c                         |  777 ----
 src/arkode/arkode_spgmr.c                          |  779 ----
 src/arkode/arkode_spils.c                          | 1822 ++++++---
 src/arkode/arkode_spils_impl.h                     |  181 +-
 src/arkode/arkode_sptfqmr.c                        |  767 ----
 src/arkode/arkode_superlumt.c                      | 1097 -----
 src/arkode/fcmix/CMakeLists.txt                    |   75 +-
 src/arkode/fcmix/farkband.c                        |   51 +-
 src/arkode/fcmix/farkbandmass.c                    |   49 +-
 src/arkode/fcmix/farkbbd.c                         |   70 +-
 src/arkode/fcmix/farkbbd.h                         |  599 ++-
 src/arkode/fcmix/farkbp.c                          |   22 +-
 src/arkode/fcmix/farkbp.h                          |  453 +-
 src/arkode/fcmix/farkdense.c                       |   48 +-
 src/arkode/fcmix/farkdensemass.c                   |   37 +-
 src/arkode/fcmix/farkjtimes.c                      |   46 +-
 src/arkode/fcmix/farkklu.c                         |   66 -
 src/arkode/fcmix/farklapack.c                      |   71 -
 src/arkode/fcmix/farklapband.c                     |  103 -
 src/arkode/fcmix/farklapbandmass.c                 |   84 -
 src/arkode/fcmix/farklapdense.c                    |   93 -
 src/arkode/fcmix/farklapdensemass.c                |   80 -
 src/arkode/fcmix/farkmasspreco.c                   |   35 +-
 src/arkode/fcmix/farkmtimes.c                      |   28 +-
 src/arkode/fcmix/farkode.c                         |  778 ++--
 src/arkode/fcmix/farkode.h                         | 2801 ++++++-------
 src/arkode/fcmix/farkpreco.c                       |   36 +-
 src/arkode/fcmix/farkroot.c                        |    5 +-
 src/arkode/fcmix/farkroot.h                        |    2 +-
 src/arkode/fcmix/farksparse.c                      |   48 +-
 src/arkode/fcmix/farksparsemass.c                  |   40 +-
 src/arkode/fcmix/farksuperlumt.c                   |   53 -
 src/cvode/CMakeLists.txt                           |  137 +-
 src/cvode/README                                   |    4 +-
 src/cvode/cvode.c                                  | 1703 ++++----
 src/cvode/cvode_band.c                             |  368 --
 src/cvode/cvode_bandpre.c                          |  545 +--
 src/cvode/cvode_bandpre_impl.h                     |   60 +-
 src/cvode/cvode_bbdpre.c                           |  648 +--
 src/cvode/cvode_bbdpre_impl.h                      |   70 +-
 src/cvode/cvode_dense.c                            |  352 --
 src/cvode/cvode_diag.c                             |   15 +-
 src/cvode/cvode_diag_impl.h                        |    5 +-
 src/cvode/cvode_direct.c                           |  756 +++-
 src/cvode/cvode_direct_impl.h                      |  129 +-
 src/cvode/cvode_impl.h                             |   41 +-
 src/cvode/cvode_io.c                               |  104 +-
 src/cvode/cvode_klu.c                              |  612 ---
 src/cvode/cvode_lapack.c                           |  660 ---
 src/cvode/cvode_sparse.c                           |  175 -
 src/cvode/cvode_sparse_impl.h                      |  109 -
 src/cvode/cvode_spbcgs.c                           |  467 ---
 src/cvode/cvode_spgmr.c                            |  471 ---
 src/cvode/cvode_spils.c                            | 1072 +++--
 src/cvode/cvode_spils_impl.h                       |  155 +-
 src/cvode/cvode_sptfqmr.c                          |  465 ---
 src/cvode/cvode_superlumt.c                        |  554 ---
 src/cvode/fcmix/CMakeLists.txt                     |   62 +-
 src/cvode/fcmix/fcvband.c                          |   72 +-
 src/cvode/fcmix/fcvbbd.c                           |   58 +-
 src/cvode/fcmix/fcvbbd.h                           |  584 ++-
 src/cvode/fcmix/fcvbp.c                            |   25 +-
 src/cvode/fcmix/fcvbp.h                            |  421 +-
 src/cvode/fcmix/fcvdense.c                         |   64 +-
 src/cvode/fcmix/fcvewt.c                           |    9 +-
 src/cvode/fcmix/fcvjtimes.c                        |   76 +-
 src/cvode/fcmix/fcvklu.c                           |   52 -
 src/cvode/fcmix/fcvlapack.c                        |   57 -
 src/cvode/fcmix/fcvlapband.c                       |  103 -
 src/cvode/fcmix/fcvlapdense.c                      |   97 -
 src/cvode/fcmix/fcvode.c                           |  254 +-
 src/cvode/fcmix/fcvode.h                           | 1360 +++---
 src/cvode/fcmix/fcvpreco.c                         |   72 +-
 src/cvode/fcmix/fcvroot.c                          |    9 +-
 src/cvode/fcmix/fcvroot.h                          |    5 +-
 src/cvode/fcmix/fcvsparse.c                        |   65 +-
 src/cvode/fcmix/fcvsuperlumt.c                     |   42 -
 src/cvodes/CMakeLists.txt                          |  124 +-
 src/cvodes/README                                  |    4 +-
 src/cvodes/cvodea.c                                |  980 ++---
 src/cvodes/cvodea_io.c                             |   95 +-
 src/cvodes/cvodes.c                                | 4326 ++++++++++----------
 src/cvodes/cvodes_band.c                           |  470 ---
 src/cvodes/cvodes_bandpre.c                        |  602 +--
 src/cvodes/cvodes_bandpre_impl.h                   |   63 +-
 src/cvodes/cvodes_bbdpre.c                         |  822 ++--
 src/cvodes/cvodes_bbdpre_impl.h                    |   78 +-
 src/cvodes/cvodes_dense.c                          |  455 --
 src/cvodes/cvodes_diag.c                           |   14 +-
 src/cvodes/cvodes_diag_impl.h                      |    3 -
 src/cvodes/cvodes_direct.c                         | 1145 +++---
 src/cvodes/cvodes_direct_impl.h                    |  187 +-
 src/cvodes/cvodes_impl.h                           |   78 +-
 src/cvodes/cvodes_io.c                             |  236 +-
 src/cvodes/cvodes_klu.c                            |  818 ----
 src/cvodes/cvodes_lapack.c                         |  839 ----
 src/cvodes/cvodes_sparse.c                         |  407 --
 src/cvodes/cvodes_sparse_impl.h                    |  137 -
 src/cvodes/cvodes_spbcgs.c                         |  583 ---
 src/cvodes/cvodes_spgmr.c                          |  589 ---
 src/cvodes/cvodes_spils.c                          | 1930 +++++----
 src/cvodes/cvodes_spils_impl.h                     |  211 +-
 src/cvodes/cvodes_sptfqmr.c                        |  578 ---
 src/cvodes/cvodes_superlumt.c                      |  705 ----
 src/ida/CMakeLists.txt                             |  130 +-
 src/ida/README                                     |    4 +-
 src/ida/fcmix/CMakeLists.txt                       |   85 +-
 src/ida/fcmix/fida.c                               |  305 +-
 src/ida/fcmix/fida.h                               | 1745 ++++----
 src/ida/fcmix/fidaband.c                           |   84 +-
 src/ida/fcmix/fidabbd.c                            |   82 +-
 src/ida/fcmix/fidabbd.h                            |  789 ++--
 src/ida/fcmix/fidadense.c                          |   74 +-
 src/ida/fcmix/fidaewt.c                            |    3 -
 src/ida/fcmix/fidajtimes.c                         |  112 +-
 src/ida/fcmix/fidaklu.c                            |   52 -
 src/ida/fcmix/fidalapack.c                         |   58 -
 src/ida/fcmix/fidalapband.c                        |  117 -
 src/ida/fcmix/fidalapdense.c                       |  116 -
 src/ida/fcmix/fidapreco.c                          |   54 +-
 src/ida/fcmix/fidaroot.c                           |    3 -
 src/ida/fcmix/fidaroot.h                           |    5 +-
 src/ida/fcmix/fidasparse.c                         |   65 +-
 src/ida/fcmix/fidasuperlumt.c                      |   42 -
 src/ida/ida.c                                      | 1486 ++++---
 src/ida/ida_band.c                                 |  328 --
 src/ida/ida_bbdpre.c                               |  635 +--
 src/ida/ida_bbdpre_impl.h                          |   63 +-
 src/ida/ida_dense.c                                |  308 --
 src/ida/ida_direct.c                               |  774 ++--
 src/ida/ida_direct_impl.h                          |  135 +-
 src/ida/ida_ic.c                                   |  262 +-
 src/ida/ida_impl.h                                 |   28 +-
 src/ida/ida_io.c                                   |  136 +-
 src/ida/ida_klu.c                                  |  564 ---
 src/ida/ida_lapack.c                               |  570 ---
 src/ida/ida_sparse.c                               |  175 -
 src/ida/ida_sparse_impl.h                          |  127 -
 src/ida/ida_spbcgs.c                               |  482 ---
 src/ida/ida_spgmr.c                                |  482 ---
 src/ida/ida_spils.c                                | 1113 +++--
 src/ida/ida_spils_impl.h                           |  213 +-
 src/ida/ida_sptfqmr.c                              |  482 ---
 src/ida/ida_superlumt.c                            |  522 ---
 src/idas/CMakeLists.txt                            |  122 +-
 src/idas/README                                    |    4 +-
 src/idas/idaa.c                                    | 1050 +++--
 src/idas/idaa_io.c                                 |   67 +-
 src/idas/idas.c                                    | 3120 +++++++-------
 src/idas/idas_band.c                               |  431 --
 src/idas/idas_bbdpre.c                             |  792 ++--
 src/idas/idas_bbdpre_impl.h                        |   70 +-
 src/idas/idas_dense.c                              |  410 --
 src/idas/idas_direct.c                             | 1225 +++---
 src/idas/idas_direct_impl.h                        |  182 +-
 src/idas/idas_ic.c                                 |  595 ++-
 src/idas/idas_impl.h                               |   71 +-
 src/idas/idas_io.c                                 |  276 +-
 src/idas/idas_klu.c                                |  780 ----
 src/idas/idas_lapack.c                             |  758 ----
 src/idas/idas_sparse.c                             |  429 --
 src/idas/idas_sparse_impl.h                        |  127 -
 src/idas/idas_spbcgs.c                             |  595 ---
 src/idas/idas_spgmr.c                              |  587 ---
 src/idas/idas_spils.c                              | 1977 ++++++---
 src/idas/idas_spils_impl.h                         |  247 +-
 src/idas/idas_sptfqmr.c                            |  588 ---
 src/idas/idas_superlumt.c                          |  679 ---
 src/kinsol/CMakeLists.txt                          |  131 +-
 src/kinsol/README                                  |    4 +-
 src/kinsol/fcmix/CMakeLists.txt                    |   85 +-
 src/kinsol/fcmix/fkinband.c                        |   45 +-
 src/kinsol/fcmix/fkinbbd.c                         |   49 +-
 src/kinsol/fcmix/fkinbbd.h                         |   91 +-
 src/kinsol/fcmix/fkindense.c                       |   41 +-
 src/kinsol/fcmix/fkinjtimes.c                      |   47 +-
 src/kinsol/fcmix/fkinklu.c                         |   52 -
 src/kinsol/fcmix/fkinlapack.c                      |   47 -
 src/kinsol/fcmix/fkinlapband.c                     |  117 -
 src/kinsol/fcmix/fkinlapdense.c                    |  105 -
 src/kinsol/fcmix/fkinpreco.c                       |  117 +-
 src/kinsol/fcmix/fkinsol.c                         |  287 +-
 src/kinsol/fcmix/fkinsol.h                         |  594 ++-
 src/kinsol/fcmix/fkinsparse.c                      |   50 +-
 src/kinsol/fcmix/fkinsuperlumt.c                   |   42 -
 src/kinsol/kinsol.c                                | 1068 +++--
 src/kinsol/kinsol_band.c                           |  357 --
 src/kinsol/kinsol_bbdpre.c                         |  652 +--
 src/kinsol/kinsol_bbdpre_impl.h                    |   68 +-
 src/kinsol/kinsol_dense.c                          |  339 --
 src/kinsol/kinsol_direct.c                         |  724 ++--
 src/kinsol/kinsol_direct_impl.h                    |   99 +-
 src/kinsol/kinsol_impl.h                           |   17 +-
 src/kinsol/kinsol_io.c                             |   10 +-
 src/kinsol/kinsol_klu.c                            |  575 ---
 src/kinsol/kinsol_lapack.c                         |  616 ---
 src/kinsol/kinsol_sparse.c                         |  178 -
 src/kinsol/kinsol_sparse_impl.h                    |   92 -
 src/kinsol/kinsol_spbcgs.c                         |  442 --
 src/kinsol/kinsol_spfgmr.c                         |  451 --
 src/kinsol/kinsol_spgmr.c                          |  443 --
 src/kinsol/kinsol_spils.c                          | 1039 +++--
 src/kinsol/kinsol_spils_impl.h                     |  189 +-
 src/kinsol/kinsol_sptfqmr.c                        |  436 --
 src/kinsol/kinsol_superlumt.c                      |  506 ---
 src/nvec_cuda/CMakeLists.txt                       |   75 +
 src/nvec_cuda/nvector_cuda.cu                      |  459 +++
 src/nvec_openmp/CMakeLists.txt                     |   25 +-
 src/nvec_openmp/README                             |    6 +-
 src/nvec_openmp/fnvector_openmp.c                  |    9 +-
 src/nvec_openmp/fnvector_openmp.h                  |   11 +-
 src/nvec_openmp/nvector_openmp.c                   |  121 +-
 src/nvec_par/CMakeLists.txt                        |   25 +-
 src/nvec_par/README                                |    4 +-
 src/nvec_par/fnvector_parallel.c                   |   11 +-
 src/nvec_par/fnvector_parallel.h                   |   11 +-
 src/nvec_par/nvector_parallel.c                    |  136 +-
 src/nvec_parhyp/CMakeLists.txt                     |   12 +-
 src/nvec_parhyp/README                             |    4 +-
 src/nvec_parhyp/nvector_parhyp.c                   |  103 +-
 src/nvec_petsc/CMakeLists.txt                      |   21 +-
 src/nvec_petsc/README                              |    4 +-
 src/nvec_petsc/nvector_petsc.c                     |  130 +-
 src/nvec_pthreads/CMakeLists.txt                   |   26 +-
 src/nvec_pthreads/README                           |    6 +-
 src/nvec_pthreads/fnvector_pthreads.c              |    9 +-
 src/nvec_pthreads/fnvector_pthreads.h              |   11 +-
 src/nvec_pthreads/nvector_pthreads.c               |  189 +-
 src/nvec_raja/CMakeLists.txt                       |   83 +
 src/nvec_raja/nvector_raja.cu                      |  617 +++
 src/nvec_ser/CMakeLists.txt                        |   25 +-
 src/nvec_ser/README                                |    5 +-
 src/nvec_ser/fnvector_serial.c                     |    9 +-
 src/nvec_ser/fnvector_serial.h                     |   11 +-
 src/nvec_ser/nvector_serial.c                      |  127 +-
 src/sundials/CMakeLists.txt                        |   13 +-
 src/sundials/README                                |    5 +-
 src/sundials/sundials_band.c                       |   40 +-
 src/sundials/sundials_dense.c                      |   50 +-
 src/sundials/sundials_direct.c                     |   75 +-
 src/sundials/sundials_iterative.c                  |    4 +-
 src/sundials/sundials_linearsolver.c               |  136 +
 src/sundials/sundials_math.c                       |    4 +-
 src/sundials/sundials_matrix.c                     |   86 +
 src/sundials/sundials_nvector.c                    |    6 +-
 src/sundials/sundials_pcg.c                        |   10 +-
 src/sundials/sundials_sparse.c                     |    4 +-
 src/sundials/sundials_spbcgs.c                     |   24 +-
 src/sundials/sundials_spfgmr.c                     |    6 +-
 src/sundials/sundials_spgmr.c                      |   18 +-
 src/sundials/sundials_sptfqmr.c                    |   42 +-
 src/sundials/sundials_version.c                    |   48 +
 src/sunlinsol_band/CMakeLists.txt                  |  105 +
 src/sunlinsol_band/README                          |   41 +
 src/sunlinsol_band/fsunlinsol_band.c               |  100 +
 src/sunlinsol_band/fsunlinsol_band.h               |   66 +
 src/sunlinsol_band/sunlinsol_band.c                |  281 ++
 src/sunlinsol_dense/CMakeLists.txt                 |  104 +
 src/sunlinsol_dense/README                         |   41 +
 src/sunlinsol_dense/fsunlinsol_dense.c             |  100 +
 src/sunlinsol_dense/fsunlinsol_dense.h             |   66 +
 src/sunlinsol_dense/sunlinsol_dense.c              |  267 ++
 src/sunlinsol_klu/CMakeLists.txt                   |  116 +
 src/sunlinsol_klu/README                           |   40 +
 src/sunlinsol_klu/fsunlinsol_klu.c                 |  161 +
 src/sunlinsol_klu/fsunlinsol_klu.h                 |   85 +
 src/sunlinsol_klu/sunlinsol_klu.c                  |  445 ++
 src/sunlinsol_lapackband/CMakeLists.txt            |  107 +
 src/sunlinsol_lapackband/README                    |   37 +
 src/sunlinsol_lapackband/fsunlinsol_lapackband.c   |   98 +
 src/sunlinsol_lapackband/fsunlinsol_lapackband.h   |   66 +
 src/sunlinsol_lapackband/sunlinsol_lapackband.c    |  275 ++
 src/sunlinsol_lapackdense/CMakeLists.txt           |  113 +
 src/sunlinsol_lapackdense/README                   |   37 +
 src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c |   96 +
 src/sunlinsol_lapackdense/fsunlinsol_lapackdense.h |   66 +
 src/sunlinsol_lapackdense/sunlinsol_lapackdense.c  |  266 ++
 src/sunlinsol_pcg/CMakeLists.txt                   |  107 +
 src/sunlinsol_pcg/README                           |   40 +
 src/sunlinsol_pcg/fsunlinsol_pcg.c                 |  195 +
 src/sunlinsol_pcg/fsunlinsol_pcg.h                 |   84 +
 src/sunlinsol_pcg/sunlinsol_pcg.c                  |  470 +++
 src/sunlinsol_spbcgs/CMakeLists.txt                |  107 +
 src/sunlinsol_spbcgs/README                        |   41 +
 src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c           |  195 +
 src/sunlinsol_spbcgs/fsunlinsol_spbcgs.h           |   84 +
 src/sunlinsol_spbcgs/sunlinsol_spbcgs.c            |  617 +++
 src/sunlinsol_spfgmr/CMakeLists.txt                |  107 +
 src/sunlinsol_spfgmr/README                        |   41 +
 src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c           |  245 ++
 src/sunlinsol_spfgmr/fsunlinsol_spfgmr.h           |   92 +
 src/sunlinsol_spfgmr/sunlinsol_spfgmr.c            |  655 +++
 src/sunlinsol_spgmr/CMakeLists.txt                 |  107 +
 src/sunlinsol_spgmr/README                         |   41 +
 src/sunlinsol_spgmr/fsunlinsol_spgmr.c             |  245 ++
 src/sunlinsol_spgmr/fsunlinsol_spgmr.h             |   92 +
 src/sunlinsol_spgmr/sunlinsol_spgmr.c              |  701 ++++
 src/sunlinsol_sptfqmr/CMakeLists.txt               |  106 +
 src/sunlinsol_sptfqmr/README                       |   41 +
 src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c         |  195 +
 src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.h         |   84 +
 src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c          |  743 ++++
 src/sunlinsol_superlumt/CMakeLists.txt             |  127 +
 src/sunlinsol_superlumt/README                     |   41 +
 src/sunlinsol_superlumt/fsunlinsol_superlumt.c     |  136 +
 src/sunlinsol_superlumt/fsunlinsol_superlumt.h     |   74 +
 src/sunlinsol_superlumt/sunlinsol_superlumt.c      |  422 ++
 src/sunmat_band/CMakeLists.txt                     |  104 +
 src/sunmat_band/README                             |   48 +
 src/sunmat_band/fsunmatrix_band.c                  |   84 +
 src/sunmat_band/fsunmatrix_band.h                  |   68 +
 src/sunmat_band/sunmatrix_band.c                   |  482 +++
 src/sunmat_dense/CMakeLists.txt                    |  104 +
 src/sunmat_dense/README                            |   44 +
 src/sunmat_dense/fsunmatrix_dense.c                |   82 +
 src/sunmat_dense/fsunmatrix_dense.h                |   66 +
 src/sunmat_dense/sunmatrix_dense.c                 |  352 ++
 src/sunmat_sparse/CMakeLists.txt                   |  104 +
 src/sunmat_sparse/README                           |   48 +
 src/sunmat_sparse/fsunmatrix_sparse.c              |   83 +
 src/sunmat_sparse/fsunmatrix_sparse.h              |   69 +
 src/sunmat_sparse/sunmatrix_sparse.c               | 1004 +++++
 test/testRunner                                    |  394 ++
 924 files changed, 88812 insertions(+), 85401 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 08b6203..e533927 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,14 +12,13 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # Top level CMakeLists.txt for SUNDIALS (for cmake build system)
+# ---------------------------------------------------------------
 
-
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Initial commands
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
 # Require a fairly recent cmake version
-
 CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1)
 
 # Set CMake policy to allow examples to build
@@ -31,183 +27,234 @@ if(COMMAND cmake_policy)
 endif(COMMAND cmake_policy)
 
 # Project SUNDIALS (initially only C supported)
-
+# sets PROJECT_SOURCE_DIR and PROJECT_BINARY_DIR variables
 PROJECT(sundials C)
 
 # Set some variables with info on the SUNDIALS project
-
 SET(PACKAGE_BUGREPORT "woodward6 at llnl.gov")
 SET(PACKAGE_NAME "SUNDIALS")
-SET(PACKAGE_STRING "SUNDIALS 2.7.0")
+SET(PACKAGE_STRING "SUNDIALS 3.1.0")
 SET(PACKAGE_TARNAME "sundials")
-SET(PACKAGE_VERSION "2.7.0")
 
-# 
+# set SUNDIALS version numbers 
+# (use "" for the version label if none is needed)
+SET(PACKAGE_VERSION_MAJOR "3")
+SET(PACKAGE_VERSION_MINOR "1")
+SET(PACKAGE_VERSION_PATCH "0")
+SET(PACKAGE_VERSION_LABEL "")
+
+IF(PACKAGE_VERSION_LABEL)
+  SET(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}-${PACKAGE_VERSION_LABEL}")
+ELSE()
+  SET(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}")
+ENDIF()
+
+#
 SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
 
 # Prohibit in-source build
-
 IF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
   MESSAGE(FATAL_ERROR "In-source build prohibited.")
 ENDIF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
 
-# Hide/show some cache variables
-
+# Hide some cache variables
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
+
+# Always show the C compiler and flags
 MARK_AS_ADVANCED(CLEAR
   CMAKE_C_COMPILER
-  CMAKE_C_FLAGS
-  CMAKE_C_FLAGS_DEBUG
-  CMAKE_C_FLAGS_MINSIZEREL
-  CMAKE_C_FLAGS_RELEASE
-  CMAKE_C_FLAGS_RELWITHDEB)
+  CMAKE_C_FLAGS)
 
 # Specify the VERSION and SOVERSION for shared libraries
 
-SET(arkodelib_VERSION "1.1.0")
-SET(arkodelib_SOVERSION "1")
+SET(arkodelib_VERSION "2.1.0")
+SET(arkodelib_SOVERSION "2")
 
-SET(cvodelib_VERSION "2.9.0")
-SET(cvodelib_SOVERSION "2")
+SET(cvodelib_VERSION "3.1.0")
+SET(cvodelib_SOVERSION "3")
 
-SET(cvodeslib_VERSION "2.9.0")
-SET(cvodeslib_SOVERSION "2")
+SET(cvodeslib_VERSION "3.1.0")
+SET(cvodeslib_SOVERSION "3")
 
-SET(idalib_VERSION "2.9.0")
-SET(idalib_SOVERSION "2")
+SET(idalib_VERSION "3.1.0")
+SET(idalib_SOVERSION "3")
 
-SET(idaslib_VERSION "1.3.0")
-SET(idaslib_SOVERSION "1")
+SET(idaslib_VERSION "2.1.0")
+SET(idaslib_SOVERSION "2")
 
-SET(kinsollib_VERSION "2.9.0")
-SET(kinsollib_SOVERSION "2")
+SET(kinsollib_VERSION "3.1.0")
+SET(kinsollib_SOVERSION "3")
 
 SET(cpodeslib_VERSION "0.0.0")
 SET(cpodeslib_SOVERSION "0")
 
-SET(nveclib_VERSION "2.7.0")
-SET(nveclib_SOVERSION "2")
+SET(nveclib_VERSION "3.1.0")
+SET(nveclib_SOVERSION "3")
 
-# Specify the location of additional CMAKE modules
+SET(sunmatrixlib_VERSION "1.1.0")
+SET(sunmatrixlib_SOVERSION "1")
 
+SET(sunlinsollib_VERSION "1.1.0")
+SET(sunlinsollib_SOVERSION "1")
+
+# Specify the location of additional CMAKE modules
 SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/config)
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # MACRO definitions
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
+INCLUDE(SundialsCMakeMacros)
 
-# Macros to hide/show cached variables.
-# These two macros can be used to "hide" or "show" in the
-# list of cached variables various variables and/or options 
-# that depend on other options.
-# Note that once a variable is modified, it will preserve its
-# value (hidding it merely makes it internal)
-
-MACRO(HIDE_VARIABLE var)
-  IF(DEFINED ${var})
-    SET(${var} "${${var}}" CACHE INTERNAL "")
-  ENDIF(DEFINED ${var})
-ENDMACRO(HIDE_VARIABLE)
-
-MACRO(SHOW_VARIABLE var type doc default)
-  IF(DEFINED ${var})
-    SET(${var} "${${var}}" CACHE "${type}" "${doc}" FORCE)
-  ELSE(DEFINED ${var})
-    SET(${var} "${default}" CACHE "${type}" "${doc}")
-  ENDIF(DEFINED ${var})
-ENDMACRO(SHOW_VARIABLE)
-
-# Macros to append a common suffix or prefix to the elements of a list
-
-MACRO(ADD_SUFFIX rootlist suffix)
-  SET(outlist )
-  FOREACH(root ${${rootlist}})
-    LIST(APPEND outlist ${root}${suffix})
-  ENDFOREACH(root)
-  SET(${rootlist} ${outlist})
-ENDMACRO(ADD_SUFFIX)
-
-MACRO(ADD_PREFIX prefix rootlist)
-  SET(outlist )
-  FOREACH(root ${${rootlist}})
-    LIST(APPEND outlist ${prefix}${root})
-  ENDFOREACH(root)
-  SET(${rootlist} ${outlist})
-ENDMACRO(ADD_PREFIX)
-
-# Macro to print warning that some features will be disabled
-# due to some failure.
-
-MACRO(PRINT_WARNING message action)
-  MESSAGE("WARNING: ${message}.\n   ${action}.")
-ENDMACRO(PRINT_WARNING)
-
-# Returns an unquoted string.  Note that CMake will readily turn such
-# strings back into lists, due to the duality of lists and
-# semicolon-separated strings.  So be careful how you use it.
-
-MACRO(LIST2STRING alist astring)
-  FOREACH(elem ${${alist}})
-   SET(${astring} "${${astring}} ${elem}")
-  ENDFOREACH(elem)
-ENDMACRO(LIST2STRING)
+# ---------------------------------------------------------------
+# Check for deprecated SUNDIALS CMake options/variables
+# ---------------------------------------------------------------
+INCLUDE(SundialsDeprecated)
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Which modules to build?
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
 # For each SUNDIALS solver available (i.e. for which we have the
 # sources), give the user the option of enabling/disabling it.
 
 IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/arkode")
-  OPTION(BUILD_ARKODE  "Build the ARKODE library"  ON)
-ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/arkode")
+  OPTION(BUILD_ARKODE "Build the ARKODE library" ON)
+ELSE()
   SET(BUILD_ARKODE OFF)
-ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/arkode")
+ENDIF()
 
 IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvode")
-  OPTION(BUILD_CVODE  "Build the CVODE library"  ON)
-ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvode")
+  OPTION(BUILD_CVODE "Build the CVODE library" ON)
+ELSE()
   SET(BUILD_CVODE OFF)
-ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvode")
+ENDIF()
 
 IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvodes")
-  OPTION(BUILD_CVODES  "Build the CVODES library"  ON)
-ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvodes")
+  OPTION(BUILD_CVODES "Build the CVODES library" ON)
+ELSE()
   SET(BUILD_CVODES OFF)
-ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cvodes")
+ENDIF()
 
 IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/ida")
-  OPTION(BUILD_IDA  "Build the IDA library"  ON)
-ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/ida")
+  OPTION(BUILD_IDA "Build the IDA library" ON)
+ELSE()
   SET(BUILD_IDA OFF)
-ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/ida")
+ENDIF()
 
 IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/idas")
-  OPTION(BUILD_IDAS  "Build the IDAS library"  ON)
-ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/idas")
+  OPTION(BUILD_IDAS "Build the IDAS library" ON)
+ELSE()
   SET(BUILD_IDAS OFF)
-ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/idas")
+ENDIF()
 
 IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/kinsol")
-  OPTION(BUILD_KINSOL  "Build the KINSOL library"  ON)
-ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/kinsol")
+  OPTION(BUILD_KINSOL "Build the KINSOL library" ON)
+ELSE()
   SET(BUILD_KINSOL OFF)
-ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/kinsol")
+ENDIF()
 
 # CPODES is always OFF for now.  (commented out for Release); ToDo: better way to do this?
 #IF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cpodes")
 #  OPTION(BUILD_CPODES  "Build the CPODES library"  OFF)
-#ELSE(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cpodes")
+#ELSE()
 #  SET(BUILD_CPODES OFF)
-#ENDIF(IS_DIRECTORY "${sundials_SOURCE_DIR}/src/cpodes")
+#ENDIF()
 
-# -------------------------------------------------------------
-# Other configuration options
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
+# xSDK specific options
+# ---------------------------------------------------------------
+INCLUDE(SundialsXSDK)
 
-# Option that allows users to build static and/or shared libraries
-# ----------------------------------------------------------------
+# ---------------------------------------------------------------
+# Build specific C flags
+# ---------------------------------------------------------------
+
+# Hide all build type specific flags
+MARK_AS_ADVANCED(FORCE
+  CMAKE_C_FLAGS_DEBUG
+  CMAKE_C_FLAGS_MINSIZEREL
+  CMAKE_C_FLAGS_RELEASE
+  CMAKE_C_FLAGS_RELWITHDEBINFO)
+
+# Only show flags for the current build type it is set
+# NOTE: Build specific flags are appended those in CMAKE_C_FLAGS
+IF(CMAKE_BUILD_TYPE)
+  IF(CMAKE_BUILD_TYPE MATCHES "Debug")
+    MESSAGE("Appending C debug flags")
+    MARK_AS_ADVANCED(CLEAR CMAKE_C_FLAGS_DEBUG)
+  ELSEIF(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
+    MESSAGE("Appending C min size release flags")
+    MARK_AS_ADVANCED(CLEAR CMAKE_C_FLAGS_MINSIZEREL)
+  ELSEIF(CMAKE_BUILD_TYPE MATCHES "Release")
+    MESSAGE("Appending C release flags")
+    MARK_AS_ADVANCED(CLEAR CMAKE_C_FLAGS_RELEASE)
+  ELSEIF(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
+    MESSAGE("Appending C release with debug info flags")
+    MARK_AS_ADVANCED(CLEAR CMAKE_C_FLAGS_RELWITHDEBINFO)
+  ENDIF()
+ENDIF()
+
+# ---------------------------------------------------------------
+# Option to specify precision (realtype)
+# ---------------------------------------------------------------
+
+SET(DOCSTR "single, double, or extended")
+SHOW_VARIABLE(SUNDIALS_PRECISION STRING "${DOCSTR}" "double")
+
+# prepare substitution variable PRECISION_LEVEL for sundials_config.h
+STRING(TOUPPER ${SUNDIALS_PRECISION} SUNDIALS_PRECISION)
+SET(PRECISION_LEVEL "#define SUNDIALS_${SUNDIALS_PRECISION}_PRECISION 1")
+
+# prepare substitution variable FPRECISION_LEVEL for sundials_fconfig.h
+IF(SUNDIALS_PRECISION MATCHES "SINGLE")
+  SET(FPRECISION_LEVEL "4")
+ENDIF(SUNDIALS_PRECISION MATCHES "SINGLE")
+IF(SUNDIALS_PRECISION MATCHES "DOUBLE")
+  SET(FPRECISION_LEVEL "8")
+ENDIF(SUNDIALS_PRECISION MATCHES "DOUBLE")
+IF(SUNDIALS_PRECISION MATCHES "EXTENDED")
+  SET(FPRECISION_LEVEL "16")
+ENDIF(SUNDIALS_PRECISION MATCHES "EXTENDED")
+
+# ---------------------------------------------------------------
+# Option to specify index type
+# ---------------------------------------------------------------
+
+SET(DOCSTR "Signed 64-bit (int64_t) or signed 32-bit (int32_t) integer")
+SHOW_VARIABLE(SUNDIALS_INDEX_TYPE STRING "${DOCSTR}" "int64_t")
+
+# prepare substitution variable INDEX_TYPE for sundials_config.h
+STRING(TOUPPER ${SUNDIALS_INDEX_TYPE} SUNDIALS_INDEX_TYPE)
+SET(INDEX_TYPE "#define SUNDIALS_${SUNDIALS_INDEX_TYPE} 1")
+
+# prepare substitution variable FINDEX_TYPE for sundials_fconfig.h
+IF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+  SET(FINDEX_TYPE "4")
+ENDIF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+IF(SUNDIALS_INDEX_TYPE MATCHES "INT64_T")
+  SET(FINDEX_TYPE "8")
+ENDIF(SUNDIALS_INDEX_TYPE MATCHES "INT64_T")
+
+# ---------------------------------------------------------------
+# Enable Fortran interface?
+# ---------------------------------------------------------------
+
+# Fortran interface is disabled by default
+SET(DOCSTR "Enable Fortran-C support")
+SHOW_VARIABLE(FCMIX_ENABLE BOOL "${DOCSTR}" OFF)
+
+# Check that at least one solver with a Fortran interface is built
+IF(NOT BUILD_ARKODE AND NOT BUILD_CVODE AND NOT BUILD_IDA AND NOT BUILD_KINSOL)
+  IF(FCMIX_ENABLE)
+    PRINT_WARNING("Enabled packages do not support Fortran" "Disabling FCMIX")
+    FORCE_VARIABLE(FCMIX_ENABLE BOOL "${DOCSTR}" OFF)
+  ENDIF()
+  HIDE_VARIABLE(FCMIX_ENABLE)
+ENDIF()
+
+# ---------------------------------------------------------------
+# Options to build static and/or shared libraries
+# ---------------------------------------------------------------
 
 OPTION(BUILD_STATIC_LIBS "Build static libraries" ON)
 OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
@@ -234,26 +281,18 @@ ENDIF(BUILD_SHARED_LIBS AND WIN32)
 # Make sure we build at least one type of libraries
 IF(NOT BUILD_STATIC_LIBS AND NOT BUILD_SHARED_LIBS)
   PRINT_WARNING("Both static and shared library generation were disabled"
-    "Building static libraries was re-enabled")
-  SET(BUILD_STATIC_LIBS ON CACHE BOOL "Build static libraries" FORCE)
+                "Building static libraries was re-enabled")
+  FORCE_VARIABLE(BUILD_STATIC_LIBS BOOL "Build static libraries" ON)
 ENDIF(NOT BUILD_STATIC_LIBS AND NOT BUILD_SHARED_LIBS)
 
-# Option to specify precision
-# ---------------------------
-
-SET(SUNDIALS_PRECISION "double" CACHE STRING "double, single or extended")
-
-# prepare substitution variable PRECISION_LEVEL for sundials_config.h
-STRING(TOUPPER ${SUNDIALS_PRECISION} SUNDIALS_PRECISION)
-SET(PRECISION_LEVEL "#define SUNDIALS_${SUNDIALS_PRECISION}_PRECISION 1")
-
+# ---------------------------------------------------------------
 # Option to use the generic math libraries (UNIX only)
-# ----------------------------------------------------
+# ---------------------------------------------------------------
 
 IF(UNIX)
   OPTION(USE_GENERIC_MATH "Use generic (std-c) math libraries" ON)
   IF(USE_GENERIC_MATH)
-    # executables will be linked against -lm 
+    # executables will be linked against -lm
     SET(EXTRA_LINK_LIBS -lm)
     # prepare substitution variable for sundials_config.h
     SET(SUNDIALS_USE_GENERIC_MATH TRUE)
@@ -276,161 +315,224 @@ if(SUNDIALS_POSIX_TIMERS)
   endif()
 endif()
 
-# -------------------------------------------------------------
-# Enable Fortran support?
-# -------------------------------------------------------------
 
-# FCMIX support is an option only if at least one solver that 
-# provides such an interface is built.
+# ===============================================================
+# Options for Parallelism
+# ===============================================================
 
-IF(BUILD_ARKODE OR BUILD_CVODE OR BUILD_IDA OR BUILD_KINSOL)
-  SHOW_VARIABLE(FCMIX_ENABLE BOOL "Enable Fortran-C support" OFF)
-ELSE(BUILD_ARKODE OR BUILD_CVODE OR BUILD_IDA OR BUILD_KINSOL)
-  HIDE_VARIABLE(FCMIX_ENABLE)
-ENDIF(BUILD_ARKODE OR BUILD_CVODE OR BUILD_IDA OR BUILD_KINSOL)
+# ---------------------------------------------------------------
+# Enable MPI support?
+# ---------------------------------------------------------------
+OPTION(MPI_ENABLE "Enable MPI support" OFF)
 
-# -------------------------------------------------------------
-# Enable Fortran90 support?
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
+# Enable OpenMP support?
+# ---------------------------------------------------------------
+OPTION(OPENMP_ENABLE "Enable OpenMP support" OFF)
 
-# F90 support is an option only if ARKode is built and 
-# examples are enabled
+# ---------------------------------------------------------------
+# Enable Pthread support?
+# ---------------------------------------------------------------
+OPTION(PTHREAD_ENABLE "Enable Pthreads support" OFF)
 
-IF(BUILD_ARKODE AND EXAMPLES_ENABLE AND FCMIX_ENABLE)
-  SHOW_VARIABLE(F90_ENABLE BOOL "Enable Fortran90 ARKode examples" OFF)
-ELSE(BUILD_ARKODE AND EXAMPLES_ENABLE AND FCMIX_ENABLE)
-  # # set back to OFF (in case was ON)
-  # SET(F90_ENABLE OFF)
-  # HIDE_VARIABLE(F90_ENABLE AND FCMIX_ENABLE)
-  HIDE_VARIABLE(F90_ENABLE)
-ENDIF(BUILD_ARKODE AND EXAMPLES_ENABLE AND FCMIX_ENABLE)
+# -------------------------------------------------------------
+# Enable CUDA support?
+# -------------------------------------------------------------
+OPTION(CUDA_ENABLE "Enable CUDA support" OFF)
 
 # -------------------------------------------------------------
-# Enable C++ support?
+# Enable RAJA support?
 # -------------------------------------------------------------
+OPTION(RAJA_ENABLE "Enable RAJA support" OFF)
 
-# C++ support is an option only if ARKode is built and 
-# examples are enabled
 
-IF(BUILD_ARKODE AND EXAMPLES_ENABLE)
-  SHOW_VARIABLE(CXX_ENABLE BOOL "Enable C++ ARKode examples" OFF)
-ELSE(BUILD_ARKODE AND EXAMPLES_ENABLE)
-  HIDE_VARIABLE(CXX_ENABLE)
-ENDIF(BUILD_ARKODE AND EXAMPLES_ENABLE)
+# ===============================================================
+# Options for external packages
+# ===============================================================
 
-# -------------------------------------------------------------
-# Enable BLAS/LAPACK support?
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
+# Enable BLAS support?
+# ---------------------------------------------------------------
+OPTION(BLAS_ENABLE "Enable BLAS support" OFF)
 
+# ---------------------------------------------------------------
+# Enable LAPACK/BLAS support?
+# ---------------------------------------------------------------
 OPTION(LAPACK_ENABLE "Enable Lapack support" OFF)
 
-IF(NOT LAPACK_ENABLE)
-  HIDE_VARIABLE(SUNDIALS_F77_FUNC_CASE)
-  HIDE_VARIABLE(SUNDIALS_F77_FUNC_UNDERSCORES)
-  HIDE_VARIABLE(LAPACK_LIBRARIES)
-ENDIF(NOT LAPACK_ENABLE)
+# LAPACK does not support extended precision
+IF(LAPACK_ENABLE AND SUNDIALS_PRECISION MATCHES "EXTENDED")
+  PRINT_WARNING("LAPACK is not compatible with ${SUNDIALS_PRECISION} precision"
+                "Disabling LAPACK")
+  FORCE_VARIABLE(LAPACK_ENABLE BOOL "LAPACK is disabled" OFF)
+ENDIF()
 
-# -------------------------------------------------------------
-# Enable SUPERLUMT support?
-# -------------------------------------------------------------
+# LAPACK does not support 64-bit integer index types
+IF(LAPACK_ENABLE AND SUNDIALS_INDEX_TYPE MATCHES "INT64_T")
+  PRINT_WARNING("LAPACK is not compatible with ${SUNDIALS_INDEX_TYPE} integers"
+                "Disabling LAPACK")
+  SET(LAPACK_ENABLE OFF CACHE BOOL "LAPACK is disabled" FORCE)
+ENDIF()
 
+# ---------------------------------------------------------------
+# Enable SuperLU_MT support?
+# ---------------------------------------------------------------
 OPTION(SUPERLUMT_ENABLE "Enable SUPERLUMT support" OFF)
 
-IF(NOT SUPERLUMT_ENABLE)
-  HIDE_VARIABLE(SUPERLUMT_THREAD_TYPE)
-  HIDE_VARIABLE(SUPERLUMT_LIBRARY_DIR)
-  HIDE_VARIABLE(SUPERLUMT_INCLUDE_DIR)
-  SET (SUPERLUMT_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
-ENDIF(NOT SUPERLUMT_ENABLE)
+# SuperLU_MT does not support extended precision
+IF(SUPERLUMT_ENABLE AND SUNDIALS_PRECISION MATCHES "EXTENDED")
+  PRINT_WARNING("SuperLU_MT is not compatible with ${SUNDIALS_PRECISION} precision"
+                "Disabling SuperLU_MT")
+  FORCE_VARIABLE(SUPERLUMT_ENABLE BOOL "SuperLU_MT is disabled" OFF)
+ENDIF()
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Enable KLU support?
-# -------------------------------------------------------------
-
+# ---------------------------------------------------------------
 OPTION(KLU_ENABLE "Enable KLU support" OFF)
 
-IF(NOT KLU_ENABLE)
-  HIDE_VARIABLE(KLU_LIBRARY_DIR)
-  HIDE_VARIABLE(KLU_INCLUDE_DIR)
-  SET (KLU_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
-ENDIF(NOT KLU_ENABLE)
+# KLU does not support single or extended precision
+IF(KLU_ENABLE AND
+  (SUNDIALS_PRECISION MATCHES "SINGLE" OR SUNDIALS_PRECISION MATCHES "EXTENDED"))
+  PRINT_WARNING("KLU is not compatible with ${SUNDIALS_PRECISION} precision"
+                "Disabling KLU")
+  FORCE_VARIABLE(KLU_ENABLE BOOL "KLU is disabled" OFF)
+ENDIF()
 
-# -------------------------------------------------------------
-# Enable MPI support?
-# -------------------------------------------------------------
-
-OPTION(MPI_ENABLE "Enable MPI support" OFF)
-
-IF(NOT MPI_ENABLE)
-  HIDE_VARIABLE(MPI_INCLUDE_PATH)
-  HIDE_VARIABLE(MPI_LIBRARIES)
-  HIDE_VARIABLE(MPI_EXTRA_LIBRARIES)
-  HIDE_VARIABLE(MPI_MPICC)
-  HIDE_VARIABLE(MPI_MPICXX)
-  HIDE_VARIABLE(MPI_MPIF77)
-  HIDE_VARIABLE(MPI_MPIF90)
-ENDIF(NOT MPI_ENABLE)
-
-# -------------------------------------------------------------
-# Enable HYPRE Vector support?
-# -------------------------------------------------------------
-
-OPTION(HYPRE_ENABLE "Enable Hypre support" OFF)
-IF(NOT MPI_ENABLE)
-  HIDE_VARIABLE(HYPRE_INCLUDE_DIR)
-  HIDE_VARIABLE(HYPRE_LIBRARY_DIR)
-  SET (HYPRE_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
-ENDIF(NOT MPI_ENABLE)
-
-# -------------------------------------------------------------
-# Enable OpenMP support?
-# -------------------------------------------------------------
-
-OPTION(OPENMP_ENABLE "Enable OpenMP support" OFF)
-
-IF(OPENMP_ENABLE)
-  FIND_PACKAGE(OpenMP)
-  IF(NOT OPENMP_FOUND)
-    message(STATUS "Disabling OpenMP support, could not determine compiler flags")
-  ENDIF(NOT OPENMP_FOUND)
-ENDIF(OPENMP_ENABLE)
-
-# -------------------------------------------------------------
-# Enable Pthread support?
-# -------------------------------------------------------------
-
-OPTION(PTHREAD_ENABLE "Enable Pthreads support" OFF)
+# ---------------------------------------------------------------
+# Enable hypre Vector support?
+# ---------------------------------------------------------------
+OPTION(HYPRE_ENABLE "Enable hypre support" OFF)
 
-IF(PTHREAD_ENABLE)
-  FIND_PACKAGE(Threads)
-  IF(CMAKE_USE_PTHREADS_INIT)
-    message(STATUS "Using Pthreads")
-    SET(PTHREADS_FOUND TRUE)
-    # SGS    
-  ELSE()
-    message(STATUS "Disabling Pthreads support, could not determine compiler flags")
-  endif()
-ENDIF(PTHREAD_ENABLE)
+# Using hypre requres building with MPI enabled
+IF(HYPRE_ENABLE AND NOT MPI_ENABLE)
+  PRINT_WARNING("MPI not enabled - Disabling hypre" 
+                "Set MPI_ENABLE to ON to use parhyp")
+  FORCE_VARIABLE(HYPRE_ENABLE BOOL "Enable hypre support" OFF)
+ENDIF()
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Enable PETSc support?
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
+OPTION(PETSC_ENABLE "Enable PETSc support" OFF)
+
+# Using PETSc requires building with MPI enabled
+IF(PETSC_ENABLE AND NOT MPI_ENABLE)
+  PRINT_WARNING("MPI not enabled - Disabling PETSc" 
+                "Set MPI_ENABLE to ON to use PETSc")
+  FORCE_VARIABLE(PETSC_ENABLE BOOL "Enable PETSc support" OFF)
+ENDIF()
 
-OPTION(PETSC_ENABLE "Enable PETSC support" OFF)
 
-IF(NOT PETSC_ENABLE)
-  HIDE_VARIABLE(PETSC_LIBRARY_DIR)
-  HIDE_VARIABLE(PETSC_INCLUDE_DIR)
-  SET (PETSC_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
-ENDIF(NOT PETSC_ENABLE)
+# ===============================================================
+# Options for examples
+# ===============================================================
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Enable examples?
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
-OPTION(EXAMPLES_ENABLE "Build the SUNDIALS examples" ON)
+# Enable C examples (on by default)
+OPTION(EXAMPLES_ENABLE_C "Build SUNDIALS C examples" ON)
+
+# F77 examples (on by default) are an option only if the Fortran
+# interface is enabled
+SET(DOCSTR "Build SUNDIALS Fortran examples")
+IF(FCMIX_ENABLE)
+  OPTION(EXAMPLES_ENABLE_F77 "${DOCSTR}" ON)
+  # Fortran examples do not support single or extended precision
+  IF(SUNDIALS_PRECISION MATCHES "EXTENDED" OR SUNDIALS_PRECISION MATCHES "SINGLE")
+    PRINT_WARNING("F77 examples are not compatible with ${SUNDIALS_PRECISION} precision"
+                  "EXAMPLES_ENABLE_F77")
+    FORCE_VARIABLE(EXAMPLES_ENABLE_F77 BOOL "Fortran examples are disabled" OFF)
+  ENDIF()
+ELSE()
+  # set back to OFF (in case was ON)
+  IF(EXAMPLES_ENABLE_F77)
+    PRINT_WARNING("EXAMPLES_ENABLE_F77 is ON but FCMIX is OFF"
+                  "Disabling EXAMPLES_ENABLE_F77")
+    FORCE_VARIABLE(EXAMPLES_ENABLE_F77 BOOL "${DOCSTR}" OFF)
+  ENDIF()
+  HIDE_VARIABLE(EXAMPLES_ENABLE_F77)
+ENDIF()
+
+# C++ examples (off by default) are an option only if ARKode is enabled
+SET(DOCSTR "Build ARKode C++ examples")
+IF(BUILD_ARKODE)
+  SHOW_VARIABLE(EXAMPLES_ENABLE_CXX BOOL "${DOCSTR}" OFF)
+ELSE()
+  # set back to OFF (in case was ON)
+  IF(EXAMPLES_ENABLE_CXX)
+    PRINT_WARNING("EXAMPLES_ENABLE_CXX is ON but BUILD_ARKODE is OFF"
+                  "Disabling EXAMPLES_ENABLE_CXX")
+    FORCE_VARIABLE(EXAMPLES_ENABLE_CXX BOOL "${DOCSTR}" OFF)
+  ENDIF()
+  HIDE_VARIABLE(EXAMPLES_ENABLE_CXX)
+ENDIF()
+
+# F90 examples (off by default) are an option only if ARKode is
+# built and the Fortran interface is enabled
+SET(DOCSTR "Build ARKode F90 examples")
+IF(FCMIX_ENABLE AND BUILD_ARKODE)
+  SHOW_VARIABLE(EXAMPLES_ENABLE_F90 BOOL "${DOCSTR}" OFF)
+  # Fortran90 examples do not support single or extended precision 
+  # NOTE: This check can be removed after Fortran configure file is integrated into examples
+  IF(SUNDIALS_PRECISION MATCHES "EXTENDED" OR SUNDIALS_PRECISION MATCHES "SINGLE")
+    PRINT_WARNING("F90 examples are not compatible with ${SUNDIALS_PRECISION} precision"
+                  "EXAMPLES_ENABLE_F90")
+    FORCE_VARIABLE(EXAMPLES_ENABLE_F90 BOOL "Fortran90 examples are disabled" OFF)
+  ENDIF()
+ELSE()
+  # set back to OFF (in case was ON)
+  IF(EXAMPLES_ENABLE_F90)
+    PRINT_WARNING("EXAMPLES_ENABLE_F90 is ON but FCMIX or BUILD_ARKODE is OFF"
+                  "Disabling EXAMPLES_ENABLE_F90")
+    FORCE_VARIABLE(EXAMPLES_ENABLE_F90 BOOL "${DOCSTR}" OFF)
+  ENDIF()
+  HIDE_VARIABLE(EXAMPLES_ENABLE_F90)
+ENDIF()
+
+# CUDA examples (off by default)
+SET(DOCSTR "Build SUNDIALS CUDA examples")
+IF(CUDA_ENABLE)
+  SHOW_VARIABLE(EXAMPLES_ENABLE_CUDA BOOL "${DOCSTR}" OFF)
+ELSE()
+  IF(EXAMPLES_ENABLE_CUDA)
+    PRINT_WARNING("EXAMPLES_ENABLE_CUDA is ON but CUDA_ENABLE is OFF"
+                  "Disabling EXAMPLES_ENABLE_CUDA")
+    FORCE_VARIABLE(EXAMPLES_ENABLE_CUDA BOOL "${DOCSTR}" OFF)
+  ENDIF()
+ENDIF()
+
+# RAJA examples (off by default)
+SET(DOCSTR "Build SUNDIALS RAJA examples")
+IF(RAJA_ENABLE)
+  SHOW_VARIABLE(EXAMPLES_ENABLE_RAJA BOOL "${DOCSTR}" OFF)
+ELSE()
+  IF(EXAMPLES_ENABLE_RAJA)
+    PRINT_WARNING("EXAMPLES_ENABLE_RAJA is ON but RAJA_ENABLE is OFF"
+                  "Disabling EXAMPLES_ENABLE_RAJA")
+    FORCE_VARIABLE(EXAMPLES_ENABLE_RAJA BOOL "${DOCSTR}" OFF)
+  ENDIF()
+ENDIF()
+
+# If any of the above examples are enabled set EXAMPLES_ENABLED to TRUE
+IF(EXAMPLES_ENABLE_C OR
+    EXAMPLES_ENABLE_F77 OR
+    EXAMPLES_ENABLE_CXX OR
+    EXAMPLES_ENABLE_F90 OR
+    EXAMPLES_ENABLE_CUDA OR
+    EXAMPLES_ENABLE_RAJA)
+  SET(EXAMPLES_ENABLED TRUE)
+ELSE()
+  SET(EXAMPLES_ENABLED FALSE)
+ENDIF()
 
-IF(EXAMPLES_ENABLE)
+# ---------------------------------------------------------------
+# Install examples?
+# ---------------------------------------------------------------
+
+IF(EXAMPLES_ENABLED)
 
   # If examples are enabled, set different options
 
@@ -442,7 +544,7 @@ IF(EXAMPLES_ENABLE)
     SET(LINK_LIBRARY_TYPE "static")
   ENDIF(BUILD_SHARED_LIBS)
 
-  # Check if example files are to be exported
+  # Enable installing examples by default
   SHOW_VARIABLE(EXAMPLES_INSTALL BOOL "Install example files" ON)
 
   # If examples are to be exported, check where we should install them.
@@ -450,13 +552,24 @@ IF(EXAMPLES_ENABLE)
 
     SHOW_VARIABLE(EXAMPLES_INSTALL_PATH PATH
       "Output directory for installing example files" "${CMAKE_INSTALL_PREFIX}/examples")
-    
+
     IF(NOT EXAMPLES_INSTALL_PATH)
       PRINT_WARNING("The example installation path is empty"
-        "Example installation path was reset to its default value")
+                    "Example installation path was reset to its default value")
       SET(EXAMPLES_INSTALL_PATH "${CMAKE_INSTALL_PREFIX}/examples" CACHE STRING
         "Output directory for installing example files" FORCE)
     ENDIF(NOT EXAMPLES_INSTALL_PATH)
+    
+    # create test_install target and directory for running smoke tests after
+    # installation
+    ADD_CUSTOM_TARGET(test_install)
+
+    SET(TEST_INSTALL_DIR ${PROJECT_BINARY_DIR}/Testing_Install)
+
+    IF(NOT EXISTS ${TEST_INSTALL_DIR})
+      FILE(MAKE_DIRECTORY ${TEST_INSTALL_DIR})
+    ENDIF()
+
 
   ELSE(EXAMPLES_INSTALL)
 
@@ -464,7 +577,7 @@ IF(EXAMPLES_ENABLE)
 
   ENDIF(EXAMPLES_INSTALL)
 
-ELSE(EXAMPLES_ENABLE)
+ELSE(EXAMPLES_ENABLED)
 
   # If examples are disabled, hide all options related to
   # building and installing the SUNDIALS examples
@@ -472,11 +585,17 @@ ELSE(EXAMPLES_ENABLE)
   HIDE_VARIABLE(EXAMPLES_INSTALL)
   HIDE_VARIABLE(EXAMPLES_INSTALL_PATH)
   
-ENDIF(EXAMPLES_ENABLE)
+ENDIF(EXAMPLES_ENABLED)
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
+# Include development examples in regression tests?
+# ---------------------------------------------------------------
+OPTION(SUNDIALS_DEVTESTS "Include development tests in make test" OFF)
+MARK_AS_ADVANCED(FORCE SUNDIALS_DEVTESTS)
+
+# ===============================================================
 # Add any other necessary compiler flags & definitions
-# -------------------------------------------------------------
+# ===============================================================
 
 # Under Windows, add compiler directive to inhibit warnings
 # about use of unsecure functions
@@ -489,68 +608,69 @@ IF(APPLE)
   SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS} -undefined dynamic_lookup")
 ENDIF(APPLE)
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # A Fortran compiler is needed if:
 # (a) FCMIX is enabled
-# (b) LAPACK is enabled (for the name-mangling scheme)
-# -------------------------------------------------------------
+# (b) BLAS is enabled (for the name-mangling scheme)
+# (c) LAPACK is enabled (for the name-mangling scheme)
+# ---------------------------------------------------------------
 
-IF(FCMIX_ENABLE OR LAPACK_ENABLE)
+IF(FCMIX_ENABLE OR BLAS_ENABLE OR LAPACK_ENABLE)
   INCLUDE(SundialsFortran)
   IF(NOT F77_FOUND AND FCMIX_ENABLE)
     PRINT_WARNING("Fortran compiler not functional"
-      "FCMIX support will not be provided")
-  ENDIF(NOT F77_FOUND AND FCMIX_ENABLE)
-ENDIF(FCMIX_ENABLE OR LAPACK_ENABLE)
+                  "FCMIX support will not be provided")
+  ENDIF()
+ENDIF()
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # A Fortran90 compiler is needed if:
-# (a) F90 is enabled, and
-# (b) ARKODE examples are enabled
-# -------------------------------------------------------------
+# (a) F90 ARKODE examples are enabled
+# ---------------------------------------------------------------
 
-IF(F90_ENABLE AND BUILD_ARKODE)
+IF(EXAMPLES_ENABLE_F90)
   INCLUDE(SundialsFortran90)
-  IF(NOT F90_FOUND AND F90_ENABLE)
+  IF(NOT F90_FOUND)
     PRINT_WARNING("Fortran90 compiler not functional"
-      "F90 support will not be provided")
-  ENDIF(NOT F90_FOUND AND F90_ENABLE)
-ENDIF(F90_ENABLE AND BUILD_ARKODE)
+                  "F90 support will not be provided")
+  ENDIF()
+ENDIF()
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # A C++ compiler is needed if:
-# (a) C++ is enabled, and
-# (b) ARKODE examples are enabled
-# -------------------------------------------------------------
+# (a) C++ ARKODE examples are enabled
+# (b) CUDA is enabled
+# (c) RAJA is enabled
+# ---------------------------------------------------------------
 
-IF(CXX_ENABLE AND BUILD_ARKODE)
+IF(EXAMPLES_ENABLE_CXX OR CUDA_ENABLE OR RAJA_ENABLE)
   INCLUDE(SundialsCXX)
-  IF(NOT CXX_FOUND AND CXX_ENABLE)
+  IF(NOT CXX_FOUND)
     PRINT_WARNING("C++ compiler not functional"
-      "C++ support will not be provided")
-  ENDIF(NOT CXX_FOUND AND CXX_ENABLE)
-ENDIF(CXX_ENABLE AND BUILD_ARKODE)
+                  "C++ support will not be provided")
+  ENDIF()
+ENDIF()
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Check if we need an alternate way of specifying the Fortran
 # name-mangling scheme if we were unable to infer it using a
-# compiler. 
+# compiler.
 # Ask the user to specify the case and number of appended underscores
-# corresponding to the Fortran name-mangling scheme of symbol names 
+# corresponding to the Fortran name-mangling scheme of symbol names
 # that do not themselves contain underscores (recall that this is all
 # we really need for the interfaces to LAPACK).
 # Note: the default scheme is lower case - one underscore
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
-IF(LAPACK_ENABLE AND NOT F77SCHEME_FOUND)
+IF(BLAS_ENABLE OR LAPACK_ENABLE AND NOT F77SCHEME_FOUND)
   # Specify the case for the Fortran name-mangling scheme
   SHOW_VARIABLE(SUNDIALS_F77_FUNC_CASE STRING
     "case of Fortran function names (lower/upper)"
     "lower")
   # Specify the number of appended underscores for the Fortran name-mangling scheme
-  SHOW_VARIABLE(SUNDIALS_F77_FUNC_UNDERSCORES STRING 
+  SHOW_VARIABLE(SUNDIALS_F77_FUNC_UNDERSCORES STRING
     "number of underscores appended to Fortran function names"
-    "one")  
+    "one")
   # Based on the given case and number of underscores,
   # set the C preprocessor macro definition
   IF(${SUNDIALS_F77_FUNC_CASE} MATCHES "lower")
@@ -580,13 +700,13 @@ IF(LAPACK_ENABLE AND NOT F77SCHEME_FOUND)
   SET(CMAKE_Fortran_SCHEME_WITH_UNDERSCORES "my_sub_")
   # We now "have" a scheme.
   SET(F77SCHEME_FOUND TRUE)
-ENDIF(LAPACK_ENABLE AND NOT F77SCHEME_FOUND)
+ENDIF(BLAS_ENABLE OR LAPACK_ENABLE AND NOT F77SCHEME_FOUND)
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # If we have a name-mangling scheme (either automatically
-# inferred or provided by the user), set the SUNDIALS 
+# inferred or provided by the user), set the SUNDIALS
 # compiler preprocessor macro definitions.
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
 SET(F77_MANGLE_MACRO1 "")
 SET(F77_MANGLE_MACRO2 "")
@@ -611,7 +731,7 @@ IF(F77SCHEME_FOUND)
   IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB__")
     SET(F77_MANGLE_MACRO1 "#define SUNDIALS_F77_FUNC(name,NAME) NAME ## __")
   ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MYSUB__")
-  # Symbols with underscores 
+  # Symbols with underscores
   IF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub")
     SET(F77_MANGLE_MACRO2 "#define SUNDIALS_F77_FUNC_(name,NAME) name")
   ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "my_sub")
@@ -632,47 +752,221 @@ IF(F77SCHEME_FOUND)
   ENDIF(${CMAKE_Fortran_SCHEME_NO_UNDERSCORES} MATCHES "MY_SUB__")
 ENDIF(F77SCHEME_FOUND)
 
+# ---------------------------------------------------------------
+# Decide how to compile MPI codes.
+# ---------------------------------------------------------------
+
+IF(MPI_ENABLE)
+  # show command to run MPI codes (defaults to mpirun)
+  SHOW_VARIABLE(MPI_RUN_COMMAND STRING "MPI run command" "mpirun")
+
+  INCLUDE(SundialsMPIC)
+  IF(MPIC_FOUND)
+    IF(CXX_FOUND AND EXAMPLES_ENABLE_CXX)
+      INCLUDE(SundialsMPICXX)
+    ENDIF()
+    IF(F77_FOUND AND EXAMPLES_ENABLE_F77)
+      INCLUDE(SundialsMPIF)
+    ENDIF()
+    IF(F90_FOUND AND EXAMPLES_ENABLE_F90)
+      INCLUDE(SundialsMPIF90)
+    ENDIF()
+  ELSE()
+    PRINT_WARNING("MPI not functional"
+                  "Parallel support will not be provided")
+  ENDIF()
+
+  IF(MPIC_MPI2)
+    SET(F77_MPI_COMM_F2C "#define SUNDIALS_MPI_COMM_F2C 1")
+  ELSE()
+    SET(F77_MPI_COMM_F2C "#define SUNDIALS_MPI_COMM_F2C 0")
+  ENDIF()
+
+ELSE()
+
+  HIDE_VARIABLE(MPI_INCLUDE_PATH)
+  HIDE_VARIABLE(MPI_LIBRARIES)
+  HIDE_VARIABLE(MPI_EXTRA_LIBRARIES)
+  HIDE_VARIABLE(MPI_MPICC)
+  HIDE_VARIABLE(MPI_MPICXX)
+  HIDE_VARIABLE(MPI_MPIF77)
+  HIDE_VARIABLE(MPI_MPIF90)
+
+ENDIF(MPI_ENABLE)
+
+# ---------------------------------------------------------------
+# If using MPI with C++, disable C++ extensions (for known wrappers)
+# ---------------------------------------------------------------
+
+# IF(MPICXX_FOUND)
+#   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMPICH_SKIP_MPICXX -DOMPI_SKIP_MPICXX -DLAM_BUILDING")
+# ENDIF(MPICXX_FOUND)
+
 # -------------------------------------------------------------
-# Find (and test) the Lapack libraries
+# Find OpenMP
+# -------------------------------------------------------------
+
+IF(OPENMP_ENABLE)
+  FIND_PACKAGE(OpenMP)
+  IF(NOT OPENMP_FOUND)
+    message(STATUS "Disabling OpenMP support, could not determine compiler flags")
+  ENDIF(NOT OPENMP_FOUND)
+ENDIF(OPENMP_ENABLE)
+
+# -------------------------------------------------------------
+# Find PThreads
+# -------------------------------------------------------------
+
+IF(PTHREAD_ENABLE)
+  FIND_PACKAGE(Threads)
+  IF(CMAKE_USE_PTHREADS_INIT)
+    message(STATUS "Using Pthreads")
+    SET(PTHREADS_FOUND TRUE)
+    # SGS    
+  ELSE()
+    message(STATUS "Disabling Pthreads support, could not determine compiler flags")
+  endif()
+ENDIF(PTHREAD_ENABLE)
+
 # -------------------------------------------------------------
+# Find CUDA
+# -------------------------------------------------------------
+
+# disable CUDA if a working C++ compiler is not found
+IF(CUDA_ENABLE AND (NOT CXX_FOUND))
+  PRINT_WARNING("C++ compiler required for CUDA support" "Disabling CUDA")
+  FORCE_VARIABLE(CUDA_ENABLE BOOL "CUDA disabled" OFF)
+ENDIF()
+
+if(CUDA_ENABLE)
+  find_package(CUDA)
+  
+  if (CUDA_FOUND)
+    #message("CUDA found!")
+    set(CUDA_NVCC_FLAGS "-lineinfo")
+  else()
+    message(STATUS "Disabling CUDA support, could not find CUDA.")
+  endif()
+endif(CUDA_ENABLE)
+
+# -------------------------------------------------------------
+# Find RAJA
+# -------------------------------------------------------------
+
+# disable RAJA if CUDA is not enabled/working
+IF(RAJA_ENABLE AND (NOT CUDA_FOUND))
+  PRINT_WARNING("CUDA is required for RAJA support" "Please enable CUDA and RAJA")
+  FORCE_VARIABLE(RAJA_ENABLE BOOL "RAJA disabled" OFF)
+ENDIF()
+
+# Check if C++11 compiler is available
+IF(RAJA_ENABLE)
+  include(CheckCXXCompilerFlag)
+  CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
+
+  IF(COMPILER_SUPPORTS_CXX11)
+    set(CMAKE_CXX_STANDARD 11)
+  ELSE()
+    PRINT_WARNING("C++11 compliant compiler required for RAJA support" "Disabling RAJA")
+    FORCE_VARIABLE(RAJA_ENABLE BOOL "RAJA disabled" OFF)
+  ENDIF()
+ENDIF()
+
+if(RAJA_ENABLE)
+  # Look for CMake configuration file in RAJA installation
+  find_package(RAJA CONFIGS)
+  if (RAJA_FOUND)
+    #message("RAJA found!")
+    include_directories(${RAJA_INCLUDE_DIR})
+    set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} ${RAJA_NVCC_FLAGS})
+  else()
+    PRINT_WARNING("RAJA configuration not found" "Please set RAJA_DIR to provide path to RAJA CMake configuration file.")
+  endif()
+endif(RAJA_ENABLE)
+
+# ===============================================================
+# Find (and test) external packages
+# ===============================================================
+
+# ---------------------------------------------------------------
+# Find (and test) the BLAS libraries
+# ---------------------------------------------------------------
+
+# If BLAS is needed, first try to find the appropriate
+# libraries and linker flags needed to link against them.
+
+IF(BLAS_ENABLE)
+
+  # find BLAS
+  INCLUDE(SundialsBlas)
+
+  # show after include so FindBlas can locate BLAS_LIBRARIES if necessary
+  SHOW_VARIABLE(BLAS_LIBRARIES STRING "Blas libraries" "${BLAS_LIBRARIES}")
+
+  IF(BLAS_LIBRARIES AND NOT BLAS_FOUND)
+    PRINT_WARNING("BLAS not functional"
+                  "BLAS support will not be provided")
+  ELSE()
+    #set sundials_config.h symbol via sundials_config.in
+    SET(SUNDIALS_BLAS TRUE)
+  ENDIF()
+
+ELSE()
+
+  IF(NOT LAPACK_ENABLE)
+    HIDE_VARIABLE(SUNDIALS_F77_FUNC_CASE)
+    HIDE_VARIABLE(SUNDIALS_F77_FUNC_UNDERSCORES)
+  ENDIF()
+  HIDE_VARIABLE(BLAS_LIBRARIES)
+
+ENDIF()
+
+# ---------------------------------------------------------------
+# Find (and test) the Lapack libraries
+# ---------------------------------------------------------------
 
 # If LAPACK is needed, first try to find the appropriate
 # libraries and linker flags needed to link against them.
 
 IF(LAPACK_ENABLE)
 
-  # find BLAS and LAPACK Libraries
+  # find LAPACK and BLAS Libraries
   INCLUDE(SundialsLapack)
 
-  SHOW_VARIABLE(LAPACK_LIBRARIES STRING "Blas and Lapack libraries" "${LAPACK_LIBRARIES}")
+  # show after include so FindLapack can locate LAPCK_LIBRARIES if necessary
+  SHOW_VARIABLE(LAPACK_LIBRARIES STRING "Lapack and Blas libraries" "${LAPACK_LIBRARIES}")
 
   IF(LAPACK_LIBRARIES AND NOT LAPACK_FOUND)
     PRINT_WARNING("LAPACK not functional"
-      "Blas/Lapack support will not be provided")
-  ELSE(LAPACK_LIBRARIES AND NOT LAPACK_FOUND)
+                  "Blas/Lapack support will not be provided")
+  ELSE()
     #set sundials_config.h symbol via sundials_config.in
     SET(SUNDIALS_BLAS_LAPACK TRUE)
-  ENDIF(LAPACK_LIBRARIES AND NOT LAPACK_FOUND)
-  
+  ENDIF()
 
-ELSE(LAPACK_ENABLE)
+ELSE()
 
+  IF(NOT BLAS_ENABLE)
+    HIDE_VARIABLE(SUNDIALS_F77_FUNC_CASE)
+    HIDE_VARIABLE(SUNDIALS_F77_FUNC_UNDERSCORES)
+  ENDIF()
   HIDE_VARIABLE(LAPACK_LIBRARIES)
 
-ENDIF(LAPACK_ENABLE)
+ENDIF()
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Find (and test) the SUPERLUMT libraries
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
+
+# >>>>>>> NOTE: Need to add check for SuperLU_MT integer type
 
 # If SUPERLUMT is needed, first try to find the appropriate
 # libraries to link against them.
 
 IF(SUPERLUMT_ENABLE)
 
-  # get thread type for SUPERLUMT (OpenMP or Pthreads(default))
-  SET(SUPERLUMT_THREAD_TYPE "Pthread" CACHE STRING "OpenMP or Pthread")
-  SHOW_VARIABLE(SUPERLUMT_THREAD_TYPE STRING "SUPERLUMT threading type: OpenMP or Pthread" "${SUPERLUMT_THREAD_TYPE}")
+  # Show SuperLU_MT options and set default thread type (Pthreads)
+  SHOW_VARIABLE(SUPERLUMT_THREAD_TYPE STRING "SUPERLUMT threading type: OpenMP or Pthread" "Pthread")
   SHOW_VARIABLE(SUPERLUMT_INCLUDE_DIR PATH "SUPERLUMT include directory" "${SUPERLUMT_INCLUDE_DIR}")
   SHOW_VARIABLE(SUPERLUMT_LIBRARY_DIR PATH "SUPERLUMT library directory" "${SUPERLUMT_LIBRARY_DIR}")
 
@@ -682,24 +976,26 @@ IF(SUPERLUMT_ENABLE)
     # sundials_config.h symbols
     SET(SUNDIALS_SUPERLUMT TRUE)
     SET(SUNDIALS_SUPERLUMT_THREAD_TYPE ${SUPERLUMT_THREAD_TYPE})
-  ENDIF(SUPERLUMT_FOUND)
+    INCLUDE_DIRECTORIES(${SUPERLUMT_INCLUDE_DIR})
+  ENDIF()
 
   IF(SUPERLUMT_LIBRARIES AND NOT SUPERLUMT_FOUND)
     PRINT_WARNING("SUPERLUMT not functional - support will not be provided"
-      "Double check spelling specified libraries (search is case sensitive)")
+                  "Double check spelling specified libraries (search is case sensitive)")
   ENDIF(SUPERLUMT_LIBRARIES AND NOT SUPERLUMT_FOUND)
 
-ELSE(SUPERLUMT_ENABLE)
+ELSE()
 
   HIDE_VARIABLE(SUPERLUMT_THREAD_TYPE)
-  HIDE_VARIABLE(SUPERLUMT_INCLUDE_DIR)
   HIDE_VARIABLE(SUPERLUMT_LIBRARY_DIR)
+  HIDE_VARIABLE(SUPERLUMT_INCLUDE_DIR)
+  SET (SUPERLUMT_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
 
-ENDIF(SUPERLUMT_ENABLE)
+ENDIF()
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Find (and test) the KLU libraries
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
 # If KLU is requested, first try to find the appropriate libraries to
 # link against them.
@@ -707,124 +1003,105 @@ ENDIF(SUPERLUMT_ENABLE)
 IF(KLU_ENABLE)
 
   SHOW_VARIABLE(KLU_INCLUDE_DIR PATH "KLU include directory"
-    "${KLU_INCLUDE_DIR}") 
+    "${KLU_INCLUDE_DIR}")
   SHOW_VARIABLE(KLU_LIBRARY_DIR PATH
     "Klu library directory" "${KLU_LIBRARY_DIR}")
 
   INCLUDE(SundialsKLU)
 
-  IF(KLU_FOUND) 
+  IF(KLU_FOUND)
     # sundials_config.h symbol
     SET(SUNDIALS_KLU TRUE)
     INCLUDE_DIRECTORIES(${KLU_INCLUDE_DIR})
   ENDIF(KLU_FOUND)
 
-  IF(KLU_LIBRARIES AND NOT KLU_FOUND) 
-    PRINT_WARNING("KLU not functional - support will not be provided" 
-      "Double check spelling of include path and specified libraries (search is case sensitive)")
+  IF(KLU_LIBRARIES AND NOT KLU_FOUND)
+    PRINT_WARNING("KLU not functional - support will not be provided"
+                  "Double check spelling of include path and specified libraries (search is case sensitive)")
   ENDIF(KLU_LIBRARIES AND NOT KLU_FOUND)
 
-ENDIF(KLU_ENABLE)
+ELSE()
 
-# -------------------------------------------------------------
-# Decide how to compile MPI codes.
-# -------------------------------------------------------------
+  HIDE_VARIABLE(KLU_LIBRARY_DIR)
+  HIDE_VARIABLE(KLU_INCLUDE_DIR)
+  SET (KLU_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
 
-IF(MPI_ENABLE)
-  # get run command for mpi (openmpi or OpenMP or Pthreads(default))
-  SET(MPI_RUN_COMMAND "mpirun" CACHE STRING "mpirun or srun")
-  SHOW_VARIABLE(MPI_RUN_COMMAND STRING "MPI run command: mpirun or srun" "${MPI_RUN_COMMAND}")
-  INCLUDE(SundialsMPIC)
-  IF(NOT MPIC_FOUND)
-    PRINT_WARNING("MPI not functional"
-      "Parallel support will not be provided")
-  ENDIF(NOT MPIC_FOUND)
-  IF(MPIC_MPI2)
-    SET(F77_MPI_COMM_F2C "#define SUNDIALS_MPI_COMM_F2C 1")
-  ELSE(MPIC_MPI2)
-    SET(F77_MPI_COMM_F2C "#define SUNDIALS_MPI_COMM_F2C 0")
-  ENDIF(MPIC_MPI2)
-  IF(MPIC_FOUND AND FCMIX_ENABLE)
-    INCLUDE(SundialsMPIF)
-  ENDIF(MPIC_FOUND AND FCMIX_ENABLE)
-  IF(MPIC_FOUND AND CXX_ENABLE)
-    INCLUDE(SundialsMPICXX)
-  ENDIF(MPIC_FOUND AND CXX_ENABLE)
-  IF(MPIC_FOUND AND F90_ENABLE)
-    INCLUDE(SundialsMPIF90)
-  ENDIF(MPIC_FOUND AND F90_ENABLE)
-ENDIF(MPI_ENABLE)
+ENDIF(KLU_ENABLE)
 
-#-------------------------------------------------------------
-# Find the Hypre libraries
-#-------------------------------------------------------------
-IF(HYPRE_ENABLE AND NOT MPI_ENABLE)
-    PRINT_WARNING("MPI not enabled - HYPRE support will not be provided" 
-      "Set MPI_ENABLE to ON to use parhyp")
-ENDIF(HYPRE_ENABLE AND NOT MPI_ENABLE)
+# ---------------------------------------------------------------
+# Find (and test) the hypre libraries
+# ---------------------------------------------------------------
+
+# >>>>>>> NOTE: Need to add check for hypre precision and integer type
 
-IF(HYPRE_ENABLE AND MPI_ENABLE)
+IF(HYPRE_ENABLE)
   SHOW_VARIABLE(HYPRE_INCLUDE_DIR PATH "HYPRE include directory"
-    "${HYPRE_INCLUDE_DIR}") 
+    "${HYPRE_INCLUDE_DIR}")
   SHOW_VARIABLE(HYPRE_LIBRARY_DIR PATH
     "HYPRE library directory" "${HYPRE_LIBRARY_DIR}")
 
   INCLUDE(SundialsHypre)
 
-  IF(HYPRE_FOUND) 
+  IF(HYPRE_FOUND)
     # sundials_config.h symbol
     SET(SUNDIALS_HYPRE TRUE)
     INCLUDE_DIRECTORIES(${HYPRE_INCLUDE_DIR})
   ENDIF(HYPRE_FOUND)
 
-  IF(HYPRE_LIBRARIES AND NOT HYPRE_FOUND) 
-    PRINT_WARNING("HYPRE not functional - support will not be provided" 
-      "Found hypre library, test code does not work")
+  IF(HYPRE_LIBRARIES AND NOT HYPRE_FOUND)
+    PRINT_WARNING("HYPRE not functional - support will not be provided"
+                  "Found hypre library, test code does not work")
   ENDIF(HYPRE_LIBRARIES AND NOT HYPRE_FOUND)
   
-ENDIF(HYPRE_ENABLE AND MPI_ENABLE)
+ELSE()
 
-# -------------------------------------------------------------
+  HIDE_VARIABLE(HYPRE_INCLUDE_DIR)
+  HIDE_VARIABLE(HYPRE_LIBRARY_DIR)
+  SET (HYPRE_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
+
+ENDIF()
+
+# ---------------------------------------------------------------
 # Find (and test) the PETSc libraries
-# -------------------------------------------------------------
-IF(PETSC_ENABLE AND NOT MPI_ENABLE)
-    PRINT_WARNING("MPI not enabled - PETSc support will not be provided" 
-      "Set MPI_ENABLE to ON to use PETSc.")
-ENDIF(PETSC_ENABLE AND NOT MPI_ENABLE)
+# ---------------------------------------------------------------
+
+# >>>>>>> NOTE: Need to add check for PETSc precision and integer type
 
-IF(PETSC_ENABLE AND MPI_ENABLE)
+IF(PETSC_ENABLE)
   SHOW_VARIABLE(PETSC_INCLUDE_DIR PATH "PETSc include directory"
-    "${PETSC_INCLUDE_DIR}") 
+    "${PETSC_INCLUDE_DIR}")
   SHOW_VARIABLE(PETSC_LIBRARY_DIR PATH
     "PETSc library directory" "${PETSC_LIBRARY_DIR}")
 
   INCLUDE(SundialsPETSc)
 
-  IF(PETSC_FOUND) 
+  IF(PETSC_FOUND)
     # sundials_config.h symbol
     SET(SUNDIALS_PETSC TRUE)
     INCLUDE_DIRECTORIES(${PETSC_INCLUDE_DIR})
   ENDIF(PETSC_FOUND)
 
-  IF(PETSC_LIBRARIES AND NOT PETSC_FOUND) 
-    PRINT_WARNING("PETSC not functional - support will not be provided" 
-      "Double check spelling specified libraries (search is case sensitive)")
+  IF(PETSC_LIBRARIES AND NOT PETSC_FOUND)
+    PRINT_WARNING("PETSC not functional - support will not be provided"
+                  "Double check spelling specified libraries (search is case sensitive)")
   ENDIF(PETSC_LIBRARIES AND NOT PETSC_FOUND)
 
-ENDIF(PETSC_ENABLE AND MPI_ENABLE)
+ELSE()
 
+  HIDE_VARIABLE(PETSC_LIBRARY_DIR)
+  HIDE_VARIABLE(PETSC_INCLUDE_DIR)
+  SET (PETSC_DISABLED TRUE CACHE INTERNAL "GUI - return when first set")
 
-# -------------------------------------------------------------
-# If using MPI with C++, disable C++ extensions (for known wrappers)
-# -------------------------------------------------------------
+ENDIF()
 
-# IF(MPICXX_FOUND)
-#   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMPICH_SKIP_MPICXX -DOMPI_SKIP_MPICXX -DLAM_BUILDING")
-# ENDIF(MPICXX_FOUND)
 
-# -------------------------------------------------------------
+# ===============================================================
+# Add source and configuration files 
+# ===============================================================
+
+# ---------------------------------------------------------------
 # Configure the header file sundials_config.h
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
 # All required substitution variables should be available at this point.
 # Generate the header file and place it in the binary dir.
@@ -832,46 +1109,74 @@ CONFIGURE_FILE(
   ${PROJECT_SOURCE_DIR}/include/sundials/sundials_config.in
   ${PROJECT_BINARY_DIR}/include/sundials/sundials_config.h
   )
+CONFIGURE_FILE(
+  ${PROJECT_SOURCE_DIR}/include/sundials/sundials_fconfig.in
+  ${PROJECT_BINARY_DIR}/include/sundials/sundials_fconfig.h
+  )
 
 # Add the include directory in the source tree and the one in
 # the binary tree (for the header file sundials_config.h)
-IF(SUPERLUMT_FOUND)
-  INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include ${SUPERLUMT_INCLUDE_DIR})
-ELSE(SUPERLUMT_FOUND)
-  INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include)
-ENDIF(SUPERLUMT_FOUND)
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include)
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Add selected modules to the build system
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
 # Shared components
 
 ADD_SUBDIRECTORY(src/sundials)
 ADD_SUBDIRECTORY(src/nvec_ser)
+ADD_SUBDIRECTORY(src/sunmat_dense)
+ADD_SUBDIRECTORY(src/sunmat_band)
+ADD_SUBDIRECTORY(src/sunmat_sparse)
+ADD_SUBDIRECTORY(src/sunlinsol_band)
+ADD_SUBDIRECTORY(src/sunlinsol_dense)
+IF(KLU_FOUND)
+  ADD_SUBDIRECTORY(src/sunlinsol_klu)
+ENDIF(KLU_FOUND)
+IF(SUPERLUMT_FOUND)
+  ADD_SUBDIRECTORY(src/sunlinsol_superlumt)
+ENDIF(SUPERLUMT_FOUND)
+IF(LAPACK_FOUND)
+  ADD_SUBDIRECTORY(src/sunlinsol_lapackband)
+  ADD_SUBDIRECTORY(src/sunlinsol_lapackdense)
+ENDIF(LAPACK_FOUND)
+ADD_SUBDIRECTORY(src/sunlinsol_spgmr)
+ADD_SUBDIRECTORY(src/sunlinsol_spfgmr)
+ADD_SUBDIRECTORY(src/sunlinsol_spbcgs)
+ADD_SUBDIRECTORY(src/sunlinsol_sptfqmr)
+ADD_SUBDIRECTORY(src/sunlinsol_pcg)
 IF(MPIC_FOUND)
   ADD_SUBDIRECTORY(src/nvec_par)
 ENDIF(MPIC_FOUND)
 
-IF(SUNDIALS_HYPRE)
+IF(HYPRE_FOUND)
   ADD_SUBDIRECTORY(src/nvec_parhyp)
-ENDIF(SUNDIALS_HYPRE)
+ENDIF(HYPRE_FOUND)
 
 IF(OPENMP_FOUND)
-  ADD_SUBDIRECTORY(src/nvec_openmp)	
+  ADD_SUBDIRECTORY(src/nvec_openmp)
 ENDIF(OPENMP_FOUND)
 
 IF(PTHREADS_FOUND)
-  ADD_SUBDIRECTORY(src/nvec_pthreads)   
+  ADD_SUBDIRECTORY(src/nvec_pthreads)
 ENDIF(PTHREADS_FOUND)
 
 IF(PETSC_FOUND)
-  ADD_SUBDIRECTORY(src/nvec_petsc)   
+  ADD_SUBDIRECTORY(src/nvec_petsc)
 ENDIF(PETSC_FOUND)
 
+IF(CUDA_FOUND)
+  ADD_SUBDIRECTORY(src/nvec_cuda)   
+ENDIF(CUDA_FOUND)
+
+IF(RAJA_FOUND)
+  ADD_SUBDIRECTORY(src/nvec_raja)   
+ENDIF(RAJA_FOUND)
+
 # ARKODE library
 
-IF(BUILD_ARKODE)	
+IF(BUILD_ARKODE)
   ADD_SUBDIRECTORY(src/arkode)
   IF(FCMIX_ENABLE AND F77_FOUND)
     ADD_SUBDIRECTORY(src/arkode/fcmix)
@@ -880,7 +1185,7 @@ ENDIF(BUILD_ARKODE)
 
 # CVODE library
 
-IF(BUILD_CVODE)	
+IF(BUILD_CVODE)
   ADD_SUBDIRECTORY(src/cvode)
   IF(FCMIX_ENABLE AND F77_FOUND)
     ADD_SUBDIRECTORY(src/cvode/fcmix)
@@ -889,13 +1194,13 @@ ENDIF(BUILD_CVODE)
 
 # CVODES library
 
-IF(BUILD_CVODES)	
+IF(BUILD_CVODES)
   ADD_SUBDIRECTORY(src/cvodes)
 ENDIF(BUILD_CVODES)
 
 # IDA library
 
-IF(BUILD_IDA)	
+IF(BUILD_IDA)
   ADD_SUBDIRECTORY(src/ida)
   IF(FCMIX_ENABLE AND F77_FOUND)
     ADD_SUBDIRECTORY(src/ida/fcmix)
@@ -904,13 +1209,13 @@ ENDIF(BUILD_IDA)
 
 # IDAS library
 
-IF(BUILD_IDAS)	
+IF(BUILD_IDAS)
   ADD_SUBDIRECTORY(src/idas)
 ENDIF(BUILD_IDAS)
 
 # KINSOL library
 
-IF(BUILD_KINSOL)	
+IF(BUILD_KINSOL)
   ADD_SUBDIRECTORY(src/kinsol)
   IF(FCMIX_ENABLE AND F77_FOUND)
     ADD_SUBDIRECTORY(src/kinsol/fcmix)
@@ -919,17 +1224,17 @@ ENDIF(BUILD_KINSOL)
 
 # CPODES library
 
-IF(BUILD_CPODES)	
+IF(BUILD_CPODES)
   ADD_SUBDIRECTORY(src/cpodes)
 ENDIF(BUILD_CPODES)
 
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 # Include the subdirectories corresponding to various examples
-# -------------------------------------------------------------
+# ---------------------------------------------------------------
 
 # If building and installing the examples is enabled, include
 # the subdirectories for those examples that will be built.
-# Also, if we will generate exported example Makefiles, set 
+# Also, if we will generate exported example Makefiles, set
 # variables needed in generating them from templates.
 
 # For now, TestRunner is not being distributed.
@@ -940,23 +1245,29 @@ ENDIF(BUILD_CPODES)
 
 INCLUDE(SundialsAddTest)
 HIDE_VARIABLE(TESTRUNNER)
-IF(EXAMPLES_ENABLE)
+
+IF(EXAMPLES_ENABLED)
+
+  # enable regression testing with 'make test'
   IF(TESTRUNNER)
     ENABLE_TESTING()
-  ENDIF(TESTRUNNER)
+  ENDIF()
 
+  # set variables used in generating CMake and Makefiles for examples
   IF(EXAMPLES_INSTALL)
+
     SET(SHELL "sh")
     SET(prefix "${CMAKE_INSTALL_PREFIX}")
     SET(exec_prefix "${CMAKE_INSTALL_PREFIX}")
     SET(includedir "${prefix}/include")
     SET(libdir "${exec_prefix}/lib")
     SET(CPP "${CMAKE_C_COMPILER}")
-    SET(CC "${CMAKE_C_COMPILER}")
     SET(CPPFLAGS "${CMAKE_C_FLAGS_RELEASE}")
+    SET(CC "${CMAKE_C_COMPILER}")
     SET(CFLAGS "${CMAKE_C_FLAGS_RELEASE}")
     SET(LDFLAGS "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
     LIST2STRING(EXTRA_LINK_LIBS LIBS)
+    
     IF(CXX_FOUND)
       SET(CXX "${CMAKE_CXX_COMPILER}")
       SET(CXX_LNKR "${CMAKE_CXX_COMPILER}")
@@ -964,6 +1275,7 @@ IF(EXAMPLES_ENABLE)
       SET(CXX_LDFLAGS "${CMAKE_CXX_FLAGS_RELEASE}")
       LIST2STRING(EXTRA_LINK_LIBS CXX_LIBS)
     ENDIF(CXX_FOUND)
+
     IF(F77_FOUND)
       SET(F77 "${CMAKE_Fortran_COMPILER}")
       SET(F77_LNKR "${CMAKE_Fortran_COMPILER}")
@@ -971,6 +1283,7 @@ IF(EXAMPLES_ENABLE)
       SET(F77_LDFLAGS "${CMAKE_Fortran_FLAGS_RELEASE}")
       LIST2STRING(EXTRA_LINK_LIBS F77_LIBS)
     ENDIF(F77_FOUND)
+
     IF(F90_FOUND)
       SET(F90 "${CMAKE_Fortran_COMPILER}")
       SET(F90_LNKR "${CMAKE_Fortran_COMPILER}")
@@ -978,17 +1291,25 @@ IF(EXAMPLES_ENABLE)
       SET(F90_LDFLAGS "${CMAKE_Fortran_FLAGS_RELEASE}")
       LIST2STRING(EXTRA_LINK_LIBS F90_LIBS)
     ENDIF(F90_FOUND)
+
     IF(SUPERLUMT_FOUND)
       LIST2STRING(SUPERLUMT_LIBRARIES SUPERLUMT_LIBS)
       SET(SUPERLUMT_LIBS "${SUPERLUMT_LINKER_FLAGS} ${SUPERLUMT_LIBS}")
     ENDIF(SUPERLUMT_FOUND)
+
     IF(KLU_FOUND)
       LIST2STRING(KLU_LIBRARIES KLU_LIBS)
       SET(KLU_LIBS "${KLU_LINKER_FLAGS} ${KLU_LIBS}")
     ENDIF(KLU_FOUND)
+
+    IF(BLAS_FOUND)
+      LIST2STRING(BLAS_LIBRARIES BLAS_LIBS)
+    ENDIF(BLAS_FOUND)
+
     IF(LAPACK_FOUND)
-      LIST2STRING(LAPACK_LIBRARIES BLAS_LAPACK_LIBS)
+      LIST2STRING(LAPACK_LIBRARIES LAPACK_LIBS)
     ENDIF(LAPACK_FOUND)
+
     IF(MPIC_FOUND)
       IF(MPI_MPICC)
         SET(MPICC "${MPI_MPICC}")
@@ -1006,6 +1327,7 @@ IF(EXAMPLES_ENABLE)
       SET(HYPRE_LIB_DIR "${HYPRE_LIBRARY_DIR}")
       SET(HYPRE_LIBS "${HYPRE_LIBRARIES}")
     ENDIF(MPIC_FOUND)
+
     IF(MPICXX_FOUND)
       IF(MPI_MPICXX)
         SET(MPICXX "${MPI_MPICXX}")
@@ -1014,6 +1336,7 @@ IF(EXAMPLES_ENABLE)
         LIST2STRING(MPI_LIBRARIES MPI_LIBS)
       ENDIF(MPI_MPICXX)
     ENDIF(MPICXX_FOUND)
+
     IF(MPIF_FOUND)
       IF(MPI_MPIF77)
         SET(MPIF77 "${MPI_MPIF77}")
@@ -1026,6 +1349,7 @@ IF(EXAMPLES_ENABLE)
         LIST2STRING(MPI_LIBRARIES MPI_LIBS)
       ENDIF(MPI_MPIF77)
     ENDIF(MPIF_FOUND)
+
     IF(MPIF90_FOUND)
       IF(MPI_MPIF90)
         SET(MPIF90 "${MPI_MPIF90}")
@@ -1036,155 +1360,250 @@ IF(EXAMPLES_ENABLE)
         LIST2STRING(MPI_LIBRARIES MPI_LIBS)
       ENDIF(MPI_MPIF90)
     ENDIF(MPIF90_FOUND)
+
   ENDIF(EXAMPLES_INSTALL)
 
+  # add ARKode examples
   IF(BUILD_ARKODE)
-    ADD_SUBDIRECTORY(examples/arkode/C_serial)
-    IF(OPENMP_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/C_openmp)
-    ENDIF(OPENMP_FOUND)
-    IF(CXX_ENABLE AND CXX_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/CXX_serial)
-    ENDIF(CXX_ENABLE AND CXX_FOUND)
-    IF(FCMIX_ENABLE AND F77_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/F77_serial)
-    ENDIF(FCMIX_ENABLE AND F77_FOUND)
-    IF(F90_ENABLE AND F90_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/F90_serial)
-    ENDIF(F90_ENABLE AND F90_FOUND)
-    IF(MPIC_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/C_parallel)
-    ENDIF(MPIC_FOUND)
-    IF(MPICXX_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/CXX_parallel)
-    ENDIF(MPICXX_FOUND)
-    IF(MPIF_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/F77_parallel)
-    ENDIF(MPIF_FOUND)
-    IF(MPIF90_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/F90_parallel)
-    ENDIF(MPIF90_FOUND)
-    IF(HYPRE_ENABLE AND HYPRE_FOUND)
-      ADD_SUBDIRECTORY(examples/arkode/C_parhyp)
-    ENDIF(HYPRE_ENABLE AND HYPRE_FOUND)
-    
+    # C examples
+    IF(EXAMPLES_ENABLE_C)
+      ADD_SUBDIRECTORY(examples/arkode/C_serial)
+      IF(OPENMP_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/C_openmp)
+      ENDIF()
+      IF(MPIC_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/C_parallel)
+      ENDIF()
+      IF(HYPRE_ENABLE AND HYPRE_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/C_parhyp)
+      ENDIF()
+    ENDIF()
+    # C++ examples
+    IF(EXAMPLES_ENABLE_CXX)
+      IF(CXX_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/CXX_serial)
+      ENDIF()
+      IF(MPICXX_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/CXX_parallel)
+      ENDIF()
+    ENDIF()
+    # F77 examples
+    IF(EXAMPLES_ENABLE_F77)
+      IF(F77_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/F77_serial)
+      ENDIF()
+      IF(MPIF_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/F77_parallel)
+      ENDIF()
+    ENDIF()
+    # F90 examples
+    IF(EXAMPLES_ENABLE_F90)
+      IF(F90_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/F90_serial)
+      ENDIF()
+      IF(MPIF90_FOUND)
+        ADD_SUBDIRECTORY(examples/arkode/F90_parallel)
+      ENDIF()
+    ENDIF()   
   ENDIF(BUILD_ARKODE)
-  
+
+  # add CVODE examples
   IF(BUILD_CVODE)
-    ADD_SUBDIRECTORY(examples/cvode/serial)
-    IF(FCMIX_ENABLE AND F77_FOUND)
-      ADD_SUBDIRECTORY(examples/cvode/fcmix_serial)
-    ENDIF(FCMIX_ENABLE AND F77_FOUND)
-    IF(MPIC_FOUND)
-      ADD_SUBDIRECTORY(examples/cvode/parallel)
-    ENDIF(MPIC_FOUND)
-    IF(MPIF_FOUND)
-      ADD_SUBDIRECTORY(examples/cvode/fcmix_parallel)
-    ENDIF(MPIF_FOUND)
-    IF(OPENMP_FOUND)
-      ADD_SUBDIRECTORY(examples/cvode/C_openmp)
-    ENDIF(OPENMP_FOUND)
-    IF(HYPRE_ENABLE AND HYPRE_FOUND)
-      ADD_SUBDIRECTORY(examples/cvode/parhyp)
-    ENDIF(HYPRE_ENABLE AND HYPRE_FOUND)
+    # C examples
+    IF(EXAMPLES_ENABLE_C)
+      ADD_SUBDIRECTORY(examples/cvode/serial)
+      IF(OPENMP_FOUND)
+        ADD_SUBDIRECTORY(examples/cvode/C_openmp)
+      ENDIF()
+      IF(MPIC_FOUND)
+        ADD_SUBDIRECTORY(examples/cvode/parallel)
+      ENDIF()
+      IF(HYPRE_ENABLE AND HYPRE_FOUND)
+        ADD_SUBDIRECTORY(examples/cvode/parhyp)
+      ENDIF()
+    ENDIF()
+    # Fortran examples
+    IF(EXAMPLES_ENABLE_F77)
+      IF(F77_FOUND)
+        ADD_SUBDIRECTORY(examples/cvode/fcmix_serial)
+      ENDIF()
+      IF(MPIF_FOUND)
+        ADD_SUBDIRECTORY(examples/cvode/fcmix_parallel)
+      ENDIF()
+    ENDIF()
+    # cuda examples
+    IF(EXAMPLES_ENABLE_CUDA)
+      IF(CUDA_ENABLE AND CUDA_FOUND)
+        ADD_SUBDIRECTORY(examples/cvode/cuda)
+      ENDIF()
+    ENDIF(EXAMPLES_ENABLE_CUDA)
+    # raja examples 
+    IF(EXAMPLES_ENABLE_RAJA)
+      IF(RAJA_ENABLE AND RAJA_FOUND)
+        ADD_SUBDIRECTORY(examples/cvode/raja)
+      ENDIF()
+    ENDIF(EXAMPLES_ENABLE_RAJA)
   ENDIF(BUILD_CVODE)
-  
-  IF(BUILD_CVODES)	
-    ADD_SUBDIRECTORY(examples/cvodes/serial)
-    IF(MPIC_FOUND)
-      ADD_SUBDIRECTORY(examples/cvodes/parallel)
-    ENDIF(MPIC_FOUND)
-    IF(OPENMP_FOUND)
-      ADD_SUBDIRECTORY(examples/cvodes/C_openmp)
-    ENDIF(OPENMP_FOUND)
+
+  # add CVODES Examples
+  IF(BUILD_CVODES)
+    # C examples
+    IF(EXAMPLES_ENABLE_C)
+      ADD_SUBDIRECTORY(examples/cvodes/serial)
+      IF(MPIC_FOUND)
+        ADD_SUBDIRECTORY(examples/cvodes/parallel)
+      ENDIF()
+      IF(OPENMP_FOUND)
+        ADD_SUBDIRECTORY(examples/cvodes/C_openmp)
+      ENDIF()
+    ENDIF()
   ENDIF(BUILD_CVODES)
-  
+
+  # add IDA examples
   IF(BUILD_IDA)
-    ADD_SUBDIRECTORY(examples/ida/serial)
-    IF(FCMIX_ENABLE AND F77_FOUND)
-      ADD_SUBDIRECTORY(examples/ida/fcmix_serial)
+    # C examples
+    IF(EXAMPLES_ENABLE_C)
+      ADD_SUBDIRECTORY(examples/ida/serial)
+      IF(OPENMP_FOUND)
+        ADD_SUBDIRECTORY(examples/ida/C_openmp)
+      ENDIF()
+      IF(MPIC_FOUND)
+        ADD_SUBDIRECTORY(examples/ida/parallel)
+      ENDIF()
+      IF(PETSC_FOUND)
+        ADD_SUBDIRECTORY(examples/ida/petsc)
+      ENDIF()
+    ENDIF()
+    # Fortran examples
+    IF(EXAMPLES_ENABLE_F77)
+      IF(F77_FOUND)
+        ADD_SUBDIRECTORY(examples/ida/fcmix_serial)
+      ENDIF()
       IF(OPENMP_FOUND)
         ADD_SUBDIRECTORY(examples/ida/fcmix_openmp)
-      ENDIF(OPENMP_FOUND)
+      ENDIF()
       IF(PTHREADS_FOUND)
 	ADD_SUBDIRECTORY(examples/ida/fcmix_pthreads)
-      ENDIF(PTHREADS_FOUND)
-    ENDIF(FCMIX_ENABLE AND F77_FOUND)
-    IF(OPENMP_FOUND)
-      ADD_SUBDIRECTORY(examples/ida/C_openmp)
-    ENDIF(OPENMP_FOUND)
-    IF(MPIC_FOUND)
-      ADD_SUBDIRECTORY(examples/ida/parallel)
-    ENDIF(MPIC_FOUND)
-    IF(PETSC_FOUND)
-      ADD_SUBDIRECTORY(examples/ida/petsc)
-    ENDIF(PETSC_FOUND)
-    IF(MPIF_FOUND)
-      ADD_SUBDIRECTORY(examples/ida/fcmix_parallel)
-    ENDIF(MPIF_FOUND)
+      ENDIF()
+      IF(MPIF_FOUND)
+        ADD_SUBDIRECTORY(examples/ida/fcmix_parallel)
+      ENDIF()
+    ENDIF()
   ENDIF(BUILD_IDA)
-  
-  IF(BUILD_IDAS)	
-    ADD_SUBDIRECTORY(examples/idas/serial)
-    IF(OPENMP_FOUND)
-      ADD_SUBDIRECTORY(examples/idas/C_openmp)
-    ENDIF(OPENMP_FOUND)
-    IF(MPIC_FOUND)
-      ADD_SUBDIRECTORY(examples/idas/parallel)
-    ENDIF(MPIC_FOUND)
+
+  # add IDAS examples
+  IF(BUILD_IDAS)
+    # C examples
+    IF(EXAMPLES_ENABLE_C)
+      ADD_SUBDIRECTORY(examples/idas/serial)
+      IF(OPENMP_FOUND)
+        ADD_SUBDIRECTORY(examples/idas/C_openmp)
+      ENDIF()
+      IF(MPIC_FOUND)
+        ADD_SUBDIRECTORY(examples/idas/parallel)
+      ENDIF()
+    ENDIF()
   ENDIF(BUILD_IDAS)
 
-  IF(BUILD_KINSOL)	
-    ADD_SUBDIRECTORY(examples/kinsol/serial)
-    IF(OPENMP_FOUND)
-      ADD_SUBDIRECTORY(examples/kinsol/C_openmp) # the only example here need special handling from testrunner (not yet implemented)
-    ENDIF(OPENMP_FOUND)
-    IF(FCMIX_ENABLE AND F77_FOUND)
-      ADD_SUBDIRECTORY(examples/kinsol/fcmix_serial)
-    ENDIF(FCMIX_ENABLE AND F77_FOUND)
-    IF(MPIC_FOUND)
-      ADD_SUBDIRECTORY(examples/kinsol/parallel)
-    ENDIF(MPIC_FOUND)
-    IF(MPIF_FOUND)
-      ADD_SUBDIRECTORY(examples/kinsol/fcmix_parallel)
-    ENDIF(MPIF_FOUND)
+  # add KINSOL examples
+  IF(BUILD_KINSOL)
+    # C examples
+    IF(EXAMPLES_ENABLE_C)
+      ADD_SUBDIRECTORY(examples/kinsol/serial)
+      IF(OPENMP_FOUND)
+        # the only example here need special handling from testrunner (not yet implemented)
+        ADD_SUBDIRECTORY(examples/kinsol/C_openmp)
+      ENDIF()
+      IF(MPIC_FOUND)
+        ADD_SUBDIRECTORY(examples/kinsol/parallel)
+      ENDIF()
+    ENDIF()
+    # Fortran examples
+    IF(EXAMPLES_ENABLE_F77)
+      IF(F77_FOUND)
+        ADD_SUBDIRECTORY(examples/kinsol/fcmix_serial)
+      ENDIF()
+      IF(MPIF_FOUND)
+        ADD_SUBDIRECTORY(examples/kinsol/fcmix_parallel)
+      ENDIF()
+    ENDIF()
   ENDIF(BUILD_KINSOL)
 
-  IF(BUILD_CPODES)	
-    ADD_SUBDIRECTORY(examples/cpodes/serial)
-    IF(MPIC_FOUND)
-      ADD_SUBDIRECTORY(examples/cpodes/parallel)
-    ENDIF(MPIC_FOUND)
+  # add CPODES examples
+  IF(BUILD_CPODES)
+    IF(EXAMPLES_ENABLE_C)
+      ADD_SUBDIRECTORY(examples/cpodes/serial)
+      IF(MPIC_FOUND)
+        ADD_SUBDIRECTORY(examples/cpodes/parallel)
+      ENDIF()
+    ENDIF()
   ENDIF(BUILD_CPODES)
 
   # Always add the nvector serial examples
   ADD_SUBDIRECTORY(examples/nvector/serial)
 
+  # # Always add the serial sunmatrix dense/band/sparse examples
+  ADD_SUBDIRECTORY(examples/sunmatrix/dense)
+  ADD_SUBDIRECTORY(examples/sunmatrix/band)
+  ADD_SUBDIRECTORY(examples/sunmatrix/sparse)
+
+  # # Always add the serial sunlinearsolver dense/band/spils examples
+  ADD_SUBDIRECTORY(examples/sunlinsol/band)
+  ADD_SUBDIRECTORY(examples/sunlinsol/dense)
+  IF(KLU_FOUND)
+    ADD_SUBDIRECTORY(examples/sunlinsol/klu)
+  ENDIF(KLU_FOUND)
+  IF(SUPERLUMT_FOUND)
+    ADD_SUBDIRECTORY(examples/sunlinsol/superlumt)
+  ENDIF(SUPERLUMT_FOUND)
+  IF(LAPACK_FOUND)
+    ADD_SUBDIRECTORY(examples/sunlinsol/lapackband)
+    ADD_SUBDIRECTORY(examples/sunlinsol/lapackdense)
+  ENDIF(LAPACK_FOUND)
+  ADD_SUBDIRECTORY(examples/sunlinsol/spgmr/serial)
+  ADD_SUBDIRECTORY(examples/sunlinsol/spfgmr/serial)
+  ADD_SUBDIRECTORY(examples/sunlinsol/spbcgs/serial)
+  ADD_SUBDIRECTORY(examples/sunlinsol/sptfqmr/serial)
+  ADD_SUBDIRECTORY(examples/sunlinsol/pcg/serial)
+
   IF(MPIC_FOUND)
       ADD_SUBDIRECTORY(examples/nvector/parallel)
+      ADD_SUBDIRECTORY(examples/sunlinsol/spgmr/parallel)
+      ADD_SUBDIRECTORY(examples/sunlinsol/spfgmr/parallel)
+      ADD_SUBDIRECTORY(examples/sunlinsol/spbcgs/parallel)
+      ADD_SUBDIRECTORY(examples/sunlinsol/sptfqmr/parallel)
+      #ADD_SUBDIRECTORY(examples/sunlinsol/pcg/parallel)
   ENDIF(MPIC_FOUND)
-  
-  IF(SUNDIALS_HYPRE)
+
+  IF(HYPRE_FOUND)
       ADD_SUBDIRECTORY(examples/nvector/parhyp)
-  ENDIF(SUNDIALS_HYPRE)
+  ENDIF()
 
   IF(PTHREADS_FOUND)
       ADD_SUBDIRECTORY(examples/nvector/pthreads)
-  ENDIF(PTHREADS_FOUND)
+  ENDIF()
 
   IF(OPENMP_FOUND)
       ADD_SUBDIRECTORY(examples/nvector/C_openmp)
-  ENDIF(OPENMP_FOUND)
-  
+  ENDIF()
+
   IF(PETSC_FOUND)
       ADD_SUBDIRECTORY(examples/nvector/petsc)
-  ENDIF(PETSC_FOUND)
+  ENDIF()
+
+  IF(CUDA_FOUND)
+      ADD_SUBDIRECTORY(examples/nvector/cuda)
+  ENDIF(CUDA_FOUND)
+  
+  IF(RAJA_FOUND)
+      ADD_SUBDIRECTORY(examples/nvector/raja)
+  ENDIF(RAJA_FOUND)
   
-ENDIF(EXAMPLES_ENABLE)
+ENDIF(EXAMPLES_ENABLED)
 
-#----------------------------------
-# Install configuration header file
-#----------------------------------
+# ---------------------------------------------------------------
+# Install configuration header files and license file
+# ---------------------------------------------------------------
 
 # install configured header file
 INSTALL(
@@ -1192,3 +1611,13 @@ INSTALL(
   DESTINATION include/sundials
   )
 
+# install configured header file for Fortran 90
+INSTALL(
+  FILES ${PROJECT_BINARY_DIR}/include/sundials/sundials_fconfig.h
+  DESTINATION include/sundials
+  )
+
+# install license file
+INSTALL(
+  FILES ${PROJECT_SOURCE_DIR}/LICENSE
+  DESTINATION .)
\ No newline at end of file
diff --git a/README b/README
index dd71714..89be12e 100644
--- a/README
+++ b/README
@@ -1,7 +1,9 @@
                             SUNDIALS 
     SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
-                   Release 2.6.2, August 2015
-      Alan Hindmarsh, Daniel Reynolds, Radu Serban, Carol Woodward
+
+David Gardner, Alan Hindmarsh, Slaven Peles, Daniel Reynolds, Radu Serban, 
+and Carol Woodward
+
            Center for Applied Scientific Computing, LLNL
 
 The family of solvers referred to as SUNDIALS consists of the following solvers:
@@ -42,6 +44,8 @@ Release history:
 |   Date   |          +----------+----------+----------+----------+---------------------+
 |          | release  |  ARKODE  |   CVODE  | CVODES   |   IDA    |   IDAS   |  KINSOL  |
 +----------+----------+----------+----------+----------+----------+---------------------+
+| Nov 2017 |   3.1.0  |  2.1.0   |  3.1.0   |  3.1.0   |  3.1.0   |  2.1.0   |  3.1.0   |
+| Sep 2017 |   3.0.0  |  2.0.0   |  3.0.0   |  3.0.0   |  3.0.0   |  2.0.0   |  3.0.0   |
 | Sep 2016 |   2.7.0  |  1.1.0   |  2.9.0   |  2.9.0   |  2.9.0   |  1.3.0   |  2.9.0   |
 | Aug 2015 |   2.6.2  |  1.0.2   |  2.8.2   |  2.8.2   |  2.8.2   |  1.2.2   |  2.8.2   |
 | Mar 2015 |   2.6.1  |  1.0.1   |  2.8.1   |  2.8.1   |  2.8.1   |  1.2.1   |  2.8.1   |
diff --git a/config/FindHypre.cmake b/config/FindHypre.cmake
index 3116792..c89fb45 100644
--- a/config/FindHypre.cmake
+++ b/config/FindHypre.cmake
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4713 $
-# $Date: 2016-03-28 07:20:43 -0700 (Mon, 28 Mar 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Slaven Peles @ LLNL, Jean Sexton @ SMU,
 #              Eddy Banks @ LLNL
 # ---------------------------------------------------------------
@@ -18,7 +15,7 @@
 # - Find hypre
 
 #  HYPRE_INCLUDE_DIR = cached location of HYPRE.h
-#  HYPRE_LIBRARY    = cached list of HYPRE library to link in
+#  HYPRE_LIBRARY     = cached list of HYPRE library to link in
 
 ### Find include dir
 find_path(temp_HYPRE_INCLUDE_DIR hypre.h ${HYPRE_INCLUDE_DIR})
diff --git a/config/FindKLU.cmake b/config/FindKLU.cmake
index d80bb6e..5ede7ad 100644
--- a/config/FindKLU.cmake
+++ b/config/FindKLU.cmake
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4957 $
-# $Date: 2016-09-23 12:21:47 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -16,6 +13,7 @@
 # ---------------------------------------------------------------
 # Find KLU library.
 # 
+
 # Set library prefixes for Windows
 IF(WIN32)
   set(CMAKE_FIND_LIBRARY_PREFIXES lib ${CMAKE_FIND_LIBRARY_PREFIXES})
diff --git a/config/FindMPI.cmake b/config/FindMPI.cmake
index f0c5f0c..f2859b1 100644
--- a/config/FindMPI.cmake
+++ b/config/FindMPI.cmake
@@ -1,3 +1,14 @@
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
 # - Find MPI
 # This module looks for MPI (Message Passing Interface) support
 # it will define the following values
diff --git a/config/FindPETSc.cmake b/config/FindPETSc.cmake
index 7c1f736..d013263 100644
--- a/config/FindPETSc.cmake
+++ b/config/FindPETSc.cmake
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision:  $
-# $Date:  $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
diff --git a/config/FindSUPERLUMT.cmake b/config/FindSUPERLUMT.cmake
index 25c4c3f..cb06c2d 100644
--- a/config/FindSUPERLUMT.cmake
+++ b/config/FindSUPERLUMT.cmake
@@ -1,52 +1,54 @@
 # ---------------------------------------------------------------
-# $Revision: 4957 $
-# $Date: 2016-09-23 12:21:47 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Eddy Banks @ LLNL
 # ---------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # ---------------------------------------------------------------
 # SUPERLUMT tests for SUNDIALS CMake-based configuration.
 # 
 
 # make sure valid thread type - if not, then warn and return
 STRING(TOUPPER "${SUPERLUMT_THREAD_TYPE}" SUPERLUMT_THREAD_TYPE_UPPER)
-If(SUPERLUMT_THREAD_TYPE AND NOT SUPERLUMT_THREAD_TYPE_UPPER STREQUAL "OPENMP" AND NOT SUPERLUMT_THREAD_TYPE_UPPER STREQUAL "PTHREAD")
+If(SUPERLUMT_THREAD_TYPE AND
+    NOT SUPERLUMT_THREAD_TYPE_UPPER STREQUAL "OPENMP" AND
+    NOT SUPERLUMT_THREAD_TYPE_UPPER STREQUAL "PTHREAD")
     PRINT_WARNING("Unknown thread type: ${SUPERLUMT_THREAD_TYPE}" "Please enter Pthread or OpenMP")
-ENDIF(SUPERLUMT_THREAD_TYPE AND NOT SUPERLUMT_THREAD_TYPE_UPPER STREQUAL "OPENMP" AND NOT SUPERLUMT_THREAD_TYPE_UPPER STREQUAL "PTHREAD")
+ENDIF()
 
 # find the SUPERLUMT include directory path
 IF(SUPERLUMT_THREAD_TYPE)
-    # if have user input for thread type - set postfix of library name
-    set(POST ${SUPERLUMT_THREAD_TYPE_UPPER})
+  # if have user input for thread type - set postfix of library name
+  set(POST ${SUPERLUMT_THREAD_TYPE_UPPER})
 
-    ### Find include dir
-    find_path(temp_SUPERLUMT_INCLUDE_DIR slu_mt_ddefs.h ${SUPERLUMT_INCLUDE_DIR})
-    if (temp_SUPERLUMT_INCLUDE_DIR)
-        set(SUPERLUMT_INCLUDE_DIR ${temp_SUPERLUMT_INCLUDE_DIR})
-    endif()
-    unset(temp_SUPERLUMT_INCLUDE_DIR CACHE)
-    
-ENDIF(SUPERLUMT_THREAD_TYPE)
+  ### Find include dir
+  find_path(temp_SUPERLUMT_INCLUDE_DIR slu_mt_ddefs.h ${SUPERLUMT_INCLUDE_DIR})
+  if (temp_SUPERLUMT_INCLUDE_DIR)
+    set(SUPERLUMT_INCLUDE_DIR ${temp_SUPERLUMT_INCLUDE_DIR})
+  endif()
+  unset(temp_SUPERLUMT_INCLUDE_DIR CACHE)
+ENDIF()
 
 IF(MSVC)
   SET(CMAKE_FIND_LIBRARY_PREFIXES lib ${CMAKE_FIND_LIBRARY_PREFIXES})
 ENDIF()
 
 if(SUPERLUMT_LIBRARY)
-    get_filename_component(SUPERLUMT_LIBRARY_DIR ${SUPERLUMT_LIBRARY} PATH)
-    set(SUPERLUMT_LIBRARY_DIR ${SUPERLUMT_LIBRARY_DIR} CACHE PATH "" FORCE)
-    
+  get_filename_component(SUPERLUMT_LIBRARY_DIR ${SUPERLUMT_LIBRARY} PATH)
+  set(SUPERLUMT_LIBRARY_DIR ${SUPERLUMT_LIBRARY_DIR} CACHE PATH "" FORCE)
 else()
-    # find library with user provided directory path
-    set(SUPERLUMT_LIBRARY_NAME superlu_mt_${POST})
-    find_library(SUPERLUMT_LIBRARY ${SUPERLUMT_LIBRARY_NAME} ${SUPERLUMT_LIBRARY_DIR} NO_DEFAULT_PATH)
+  # find library with user provided directory path
+  set(SUPERLUMT_LIBRARY_NAME superlu_mt_${POST})
+  find_library(SUPERLUMT_LIBRARY ${SUPERLUMT_LIBRARY_NAME} ${SUPERLUMT_LIBRARY_DIR} NO_DEFAULT_PATH)
 endif()
 mark_as_advanced(SUPERLUMT_LIBRARY)
-    
+
 # add threading library (pthread or openmp)
 If(SUPERLUMT_THREAD_TYPE_UPPER STREQUAL "PTHREAD")
   # add pthread to libraries
@@ -70,16 +72,18 @@ mark_as_advanced(SUPERLUMT_THREAD_LIBRARY)
 set(SUPERLUMT_LIBRARIES ${SUPERLUMT_LIBRARY} ${SUPERLUMT_THREAD_LIBRARY})
 
 # If LAPACK/BLAS not enabled - find BLAS with SUPERLUMT
-if(NOT LAPACK_ENABLE)
-    set(SUPERLUMT_BLAS_LIBRARY_NAME blas_${POST})
-    
-    #unset(SUPERLUMT_BLAS_LIBRARIES CACHE)
-    FIND_LIBRARY(SUPERLUMT_BLAS_LIBRARIES ${SUPERLUMT_BLAS_LIBRARY_NAME} ${SUPERLUMT_LIBRARY_DIR} NO_DEFAULT_PATH)
-    
-    if (NOT SUPERLUMT_BLAS_LIBRARIES)
-      PRINT_WARNING("Can't find SUPERLUMT_BLAS_LIBRARY" "Try setting LAPACK_ENABLE to ON")
-    else ()
-      set(SUPERLUMT_LIBRARIES ${SUPERLUMT_LIBRARIES} ${SUPERLUMT_BLAS_LIBRARIES})
-    endif ()
-    mark_as_advanced(SUPERLUMT_BLAS_LIBRARIES)
-endif(NOT LAPACK_ENABLE)
+if(NOT BLAS_ENABLE AND NOT LAPACK_ENABLE)
+  set(SUPERLUMT_BLAS_LIBRARY_NAME blas_${POST})
+
+  #unset(SUPERLUMT_BLAS_LIBRARIES CACHE)
+  FIND_LIBRARY(SUPERLUMT_BLAS_LIBRARIES ${SUPERLUMT_BLAS_LIBRARY_NAME} ${SUPERLUMT_LIBRARY_DIR} NO_DEFAULT_PATH)
+
+  if (NOT SUPERLUMT_BLAS_LIBRARIES)
+    PRINT_WARNING("Can't find SUPERLUMT_BLAS_LIBRARY, support will not be provided."
+                  "Try setting BLAS_ENABLE or LAPACK_ENABLE to ON")
+    SET(SUPERLUMT_FOUND FALSE)
+  else ()
+    set(SUPERLUMT_LIBRARIES ${SUPERLUMT_LIBRARIES} ${SUPERLUMT_BLAS_LIBRARIES})
+  endif ()
+  mark_as_advanced(SUPERLUMT_BLAS_LIBRARIES)
+endif(NOT BLAS_ENABLE AND NOT LAPACK_ENABLE)
diff --git a/config/SundialsAddTest.cmake b/config/SundialsAddTest.cmake
index 3ce3bf8..49031aa 100644
--- a/config/SundialsAddTest.cmake
+++ b/config/SundialsAddTest.cmake
@@ -12,52 +12,83 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 #
-# SUNDIALS_ADD_TEST(<test name> <executable> )
+# SUNDIALS_ADD_TEST(<test name> <executable>)
 # 
-# Add Sundials regression test.
-
-# Executable is run and output is compared with output in the
-# test/answers directory.  If output differs significantly then test
-# fails.  Default signicance is 4 decimal points for floating values
-# and 10% for integer values.
+# CMake macro to add a Sundials regression test. Keyword input
+# arguments can be added after <executable> to set regression
+# test options (see oneValueArgs and multiValueArgs below).
+#
+# The executable is run and its output compared with the output in the
+# test/answers directory. If the output differs significantly then the
+# test fails. The default signicance is 4 decimal points for floating
+# values and 10% for integer values.
+# ---------------------------------------------------------------
 
-IF(EXAMPLES_ENABLE)
+IF(EXAMPLES_ENABLED)
 
   find_package(PythonInterp)
   IF(${PYTHON_VERSION_MAJOR} LESS 3)
-      IF(${PYTHON_VERSION_MINOR} LESS 7)
-	message( WARNING "***************************************************************************\nWARNING\nPython version must be 2.7.x or greater in order to run regression tests.\nExamples will build but 'make test' will fail.\n***************************************************************************")
-      ENDIF()
+    IF(${PYTHON_VERSION_MINOR} LESS 7)
+      PRINT_WARNING("Python version must be 2.7.x or greater to run regression tests"
+                    "Examples will build but 'make test' will fail.")
+    ENDIF()
   ENDIF()
 
+  # look for the testRunner script in the test directory
   FIND_PROGRAM(TESTRUNNER testRunner PATHS test)
-ENDIF(EXAMPLES_ENABLE)
 
-macro(SUNDIALS_ADD_TEST NAME EXECUTABLE)
+ENDIF(EXAMPLES_ENABLED)
+
+
+MACRO(SUNDIALS_ADD_TEST NAME EXECUTABLE)
+
+  # macro options
+  # NODIFF = do not diff the test output against an answer file
+  SET(options "NODIFF")
+
+  # macro keyword inputs followed by a single value
+  # MPI_NPROCS         = number of mpi tasks to use in parallel tests
+  # FLOAT_PRECISION    = precision for floating point failure comparision (num digits)
+  # INTEGER_PRECENTAGE = integer percentage difference for failure comparison
+  # ANSWER_DIR         = path to the directory containing the test answer file
+  # ANSWER_FILE        = name of test answer file
+  # EXAMPLE_TYPE       = release or develop examples
+  SET(oneValueArgs "MPI_NPROCS" "FLOAT_PRECISION" "INTEGER_PERCENTAGE"
+    "ANSWER_DIR" "ANSWER_FILE" "EXAMPLE_TYPE")
 
-  set(options "")
-  set(oneValueArgs "MPI_NPROCS" "ANSWER_FILE" "FLOAT_PRECISION" "INTEGER_PERCENTAGE")
-  set(multiValueArgs "TEST_ARGS")
+  # macro keyword inputs followed by multiple values
+  # TEST_ARGS = command line arguments to pass to the test executable
+  SET(multiValueArgs "TEST_ARGS")
 
-  CMAKE_PARSE_ARGUMENTS(SUNDIALS_ADD_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+  # parse inputs and create variables SUNDIALS_ADD_TEST_<keyword>
+  CMAKE_PARSE_ARGUMENTS(SUNDIALS_ADD_TEST
+    "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
   # SGS add check to make sure parallel is integer
   # SGS add check for float and integer precision
 
-  set(TEST_ARGS  "-v" "--testname=${NAME}" 
+  # command line arguments for the test runner script
+  SET(TEST_ARGS
+    "--verbose"
+    "--testname=${NAME}" 
     "--executablename=$<TARGET_FILE:${EXECUTABLE}>"
-    "--answersdir=${CMAKE_SOURCE_DIR}/test/answers"
     "--outputdir=${CMAKE_BINARY_DIR}/Testing/output"
     )
 
+  # only check the return value, do not diff the output and answer files
+  IF(NOT ${SUNDIALS_DEVTESTS} OR ${SUNDIALS_ADD_TEST_NODIFF})
+    LIST(APPEND TEST_ARGS "--nodiff")
+  ENDIF()
+
+  # set the number of mpi tasks to use in parallel tests
   IF("${SUNDIALS_ADD_TEST_MPI_NPROCS}" STREQUAL "")
   ELSE()
 
     IF(MPI_ENABLE)
       IF(MPI_RUN_COMMAND MATCHES "srun")
-	set(RUN_COMMAND "srun -N1 -n${SUNDIALS_ADD_TEST_MPI_NPROCS} -ppdebug")
+	SET(RUN_COMMAND "srun -N1 -n${SUNDIALS_ADD_TEST_MPI_NPROCS} -ppdebug")
       ELSE(MPI_RUN_COMMAND MATCHES "srun")
-	set(RUN_COMMAND "mpirun -n ${SUNDIALS_ADD_TEST_MPI_NPROCS}")
+	SET(RUN_COMMAND "${MPI_RUN_COMMAND} -n ${SUNDIALS_ADD_TEST_MPI_NPROCS}")
       ENDIF(MPI_RUN_COMMAND MATCHES "srun")
       
       LIST(APPEND TEST_ARGS "--runcommand=\"${RUN_COMMAND}\"")
@@ -66,28 +97,82 @@ macro(SUNDIALS_ADD_TEST NAME EXECUTABLE)
 
   ENDIF()
   
+  # set the test input args
   IF("${SUNDIALS_ADD_TEST_TEST_ARGS}" STREQUAL "")
   ELSE()
-    string (REPLACE ";" " " USER_ARGS "${SUNDIALS_ADD_TEST_TEST_ARGS}")
+    STRING (REPLACE ";" " " USER_ARGS "${SUNDIALS_ADD_TEST_TEST_ARGS}")
     LIST(APPEND TEST_ARGS "--runargs=\"${USER_ARGS}\"")
   ENDIF()
 
+  # set the test answer directory name (default is test/answers)
+  IF("${SUNDIALS_ADD_TEST_ANSWER_DIR}" STREQUAL "")
+  ELSE()
+    LIST(APPEND TEST_ARGS "--answerdir=${SUNDIALS_ADD_TEST_ANSWER_DIR}")
+  ENDIF()
+
+  # set the test answer file name (default is test_name_test_agrs)
   IF("${SUNDIALS_ADD_TEST_ANSWER_FILE}" STREQUAL "")
   ELSE()
     LIST(APPEND TEST_ARGS "--answerfile=${SUNDIALS_ADD_TEST_ANSWER_FILE}")
   ENDIF()
 
+  # set the precision for floating point failure comparison (number of digits, default 4)
   IF("${SUNDIALS_ADD_TEST_FLOAT_PRECISION}" STREQUAL "")
   ELSE()
     LIST(APPEND TEST_ARGS "--floatprecision=${SUNDIALS_ADD_TEST_FLOAT_PRECISION}")
   ENDIF()
 
+  # set the integer percentage difference for failure comparison (default 10%)
   IF("${SUNDIALS_ADD_TEST_INTEGER_PERCENTAGE}" STREQUAL "")
   ELSE()
     LIST(APPEND TEST_ARGS "--integerpercentage=${SUNDIALS_ADD_TEST_INTEGER_PERCENTAGE}")
   ENDIF()
 
-  ADD_TEST(NAME ${NAME}
-    COMMAND ${PYTHON_EXECUTABLE} ${TESTRUNNER} ${TEST_ARGS})
+  # create test case with the corresponding test runner command and arguments
+  # all tests are added during development and only unlabeled tests when released
+  IF(${SUNDIALS_DEVTESTS} OR "${SUNDIALS_ADD_TEST_EXAMPLE_TYPE}" STREQUAL "")
+    ADD_TEST(NAME ${NAME} COMMAND ${PYTHON_EXECUTABLE} ${TESTRUNNER} ${TEST_ARGS})
+  ENDIF()
+
+ENDMACRO()
+
+
+MACRO(SUNDIALS_ADD_TEST_INSTALL SOLVER EXECUTABLE)
+
+  # macro options
+  SET(options )
+
+  # macro keyword inputs followed by a single value
+  # EXAMPLE_DIR = path to the directory containing the installed example
+  SET(oneValueArgs "EXAMPLE_DIR")
+
+  # macro keyword inputs followed by multiple values
+  SET(multiValueArgs )
+
+  # parse inputs and create variables SUNDIALS_ADD_TEST_<keyword>
+  CMAKE_PARSE_ARGUMENTS(SUNDIALS_ADD_TEST_INSTALL
+    "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  # create testing directory for this solver
+  FILE(MAKE_DIRECTORY ${TEST_INSTALL_DIR}/${SOLVER})
+
+  # command line arguments for the test runner script
+  set(TEST_ARGS
+    "--testname=${EXECUTABLE}" 
+    "--executablename=./${EXECUTABLE}"
+    "--outputdir=${TEST_INSTALL_DIR}/${SOLVER}"
+    "--builddir=${SUNDIALS_ADD_TEST_INSTALL_EXAMPLE_DIR}"
+    "--buildcmd=${CMAKE_COMMAND}"
+    "--nodiff"
+    )
+  
+  # add test_install target for this solver
+  ADD_CUSTOM_TARGET(${SOLVER}_test_install
+    COMMAND ${PYTHON_EXECUTABLE} ${TESTRUNNER} ${TEST_ARGS}
+    COMMENT "Running ${SOLVER} installation tests"
+    WORKING_DIRECTORY ${TEST_INSTALL_DIR}/${SOLVER})
+
+  # make test_install depend on solver_test_install
+  ADD_DEPENDENCIES(test_install ${SOLVER}_test_install)
 
-endmacro()
+ENDMACRO()
\ No newline at end of file
diff --git a/config/SundialsBlas.cmake b/config/SundialsBlas.cmake
new file mode 100644
index 0000000..f738866
--- /dev/null
+++ b/config/SundialsBlas.cmake
@@ -0,0 +1,101 @@
+# ---------------------------------------------------------------
+# Programmer:  David J. Gardner @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# BLAS tests for SUNDIALS CMake-based configuration. Based on 
+# SundialsLapack.cmake
+#
+
+SET(BLAS_FOUND FALSE)
+
+# If BLAS libraries are undefined, try to find them (if we have
+# a working Fortran compiler) or look for them in the most
+# obvious place...
+if(NOT BLAS_LIBRARIES)
+  if(F77_FOUND)
+    include(FindBLAS)
+  else(F77_FOUND)
+    find_library(BLAS_LIBRARIES
+      NAMES blas
+      PATHS /usr/lib /usr/local/lib
+      "$ENV{ProgramFiles}/BLAS/Lib"
+      )
+  endif(F77_FOUND)
+
+  # If the xSDK flag is used, set it to what was found
+  if(BLAS_LIBRARIES AND TPL_ENABLE_BLAS)
+    SET(DOCSTR "Blas library")
+    FORCE_VARIABLE(TPL_BLAS_LIBRARIES STRING "${DOCSTR}" "${BLAS_LIBRARIES}")
+  endif()
+endif()
+
+# If we have the BLAS libraries, test them
+if(BLAS_LIBRARIES)
+  message(STATUS "Looking for BLAS libraries... OK")
+
+  # Create the BlasTest directory
+  set(BlasTest_DIR ${PROJECT_BINARY_DIR}/BlasTest)
+  file(MAKE_DIRECTORY ${BlasTest_DIR})
+
+  # Create a CMakeLists.txt file 
+  file(WRITE ${BlasTest_DIR}/CMakeLists.txt
+    "CMAKE_MINIMUM_REQUIRED(VERSION 2.4)\n"
+    "PROJECT(ltest C)\n"
+    "SET(CMAKE_VERBOSE_MAKEFILE ON)\n"
+    "SET(CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\")\n"
+    "SET(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS}\")\n"
+    "SET(CMAKE_C_FLAGS_RELEASE \"${CMAKE_C_FLAGS_RELEASE}\")\n"
+    "SET(CMAKE_C_FLAGS_DEBUG \"${CMAKE_C_FLAGS_DEBUG}\")\n"
+    "SET(CMAKE_C_FLAGS_RELWITHDEBUGINFO \"${CMAKE_C_FLAGS_RELWITHDEBUGINFO}\")\n"
+    "SET(CMAKE_C_FLAGS_MINSIZE \"${CMAKE_C_FLAGS_MINSIZE}\")\n"
+    "ADD_EXECUTABLE(ltest ltest.c)\n"
+    "TARGET_LINK_LIBRARIES(ltest ${BLAS_LIBRARIES})\n")
+
+  # Create a C source file which calls a Blas function (dcopy)
+  file(WRITE ${BlasTest_DIR}/ltest.c
+    "${F77_MANGLE_MACRO1}\n"
+    "#define dcopy_f77 SUNDIALS_F77_FUNC(dcopy, DCOPY)\n"
+    "extern void dcopy_f77(int *n, const double *x, const int *inc_x, double *y, const int *inc_y);\n"
+    "int main(){\n"
+    "int n=1;\n"
+    "double x, y;\n"
+    "dcopy_f77(&n, &x, &n, &y, &n);\n"
+    "return(0);\n"
+    "}\n")
+
+  # Attempt to link the "ltest" executable
+  try_compile(LTEST_OK ${BlasTest_DIR} ${BlasTest_DIR}
+    ltest OUTPUT_VARIABLE MY_OUTPUT)
+
+  # To ensure we do not use stuff from the previous attempts, 
+  # we must remove the CMakeFiles directory.
+  file(REMOVE_RECURSE ${BlasTest_DIR}/CMakeFiles)
+
+  # Process test result
+  if(LTEST_OK)
+    message(STATUS "Checking if BLAS works... OK")
+    set(BLAS_FOUND TRUE)
+
+    # get path to BLAS library to use in generated makefiles for examples
+    # check length to protect against BLAS_LIBRARIES having multiple entries
+    list(LENGTH BLAS_LIBRARIES len)
+    if(len EQUAL 1)
+      get_filename_component(BLAS_LIBRARY_DIR ${BLAS_LIBRARIES} PATH)
+    endif()
+
+  else(LTEST_OK)
+    message(STATUS "Checking if BLAS works... FAILED")
+  endif(LTEST_OK)
+
+else(BLAS_LIBRARIES)
+  message(STATUS "Looking for BLAS libraries... FAILED")
+endif(BLAS_LIBRARIES)
diff --git a/config/SundialsCMakeMacros.cmake b/config/SundialsCMakeMacros.cmake
new file mode 100644
index 0000000..85659d9
--- /dev/null
+++ b/config/SundialsCMakeMacros.cmake
@@ -0,0 +1,118 @@
+# ---------------------------------------------------------------
+# Programmer: David J. Gardner @ LLNL
+#             Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# CMake macros used throughout the SUNDIALS build system
+# ---------------------------------------------------------------
+
+# Print variable and value
+IF (NOT COMMAND PRINT_VARIABLE)
+  FUNCTION(PRINT_VARIABLE var)
+    MESSAGE("${var} = '${${var}}'")
+  ENDFUNCTION()
+ENDIF()
+
+# Macros to hide/show cached variables.
+# These two macros can be used to "hide" or "show" in the
+# list of cached variables various variables and/or options 
+# that depend on other options.
+# Note that once a variable is modified, it will preserve its
+# value (hidding it merely makes it internal)
+
+# hide variable (set as internal), retain its value, and
+# leave the documentation string empty
+MACRO(HIDE_VARIABLE var)
+  IF(DEFINED ${var})
+    SET(${var} "${${var}}" CACHE INTERNAL "")
+  ENDIF(DEFINED ${var})
+ENDMACRO(HIDE_VARIABLE)
+
+# show variable (set as cache)
+MACRO(SHOW_VARIABLE var type doc default)
+  IF(DEFINED ${var})
+    # ignores <default> and forces <var> to its current value
+    SET(${var} "${${var}}" CACHE "${type}" "${doc}" FORCE)
+  ELSE(DEFINED ${var})
+    # set to <var> to the <default> value
+    SET(${var} "${default}" CACHE "${type}" "${doc}")
+  ENDIF(DEFINED ${var})
+ENDMACRO(SHOW_VARIABLE)
+
+# show variable (set as cache) and overwrite (force) its value
+MACRO(FORCE_VARIABLE var type doc val)
+  SET(${var} "${val}" CACHE "${type}" "${doc}" FORCE)
+ENDMACRO(FORCE_VARIABLE)
+
+# Macros to append a common suffix or prefix to the elements of a list
+
+MACRO(ADD_SUFFIX rootlist suffix)
+  SET(outlist )
+  FOREACH(root ${${rootlist}})
+    LIST(APPEND outlist ${root}${suffix})
+  ENDFOREACH(root)
+  SET(${rootlist} ${outlist})
+ENDMACRO(ADD_SUFFIX)
+
+MACRO(ADD_PREFIX prefix rootlist)
+  SET(outlist )
+  FOREACH(root ${${rootlist}})
+    LIST(APPEND outlist ${prefix}${root})
+  ENDFOREACH(root)
+  SET(${rootlist} ${outlist})
+ENDMACRO(ADD_PREFIX)
+
+# Macro to print warning that some features will be disabled
+# due to some failure.
+
+MACRO(PRINT_WARNING message action)
+  SET(MSG
+  "------------------------------------------------------------\n"
+  "WARNING: ${message}\n"
+  "${action}\n"
+  "------------------------------------------------------------")
+  MESSAGE(WARNING ${MSG})
+ENDMACRO()
+
+# Macro to print fatal error messages. Fatal errors will NOT allow
+# a makefile to be generated
+
+MACRO(PRINT_ERROR message)
+  SET(MSG
+  "************************************************************\n"
+  "ERROR: ${message}\n"
+  "************************************************************")
+  MESSAGE(FATAL_ERROR ${MSG})
+ENDMACRO()
+
+# Returns an unquoted string. Note that CMake will readily turn such
+# strings back into lists, due to the duality of lists and
+# semicolon-separated strings. So be careful how you use it.
+
+MACRO(LIST2STRING alist astring)
+  FOREACH(elem ${${alist}})
+   SET(${astring} "${${astring}} ${elem}")
+  ENDFOREACH(elem)
+ENDMACRO(LIST2STRING)
+
+# Returns a string of unique example names from a list of example tuples
+
+MACRO(EXAMPLES2STRING example_list example_string)
+  SET(tmp_list "")
+  FOREACH(example_tuple ${${example_list}})
+    LIST(GET example_tuple 0 example)
+    LIST(APPEND tmp_list ${example})
+  ENDFOREACH()
+  LIST(REMOVE_DUPLICATES tmp_list)
+  LIST2STRING(tmp_list ${example_string})
+ENDMACRO(EXAMPLES2STRING)
+
diff --git a/config/SundialsCXX.cmake b/config/SundialsCXX.cmake
index 14a757a..02de351 100644
--- a/config/SundialsCXX.cmake
+++ b/config/SundialsCXX.cmake
@@ -1,9 +1,19 @@
 # ---------------------------------------------------------------
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
-# Copyright (c) 2013, Southern Methodist University.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # C++-related tests for SUNDIALS CMake-based configuration.
 
@@ -13,18 +23,44 @@ include(CMakeDetermineCXXCompiler)
 
 if(CMAKE_CXX_COMPILER)
   message(STATUS "Searching for a C++ compiler... ${CMAKE_CXX_COMPILER}")
+
   # Enable the language for next steps
   enable_language(CXX)
-  mark_as_advanced(CLEAR 
+
+  # show some cache variables
+  MARK_AS_ADVANCED(CLEAR
     CMAKE_CXX_COMPILER
-    CMAKE_CXX_FLAGS
+    CMAKE_CXX_FLAGS)
+
+  # hide all build type specific flags
+  MARK_AS_ADVANCED(FORCE
     CMAKE_CXX_FLAGS_DEBUG
     CMAKE_CXX_FLAGS_MINSIZEREL
     CMAKE_CXX_FLAGS_RELEASE
-    CMAKE_CXX_FLAGS_RELWITHDEB)
+    CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+
+  # only show flags for the current build type
+  # these flags are appended to CMAKE_CXX_FLAGS
+  IF(CMAKE_BUILD_TYPE)
+    IF(CMAKE_BUILD_TYPE MATCHES "Debug")
+      MESSAGE("Appending CXX debug flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_CXX_FLAGS_DEBUG)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
+      MESSAGE("Appending CXX min size release flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_CXX_FLAGS_MINSIZEREL)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "Release")
+      MESSAGE("Appending CXX release flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_CXX_FLAGS_RELEASE)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
+      MESSAGE("Appending CXX release with debug info flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+    ENDIF()
+  ENDIF()
+
   # Create the CXXTest directory
   set(CXXTest_DIR ${PROJECT_BINARY_DIR}/CXXTest)
   file(MAKE_DIRECTORY ${CXXTest_DIR})
+
   # Create a CMakeLists.txt file which will generate the executable "cxxtest"
   file(WRITE ${CXXTest_DIR}/CMakeLists.txt
     "CMAKE_MINIMUM_REQUIRED(VERSION 2.4)\n"
@@ -37,6 +73,7 @@ if(CMAKE_CXX_COMPILER)
     "SET(CMAKE_CXX_FLAGS_RELWITHDEBUGINFO \"${CMAKE_CXX_FLAGS_RELWITHDEBUGINFO}\")\n"
     "SET(CMAKE_CXX_FLAGS_MINSIZE \"${CMAKE_CXX_FLAGS_MINSIZE}\")\n"
     "ADD_EXECUTABLE(cxxtest cxxtest.cpp)\n")
+
   # Create the C++ source cxxtest.cpp which does some simple calls
   file(WRITE ${CXXTest_DIR}/cxxtest.cpp
     "#include <string>\n"
@@ -44,17 +81,21 @@ if(CMAKE_CXX_COMPILER)
     "std::string c;\n"
     "return(0);\n"
     "}\n")
+
   # Use TRY_COMPILE to make the target "cxxtest"
   try_compile(CXXTEST_OK ${CXXTest_DIR} ${CXXTest_DIR}
     ftest OUTPUT_VARIABLE MY_OUTPUT)
+
   # To ensure we do not use stuff from the previous attempts, 
   # we must remove the CMakeFiles directory.
   file(REMOVE_RECURSE ${CXXTest_DIR}/CMakeFiles)
+
   # Proceed based on test results
   if(CXXTEST_OK)
     message(STATUS "Trying to compile and link a simple C++ program... OK")
     set(CXX_FOUND TRUE)
   endif(CXXTEST_OK)
+
 else(CMAKE_CXX_COMPILER)
   message(STATUS "Searching for a C++ compiler... FAILED")
 endif(CMAKE_CXX_COMPILER)
diff --git a/config/SundialsDeprecated.cmake b/config/SundialsDeprecated.cmake
new file mode 100644
index 0000000..e9ab206
--- /dev/null
+++ b/config/SundialsDeprecated.cmake
@@ -0,0 +1,40 @@
+# ---------------------------------------------------------------
+# Programmer:  David J. Gardner @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# Print warning is the user sets a deprecated CMake variable and
+# copy the value into the correct CMake variable
+# ---------------------------------------------------------------
+
+# macro to print warning for deprecated CMake variable
+MACRO(PRINT_DEPRECATED old_variable new_variable)
+  PRINT_WARNING("${old_variable} is deprecated and will be removed in the future."
+                "Copying value to ${new_variable}.")
+ENDMACRO()
+
+IF(DEFINED EXAMPLES_ENABLE)
+  PRINT_DEPRECATED(EXAMPLES_ENABLE EXAMPLES_ENABLE_C)
+  FORCE_VARIABLE(EXAMPLES_ENABLE_C BOOL "Build SUNDIALS C examples" ${EXAMPLES_ENABLE})
+  UNSET(EXAMPLES_ENABLE)
+ENDIF()
+
+IF(DEFINED CXX_ENABLE)
+  PRINT_DEPRECATED(CXX_ENABLE EXAMPLES_ENABLE_CXX)
+  FORCE_VARIABLE(EXAMPLES_ENABLE_CXX BOOL "Build ARKode C++ examples" ${CXX_ENABLE})
+  UNSET(CXX_ENABLE)
+ENDIF()
+
+IF(DEFINED F90_ENABLE)
+  PRINT_DEPRECATED(F90_ENABLE EXAMPLES_ENABLE_F90)
+  FORCE_VARIABLE(EXAMPLES_ENABLE_F90 BOOL "Build ARKode Fortran90 examples" ${F90_ENABLE})
+  UNSET(F90_ENABLE)
+ENDIF()
diff --git a/config/SundialsFortran.cmake b/config/SundialsFortran.cmake
index 4fe16e7..2360eaf 100644
--- a/config/SundialsFortran.cmake
+++ b/config/SundialsFortran.cmake
@@ -1,13 +1,15 @@
 # ---------------------------------------------------------------
-# $Revision: 4511 $
-# $Date: 2015-06-29 16:48:09 -0700 (Mon, 29 Jun 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Copyright (c) 2008, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # ---------------------------------------------------------------
 # Fortran-related tests for SUNDIALS CMake-based configuration.
 #
@@ -36,18 +38,61 @@ include(CMakeDetermineFortranCompiler)
 
 if(CMAKE_Fortran_COMPILER)
   message(STATUS "Searching for a Fortran compiler... ${CMAKE_Fortran_COMPILER}")
+
+  # If Fortran compiler flags are set using environemnt variables and both FFLAGS
+  # and FCFLAGS are used, then check if the variables are the same. If they are
+  # not the same then a fatal error occurs.
+  # 
+  # NOTE: This check must occur before 'enable_language(Fortran)' as it will use
+  # the value of FFLAGS to set CMAKE_Fortran_FLAGS
+  SET(ENV_FFLAGS "$ENV{FFLAGS}")
+  SET(ENV_FCFLAGS "$ENV{FCFLAGS}")
+  IF ((NOT "${ENV_FFLAGS}" STREQUAL "") AND
+      (NOT "${ENV_FCFLAGS}" STREQUAL "") AND
+      ("${CMAKE_Fortran_FLAGS}" STREQUAL ""))
+    # check if environment variables are equal
+    IF (NOT "${ENV_FFLAGS}" STREQUAL "${ENV_FCFLAGS}")
+      PRINT_ERROR("FFLAGS='${ENV_FFLAGS}' and FCFLAGS='${ENV_FCFLAGS}' are both set but are not equal.")
+    ENDIF()
+  ENDIF()
+
   # Enable the language for next steps
   enable_language(Fortran)
-  mark_as_advanced(CLEAR 
+
+  # show some cache variables
+  MARK_AS_ADVANCED(CLEAR
     CMAKE_Fortran_COMPILER
-    CMAKE_Fortran_FLAGS
+    CMAKE_Fortran_FLAGS)
+
+  # hide all build type specific flags
+  MARK_AS_ADVANCED(FORCE
     CMAKE_Fortran_FLAGS_DEBUG
     CMAKE_Fortran_FLAGS_MINSIZEREL
     CMAKE_Fortran_FLAGS_RELEASE
-    CMAKE_Fortran_FLAGS_RELWITHDEB)
+    CMAKE_Fortran_FLAGS_RELWITHDEBINFO)
+
+  # only show flags for the current build type
+  # these flags are appended to CMAKE_Fortran_FLAGS
+  IF(CMAKE_BUILD_TYPE)
+    IF(CMAKE_BUILD_TYPE MATCHES "Debug")
+      MESSAGE("Appending Fortran debug flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_DEBUG)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
+      MESSAGE("Appending Fortran min size release flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_MINSIZEREL)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "Release")
+      MESSAGE("Appending Fortran release flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_RELEASE)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
+      MESSAGE("Appending Fortran release with debug info flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_RELWITHDEBINFO)
+    ENDIF()
+  ENDIF()
+
   # Create the FortranTest directory
   set(FortranTest_DIR ${PROJECT_BINARY_DIR}/FortranTest)
   file(MAKE_DIRECTORY ${FortranTest_DIR})
+
   # Create a CMakeLists.txt file which will generate the "flib" library
   # and an executable "ftest"
   file(WRITE ${FortranTest_DIR}/CMakeLists.txt
@@ -63,6 +108,7 @@ if(CMAKE_Fortran_COMPILER)
     "ADD_LIBRARY(flib flib.f)\n"
     "ADD_EXECUTABLE(ftest ftest.f)\n"
     "TARGET_LINK_LIBRARIES(ftest flib)\n")
+
   # Create the Fortran source flib.f which defines two subroutines, "mysub" and "my_sub"
   file(WRITE ${FortranTest_DIR}/flib.f
     "        SUBROUTINE mysub\n"
@@ -71,22 +117,27 @@ if(CMAKE_Fortran_COMPILER)
     "        SUBROUTINE my_sub\n"
     "        RETURN\n"
     "        END\n")
+
   # Create the Fortran source ftest.f which calls "mysub" and "my_sub"
   file(WRITE ${FortranTest_DIR}/ftest.f
     "        PROGRAM ftest\n"
     "        CALL mysub()\n"
     "        CALL my_sub()\n"
     "        END\n")
+
   # Use TRY_COMPILE to make the targets "flib" and "ftest"
   try_compile(FTEST_OK ${FortranTest_DIR} ${FortranTest_DIR}
     ftest OUTPUT_VARIABLE MY_OUTPUT)
+
   # To ensure we do not use stuff from the previous attempts, 
   # we must remove the CMakeFiles directory.
   file(REMOVE_RECURSE ${FortranTest_DIR}/CMakeFiles)
+
   # Proceed based on test results
   if(FTEST_OK)
     message(STATUS "Trying to compile and link a simple Fortran program... OK")
     set(F77_FOUND TRUE)
+
     # Infer Fortran name-mangling scheme for symbols WITHOUT underscores.
     # Overwrite CMakeLists.txt with one which will generate the "ctest1" executable
     file(WRITE ${FortranTest_DIR}/CMakeLists.txt
@@ -102,11 +153,13 @@ if(CMAKE_Fortran_COMPILER)
       "ADD_EXECUTABLE(ctest1 ctest1.c)\n"
       "FIND_LIBRARY(FLIB flib ${FortranTest_DIR})\n"
       "TARGET_LINK_LIBRARIES(ctest1 \${FLIB})\n")
+
     # Define the list "options" of all possible schemes that we want to consider
     # Get its length and initialize the counter "iopt" to zero
     set(options mysub mysub_ mysub__ MYSUB MYSUB_ MYSUB__)
     list(LENGTH options imax)
     set(iopt 0)
+
     # We will attempt to sucessfully generate the "ctest1" executable as long as
     # there still are entries in the "options" list
     while(${iopt} LESS ${imax})   
@@ -132,6 +185,7 @@ if(CMAKE_Fortran_COMPILER)
         math(EXPR iopt ${iopt}+1)
       endif(CTEST_OK)
     endwhile(${iopt} LESS ${imax})   
+
     # Infer Fortran name-mangling scheme for symbols WITH underscores.
     # Practically a duplicate of the previous steps.
     file(WRITE ${FortranTest_DIR}/CMakeLists.txt
@@ -147,6 +201,7 @@ if(CMAKE_Fortran_COMPILER)
       "ADD_EXECUTABLE(ctest2 ctest2.c)\n"
       "FIND_LIBRARY(FLIB flib ${FortranTest_DIR})\n"
       "TARGET_LINK_LIBRARIES(ctest2 \${FLIB})\n")
+
     set(options my_sub my_sub_ my_sub__ MY_SUB MY_SUB_ MY_SUB__)
     list(LENGTH options imax)
     set(iopt 0)
@@ -163,6 +218,7 @@ if(CMAKE_Fortran_COMPILER)
         math(EXPR iopt ${iopt}+1)
       endif(CTEST_OK)
     endwhile(${iopt} LESS ${imax})   
+
     # Proceed based on whether the previous tests were successfull or not
     if(CMAKE_Fortran_SCHEME_NO_UNDERSCORES AND CMAKE_Fortran_SCHEME_WITH_UNDERSCORES)
       message(STATUS "Determining Fortran name-mangling scheme... OK")
@@ -170,9 +226,11 @@ if(CMAKE_Fortran_COMPILER)
     else(CMAKE_Fortran_SCHEME_NO_UNDERSCORES AND CMAKE_Fortran_SCHEME_WITH_UNDERSCORES)
       message(STATUS "Determining Fortran name-mangling scheme... FAILED")
     endif(CMAKE_Fortran_SCHEME_NO_UNDERSCORES AND CMAKE_Fortran_SCHEME_WITH_UNDERSCORES)
+    
   else(FTEST_OK)
     message(STATUS "Trying to compile and link a simple Fortran program... FAILED")
   endif(FTEST_OK)
+
 else(CMAKE_Fortran_COMPILER)
   message(STATUS "Searching for a Fortran compiler... FAILED")
 endif(CMAKE_Fortran_COMPILER)
diff --git a/config/SundialsFortran90.cmake b/config/SundialsFortran90.cmake
index efc9fe1..be796ff 100644
--- a/config/SundialsFortran90.cmake
+++ b/config/SundialsFortran90.cmake
@@ -1,9 +1,19 @@
 # ---------------------------------------------------------------
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
-# Copyright (c) 2013, Southern Methodist University.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # Fortran90-related tests for SUNDIALS CMake-based configuration.
 
@@ -12,18 +22,61 @@ include(CMakeDetermineFortranCompiler)
 
 if(CMAKE_Fortran_COMPILER)
   message(STATUS "Searching for a Fortran compiler... ${CMAKE_Fortran_COMPILER}")
+
+  # If Fortran compiler flags are set using environemnt variables and both FFLAGS
+  # and FCFLAGS are used, then check if the variables are the same. If they are
+  # not the same then a fatal error occurs.
+  # 
+  # NOTE: This check must occur before 'enable_language(Fortran)' as it will use
+  # the value of FFLAGS to set CMAKE_Fortran_FLAGS
+  SET(ENV_FFLAGS "$ENV{FFLAGS}")
+  SET(ENV_FCFLAGS "$ENV{FCFLAGS}")
+  IF ((NOT "${ENV_FFLAGS}" STREQUAL "") AND
+      (NOT "${ENV_FCFLAGS}" STREQUAL "") AND
+      ("${CMAKE_Fortran_FLAGS}" STREQUAL ""))
+    # check if environment variables are equal
+    IF (NOT "${ENV_FFLAGS}" STREQUAL "${ENV_FCFLAGS}")
+      PRINT_ERROR("FFLAGS='${ENV_FFLAGS}' and FCFLAGS='${ENV_FCFLAGS}' are both set but are not equal.")
+    ENDIF()
+  ENDIF()
+
   # Enable the language for next steps
   enable_language(Fortran)
-  mark_as_advanced(CLEAR 
+
+  # show some cache variables
+  MARK_AS_ADVANCED(CLEAR
     CMAKE_Fortran_COMPILER
-    CMAKE_Fortran_FLAGS
+    CMAKE_Fortran_FLAGS)
+
+  # hide all build type specific flags
+  MARK_AS_ADVANCED(FORCE
     CMAKE_Fortran_FLAGS_DEBUG
     CMAKE_Fortran_FLAGS_MINSIZEREL
     CMAKE_Fortran_FLAGS_RELEASE
-    CMAKE_Fortran_FLAGS_RELWITHDEB)
+    CMAKE_Fortran_FLAGS_RELWITHDEBINFO)
+
+  # only show flags for the current build type
+  # these flags are appended to CMAKE_Fortran_FLAGS
+  IF(CMAKE_BUILD_TYPE)       
+    IF(CMAKE_BUILD_TYPE MATCHES "Debug")
+      MESSAGE("Appending Fortran debug flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_DEBUG)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
+      MESSAGE("Appending Fortran min size release flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_MINSIZEREL)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "Release")
+      MESSAGE("Appending Fortran release flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_RELEASE)
+    ELSEIF(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
+      MESSAGE("Appending Fortran release with debug info flags")
+      MARK_AS_ADVANCED(CLEAR CMAKE_Fortran_FLAGS_RELWITHDEBINFO)
+    ENDIF()
+  ENDIF()
+
   # Create the Fortran90Test directory
   set(Fortran90Test_DIR ${PROJECT_BINARY_DIR}/Fortran90Test)
   file(MAKE_DIRECTORY ${Fortran90Test_DIR})
+
   # Create a CMakeLists.txt file which will generate the "f90lib" library
   # and an executable "f90test"
   file(WRITE ${Fortran90Test_DIR}/CMakeLists.txt
@@ -39,6 +92,7 @@ if(CMAKE_Fortran_COMPILER)
     "ADD_LIBRARY(f90lib f90lib.f90)\n"
     "ADD_EXECUTABLE(f90test f90test.f90)\n"
     "TARGET_LINK_LIBRARIES(f90test f90lib)\n")
+
   # Create the Fortran source f90lib.f90 which defines two subroutines, "mysub" and "my_sub"
   file(WRITE ${Fortran90Test_DIR}/f90lib.f90
     "subroutine mysub\n"
@@ -47,18 +101,22 @@ if(CMAKE_Fortran_COMPILER)
     "subroutine my_sub\n"
     "  return\n"
     "end\n")
+
   # Create the Fortran source f90test.f90 which calls "mysub" and "my_sub"
   file(WRITE ${Fortran90Test_DIR}/f90test.f90
     "program f90test\n"
     "  call mysub()\n"
     "  call my_sub()\n"
     "end\n")
+
   # Use TRY_COMPILE to make the targets "f90lib" and "f90test"
   try_compile(F90TEST_OK ${Fortran90Test_DIR} ${Fortran90Test_DIR}
     f90test OUTPUT_VARIABLE MY_OUTPUT)
+
   # To ensure we do not use stuff from the previous attempts, 
   # we must remove the CMakeFiles directory.
   file(REMOVE_RECURSE ${Fortran90Test_DIR}/CMakeFiles)
+
   # Proceed based on test results
   if(F90TEST_OK)
     message(STATUS "Trying to compile and link a simple Fortran90 program... OK")
@@ -66,6 +124,7 @@ if(CMAKE_Fortran_COMPILER)
   else(F90TEST_OK)
     message(STATUS "Trying to compile and link a simple Fortran90 program... FAILED")
   endif(F90TEST_OK)
+
 else(CMAKE_Fortran_COMPILER)
   message(STATUS "Searching for a Fortran compiler... FAILED")
 endif(CMAKE_Fortran_COMPILER)
diff --git a/config/SundialsHypre.cmake b/config/SundialsHypre.cmake
index a065c6d..d175a56 100644
--- a/config/SundialsHypre.cmake
+++ b/config/SundialsHypre.cmake
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4713 $
-# $Date: 2016-03-28 07:20:43 -0700 (Mon, 28 Mar 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Slaven Peles @ LLNL, Jean Sexton @ SMU
 #              Eddy Banks @ LLNL
 # ---------------------------------------------------------------
@@ -17,6 +14,7 @@
 # ---------------------------------------------------------------
 # Hypre tests for SUNDIALS CMake-based configuration.
 # 
+
 ### This is only set if running GUI - simply return first time enabled
 IF(HYPRE_DISABLED)
   SET(HYPRE_DISABLED FALSE CACHE INTERNAL "GUI - now enabled" FORCE)
diff --git a/config/SundialsKLU.cmake b/config/SundialsKLU.cmake
index 9118314..d865ff1 100644
--- a/config/SundialsKLU.cmake
+++ b/config/SundialsKLU.cmake
@@ -1,13 +1,15 @@
 # ---------------------------------------------------------------
-# $Revision: 4955 $
-# $Date: 2016-09-23 10:01:28 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # ---------------------------------------------------------------
 # KLU tests for SUNDIALS CMake-based configuration.
 #    - loosely based on SundialsLapack.cmake
diff --git a/config/SundialsLapack.cmake b/config/SundialsLapack.cmake
index aa2f60d..5c75ec5 100644
--- a/config/SundialsLapack.cmake
+++ b/config/SundialsLapack.cmake
@@ -1,17 +1,17 @@
 # ---------------------------------------------------------------
-# $Revision: 4511 $
-# $Date: 2015-06-29 16:48:09 -0700 (Mon, 29 Jun 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Copyright (c) 2008, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # ---------------------------------------------------------------
 # BLAS/LAPACK tests for SUNDIALS CMake-based configuration.
-#
-# 
 
 SET(LAPACK_FOUND FALSE)
 
@@ -28,14 +28,22 @@ if(NOT LAPACK_LIBRARIES)
       "$ENV{ProgramFiles}/LAPACK/Lib"
       )
   endif(F77_FOUND)
-endif(NOT LAPACK_LIBRARIES)
+
+  # If the xSDK flag is used, set it to what was found
+  if(LAPACK_LIBRARIES AND TPL_ENABLE_LAPACK)
+    SET(DOCSTR "Lapack library")
+    FORCE_VARIABLE(TPL_LAPACK_LIBRARIES STRING "${DOCSTR}" "${LAPACK_LIBRARIES}")
+  endif()
+endif()
 
 # If we have the LAPACK libraries, test them
 if(LAPACK_LIBRARIES)
   message(STATUS "Looking for LAPACK libraries... OK")
+
   # Create the LapackTest directory
   set(LapackTest_DIR ${PROJECT_BINARY_DIR}/LapackTest)
   file(MAKE_DIRECTORY ${LapackTest_DIR})
+
   # Create a CMakeLists.txt file 
   file(WRITE ${LapackTest_DIR}/CMakeLists.txt
     "CMAKE_MINIMUM_REQUIRED(VERSION 2.4)\n"
@@ -48,7 +56,8 @@ if(LAPACK_LIBRARIES)
     "SET(CMAKE_C_FLAGS_RELWITHDEBUGINFO \"${CMAKE_C_FLAGS_RELWITHDEBUGINFO}\")\n"
     "SET(CMAKE_C_FLAGS_MINSIZE \"${CMAKE_C_FLAGS_MINSIZE}\")\n"
     "ADD_EXECUTABLE(ltest ltest.c)\n"
-    "TARGET_LINK_LIBRARIES(ltest ${LAPACK_LIBRARIES})\n")    
+    "TARGET_LINK_LIBRARIES(ltest ${LAPACK_LIBRARIES})\n")
+
   # Create a C source file which calls a Blas function (dcopy) and an Lapack function (dgetrf)
   file(WRITE ${LapackTest_DIR}/ltest.c
     "${F77_MANGLE_MACRO1}\n"
@@ -63,19 +72,34 @@ if(LAPACK_LIBRARIES)
     "dgetrf_f77(&n, &n, &x, &n, &n, &n);\n"
     "return(0);\n"
     "}\n")
+
   # Attempt to link the "ltest" executable
   try_compile(LTEST_OK ${LapackTest_DIR} ${LapackTest_DIR}
-    ltest OUTPUT_VARIABLE MY_OUTPUT)    
+    ltest OUTPUT_VARIABLE MY_OUTPUT)
+
   # To ensure we do not use stuff from the previous attempts, 
   # we must remove the CMakeFiles directory.
   file(REMOVE_RECURSE ${LapackTest_DIR}/CMakeFiles)
+
   # Process test result
   if(LTEST_OK)
-    message(STATUS "Checking if Lapack works... OK")
+    message(STATUS "Checking if LAPACK works... OK")
     set(LAPACK_FOUND TRUE)
+
+    # get path to LAPACK library to use in generated makefiles for examples, if
+    # LAPACK_LIBRARIES contains multiple items only use the path of the first entry
+    list(LENGTH LAPACK_LIBRARIES len)
+    if(len EQUAL 1)
+      get_filename_component(LAPACK_LIBRARY_DIR ${LAPACK_LIBRARIES} PATH)
+    else()
+      list(GET LAPACK_LIBRARIES 0 TMP_LAPACK_LIBRARIES)
+      get_filename_component(LAPACK_LIBRARY_DIR ${TMP_LAPACK_LIBRARIES} PATH)
+    endif()
+
   else(LTEST_OK)
-    message(STATUS "Checking if Lapack works... FAILED")
+    message(STATUS "Checking if LAPACK works... FAILED")
   endif(LTEST_OK)
+
 else(LAPACK_LIBRARIES)
   message(STATUS "Looking for LAPACK libraries... FAILED")
 endif(LAPACK_LIBRARIES)
diff --git a/config/SundialsMPIC.cmake b/config/SundialsMPIC.cmake
index 062fa69..f5c0e1d 100644
--- a/config/SundialsMPIC.cmake
+++ b/config/SundialsMPIC.cmake
@@ -1,23 +1,20 @@
 # ---------------------------------------------------------------
-# $Revision: 4511 $
-# $Date: 2015-06-29 16:48:09 -0700 (Mon, 29 Jun 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Copyright (c) 2008, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # ---------------------------------------------------------------
 # MPI-C tests for SUNDIALS CMake-based configuration.
 #
 # 
 
-# make sure valid mpi_run_command. If not, then warn and return
-If(MPI_RUN_COMMAND AND NOT MPI_RUN_COMMAND STREQUAL "mpirun" AND NOT MPI_RUN_COMMAND STREQUAL "srun")
-    PRINT_WARNING("Unknown mpi run command: ${MPI_RUN_COMMAND}" "Please enter mpirun or srun")
-ENDIF(MPI_RUN_COMMAND AND NOT MPI_RUN_COMMAND STREQUAL "mpirun" AND NOT MPI_RUN_COMMAND STREQUAL "srun")
-
 set(MPIC_FOUND FALSE)
 set(MPIC_MPI2 FALSE)
 
diff --git a/config/SundialsMPICXX.cmake b/config/SundialsMPICXX.cmake
index 481615c..8fc2fa6 100644
--- a/config/SundialsMPICXX.cmake
+++ b/config/SundialsMPICXX.cmake
@@ -1,9 +1,19 @@
 # ---------------------------------------------------------------
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
-# Copyright (c) 2013, Southern Methodist University.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # MPI-C++ tests for SUNDIALS CMake-based configuration.
 
diff --git a/config/SundialsMPIF.cmake b/config/SundialsMPIF.cmake
index 73affac..fe44cf3 100644
--- a/config/SundialsMPIF.cmake
+++ b/config/SundialsMPIF.cmake
@@ -1,13 +1,15 @@
 # ---------------------------------------------------------------
-# $Revision: 4511 $
-# $Date: 2015-06-29 16:48:09 -0700 (Mon, 29 Jun 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Copyright (c) 2008, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # ---------------------------------------------------------------
 # MPI-Fortran tests for SUNDIALS CMake-based configuration.
 #
diff --git a/config/SundialsMPIF90.cmake b/config/SundialsMPIF90.cmake
index 104dd9d..ba6d795 100644
--- a/config/SundialsMPIF90.cmake
+++ b/config/SundialsMPIF90.cmake
@@ -1,9 +1,19 @@
 # ---------------------------------------------------------------
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
-# Copyright (c) 2013, Southern Methodist University.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # MPI-Fortran90 tests for SUNDIALS CMake-based configuration.
 
diff --git a/config/SundialsPETSc.cmake b/config/SundialsPETSc.cmake
index 4ab8f49..aaf4671 100644
--- a/config/SundialsPETSc.cmake
+++ b/config/SundialsPETSc.cmake
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision:  $
-# $Date:  $
-# ---------------------------------------------------------------
 # Programmer:  Eddy Banks @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -16,6 +13,7 @@
 # ---------------------------------------------------------------
 # PETSc tests for SUNDIALS CMake-based configuration.
 # 
+
 ### This is only set if running GUI - simply return first time enabled
 IF(PETSC_DISABLED)
   SET(PETSC_DISABLED FALSE CACHE INTERNAL "GUI - now enabled" FORCE)
diff --git a/config/SundialsSuperLUMT.cmake b/config/SundialsSuperLUMT.cmake
index 662e3af..aa10a83 100644
--- a/config/SundialsSuperLUMT.cmake
+++ b/config/SundialsSuperLUMT.cmake
@@ -1,17 +1,21 @@
 # ---------------------------------------------------------------
-# $Revision: 4955 $
-# $Date: 2016-09-23 10:01:28 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Eddy Banks @ LLNL
 # ---------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # ---------------------------------------------------------------
 # SUPERLUMT tests for SUNDIALS CMake-based configuration.
 #    - loosely based on SundialsLapack.cmake
-# 
+#
+
+
 ### This is only set if running GUI - simply return first time enabled
 IF(SUPERLUMT_DISABLED)
   SET(SUPERLUMT_DISABLED FALSE CACHE INTERNAL "GUI - SUPERLUMT now enabled" FORCE)
@@ -22,12 +26,15 @@ SET(SUPERLUMT_FOUND FALSE)
 
 # set SUPERLUMT_LIBRARIES
 include(FindSUPERLUMT)
+
 # If we have the SUPERLUMT libraries, test them
 if(SUPERLUMT_LIBRARY AND SUPERLUMT_LIBRARIES)
   message(STATUS "Looking for SUPERLUMT libraries... OK")
+
   # Create the SUPERLUMT_TEST directory
   set(SUPERLUMT_TEST_DIR ${PROJECT_BINARY_DIR}/SUPERLUMT_TEST)
   file(MAKE_DIRECTORY ${SUPERLUMT_TEST_DIR})
+
   # Create a CMakeLists.txt file 
   file(WRITE ${SUPERLUMT_TEST_DIR}/CMakeLists.txt
     "CMAKE_MINIMUM_REQUIRED(VERSION 2.4)\n"
@@ -42,7 +49,8 @@ if(SUPERLUMT_LIBRARY AND SUPERLUMT_LIBRARIES)
     "INCLUDE_DIRECTORIES(${SUPERLUMT_INCLUDE_DIR})\n"
     "ADD_EXECUTABLE(ltest ltest.c)\n"
     "TARGET_LINK_LIBRARIES(ltest ${SUPERLUMT_LIBRARIES})\n")    
-# Create a C source file which calls a SUPERLUMT function
+
+  # Create a C source file which calls a SUPERLUMT function
   file(WRITE ${SUPERLUMT_TEST_DIR}/ltest.c
     "\#include \"slu_mt_ddefs.h\"\n"
 #    "\#include \"pdsp_defs.h\"\n"
@@ -51,12 +59,14 @@ if(SUPERLUMT_LIBRARY AND SUPERLUMT_LIBRARIES)
     "NCformat *Astore;\n" 
     "return(0);\n"
     "}\n")
+
   # Attempt to link the "ltest" executable
   try_compile(LTEST_OK ${SUPERLUMT_TEST_DIR} ${SUPERLUMT_TEST_DIR} ltest OUTPUT_VARIABLE MY_OUTPUT)
       
   # To ensure we do not use stuff from the previous attempts, 
   # we must remove the CMakeFiles directory.
   file(REMOVE_RECURSE ${SUPERLUMT_TEST_DIR}/CMakeFiles)
+
   # Process test result
   if(LTEST_OK)
     message(STATUS "Checking if SUPERLUMT works... OK")
@@ -66,6 +76,6 @@ if(SUPERLUMT_LIBRARY AND SUPERLUMT_LIBRARIES)
   endif(LTEST_OK)
 
 else()
-  PRINT_WARNING("SUPERLUMT LIBRARIES NOT Found. Please check library path" "${SUPERLUMT_LIBRARY_DIR} ")
+  PRINT_WARNING("SUPERLUMT LIBRARIES NOT Found. Please check library path" "${SUPERLUMT_LIBRARY_DIR}")
   message(STATUS "Looking for SUPERLUMT libraries... FAILED")
 endif()
diff --git a/config/SundialsXSDK.cmake b/config/SundialsXSDK.cmake
new file mode 100644
index 0000000..aaf0f41
--- /dev/null
+++ b/config/SundialsXSDK.cmake
@@ -0,0 +1,314 @@
+# ---------------------------------------------------------------
+# Programmer:  David J. Gardner @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# xSDK specific CMake variables. If set, these variables will 
+# overwrite the value in equivalent SUNDIALS CMake variable.
+#
+# Only USE_XSDK_DEFAULTS is created in CACHE by default (set to 
+# OFF). The other xSDK variables are left undefined. They can be
+# be set by passing -D<variable_name>=<value> to cmake or can be 
+# enabled in the cmake-gui setting USE_XSDK_DEFAULTS to ON.
+#
+# When USE_XSDK_DEFAULTS is ON the default values are overwritten
+# by values passed to cmake or manually set in the cmake-gui.
+# ---------------------------------------------------------------
+
+# always show the option to turn on xSDK defaults
+OPTION(USE_XSDK_DEFAULTS "Enable default xSDK settings" OFF)
+
+# ---------------------------------------------------------------
+# Set default values for some xSDK variables
+# ---------------------------------------------------------------
+
+IF(USE_XSDK_DEFAULTS)
+
+  MESSAGE("Enabeling xSDK defaults")
+  
+  # set the CMake build type, SUNDIALS does not set a build type by default
+  IF(NOT CMAKE_BUILD_TYPE)
+    MESSAGE("Setting build type to Debug")
+    SET(DOCSTR "Choose the type of build: None Debug Release RelWithDebInfo MinSizeRel")
+    FORCE_VARIABLE(CMAKE_BUILD_TYPE STRING "${DOCSTR}" "Debug")
+  ENDIF()
+
+  # set build precision, SUNDIALS_PRECISION defaults to double
+  SHOW_VARIABLE(XSDK_PRECISION STRING "single, double, or quad" "double")
+
+  # set build index size, SUNDIALS_INDEX_TYPE defaults to int64_t
+  SHOW_VARIABLE(XSDK_INDEX_SIZE STRING "32 or 64" "32")
+
+  # disable Fortran-C interface, FCMIX defaults to OFF
+  SHOW_VARIABLE(XSDK_ENABLE_FORTRAN BOOL "Enable Fortran-C support" OFF)
+
+  # disable BLAS by default
+  SHOW_VARIABLE(TPL_ENABLE_BLAS BOOL "Enable BLAS support" OFF)
+
+  # disable LAPACK by default
+  SHOW_VARIABLE(TPL_ENABLE_LAPACK BOOL "Enable LAPACK support" OFF)
+
+  # disable SuperLU_MT by default
+  SHOW_VARIABLE(TPL_ENABLE_SUPERLUMT BOOL "Enable SuperLU_MT support" OFF)
+
+  # disable KLU by default
+  SHOW_VARIABLE(TPL_ENABLE_KLU BOOL "Enable KLU support" OFF)
+
+  # disable PETSc by default
+  SHOW_VARIABLE(TPL_ENABLE_PETSC BOOL "Enable PETSc support" OFF)
+
+  # disable hypre by default
+  SHOW_VARIABLE(TPL_ENABLE_HYPRE BOOL "Enable hypre support" OFF)
+
+ENDIF()
+
+# ---------------------------------------------------------------
+# hide (make advanced) and overwrite equivalent SUNDIALS variables
+# ---------------------------------------------------------------
+
+# ---------------------------------------------------------------
+# SUNDIALS precision, indextype, and Fortran interface
+# ---------------------------------------------------------------
+
+# XSDK_PRECISION => SUNDIALS_PRECISION
+IF(XSDK_PRECISION)
+  MESSAGE("Replacing SUNDIALS_PRECISION with XSDK_PRECISION")
+  SET(DOCSTR "single, double, or extended")
+
+  IF(XSDK_PRECISION MATCHES "quad")
+    FORCE_VARIABLE(SUNDIALS_PRECISION STRING "${DOCSTR}" "extended")
+  ELSE()
+    FORCE_VARIABLE(SUNDIALS_PRECISION STRING "${DOCSTR}" "${XSDK_PRECISION}")
+  ENDIF()
+
+  MARK_AS_ADVANCED(FORCE SUNDIALS_PRECISION)
+ENDIF()
+
+# XSDK_INDEX_SIZE => SUNDIALS_INDEX_TYPE
+IF(XSDK_INDEX_SIZE)
+  MESSAGE("Replacing SUNDIALS_INDEX_TYPE with XSDK_INDEX_SIZE")
+  SET(DOCSTR "Signed 64-bit (int64_t) or signed 32-bit (int32_t) integer")
+
+  IF(XSDK_INDEX_SIZE MATCHES "32")
+    FORCE_VARIABLE(SUNDIALS_INDEX_TYPE STRING "${DOCSTR}" "int32_t")
+  ELSE()
+    FORCE_VARIABLE(SUNDIALS_INDEX_TYPE STRING "${DOCSTR}" "int64_t")
+  ENDIF()
+
+  MARK_AS_ADVANCED(FORCE SUNDIALS_INDEX_TYPE)
+ENDIF()
+
+# XSDK_FORTRAN_ENABLE => FCMIX_ENABLE
+IF(DEFINED XSDK_ENABLE_FORTRAN)
+  MESSAGE("Replacing FCMIX_ENABLE with XSDK_ENABLE_FORTRAN")
+  SET(DOCSTR "Enable Fortran-C support")
+  
+  # check that at least one solver with a Fortran interface is built
+  IF(NOT BUILD_ARKODE AND NOT BUILD_CVODE AND NOT BUILD_IDA AND NOT BUILD_KINSOL)
+    IF(XSDK_ENABLE_FORTRAN)
+      PRINT_WARNING("Enabled packages do not support Fortran" 
+                    "Disabeling XSDK_ENABLE_FORTRAN")
+      FORCE_VARIABLE(XSDK_ENABLE_FORTRAN BOOL "${DOCSTR}" OFF)
+    ENDIF()
+    HIDE_VARIABLE(FCMIX_ENABLE)
+    HIDE_VARIABLE(XSDK_ENABLE_FORTRAN)
+  ENDIF()
+
+  FORCE_VARIABLE(FCMIX_ENABLE BOOL "${DOCSTR}" "${XSDK_ENABLE_FORTRAN}")
+  MARK_AS_ADVANCED(FORCE FCMIX_ENABLE)
+ENDIF()
+
+
+# ---------------------------------------------------------------
+# BLAS
+# ---------------------------------------------------------------
+
+# TPL_ENABLE_BLAS => BLAS_ENABLE
+IF(DEFINED TPL_ENABLE_BLAS)
+  MESSAGE("Replacing BLAS_ENABLE with TPL_ENABLE_BLAS")
+  SET(DOCSTR "Enable Blas support")
+
+  FORCE_VARIABLE(BLAS_ENABLE BOOL "${DOCSTR}" "${TPL_ENABLE_BLAS}")
+  MARK_AS_ADVANCED(FORCE BLAS_ENABLE)
+ENDIF()
+
+# TPL_BLAS_LIBRARIES => BLAS_LIBRARIES
+IF(TPL_ENABLE_BLAS)
+  MESSAGE("Replacing BLAS_LIBRARIES with TPL_BLAS_LIBRARIES")
+  SET(DOCSTR "Blas library")
+
+  SHOW_VARIABLE(TPL_BLAS_LIBRARIES STRING "${DOCSTR}" "${TPL_BLAS_LIBRARIES}")
+  FORCE_VARIABLE(BLAS_LIBRARIES STRING "${DOCSTR}" "${TPL_BLAS_LIBRARIES}")
+  MARK_AS_ADVANCED(FORCE BLAS_LIBRARIES)
+ENDIF()
+
+
+# ---------------------------------------------------------------
+# LAPACK
+# ---------------------------------------------------------------
+
+# TPL_ENABLE_LAPACK => LAPACK_ENABLE
+IF(DEFINED TPL_ENABLE_LAPACK)
+  MESSAGE("Replacing LAPACK_ENABLE with TPL_ENABLE_LAPACK")
+  SET(DOCSTR "Enable Lapack support")
+
+  FORCE_VARIABLE(LAPACK_ENABLE BOOL "${DOCSTR}" "${TPL_ENABLE_LAPACK}")
+  MARK_AS_ADVANCED(FORCE LAPACK_ENABLE)
+ENDIF()
+
+# TPL_LAPACK_LIBRARIES => LAPACK_LIBRARIES
+IF(TPL_ENABLE_LAPACK)
+  MESSAGE("Replacing LAPACK_LIBRARIES with TPL_LAPACK_LIBRARIES")
+  SET(DOCSTR "Lapack library")
+
+  SHOW_VARIABLE(TPL_LAPACK_LIBRARIES STRING "${DOCSTR}" "${TPL_LAPACK_LIBRARIES}")
+  FORCE_VARIABLE(LAPACK_LIBRARIES STRING "${DOCSTR}" "${TPL_LAPACK_LIBRARIES}")
+  MARK_AS_ADVANCED(FORCE LAPACK_LIBRARIES)
+ENDIF()
+
+
+# ---------------------------------------------------------------
+# SuperLU_MT
+# ---------------------------------------------------------------
+
+# TPL_ENABLE_SUPERLUMT => SUPERLUMT_ENABLE
+IF(DEFINED TPL_ENABLE_SUPERLUMT)
+  MESSAGE("Replacing SUPERLUMT_ENABLE with TPL_ENABLE_SUPERLUMT")
+  SET(DOCSTR "Enable SuperLU_MT support")
+
+  FORCE_VARIABLE(SUPERLUMT_ENABLE BOOL "${DOCSTR}" "${TPL_ENABLE_SUPERLUMT}")
+  MARK_AS_ADVANCED(FORCE SUPERLUMT_ENABLE)
+ENDIF()
+
+# TPL_SUPERLUMT_INCLUDE_DIRS => SUPERLUMT_INCLUDE_DIR
+# TPL_SUPERLUMT_LIBRARIES    => SUPERLUMT_LIBRARY     => SUPERLUMT_LIBRARIES
+IF(TPL_ENABLE_SUPERLUMT)
+  MESSAGE("Replacing SUPERLUMT_INCLUDE_DIR with TPL_SUPERLUMT_INCLUDE_DIRS")
+  SET(DOCSTR "SuperLU_MT include directory")
+
+  SHOW_VARIABLE(TPL_SUPERLUMT_INCLUDE_DIRS STRING "${DOCSTR}" "${TPL_SUPERLUMT_INCLUDE_DIRS}")
+  FORCE_VARIABLE(SUPERLUMT_INCLUDE_DIR STRING "${DOCSTR}" "${TPL_SUPERLUMT_INCLUDE_DIRS}")
+  MARK_AS_ADVANCED(FORCE SUPERLUMT_INCLUDE_DIR)
+
+  MESSAGE("Replacing SUPERLUMT_LIBRARY with TPL_SUPERLUMT_LIBRARIES")
+  SET(DOCSTR "SuperLU_MT library")
+
+  SHOW_VARIABLE(TPL_SUPERLUMT_LIBRARIES STRING "${DOCSTR}" "${TPL_SUPERLUMT_LIBRARIES}")
+  FORCE_VARIABLE(SUPERLUMT_LIBRARY STRING "${DOCSTR}" "${TPL_SUPERLUMT_LIBRARIES}")
+  MARK_AS_ADVANCED(FORCE SUPERLUMT_LIBRARY)
+  MARK_AS_ADVANCED(FORCE SUPERLUMT_LIBRARY_DIR)
+
+  MESSAGE("Replacing SUPERLUMT_THREAD_TYPE with TPL_SUPERLUMT_THREAD_TYPE")
+  SET(DOCSTR "SuperLU_MT thread type (OpenMP or Pthread)")
+  
+  SHOW_VARIABLE(TPL_SUPERLUMT_THREAD_TYPE STRING "${DOCSTR}" "PThread")
+  FORCE_VARIABLE(SUPERLUMT_THREAD_TYPE STRING "${DOCSTR}" "${TPL_SUPERLUMT_THREAD_TYPE}")
+  MARK_AS_ADVANCED(FORCE SUPERLUMT_THREAD_TYPE)
+ENDIF()
+
+
+# ---------------------------------------------------------------
+# KLU
+# ---------------------------------------------------------------
+
+# TPL_ENABLE_KLU => KLU_ENABLE
+IF(DEFINED TPL_ENABLE_KLU)
+  MESSAGE("Replacing KLU_ENABLE with TPL_ENABLE_KLU")
+  SET(DOCSTR "Enable KLU support")
+
+  FORCE_VARIABLE(KLU_ENABLE BOOL "${DOCSTR}" "${TPL_ENABLE_KLU}")
+  MARK_AS_ADVANCED(FORCE KLU_ENABLE)
+ENDIF()
+
+# TPL_KLU_INCLUDE_DIRS => KLU_INCLUDE_DIR
+# TPL_KLU_LIBRARIES    => KLU_LIBRARY     => KLU_LIBRARIES
+IF(TPL_ENABLE_KLU)
+  MESSAGE("Replacing KLU_INCLUDE_DIR with TPL_KLU_INCLUDE_DIRS")
+  SET(DOCSTR "KLU include directory")
+
+  SHOW_VARIABLE(TPL_KLU_INCLUDE_DIRS STRING "${DOCSTR}" "${TPL_KLU_INCLUDE_DIRS}")
+  FORCE_VARIABLE(KLU_INCLUDE_DIR STRING "${DOCSTR}" "${TPL_KLU_INCLUDE_DIRS}")
+  MARK_AS_ADVANCED(FORCE KLU_INCLUDE_DIR)
+
+  MESSAGE("Replacing KLU_LIBRARY with TPL_KLU_LIBRARIES")
+  SET(DOCSTR "KLU library")
+
+  SHOW_VARIABLE(TPL_KLU_LIBRARIES STRING "${DOCSTR}" "${TPL_KLU_LIBRARIES}")
+  FORCE_VARIABLE(KLU_LIBRARY STRING "${DOCSTR}" "${TPL_KLU_LIBRARIES}")
+  MARK_AS_ADVANCED(FORCE KLU_LIBRARY)
+  MARK_AS_ADVANCED(FORCE KLU_LIBRARY_DIR)
+ENDIF()
+
+
+# ---------------------------------------------------------------
+# HYPRE
+# ---------------------------------------------------------------
+
+# TPL_ENABLE_HYPRE => HYPRE_ENABLE
+IF(DEFINED TPL_ENABLE_HYPRE)
+  MESSAGE("Replacing HYPRE_ENABLE with TPL_ENABLE_HYPRE")
+  SET(DOCSTR "Enable hypre support")
+
+  FORCE_VARIABLE(HYPRE_ENABLE BOOL "${DOCSTR}" "${TPL_ENABLE_HYPRE}")
+  MARK_AS_ADVANCED(FORCE HYPRE_ENABLE)
+ENDIF()
+
+# TPL_HYPRE_INCLUDE_DIRS => HYPRE_INCLUDE_DIR
+# TPL_HYPRE_LIBRARIES    => HYPRE_LIBRARY     => HYPRE_LIBRARIES
+IF(TPL_ENABLE_HYPRE)
+  MESSAGE("Replacing HYPRE_INCLUDE_DIR with TPL_HYPRE_INCLUDE_DIRS")
+  SET(DOCSTR "hypre include directory")
+
+  SHOW_VARIABLE(TPL_HYPRE_INCLUDE_DIRS STRING "${DOCSTR}" "${TPL_HYPRE_INCLUDE_DIRS}")
+  FORCE_VARIABLE(HYPRE_INCLUDE_DIR STRING "${DOCSTR}" "${TPL_HYPRE_INCLUDE_DIRS}")
+  MARK_AS_ADVANCED(FORCE HYPRE_INCLUDE_DIR)
+
+  MESSAGE("Replacing HYPRE_LIBRARY with TPL_HYPRE_LIBRARIES")
+  SET(DOCSTR "hypre library")
+
+  SHOW_VARIABLE(TPL_HYPRE_LIBRARIES STRING "${DOCSTR}" "${TPL_HYPRE_LIBRARIES}")
+  FORCE_VARIABLE(HYPRE_LIBRARY STRING "${DOCSTR}" "${TPL_HYPRE_LIBRARIES}")
+  MARK_AS_ADVANCED(FORCE HYPRE_LIBRARY)
+  MARK_AS_ADVANCED(FORCE HYPRE_LIBRARY_DIR)
+ENDIF()
+
+
+# ---------------------------------------------------------------
+# PETSC
+# ---------------------------------------------------------------
+
+# TPL_ENABLE_PETSC => PETSC_ENABLE
+IF(DEFINED TPL_ENABLE_PETSC)
+  MESSAGE("Replacing PETSC_ENABLE with TPL_ENABLE_PETSC")
+  SET(DOCSTR "Enable petsc support")
+
+  FORCE_VARIABLE(PETSC_ENABLE BOOL "${DOCSTR}" "${TPL_ENABLE_PETSC}")
+  MARK_AS_ADVANCED(FORCE PETSC_ENABLE)
+ENDIF()
+
+# TPL_PETSC_INCLUDE_DIRS => PETSC_INCLUDE_DIR
+# TPL_PETSC_LIBRARIES    => PETSC_LIBRARY     => PETSC_LIBRARIES
+IF(TPL_ENABLE_PETSC)
+  MESSAGE("Replacing PETSC_INCLUDE_DIR with TPL_PETSC_INCLUDE_DIRS")
+  SET(DOCSTR "PETSc include directory")
+
+  SHOW_VARIABLE(TPL_PETSC_INCLUDE_DIRS STRING "${DOCSTR}" "${TPL_PETSC_INCLUDE_DIRS}")
+  FORCE_VARIABLE(PETSC_INCLUDE_DIR STRING "${DOCSTR}" "${TPL_PETSC_INCLUDE_DIRS}")
+  MARK_AS_ADVANCED(FORCE PETSC_INCLUDE_DIR)
+
+  MESSAGE("Replacing PETSC_LIBRARY with TPL_PETSC_LIBRARIES")
+  SET(DOCSTR "PETSc library")
+
+  SHOW_VARIABLE(TPL_PETSC_LIBRARIES STRING "${DOCSTR}" "${TPL_PETSC_LIBRARIES}")
+  FORCE_VARIABLE(PETSC_LIBRARY STRING "${DOCSTR}" "${TPL_PETSC_LIBRARIES}")
+  MARK_AS_ADVANCED(FORCE PETSC_LIBRARY)
+  MARK_AS_ADVANCED(FORCE PETSC_LIBRARY_DIR)
+ENDIF()
diff --git a/examples/arkode/CXX_parallel/CMakeLists.txt b/examples/arkode/CXX_parallel/CMakeLists.txt
index 8f51139..3148596 100644
--- a/examples/arkode/CXX_parallel/CMakeLists.txt
+++ b/examples/arkode/CXX_parallel/CMakeLists.txt
@@ -2,13 +2,13 @@
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -19,16 +19,17 @@
 # For details, see the LICENSE file.
 # -----------------------------------------------------------------
 # CMakeLists.txt file for ARKODE C++ parallel examples
+# -----------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable ARKODE_examples with the names of the parallel ARKODE examples
-
+# Examples using SUNDIALS linear solvers
 SET(ARKODE_examples
-  ark_heat2D
+  "ark_heat2D\;\;\;develop"
   )
 
-# Add variable ARKODE_extras with the names of auxiliary files to install
-
+# Auxiliary files to install
 SET(ARKODE_extras
   plot_heat2D.py
   )
@@ -41,52 +42,63 @@ IF(MPI_MPICXX)
   # use MPI_MPICXX as the compiler
   SET(CMAKE_CXX_COMPILER ${MPI_MPICXX})
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMPICH_SKIP_MPICXX -DOMPI_SKIP_MPICXX -DLAM_BUILDING")
-ELSE(MPI_MPICXX)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICXX)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${ARKODE_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${ARKODE_examples})
 
-# Add the build and install targets for each ARKODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
 
-FOREACH(example ${ARKODE_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.cpp)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPICXX)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICXX)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.cpp ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_parallel)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${ARKODE_examples})
+    INSTALL(FILES ${example}.cpp ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_parallel)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${ARKODE_examples})
+
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -95,32 +107,33 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${ARKODE_extras})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_parallel)
-  ENDFOREACH(extrafile ${ARKODE_extras})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
-  LIST2STRING(ARKODE_examples EXAMPLES)
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(ARKODE_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_CXX_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/CXX_parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_CXX_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/CXX_parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/CXX_parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/arkode/CXX_parallel/README b/examples/arkode/CXX_parallel/README
index 5c2f8b4..f178cbc 100644
--- a/examples/arkode/CXX_parallel/README
+++ b/examples/arkode/CXX_parallel/README
@@ -13,7 +13,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -24,7 +23,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -37,7 +39,6 @@ The following CMake command was used to configure SUNDIALS:
 -DHYPRE_LIBRARY=/usr/casc/sundials/apps/rh6/hypre/2.11.1/lib/libHYPRE.a \
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
--DFCMIX_ENABLE=ON \
 -DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
diff --git a/examples/arkode/CXX_parallel/ark_heat2D.cpp b/examples/arkode/CXX_parallel/ark_heat2D.cpp
index 3d9528b..a15a28a 100644
--- a/examples/arkode/CXX_parallel/ark_heat2D.cpp
+++ b/examples/arkode/CXX_parallel/ark_heat2D.cpp
@@ -53,10 +53,21 @@
 #include <math.h>
 #include "arkode/arkode.h"            // prototypes for ARKode fcts., consts. 
 #include "nvector/nvector_parallel.h" // parallel N_Vector types, fcts., macros 
-#include "arkode/arkode_pcg.h"        // prototype for ARKPcg solver 
+#include "sunlinsol/sunlinsol_pcg.h"  // access to PCG SUNLinearSolver
+#include "arkode/arkode_spils.h"      // access to ARKSpils interface
 #include "sundials/sundials_types.h"  // def. of type 'realtype' 
 #include "mpi.h"                      // MPI header file
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
 using namespace std;
 
 // accessor macros between (x,y) location and 1D NVector array
@@ -67,14 +78,14 @@ using namespace std;
 
 // user data structure 
 typedef struct {
-  long int nx;          // global number of x grid points 
-  long int ny;          // global number of y grid points
-  long int is;          // global x indices of this subdomain
-  long int ie;
-  long int js;          // global y indices of this subdomain
-  long int je;
-  long int nxl;         // local number of x grid points 
-  long int nyl;         // local number of y grid points 
+  sunindextype nx;          // global number of x grid points 
+  sunindextype ny;          // global number of y grid points
+  sunindextype is;          // global x indices of this subdomain
+  sunindextype ie;
+  sunindextype js;          // global y indices of this subdomain
+  sunindextype je;
+  sunindextype nxl;         // local number of x grid points 
+  sunindextype nyl;         // local number of y grid points 
   realtype dx;          // x-directional mesh spacing 
   realtype dy;          // y-directional mesh spacing 
   realtype kx;          // x-directional diffusion coefficient 
@@ -98,11 +109,10 @@ typedef struct {
 // User-supplied Functions Called by the Solver 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 static int PSet(realtype t, N_Vector y, N_Vector fy, booleantype jok, 
-		booleantype *jcurPtr, realtype gamma, void *user_data,
-		N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+		booleantype *jcurPtr, realtype gamma, void *user_data);
 static int PSol(realtype t, N_Vector y, N_Vector fy, N_Vector r, 
 		N_Vector z, realtype gamma, realtype delta, int lr, 
-		void *user_data, N_Vector tmp);
+		void *user_data);
 
 // Private functions 
 //    checks function return values 
@@ -123,20 +133,21 @@ int main(int argc, char* argv[]) {
   realtype T0 = RCONST(0.0);   // initial time 
   realtype Tf = RCONST(0.3);   // final time 
   int Nt = 20;                 // total number of output times 
-  long int nx = 60;            // spatial mesh size
-  long int ny = 120;
+  sunindextype nx = 60;            // spatial mesh size
+  sunindextype ny = 120;
   realtype kx = 0.5;           // heat conductivity coefficients
   realtype ky = 0.75;
   realtype rtol = 1.e-5;       // relative and absolute tolerances
   realtype atol = 1.e-10;
   UserData *udata = NULL;
   realtype *data;
-  long int N, Ntot, i, j;
+  sunindextype N, Ntot, i, j;
 
   // general problem variables 
   int flag;                      // reusable error-checking flag 
   int myid;                      // MPI process ID
   N_Vector y = NULL;             // empty vector for storing solution 
+  SUNLinearSolver LS = NULL;     // empty linear solver memory structure
   void *arkode_mem = NULL;       // empty ARKode memory structure 
 
   // initialize MPI
@@ -175,7 +186,7 @@ int main(int argc, char* argv[]) {
     cout << "   nyl (proc 0) = " << udata->nyl << "\n\n";
   }
 
-  // Initialize data structures 
+  // Initialize vector data structures 
   N = (udata->nxl)*(udata->nyl);
   Ntot = nx*ny;
   y = N_VNew_Parallel(udata->comm, N, Ntot);         // Create parallel vector for solution 
@@ -185,7 +196,13 @@ int main(int argc, char* argv[]) {
   if (check_flag((void *) udata->h, "N_VNew_Parallel", 0)) return 1;
   udata->d = N_VNew_Parallel(udata->comm, N, Ntot);  // Create vector for Jacobian diagonal
   if (check_flag((void *) udata->d, "N_VNew_Parallel", 0)) return 1;
-  arkode_mem = ARKodeCreate();                       // Create the solver memory 
+
+  // Initialize linear solver data structure
+  LS = SUNPCG(y, 1, 20);
+  if (check_flag((void *) LS, "SUNPCG", 0)) return 1;
+
+  // Initialize ARKode data structure
+  arkode_mem = ARKodeCreate();
   if (check_flag((void *) arkode_mem, "ARKodeCreate", 0)) return 1;
 
   // fill in the heat source array
@@ -210,8 +227,8 @@ int main(int argc, char* argv[]) {
   flag = ARKodeSStolerances(arkode_mem, rtol, atol);      // Specify tolerances 
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  // Linear solver specification 
-  flag = ARKPcg(arkode_mem, 1, 20);                           // Specify the PCG solver 
+  // Linear solver interface
+  flag = ARKSpilsSetLinearSolver(arkode_mem, LS);             // Attach linear solver
   if (check_flag(&flag, "ARKPcg", 1)) return 1;
   flag = ARKSpilsSetPreconditioner(arkode_mem, PSet, PSol);   // Specify the Preconditoner
   if (check_flag(&flag, "ARKSpilsSetPreconditioner", 1)) return 1;
@@ -225,7 +242,8 @@ int main(int argc, char* argv[]) {
   sprintf(outname, "heat2d_subdomain.%03i.txt", udata->myid);
   FILE *UFID = fopen(outname,"w");
   fprintf(UFID, "%li  %li  %li  %li  %li  %li\n", 
-	  udata->nx, udata->ny, udata->is, udata->ie, udata->js, udata->je);
+	  (long int) udata->nx, (long int) udata->ny, (long int) udata->is,
+          (long int) udata->ie, (long int) udata->js, (long int) udata->je);
   fclose(UFID);
 
   // Open output streams for results, access data array 
@@ -234,7 +252,7 @@ int main(int argc, char* argv[]) {
   data = N_VGetArrayPointer(y);
 
   // output initial condition to disk 
-  for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[i]);
+  for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM, data[i]);
   fprintf(UFID,"\n");
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
@@ -246,7 +264,7 @@ int main(int argc, char* argv[]) {
   if (outproc) {
     cout << "        t      ||u||_rms\n";
     cout << "   ----------------------\n";
-    printf("  %10.6f  %10.6f\n", t, urms);
+    printf("  %10.6"FSYM"  %10.6"FSYM"\n", t, urms);
   }
   int iout;
   for (iout=0; iout<Nt; iout++) {
@@ -254,7 +272,7 @@ int main(int argc, char* argv[]) {
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);         // call integrator 
     if (check_flag(&flag, "ARKode", 1)) break;
     urms = sqrt(N_VDotProd(y,y)/nx/ny);
-    if (outproc)  printf("  %10.6f  %10.6f\n", t, urms);        // print solution stats 
+    if (outproc)  printf("  %10.6"FSYM"  %10.6"FSYM"\n", t, urms);        // print solution stats 
     if (flag >= 0) {                                            // successful solve: update output time
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -265,7 +283,7 @@ int main(int argc, char* argv[]) {
     }
 
     // output results to disk 
-    for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[i]);
+    for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM"", data[i]);
     fprintf(UFID,"\n");
   }
   if (outproc)  cout << "   ----------------------\n";
@@ -313,12 +331,13 @@ int main(int argc, char* argv[]) {
   }
 
   // Clean up and return with successful completion 
-  N_VDestroy_Parallel(y);        // Free vectors 
+  ARKodeFree(&arkode_mem);     // Free integrator memory 
+  SUNLinSolFree(LS);           // Free linear solver
+  N_VDestroy_Parallel(y);      // Free vectors 
   N_VDestroy_Parallel(udata->h);
   N_VDestroy_Parallel(udata->d);
   FreeUserData(udata);         // Free user data 
   delete udata;       
-  ARKodeFree(&arkode_mem);     // Free integrator memory 
   flag = MPI_Finalize();       // Finalize MPI
   return 0;
 }
@@ -332,8 +351,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
   N_VConst(0.0, ydot);                           // Initialize ydot to zero 
   UserData *udata = (UserData *) user_data;      // access problem data 
-  long int nxl = udata->nxl;                     // set variable shortcuts 
-  long int nyl = udata->nyl;
+  sunindextype nxl = udata->nxl;                     // set variable shortcuts 
+  sunindextype nyl = udata->nyl;
   realtype kx = udata->kx;
   realtype ky = udata->ky;
   realtype dx = udata->dx;
@@ -351,7 +370,7 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   realtype c1 = kx/dx/dx;
   realtype c2 = ky/dy/dy;
   realtype c3 = -TWO*(c1 + c2);
-  long int i, j;
+  sunindextype i, j;
   for (j=1; j<nyl-1; j++)                        // diffusive terms
     for (i=1; i<nxl-1; i++)
       Ydot[IDX(i,j,nxl)] = c1*(Y[IDX(i-1,j,nxl)] + Y[IDX(i+1,j,nxl)])
@@ -423,29 +442,28 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 
 // Preconditioner setup routine (fills inverse of Jacobian diagonal)
 static int PSet(realtype t, N_Vector y, N_Vector fy, booleantype jok, 
-		booleantype *jcurPtr, realtype gamma, void *user_data,
-		N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+		booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   UserData *udata = (UserData *) user_data;      // variable shortcuts 
   realtype kx = udata->kx;
   realtype ky = udata->ky;
   realtype dx = udata->dx;
   realtype dy = udata->dy;
-  realtype *diag = N_VGetArrayPointer(tmp1);  // access data arrays 
+  realtype *diag = N_VGetArrayPointer(udata->d);  // access data arrays 
   if (check_flag((void *) diag, "N_VGetArrayPointer", 0)) return -1;
 
-  // set all entries of tmp1 to the diagonal values of interior
+  // set all entries of d to the diagonal values of interior
   // (since boundary RHS is 0, set boundary diagonals to the same)
   realtype c = ONE + gamma*TWO*(kx/dx/dx + ky/dy/dy);
-  N_VConst(c, tmp1);
-  N_VInv(tmp1, udata->d);      // set d to inverse of diagonal
+  N_VConst(c, udata->d);
+  N_VInv(udata->d, udata->d);  // invert diagonal
   return 0;                    // Return with success 
 }
 
 // Preconditioner solve routine
 static int PSol(realtype t, N_Vector y, N_Vector fy, N_Vector r, 
 		N_Vector z, realtype gamma, realtype delta, int lr, 
-		void *user_data, N_Vector tmp)
+		void *user_data)
 {
   UserData *udata = (UserData *) user_data;  // access user_data structure
   N_VProd(r, udata->d, z);                   // perform Jacobi iteration
diff --git a/examples/arkode/CXX_parallel/ark_heat2D.out b/examples/arkode/CXX_parallel/ark_heat2D.out
index dc415b3..ffa0718 100644
--- a/examples/arkode/CXX_parallel/ark_heat2D.out
+++ b/examples/arkode/CXX_parallel/ark_heat2D.out
@@ -39,11 +39,11 @@ Final Solver Statistics:
    Internal solver steps = 51 (attempted = 51)
    Total RHS evals:  Fe = 0,  Fi = 514
    Total linear solver setups = 18
-   Total linear iterations = 4094
-   Total number of Jacobian-vector products = 4094
+   Total linear iterations = 4451
+   Total number of Jacobian-vector products = 4451
    Total number of Preconditioner setups = 1
-   Total number of Preconditioner solves = 4237
-   Total number of linear solver convergence failures = 143
+   Total number of Preconditioner solves = 4666
+   Total number of linear solver convergence failures = 215
    Total number of Newton iterations = 255
    Total number of nonlinear solver convergence failures = 0
    Total number of error test failures = 0
diff --git a/examples/arkode/CXX_serial/CMakeLists.txt b/examples/arkode/CXX_serial/CMakeLists.txt
index 8ebc0f3..c16e8a4 100644
--- a/examples/arkode/CXX_serial/CMakeLists.txt
+++ b/examples/arkode/CXX_serial/CMakeLists.txt
@@ -1,5 +1,6 @@
 # ---------------------------------------------------------------
-# Programmer:  Daniel R. Reynolds @ SMU
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
 # Copyright (c) 2015, Southern Methodist University and 
@@ -17,79 +18,226 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for ARKODE serial examples
+# ---------------------------------------------------------------
 
-# Add variable ARKODE_examples with the names of the serial ARKODE examples
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS linear solvers
 SET(ARKODE_examples
-  ark_analytic_sys
+  "ark_analytic_sys\;develop"
   )
 
-# Add variable ARKODE_examples_BL with the names of the serial ARKODE examples
-# that use Lapack
-
+# Examples using LAPACK linear solvers
 SET(ARKODE_examples_BL
   )
 
-# Add variable ARKODE_extras with the names of auxiliary files to install
+# Examples using KLU linear solver
+SET(ARKODE_examples_KLU
+  )
+
+# Examples using SuperLU_MT linear solver
+SET(ARKODE_examples_SUPERLUMT
+  )
 
+# Auxiliary files to install
 SET(ARKODE_extras
   plot_sol.py
   )
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${ARKODE_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${ARKODE_examples})
 
-# Add the build and install targets for each ARKODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${ARKODE_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.cpp)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.cpp ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${ARKODE_examples})
+    INSTALL(FILES ${example}.cpp ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${ARKODE_examples})
 
-# Add the build and install targets for each Lapack ARKODE example (if needed)
 
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${ARKODE_examples_BL})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${ARKODE_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.cpp)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.cpp ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${ARKODE_examples_BL})
+      INSTALL(FILES ${example}.cpp ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${ARKODE_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
+
+# Add the build and install targets for each KLU example (if needed)
+IF(KLU_FOUND)
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${ARKODE_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.cpp)
+
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+    # install example source and out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${ARKODE_examples_KLU})
+
+ENDIF(KLU_FOUND)
+
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
+IF(SUPERLUMT_FOUND)
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${ARKODE_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.cpp)
+
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+    # install example source and out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/CXX_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${ARKODE_examples_SUPERLUMT})
+
+ENDIF(SUPERLUMT_FOUND)
+
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -103,12 +251,26 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
-  LIST2STRING(ARKODE_examples EXAMPLES)
+
+  EXAMPLES2STRING(ARKODE_examples EXAMPLES)
+
   IF(LAPACK_FOUND)
-    LIST2STRING(ARKODE_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(ARKODE_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
+
+  IF(KLU_FOUND)
+    EXAMPLES2STRING(ARKODE_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
+
+  IF(SUPERLUMT_FOUND)
+    EXAMPLES2STRING(ARKODE_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -116,10 +278,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_CXX_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/CXX_serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_CXX_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/CXX_serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/arkode/CXX_serial/README b/examples/arkode/CXX_serial/README
index 7f114b2..bfb7f41 100644
--- a/examples/arkode/CXX_serial/README
+++ b/examples/arkode/CXX_serial/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/CXX_serial/ark_analytic_sys.cpp b/examples/arkode/CXX_serial/ark_analytic_sys.cpp
index f9779e0..ff6bfc2 100644
--- a/examples/arkode/CXX_serial/ark_analytic_sys.cpp
+++ b/examples/arkode/CXX_serial/ark_analytic_sys.cpp
@@ -38,7 +38,7 @@
  * In this example, we choose lamda = -100.
  * 
  * This program solves the problem with the DIRK method,
- * Newton iteration with the ARKDENSE dense linear solver, and a
+ * Newton iteration with the dense linear solver, and a
  * user-supplied Jacobian routine.
  * Output is printed every 1.0 units of time (10 total).
  * Run statistics (optional outputs) are printed at the end.
@@ -49,22 +49,32 @@
 #include <iostream>
 #include <string.h>
 #include <math.h>
-#include <arkode/arkode.h>            // prototypes for ARKode fcts., consts.
-#include <nvector/nvector_serial.h>   // serial N_Vector types, fcts., macros
-#include <arkode/arkode_dense.h>      // prototype for ARKDense solver
-#include <sundials/sundials_dense.h>  // defs. of DlsMat and DENSE_ELEM
-#include <sundials/sundials_types.h>  // def. of type 'realtype'
+#include <arkode/arkode.h>              // prototypes for ARKode fcts., consts.
+#include <nvector/nvector_serial.h>     // access to serial N_Vector
+#include <sunmatrix/sunmatrix_dense.h>  // access to dense SUNMatrix 
+#include <sunlinsol/sunlinsol_dense.h>  // access to dense SUNLinearSolver
+#include <arkode/arkode_direct.h>       // access to ARKDls interface
+#include <sundials/sundials_types.h>    // def. of type 'realtype'
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 using namespace std;
 
 // User-supplied Functions Called by the Solver
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 // Private function to perform matrix-matrix product
-static int dense_MM(DlsMat A, DlsMat B, DlsMat C);
+static int dense_MM(SUNMatrix A, SUNMatrix B, SUNMatrix C);
 
 // Private function to check function return values
 static int check_flag(void *flagvalue, const string funcname, int opt);
@@ -73,17 +83,19 @@ static int check_flag(void *flagvalue, const string funcname, int opt);
 int main()
 {
   // general problem parameters
-  realtype T0 = RCONST(0.0);       // initial time
-  realtype Tf = RCONST(0.05);      // final time
-  realtype dTout = RCONST(0.005);  // time between outputs
-  long int NEQ = 3;                // number of dependent vars.
-  realtype reltol = 1.0e-6;        // tolerances
-  realtype abstol = 1.0e-10;
-  realtype lamda  = -100.0;        // stiffness parameter
+  realtype T0 = RCONST(0.0);         // initial time
+  realtype Tf = RCONST(0.05);        // final time
+  realtype dTout = RCONST(0.005);    // time between outputs
+  sunindextype NEQ = 3;              // number of dependent vars.
+  realtype reltol = RCONST(1.0e-6);  // tolerances
+  realtype abstol = RCONST(1.0e-10);
+  realtype lamda  = RCONST(-100.0);  // stiffness parameter
 
   // general problem variables
   int flag;                      // reusable error-checking flag
   N_Vector y = NULL;             // empty vector for storing solution
+  SUNMatrix A = NULL;            // empty dense matrix for solver
+  SUNLinearSolver LS = NULL;     // empty dense linear solver
   void *arkode_mem = NULL;       // empty ARKode memory structure
 
   // Initial problem output
@@ -92,15 +104,23 @@ int main()
   cout << "   reltol = " << reltol << "\n";
   cout << "   abstol = " << abstol << "\n\n";
 
-  // Initialize data structures
-  y = N_VNew_Serial(NEQ);         // Create serial vector solution
+  // Initialize vector data structure and specify initial condition
+  y = N_VNew_Serial(NEQ);
   if (check_flag((void *)y, "N_VNew_Serial", 0)) return 1;
-  NV_Ith_S(y,0) = 1.0;            // Specify initial condition
+  NV_Ith_S(y,0) = 1.0;
   NV_Ith_S(y,1) = 1.0;
   NV_Ith_S(y,2) = 1.0;
-  arkode_mem = ARKodeCreate();    // Create the solver memory
-  if (check_flag((void *)arkode_mem, "ARKodeCreate", 0)) return 1;
 
+  // Initialize dense matrix data structure and solver
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)A, "SUNDenseMatrix", 0)) return 1;
+  LS = SUNDenseLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return 1;
+
+  // Create the ARKode memory structure
+  arkode_mem = ARKodeCreate();
+  if (check_flag((void *)arkode_mem, "ARKodeCreate", 0)) return 1;
+  
   /* Call ARKodeInit to initialize the integrator memory and specify the
      right-hand side function in y'=f(t,y), the inital time T0, and
      the initial dependent variable vector y.  Note: since this
@@ -114,11 +134,11 @@ int main()
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);   // Specify tolerances
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  // Linear solver specification
-  flag = ARKDense(arkode_mem, NEQ);              // Specify dense linear solver
-  if (check_flag(&flag, "ARKDense", 1)) return 1;
-  flag = ARKDlsSetDenseJacFn(arkode_mem, Jac);   // Set Jacobian routine
-  if (check_flag(&flag, "ARKDlsSetDenseJacFn", 1)) return 1;
+  // Linear solver interface
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);         // Attach matrix and linear solver
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                  // Set Jacobian routine
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
 
   // Specify linearly implicit RHS, with non-time-dependent Jacobian
   flag = ARKodeSetLinear(arkode_mem, 0);
@@ -129,7 +149,7 @@ int main()
   fprintf(UFID,"# t y1 y2 y3\n");
 
   // output initial condition to disk 
-  fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+  fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	  T0, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
@@ -140,16 +160,16 @@ int main()
   cout << "   --------------------------------------\n";
   while (Tf - t > 1.0e-15) {
 
-    flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);       // call integrator
+    flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);           // call integrator
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %8.4f  %8.5f  %8.5f  %8.5f\n",                  // access/print solution
+    printf("  %8.4"FSYM"  %8.5"FSYM"  %8.5"FSYM"  %8.5"FSYM"\n",  // access/print solution
            t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));
-    fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+    fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	    t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
-    if (flag >= 0) {                                          // successful solve: update time
+    if (flag >= 0) {                                              // successful solve: update time
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
-    } else {                                                  // unsuccessful solve: break
+    } else {                                                      // unsuccessful solve: break
       fprintf(stderr,"Solver failure, stopping integration\n");
       break;
     }
@@ -189,8 +209,10 @@ int main()
   cout << "   Total number of error test failures = " << netf << "\n\n";
 
   // Clean up and return with successful completion
-  N_VDestroy_Serial(y);        // Free y vector
   ARKodeFree(&arkode_mem);     // Free integrator memory
+  SUNLinSolFree(LS);           // Free linear solver
+  SUNMatDestroy(A);            // Free A matrix
+  N_VDestroy(y);               // Free y vector
   return 0;
 }
 
@@ -226,47 +248,48 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 }
 
 // Jacobian routine to compute J(t,y) = df/dy.
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector y, N_Vector fy,
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *rdata = (realtype *) user_data;   // cast user_data to realtype
   realtype lam = rdata[0];                    // set shortcut for stiffness parameter
-  DlsMat V  = NewDenseMat(3,3);               // create temporary DlsMat objects
-  DlsMat D  = NewDenseMat(3,3);
-  DlsMat Vi = NewDenseMat(3,3);
+  SUNMatrix V  = SUNDenseMatrix(3,3);          // create temporary SUNMatrix objects
+  SUNMatrix D  = SUNDenseMatrix(3,3);          // create temporary SUNMatrix objects
+  SUNMatrix Vi = SUNDenseMatrix(3,3);          // create temporary SUNMatrix objects
+  sunindextype N = SUNDenseMatrix_Rows(J);
 
-  DenseScale(0.0, V);     // initialize temporary matrices to zero
-  DenseScale(0.0, D);
-  DenseScale(0.0, Vi);
+  SUNMatZero(V);        // initialize temporary matrices to zero
+  SUNMatZero(D);        // (not technically required)
+  SUNMatZero(Vi);
 
   // Fill in temporary matrices:
   //    V = [1 -1 1; -1 2 1; 0 -1 2]
-  DENSE_ELEM(V,0,0) =  1.0;
-  DENSE_ELEM(V,0,1) = -1.0;
-  DENSE_ELEM(V,0,2) =  1.0;
-  DENSE_ELEM(V,1,0) = -1.0;
-  DENSE_ELEM(V,1,1) =  2.0;
-  DENSE_ELEM(V,1,2) =  1.0;
-  DENSE_ELEM(V,2,0) =  0.0;
-  DENSE_ELEM(V,2,1) = -1.0;
-  DENSE_ELEM(V,2,2) =  2.0;
+  SM_ELEMENT_D(V,0,0) =  1.0;
+  SM_ELEMENT_D(V,0,1) = -1.0;
+  SM_ELEMENT_D(V,0,2) =  1.0;
+  SM_ELEMENT_D(V,1,0) = -1.0;
+  SM_ELEMENT_D(V,1,1) =  2.0;
+  SM_ELEMENT_D(V,1,2) =  1.0;
+  SM_ELEMENT_D(V,2,0) =  0.0;
+  SM_ELEMENT_D(V,2,1) = -1.0;
+  SM_ELEMENT_D(V,2,2) =  2.0;
 
   //    Vi = 0.25*[5 1 -3; 2 2 -2; 1 1 1]
-  DENSE_ELEM(Vi,0,0) =  0.25*5.0;
-  DENSE_ELEM(Vi,0,1) =  0.25*1.0;
-  DENSE_ELEM(Vi,0,2) = -0.25*3.0;
-  DENSE_ELEM(Vi,1,0) =  0.25*2.0;
-  DENSE_ELEM(Vi,1,1) =  0.25*2.0;
-  DENSE_ELEM(Vi,1,2) = -0.25*2.0;
-  DENSE_ELEM(Vi,2,0) =  0.25*1.0;
-  DENSE_ELEM(Vi,2,1) =  0.25*1.0;
-  DENSE_ELEM(Vi,2,2) =  0.25*1.0;
+  SM_ELEMENT_D(Vi,0,0) =  0.25*5.0;
+  SM_ELEMENT_D(Vi,0,1) =  0.25*1.0;
+  SM_ELEMENT_D(Vi,0,2) = -0.25*3.0;
+  SM_ELEMENT_D(Vi,1,0) =  0.25*2.0;
+  SM_ELEMENT_D(Vi,1,1) =  0.25*2.0;
+  SM_ELEMENT_D(Vi,1,2) = -0.25*2.0;
+  SM_ELEMENT_D(Vi,2,0) =  0.25*1.0;
+  SM_ELEMENT_D(Vi,2,1) =  0.25*1.0;
+  SM_ELEMENT_D(Vi,2,2) =  0.25*1.0;
 
   //    D = [-0.5 0 0; 0 -0.1 0; 0 0 lam]
-  DENSE_ELEM(D,0,0) = -0.5;
-  DENSE_ELEM(D,1,1) = -0.1;
-  DENSE_ELEM(D,2,2) = lam;
+  SM_ELEMENT_D(D,0,0) = -0.5;
+  SM_ELEMENT_D(D,1,1) = -0.1;
+  SM_ELEMENT_D(D,2,2) = lam;
 
   // Compute J = V*D*Vi
   if (dense_MM(D,Vi,J) != 0) {     // J = D*Vi
@@ -277,7 +300,7 @@ static int Jac(long int N, realtype t,
     cerr << "matmul error\n";
     return 1;
   }
-  DenseCopy(D, J);                 // J = D [= V*D*Vi]
+  SUNMatCopy(D, J);
 
   return 0;                        // Return with success
 }
@@ -286,29 +309,31 @@ static int Jac(long int N, realtype t,
  * Private helper functions
  *-------------------------------*/
 
-// DlsMat matrix-multiply utility routine: C = A*B.
-static int dense_MM(DlsMat A, DlsMat B, DlsMat C)
+// SUNDenseMatrix matrix-multiply utility routine: C = A*B.
+static int dense_MM(SUNMatrix A, SUNMatrix B, SUNMatrix C)
 {
   // check for legal dimensions
-  if ((A->N != B->M) || (C->M != A->M) || (C->N != B->N)) {
+  if ( (SUNDenseMatrix_Columns(A) != SUNDenseMatrix_Rows(B)) ||
+       (SUNDenseMatrix_Rows(C) != SUNDenseMatrix_Rows(A)) ||
+       (SUNDenseMatrix_Columns(C) != SUNDenseMatrix_Columns(B)) ) {
     cerr << "\n matmul error: dimension mismatch\n\n";
     return 1;
   }
 
-  realtype **adata = A->cols;     // access data and extents
-  realtype **bdata = B->cols;
-  realtype **cdata = C->cols;
-  long int m = C->M;
-  long int n = C->N;
-  long int l = A->N;
-  int i, j, k;
-  DenseScale(0.0, C);             // initialize output
+  realtype **adata = SUNDenseMatrix_Cols(A);     // access data and extents
+  realtype **bdata = SUNDenseMatrix_Cols(B);
+  realtype **cdata = SUNDenseMatrix_Cols(C);
+  sunindextype m = SUNDenseMatrix_Rows(C);
+  sunindextype n = SUNDenseMatrix_Columns(C);
+  sunindextype l = SUNDenseMatrix_Columns(A);
+  sunindextype i, j, k;
+  SUNMatZero(C);                                 // initialize output
 
   // perform multiply (not optimal, but fine for 3x3 matrices)
   for (i=0; i<m; i++)
     for (j=0; j<n; j++)
       for (k=0; k<l; k++)
-     cdata[i][j] += adata[i][k] * bdata[k][j];
+        cdata[i][j] += adata[i][k] * bdata[k][j];
 
   return 0;                       // Return with success
 }
diff --git a/examples/arkode/CXX_serial/ark_analytic_sys.out b/examples/arkode/CXX_serial/ark_analytic_sys.out
index 858d646..76110a1 100644
--- a/examples/arkode/CXX_serial/ark_analytic_sys.out
+++ b/examples/arkode/CXX_serial/ark_analytic_sys.out
@@ -6,25 +6,25 @@ Analytical ODE test problem:
 
       t        y0        y1        y2
    --------------------------------------
-    0.0050   0.70327   0.70627   0.41004
-    0.0100   0.52267   0.52865   0.05231
-    0.0150   0.41249   0.42145  -0.16456
-    0.0200   0.34504   0.35696  -0.29600
-    0.0250   0.30349   0.31838  -0.37563
-    0.0300   0.27767   0.29551  -0.42383
-    0.0350   0.26138   0.28216  -0.45296
-    0.0400   0.25088   0.27459  -0.47053
-    0.0450   0.24389   0.27053  -0.48109
-    0.0500   0.23903   0.26858  -0.48740
+    0.0050   0.70360   0.70658   0.41068
+    0.0100   0.52305   0.52902   0.05307
+    0.0150   0.41276   0.42171  -0.16403
+    0.0200   0.34525   0.35717  -0.29559
+    0.0250   0.30366   0.31854  -0.37531
+    0.0300   0.27780   0.29563  -0.42358
+    0.0350   0.26149   0.28226  -0.45275
+    0.0400   0.25097   0.27467  -0.47037
+    0.0450   0.24396   0.27058  -0.48097
+    0.0500   0.23909   0.26863  -0.48730
    --------------------------------------
 
 Final Solver Statistics:
-   Internal solver steps = 91 (attempted = 93)
-   Total RHS evals:  Fe = 0,  Fi = 934
-   Total linear solver setups = 12
+   Internal solver steps = 69 (attempted = 71)
+   Total RHS evals:  Fe = 0,  Fi = 714
+   Total linear solver setups = 20
    Total RHS evals for setting up the linear system = 0
-   Total number of Jacobian evaluations = 4
-   Total number of Newton iterations = 465
+   Total number of Jacobian evaluations = 3
+   Total number of Newton iterations = 355
    Total number of linear solver convergence failures = 0
    Total number of error test failures = 2
 
diff --git a/examples/arkode/C_openmp/CMakeLists.txt b/examples/arkode/C_openmp/CMakeLists.txt
index 788f249..75d79db 100644
--- a/examples/arkode/C_openmp/CMakeLists.txt
+++ b/examples/arkode/C_openmp/CMakeLists.txt
@@ -2,13 +2,13 @@
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,64 +17,79 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for ARKODE OpenMP examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if OpenMP is enabled
 IF(OPENMP_FOUND)
 
-# Add variable ARKode_examples_OMP with the names of the openmp ARKode examples
-SET(ARKODE_examples_OMP
-  ark_brusselator1D_omp
-  )
+  # Examples using SUNDIALS linear solvers
+  SET(ARKODE_examples
+    "ark_brusselator1D_omp\;4\;develop"
+    )
 
-# Add variable ARKODE_extras_OMP with the names of auxiliary files to install
-SET(ARKODE_extras_OMP
-  plot_brusselator1D.py
-  )
+  # Auxiliary files to install
+  SET(ARKODE_extras_OMP
+    plot_brusselator1D.py
+    )
 
 ENDIF(OPENMP_FOUND)
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECOMP_LIB sundials_nvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECOMP_LIB sundials_nvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${ARKODE_LIB} ${NVECOMP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # update the compilation flags to include OpenMP support
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 
+
 # Add the build and install targets for each ARKODE example
-FOREACH(example ${ARKODE_examples_OMP})
+FOREACH(example_tuple ${ARKODE_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} TEST_ARGS 4)
+
+  # add to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    TEST_ARGS ${example_args}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${ARKODE_examples_OMP})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_openmp)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${ARKODE_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -83,36 +98,33 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${ARKODE_extras_OMP})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_openmp)
-  ENDFOREACH(extrafile ${ARKODE_extras_OMP})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
-  LIST2STRING(ARKODE_examples_OMP EXAMPLES)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
 
+  EXAMPLES2STRING(ARKODE_examples EXAMPLES)
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/C_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/C_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/C_openmp/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_openmp 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_openmp
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -124,7 +136,7 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/arkode/C_openmp/Makefile_ex 
+      FILES ${PROJECT_BINARY_DIR}/examples/arkode/C_openmp/Makefile_ex
       DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_openmp
       RENAME Makefile
       )
diff --git a/examples/arkode/C_openmp/README b/examples/arkode/C_openmp/README
index 4b4d911..3d52ea9 100644
--- a/examples/arkode/C_openmp/README
+++ b/examples/arkode/C_openmp/README
@@ -13,7 +13,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -24,7 +23,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -38,7 +40,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/C_openmp/ark_brusselator1D_omp.c b/examples/arkode/C_openmp/ark_brusselator1D_omp.c
index cac3dea..98cc72b 100644
--- a/examples/arkode/C_openmp/ark_brusselator1D_omp.c
+++ b/examples/arkode/C_openmp/ark_brusselator1D_omp.c
@@ -39,7 +39,7 @@
  * on a uniform spatial grid.
  *
  * This program solves the problem with the DIRK method, using a
- * Newton iteration with the ARKBAND band linear solver, and a
+ * Newton iteration with the band linear solver, and a
  * user-supplied Jacobian routine.  This example uses the OpenMP 
  * vector kernel, and employs OpenMP threading within the 
  * right-hand side and Jacobian construction functions.
@@ -53,41 +53,52 @@
 #include <stdlib.h>
 #include <math.h>
 #include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
-#include <nvector/nvector_openmp.h>   /* OpenMP N_Vector types, fcts., macros */
-#include <arkode/arkode_band.h>       /* prototype for ARKBand solver */
+#include <nvector/nvector_openmp.h>   /* access to OpenMP N_Vector */
+#include <sunmatrix/sunmatrix_band.h> /* access to band SUNMatrix */
+#include <sunlinsol/sunlinsol_band.h> /* access to band SUNLinearSolver */
+#include <arkode/arkode_direct.h>     /* access to ARKDls interface */
 #include <sundials/sundials_types.h>  /* def. of type 'realtype' */
 #include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc. */
 #ifdef _OPENMP
 #include <omp.h>                      /* OpenMP functions */
 #endif
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
 /* accessor macros between (x,v) location and 1D NVector array */
 #define IDX(x,v) (3*(x)+v)
 
 /* user data structure */
 typedef struct {  
-  long int N;    /* number of intervals      */
-  int nthreads;  /* number of OpenMP threads */
-  realtype dx;   /* mesh spacing             */
-  realtype a;    /* constant forcing on u    */
-  realtype b;    /* steady-state value of w  */
-  realtype du;   /* diffusion coeff for u    */
-  realtype dv;   /* diffusion coeff for v    */
-  realtype dw;   /* diffusion coeff for w    */
-  realtype ep;   /* stiffness parameter      */
+  sunindextype N;  /* number of intervals      */
+  int nthreads;    /* number of OpenMP threads */
+  realtype dx;     /* mesh spacing             */
+  realtype a;      /* constant forcing on u    */
+  realtype b;      /* steady-state value of w  */
+  realtype du;     /* diffusion coeff for u    */
+  realtype dv;     /* diffusion coeff for v    */
+  realtype dw;     /* diffusion coeff for w    */
+  realtype ep;     /* stiffness parameter      */
 } *UserData;
 
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector y, N_Vector fy, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private helper functions  */
-static int LaplaceMatrix(realtype c, DlsMat Jac, UserData udata);
-static int ReactionJac(realtype c, N_Vector y, DlsMat Jac, UserData udata);
+static int LaplaceMatrix(realtype c, SUNMatrix Jac, UserData udata);
+static int ReactionJac(realtype c, N_Vector y, SUNMatrix Jac, UserData udata);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -102,7 +113,7 @@ int main(int argc, char *argv[])
   int Nvar = 3;                 /* number of solution fields */
   UserData udata = NULL;
   realtype *data;
-  long int N = 201;             /* spatial mesh size */
+  sunindextype N = 201;         /* spatial mesh size */
   realtype a = 0.6;             /* problem parameters */
   realtype b = 2.0;
   realtype du = 0.025;
@@ -111,7 +122,7 @@ int main(int argc, char *argv[])
   realtype ep = 1.0e-5;         /* stiffness parameter */
   realtype reltol = 1.0e-6;     /* tolerances */
   realtype abstol = 1.0e-10;
-  long int NEQ, i;
+  sunindextype NEQ, i;
 
   /* general problem variables */
   int flag;                     /* reusable error-checking flag */
@@ -119,6 +130,8 @@ int main(int argc, char *argv[])
   N_Vector umask = NULL;        /* empty mask vectors for viewing solution components */
   N_Vector vmask = NULL;
   N_Vector wmask = NULL;
+  SUNMatrix A = NULL;           /* empty matrix for linear solver */
+  SUNLinearSolver LS = NULL;    /* empty linear solver structure */
   void *arkode_mem = NULL;      /* empty ARKode memory structure */
   realtype pi, t, dTout, tout, u, v, w;
   FILE *FID, *UFID, *VFID, *WFID;
@@ -130,11 +143,11 @@ int main(int argc, char *argv[])
   if (check_flag((void *) udata, "malloc", 2)) return 1;
 
   /* set the number of threads to use */
-  num_threads = 1; /* default value */
+  num_threads = 1;                       /* default value */
 #ifdef _OPENMP
   num_threads = omp_get_max_threads();   /* overwrite with OMP_NUM_THREADS environment variable */
 #endif
-  if (argc > 1)   /* overwrite with command line value, if supplied */
+  if (argc > 1)                          /* overwrite with command line value, if supplied */
     num_threads = strtol(argv[1], NULL, 0);
 
   /* store the inputs in the UserData structure */
@@ -152,15 +165,15 @@ int main(int argc, char *argv[])
 
   /* Initial problem output */
   printf("\n1D Brusselator PDE test problem:\n");
-  printf("    N = %li,  NEQ = %li\n", udata->N, NEQ);
+  printf("    N = %li,  NEQ = %li\n", (long int) udata->N, (long int) NEQ);
   printf("    num_threads = %i\n", num_threads);
-  printf("    problem parameters:  a = %g,  b = %g,  ep = %g\n",
+  printf("    problem parameters:  a = %"GSYM",  b = %"GSYM",  ep = %"GSYM"\n",
 	 udata->a, udata->b, udata->ep);
-  printf("    diffusion coefficients:  du = %g,  dv = %g,  dw = %g\n", 
+  printf("    diffusion coefficients:  du = %"GSYM",  dv = %"GSYM",  dw = %"GSYM"\n", 
 	 udata->du, udata->dv, udata->dw);
-  printf("    reltol = %.1e,  abstol = %.1e\n\n", reltol, abstol);
+  printf("    reltol = %.1"ESYM",  abstol = %.1"ESYM"\n\n", reltol, abstol);
 
-  /* Initialize data structures */
+  /* Initialize vector data structures */
   y = N_VNew_OpenMP(NEQ, num_threads);      /* Create vector for solution */
   if (check_flag((void *)y, "N_VNew_OpenMP", 0)) return 1;
   udata->dx = RCONST(1.0)/(N-1);            /* set spatial mesh spacing */
@@ -197,6 +210,12 @@ int main(int argc, char *argv[])
   if (check_flag((void *) data, "N_VGetArrayPointer", 0)) return 1;
   for (i=0; i<N; i++)  data[IDX(i,2)] = RCONST(1.0);
 
+  /* Initialize matrix and linear solver data structures */
+  A = SUNBandMatrix(NEQ, 4, 4, 8);
+  if (check_flag((void *)A, "SUNBandMatrix", 0)) return 1;
+  LS = SUNBandLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNBandLinearSolver", 0)) return 1;
+  
   /* Create the solver memory */
   arkode_mem = ARKodeCreate();
   if (check_flag((void *)arkode_mem, "ARKodeCreate", 0)) return 1;
@@ -215,14 +234,14 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
   /* Linear solver specification */
-  flag = ARKBand(arkode_mem, NEQ, 4, 4);          /* Specify the band linear solver */
-  if (check_flag(&flag, "ARKBand", 1)) return 1;
-  flag = ARKDlsSetBandJacFn(arkode_mem, Jac);     /* Set the Jacobian routine */
-  if (check_flag(&flag, "ARKDlsSetBandJacFn", 1)) return 1;
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);          /* Attach matrix and linear solver */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                   /* Set the Jacobian routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
 
   /* output spatial mesh to disk */
   FID=fopen("bruss_mesh.txt","w");
-  for (i=0; i<N; i++)  fprintf(FID,"  %.16e\n", udata->dx*i);
+  for (i=0; i<N; i++)  fprintf(FID,"  %.16"ESYM"\n", udata->dx*i);
   fclose(FID);
   
   /* Open output stream for results, access data arrays */
@@ -233,9 +252,9 @@ int main(int argc, char *argv[])
   /* output initial condition to disk */
   data = N_VGetArrayPointer(y);
   if (check_flag((void *)data, "N_VGetArrayPointer", 0)) return 1;
-  for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-  for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-  for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+  for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM, data[IDX(i,0)]);
+  for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM, data[IDX(i,1)]);
+  for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM, data[IDX(i,2)]);
   fprintf(UFID,"\n");
   fprintf(VFID,"\n");
   fprintf(WFID,"\n");
@@ -257,7 +276,7 @@ int main(int argc, char *argv[])
     v = SUNRsqrt(v*v/N);
     w = N_VWL2Norm(y,wmask);
     w = SUNRsqrt(w*w/N);
-    printf("  %10.6f  %10.6f  %10.6f  %10.6f\n", t, u, v, w);
+    printf("  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"\n", t, u, v, w);
     if (flag >= 0) {                                       /* successful solve: update output time */
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -267,9 +286,9 @@ int main(int argc, char *argv[])
     }
 
     /* output results to disk */
-    for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-    for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-    for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+    for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM, data[IDX(i,0)]);
+    for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM, data[IDX(i,1)]);
+    for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM, data[IDX(i,2)]);
     fprintf(UFID,"\n");
     fprintf(VFID,"\n");
     fprintf(WFID,"\n");
@@ -310,12 +329,14 @@ int main(int argc, char *argv[])
   printf("   Total number of error test failures = %li\n\n", netf);
 
   /* Clean up and return with successful completion */
+  free(udata);                  /* Free user data */
+  ARKodeFree(&arkode_mem);      /* Free integrator memory */
+  SUNLinSolFree(LS);            /* Free linear solver */
+  SUNMatDestroy(A);             /* Free matrix */
   N_VDestroy_OpenMP(y);         /* Free vectors */
   N_VDestroy_OpenMP(umask);
   N_VDestroy_OpenMP(vmask);
   N_VDestroy_OpenMP(wmask);
-  free(udata);                  /* Free user data */
-  ARKodeFree(&arkode_mem);      /* Free integrator memory */
   return 0;
 }
 
@@ -327,7 +348,7 @@ int main(int argc, char *argv[])
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
   UserData udata = (UserData) user_data;      /* access problem data */
-  long int N  = udata->N;                     /* set variable shortcuts */
+  sunindextype N = udata->N;                  /* set variable shortcuts */
   realtype a  = udata->a;
   realtype b  = udata->b;
   realtype ep = udata->ep;
@@ -337,7 +358,7 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   realtype dx = udata->dx;
   realtype *Ydata=NULL, *dYdata=NULL;
   realtype uconst, vconst, wconst, u, ul, ur, v, vl, vr, w, wl, wr;
-  long int i;
+  sunindextype i;
 
   /* clear out ydot (to be careful) */
   N_VConst(0.0, ydot);
@@ -380,13 +401,12 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
-static int Jac(long int M, long int mu, long int ml,
-               realtype t, N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector y, N_Vector fy, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
-  UserData udata = (UserData) user_data;     /* access problem data */
-  SetToZero(J);                              /* Initialize Jacobian to zero */
+  UserData udata = (UserData) user_data;  /* access problem data */
+  SUNMatZero(J);                          /* Initialize Jacobian to zero */
 
   /* Fill in the Laplace matrix */
   if (LaplaceMatrix(RCONST(1.0), J, udata)) {
@@ -409,26 +429,29 @@ static int Jac(long int M, long int mu, long int ml,
 
 /* Routine to compute the stiffness matrix from (L*y), scaled by the factor c.
    We add the result into Jac and do not erase what was already there */
-static int LaplaceMatrix(realtype c, DlsMat Jac, UserData udata)
+static int LaplaceMatrix(realtype c, SUNMatrix Jac, UserData udata)
 {
-  long int i;                /* set shortcuts */
-  long int N = udata->N;
+  sunindextype N = udata->N;            /* set shortcuts */
   realtype dx = udata->dx;
+  sunindextype i;
+  realtype uconst = c*udata->du/dx/dx;
+  realtype vconst = c*udata->dv/dx/dx;
+  realtype wconst = c*udata->dw/dx/dx;
   
   /* iterate over intervals, filling in Jacobian entries */
 #pragma omp parallel for default(shared) private(i) schedule(static) num_threads(udata->nthreads)
   for (i=1; i<N-1; i++) {
 
     /* Jacobian of (L*y) at this node */
-    BAND_ELEM(Jac,IDX(i,0),IDX(i-1,0)) += c*udata->du/dx/dx;
-    BAND_ELEM(Jac,IDX(i,1),IDX(i-1,1)) += c*udata->dv/dx/dx;
-    BAND_ELEM(Jac,IDX(i,2),IDX(i-1,2)) += c*udata->dw/dx/dx;
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,0)) += -c*RCONST(2.0)*udata->du/dx/dx;
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,1)) += -c*RCONST(2.0)*udata->dv/dx/dx;
-    BAND_ELEM(Jac,IDX(i,2),IDX(i,2)) += -c*RCONST(2.0)*udata->dw/dx/dx;
-    BAND_ELEM(Jac,IDX(i,0),IDX(i+1,0)) += c*udata->du/dx/dx;
-    BAND_ELEM(Jac,IDX(i,1),IDX(i+1,1)) += c*udata->dv/dx/dx;
-    BAND_ELEM(Jac,IDX(i,2),IDX(i+1,2)) += c*udata->dw/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i-1,0)) += uconst;
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i-1,1)) += vconst;
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i-1,2)) += wconst;
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,0)) -= RCONST(2.0)*uconst;
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,1)) -= RCONST(2.0)*vconst;
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i,2)) -= RCONST(2.0)*wconst;
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i+1,0)) += uconst;
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i+1,1)) += vconst;
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i+1,2)) += wconst;
   }
 
   return 0;
@@ -438,12 +461,12 @@ static int LaplaceMatrix(realtype c, DlsMat Jac, UserData udata)
 
 /* Routine to compute the Jacobian matrix from R(y), scaled by the factor c.
    We add the result into Jac and do not erase what was already there */
-static int ReactionJac(realtype c, N_Vector y, DlsMat Jac, UserData udata)
+static int ReactionJac(realtype c, N_Vector y, SUNMatrix Jac, UserData udata)
 {
-  long int N  = udata->N;                      /* set shortcuts */
-  long int i;
-  realtype u, v, w;
+  sunindextype N = udata->N;                   /* set shortcuts */
   realtype ep = udata->ep;
+  sunindextype i;
+  realtype u, v, w;
   realtype *Ydata = N_VGetArrayPointer(y);     /* access solution array */
   if (check_flag((void *)Ydata, "N_VGetArrayPointer", 0)) return 1;
   
@@ -457,18 +480,18 @@ static int ReactionJac(realtype c, N_Vector y, DlsMat Jac, UserData udata)
     w = Ydata[IDX(i,2)];
 
     /* all vars wrt u */
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,0)) += c*(RCONST(2.0)*u*v-(w+RCONST(1.0)));
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,0)) += c*(w - RCONST(2.0)*u*v);
-    BAND_ELEM(Jac,IDX(i,2),IDX(i,0)) += c*(-w);
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,0)) += c*(RCONST(2.0)*u*v-(w+RCONST(1.0)));
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,0)) += c*(w - RCONST(2.0)*u*v);
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i,0)) += c*(-w);
 
     /* all vars wrt v */
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,1)) += c*(u*u);
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,1)) += c*(-u*u);
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,1)) += c*(u*u);
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,1)) += c*(-u*u);
 
     /* all vars wrt w */
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,2)) += c*(-u);
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,2)) += c*(u);
-    BAND_ELEM(Jac,IDX(i,2),IDX(i,2)) += c*(-RCONST(1.0)/ep - u);
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,2)) += c*(-u);
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,2)) += c*(u);
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i,2)) += c*(-RCONST(1.0)/ep - u);
 
   }
 
diff --git a/examples/arkode/C_parallel/CMakeLists.txt b/examples/arkode/C_parallel/CMakeLists.txt
index 6d866f4..71074bc 100644
--- a/examples/arkode/C_parallel/CMakeLists.txt
+++ b/examples/arkode/C_parallel/CMakeLists.txt
@@ -2,13 +2,13 @@
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -19,16 +19,18 @@
 # For details, see the LICENSE file.
 # -----------------------------------------------------------------
 # CMakeLists.txt file for ARKODE parallel C examples
+# -----------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable ARKODE_examples with the names of the parallel ARKODE examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(ARKODE_examples
-  "ark_diurnal_kry_p\;1\;4"
-  "ark_diurnal_kry_bbd_p\;1\;4"
+  "ark_diurnal_kry_p\;1\;4\;develop"
+  "ark_diurnal_kry_bbd_p\;1\;4\;develop"
   )
 
-# Add variable ARKODE_extras with the names of auxiliary files to install
+# Auxiliary files to install
 SET(ARKODE_extras
   # none yet
   )
@@ -36,56 +38,67 @@ SET(ARKODE_extras
 # Check whether we use MPI compiler scripts.
 # If yes, then change the C compiler to the MPICC script.
 # If not, then add the MPI include directory for MPI headers.
+
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${ARKODE_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # Add the build and install targets for each ARKODE example
 FOREACH(example_tuple ${ARKODE_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPICC)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${ARKODE_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -99,31 +112,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
-  FOREACH(example_tuple ${ARKODE_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${ARKODE_examples})
 
+  EXAMPLES2STRING(ARKODE_examples EXAMPLES)
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/C_parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/C_parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/C_parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/arkode/C_parallel/README b/examples/arkode/C_parallel/README
index ea16e11..8db14fb 100644
--- a/examples/arkode/C_parallel/README
+++ b/examples/arkode/C_parallel/README
@@ -10,7 +10,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -21,7 +20,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -35,7 +37,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c b/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c
index 04f22db..f8abe8d 100644
--- a/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c
+++ b/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c
@@ -41,7 +41,7 @@
  * neq = 2*MX*MY.
  *
  * The solution is done with the DIRK/GMRES method (i.e. using the
- * ARKSPGMR linear solver) and a block-diagonal matrix with banded
+ * SUNSPGMR linear solver) and a block-diagonal matrix with banded
  * blocks as a preconditioner, using the ARKBBDPRE module.
  * Each block is generated using difference quotients, with
  * half-bandwidths mudq = mldq = 2*MXSUB, but the retained banded
@@ -61,13 +61,14 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
-#include <arkode/arkode.h>            /* prototypes for ARKODE fcts. */
-#include <arkode/arkode_spgmr.h>      /* prototypes and constants for ARKSPGMR */
-#include <arkode/arkode_bbdpre.h>     /* prototypes for ARKBBDPRE module */
-#include <nvector/nvector_parallel.h> /* def. of N_Vector, macro NV_DATA_P */
-#include <sundials/sundials_types.h>  /* definitions of realtype, booleantype */
-#include <sundials/sundials_math.h>   /* definition of macros SUNSQR and EXP */
-#include <mpi.h>                      /* MPI constants and types */
+#include <arkode/arkode.h>              /* prototypes for ARKODE fcts.      */
+#include <nvector/nvector_parallel.h>   /* access to MPI-parallel N_Vector  */
+#include <sunlinsol/sunlinsol_spgmr.h>  /* access to SPGMR SUNLinearSolver  */
+#include <arkode/arkode_spils.h>        /* access to ARKSpils interface     */
+#include <arkode/arkode_bbdpre.h>       /* access to ARKBBDPRE module       */
+#include <sundials/sundials_types.h>    /* SUNDIALS type definitions        */
+#include <sundials/sundials_math.h>     /* definition of macros SUNSQR, EXP */
+#include <mpi.h>                        /* MPI constants and types          */
 
 
 /* Problem Constants */
@@ -117,30 +118,30 @@ typedef struct {
   realtype q4, om, dx, dy, hdco, haco, vdco;
   realtype uext[NVARS*(MXSUB+2)*(MYSUB+2)];
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmxsub2, Nlocal;
+  sunindextype nvmxsub, nvmxsub2, Nlocal;
   MPI_Comm comm;
 } *UserData;
 
 /* Prototypes of private helper functions */
-static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+static void InitUserData(int my_pe, sunindextype local_N, MPI_Comm comm,
                          UserData data);
 static void SetInitialProfiles(N_Vector u, UserData data);
-static void PrintIntro(int npes, long int mudq, long int mldq,
-		       long int mukeep, long int mlkeep);
+static void PrintIntro(int npes, sunindextype mudq, sunindextype mldq,
+		       sunindextype mukeep, sunindextype mlkeep);
 static void PrintOutput(void *arkode_mem, int my_pe, MPI_Comm comm,
                         N_Vector u, realtype t);
 static void PrintFinalStats(void *arkode_mem);
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype uarray[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[]);
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[]);
 static void fucomm(realtype t, N_Vector u, void *user_data);
 
@@ -148,7 +149,7 @@ static void fucomm(realtype t, N_Vector u, void *user_data);
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
 /* Prototype of functions called by the ARKBBDPRE module */
-static int flocal(long int Nlocal, realtype t, N_Vector u,
+static int flocal(sunindextype Nlocal, realtype t, N_Vector u,
                   N_Vector udot, void *user_data);
 
 /* Private function to check function return values */
@@ -159,14 +160,16 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   UserData data;
+  SUNLinearSolver LS;
   void *arkode_mem;
   realtype abstol, reltol, t, tout;
   N_Vector u;
   int iout, my_pe, npes, flag, jpre;
-  long int neq, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype neq, local_N, mudq, mldq, mukeep, mlkeep;
   MPI_Comm comm;
 
   data = NULL;
+  LS = NULL;
   arkode_mem = NULL;
   u = NULL;
 
@@ -202,6 +205,11 @@ int main(int argc, char *argv[])
   abstol = ATOL;
   reltol = RTOL;
 
+  /* Create SPGMR solver structure -- use left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+  
   /* Call ARKodeCreate to create the solver memory */
   arkode_mem = ARKodeCreate();
   if(check_flag((void *)arkode_mem, "ARKodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
@@ -225,17 +233,16 @@ int main(int argc, char *argv[])
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);
   if (check_flag(&flag, "ARKodeSStolerances", 1, my_pe)) return(1);
 
-  /* Call ARKSpgmr to specify the linear solver ARKSPGMR with left
-     preconditioning and the default Krylov dimension maxl */
-  flag = ARKSpgmr(arkode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "ARKBBDSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Attach SPGMR solver structure to ARKSpils interface */
+  flag = ARKSpilsSetLinearSolver(arkode_mem, LS);
+  if (check_flag(&flag, "ARKSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Initialize BBD preconditioner */
   mudq = mldq = NVARS*MXSUB;
   mukeep = mlkeep = NVARS;
   flag = ARKBBDPrecInit(arkode_mem, local_N, mudq, mldq, 
 			mukeep, mlkeep, ZERO, flocal, NULL);
-  if(check_flag(&flag, "ARKBBDPrecAlloc", 1, my_pe)) MPI_Abort(comm, 1);
+  if(check_flag(&flag, "ARKBBDPrecInit", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Print heading */
   if (my_pe == 0) PrintIntro(npes, mudq, mldq, mukeep, mlkeep);
@@ -243,7 +250,8 @@ int main(int argc, char *argv[])
   /* Loop over jpre (= PREC_LEFT, PREC_RIGHT), and solve the problem */
   for (jpre=PREC_LEFT; jpre<=PREC_RIGHT; jpre++) {
 
-    /* On second run, re-initialize u, the integrator, ARKBBDPRE, and ARKSPGMR */
+    /* On second run, re-initialize u, the integrator, ARKBBDPRE, 
+       and preconditioning type */
     if (jpre == PREC_RIGHT) {
 
       SetInitialProfiles(u, data);
@@ -254,8 +262,8 @@ int main(int argc, char *argv[])
       flag = ARKBBDPrecReInit(arkode_mem, mudq, mldq, ZERO);
       if(check_flag(&flag, "ARKBBDPrecReInit", 1, my_pe)) MPI_Abort(comm, 1);
 
-      flag = ARKSpilsSetPrecType(arkode_mem, PREC_RIGHT);
-      check_flag(&flag, "ARKSpilsSetPrecType", 1, my_pe);
+      flag = SUNSPGMRSetPrecType(LS, PREC_RIGHT);
+      check_flag(&flag, "SUNSPGMRSetPrecType", 1, my_pe);
 
       if (my_pe == 0) {
 	printf("\n\n-------------------------------------------------------");
@@ -285,6 +293,7 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(u);
   free(data);
   ARKodeFree(&arkode_mem);
+  SUNLinSolFree(LS);
   MPI_Finalize();
   return(0);
 }
@@ -292,7 +301,7 @@ int main(int argc, char *argv[])
 /*********************** Private Helper Functions ************************/
 
 /* Load constants in data */
-static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+static void InitUserData(int my_pe, sunindextype local_N, MPI_Comm comm,
                          UserData data)
 {
   int isubx, isuby;
@@ -324,7 +333,7 @@ static void SetInitialProfiles(N_Vector u, UserData data)
 {
   int isubx, isuby;
   int lx, ly, jx, jy;
-  long int offset;
+  sunindextype offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *uarray;
 
@@ -359,16 +368,16 @@ static void SetInitialProfiles(N_Vector u, UserData data)
 }
 
 /* Print problem introduction */
-static void PrintIntro(int npes, long int mudq, long int mldq,
-		       long int mukeep, long int mlkeep)
+static void PrintIntro(int npes, sunindextype mudq, sunindextype mldq,
+		       sunindextype mukeep, sunindextype mlkeep)
 {
   printf("\n2-species diurnal advection-diffusion problem\n");
   printf("  %d by %d mesh on %d processors\n", MX, MY, npes);
   printf("  Using ARKBBDPRE preconditioner module\n");
   printf("    Difference-quotient half-bandwidths are");
-  printf(" mudq = %ld,  mldq = %ld\n", mudq, mldq);
+  printf(" mudq = %ld,  mldq = %ld\n", (long int) mudq, (long int) mldq);
   printf("    Retained band block half-bandwidths are");
-  printf(" mukeep = %ld,  mlkeep = %ld", mukeep, mlkeep);
+  printf(" mukeep = %ld,  mlkeep = %ld", (long int) mukeep, (long int) mlkeep);
   return;
 }
 
@@ -377,7 +386,8 @@ static void PrintOutput(void *arkode_mem, int my_pe, MPI_Comm comm,
                         N_Vector u, realtype t)
 {
   int flag, npelast;
-  long int i0, i1, nst;
+  sunindextype i0, i1;
+  long int nst;
   realtype hu, *uarray, tempu[2];
   MPI_Status status;
 
@@ -429,9 +439,9 @@ static void PrintFinalStats(void *arkode_mem)
 {
   long int lenrw, leniw ;
   long int lenrwLS, leniwLS;
-  long int lenrwBBDP, leniwBBDP, ngevalsBBDP;
+  long int lenrwBBDP, leniwBBDP;
   long int nst, nfe, nfi, nsetups, nni, ncfn, netf;
-  long int nli, npe, nps, ncfl, nfeLS;
+  long int nli, npe, nps, ncfl, nfeLS, ngevalsBBDP;
   int flag;
 
   flag = ARKodeGetWorkSpace(arkode_mem, &lenrw, &leniw);
@@ -477,18 +487,18 @@ static void PrintFinalStats(void *arkode_mem)
   flag = ARKBBDPrecGetNumGfnEvals(arkode_mem, &ngevalsBBDP);
   check_flag(&flag, "ARKBBDPrecGetNumGfnEvals", 1, 0);
   printf("In ARKBBDPRE: real/integer local work space sizes = %ld, %ld\n",
-	 lenrwBBDP, leniwBBDP);  
+	 lenrwBBDP, leniwBBDP);
   printf("             no. flocal evals. = %ld\n",ngevalsBBDP);
 }
  
 /* Routine to send boundary data to neighboring PEs */
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype uarray[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -532,10 +542,10 @@ static void BSend(MPI_Comm comm,
    2) request should have 4 entries, and should be passed in both calls also. */
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
 
@@ -572,11 +582,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[],
    2) request should have 4 entries, and should be passed in both calls also. */
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
 
@@ -625,7 +635,7 @@ static void fucomm(realtype t, N_Vector u, void *user_data)
   realtype *uarray, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmysub;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
 
   data = (UserData) user_data;
@@ -672,7 +682,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 /* flocal routine.  Compute f(t,y).  This routine assumes that all
    inter-processor communication of data needed to calculate f has already
    been done, and this data is in the work array uext.                    */
-static int flocal(long int Nlocal, realtype t, N_Vector u,
+static int flocal(sunindextype Nlocal, realtype t, N_Vector u,
                   N_Vector udot, void *user_data)
 {
   realtype *uext;
@@ -682,7 +692,7 @@ static int flocal(long int Nlocal, realtype t, N_Vector u,
   realtype q4coef, dely, verdco, hordco, horaco;
   int i, lx, ly, jy;
   int isubx, isuby;
-  long int nvmxsub, nvmxsub2, offsetu, offsetue;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
   UserData data;
   realtype *uarray, *duarray;
 
diff --git a/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.out b/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.out
index 400b519..713c077 100644
--- a/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.out
+++ b/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.out
@@ -59,7 +59,7 @@ At top right:    c1, c2 =    3.334e-07    4.163e+11
 Final Statistics: 
 
 lenrw   =  3058     leniw   =   160
-lenrwls =  2046     leniwls =    80
+lenrwls =  2450     leniwls =   106
 nst     =  7432     nfe     =     0
 nfe     = 78033     nfels   = 83813
 nni     = 40719     nli     = 83813
@@ -67,7 +67,7 @@ nsetups =   450     netf    =    30
 npe     =   125     nps     = 122360
 ncfn    =     0     ncfl    =     0
 
-In ARKBBDPRE: real/integer local work space sizes = 600, 50
+In ARKBBDPRE: real/integer local work space sizes = 1300, 192
              no. flocal evals. = 2750
 
 
@@ -128,7 +128,7 @@ At top right:    c1, c2 =    1.656e-25    4.163e+11
 Final Statistics: 
 
 lenrw   =  3058     leniw   =   160
-lenrwls =  2046     leniwls =    80
+lenrwls =  2450     leniwls =   106
 nst     =  7430     nfe     =     0
 nfe     = 78034     nfels   = 101865
 nni     = 40725     nli     = 101865
@@ -136,5 +136,5 @@ nsetups =   451     netf    =    31
 npe     =   125     nps     = 139198
 ncfn    =     0     ncfl    =     0
 
-In ARKBBDPRE: real/integer local work space sizes = 600, 50
+In ARKBBDPRE: real/integer local work space sizes = 1300, 192
              no. flocal evals. = 2750
diff --git a/examples/arkode/C_parallel/ark_diurnal_kry_p.c b/examples/arkode/C_parallel/ark_diurnal_kry_p.c
index d7439e3..09a4e15 100644
--- a/examples/arkode/C_parallel/ark_diurnal_kry_p.c
+++ b/examples/arkode/C_parallel/ark_diurnal_kry_p.c
@@ -41,7 +41,7 @@
  * neq = 2*MX*MY.
  *
  * The solution is done with the DIRK/GMRES method (i.e. using the
- * ARKSPGMR linear solver) and the block-diagonal part of the
+ * SUNSPGMR linear solver) and the block-diagonal part of the
  * Newton matrix as a left preconditioner. A copy of the
  * block-diagonal part of the Jacobian is saved and conditionally
  * reused within the preconditioner routine.
@@ -58,13 +58,14 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
-#include <arkode/arkode.h>             /* prototypes for ARKODE fcts. */
-#include <arkode/arkode_spgmr.h>       /* prototypes & constants for ARKSPGMR  */
-#include <nvector/nvector_parallel.h>  /* def. of N_Vector, macro NV_DATA_P  */
-#include <sundials/sundials_dense.h>   /* prototypes for small dense fcts. */
-#include <sundials/sundials_types.h>   /* definitions of realtype, booleantype */
-#include <sundials/sundials_math.h>    /* definition of macros SUNSQR and EXP */
-#include <mpi.h>                       /* MPI constants and types */
+#include <arkode/arkode.h>               /* prototypes for ARKODE fcts.      */
+#include <nvector/nvector_parallel.h>    /* access to MPI-parallel N_Vector  */
+#include <sunlinsol/sunlinsol_spgmr.h>   /* access to SPGMR SUNLinearSolver  */
+#include <sundials/sundials_dense.h>     /* prototypes for small dense fcts. */
+#include <arkode/arkode_spils.h>         /* access to ARKSpils interface     */
+#include <sundials/sundials_types.h>     /* SUNDIALS type definitions        */
+#include <sundials/sundials_math.h>      /* definition of macros SUNSQR, EXP */
+#include <mpi.h>                         /* MPI constants and types          */
 
 /* Problem Constants */
 #define NVARS        2                    /* number of species         */
@@ -132,7 +133,7 @@ typedef struct {
 
   /* For preconditioner */
   realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
 
 } *UserData;
 
@@ -145,15 +146,15 @@ static void PrintOutput(void *arkode_mem, int my_pe, MPI_Comm comm,
 static void PrintFinalStats(void *arkode_mem);
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype udata[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[]);
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[]);
 static void ucomm(realtype t, N_Vector u, UserData data);
 static void fcalc(realtype t, realtype udata[], realtype dudata[],
@@ -164,12 +165,10 @@ static void fcalc(realtype t, realtype udata[], realtype dudata[],
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   realtype gamma, void *user_data);
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
-                  N_Vector r, N_Vector z, 
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  N_Vector r, N_Vector z, realtype gamma, 
+                  realtype delta, int lr, void *user_data);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
@@ -181,13 +180,15 @@ int main(int argc, char *argv[])
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *arkode_mem;
   int iout, flag, my_pe, npes;
-  long int neq, local_N;
+  sunindextype neq, local_N;
   MPI_Comm comm;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   arkode_mem = NULL;
 
   /* Set problem size neq */
@@ -221,6 +222,11 @@ int main(int argc, char *argv[])
   SetInitialProfiles(u, data);
   abstol = ATOL; reltol = RTOL;
 
+  /* Create SPGMR solver structure -- use left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+  
   /* Call ARKodeCreate to create the solver memory */
   arkode_mem = ARKodeCreate();
   if (check_flag((void *)arkode_mem, "ARKodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
@@ -244,16 +250,16 @@ int main(int argc, char *argv[])
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);
   if (check_flag(&flag, "ARKodeSStolerances", 1, my_pe)) return(1);
 
-  /* Call ARKSpgmr to specify the linear solver ARKSPGMR 
-     with left preconditioning and the default Krylov dimension maxl */
-  flag = ARKSpgmr(arkode_mem, PREC_LEFT, 0);
-  if (check_flag(&flag, "ARKSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Attach SPGMR solver structure to ARKSpils interface */
+  flag = ARKSpilsSetLinearSolver(arkode_mem, LS);
+  if (check_flag(&flag, "ARKSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Set preconditioner setup and solve routines Precond and PSolve, 
      and the pointer to the user-defined block data */
   flag = ARKSpilsSetPreconditioner(arkode_mem, Precond, PSolve);
   if (check_flag(&flag, "ARKSpilsSetPreconditioner", 1, my_pe)) MPI_Abort(comm, 1);
 
+  /* Print heading */
   if (my_pe == 0)
     printf("\n2-species diurnal advection-diffusion problem\n\n");
 
@@ -268,9 +274,10 @@ int main(int argc, char *argv[])
   if (my_pe == 0) PrintFinalStats(arkode_mem);
 
   /* Free memory */
-  N_VDestroy_Parallel(u);
   FreeUserData(data);
   ARKodeFree(&arkode_mem);
+  SUNLinSolFree(LS);
+  N_VDestroy_Parallel(u);
   MPI_Finalize();
   return(0);
 }
@@ -310,7 +317,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
     for (ly = 0; ly < MYSUB; ly++) {
       (data->P)[lx][ly] = newDenseMat(NVARS, NVARS);
       (data->Jbd)[lx][ly] = newDenseMat(NVARS, NVARS);
-      (data->pivot)[lx][ly] = newLintArray(NVARS);
+      (data->pivot)[lx][ly] = newIndexArray(NVARS);
     }
   }
 }
@@ -333,7 +340,7 @@ static void FreeUserData(UserData data)
 static void SetInitialProfiles(N_Vector u, UserData data)
 {
   int isubx, isuby, lx, ly, jx, jy;
-  long int offset;
+  sunindextype offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *udata;
 
@@ -374,7 +381,8 @@ static void PrintOutput(void *arkode_mem, int my_pe, MPI_Comm comm,
   int flag;
   realtype hu, *udata, tempu[2];
   int npelast;
-  long int i0, i1, nst;
+  sunindextype i0, i1;
+  long int nst;
   MPI_Status status;
 
   npelast = NPEX*NPEY - 1;
@@ -424,7 +432,7 @@ static void PrintOutput(void *arkode_mem, int my_pe, MPI_Comm comm,
 /* Print final statistics contained in iopt */
 static void PrintFinalStats(void *arkode_mem)
 {
-  long int lenrw, leniw ;
+  long int lenrw, leniw;
   long int lenrwLS, leniwLS;
   long int nst, nfe, nfi, nsetups, nni, ncfn, netf;
   long int nli, npe, nps, ncfl, nfeLS;
@@ -459,7 +467,7 @@ static void PrintFinalStats(void *arkode_mem)
   check_flag(&flag, "ARKSpilsGetNumRhsEvals", 1, 0);
 
   printf("\nFinal Statistics: \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
+  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw,   leniw);
   printf("lenrwls = %5ld     leniwls = %5ld\n", lenrwLS, leniwLS);
   printf("nst     = %5ld     nfe     = %5ld\n", nst, nfe);
   printf("nfi     = %5ld     nfels   = %5ld\n", nfi, nfeLS);
@@ -470,13 +478,12 @@ static void PrintFinalStats(void *arkode_mem)
 }
  
 /* Routine to send boundary data to neighboring PEs */
-static void BSend(MPI_Comm comm, 
-                  int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
-                  realtype udata[])
+static void BSend(MPI_Comm comm, int my_pe, int isubx, 
+                  int isuby, sunindextype dsizex, 
+                  sunindextype dsizey, realtype udata[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -521,10 +528,10 @@ static void BSend(MPI_Comm comm,
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
 
@@ -562,11 +569,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[],
 
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
 
@@ -616,7 +623,7 @@ static void ucomm(realtype t, N_Vector u, UserData data)
   realtype *udata, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmysub;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
 
   udata = N_VGetArrayPointer(u);
@@ -652,7 +659,7 @@ static void fcalc(realtype t, realtype udata[],
   realtype q4coef, dely, verdco, hordco, horaco;
   int i, lx, ly, jy;
   int isubx, isuby;
-  long int nvmxsub, nvmxsub2, offsetu, offsetue;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
 
   /* Get subgrid indices, data sizes, extended work array uext */
   isubx = data->isubx;   isuby = data->isuby;
@@ -795,13 +802,12 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 /* Preconditioner setup routine. Generate and preprocess P. */
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MYSUB], **(*Jbd)[MYSUB];
   int nvmxsub, ier, offset;
-  long int *(*pivot)[MYSUB];
+  sunindextype *(*pivot)[MYSUB];
   int lx, ly, jy, isuby;
   realtype *udata, **a, **j;
   UserData data;
@@ -817,19 +823,18 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
   nvmxsub = data->nvmxsub;
 
   if (jok) {
-
-  /* jok = TRUE: Copy Jbd to P */
+  /* jok = SUNTRUE: Copy Jbd to P */
     for (ly = 0; ly < MYSUB; ly++)
       for (lx = 0; lx < MXSUB; lx++)
         denseCopy(Jbd[lx][ly], P[lx][ly], NVARS, NVARS);
 
-  *jcurPtr = FALSE;
+  *jcurPtr = SUNFALSE;
 
   }
 
   else {
 
-  /* jok = FALSE: Generate Jbd from scratch and copy to P */
+  /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
 
   /* Make local copies of problem variables, for efficiency */
   q4coef = data->q4;
@@ -860,7 +865,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
 
   }
 
@@ -885,11 +890,11 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
                   N_Vector r, N_Vector z, 
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype **(*P)[MYSUB];
   int nvmxsub;
-  long int *(*pivot)[MYSUB];
+  sunindextype *(*pivot)[MYSUB];
   int lx, ly;
   realtype *zdata, *v;
   UserData data;
@@ -903,7 +908,6 @@ static int PSolve(realtype tn, N_Vector u, N_Vector fu,
      in P and pivot data in pivot, and return the solution in z.
      First copy vector r to z. */
   N_VScale(RCONST(1.0), r, z);
-
   nvmxsub = data->nvmxsub;
   zdata = N_VGetArrayPointer(z);
 
diff --git a/examples/arkode/C_parallel/ark_diurnal_kry_p.out b/examples/arkode/C_parallel/ark_diurnal_kry_p.out
index de34bc8..439183f 100644
--- a/examples/arkode/C_parallel/ark_diurnal_kry_p.out
+++ b/examples/arkode/C_parallel/ark_diurnal_kry_p.out
@@ -53,7 +53,7 @@ At top right:    c1, c2 =   -1.129e-28    4.163e+11
 Final Statistics: 
 
 lenrw   =  3058     leniw   =   160
-lenrwls =  2046     leniwls =    80
+lenrwls =  2450     leniwls =   106
 nst     =  7220     nfe     =     0
 nfi     = 75855     nfels   = 88509
 nni     = 39606     nli     = 88509
diff --git a/examples/arkode/C_parhyp/CMakeLists.txt b/examples/arkode/C_parhyp/CMakeLists.txt
index b34b640..9250115 100644
--- a/examples/arkode/C_parhyp/CMakeLists.txt
+++ b/examples/arkode/C_parhyp/CMakeLists.txt
@@ -2,13 +2,13 @@
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,14 +17,16 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for ARKODE parhyp C examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable ARKODE_examples with the names of the parhyp ARKODE examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(ARKODE_examples
-  "ark_diurnal_kry_ph\;1\;4"
+  "ark_diurnal_kry_ph\;1\;4\;develop"
 #  "ark_diurnal_kry_bbd_ph\;1\;4"
   )
 
@@ -36,58 +38,65 @@ SET(ARKODE_extras
 # Check whether we use MPI compiler scripts.
 # If yes, then change the C compiler to the MPICC script.
 # If not, then add the MPI include directory for MPI headers.
+
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECP_LIB sundials_nvecparhyp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECP_LIB sundials_nvecparhyp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${ARKODE_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-SET(HYPRE_LIBS ${HYPRE_LIBRARIES})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # Add the build and install targets for each ARKODE example
 FOREACH(example_tuple ${ARKODE_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-  TARGET_LINK_LIBRARIES(${example} ${HYPRE_LIBS})
+
+  # add to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${HYPRE_LIBRARIES})
+
   IF(NOT MPI_MPICC)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  ENDIF()
+
+  # install example
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parhyp)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parhyp)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${ARKODE_examples})
 
+
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -96,36 +105,33 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${ARKODE_extras})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parhyp)
-  ENDFOREACH(extrafile ${ARKODE_extras})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
-  FOREACH(example_tuple ${ARKODE_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${ARKODE_examples})
 
+  EXAMPLES2STRING(ARKODE_examples EXAMPLES)
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parhyp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/C_parhyp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parhyp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/C_parhyp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/C_parhyp/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parhyp 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_parhyp
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/arkode/C_parhyp/README b/examples/arkode/C_parhyp/README
index 20608f4..4dc5a0c 100644
--- a/examples/arkode/C_parhyp/README
+++ b/examples/arkode/C_parhyp/README
@@ -8,7 +8,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c b/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c
index f8df6a2..adaa06e 100644
--- a/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c
+++ b/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c
@@ -1,7 +1,4 @@
 /*-----------------------------------------------------------------
- * $Revision$
- * $Date$
- * -----------------------------------------------------------------
  * Programmer(s): Daniel R. Reynolds, Jean Sexton @ SMU
  *                Slaven Peles @ LLNL
  *---------------------------------------------------------------
@@ -45,7 +42,7 @@
  * neq = 2*MX*MY.
  *
  * The solution is done with the DIRK/GMRES method (i.e. using the
- * ARKSPGMR linear solver) and the block-diagonal part of the
+ * SUNSPGMR linear solver) and the block-diagonal part of the
  * Newton matrix as a left preconditioner. A copy of the
  * block-diagonal part of the Jacobian is saved and conditionally
  * reused within the preconditioner routine.
@@ -57,16 +54,17 @@
  * This example uses Hypre vector and MPI parallelization. User is 
  * expected to be familiar with the Hypre library. 
  * 
- * Execution: mpiexec -n N ark_diurnal_kry_p   with N = NPEX*NPEY
+ * Execution: mpiexec -n N ark_diurnal_kry_ph  with N = NPEX*NPEY
  * (see constants below).
  *---------------------------------------------------------------*/
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 #include <arkode/arkode.h>             /* prototypes for ARKODE fcts. */
-#include <arkode/arkode_spgmr.h>       /* prototypes & constants for ARKSPGMR  */
 #include <nvector/nvector_parhyp.h>    /* declaration of N_Vector  */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver  */
 #include <sundials/sundials_dense.h>   /* prototypes for small dense fcts. */
+#include <arkode/arkode_spils.h>         /* access to ARKSpils interface     */
 #include <sundials/sundials_types.h>   /* definitions of realtype, booleantype */
 #include <sundials/sundials_math.h>    /* definition of macros SUNSQR and EXP */
 #include <mpi.h>                       /* MPI constants and types */
@@ -140,29 +138,30 @@ typedef struct {
 
   /* For preconditioner */
   realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
 
 } *UserData;
 
 /* Private Helper Functions */
 static void InitUserData(int my_pe, MPI_Comm comm, UserData data);
 static void FreeUserData(UserData data);
-static void SetInitialProfiles(HYPRE_IJVector Uij, UserData data, long int local_length, 
-                               long int my_base);
+static void SetInitialProfiles(HYPRE_IJVector Uij, UserData data,
+                               sunindextype local_length, 
+                               sunindextype my_base);
 static void PrintOutput(void *arkode_mem, int my_pe, MPI_Comm comm,
                         N_Vector u, realtype t);
 static void PrintFinalStats(void *arkode_mem);
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype udata[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-                      long int dsizex, long int dsizey,
+                      sunindextype dsizex, sunindextype dsizey,
                       realtype uext[], realtype buffer[]);
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[]);
 static void ucomm(realtype t, N_Vector u, UserData data);
 static void fcalc(realtype t, realtype udata[], realtype dudata[],
@@ -173,12 +172,11 @@ static void fcalc(realtype t, realtype udata[], realtype dudata[],
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   realtype gamma, void *user_data);
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
                   N_Vector r, N_Vector z, 
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
@@ -190,21 +188,20 @@ int main(int argc, char *argv[])
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *arkode_mem;
-  int iout, flag;
+  int iout, flag, my_pe, npes;
   MPI_Comm comm;
   
-  HYPRE_Int local_N, npes, my_pe;
+  HYPRE_Int local_N;
   HYPRE_ParVector Upar; /* Declare HYPRE parallel vector */
   HYPRE_IJVector  Uij;  /* Declare "IJ" interface to HYPRE vector */
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   arkode_mem = NULL;
 
-  /* Set problem size neq */
-  /* neq = NVARS*MX*MY;   */
-
   /* Get processor number and total number of pe's */
   MPI_Init(&argc, &argv);
   comm = MPI_COMM_WORLD;
@@ -243,6 +240,11 @@ int main(int argc, char *argv[])
   /* Set tolerances */
   abstol = ATOL; reltol = RTOL;
 
+  /* Create SPGMR solver structure -- use left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+  
   /* Call ARKodeCreate to create the solver memory */
   arkode_mem = ARKodeCreate();
   if (check_flag((void *)arkode_mem, "ARKodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
@@ -266,10 +268,9 @@ int main(int argc, char *argv[])
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);
   if (check_flag(&flag, "ARKodeSStolerances", 1, my_pe)) return(1);
 
-  /* Call ARKSpgmr to specify the linear solver ARKSPGMR 
-     with left preconditioning and the default Krylov dimension maxl */
-  flag = ARKSpgmr(arkode_mem, PREC_LEFT, 0);
-  if (check_flag(&flag, "ARKSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Attach SPGMR solver structure to ARKSpils interface */
+  flag = ARKSpilsSetLinearSolver(arkode_mem, LS);
+  if (check_flag(&flag, "ARKSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Set preconditioner setup and solve routines Precond and PSolve, 
      and the pointer to the user-defined block data */
@@ -294,6 +295,7 @@ int main(int argc, char *argv[])
   HYPRE_IJVectorDestroy(Uij); /* Free the underlying hypre vector */
   FreeUserData(data);
   ARKodeFree(&arkode_mem);
+  SUNLinSolFree(LS);
   MPI_Finalize();
   return(0);
 }
@@ -333,7 +335,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
     for (ly = 0; ly < MYSUB; ly++) {
       (data->P)[lx][ly] = newDenseMat(NVARS, NVARS);
       (data->Jbd)[lx][ly] = newDenseMat(NVARS, NVARS);
-      (data->pivot)[lx][ly] = newLintArray(NVARS);
+      (data->pivot)[lx][ly] = newIndexArray(NVARS);
     }
   }
 }
@@ -353,11 +355,12 @@ static void FreeUserData(UserData data)
 }
 
 /* Set initial conditions in u */
-static void SetInitialProfiles(HYPRE_IJVector Uij, UserData data, long int local_length, 
-                               long int my_base)
+static void SetInitialProfiles(HYPRE_IJVector Uij, UserData data,
+                               sunindextype local_length, 
+                               sunindextype my_base)
 {
   int isubx, isuby, lx, ly, jx, jy;
-  long int offset;
+  sunindextype offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *udata;
   HYPRE_Int *iglobal;
@@ -405,7 +408,8 @@ static void PrintOutput(void *arkode_mem, int my_pe, MPI_Comm comm,
   int flag;
   realtype hu, *udata, tempu[2];
   int npelast;
-  long int i0, i1, nst;
+  sunindextype i0, i1;
+  long int nst;
   MPI_Status status;
   HYPRE_ParVector uhyp;
   
@@ -506,11 +510,11 @@ static void PrintFinalStats(void *arkode_mem)
 /* Routine to send boundary data to neighboring PEs */
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype udata[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -555,10 +559,10 @@ static void BSend(MPI_Comm comm,
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-                      long int dsizex, long int dsizey,
+                      sunindextype dsizex, sunindextype dsizey,
                       realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
 
@@ -596,11 +600,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[],
 
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
 
@@ -651,7 +655,7 @@ static void ucomm(realtype t, N_Vector u, UserData data)
   realtype *udata, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmysub;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
   HYPRE_ParVector uhyp;
   
@@ -690,7 +694,7 @@ static void fcalc(realtype t, realtype udata[],
   realtype q4coef, dely, verdco, hordco, horaco;
   int i, lx, ly, jy;
   int isubx, isuby;
-  long int nvmxsub, nvmxsub2, offsetu, offsetue;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
 
   /* Get subgrid indices, data sizes, extended work array uext */
   isubx = data->isubx;   isuby = data->isuby;
@@ -843,13 +847,12 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MYSUB], **(*Jbd)[MYSUB];
   int nvmxsub, ier, offset;
-  long int *(*pivot)[MYSUB];
+  sunindextype *(*pivot)[MYSUB];
   int lx, ly, jy, isuby;
   realtype *udata, **a, **j;
   HYPRE_ParVector uhyp;
@@ -869,18 +872,18 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 
   if (jok) {
 
-    /* jok = TRUE: Copy Jbd to P */
+    /* jok = SUNTRUE: Copy Jbd to P */
     for (ly = 0; ly < MYSUB; ly++)
       for (lx = 0; lx < MXSUB; lx++)
         denseCopy(Jbd[lx][ly], P[lx][ly], NVARS, NVARS);
 
-  *jcurPtr = FALSE;
+  *jcurPtr = SUNFALSE;
 
   }
 
   else {
 
-    /* jok = FALSE: Generate Jbd from scratch and copy to P */
+    /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
 
     /* Make local copies of problem variables, for efficiency */
     q4coef = data->q4;
@@ -911,7 +914,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
 
-    *jcurPtr = TRUE;
+    *jcurPtr = SUNTRUE;
 
   }
 
@@ -938,11 +941,11 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
                   N_Vector r, N_Vector z, 
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype **(*P)[MYSUB];
   int nvmxsub;
-  long int *(*pivot)[MYSUB];
+  sunindextype *(*pivot)[MYSUB];
   int lx, ly;
   realtype *zdata, *v;
   HYPRE_ParVector zhyp;
diff --git a/examples/arkode/C_parhyp/ark_diurnal_kry_ph.out b/examples/arkode/C_parhyp/ark_diurnal_kry_ph.out
index de34bc8..439183f 100644
--- a/examples/arkode/C_parhyp/ark_diurnal_kry_ph.out
+++ b/examples/arkode/C_parhyp/ark_diurnal_kry_ph.out
@@ -53,7 +53,7 @@ At top right:    c1, c2 =   -1.129e-28    4.163e+11
 Final Statistics: 
 
 lenrw   =  3058     leniw   =   160
-lenrwls =  2046     leniwls =    80
+lenrwls =  2450     leniwls =   106
 nst     =  7220     nfe     =     0
 nfi     = 75855     nfels   = 88509
 nni     = 39606     nli     = 88509
diff --git a/examples/arkode/C_serial/CMakeLists.txt b/examples/arkode/C_serial/CMakeLists.txt
index 97c3027..ad71db4 100644
--- a/examples/arkode/C_serial/CMakeLists.txt
+++ b/examples/arkode/C_serial/CMakeLists.txt
@@ -1,5 +1,6 @@
 # ---------------------------------------------------------------
-# Programmer:  Daniel R. Reynolds @ SMU
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
 # Copyright (c) 2015, Southern Methodist University and 
@@ -8,7 +9,7 @@
 # This work was performed under the auspices of the U.S. Department 
 # of Energy by Southern Methodist University and Lawrence Livermore 
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,46 +18,42 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for ARKODE serial examples
+# ---------------------------------------------------------------
 
-# Add variable ARKODE_examples with the names of the serial ARKODE examples
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS linear solvers
 SET(ARKODE_examples
-  ark_analytic
-  ark_analytic_nonlin
-  ark_brusselator
-  ark_brusselator_fp
-  ark_brusselator1D
-  ark_heat1D
-  ark_heat1D_adapt
-  ark_KrylovDemo_prec
-  ark_robertson
-  ark_robertson_root
+  "ark_analytic\;"
+  "ark_analytic_nonlin\;develop"
+  "ark_brusselator\;develop"
+  "ark_brusselator_fp\;develop"
+  "ark_brusselator1D\;develop"
+  "ark_heat1D\;develop"
+  "ark_heat1D_adapt\;develop"
+  "ark_KrylovDemo_prec\;develop"
+  "ark_robertson\;"
+  "ark_robertson_root\;develop"
   )
 
-# Add variable ARKODE_examples_BL with the names of the serial ARKODE examples
-# that use Lapack
-
+# Examples using LAPACK linear solvers
 SET(ARKODE_examples_BL
   )
 
-# Add variable ARKODE_examples_KLU with the names of the serial ARKODE examples
-# that use KLU
-
+# Examples using KLU linear solver
 SET(ARKODE_examples_KLU
-  ark_brusselator1D_klu
+  "ark_brusselator1D_klu\;develop"
   )
 
-# Add variable ARKODE_examples_SUPERLUMT with the names of the serial ARKODE examples
-# that use SUPERLUMT
-
+# Examples using SuperLU_MT linear solver
 SET(ARKODE_examples_SUPERLUMT
-  ark_brusselator1D_FEM_slu
+  "ark_brusselator1D_FEM_slu\;develop"
   )
 
-# Add variable ARKODE_extras with the names of auxiliary files to install
-
+# Auxiliary files to install
 SET(ARKODE_extras
   plot_brusselator1D.py
   plot_brusselator1D_FEM.py
@@ -68,84 +65,195 @@ SET(ARKODE_extras
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${ARKODE_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # Add the build and install targets for each ARKODE example
+FOREACH(example_tuple ${ARKODE_examples})
 
-FOREACH(example ${ARKODE_examples})
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${ARKODE_examples})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${ARKODE_examples})
 
-# Add the build and install targets for each Lapack ARKODE example (if needed)
 
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${ARKODE_examples_BL})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${ARKODE_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${ARKODE_examples_BL})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${ARKODE_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If KLU support is enabled, add the build and install targets for 
-# the examples using KLU
+
+# Add the build and install targets for each KLU example (if needed)
 IF(KLU_FOUND)
-  FOREACH(example ${ARKODE_examples_KLU})
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${ARKODE_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${ARKODE_examples_KLU})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${ARKODE_examples_KLU})
+
 ENDIF(KLU_FOUND)
 
-# If SuperLUMT support is enabled, add the build and install targets for 
-# the examples using SuperLUMT
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
 IF(SUPERLUMT_FOUND)
-  FOREACH(example ${ARKODE_examples_SUPERLUMT})
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${ARKODE_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${ARKODE_examples_SUPERLUMT})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${ARKODE_examples_SUPERLUMT})
+
 ENDIF(SUPERLUMT_FOUND)
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -159,25 +267,26 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
-  LIST2STRING(ARKODE_examples EXAMPLES)
+
+  EXAMPLES2STRING(ARKODE_examples EXAMPLES)
 
   IF(LAPACK_FOUND)
-    LIST2STRING(ARKODE_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(ARKODE_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
 
   IF(KLU_FOUND)
-    LIST2STRING(ARKODE_examples_KLU EXAMPLES)
-  ENDIF(KLU_FOUND)
+    EXAMPLES2STRING(ARKODE_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
 
   IF(SUPERLUMT_FOUND)
-    LIST2STRING(ARKODE_examples_SUPERLUMT EXAMPLES)
-  ENDIF(SUPERLUMT_FOUND)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
-
+    EXAMPLES2STRING(ARKODE_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -185,10 +294,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/C_serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/C_serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
@@ -215,4 +324,8 @@ IF(EXAMPLES_INSTALL)
       )
   ENDIF(UNIX)
 
+  # add test_install target
+  SUNDIALS_ADD_TEST_INSTALL(arkode ark_analytic
+    EXAMPLE_DIR ${EXAMPLES_INSTALL_PATH}/arkode/C_serial)
+
 ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/arkode/C_serial/README b/examples/arkode/C_serial/README
index 91c6135..38e45da 100644
--- a/examples/arkode/C_serial/README
+++ b/examples/arkode/C_serial/README
@@ -20,7 +20,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -31,7 +30,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -45,7 +47,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/C_serial/ark_KrylovDemo_prec.c b/examples/arkode/C_serial/ark_KrylovDemo_prec.c
index 27c0062..22e46cf 100644
--- a/examples/arkode/C_serial/ark_KrylovDemo_prec.c
+++ b/examples/arkode/C_serial/ark_KrylovDemo_prec.c
@@ -58,7 +58,7 @@
  *
  * The resulting ODE system is stiff.
  *
- * The ODE system is solved using Newton iteration and the ARKSPGMR
+ * The ODE system is solved using Newton iteration and the SUNSPGMR
  * linear solver (scaled preconditioned GMRES).
  *
  * The preconditioner matrix used is the product of two matrices:
@@ -72,9 +72,10 @@
  * The product preconditoner is applied on the left and on the
  * right. In each case, both the modified and classical Gram-Schmidt
  * options are tested.
- * In the series of runs, ARKodeInit and ARKSpgmr are called only
- * for the first run, whereas ARKodeReInit, ARKSpilsSetPrecType and
- * ARKSpilsSetGSType are called for each of the remaining three runs.
+ * In the series of runs, ARKodeInit, SUNSPGMR and 
+ * ARKSpilsSetLinearSolver are called only for the first run, whereas 
+ * ARKodeReInit, SUNSPGMRSetPrecType, and SUNSPGMRSetGSType are called
+ * for each of the remaining three runs.
  *
  * A problem description, performance statistics at selected output
  * times, and final statistics are written to standard output.
@@ -83,12 +84,12 @@
  * but there should be no such messages.
  *
  * Note: This program requires the dense linear solver functions
- * newDenseMat, newLintArray, denseAddIdentity, denseGETRF, denseGETRS, 
+ * newDenseMat, newIndexArray, denseAddIdentity, denseGETRF, denseGETRS, 
  * destroyMat and destroyArray.
  *
  * Note: This program assumes the sequential implementation for the
- * type N_Vector and uses the N_VGetArrayPointer_Serial to gain access 
- * to the contiguous array of components of an N_Vector.
+ * type N_Vector and uses the N_VGetArrayPointer function to gain
+ * access to the contiguous array of components of an N_Vector.
  *-------------------------------------------------------------------
  * Reference: Peter N. Brown and Alan C. Hindmarsh, Reduced Storage
  * Matrix Methods in Stiff ODE Systems, J. Appl. Math. & Comp., 31
@@ -100,12 +101,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <arkode/arkode.h>           /* main integrator header file */
-#include <arkode/arkode_spgmr.h>     /* prototypes & constants for ARKSPGMR solver */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_dense.h> /* use generic DENSE solver in preconditioning */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS and SUNSQR */
+#include <arkode/arkode.h>              /* main integrator header file                 */
+#include <sunlinsol/sunlinsol_spgmr.h>  /* access to SPGMR SUNLinearSolver             */
+#include <arkode/arkode_spils.h>        /* access to ARKSpils interface                */
+#include <nvector/nvector_serial.h>     /* serial N_Vector types, fct. and macros      */
+#include <sundials/sundials_dense.h>    /* use generic DENSE solver in preconditioning */
+#include <sundials/sundials_types.h>    /* definition of realtype                      */
+#include <sundials/sundials_math.h>     /* contains the macros ABS and SUNSQR          */
 
 /* Constants */
 
@@ -168,7 +170,7 @@
 
 typedef struct {
   realtype **P[NGRP];
-  long int *pivot[NGRP];
+  sunindextype *pivot[NGRP];
   int ns, mxns;
   int mp, mq, mx, my, ngrp, ngx, ngy, mxmp;
   int jgx[NGX+1], jgy[NGY+1], jigx[MX], jigy[MY];
@@ -176,6 +178,7 @@ typedef struct {
   realtype acoef[NS][NS], bcoef[NS], diff[NS];
   realtype cox[NS], coy[NS], dx, dy, srur;
   realtype fsave[NEQ];
+  N_Vector tmp;
   N_Vector rewt;
   void *arkode_mem;
 } *WebData;
@@ -196,7 +199,7 @@ static void WebRates(realtype x, realtype y, realtype t, realtype c[],
 		     realtype rate[], WebData wdata);
 static void fblock (realtype t, realtype cdata[], int jx, int jy,
 		    realtype cdotdata[], WebData wdata);
-static void GSIter(realtype gamma, N_Vector z, N_Vector x,WebData wdata);
+static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata);
 
 /* Small Vector Kernels */
 
@@ -210,15 +213,11 @@ static void v_zero(realtype u[], int n);
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
-static int Precond(realtype tn, N_Vector c, N_Vector fc,
-		   booleantype jok, booleantype *jcurPtr, realtype gamma,
-		   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3);
+static int Precond(realtype tn, N_Vector c, N_Vector fc, booleantype jok, 
+                   booleantype *jcurPtr, realtype gamma, void *user_data);
 
-static int PSolve(realtype tn, N_Vector c, N_Vector fc,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+static int PSolve(realtype tn, N_Vector c, N_Vector fc, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data);
 
 /* Private function to check function return values */
 
@@ -231,6 +230,7 @@ int main()
   realtype abstol=ATOL, reltol=RTOL, t, tout;
   N_Vector c;
   WebData wdata;
+  SUNLinearSolver LS;
   void *arkode_mem;
   booleantype firstrun;
   int jpre, gstype, flag;
@@ -238,6 +238,7 @@ int main()
 
   c = NULL;
   wdata = NULL;
+  LS = NULL;
   arkode_mem = NULL;
 
   /* Initializations */
@@ -276,19 +277,22 @@ int main()
         if(check_flag(&flag, "ARKodeInit", 1)) return(1);
 
         flag = ARKodeSStolerances(arkode_mem, reltol, abstol);
-        if (check_flag(&flag, "ARKodeSStolerances", 1)) return(1);
+        if(check_flag(&flag, "ARKodeSStolerances", 1)) return(1);
 
-	flag = ARKodeSetMaxNumSteps(arkode_mem, 1000);
-	if (check_flag(&flag, "ARKodeSetMaxNumSteps", 1)) return(1);
+        flag = ARKodeSetMaxNumSteps(arkode_mem, 1000);
+        if(check_flag(&flag, "ARKodeSetMaxNumSteps", 1)) return(1);
 
-	flag = ARKodeSetNonlinConvCoef(arkode_mem, 1.e-3);
-	if (check_flag(&flag, "ARKodeSetNonlinConvCoef", 1)) return(1);
+        flag = ARKodeSetNonlinConvCoef(arkode_mem, 1.e-3);
+        if(check_flag(&flag, "ARKodeSetNonlinConvCoef", 1)) return(1);
 
-        flag = ARKSpgmr(arkode_mem, jpre, MAXL);
-        if(check_flag(&flag, "ARKSpgmr", 1)) return(1);
+        LS = SUNSPGMR(c, jpre, MAXL);
+        if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
 
-        flag = ARKSpilsSetGSType(arkode_mem, gstype);
-        if(check_flag(&flag, "ARKSpilsSetGSType", 1)) return(1);
+        flag = ARKSpilsSetLinearSolver(arkode_mem, LS);
+        if(check_flag(&flag, "ARKSpilsSetLinearSolver", 1)) return 1;
+
+        flag = SUNSPGMRSetGSType(LS, gstype);
+        if(check_flag(&flag, "SUNSPGMRSetGSType", 1)) return(1);
 
         flag = ARKSpilsSetEpsLin(arkode_mem, DELT);
         if(check_flag(&flag, "ARKSpilsSetEpsLin", 1)) return(1);
@@ -301,10 +305,10 @@ int main()
         flag = ARKodeReInit(arkode_mem, NULL, f, T0, c);
         if(check_flag(&flag, "ARKodeReInit", 1)) return(1);
 
-        flag = ARKSpilsSetPrecType(arkode_mem, jpre);
-        check_flag(&flag, "ARKSpilsSetPrecType", 1);
-        flag = ARKSpilsSetGSType(arkode_mem, gstype);
-        if(check_flag(&flag, "ARKSpilsSetGSType", 1)) return(1);
+        flag = SUNSPGMRSetPrecType(LS, jpre);
+        check_flag(&flag, "SUNSPGMRSetPrecType", 1);
+        flag = SUNSPGMRSetGSType(LS, gstype);
+        if(check_flag(&flag, "SUNSPGMRSetGSType", 1)) return(1);
 
       }
       
@@ -329,7 +333,8 @@ int main()
 
   /* Free all memory */
   ARKodeFree(&arkode_mem);
-  N_VDestroy_Serial(c);
+  N_VDestroy(c);
+  SUNLinSolFree(LS);
   FreeUserData(wdata);
 
   return(0);
@@ -338,15 +343,16 @@ int main()
 static WebData AllocUserData(void)
 {
   int i, ngrp = NGRP;
-  long int ns = NS;
+  sunindextype ns = NS;
   WebData wdata;
   
   wdata = (WebData) malloc(sizeof *wdata);
   for(i=0; i < ngrp; i++) {
     (wdata->P)[i] = newDenseMat(ns, ns);
-    (wdata->pivot)[i] = newLintArray(ns);
+    (wdata->pivot)[i] = newIndexArray(ns);
   }
   wdata->rewt = N_VNew_Serial(NEQ);
+  wdata->tmp = N_VNew_Serial(NEQ);
   return(wdata);
 }
 
@@ -619,10 +625,10 @@ static void PrintFinalStats(void *arkode_mem)
   check_flag(&flag, "ARKSpilsGetNumRhsEvals", 1);
 
   printf("\n\n Final statistics for this run:\n\n");
-  printf(" ARKode real workspace length           = %4ld \n", lenrw);
-  printf(" ARKode integer workspace length        = %4ld \n", leniw);
-  printf(" ARKSPGMR real workspace length         = %4ld \n", lenrwLS);
-  printf(" ARKSPGMR integer workspace length      = %4ld \n", leniwLS);
+  printf(" ARKode real workspace length          = %4ld \n", lenrw);
+  printf(" ARKode integer workspace length       = %4ld \n", leniw);
+  printf(" SUNSPGMR real workspace length        = %4ld \n", lenrwLS);
+  printf(" SUNSPGMR integer workspace length     = %4ld \n", leniwLS);
   printf(" Number of steps                       = %4ld \n", nst);
   printf(" Number of f-s (explicit)              = %4ld \n", nfe);
   printf(" Number of f-s (implicit)              = %4ld \n", nfi);
@@ -757,17 +763,15 @@ static void WebRates(realtype x, realtype y, realtype t, realtype c[],
  of a block-diagonal preconditioner. The blocks are of size mp, and
  there are ngrp=ngx*ngy blocks computed in the block-grouping scheme.
 */ 
-static int Precond(realtype t, N_Vector c, N_Vector fc,
-		   booleantype jok, booleantype *jcurPtr, realtype gamma,
-		   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3)
+static int Precond(realtype t, N_Vector c, N_Vector fc, booleantype jok,
+                   booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   realtype ***P;
   int ier;
-  long int **pivot;
+  sunindextype **pivot;
   int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
   int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
-  long int mp;
+  sunindextype mp;
   realtype uround, fac, r, r0, save, srur;
   realtype *f1, *fsave, *cdata, *rewtdata;
   WebData wdata;
@@ -800,7 +804,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
      Here, fsave contains the base value of the rate vector and 
      r0 is a minimum increment factor for the difference quotient. */
   
-  f1 = N_VGetArrayPointer(vtemp1);
+  f1 = N_VGetArrayPointer(wdata->tmp);
   
   fac = N_VWrmsNorm (fc, rewt);
   r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*NEQ*fac;
@@ -838,7 +842,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
     if (ier != 0) return(1);
   }
   
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
   return(0);
 }
 
@@ -870,15 +874,13 @@ static void fblock(realtype t, realtype cdata[], int jx, int jy,
   Then it computes ((I - gamma*Jr)-inverse)*z, using LU factors of the
   blocks in P, and pivot information in pivot, and returns the result in z.
 */
-static int PSolve(realtype tn, N_Vector c, N_Vector fc,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+static int PSolve(realtype tn, N_Vector c, N_Vector fc, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data)
 {
   realtype   ***P;
-  long int **pivot;
+  sunindextype **pivot;
   int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
-  long int mp;
+  sunindextype mp;
   WebData wdata;
   
   wdata = (WebData) user_data;
@@ -887,7 +889,7 @@ static int PSolve(realtype tn, N_Vector c, N_Vector fc,
   
   /* call GSIter for Gauss-Seidel iterations */
   
-  GSIter(gamma, z, vtemp, wdata);
+  GSIter(gamma, z, wdata->tmp, wdata);
   
   /* Do backsolves for inverse of block-diagonal preconditioner factor */
   
diff --git a/examples/arkode/C_serial/ark_KrylovDemo_prec.out b/examples/arkode/C_serial/ark_KrylovDemo_prec.out
index d8a9257..d1e06e8 100644
--- a/examples/arkode/C_serial/ark_KrylovDemo_prec.out
+++ b/examples/arkode/C_serial/ark_KrylovDemo_prec.out
@@ -418,10 +418,10 @@ Species 6
 
  Final statistics for this run:
 
- ARKode real workspace length           = 3298 
- ARKode integer workspace length        =   55 
- ARKSPGMR real workspace length         = 2206 
- ARKSPGMR integer workspace length      =   10 
+ ARKode real workspace length          = 3298 
+ ARKode integer workspace length       =   55 
+ SUNSPGMR real workspace length        = 2642 
+ SUNSPGMR integer workspace length     =   22 
  Number of steps                       =  258 
  Number of f-s (explicit)              =    0 
  Number of f-s (implicit)              = 4238 
@@ -487,10 +487,10 @@ t =   1.00e+01  nst = 264  nfe = 0  nfi = 4356  nni = 2901  hu =    9.24e-02
 
  Final statistics for this run:
 
- ARKode real workspace length           = 3298 
- ARKode integer workspace length        =   55 
- ARKSPGMR real workspace length         = 2206 
- ARKSPGMR integer workspace length      =   10 
+ ARKode real workspace length          = 3298 
+ ARKode integer workspace length       =   55 
+ SUNSPGMR real workspace length        = 2642 
+ SUNSPGMR integer workspace length     =   22 
  Number of steps                       =  264 
  Number of f-s (explicit)              =    0 
  Number of f-s (implicit)              = 4356 
@@ -556,10 +556,10 @@ t =   1.00e+01  nst = 359  nfe = 0  nfi = 5723  nni = 3907  hu =    1.35e-01
 
  Final statistics for this run:
 
- ARKode real workspace length           = 3298 
- ARKode integer workspace length        =   55 
- ARKSPGMR real workspace length         = 2206 
- ARKSPGMR integer workspace length      =   10 
+ ARKode real workspace length          = 3298 
+ ARKode integer workspace length       =   55 
+ SUNSPGMR real workspace length        = 2642 
+ SUNSPGMR integer workspace length     =   22 
  Number of steps                       =  359 
  Number of f-s (explicit)              =    0 
  Number of f-s (implicit)              = 5723 
@@ -625,10 +625,10 @@ t =   1.00e+01  nst = 359  nfe = 0  nfi = 5729  nni = 3912  hu =    1.31e-01
 
  Final statistics for this run:
 
- ARKode real workspace length           = 3298 
- ARKode integer workspace length        =   55 
- ARKSPGMR real workspace length         = 2206 
- ARKSPGMR integer workspace length      =   10 
+ ARKode real workspace length          = 3298 
+ ARKode integer workspace length       =   55 
+ SUNSPGMR real workspace length        = 2642 
+ SUNSPGMR integer workspace length     =   22 
  Number of steps                       =  359 
  Number of f-s (explicit)              =    0 
  Number of f-s (implicit)              = 5729 
diff --git a/examples/arkode/C_serial/ark_analytic.c b/examples/arkode/C_serial/ark_analytic.c
index beadb5e..6329e0b 100644
--- a/examples/arkode/C_serial/ark_analytic.c
+++ b/examples/arkode/C_serial/ark_analytic.c
@@ -28,7 +28,7 @@
  * than 100 the problem becomes quite stiff.
  * 
  * This program solves the problem with the DIRK method,
- * Newton iteration with the ARKDENSE dense linear solver, and a
+ * Newton iteration with the dense SUNLinearSolver, and a
  * user-supplied Jacobian routine.
  * Output is printed every 1.0 units of time (10 total).
  * Run statistics (optional outputs) are printed at the end.
@@ -37,21 +37,34 @@
 /* Header files */
 #include <stdio.h>
 #include <math.h>
-#include <arkode/arkode.h>           /* prototypes for ARKODE fcts., consts. */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_dense.h>     /* prototype for ARKDense */
-#include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
-#include <sundials/sundials_types.h> /* definition of type realtype */
+#include <arkode/arkode.h>                 /* prototypes for ARKODE fcts., consts. */
+#include <nvector/nvector_serial.h>        /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_dense.h>     /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h>     /* access to dense SUNLinearSolver      */
+#include <arkode/arkode_direct.h>          /* access to ARKDls interface           */
+#include <sundials/sundials_types.h>       /* definition of type realtype          */
+#include <sundials/sundials_math.h>
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
+/* Private function to check computed solution */
+static int check_ans(N_Vector y, realtype t, realtype rtol, realtype atol);
 
 /* Main Program */
 int main()
@@ -60,7 +73,7 @@ int main()
   realtype T0 = RCONST(0.0);      /* initial time */
   realtype Tf = RCONST(10.0);     /* final time */
   realtype dTout = RCONST(1.0);   /* time between outputs */
-  long int NEQ = 1;               /* number of dependent vars. */
+  sunindextype NEQ = 1;           /* number of dependent vars. */
   realtype reltol = 1.0e-6;       /* tolerances */
   realtype abstol = 1.0e-10;
   realtype lamda  = -100.0;       /* stiffness parameter */
@@ -68,6 +81,8 @@ int main()
   /* general problem variables */
   int flag;                       /* reusable error-checking flag */
   N_Vector y = NULL;              /* empty vector for storing solution */
+  SUNMatrix A = NULL;             /* empty matrix for linear solver */
+  SUNLinearSolver LS = NULL;      /* empty linear solver object */
   void *arkode_mem = NULL;        /* empty ARKode memory structure */
   FILE *UFID;
   realtype t, tout;
@@ -75,9 +90,9 @@ int main()
 
   /* Initial diagnostics output */
   printf("\nAnalytical ODE test problem:\n");
-  printf("    lamda = %g\n",    lamda);
-  printf("   reltol = %.1e\n",  reltol);
-  printf("   abstol = %.1e\n\n",abstol);
+  printf("    lamda = %"GSYM"\n",    lamda);
+  printf("   reltol = %.1"ESYM"\n",  reltol);
+  printf("   abstol = %.1"ESYM"\n\n",abstol);
 
   /* Initialize data structures */
   y = N_VNew_Serial(NEQ);          /* Create serial vector for solution */
@@ -99,11 +114,17 @@ int main()
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);  /* Specify tolerances */
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  /* Linear solver specification */
-  flag = ARKDense(arkode_mem, NEQ);                       /* Specify dense linear solver */
-  if (check_flag(&flag, "ARKDense", 1)) return 1;
-  flag = ARKDlsSetDenseJacFn(arkode_mem, Jac);            /* Set Jacobian routine */
-  if (check_flag(&flag, "ARKDlsSetDenseJacFn", 1)) return 1;
+  /* Initialize dense matrix data structure and solver */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)A, "SUNDenseMatrix", 0)) return 1;
+  LS = SUNDenseLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return 1;
+
+  /* Linear solver interface */
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);        /* Attach matrix and linear solver */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                 /* Set Jacobian routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
 
   /* Specify linearly implicit RHS, with non-time-dependent Jacobian */
   flag = ARKodeSetLinear(arkode_mem, 0);
@@ -114,7 +135,7 @@ int main()
   fprintf(UFID,"# t u\n");
 
   /* output initial condition to disk */
-  fprintf(UFID," %.16e %.16e\n", T0, NV_Ith_S(y,0));  
+  fprintf(UFID," %.16"ESYM" %.16"ESYM"\n", T0, NV_Ith_S(y,0));  
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
      prints results.  Stops when the final time has been reached */
@@ -126,8 +147,8 @@ int main()
 
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);      /* call integrator */
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %10.6f  %10.6f\n", t, NV_Ith_S(y,0));          /* access/print solution */
-    fprintf(UFID," %.16e %.16e\n", t, NV_Ith_S(y,0));  
+    printf("  %10.6"FSYM"  %10.6"FSYM"\n", t, NV_Ith_S(y,0));          /* access/print solution */
+    fprintf(UFID," %.16"ESYM" %.16"ESYM"\n", t, NV_Ith_S(y,0));  
     if (flag >= 0) {                                         /* successful solve: update time */
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -169,10 +190,16 @@ int main()
   printf("   Total number of linear solver convergence failures = %li\n", ncfn);
   printf("   Total number of error test failures = %li\n\n", netf);
 
-  /* Clean up and return with successful completion */
+  /* check the solution error */
+  flag = check_ans(y, t, reltol, abstol);
+
+  /* Clean up and return */
   N_VDestroy(y);            /* Free y vector */
   ARKodeFree(&arkode_mem);  /* Free integrator memory */
-  return 0;
+  SUNLinSolFree(LS);        /* Free linear solver */
+  SUNMatDestroy(A);         /* Free A matrix */
+ 
+  return flag;
 }
 
 /*-------------------------------
@@ -193,15 +220,15 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 }
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *rdata = (realtype *) user_data;   /* cast user_data to realtype */
   realtype lamda = rdata[0];                  /* set shortcut for stiffness parameter */
-
-  /* Fill in Jacobian of f: "DENSE_ELEM" accesses the (0,0) entry of J */
-  DENSE_ELEM(J,0,0) = lamda;
+  realtype *Jdata = SUNDenseMatrix_Data(J);
+  
+  /* Fill in Jacobian of f: set the first entry of the data array to set the (0,0) entry */
+  Jdata[0] = lamda;
 
   return 0;                                   /* return with success */
 }
@@ -245,5 +272,26 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
   return 0;
 }
 
+/* check the computed solution */
+static int check_ans(N_Vector y, realtype t, realtype rtol, realtype atol)
+{
+  int      passfail=0;     /* answer pass (0) or fail (1) flag     */  
+  realtype ans, err, ewt;  /* answer data, error, and error weight */
+  realtype ONE=RCONST(1.0);
+
+  /* compute solution error */
+  ans  = atan(t);
+  ewt = ONE / (rtol * SUNRabs(ans) + atol);
+  err = ewt * SUNRabs(NV_Ith_S(y,0) - ans);
+
+  /* is the solution within the tolerances? */
+  passfail = (err < ONE) ? 0 : 1; 
+
+  if (passfail) {
+    fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%g \n\n", err);
+  }
+
+  return(passfail);
+}
 
 /*---- end of file ----*/
diff --git a/examples/arkode/C_serial/ark_analytic_nonlin.c b/examples/arkode/C_serial/ark_analytic_nonlin.c
index 4b35bcd..4134914 100644
--- a/examples/arkode/C_serial/ark_analytic_nonlin.c
+++ b/examples/arkode/C_serial/ark_analytic_nonlin.c
@@ -37,6 +37,16 @@
 #include <sundials/sundials_types.h>  /* def. of type 'realtype' */
 #include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc. */
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
@@ -50,7 +60,7 @@ int main()
   realtype T0 = RCONST(0.0);     /* initial time */
   realtype Tf = RCONST(10.0);    /* final time */
   realtype dTout = RCONST(1.0);  /* time between outputs */
-  long int NEQ = 1;              /* number of dependent vars. */
+  sunindextype NEQ = 1;          /* number of dependent vars. */
   realtype reltol = 1.0e-6;      /* tolerances */
   realtype abstol = 1.0e-10;
 
@@ -64,8 +74,8 @@ int main()
 
   /* Initial problem output */
   printf("\nAnalytical ODE test problem:\n");
-  printf("   reltol = %.1e\n",  reltol);
-  printf("   abstol = %.1e\n\n",abstol);
+  printf("   reltol = %.1"ESYM"\n",  reltol);
+  printf("   abstol = %.1"ESYM"\n\n",abstol);
 
   /* Initialize data structures */
   y = N_VNew_Serial(NEQ);          /* Create serial vector for solution */
@@ -90,7 +100,7 @@ int main()
   fprintf(UFID,"# t u\n");
 
   /* output initial condition to disk */
-  fprintf(UFID," %.16e %.16e\n", T0, NV_Ith_S(y,0));  
+  fprintf(UFID," %.16"ESYM" %.16"ESYM"\n", T0, NV_Ith_S(y,0));  
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
      prints results.  Stops when the final time has been reached */
@@ -102,8 +112,8 @@ int main()
 
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);       /* call integrator */
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %10.6f  %10.6f\n", t, NV_Ith_S(y,0));           /* access/print solution */
-    fprintf(UFID," %.16e %.16e\n", t, NV_Ith_S(y,0));  
+    printf("  %10.6"FSYM"  %10.6"FSYM"\n", t, NV_Ith_S(y,0));           /* access/print solution */
+    fprintf(UFID," %.16"ESYM" %.16"ESYM"\n", t, NV_Ith_S(y,0));  
     if (flag >= 0) {                                          /* successful solve: update time */
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -131,7 +141,7 @@ int main()
   printf("   Total number of error test failures = %li\n\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);        /* Free y vector */
+  N_VDestroy(y);               /* Free y vector */
   ARKodeFree(&arkode_mem);     /* Free integrator memory */
   return 0;
 }
diff --git a/examples/arkode/C_serial/ark_brusselator.c b/examples/arkode/C_serial/ark_brusselator.c
index 9869114..731af32 100644
--- a/examples/arkode/C_serial/ark_brusselator.c
+++ b/examples/arkode/C_serial/ark_brusselator.c
@@ -50,7 +50,7 @@
  * This file is hard-coded to use test 2.
  * 
  * This program solves the problem with the DIRK method, using a
- * Newton iteration with the ARKDENSE dense linear solver, and a
+ * Newton iteration with the SUNDENSE dense linear solver, and a
  * user-supplied Jacobian routine.
  *
  * 100 outputs are printed at equal intervals, and run statistics 
@@ -60,16 +60,26 @@
 /* Header files */
 #include <stdio.h>
 #include <math.h>
-#include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
-#include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_dense.h>      /* prototype for ARKDense solver */
-#include <sundials/sundials_dense.h>  /* defs. of DlsMat and DENSE_ELEM */
-#include <sundials/sundials_types.h>  /* def. of type 'realtype' */
+#include <arkode/arkode.h>              /* prototypes for ARKode fcts., consts. */
+#include <nvector/nvector_serial.h>     /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_dense.h>  /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h>  /* access to dense SUNLinearSolver      */
+#include <arkode/arkode_direct.h>       /* access to ARKDls interface           */
+#include <sundials/sundials_types.h>    /* def. of type 'realtype' */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private function to check function return values */
@@ -82,7 +92,7 @@ int main()
   realtype T0 = RCONST(0.0);     /* initial time */
   realtype Tf = RCONST(10.0);    /* final time */
   realtype dTout = RCONST(1.0);  /* time between outputs */
-  long int NEQ = 3;              /* number of dependent vars. */
+  sunindextype NEQ = 3;          /* number of dependent vars. */
   int Nt = ceil(Tf/dTout);       /* number of output times */
   int test = 2;                  /* test problem to run */
   realtype reltol = 1.0e-6;      /* tolerances */
@@ -92,6 +102,8 @@ int main()
   /* general problem variables */
   int flag;                      /* reusable error-checking flag */
   N_Vector y = NULL;             /* empty vector for storing solution */
+  SUNMatrix A = NULL;            /* empty matrix for solver */
+  SUNLinearSolver LS = NULL;     /* empty linear solver object */
   void *arkode_mem = NULL;       /* empty ARKode memory structure */
   realtype rdata[3];
   FILE *UFID;
@@ -125,9 +137,9 @@ int main()
 
   /* Initial problem output */
   printf("\nBrusselator ODE test problem:\n");
-  printf("    initial conditions:  u0 = %g,  v0 = %g,  w0 = %g\n",u0,v0,w0);
-  printf("    problem parameters:  a = %g,  b = %g,  ep = %g\n",a,b,ep);
-  printf("    reltol = %.1e,  abstol = %.1e\n\n",reltol,abstol);
+  printf("    initial conditions:  u0 = %"GSYM",  v0 = %"GSYM",  w0 = %"GSYM"\n",u0,v0,w0);
+  printf("    problem parameters:  a = %"GSYM",  b = %"GSYM",  ep = %"GSYM"\n",a,b,ep);
+  printf("    reltol = %.1"ESYM",  abstol = %.1"ESYM"\n\n",reltol,abstol);
 
   /* Initialize data structures */
   rdata[0] = a;     /* set user data  */
@@ -154,18 +166,24 @@ int main()
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);    /* Specify tolerances */
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  /* Linear solver specification */
-  flag = ARKDense(arkode_mem, NEQ);                         /* Specify dense linear solver */
-  if (check_flag(&flag, "ARKDense", 1)) return 1;
-  flag = ARKDlsSetDenseJacFn(arkode_mem, Jac);              /* Set Jacobian routine */
-  if (check_flag(&flag, "ARKDlsSetDenseJacFn", 1)) return 1;
+  /* Initialize dense matrix data structure and solver */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)A, "SUNDenseMatrix", 0)) return 1;
+  LS = SUNDenseLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return 1;
+
+  /* Linear solver interface */
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);        /* Attach matrix and linear solver */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                 /* Set Jacobian routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
 
   /* Open output stream for results, output comment line */
   UFID = fopen("solution.txt","w");
   fprintf(UFID,"# t u v w\n");
 
   /* output initial condition to disk */
-  fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+  fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	  T0, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
@@ -178,9 +196,9 @@ int main()
 
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);      /* call integrator */
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %10.6f  %10.6f  %10.6f  %10.6f\n",             /* access/print solution */
+    printf("  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"\n",             /* access/print solution */
            t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));
-    fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+    fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	    t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
     if (flag >= 0) {                                         /* successful solve: update time */
       tout += dTout;
@@ -224,8 +242,10 @@ int main()
   printf("   Total number of error test failures = %li\n\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);        /* Free y vector */
+  N_VDestroy(y);               /* Free y vector */
   ARKodeFree(&arkode_mem);     /* Free integrator memory */
+  SUNLinSolFree(LS);           /* Free linear solver */
+  SUNMatDestroy(A);            /* Free A matrix */
   return 0;
 }
 
@@ -253,8 +273,7 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 }
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *rdata = (realtype *) user_data;   /* cast user_data to realtype */
@@ -263,20 +282,20 @@ static int Jac(long int N, realtype t,
   realtype v = NV_Ith_S(y,1);
   realtype w = NV_Ith_S(y,2);
 
-  /* fill in the Jacobian */
-  DENSE_ELEM(J,0,0) = -(w+1.0) + 2.0*u*v;
-  DENSE_ELEM(J,0,1) = u*u;
-  DENSE_ELEM(J,0,2) = -u;
+  /* fill in the Jacobian via SUNDenseMatrix macro, SM_ELEMENT_D (see sunmatrix_dense.h) */
+  SM_ELEMENT_D(J,0,0) = -(w+1.0) + 2.0*u*v;
+  SM_ELEMENT_D(J,0,1) = u*u;
+  SM_ELEMENT_D(J,0,2) = -u;
 
-  DENSE_ELEM(J,1,0) = w - 2.0*u*v;
-  DENSE_ELEM(J,1,1) = -u*u;
-  DENSE_ELEM(J,1,2) = u;
+  SM_ELEMENT_D(J,1,0) = w - 2.0*u*v;
+  SM_ELEMENT_D(J,1,1) = -u*u;
+  SM_ELEMENT_D(J,1,2) = u;
 
-  DENSE_ELEM(J,2,0) = -w;
-  DENSE_ELEM(J,2,1) = 0.0;
-  DENSE_ELEM(J,2,2) = -1.0/ep - u;
+  SM_ELEMENT_D(J,2,0) = -w;
+  SM_ELEMENT_D(J,2,1) = 0.0;
+  SM_ELEMENT_D(J,2,2) = -1.0/ep - u;
 
-  return 0;                                  /* Return with success */
+  return 0;                                   /* Return with success */
 }
 
 /*-------------------------------
diff --git a/examples/arkode/C_serial/ark_brusselator1D.c b/examples/arkode/C_serial/ark_brusselator1D.c
index e704619..e198995 100644
--- a/examples/arkode/C_serial/ark_brusselator1D.c
+++ b/examples/arkode/C_serial/ark_brusselator1D.c
@@ -39,7 +39,7 @@
  * on a uniform spatial grid.
  *
  * This program solves the problem with the DIRK method, using a
- * Newton iteration with the ARKBAND band linear solver, and a
+ * Newton iteration with the SUNBAND band linear solver, and a
  * user-supplied Jacobian routine.
  *
  * 100 outputs are printed at equal intervals, and run statistics 
@@ -50,38 +50,47 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
-#include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
-#include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_band.h>       /* prototype for ARKBand solver */
-#include <sundials/sundials_band.h>   /* defs. of DlsMat and BAND_ELEM */
-#include <sundials/sundials_types.h>  /* def. of type 'realtype' */
-#include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc. */
+#include <arkode/arkode.h>             /* prototypes for ARKode fcts., consts. */
+#include <nvector/nvector_serial.h>    /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <arkode/arkode_direct.h>      /* access to ARKDls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype, etc */
+#include <sundials/sundials_math.h>    /* def. of SUNRsqrt, etc.               */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* accessor macros between (x,v) location and 1D NVector array */
 #define IDX(x,v) (3*(x)+v)
 
 /* user data structure */
 typedef struct {
-  long int N;    /* number of intervals     */
-  realtype dx;   /* mesh spacing            */
-  realtype a;    /* constant forcing on u   */
-  realtype b;    /* steady-state value of w */
-  realtype du;   /* diffusion coeff for u   */
-  realtype dv;   /* diffusion coeff for v   */
-  realtype dw;   /* diffusion coeff for w   */
-  realtype ep;   /* stiffness parameter     */
+  sunindextype N;  /* number of intervals     */
+  realtype dx;     /* mesh spacing            */
+  realtype a;      /* constant forcing on u   */
+  realtype b;      /* steady-state value of w */
+  realtype du;     /* diffusion coeff for u   */
+  realtype dv;     /* diffusion coeff for v   */
+  realtype dw;     /* diffusion coeff for w   */
+  realtype ep;     /* stiffness parameter     */
 } *UserData;
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector y, N_Vector fy,
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private helper functions  */
-static int LaplaceMatrix(realtype c, DlsMat Jac, UserData udata);
-static int ReactionJac(realtype c, N_Vector y, DlsMat Jac, UserData udata);
+static int LaplaceMatrix(realtype c, SUNMatrix Jac, UserData udata);
+static int ReactionJac(realtype c, N_Vector y, SUNMatrix Jac, UserData udata);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -96,7 +105,7 @@ int main()
   int Nvar = 3;                 /* number of solution fields */
   UserData udata = NULL;
   realtype *data;
-  long int N = 201;             /* spatial mesh size */
+  sunindextype N = 201;         /* spatial mesh size */
   realtype a = 0.6;             /* problem parameters */
   realtype b = 2.0;
   realtype du = 0.025;
@@ -105,7 +114,7 @@ int main()
   realtype ep = 1.0e-5;         /* stiffness parameter */
   realtype reltol = 1.0e-6;     /* tolerances */
   realtype abstol = 1.0e-10;
-  long int NEQ, i;
+  sunindextype NEQ, i;
 
   /* general problem variables */
   int flag;                     /* reusable error-checking flag */
@@ -113,6 +122,8 @@ int main()
   N_Vector umask = NULL;        /* empty mask vectors for viewing solution components */
   N_Vector vmask = NULL;
   N_Vector wmask = NULL;
+  SUNMatrix A = NULL;           /* empty matrix object for solver */
+  SUNLinearSolver LS = NULL;    /* empty linear solver object */
   void *arkode_mem = NULL;      /* empty ARKode memory structure */
   realtype pi, t, dTout, tout, u, v, w;
   FILE *FID, *UFID, *VFID, *WFID;
@@ -137,12 +148,12 @@ int main()
 
   /* Initial problem output */
   printf("\n1D Brusselator PDE test problem:\n");
-  printf("    N = %li,  NEQ = %li\n", udata->N, NEQ);
-  printf("    problem parameters:  a = %g,  b = %g,  ep = %g\n",
+  printf("    N = %li,  NEQ = %li\n", (long int) udata->N, (long int) NEQ);
+  printf("    problem parameters:  a = %"GSYM",  b = %"GSYM",  ep = %"GSYM"\n",
       udata->a, udata->b, udata->ep);
-  printf("    diffusion coefficients:  du = %g,  dv = %g,  dw = %g\n",
+  printf("    diffusion coefficients:  du = %"GSYM",  dv = %"GSYM",  dw = %"GSYM"\n",
       udata->du, udata->dv, udata->dw);
-  printf("    reltol = %.1e,  abstol = %.1e\n\n", reltol, abstol);
+  printf("    reltol = %.1"ESYM",  abstol = %.1"ESYM"\n\n", reltol, abstol);
 
   /* Initialize data structures */
   y = N_VNew_Serial(NEQ);           /* Create serial vector for solution */
@@ -198,15 +209,21 @@ int main()
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);    /* Specify tolerances */
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  /* Linear solver specification */
-  flag = ARKBand(arkode_mem, NEQ, 4, 4);          /* Specify the band linear solver */
-  if (check_flag(&flag, "ARKBand", 1)) return 1;
-  flag = ARKDlsSetBandJacFn(arkode_mem, Jac);     /* Set the Jacobian routine */
-  if (check_flag(&flag, "ARKDlsSetBandJacFn", 1)) return 1;
+  /* Initialize band matrix data structure and solver -- A will be factored, so set smu to ml+mu */
+  A = SUNBandMatrix(NEQ, 4, 4, 8);
+  if (check_flag((void *)A, "SUNBandMatrix", 0)) return 1;
+  LS = SUNBandLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNBandLinearSolver", 0)) return 1;
+  
+  /* Linear solver interface */
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);        /* Attach matrix and linear solver */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                 /* Set the Jacobian routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
 
   /* output spatial mesh to disk */
   FID = fopen("bruss_mesh.txt","w");
-  for (i=0; i<N; i++)  fprintf(FID,"  %.16e\n", udata->dx*i);
+  for (i=0; i<N; i++)  fprintf(FID,"  %.16"ESYM"\n", udata->dx*i);
   fclose(FID);
 
   /* Open output streams for results, access data array */
@@ -217,9 +234,9 @@ int main()
   /* output initial condition to disk */
   data = N_VGetArrayPointer(y);
   if (check_flag((void *)data, "N_VGetArrayPointer", 0)) return 1;
-  for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-  for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-  for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+  for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM"", data[IDX(i,0)]);
+  for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM"", data[IDX(i,1)]);
+  for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM"", data[IDX(i,2)]);
   fprintf(UFID,"\n");
   fprintf(VFID,"\n");
   fprintf(WFID,"\n");
@@ -241,7 +258,7 @@ int main()
     v = SUNRsqrt(v*v/N);
     w = N_VWL2Norm(y,wmask);
     w = SUNRsqrt(w*w/N);
-    printf("  %10.6f  %10.6f  %10.6f  %10.6f\n", t, u, v, w);
+    printf("  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"\n", t, u, v, w);
     if (flag >= 0) {                                       /* successful solve: update output time */
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -251,9 +268,9 @@ int main()
     }
 
     /* output results to disk */
-    for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-    for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-    for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+    for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM"", data[IDX(i,0)]);
+    for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM"", data[IDX(i,1)]);
+    for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM"", data[IDX(i,2)]);
     fprintf(UFID,"\n");
     fprintf(VFID,"\n");
     fprintf(WFID,"\n");
@@ -294,12 +311,14 @@ int main()
   printf("   Total number of error test failures = %li\n\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);         /* Free vectors */
-  N_VDestroy_Serial(umask);
-  N_VDestroy_Serial(vmask);
-  N_VDestroy_Serial(wmask);
+  N_VDestroy(y);                /* Free vectors */
+  N_VDestroy(umask);
+  N_VDestroy(vmask);
+  N_VDestroy(wmask);
   free(udata);                  /* Free user data */
   ARKodeFree(&arkode_mem);      /* Free integrator memory */
+  SUNLinSolFree(LS);            /* Free linear solver */
+  SUNMatDestroy(A);             /* Free A matrix */
   return 0;
 }
 
@@ -311,7 +330,7 @@ int main()
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
   UserData udata = (UserData) user_data;      /* access problem data */
-  long int N  = udata->N;                     /* set variable shortcuts */
+  sunindextype N = udata->N;                  /* set variable shortcuts */
   realtype a  = udata->a;
   realtype b  = udata->b;
   realtype ep = udata->ep;
@@ -321,7 +340,7 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   realtype dx = udata->dx;
   realtype *Ydata=NULL, *dYdata=NULL;
   realtype uconst, vconst, wconst, u, ul, ur, v, vl, vr, w, wl, wr;
-  long int i;
+  sunindextype i;
 
   Ydata = N_VGetArrayPointer(y);     /* access data arrays */
   if (check_flag((void *)Ydata, "N_VGetArrayPointer", 0)) return 1;
@@ -357,13 +376,11 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 }
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
-static int Jac(long int M, long int mu, long int ml,
-               realtype t, N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   UserData udata = (UserData) user_data;     /* access problem data */
-  SetToZero(J);                              /* Initialize Jacobian to zero */
+  SUNMatZero(J);                             /* Initialize Jacobian to zero */
 
   /* Fill in the Laplace matrix */
   LaplaceMatrix(RCONST(1.0), J, udata);
@@ -380,23 +397,24 @@ static int Jac(long int M, long int mu, long int ml,
 
 /* Routine to compute the stiffness matrix from (L*y), scaled by the factor c.
    We add the result into Jac and do not erase what was already there */
-static int LaplaceMatrix(realtype c, DlsMat Jac, UserData udata)
+static int LaplaceMatrix(realtype c, SUNMatrix Jac, UserData udata)
 {
-  long int i;                /* set shortcuts */
-  long int N = udata->N;
+  sunindextype N = udata->N;           /* set shortcuts */
   realtype dx = udata->dx;
+  sunindextype i;
 
-  /* iterate over intervals, filling in Jacobian of (L*y) */
+  /* iterate over intervals, filling in Jacobian of (L*y) using SM_ELEMENT_B 
+     macro (see sunmatrix_band.h) */
   for (i=1; i<N-1; i++) {
-    BAND_ELEM(Jac,IDX(i,0),IDX(i-1,0)) += c*udata->du/dx/dx;
-    BAND_ELEM(Jac,IDX(i,1),IDX(i-1,1)) += c*udata->dv/dx/dx;
-    BAND_ELEM(Jac,IDX(i,2),IDX(i-1,2)) += c*udata->dw/dx/dx;
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,0)) += -c*RCONST(2.0)*udata->du/dx/dx;
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,1)) += -c*RCONST(2.0)*udata->dv/dx/dx;
-    BAND_ELEM(Jac,IDX(i,2),IDX(i,2)) += -c*RCONST(2.0)*udata->dw/dx/dx;
-    BAND_ELEM(Jac,IDX(i,0),IDX(i+1,0)) += c*udata->du/dx/dx;
-    BAND_ELEM(Jac,IDX(i,1),IDX(i+1,1)) += c*udata->dv/dx/dx;
-    BAND_ELEM(Jac,IDX(i,2),IDX(i+1,2)) += c*udata->dw/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i-1,0)) += c*udata->du/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i-1,1)) += c*udata->dv/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i-1,2)) += c*udata->dw/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,0)) += -c*RCONST(2.0)*udata->du/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,1)) += -c*RCONST(2.0)*udata->dv/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i,2)) += -c*RCONST(2.0)*udata->dw/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i+1,0)) += c*udata->du/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i+1,1)) += c*udata->dv/dx/dx;
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i+1,2)) += c*udata->dw/dx/dx;
   }
 
   return 0;                  /* Return with success */
@@ -404,12 +422,12 @@ static int LaplaceMatrix(realtype c, DlsMat Jac, UserData udata)
 
 /* Routine to compute the Jacobian matrix from R(y), scaled by the factor c.
    We add the result into Jac and do not erase what was already there */
-static int ReactionJac(realtype c, N_Vector y, DlsMat Jac, UserData udata)
+static int ReactionJac(realtype c, N_Vector y, SUNMatrix Jac, UserData udata)
 {
-  long int N  = udata->N;                      /* set shortcuts */
-  long int i;
-  realtype u, v, w;
+  sunindextype N = udata->N;                      /* set shortcuts */
   realtype ep = udata->ep;
+  sunindextype i;
+  realtype u, v, w;
   realtype *Ydata = N_VGetArrayPointer(y);     /* access solution array */
   if (check_flag((void *)Ydata, "N_VGetArrayPointer", 0)) return 1;
 
@@ -421,18 +439,18 @@ static int ReactionJac(realtype c, N_Vector y, DlsMat Jac, UserData udata)
     w = Ydata[IDX(i,2)];
 
     /* all vars wrt u */
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,0)) += c*(RCONST(2.0)*u*v-(w+RCONST(1.0)));
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,0)) += c*(w - RCONST(2.0)*u*v);
-    BAND_ELEM(Jac,IDX(i,2),IDX(i,0)) += c*(-w);
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,0)) += c*(RCONST(2.0)*u*v-(w+RCONST(1.0)));
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,0)) += c*(w - RCONST(2.0)*u*v);
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i,0)) += c*(-w);
 
     /* all vars wrt v */
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,1)) += c*(u*u);
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,1)) += c*(-u*u);
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,1)) += c*(u*u);
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,1)) += c*(-u*u);
 
     /* all vars wrt w */
-    BAND_ELEM(Jac,IDX(i,0),IDX(i,2)) += c*(-u);
-    BAND_ELEM(Jac,IDX(i,1),IDX(i,2)) += c*(u);
-    BAND_ELEM(Jac,IDX(i,2),IDX(i,2)) += c*(-RCONST(1.0)/ep - u);
+    SM_ELEMENT_B(Jac,IDX(i,0),IDX(i,2)) += c*(-u);
+    SM_ELEMENT_B(Jac,IDX(i,1),IDX(i,2)) += c*(u);
+    SM_ELEMENT_B(Jac,IDX(i,2),IDX(i,2)) += c*(-RCONST(1.0)/ep - u);
 
   }
 
diff --git a/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c b/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c
index 0546ddc..b9bc605 100644
--- a/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c
+++ b/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c
@@ -54,7 +54,7 @@
  * and the mass matrix, M.
  *
  * This program solves the problem with the DIRK method, using a
- * Newton iteration with the ARKSUPERLUMT sparse linear solver.
+ * Newton iteration with the SuperLU_MT SUNLinearSolver.
  *
  * 100 outputs are printed at equal time intervals, and run 
  * statistics are printed at the end.
@@ -64,13 +64,23 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
-#include <arkode/arkode.h>             /* prototypes for ARKode fcts., consts. */
-#include <nvector/nvector_serial.h>    /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_superlumt.h>   /* prototype for ARKSuperLUMT solver */
-#include <sundials/sundials_types.h>   /* def. of type 'realtype' */
-#include <sundials/sundials_math.h>    /* def. of SUNRsqrt, etc. */
-#include <sundials/sundials_sparse.h>  /* defs. of SlsMat and SlsMat routines */
-
+#include <arkode/arkode.h>                  /* prototypes for ARKode fcts., consts. */
+#include <nvector/nvector_serial.h>         /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_sparse.h>     /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h>  /* access to SuperLU_MT SUNLinearSolver */
+#include <arkode/arkode_direct.h>           /* access to ARKDls interface           */
+#include <sundials/sundials_types.h>        /* defs. of realtype, sunindextype, etc */
+#include <sundials/sundials_math.h>         /* def. of SUNRsqrt, etc.               */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* accessor macros between (x,v) location and 1D NVector array */
 /* [variables are grouped according to spatial location] */
@@ -102,16 +112,16 @@
 
 /* user data structure */
 typedef struct {  
-  int N;         /* number of intervals     */
-  realtype *x;   /* mesh node locations     */
-  realtype a;    /* constant forcing on u   */
-  realtype b;    /* steady-state value of w */
-  realtype du;   /* diffusion coeff for u   */
-  realtype dv;   /* diffusion coeff for v   */
-  realtype dw;   /* diffusion coeff for w   */
-  realtype ep;   /* stiffness parameter     */
-  N_Vector tmp;  /* temporary vector        */
-  SlsMat R;      /* temporary storage       */
+  sunindextype N;   /* number of intervals     */
+  realtype *x;      /* mesh node locations     */
+  realtype a;       /* constant forcing on u   */
+  realtype b;       /* steady-state value of w */
+  realtype du;      /* diffusion coeff for u   */
+  realtype dv;      /* diffusion coeff for v   */
+  realtype dw;      /* diffusion coeff for w   */
+  realtype ep;      /* stiffness parameter     */
+  N_Vector tmp;     /* temporary vector        */
+  SUNMatrix R;      /* temporary storage       */
 } *UserData;
 
 
@@ -119,15 +129,14 @@ typedef struct {
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 static int f_diff(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 static int f_rx(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int MassMatrix(realtype t, SlsMat M, void *user_data, 
+static int MassMatrix(realtype t, SUNMatrix M, void *user_data, 
 		      N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int Jac(realtype t, N_Vector y, N_Vector fy, 
-               SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private helper functions  */
-static int LaplaceMatrix(SlsMat Jac, UserData udata);
-static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata);
+static int LaplaceMatrix(SUNMatrix Jac, UserData udata);
+static int ReactionJac(N_Vector y, SUNMatrix Jac, UserData udata);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -142,7 +151,7 @@ int main(int argc, char *argv[]) {
   int Nvar = 3;                 /* number of solution fields */
   UserData udata = NULL;
   realtype *data;
-  int N = 201;                  /* spatial mesh size */
+  sunindextype N = 201;         /* spatial mesh size */
   realtype a = 0.6;             /* problem parameters */
   realtype b = 2.0;
   realtype du = 0.025;
@@ -151,7 +160,8 @@ int main(int argc, char *argv[]) {
   realtype ep = 1.0e-5;         /* stiffness parameter */
   realtype reltol = 1.0e-6;     /* tolerances */
   realtype abstol = 1.0e-10;
-  int i, NEQ, NNZ, num_threads;
+  sunindextype i, NEQ, NNZ;
+  int num_threads;
 
   /* general problem variables */
   int flag;                     /* reusable error-checking flag */
@@ -159,12 +169,16 @@ int main(int argc, char *argv[]) {
   N_Vector umask = NULL;
   N_Vector vmask = NULL;
   N_Vector wmask = NULL;
+  SUNMatrix A = NULL;           /* empty matrix object for solver */
+  SUNMatrix M = NULL;           /* empty mass matrix object */
+  SUNLinearSolver LS = NULL;    /* empty linear solver object */
+  SUNLinearSolver MLS = NULL;   /* empty mass matrix solver object */
   void *arkode_mem = NULL;
   FILE *FID, *UFID, *VFID, *WFID;
   realtype h, z, t, dTout, tout, u, v, w, pi;
   int iout;
   long int nst, nst_a, nfe, nfi, nsetups, nje, nni, ncfn;
-  long int netf, nms, nMv;
+  long int netf, nmset, nms, nMv;
 
   /* if a command-line argument was supplied, set num_threads */
   num_threads = 1;
@@ -192,13 +206,13 @@ int main(int argc, char *argv[]) {
 
   /* Initial problem output */
   printf("\n1D FEM Brusselator PDE test problem:\n");
-  printf("    N = %i,  NEQ = %i\n", udata->N, NEQ);
+  printf("    N = %li,  NEQ = %li\n", (long int) udata->N, (long int) NEQ);
   printf("    num_threads = %i\n", num_threads);
-  printf("    problem parameters:  a = %g,  b = %g,  ep = %g\n",
+  printf("    problem parameters:  a = %"GSYM",  b = %"GSYM",  ep = %"GSYM"\n",
 	 udata->a, udata->b, udata->ep);
-  printf("    diffusion coefficients:  du = %g,  dv = %g,  dw = %g\n", 
+  printf("    diffusion coefficients:  du = %"GSYM",  dv = %"GSYM",  dw = %"GSYM"\n", 
 	 udata->du, udata->dv, udata->dw);
-  printf("    reltol = %.1e,  abstol = %.1e\n\n", reltol, abstol);
+  printf("    reltol = %.1"ESYM",  abstol = %.1"ESYM"\n\n", reltol, abstol);
 
   /* Initialize data structures */
   y = N_VNew_Serial(NEQ);           /* Create serial vector for solution */
@@ -268,19 +282,33 @@ int main(int argc, char *argv[]) {
   flag = ARKodeResStolerance(arkode_mem, abstol);           /* Specify residual tolerance */
   if (check_flag(&flag, "ARKodeResStolerance", 1)) return 1;
 
-  /* Linear solver specification */
+  /* Initialize sparse matrix data structure and SuperLU_MT solvers (system and mass) */
   NNZ = 15*NEQ;
-  flag = ARKSuperLUMT(arkode_mem, num_threads, NEQ, NNZ);   /* SuperLUMT sparse solver */
-  if (check_flag(&flag, "ARKSuperLUMT", 1)) return 1;
-  flag = ARKSlsSetSparseJacFn(arkode_mem, Jac);             /* Set the Jacobian routine */
-  if (check_flag(&flag, "ARKSlsSetSparseJacFn", 1)) return 1;
-  flag = ARKMassSuperLUMT(arkode_mem, num_threads,          /* Mass matrix linear solver */
-			  NEQ, NNZ, MassMatrix);
-  if (check_flag(&flag, "ARKMassSuperLUMT", 1)) return 1;
+  A = SUNSparseMatrix(NEQ, NEQ, NNZ, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return 1;
+  LS = SUNSuperLUMT(y, A, num_threads);
+  if (check_flag((void *)LS, "SUNSuperLUMT", 0)) return 1;
+  M = SUNSparseMatrix(NEQ, NEQ, NNZ, CSC_MAT);
+  if (check_flag((void *)M, "SUNSparseMatrix", 0)) return 1;
+  MLS = SUNSuperLUMT(y, M, num_threads);
+  if (check_flag((void *)MLS, "SUNSuperLUMT", 0)) return 1;
+  
+  /* Attach the matrix, linear solver, and Jacobian construction routine to ARKode */
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);        /* Attach matrix and LS */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                 /* Supply Jac routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
+
+  /* Attach the mass matrix, linear solver and construction routines to ARKode;
+     notify ARKode that the mass matrix is not time-dependent */
+  flag = ARKDlsSetMassLinearSolver(arkode_mem, MLS, M, SUNFALSE);   /* Attach matrix and LS */
+  if (check_flag(&flag, "ARKDlsSetMassLinearSolver", 1)) return 1;
+  flag = ARKDlsSetMassFn(arkode_mem, MassMatrix);                /* Supply M routine */
+  if (check_flag(&flag, "ARKDlsSetMassFn", 1)) return 1;
 
   /* output mesh to disk */
   FID=fopen("bruss_FEM_mesh.txt","w");
-  for (i=0; i<N; i++)  fprintf(FID,"  %.16e\n", udata->x[i]);
+  for (i=0; i<N; i++)  fprintf(FID,"  %.16"ESYM"\n", udata->x[i]);
   fclose(FID);
 
   /* Open output stream for results, access data arrays */
@@ -291,9 +319,9 @@ int main(int argc, char *argv[]) {
   if (check_flag((void *)data, "N_VGetArrayPointer", 0)) return 1;
 
   /* output initial condition to disk */
-  for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-  for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-  for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+  for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM, data[IDX(i,0)]);
+  for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM, data[IDX(i,1)]);
+  for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM, data[IDX(i,2)]);
   fprintf(UFID,"\n");
   fprintf(VFID,"\n");
   fprintf(WFID,"\n");
@@ -315,7 +343,7 @@ int main(int argc, char *argv[]) {
     v = SUNRsqrt(v*v/N);
     w = N_VWL2Norm(y,wmask);
     w = SUNRsqrt(w*w/N);
-    printf("  %10.6f  %10.6f  %10.6f  %10.6f\n", t, u, v, w);
+    printf("  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"\n", t, u, v, w);
     if (flag >= 0) {                                       /* successful solve: update output time */
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -325,9 +353,9 @@ int main(int argc, char *argv[]) {
     }
 
     /* output results to disk */
-    for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-    for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-    for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+    for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM, data[IDX(i,0)]);
+    for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM, data[IDX(i,1)]);
+    for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM, data[IDX(i,2)]);
     fprintf(UFID,"\n");
     fprintf(VFID,"\n");
     fprintf(WFID,"\n");
@@ -352,17 +380,21 @@ int main(int argc, char *argv[]) {
   check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1);
   flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn);
   check_flag(&flag, "ARKodeGetNumNonlinSolvConvFails", 1);
-  flag = ARKodeGetNumMassSolves(arkode_mem, &nms);
-  check_flag(&flag, "ARKodeGetNumMassSolves", 1);
-  flag = ARKodeGetNumMassMultiplies(arkode_mem, &nMv);
-  check_flag(&flag, "ARKodeGetNumMassMultiplies", 1);
-  flag = ARKSlsGetNumJacEvals(arkode_mem, &nje);
-  check_flag(&flag, "ARKSlsGetNumJacEvals", 1);
+  flag = ARKDlsGetNumMassSetups(arkode_mem, &nmset);
+  check_flag(&flag, "ARKDlsGetNumMassSetups", 1);
+  flag = ARKDlsGetNumMassSolves(arkode_mem, &nms);
+  check_flag(&flag, "ARKDlsGetNumMassSolves", 1);
+  flag = ARKDlsGetNumMassMult(arkode_mem, &nMv);
+  check_flag(&flag, "ARKDlsGetNumMassMult", 1);
+  flag = ARKDlsGetNumJacEvals(arkode_mem, &nje);
+  check_flag(&flag, "ARKDlsGetNumJacEvals", 1);
 
   printf("\nFinal Solver Statistics:\n");
   printf("   Internal solver steps = %li (attempted = %li)\n", nst, nst_a);
   printf("   Total RHS evals:  Fe = %li,  Fi = %li\n", nfe, nfi);
+  printf("   Total mass matrix setups = %li\n", nmset);
   printf("   Total mass matrix solves = %li\n", nms);
+  printf("   Total mass times evals = %li\n", nMv);
   printf("   Total linear solver setups = %li\n", nsetups);
   printf("   Total number of Jacobian evaluations = %li\n", nje);
   printf("   Total number of Newton iterations = %li\n", nni);
@@ -370,15 +402,19 @@ int main(int argc, char *argv[]) {
   printf("   Total number of error test failures = %li\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);            /* Free vectors */
-  N_VDestroy_Serial(umask);
-  N_VDestroy_Serial(vmask);
-  N_VDestroy_Serial(wmask);
-  SparseDestroyMat(udata->R);      /* Free user data */
-  N_VDestroy_Serial(udata->tmp);
+  N_VDestroy(y);                   /* Free vectors */
+  N_VDestroy(umask);
+  N_VDestroy(vmask);
+  N_VDestroy(wmask);
+  SUNMatDestroy(udata->R);         /* Free user data */
+  N_VDestroy(udata->tmp);
   free(udata->x);
   free(udata);
   ARKodeFree(&arkode_mem);         /* Free integrator memory */
+  SUNLinSolFree(LS);               /* Free linear solvers */
+  SUNLinSolFree(MLS);
+  SUNMatDestroy(A);                /* Free matrices */
+  SUNMatDestroy(M);
   return 0;
 }
 
@@ -418,13 +454,13 @@ static int f_diff(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
   UserData udata = (UserData) user_data;
 
   /* shortcuts to number of intervals, background values */
-  int N = udata->N;
+  sunindextype N = udata->N;
   realtype du = udata->du;
   realtype dv = udata->dv;
   realtype dw = udata->dw;
 
   /* local variables */
-  long int i;
+  sunindextype i;
   realtype ul, ur, vl, vr, wl, wr;
   realtype xl, xr, f1;
   booleantype left, right;
@@ -440,8 +476,8 @@ static int f_diff(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
   for (i=0; i<N-1; i++) {
 
     /* set booleans to determine whether equations exist on the left/right */
-    left  = (i==0)     ? FALSE : TRUE;
-    right = (i==(N-2)) ? FALSE : TRUE;
+    left  = (i==0)     ? SUNFALSE : SUNTRUE;
+    right = (i==(N-2)) ? SUNFALSE : SUNTRUE;
 
     /* set nodal value shortcuts (interval index aligns with left node) */
     ul = Ydata[IDX(i,0)];
@@ -499,13 +535,13 @@ static int f_rx(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
   UserData udata = (UserData) user_data;
 
   /* shortcuts to number of intervals, background values */
-  int N = udata->N;
+  sunindextype N = udata->N;
   realtype a  = udata->a;
   realtype b  = udata->b;
   realtype ep = udata->ep;
 
   /* local variables */
-  long int i;
+  sunindextype i;
   realtype ul, ur, vl, vr, wl, wr;
   realtype u, v, w, xl, xr, f1, f2, f3;
   booleantype left, right;
@@ -521,8 +557,8 @@ static int f_rx(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
   for (i=0; i<N-1; i++) {
 
     /* set booleans to determine whether equations exist on the left/right */
-    left  = (i==0)     ? FALSE : TRUE;
-    right = (i==(N-2)) ? FALSE : TRUE;
+    left  = (i==0)     ? SUNFALSE : SUNTRUE;
+    right = (i==(N-2)) ? SUNFALSE : SUNTRUE;
 
     /* set nodal value shortcuts (interval index aligns with left node) */
     ul = Ydata[IDX(i,0)];
@@ -639,17 +675,17 @@ static int f_rx(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
 
 
 /* Interface routine to compute the Jacobian of the full RHS function, f(y) */
-static int Jac(realtype t, N_Vector y, N_Vector fy, 
-               SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
 
   /* temporary variables */
   int ier;
   UserData udata = (UserData) user_data;
-  int N = udata->N;
+  sunindextype N = udata->N;
 
   /* ensure that Jac is the correct size */
-  if ((J->M != N*3) || (J->N != N*3)) {
+  if ( (SUNSparseMatrix_Rows(J) != N*3) ||
+       (SUNSparseMatrix_Columns(J) != N*3) ) {
     printf("Jacobian calculation error: matrix is the wrong size!\n");
     return 1;
   }
@@ -663,7 +699,9 @@ static int Jac(realtype t, N_Vector y, N_Vector fy,
 
   /* Create empty reaction Jacobian matrix (if not done already) */
   if (udata->R == NULL) {
-    udata->R = SparseNewMat(J->M, J->N, J->NNZ, CSC_MAT);
+    udata->R = SUNSparseMatrix(SUNSparseMatrix_Rows(J),
+                               SUNSparseMatrix_Columns(J),
+                               SUNSparseMatrix_NNZ(J), CSC_MAT);
     if (udata->R == NULL) {
       printf("Jac: error in allocating R matrix!\n");
       return 1;
@@ -678,7 +716,7 @@ static int Jac(realtype t, N_Vector y, N_Vector fy,
   }
 
   /* Add R to J */
-  ier = SparseAddMat(J,udata->R);
+  ier = SUNMatScaleAdd(ONE, J, udata->R);
   if (ier != 0) {
     printf("Jac: error in adding sparse matrices = %i!\n",ier);
     return 1;
@@ -690,23 +728,24 @@ static int Jac(realtype t, N_Vector y, N_Vector fy,
 
 
 /* Routine to compute the mass matrix multiplying y_t. */
-static int MassMatrix(realtype t, SlsMat M, void *user_data, 
+static int MassMatrix(realtype t, SUNMatrix M, void *user_data, 
 		      N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) {
 
   /* user data structure */
   UserData udata = (UserData) user_data;
 
   /* set shortcuts */
-  int N = udata->N;
-  int i, nz=0;
-  int *colptrs = *M->colptrs;
-  int *rowvals = *M->rowvals;
+  sunindextype N = udata->N;
+  sunindextype i, nz=0;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(M);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(M);
+  realtype *data = SUNSparseMatrix_Data(M);
 
   /* local data */
   realtype xl, xr, f1, f2, f3, dtmp;
 
   /* clear out mass matrix */
-  SparseSetMatToZero(M);
+  SUNMatZero(M);
 
   /* iterate over columns, filling in matrix entries */
   for (i=0; i<N; i++) {
@@ -721,7 +760,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f1 = ChiL(xl,xr,X1(xl,xr)) * ChiR(xl,xr,X1(xl,xr));
       f2 = ChiL(xl,xr,X2(xl,xr)) * ChiR(xl,xr,X2(xl,xr));
       f3 = ChiL(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
-      M->data[nz] = Quad(f1,f2,f3,xl,xr);
+      data[nz] = Quad(f1,f2,f3,xl,xr);
       rowvals[nz++] = IDX(i-1,0);
     }
     /*    this u trial function */
@@ -742,7 +781,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f3 = ChiR(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
       dtmp += Quad(f1,f2,f3,xl,xr);
     }
-    M->data[nz] = dtmp;
+    data[nz] = dtmp;
     rowvals[nz++] = IDX(i,0);
     /*    right u trial function */
     if (i<N-1) {
@@ -751,7 +790,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f1 = ChiL(xl,xr,X1(xl,xr)) * ChiR(xl,xr,X1(xl,xr));
       f2 = ChiL(xl,xr,X2(xl,xr)) * ChiR(xl,xr,X2(xl,xr));
       f3 = ChiL(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
-      M->data[nz] = Quad(f1,f2,f3,xl,xr);
+      data[nz] = Quad(f1,f2,f3,xl,xr);
       rowvals[nz++] = IDX(i+1,0);
     }
 
@@ -766,7 +805,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f1 = ChiL(xl,xr,X1(xl,xr)) * ChiR(xl,xr,X1(xl,xr));
       f2 = ChiL(xl,xr,X2(xl,xr)) * ChiR(xl,xr,X2(xl,xr));
       f3 = ChiL(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
-      M->data[nz] = Quad(f1,f2,f3,xl,xr);
+      data[nz] = Quad(f1,f2,f3,xl,xr);
       rowvals[nz++] = IDX(i-1,1);
     }
     /*    this v trial function */
@@ -787,7 +826,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f3 = ChiR(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
       dtmp += Quad(f1,f2,f3,xl,xr);
     }
-    M->data[nz] = dtmp;
+    data[nz] = dtmp;
     rowvals[nz++] = IDX(i,1);
     /*    right v trial function */
     if (i<N-1) {
@@ -796,7 +835,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f1 = ChiL(xl,xr,X1(xl,xr)) * ChiR(xl,xr,X1(xl,xr));
       f2 = ChiL(xl,xr,X2(xl,xr)) * ChiR(xl,xr,X2(xl,xr));
       f3 = ChiL(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
-      M->data[nz] = Quad(f1,f2,f3,xl,xr);
+      data[nz] = Quad(f1,f2,f3,xl,xr);
       rowvals[nz++] = IDX(i+1,1);
     }
 
@@ -811,7 +850,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f1 = ChiL(xl,xr,X1(xl,xr)) * ChiR(xl,xr,X1(xl,xr));
       f2 = ChiL(xl,xr,X2(xl,xr)) * ChiR(xl,xr,X2(xl,xr));
       f3 = ChiL(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
-      M->data[nz] = Quad(f1,f2,f3,xl,xr);
+      data[nz] = Quad(f1,f2,f3,xl,xr);
       rowvals[nz++] = IDX(i-1,2);
     }
     /*    this w trial function */
@@ -832,7 +871,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f3 = ChiR(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
       dtmp += Quad(f1,f2,f3,xl,xr);
     }
-    M->data[nz] = dtmp;
+    data[nz] = dtmp;
     rowvals[nz++] = IDX(i,2);
     /*    right w trial function */
     if (i<N-1) {
@@ -841,7 +880,7 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
       f1 = ChiL(xl,xr,X1(xl,xr)) * ChiR(xl,xr,X1(xl,xr));
       f2 = ChiL(xl,xr,X2(xl,xr)) * ChiR(xl,xr,X2(xl,xr));
       f3 = ChiL(xl,xr,X3(xl,xr)) * ChiR(xl,xr,X3(xl,xr));
-      M->data[nz] = Quad(f1,f2,f3,xl,xr);
+      data[nz] = Quad(f1,f2,f3,xl,xr);
       rowvals[nz++] = IDX(i+1,2);
     }
 
@@ -864,21 +903,22 @@ static int MassMatrix(realtype t, SlsMat M, void *user_data,
 
 
 /* Routine to compute the Laplace matrix */
-static int LaplaceMatrix(SlsMat L, UserData udata)
+static int LaplaceMatrix(SUNMatrix L, UserData udata)
 {
 
   /* set shortcuts, local variables */
-  int N = udata->N;
+  sunindextype N = udata->N;
   realtype du = udata->du;
   realtype dv = udata->dv;
   realtype dw = udata->dw;
-  int i, nz=0;
+  sunindextype i, nz=0;
   realtype xl, xr;
-  int *colptrs = *L->colptrs;
-  int *rowvals = *L->rowvals;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(L);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(L);
+  realtype *data = SUNSparseMatrix_Data(L);
   
   /* clear out matrix */
-  SparseSetMatToZero(L);
+  SUNMatZero(L);
 
   /* iterate over columns, filling in Laplace matrix entries */
   for (i=0; i<N; i++) {
@@ -889,22 +929,22 @@ static int LaplaceMatrix(SlsMat L, UserData udata)
     if (i>1) {
       xl = udata->x[i-1];
       xr = udata->x[i];
-      L->data[nz] = (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] = (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i-1,0);
     }
     if (i<N-1 && i>0) {
       xl = udata->x[i-1];
       xr = udata->x[i];
-      L->data[nz] = (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiR_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] = (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiR_x(xl,xr) * ChiR_x(xl,xr);
       xl = udata->x[i];
       xr = udata->x[i+1];
-      L->data[nz] += (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiL_x(xl,xr);
+      data[nz] += (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiL_x(xl,xr);
       rowvals[nz++] = IDX(i,0);
     }
     if (i<N-2) {
       xl = udata->x[i];
       xr = udata->x[i+1];
-      L->data[nz] = (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] = (-du) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i+1,0);
     }
 
@@ -914,22 +954,22 @@ static int LaplaceMatrix(SlsMat L, UserData udata)
     if (i>1) {
       xl = udata->x[i-1];
       xr = udata->x[i];
-      L->data[nz] = (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] = (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i-1,1);
     }
     if (i>0 && i<N-1) {
       xl = udata->x[i];
       xr = udata->x[i+1];
-      L->data[nz] = (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiL_x(xl,xr);
+      data[nz] = (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiL_x(xl,xr);
       xl = udata->x[i-1];
       xr = udata->x[i];
-      L->data[nz] += (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiR_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] += (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiR_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i,1);
     }
     if (i<N-2) {
       xl = udata->x[i];
       xr = udata->x[i+1];
-      L->data[nz] = (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] = (-dv) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i+1,1);
     }
 
@@ -939,22 +979,22 @@ static int LaplaceMatrix(SlsMat L, UserData udata)
     if (i>1) {
       xl = udata->x[i-1];
       xr = udata->x[i];
-      L->data[nz] = (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] = (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i-1,2);
     }
     if (i>0 && i<N-1) {
       xl = udata->x[i];
       xr = udata->x[i+1];
-      L->data[nz] = (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiL_x(xl,xr);
+      data[nz] = (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiL_x(xl,xr);
       xl = udata->x[i-1];
       xr = udata->x[i];
-      L->data[nz] += (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiR_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] += (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiR_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i,2);
     }
     if (i<N-2) {
       xl = udata->x[i];
       xr = udata->x[i+1];
-      L->data[nz] = (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
+      data[nz] = (-dw) * Quad(ONE,ONE,ONE,xl,xr) * ChiL_x(xl,xr) * ChiR_x(xl,xr);
       rowvals[nz++] = IDX(i+1,2);
     }
 
@@ -969,13 +1009,14 @@ static int LaplaceMatrix(SlsMat L, UserData udata)
 
 
 /* Routine to compute the Jacobian matrix from R(y) */
-static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
+static int ReactionJac(N_Vector y, SUNMatrix Jac, UserData udata)
 {
   /* set shortcuts, local variables */
-  int N = udata->N;
-  int i, nz=0;
-  int *colptrs = *Jac->colptrs;
-  int *rowvals = *Jac->rowvals;
+  sunindextype N = udata->N;
+  sunindextype i, nz=0;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(Jac);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(Jac);
+  realtype *data = SUNSparseMatrix_Data(Jac);
   realtype ep = udata->ep;
   realtype ul, uc, ur, vl, vc, vr, wl, wc, wr;
   realtype u1l, u2l, u3l, v1l, v2l, v3l, w1l, w2l, w3l;
@@ -997,7 +1038,7 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
   dQdf1r = dQdf2r = dQdf3r = ChiL1r = ChiL2r = ChiL3r = ChiR1r = ChiR2r = ChiR3r = 0.0;
 
   /* clear out matrix */
-  SparseSetMatToZero(Jac);
+  SUNMatZero(Jac);
 
   /* iterate over columns, filling in reaction Jacobian */
   for (i=0; i<N; i++) {
@@ -1082,21 +1123,21 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (-(w1l+ONE) + TWO*v1l*u1l) * ChiL1l * ChiR1l;
       df2 = (-(w2l+ONE) + TWO*v2l*u2l) * ChiL2l * ChiR2l;
       df3 = (-(w3l+ONE) + TWO*v3l*u3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,0);
 
       /*  dR_vl/duc */
       df1 = (w1l - TWO*v1l*u1l) * ChiL1l * ChiR1l;
       df2 = (w2l - TWO*v2l*u2l) * ChiL2l * ChiR2l;
       df3 = (w3l - TWO*v3l*u3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,1);
 
       /*  dR_wl/duc */
       df1 = (-w1l) * ChiL1l * ChiR1l;
       df2 = (-w2l) * ChiL2l * ChiR2l;
       df3 = (-w3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,2);
     }
     if (i>0 && i<N-1) {
@@ -1104,36 +1145,36 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (-(w1r+ONE) + TWO*v1r*u1r) * ChiL1r * ChiL1r;
       df2 = (-(w2r+ONE) + TWO*v2r*u2r) * ChiL2r * ChiL2r;
       df3 = (-(w3r+ONE) + TWO*v3r*u3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
 
       df1 = (-(w1l+ONE) + TWO*v1l*u1l) * ChiR1l * ChiR1l;
       df2 = (-(w2l+ONE) + TWO*v2l*u2l) * ChiR2l * ChiR2l;
       df3 = (-(w3l+ONE) + TWO*v3l*u3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] += dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] += dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i,0);
 
       /*  dR_vc/duc */
       df1 = (w1l - TWO*v1l*u1l) * ChiR1l * ChiR1l;
       df2 = (w2l - TWO*v2l*u2l) * ChiR2l * ChiR2l;
       df3 = (w3l - TWO*v3l*u3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
 
       df1 = (w1r - TWO*v1r*u1r) * ChiL1r * ChiL1r;
       df2 = (w2r - TWO*v2r*u2r) * ChiL2r * ChiL2r;
       df3 = (w3r - TWO*v3r*u3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i,1);
 
       /*  dR_wc/duc */
       df1 = (-w1r) * ChiL1r * ChiL1r;
       df2 = (-w2r) * ChiL2r * ChiL2r;
       df3 = (-w3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
 
       df1 = (-w1l) * ChiR1l * ChiR1l;
       df2 = (-w2l) * ChiR2l * ChiR2l;
       df3 = (-w3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] += dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] += dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i,2);
     }
     if (i<N-2) {
@@ -1141,21 +1182,21 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (-(w1r+ONE) + TWO*v1r*u1r) * ChiL1r * ChiR1r;
       df2 = (-(w2r+ONE) + TWO*v2r*u2r) * ChiL2r * ChiR2r;
       df3 = (-(w3r+ONE) + TWO*v3r*u3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,0);
 
       /*  dR_vr/duc */
       df1 = (w1r - TWO*v1r*u1r) * ChiL1r * ChiR1r;
       df2 = (w2r - TWO*v2r*u2r) * ChiL2r * ChiR2r;
       df3 = (w3r - TWO*v3r*u3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,1);
 
       /*  dR_wr/duc */
       df1 = (-w1r) * ChiL1r * ChiR1r;
       df2 = (-w2r) * ChiL2r * ChiR2r;
       df3 = (-w3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,2);
     }
 
@@ -1168,14 +1209,14 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (u1l*u1l) * ChiL1l * ChiR1l;
       df2 = (u2l*u2l) * ChiL2l * ChiR2l;
       df3 = (u3l*u3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,0);
 
       /*  dR_vl/dvc */
       df1 = (-u1l*u1l) * ChiL1l * ChiR1l;
       df2 = (-u2l*u2l) * ChiL2l * ChiR2l;
       df3 = (-u3l*u3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,1);
     }
     if (i>0 && i<N-1) {
@@ -1183,24 +1224,24 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (u1l*u1l) * ChiR1l * ChiR1l;
       df2 = (u2l*u2l) * ChiR2l * ChiR2l;
       df3 = (u3l*u3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
 
       df1 = (u1r*u1r) * ChiL1r * ChiL1r;
       df2 = (u2r*u2r) * ChiL2r * ChiL2r;
       df3 = (u3r*u3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i,0);
 
       /*  dR_vc/dvc */
       df1 = (-u1l*u1l) * ChiR1l * ChiR1l;
       df2 = (-u2l*u2l) * ChiR2l * ChiR2l;
       df3 = (-u3l*u3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
 
       df1 = (-u1r*u1r) * ChiL1r * ChiL1r;
       df2 = (-u2r*u2r) * ChiL2r * ChiL2r;
       df3 = (-u3r*u3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i,1);
     }
     if (i<N-2) {
@@ -1208,14 +1249,14 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (u1r*u1r) * ChiL1r * ChiR1r;
       df2 = (u2r*u2r) * ChiL2r * ChiR2r;
       df3 = (u3r*u3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,0);
 
       /*  dR_vr/dvc */
       df1 = (-u1r*u1r) * ChiL1r * ChiR1r;
       df2 = (-u2r*u2r) * ChiL2r * ChiR2r;
       df3 = (-u3r*u3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,1);
     }
 
@@ -1228,21 +1269,21 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (-u1l) * ChiL1l * ChiR1l;
       df2 = (-u2l) * ChiL2l * ChiR2l;
       df3 = (-u3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,0);
 
       /*  dR_vl/dwc */
       df1 = (u1l) * ChiL1l * ChiR1l;
       df2 = (u2l) * ChiL2l * ChiR2l;
       df3 = (u3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,1);
 
       /*  dR_wl/dwc */
       df1 = (-ONE/ep - u1l) * ChiL1l * ChiR1l;
       df2 = (-ONE/ep - u2l) * ChiL2l * ChiR2l;
       df3 = (-ONE/ep - u3l) * ChiL3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
       rowvals[nz++] = IDX(i-1,2);
     }
     if (i>0 && i<N-1) {
@@ -1250,36 +1291,36 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (-u1l) * ChiR1l * ChiR1l;
       df2 = (-u2l) * ChiR2l * ChiR2l;
       df3 = (-u3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
 
       df1 = (-u1r) * ChiL1r * ChiL1r;
       df2 = (-u2r) * ChiL2r * ChiL2r;
       df3 = (-u3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i,0);
 
       /*  dR_vc/dwc */
       df1 = (u1l) * ChiR1l * ChiR1l;
       df2 = (u2l) * ChiR2l * ChiR2l;
       df3 = (u3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
 
       df1 = (u1r) * ChiL1r * ChiL1r;
       df2 = (u2r) * ChiL2r * ChiL2r;
       df3 = (u3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i,1);
 
       /*  dR_wc/dwc */
       df1 = (-ONE/ep - u1l) * ChiR1l * ChiR1l;
       df2 = (-ONE/ep - u2l) * ChiR2l * ChiR2l;
       df3 = (-ONE/ep - u3l) * ChiR3l * ChiR3l;
-      Jac->data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
+      data[nz] = dQdf1l*df1 + dQdf2l*df2 + dQdf3l*df3;
 
       df1 = (-ONE/ep - u1r) * ChiL1r * ChiL1r;
       df2 = (-ONE/ep - u2r) * ChiL2r * ChiL2r;
       df3 = (-ONE/ep - u3r) * ChiL3r * ChiL3r;
-      Jac->data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] += dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i,2);
     }
     if (i<N-2) {
@@ -1287,21 +1328,21 @@ static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
       df1 = (-u1r) * ChiL1r * ChiR1r;
       df2 = (-u2r) * ChiL2r * ChiR2r;
       df3 = (-u3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,0);
 
       /*  dR_vr/dwc */
       df1 = (u1r) * ChiL1r * ChiR1r;
       df2 = (u2r) * ChiL2r * ChiR2r;
       df3 = (u3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,1);
 
       /*  dR_wr/dwc */
       df1 = (-ONE/ep - u1r) * ChiL1r * ChiR1r;
       df2 = (-ONE/ep - u2r) * ChiL2r * ChiR2r;
       df3 = (-ONE/ep - u3r) * ChiL3r * ChiR3r;
-      Jac->data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
+      data[nz] = dQdf1r*df1 + dQdf2r*df2 + dQdf3r*df3;
       rowvals[nz++] = IDX(i+1,2);
     }
 
diff --git a/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.out b/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.out
index b7dc944..742675c 100644
--- a/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.out
+++ b/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.out
@@ -113,7 +113,9 @@
 Final Solver Statistics:
    Internal solver steps = 95 (attempted = 95)
    Total RHS evals:  Fe = 0,  Fi = 1615
+   Total mass matrix setups = 1
    Total mass matrix solves = 289
+   Total mass times evals = 1706
    Total linear solver setups = 32
    Total number of Jacobian evaluations = 12
    Total number of Newton iterations = 1136
diff --git a/examples/arkode/C_serial/ark_brusselator1D_klu.c b/examples/arkode/C_serial/ark_brusselator1D_klu.c
index 7a473c6..fa8feb2 100644
--- a/examples/arkode/C_serial/ark_brusselator1D_klu.c
+++ b/examples/arkode/C_serial/ark_brusselator1D_klu.c
@@ -45,7 +45,7 @@
  * 
  * This program solves the problem with the DIRK method, using a
  * Newton iteration.  The inner linear systems are solved using 
- * the ARKKLU linear solver.
+ * the SUNKLU linear solver.
  *
  * 100 outputs are printed at equal intervals, and run statistics 
  * are printed at the end.
@@ -55,11 +55,23 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
-#include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
-#include <arkode/arkode_klu.h>        /* prototype for ARKKLU solver */
-#include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
-#include <sundials/sundials_types.h>  /* def. of type 'realtype' */
-#include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc. */
+#include <arkode/arkode.h>               /* prototypes for ARKode fcts., consts. */
+#include <nvector/nvector_serial.h>      /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_sparse.h>  /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>     /* access to KLU SUNLinearSolver        */
+#include <arkode/arkode_direct.h>        /* access to ARKDls interface           */
+#include <sundials/sundials_types.h>     /* defs. of realtype, sunindextype, etc */
+#include <sundials/sundials_math.h>      /* def. of SUNRsqrt, etc.               */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* accessor macros between (x,v) location and 1D NVector array */
 #define IDX(x,v) (3*(x)+v)
@@ -70,27 +82,26 @@
 
 /* user data structure */
 typedef struct {  
-  int N;         /* number of intervals     */
-  realtype dx;   /* mesh spacing            */
-  realtype a;    /* constant forcing on u   */
-  realtype b;    /* steady-state value of w */
-  realtype du;   /* diffusion coeff for u   */
-  realtype dv;   /* diffusion coeff for v   */
-  realtype dw;   /* diffusion coeff for w   */
-  realtype ep;   /* stiffness parameter     */
-  SlsMat R;      /* temporary storage       */
+  sunindextype N;  /* number of intervals     */
+  realtype dx;     /* mesh spacing            */
+  realtype a;      /* constant forcing on u   */
+  realtype b;      /* steady-state value of w */
+  realtype du;     /* diffusion coeff for u   */
+  realtype dv;     /* diffusion coeff for v   */
+  realtype dw;     /* diffusion coeff for w   */
+  realtype ep;     /* stiffness parameter     */
+  SUNMatrix R;     /* temporary storage       */
 } *UserData;
 
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(realtype t, N_Vector y, N_Vector fy, 
-	       SlsMat J, void *user_data, 
-	       N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+	       void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private function to check function return values */
-static int LaplaceMatrix(SlsMat Jac, UserData udata);
-static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata);
+static int LaplaceMatrix(SUNMatrix Jac, UserData udata);
+static int ReactionJac(N_Vector y, SUNMatrix Jac, UserData udata);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -106,7 +117,7 @@ int main()
   int Nvar = 3;
   UserData udata = NULL;
   realtype *data;
-  int N = 201;                  /* spatial mesh size */
+  sunindextype N = 201;         /* spatial mesh size */
   realtype a = 0.6;             /* problem parameters */
   realtype b = 2.0;
   realtype du = 0.025;
@@ -115,8 +126,7 @@ int main()
   realtype ep = 1.0e-5;         /* stiffness parameter */
   realtype reltol = 1.0e-6;     /* tolerances */
   realtype abstol = 1.0e-10;
-  int i;
-  long int NEQ, NNZ;
+  sunindextype NEQ, i, NNZ;
 
   /* general problem variables */
   int flag;                     /* reusable error-checking flag */
@@ -124,6 +134,8 @@ int main()
   N_Vector umask = NULL;
   N_Vector vmask = NULL;
   N_Vector wmask = NULL;
+  SUNMatrix A = NULL;           /* empty matrix object for solver */
+  SUNLinearSolver LS = NULL;    /* empty linear solver object */
   void *arkode_mem = NULL;
   realtype pi;
   FILE *FID, *UFID, *VFID, *WFID;
@@ -153,12 +165,12 @@ int main()
 
   /* Initial problem output */
   printf("\n1D Brusselator PDE test problem (KLU solver):\n");
-  printf("    N = %i,  NEQ = %li\n", udata->N, NEQ);
-  printf("    problem parameters:  a = %g,  b = %g,  ep = %g\n",
+  printf("    N = %li,  NEQ = %li\n", (long int) udata->N, (long int) NEQ);
+  printf("    problem parameters:  a = %"GSYM",  b = %"GSYM",  ep = %"GSYM"\n",
 	 udata->a, udata->b, udata->ep);
-  printf("    diffusion coefficients:  du = %g,  dv = %g,  dw = %g\n", 
+  printf("    diffusion coefficients:  du = %"GSYM",  dv = %"GSYM",  dw = %"GSYM"\n", 
 	 udata->du, udata->dv, udata->dw);
-  printf("    reltol = %.1e,  abstol = %.1e\n\n", reltol, abstol);
+  printf("    reltol = %.1"ESYM",  abstol = %.1"ESYM"\n\n", reltol, abstol);
 
   /* Initialize data structures */
   y = N_VNew_Serial(NEQ);           /* Create serial vector for solution */
@@ -215,16 +227,22 @@ int main()
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);    /* Specify tolerances */
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  /* Specify the KLU sparse linear solver and Jacobian function */
+  /* Initialize sparse matrix data structure and KLU solver */
   NNZ = 5*NEQ;
-  flag = ARKKLU(arkode_mem, NEQ, NNZ, CSC_MAT);
-  if (check_flag(&flag, "ARKKLU", 1)) return 1;
-  flag = ARKSlsSetSparseJacFn(arkode_mem, Jac);
-  if (check_flag(&flag, "ARKSlsSetSparseJacFn", 1)) return 1;
+  A = SUNSparseMatrix(NEQ, NEQ, NNZ, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return 1;
+  LS = SUNKLU(y, A);
+  if (check_flag((void *)LS, "SUNKLU", 0)) return 1;
+  
+  /* Attach the matrix, linear solver, and Jacobian construction routine to ARKode */
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);        /* Attach matrix and LS */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                 /* Supply Jac routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
  
    /* output spatial mesh to disk */
   FID = fopen("bruss_mesh.txt","w");
-  for (i=0; i<N; i++)  fprintf(FID,"  %.16e\n", udata->dx*i);
+  for (i=0; i<N; i++)  fprintf(FID,"  %.16"ESYM"\n", udata->dx*i);
   fclose(FID);
 
   /* Open output stream for results, access data arrays */
@@ -235,9 +253,9 @@ int main()
   if (check_flag((void *) data, "N_VGetArrayPointer", 0)) return 1;
 
   /* output initial condition to disk */
-  for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-  for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-  for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+  for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM"", data[IDX(i,0)]);
+  for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM"", data[IDX(i,1)]);
+  for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM"", data[IDX(i,2)]);
   fprintf(UFID,"\n");
   fprintf(VFID,"\n");
   fprintf(WFID,"\n");
@@ -258,7 +276,7 @@ int main()
     v = SUNRsqrt(v*v/N);
     w = N_VWL2Norm(y,wmask);
     w = SUNRsqrt(w*w/N);
-    printf("  %10.6f  %10.6f  %10.6f  %10.6f\n", t, u, v, w);
+    printf("  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"\n", t, u, v, w);
     if (flag >= 0) {                                       /* successful solve: update output time */
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -268,9 +286,9 @@ int main()
     }
 
     /* output results to disk */
-    for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[IDX(i,0)]);
-    for (i=0; i<N; i++)  fprintf(VFID," %.16e", data[IDX(i,1)]);
-    for (i=0; i<N; i++)  fprintf(WFID," %.16e", data[IDX(i,2)]);
+    for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM"", data[IDX(i,0)]);
+    for (i=0; i<N; i++)  fprintf(VFID," %.16"ESYM"", data[IDX(i,1)]);
+    for (i=0; i<N; i++)  fprintf(WFID," %.16"ESYM"", data[IDX(i,2)]);
     fprintf(UFID,"\n");
     fprintf(VFID,"\n");
     fprintf(WFID,"\n");
@@ -296,8 +314,8 @@ int main()
   check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1);
   flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn);
   check_flag(&flag, "ARKodeGetNumNonlinSolvConvFails", 1);
-  flag = ARKSlsGetNumJacEvals(arkode_mem, &nje);
-  check_flag(&flag, "ARKSlsGetNumJacEvals", 1);
+  flag = ARKDlsGetNumJacEvals(arkode_mem, &nje);
+  check_flag(&flag, "ARKDlsGetNumJacEvals", 1);
 
   printf("\nFinal Solver Statistics:\n");
   printf("   Internal solver steps = %li (attempted = %li)\n", nst, nst_a);
@@ -309,13 +327,15 @@ int main()
   printf("   Total number of error test failures = %li\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);         /* Free vectors */
-  N_VDestroy_Serial(umask);
-  N_VDestroy_Serial(vmask);
-  N_VDestroy_Serial(wmask);
-  SparseDestroyMat(udata->R);   /* Free user data */
+  N_VDestroy(y);                /* Free vectors */
+  N_VDestroy(umask);
+  N_VDestroy(vmask);
+  N_VDestroy(wmask);
+  SUNMatDestroy(udata->R);      /* Free user data */
   free(udata);
-  ARKodeFree(&arkode_mem);
+  ARKodeFree(&arkode_mem);      /* Free integrator memory */
+  SUNLinSolFree(LS);            /* Free linear solver */
+  SUNMatDestroy(A);             /* Free A matrix */
   return 0;
 }
 
@@ -327,17 +347,17 @@ int main()
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
   UserData udata = (UserData) user_data;      /* access problem data */
-  int N       = udata->N;                     /* set variable shortcuts */
-  realtype a  = udata->a;
-  realtype b  = udata->b;
-  realtype ep = udata->ep;
-  realtype du = udata->du;
-  realtype dv = udata->dv;
-  realtype dw = udata->dw;
-  realtype dx = udata->dx;
+  sunindextype N = udata->N;                     /* set variable shortcuts */
+  realtype a     = udata->a;
+  realtype b     = udata->b;
+  realtype ep    = udata->ep;
+  realtype du    = udata->du;
+  realtype dv    = udata->dv;
+  realtype dw    = udata->dw;
+  realtype dx    = udata->dx;
   realtype *Ydata=NULL, *dYdata=NULL;
   realtype uconst, vconst, wconst, u, ul, ur, v, vl, vr, w, wl, wr;
-  int i;
+  sunindextype i;
 
   Ydata = N_VGetArrayPointer(y);     /* access data arrays */
   if (check_flag((void *) Ydata, "N_VGetArrayPointer", 0)) return 1;
@@ -376,16 +396,16 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
-static int Jac(realtype t, N_Vector y, N_Vector fy, 
-	       SlsMat J, void *user_data, 
-	       N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+	       void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   /* problem data */
   UserData udata = (UserData) user_data;
-  int N = udata->N;
+  sunindextype N = udata->N;
 
   /* ensure that Jac is the correct size */
-  if ((J->M != N*3) || (J->N != N*3)) {
+  if ( (SUNSparseMatrix_Rows(J) != N*3) ||
+       (SUNSparseMatrix_Columns(J) != N*3) ) {
     printf("Jacobian calculation error: matrix is the wrong size!\n");
     return 1;
   }
@@ -396,23 +416,25 @@ static int Jac(realtype t, N_Vector y, N_Vector fy,
     return 1;
   }
 
-  /* Add in the Jacobian of the reaction terms matrix */
+  /* Create matrix for Jacobian of the reaction terms if necessary */
   if (udata->R == NULL) {
-    udata->R = SparseNewMat(J->M, J->N, J->NNZ, CSC_MAT);
+    udata->R = SUNSparseMatrix(SUNSparseMatrix_Rows(J),
+                               SUNSparseMatrix_Columns(J),
+                               SUNSparseMatrix_NNZ(J), CSC_MAT);
     if (udata->R == NULL) {
       printf("Jacobian calculation error in allocating R matrix!\n");
       return 1;
     }
   }
       
-  /* Add in the Jacobian of the reaction terms matrix */
+  /* Compute the Jacobian of the reaction terms */
   if (ReactionJac(y, udata->R, udata)) {
     printf("Jacobian calculation error in calling ReactionJac!\n");
     return 1;
   }
 
   /* Add R to J */
-  if (SparseAddMat(J,udata->R) != 0) {
+  if (SUNMatScaleAdd(ONE, J, udata->R) != 0) {
     printf("Jacobian calculation error in adding sparse matrices!\n");
     return 1;
   }
@@ -428,17 +450,17 @@ static int Jac(realtype t, N_Vector y, N_Vector fy,
  *-------------------------------*/
 
 /* Routine to compute the stiffness matrix from (L*y) */
-static int LaplaceMatrix(SlsMat Lap, UserData udata)
+static int LaplaceMatrix(SUNMatrix Lap, UserData udata)
 {
-  int N = udata->N;  /* set shortcuts */
-  int i, nz=0;
+  sunindextype N = udata->N;  /* set shortcuts */
+  sunindextype i, nz=0;
   realtype uconst, uconst2, vconst, vconst2, wconst, wconst2;
-  int *colptrs = *Lap->colptrs;
-  int *rowvals = *Lap->rowvals;
-  realtype *data = Lap->data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(Lap);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(Lap);
+  realtype *data = SUNSparseMatrix_Data(Lap);
   
   /* clear out matrix */
-  SparseSetMatToZero(Lap);
+  SUNMatZero(Lap);
 
   /* set first column to zero */
   colptrs[IDX(0,0)] = nz;
@@ -515,20 +537,20 @@ static int LaplaceMatrix(SlsMat Lap, UserData udata)
 
 
 /* Routine to compute the Jacobian matrix from R(y) */
-static int ReactionJac(N_Vector y, SlsMat Jac, UserData udata)
+static int ReactionJac(N_Vector y, SUNMatrix Jac, UserData udata)
 {
-  int N = udata->N;                            /* set shortcuts */
-  int i, nz=0;
+  sunindextype N = udata->N;                   /* set shortcuts */
+  sunindextype i, nz=0;
   realtype u, v, w;
   realtype ep = udata->ep;
-  int *colptrs = *Jac->colptrs;
-  int *rowvals = *Jac->rowvals;
-  realtype *data = Jac->data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(Jac);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(Jac);
+  realtype *data = SUNSparseMatrix_Data(Jac);
   realtype *Ydata = N_VGetArrayPointer(y);     /* access solution array */
   if (check_flag((void *) Ydata, "N_VGetArrayPointer", 0)) return 1;
 
   /* clear out matrix */
-  SparseSetMatToZero(Jac);
+  SUNMatZero(Jac);
 
   /* set first matrix column to zero */
   colptrs[IDX(0,0)] = 0;
diff --git a/examples/arkode/C_serial/ark_brusselator_fp.c b/examples/arkode/C_serial/ark_brusselator_fp.c
index 540ded2..72c5abc 100644
--- a/examples/arkode/C_serial/ark_brusselator_fp.c
+++ b/examples/arkode/C_serial/ark_brusselator_fp.c
@@ -63,6 +63,16 @@
 #include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
 #include <sundials/sundials_types.h>  /* def. of type 'realtype' */
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
 /* User-supplied Functions Called by the Solver */
 static int fe(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 static int fi(realtype t, N_Vector y, N_Vector ydot, void *user_data);
@@ -77,7 +87,7 @@ int main()
   realtype T0 = RCONST(0.0);     /* initial time */
   realtype Tf = RCONST(10.0);    /* final time */
   realtype dTout = RCONST(1.0);  /* time between outputs */
-  long int NEQ = 3;              /* number of dependent vars. */
+  sunindextype NEQ = 3;          /* number of dependent vars. */
   int Nt = ceil(Tf/dTout);       /* number of output times */
   int test = 3;                  /* test problem to run */
   realtype reltol = 1.0e-6;      /* tolerances */
@@ -122,9 +132,9 @@ int main()
 
   /* Initial problem output */
   printf("\nBrusselator ODE test problem, fixed-point solver:\n");
-  printf("    initial conditions:  u0 = %g,  v0 = %g,  w0 = %g\n",u0,v0,w0);
-  printf("    problem parameters:  a = %g,  b = %g,  ep = %g\n",a,b,ep);
-  printf("    reltol = %.1e,  abstol = %.1e\n\n",reltol,abstol);
+  printf("    initial conditions:  u0 = %"GSYM",  v0 = %"GSYM",  w0 = %"GSYM"\n",u0,v0,w0);
+  printf("    problem parameters:  a = %"GSYM",  b = %"GSYM",  ep = %"GSYM"\n",a,b,ep);
+  printf("    reltol = %.1"ESYM",  abstol = %.1"ESYM"\n\n",reltol,abstol);
 
   /* Initialize data structures */
   rdata[0] = a;    /* set user data  */
@@ -159,7 +169,7 @@ int main()
   fprintf(UFID,"# t u v w\n");
 
   /* output initial condition to disk */
-  fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+  fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	  T0, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
@@ -172,9 +182,9 @@ int main()
 
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);      /* call integrator */
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %10.6f  %10.6f  %10.6f  %10.6f\n",             /* access/print solution */
+    printf("  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"  %10.6"FSYM"\n",             /* access/print solution */
            t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));
-    fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+    fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	    t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
     if (flag >= 0) {                                         /* successful solve: update time */
       tout += dTout;
@@ -209,7 +219,7 @@ int main()
   printf("   Total number of error test failures = %li\n\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);        /* Free y vector */
+  N_VDestroy(y);        /* Free y vector */
   ARKodeFree(&arkode_mem);     /* Free integrator memory */
   return 0;
 }
diff --git a/examples/arkode/C_serial/ark_heat1D.c b/examples/arkode/C_serial/ark_heat1D.c
index 77c4daa..7c215e9 100644
--- a/examples/arkode/C_serial/ark_heat1D.c
+++ b/examples/arkode/C_serial/ark_heat1D.c
@@ -32,7 +32,7 @@
  *
  * This program solves the problem with either an ERK or DIRK
  * method.  For the DIRK method, we use a Newton iteration with 
- * the PCG linear solver, and a user-supplied Jacobian-vector 
+ * the SUNPCG linear solver, and a user-supplied Jacobian-vector 
  * product routine.
  *
  * 100 outputs are printed at equal intervals, and run statistics 
@@ -45,21 +45,32 @@
 #include <math.h>
 #include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
 #include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_pcg.h>        /* prototype for ARKPcg solver */
-#include <sundials/sundials_types.h>  /* def. of type 'realtype' */
-#include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc. */
+#include <sunlinsol/sunlinsol_pcg.h>  /* access to PCG SUNLinearSolver        */
+#include <arkode/arkode_spils.h>      /* access to ARKSpils interface         */
+#include <sundials/sundials_types.h>  /* defs. of realtype, sunindextype, etc */
+#include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc.               */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* user data structure */
 typedef struct {
-  long int N;    /* number of intervals   */
-  realtype dx;   /* mesh spacing          */
-  realtype k;    /* diffusion coefficient */
+  sunindextype N;  /* number of intervals   */
+  realtype dx;     /* mesh spacing          */
+  realtype k;      /* diffusion coefficient */
 } *UserData;
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 static int Jac(N_Vector v, N_Vector Jv, realtype t, N_Vector y,
-            N_Vector fy, void *user_data, N_Vector tmp);
+               N_Vector fy, void *user_data, N_Vector tmp);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -75,14 +86,15 @@ int main() {
   realtype atol = 1.e-10;      /* absolute tolerance */
   UserData udata = NULL;
   realtype *data;
-  long int N = 201;            /* spatial mesh size */
+  sunindextype N = 201;        /* spatial mesh size */
   realtype k = 0.5;            /* heat conductivity */
-  long int i;
+  sunindextype i;
 
   /* general problem variables */
-  int flag;                 /* reusable error-checking flag */
-  N_Vector y = NULL;             /* empty vector for storing solution */
-  void *arkode_mem = NULL;        /* empty ARKode memory structure */
+  int flag;                    /* reusable error-checking flag */
+  N_Vector y = NULL;           /* empty vector for storing solution */
+  SUNLinearSolver LS = NULL;   /* empty linear solver object */
+  void *arkode_mem = NULL;     /* empty ARKode memory structure */
   FILE *FID, *UFID;
   realtype t, dTout, tout;
   int iout;
@@ -96,8 +108,8 @@ int main() {
 
   /* Initial problem output */
   printf("\n1D Heat PDE test problem:\n");
-  printf("  N = %li\n", udata->N);
-  printf("  diffusion coefficient:  k = %g\n", udata->k);
+  printf("  N = %li\n", (long int) udata->N);
+  printf("  diffusion coefficient:  k = %"GSYM"\n", udata->k);
 
   /* Initialize data structures */
   y = N_VNew_Serial(N);            /* Create serial vector for solution */
@@ -123,11 +135,15 @@ int main() {
   flag = ARKodeSStolerances(arkode_mem, rtol, atol);      /* Specify tolerances */
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  /* Linear solver specification */
-  flag = ARKPcg(arkode_mem, 0, N);                        /* Specify the PCG solver */
-  if (check_flag(&flag, "ARKPcg", 1)) return 1;
-  flag = ARKSpilsSetJacTimesVecFn(arkode_mem, Jac);       /* Set the Jacobian routine */
-  if (check_flag(&flag, "ARKSpilsSetJacTimesVecFn", 1)) return 1;
+  /* Initialize PCG solver -- no preconditioning, with up to N iterations  */
+  LS = SUNPCG(y, 0, N);
+  if (check_flag((void *)LS, "SUNPCG", 0)) return 1;
+  
+  /* Linear solver interface -- set user-supplied J*v routine (no 'jtsetup' required) */
+  flag = ARKSpilsSetLinearSolver(arkode_mem, LS);        /* Attach linear solver to ARKode */
+  if (check_flag(&flag, "ARKSpilsSetLinearSolver", 1)) return 1;
+  flag = ARKSpilsSetJacTimes(arkode_mem, NULL, Jac);     /* Set the Jacobian routine */
+  if (check_flag(&flag, "ARKSpilsSetJacTimes", 1)) return 1;
 
   /* Specify linearly implicit RHS, with non-time-dependent Jacobian */
   flag = ARKodeSetLinear(arkode_mem, 0);
@@ -135,7 +151,7 @@ int main() {
 
   /* output mesh to disk */
   FID=fopen("heat_mesh.txt","w");
-  for (i=0; i<N; i++)  fprintf(FID,"  %.16e\n", udata->dx*i);
+  for (i=0; i<N; i++)  fprintf(FID,"  %.16"ESYM"\n", udata->dx*i);
   fclose(FID);
 
   /* Open output stream for results, access data array */
@@ -143,7 +159,7 @@ int main() {
   data = N_VGetArrayPointer(y);
 
   /* output initial condition to disk */
-  for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[i]);
+  for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM"", data[i]);
   fprintf(UFID,"\n");
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
@@ -153,12 +169,12 @@ int main() {
   tout = T0+dTout;
   printf("        t      ||u||_rms\n");
   printf("   -------------------------\n");
-  printf("  %10.6f  %10.6f\n", t, SUNRsqrt(N_VDotProd(y,y)/N));
+  printf("  %10.6"FSYM"  %10.6"FSYM"\n", t, SUNRsqrt(N_VDotProd(y,y)/N));
   for (iout=0; iout<Nt; iout++) {
 
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);         /* call integrator */
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %10.6f  %10.6f\n", t, SUNRsqrt(N_VDotProd(y,y)/N));   /* print solution stats */
+    printf("  %10.6"FSYM"  %10.6"FSYM"\n", t, SUNRsqrt(N_VDotProd(y,y)/N));   /* print solution stats */
     if (flag >= 0) {                                            /* successful solve: update output time */
       tout += dTout;
       tout = (tout > Tf) ? Tf : tout;
@@ -168,7 +184,7 @@ int main() {
     }
 
     /* output results to disk */
-    for (i=0; i<N; i++)  fprintf(UFID," %.16e", data[i]);
+    for (i=0; i<N; i++)  fprintf(UFID," %.16"ESYM"", data[i]);
     fprintf(UFID,"\n");
   }
   printf("   -------------------------\n");
@@ -208,9 +224,10 @@ int main() {
   printf("   Total number of error test failures = %li\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);        /* Free vectors */
+  N_VDestroy(y);               /* Free vectors */
   free(udata);                 /* Free user data */
   ARKodeFree(&arkode_mem);     /* Free integrator memory */
+  SUNLinSolFree(LS);           /* Free linear solver */
   return 0;
 }
 
@@ -222,12 +239,12 @@ int main() {
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
   UserData udata = (UserData) user_data;    /* access problem data */
-  long int N  = udata->N;                   /* set variable shortcuts */
+  sunindextype N  = udata->N;                   /* set variable shortcuts */
   realtype k  = udata->k;
   realtype dx = udata->dx;
   realtype *Y=NULL, *Ydot=NULL;
   realtype c1, c2;
-  long int i, isource;
+  sunindextype i, isource;
 
   Y = N_VGetArrayPointer(y);      /* access data arrays */
   if (check_flag((void *) Y, "N_VGetArrayPointer", 0)) return 1;
@@ -253,12 +270,12 @@ static int Jac(N_Vector v, N_Vector Jv, realtype t, N_Vector y,
 	       N_Vector fy, void *user_data, N_Vector tmp)
 {
   UserData udata = (UserData) user_data;     /* variable shortcuts */
-  long int N  = udata->N;
+  sunindextype N = udata->N;
   realtype k  = udata->k;
   realtype dx = udata->dx;
   realtype *V=NULL, *JV=NULL;
   realtype c1, c2;
-  long int i;
+  sunindextype i;
 
   V = N_VGetArrayPointer(v);       /* access data arrays */
   if (check_flag((void *) V, "N_VGetArrayPointer", 0)) return 1;
diff --git a/examples/arkode/C_serial/ark_heat1D.out b/examples/arkode/C_serial/ark_heat1D.out
index dd54665..2868ce4 100644
--- a/examples/arkode/C_serial/ark_heat1D.out
+++ b/examples/arkode/C_serial/ark_heat1D.out
@@ -18,12 +18,12 @@
    -------------------------
 
 Final Solver Statistics:
-   Internal solver steps = 197 (attempted = 197)
-   Total RHS evals:  Fe = 0,  Fi = 1974
+   Internal solver steps = 191 (attempted = 191)
+   Total RHS evals:  Fe = 0,  Fi = 1914
    Total linear solver setups = 0
-   Total linear iterations = 17309
-   Total number of Jacobian-vector products = 17309
+   Total linear iterations = 18265
+   Total number of Jacobian-vector products = 18265
    Total number of linear solver convergence failures = 0
-   Total number of Newton iterations = 985
+   Total number of Newton iterations = 955
    Total number of nonlinear solver convergence failures = 0
    Total number of error test failures = 0
diff --git a/examples/arkode/C_serial/ark_heat1D_adapt.c b/examples/arkode/C_serial/ark_heat1D_adapt.c
index 2833111..2fc5b92 100644
--- a/examples/arkode/C_serial/ark_heat1D_adapt.c
+++ b/examples/arkode/C_serial/ark_heat1D_adapt.c
@@ -35,7 +35,7 @@
  * [0, 1], but as the simulation proceeds the mesh is adapted.
  *
  * This program solves the problem with a DIRK method, solved with 
- * a Newton iteration and PCG linear solver, with a user-supplied 
+ * a Newton iteration and SUNPCG linear solver, with a user-supplied 
  * Jacobian-vector product routine.
  *---------------------------------------------------------------*/
 
@@ -45,13 +45,24 @@
 #include <math.h>
 #include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
 #include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_pcg.h>        /* prototype for ARKPcg solver */
-#include <sundials/sundials_types.h>  /* def. of type 'realtype' */
-#include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc. */
+#include <sunlinsol/sunlinsol_pcg.h>  /* access to PCG SUNLinearSolver        */
+#include <arkode/arkode_spils.h>      /* access to ARKSpils interface         */
+#include <sundials/sundials_types.h>  /* defs. of realtype, sunindextype, etc */
+#include <sundials/sundials_math.h>   /* def. of SUNRsqrt, etc.               */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* user data structure */
 typedef struct {
-  long int N;           /* current number of intervals */
+  sunindextype N;       /* current number of intervals */
   realtype *x;          /* current mesh */
   realtype k;           /* diffusion coefficient */
   realtype refine_tol;  /* adaptivity tolerance */
@@ -60,12 +71,12 @@ typedef struct {
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 static int Jac(N_Vector v, N_Vector Jv, realtype t, N_Vector y,
-            N_Vector fy, void *user_data, N_Vector tmp);
+               N_Vector fy, void *user_data, N_Vector tmp);
 
 /* Private function to check function return values */
-realtype * adapt_mesh(N_Vector y, long int *Nnew, UserData udata);
-static int project(long int Nold, realtype *xold, N_Vector yold, 
-		   long int Nnew, realtype *xnew, N_Vector ynew);
+realtype * adapt_mesh(N_Vector y, sunindextype *Nnew, UserData udata);
+static int project(sunindextype Nold, realtype *xold, N_Vector yold, 
+                   sunindextype Nnew, realtype *xnew, N_Vector ynew);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /* Main Program */
@@ -79,10 +90,11 @@ int main() {
   realtype hscale = 1.0;       /* time step change factor on resizes */
   UserData udata = NULL;
   realtype *data;
-  long int N = 21;             /* initial spatial mesh size */
+  sunindextype N = 21;             /* initial spatial mesh size */
   realtype refine = 3.e-3;     /* adaptivity refinement tolerance */
   realtype k = 0.5;            /* heat conductivity */
-  long int i, nni, nni_cur=0, nni_tot=0, nli, nli_tot=0;
+  sunindextype i;
+  long int nni, nni_cur=0, nni_tot=0, nli, nli_tot=0;
   int iout=0;
 
   /* general problem variables */
@@ -90,11 +102,12 @@ int main() {
   N_Vector y  = NULL;          /* empty vector for storing solution */
   N_Vector y2 = NULL;          /* empty vector for storing solution */
   N_Vector yt = NULL;          /* empty vector for swapping */
+  SUNLinearSolver LS = NULL;   /* empty linear solver object */
   void *arkode_mem = NULL;     /* empty ARKode memory structure */
   FILE *XFID, *UFID;
   realtype t, olddt, newdt;
   realtype *xnew = NULL;
-  long int Nnew;
+  sunindextype Nnew;
 
   /* allocate and fill initial udata structure */
   udata = (UserData) malloc(sizeof(*udata));
@@ -106,8 +119,8 @@ int main() {
 
   /* Initial problem output */
   printf("\n1D adaptive Heat PDE test problem:\n");
-  printf("  diffusion coefficient:  k = %g\n", udata->k);
-  printf("  initial N = %li\n", udata->N);
+  printf("  diffusion coefficient:  k = %"GSYM"\n", udata->k);
+  printf("  initial N = %li\n", (long int) udata->N);
 
   /* Initialize data structures */
   y = N_VNew_Serial(N);       /* Create initial serial vector for solution */
@@ -118,7 +131,7 @@ int main() {
   XFID=fopen("heat_mesh.txt","w");
 
   /* output initial mesh to disk */
-  for (i=0; i<udata->N; i++)  fprintf(XFID," %.16e", udata->x[i]);
+  for (i=0; i<udata->N; i++)  fprintf(XFID," %.16"ESYM, udata->x[i]);
   fprintf(XFID,"\n");
 
   /* Open output stream for results, access data array */
@@ -126,7 +139,7 @@ int main() {
 
   /* output initial condition to disk */
   data = N_VGetArrayPointer(y);
-  for (i=0; i<udata->N; i++)  fprintf(UFID," %.16e", data[i]);
+  for (i=0; i<udata->N; i++)  fprintf(UFID," %.16"ESYM, data[i]);
   fprintf(UFID,"\n");
 
 
@@ -150,11 +163,19 @@ int main() {
   flag = ARKodeSetPredictorMethod(arkode_mem, 0);     /* Set predictor method */
   if (check_flag(&flag, "ARKodeSetPredictorMethod", 1)) return 1;
 
-  /* Linear solver specification */
-  flag = ARKPcg(arkode_mem, 0, N);
-  if (check_flag(&flag, "ARKPcg", 1)) return 1;
-  flag = ARKSpilsSetJacTimesVecFn(arkode_mem, Jac);
-  if (check_flag(&flag, "ARKSpilsSetJacTimesVecFn", 1)) return 1;
+  /* Specify linearly implicit RHS, with time-dependent Jacobian */
+  flag = ARKodeSetLinear(arkode_mem, 1);
+  if (check_flag(&flag, "ARKodeSetLinear", 1)) return 1;
+
+  /* Initialize PCG solver -- no preconditioning, with up to N iterations  */
+  LS = SUNPCG(y, 0, N);
+  if (check_flag((void *)LS, "SUNPCG", 0)) return 1;
+  
+  /* Linear solver interface -- set user-supplied J*v routine (no 'jtsetup' required) */
+  flag = ARKSpilsSetLinearSolver(arkode_mem, LS);        /* Attach linear solver to ARKode */
+  if (check_flag(&flag, "ARKSpilsSetLinearSolver", 1)) return 1;
+  flag = ARKSpilsSetJacTimes(arkode_mem, NULL, Jac);     /* Set the Jacobian routine */
+  if (check_flag(&flag, "ARKSpilsSetJacTimes", 1)) return 1;
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
      prints results.  Stops when the final time has been reached */
@@ -163,8 +184,9 @@ int main() {
   newdt = 0.0;
   printf("  iout          dt_old                 dt_new               ||u||_rms       N   NNI  NLI\n");
   printf(" ----------------------------------------------------------------------------------------\n");
-  printf(" %4i  %19.15e  %19.15e  %19.15e  %li   %2i  %3i\n", 
-	 iout, olddt, newdt, SUNRsqrt(N_VDotProd(y,y)/udata->N), udata->N, 0, 0);
+  printf(" %4i  %19.15"ESYM"  %19.15"ESYM"  %19.15"ESYM"  %li   %2i  %3i\n", 
+	 iout, olddt, newdt, SUNRsqrt(N_VDotProd(y,y)/udata->N),
+         (long int) udata->N, 0, 0);
   while (t < Tf) {
 
     /* "set" routines */
@@ -189,17 +211,18 @@ int main() {
 
     /* print current solution stats */
     iout++;
-    printf(" %4i  %19.15e  %19.15e  %19.15e  %li   %2li  %3li\n", 
-	   iout, olddt, newdt, SUNRsqrt(N_VDotProd(y,y)/udata->N), udata->N, nni-nni_cur, nli);
+    printf(" %4i  %19.15"ESYM"  %19.15"ESYM"  %19.15"ESYM"  %li   %2li  %3li\n", 
+	   iout, olddt, newdt, SUNRsqrt(N_VDotProd(y,y)/udata->N),
+           (long int) udata->N, nni-nni_cur, nli);
     nni_cur = nni;
     nni_tot = nni;
     nli_tot += nli;
 
     /* output results and current mesh to disk */
     data = N_VGetArrayPointer(y);
-    for (i=0; i<udata->N; i++)  fprintf(UFID," %.16e", data[i]);
+    for (i=0; i<udata->N; i++)  fprintf(UFID," %.16"ESYM, data[i]);
     fprintf(UFID,"\n");
-    for (i=0; i<udata->N; i++)  fprintf(XFID," %.16e", udata->x[i]);
+    for (i=0; i<udata->N; i++)  fprintf(XFID," %.16"ESYM, udata->x[i]);
     fprintf(XFID,"\n");
 
     /* adapt the spatial mesh */
@@ -215,7 +238,7 @@ int main() {
     if (check_flag(&flag, "project", 1)) return 1;
 
     /* delete old vector, old mesh */
-    N_VDestroy_Serial(y);
+    N_VDestroy(y);
     free(udata->x);
     
     /* swap x and xnew so that new mesh is stored in udata structure */
@@ -232,18 +255,18 @@ int main() {
     flag = ARKodeResize(arkode_mem, y, hscale, t, NULL, NULL);
     if (check_flag(&flag, "ARKodeResize", 1)) return 1;
 
-    /* destroy and re-allocate linear solver memory */
-    flag = ARKPcg(arkode_mem, 0, udata->N);
-    if (check_flag(&flag, "ARKPcg", 1)) return 1;
-    flag = ARKSpilsSetJacTimesVecFn(arkode_mem, Jac);
-    if (check_flag(&flag, "ARKSpilsSetJacTimesVecFn", 1)) return 1;
+    /* destroy and re-allocate linear solver memory; reattach to ARKSpils interface */
+    SUNLinSolFree(LS);
+    LS = SUNPCG(y, 0, N);
+    if (check_flag((void *)LS, "SUNPCG", 0)) return 1;
+    flag = ARKSpilsSetLinearSolver(arkode_mem, LS);
+    if (check_flag(&flag, "ARKSpilsSetLinearSolver", 1)) return 1;
+    flag = ARKSpilsSetJacTimes(arkode_mem, NULL, Jac);
+    if (check_flag(&flag, "ARKSpilsSetJacTimes", 1)) return 1;
 
   }
   printf(" ----------------------------------------------------------------------------------------\n");
 
-  /* Free integrator memory */
-  ARKodeFree(&arkode_mem);
-
   /* print some final statistics */
   printf(" Final solver statistics:\n");
   printf("   Total number of time steps = %i\n", iout);
@@ -253,9 +276,11 @@ int main() {
   /* Clean up and return with successful completion */
   fclose(UFID);
   fclose(XFID);
-  N_VDestroy_Serial(y);        /* Free vectors */
+  N_VDestroy(y);               /* Free vectors */
   free(udata->x);              /* Free user data */
   free(udata);   
+  ARKodeFree(&arkode_mem);     /* Free integrator memory */
+  SUNLinSolFree(LS);           /* Free linear solver */
 
   return 0;
 }
@@ -268,12 +293,12 @@ int main() {
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
   UserData udata = (UserData) user_data;    /* access problem data */
-  long int N  = udata->N;                   /* set variable shortcuts */
+  sunindextype N = udata->N;                /* set variable shortcuts */
   realtype k  = udata->k;
   realtype *x = udata->x;
   realtype *Y=NULL, *Ydot=NULL;
   realtype dxL, dxR;
-  long int i;
+  sunindextype i;
   Y = N_VGetArrayPointer(y);      /* access data arrays */
   if (check_flag((void *) Y, "N_VGetArrayPointer", 0)) return 1;
   Ydot = N_VGetArrayPointer(ydot);
@@ -304,15 +329,15 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
 static int Jac(N_Vector v, N_Vector Jv, realtype t, N_Vector y, 
-	       N_Vector fy, void *user_data, N_Vector tmp)
+               N_Vector fy, void *user_data, N_Vector tmp)
 {
   UserData udata = (UserData) user_data;     /* variable shortcuts */
-  long int N  = udata->N;
+  sunindextype N = udata->N;
   realtype k  = udata->k;
   realtype *x = udata->x;
   realtype *V=NULL, *JV=NULL;
   realtype dxL, dxR;
-  long int i;
+  sunindextype i;
   V = N_VGetArrayPointer(v);       /* access data arrays */
   if (check_flag((void *) V, "N_VGetArrayPointer", 0)) return 1;
   JV = N_VGetArrayPointer(Jv);
@@ -345,12 +370,12 @@ static int Jac(N_Vector v, N_Vector Jv, realtype t, N_Vector y,
       Nnew [output] -- the size of the new mesh
       udata [input] -- the current system information 
    The return for this function is a pointer to the new mesh. */
-realtype * adapt_mesh(N_Vector y, long int *Nnew, UserData udata)
+realtype * adapt_mesh(N_Vector y, sunindextype *Nnew, UserData udata)
 {
-  int i, j;
+  sunindextype i, j;
   int *marks=NULL;
   realtype ydd, *xold=NULL, *Y=NULL, *xnew=NULL;
-  long int num_refine, N_new;
+  sunindextype num_refine, N_new;
 
   /* Access current solution and mesh arrays */
   xold = udata->x;
@@ -360,19 +385,6 @@ realtype * adapt_mesh(N_Vector y, long int *Nnew, UserData udata)
   /* create marking array */
   marks = calloc(udata->N-1, sizeof(int));
 
-  /* /\* perform marking:  */
-  /*     0 -> leave alone */
-  /*     1 -> refine */
-  /* realtype ymax, ymin; */
-  /* for (i=0; i<(udata->N-1); i++) { */
-
-  /*   /\* check for refinement *\/ */
-  /*   if (fabs(Y[i+1] - Y[i]) > udata->refine_tol) { */
-  /*     marks[i] = 1; */
-  /*     continue; */
-  /*   } */
-  /* } */
-
   /* perform marking: 
       0 -> leave alone
       1 -> refine */
@@ -440,10 +452,10 @@ realtype * adapt_mesh(N_Vector y, long int *Nnew, UserData udata)
       xnew [input] -- the new mesh
       ynew [output] -- the vector defined over the new mesh
                        (allocated prior to calling project) */
-static int project(long int Nold, realtype *xold, N_Vector yold, 
-		   long int Nnew, realtype *xnew, N_Vector ynew)
+static int project(sunindextype Nold, realtype *xold, N_Vector yold, 
+		   sunindextype Nnew, realtype *xnew, N_Vector ynew)
 {
-  int iv, i, j;
+  sunindextype iv, i, j;
   realtype *Yold=NULL, *Ynew=NULL;
 
   /* Access data arrays */
diff --git a/examples/arkode/C_serial/ark_heat1D_adapt.out b/examples/arkode/C_serial/ark_heat1D_adapt.out
index 5deda13..803aa6d 100644
--- a/examples/arkode/C_serial/ark_heat1D_adapt.out
+++ b/examples/arkode/C_serial/ark_heat1D_adapt.out
@@ -6,102 +6,156 @@
  ----------------------------------------------------------------------------------------
     0  0.000000000000000e+00  0.000000000000000e+00  0.000000000000000e+00  21    0    0
     1  3.629021901461023e-12  7.505751048377368e-09  2.979166031186306e-12  21    5    5
-    2  7.505751048377368e-09  1.501150209675474e-07  6.164657920203414e-09  21   10    5
-    3  1.501150209675474e-07  3.002300419350948e-06  1.293969127876394e-07  21   10    9
-    4  3.002300419350948e-06  6.004600838701896e-05  2.593514282989167e-06  21   10   10
-    5  6.004600838701896e-05  2.854024143748609e-04  5.166758334585204e-05  21   10   19
-    6  2.854024143748609e-04  2.575205831761056e-04  2.798713300800731e-04  21   10   25
-    7  2.575205831761056e-04  4.094402057669300e-04  4.794364798148849e-04  21   10   24
-    8  4.094402057669300e-04  4.094402057669300e-04  7.863867077537864e-04  21   10   25
-    9  4.094402057669300e-04  6.523109871323949e-04  1.082800057988263e-03  21   10   25
-   10  6.523109871323949e-04  5.699145720577265e-04  1.606864160614628e-03  23   10   38
-   11  5.699145720577265e-04  1.008085270318922e-03  2.005677987304881e-03  23   10   32
-   12  1.008085270318922e-03  1.008085270318922e-03  2.683212443767887e-03  23   10   37
-   13  1.008085270318922e-03  8.454396857243886e-04  3.678750660517184e-03  25   10   37
-   14  8.454396857243886e-04  1.990629597547611e-03  4.265439688800132e-03  25   10   30
-   15  1.990629597547611e-03  1.990629597547611e-03  5.575407085415051e-03  25   10   39
-   16  1.990629597547611e-03  3.607197488602903e-03  6.798927523968801e-03  25   10   30
-   17  4.981039682699363e-04  4.981039682699363e-04  6.927552935378208e-03  27   30  156
-   18  4.981039682699363e-04  4.981039682699363e-04  7.442138500375902e-03  29   10   25
-   19  4.981039682699363e-04  1.668573980211983e-03  7.723152304280749e-03  29   10   24
-   20  1.668573980211983e-03  3.654706558768539e-03  8.637924517668507e-03  29   10   37
-   21  3.654706558768539e-03  7.224979051078588e-03  1.050599896879328e-02  29   10   49
-   22  2.276551141355698e-04  2.276551141355698e-04  1.033397994768772e-02  32   40  256
-   23  2.276551141355698e-04  4.413353554788115e-04  1.092338188288813e-02  34   10   20
-   24  4.413353554788115e-04  1.019444046442095e-03  1.113522375604393e-02  34   10   24
-   25  1.019444046442095e-03  1.019444046442095e-03  1.161555502336150e-02  34   10   35
-   26  1.019444046442095e-03  3.726408116521474e-03  1.208389269353381e-02  34   10   29
-   27  3.726408116521474e-03  3.726408116521474e-03  1.369916870976818e-02  34   10   59
-   28  3.726408116521474e-03  1.017517861007844e-02  1.517662504289777e-02  34   10   55
-   29  1.350491936829535e-03  1.350491936829535e-03  1.559233522680444e-02  36   30  212
-   30  1.350491936829535e-03  3.706502672803281e-03  1.608657213958387e-02  36   10   25
-   31  2.814808489615957e-03  2.814808489615957e-03  1.706503329381448e-02  38   20  119
-   32  6.183994739341915e-04  6.183994739341915e-04  1.691544997123700e-02  40   30  223
-   33  6.183994739341915e-04  1.092896364473831e-03  1.711576767264562e-02  40   10   34
-   34  1.092896364473831e-03  3.025071844878339e-03  1.746342433106013e-02  40   10   43
-   35  3.025071844878339e-03  7.404939993948745e-03  1.838448885341201e-02  40   10   79
-   36  7.404939993948745e-03  1.389603706836776e-02  2.040556371949357e-02  40   10  139
-   37  6.710477939748602e-04  6.710477939748602e-04  1.988129068907885e-02  44   40  647
-   38  6.710477939748602e-04  1.028024256319047e-03  1.965202427908446e-02  46   10   36
-   39  1.028024256319047e-03  2.833952015856033e-03  1.989188365758057e-02  46   10   37
-   40  2.833952015856033e-03  4.952800324532025e-03  2.052762374827459e-02  46   10   66
-   41  4.952800324532025e-03  8.714201527775771e-03  2.155483443164250e-02  46   10  105
-   42  8.714201527775771e-03  1.720615368906233e-02  2.313292126778931e-02  46   10  167
-   43  3.805803440168311e-03  3.805803440168311e-03  2.360451299933607e-02  48   30  689
-   44  8.023837169729728e-04  8.023837169729728e-04  2.346209634272231e-02  50   30  314
-   45  8.023837169729728e-04  1.503536834976284e-03  2.358170211412561e-02  50   10   55
-   46  1.503536834976284e-03  4.513095256928524e-03  2.380061610322121e-02  50   10   59
-   47  3.495461232776950e-03  3.495461232776950e-03  2.428544643707820e-02  50   20  227
-   48  3.495461232776950e-03  1.098574695245117e-02  2.473894746889214e-02  50   10   75
-   49  1.098574695245117e-02  1.818917139221294e-02  2.598434629024265e-02  50   10  172
-   50  1.818917139221294e-02  2.767038680802522e-02  2.756281122436279e-02  50   10  283
-   51  6.917596702006305e-03  6.917596702006305e-03  2.913159038624379e-02  54   15  479
-   52  6.917596702006305e-03  1.065864858639081e-02  2.956607928921659e-02  54   10  134
-   53  1.065864858639081e-02  1.729721723319153e-02  2.981861064666339e-02  56   10  230
-   54  1.729721723319153e-02  2.878451485340029e-02  3.010100614649229e-02  58   10  278
-   55  2.878451485340029e-02  2.878451485340029e-02  3.043378148315333e-02  60   10  334
-   56  7.196128713350072e-03  7.196128713350072e-03  3.058796042164046e-02  60   15  351
-   57  7.196128713350072e-03  1.269773298304222e-02  3.072680212128632e-02  60   10  103
-   58  1.269773298304222e-02  3.569678515456698e-02  3.093999932706822e-02  60   10  165
-   59  3.569678515456698e-02  5.811742143859773e-02  3.138094315135925e-02  60   10  330
-   60  1.452935535964943e-02  1.452935535964943e-02  3.151366976890378e-02  60   18  596
-   61  1.452935535964943e-02  3.911347912422928e-02  3.162764839842241e-02  60   10  145
-   62  3.911347912422928e-02  6.256393965526523e-02  3.186787605580501e-02  60   10  380
-   63  1.564098491381631e-02  1.564098491381631e-02  3.194430211081341e-02  60   12  335
-   64  1.564098491381631e-02  3.474495618112731e-02  3.201248645476758e-02  60   10  135
-   65  8.686239045281827e-03  8.686239045281827e-03  3.204730735551981e-02  60   11  424
-   66  8.686239045281827e-03  1.579835682746987e-02  3.208019059681224e-02  60   10  330
-   67  1.579835682746987e-02  2.864626865176246e-02  3.213558185506317e-02  60   10  224
-   68  2.864626865176246e-02  4.778509342320859e-02  3.222364307660728e-02  60   10  316
-   69  1.194627335580215e-02  1.194627335580215e-02  3.225635676188716e-02  60   21  750
-   70  1.194627335580215e-02  3.465947907026466e-02  3.228701697329782e-02  60   10  162
-   71  3.465947907026466e-02  7.907534915954270e-02  3.236578972146440e-02  60   10  296
-   72  1.976883728988568e-02  1.976883728988568e-02  3.240484236283207e-02  60   12  424
-   73  1.976883728988568e-02  4.238773098868815e-02  3.244021773389890e-02  60   10  267
-   74  4.238773098868815e-02  4.238773098868815e-02  3.250539064364061e-02  60   10  374
-   75  4.238773098868815e-02  4.238773098868815e-02  3.255839583346429e-02  60   10  365
-   76  1.059693274717204e-02  1.059693274717204e-02  3.257003190199415e-02  60   23  675
-   77  1.059693274717204e-02  3.374224101621920e-02  3.258108845266754e-02  60   10  119
-   78  3.374224101621920e-02  7.028500459469654e-02  3.261274207384274e-02  60   14  539
-   79  1.757125114867414e-02  1.757125114867414e-02  3.262729018183993e-02  60   12  317
-   80  1.757125114867414e-02  3.430166354319600e-02  3.264065556631886e-02  60   10  186
-   81  3.430166354319600e-02  5.964635069535813e-02  3.266369564112172e-02  60   10  300
-   82  1.491158767383953e-02  1.491158767383953e-02  3.267257507399515e-02  60   12  303
-   83  1.491158767383953e-02  4.151059356915939e-02  3.268083759515131e-02  60   10  134
-   84  1.037764839228985e-02  1.037764839228985e-02  3.268624676047530e-02  60   23  767
-   85  1.037764839228985e-02  2.337923819490379e-02  3.269138828929134e-02  60   10  214
-   86  2.337923819490379e-02  5.584751455212315e-02  3.270207501116806e-02  60   10  224
-   87  1.396187863803079e-02  1.396187863803079e-02  3.270790060704231e-02  60   12  243
-   88  1.396187863803079e-02  4.841828824573841e-02  3.271334794042778e-02  60   10  155
-   89  4.841828824573841e-02  7.963760672802837e-02  3.272963100640804e-02  60   10  324
-   90  1.990940168200709e-02  1.990940168200709e-02  3.273528876716780e-02  60   12  441
-   91  1.990940168200709e-02  3.127117602453464e-02  3.274045071854639e-02  60   10  212
-   92  3.127117602453464e-02  5.250130431989954e-02  3.274757629125738e-02  60   10  408
-   93  5.250130431989954e-02  1.730734444761127e-02  3.275738955577872e-02  60   10  401
-   94  1.730734444761127e-02  1.730734444761127e-02  3.276011960220934e-02  60   10  134
+    2  7.505751048377368e-09  1.501150209675474e-07  6.164657920203414e-09  21    5    5
+    3  1.501150209675474e-07  3.002300419350948e-06  1.293969127947313e-07  21    5   10
+    4  3.002300419350948e-06  6.004600838701896e-05  2.593514282996240e-06  21    5   10
+    5  6.004600838701896e-05  2.853822155069504e-04  5.166758334585902e-05  21    5   20
+    6  2.853822155069504e-04  2.575259959881400e-04  2.798554542679515e-04  21    5   25
+    7  2.575259959881400e-04  4.094548233861796e-04  4.794251765596532e-04  21    5   25
+    8  4.094548233861796e-04  4.094548233861796e-04  7.863865837860686e-04  21    5   29
+    9  4.094548233861796e-04  6.522930286475272e-04  1.082810355919634e-03  21    5   29
+   10  6.522930286475272e-04  5.699101877577966e-04  1.606861594786204e-03  23    5   40
+   11  5.699101877577966e-04  1.007840457057906e-03  2.005672441483511e-03  23    5   35
+   12  1.007840457057906e-03  1.007840457057906e-03  2.683046459431835e-03  23    5   40
+   13  1.007840457057906e-03  8.454000528271813e-04  3.678403481054160e-03  25    5   40
+   14  8.454000528271813e-04  1.990435218830378e-03  4.265076936821718e-03  25    5   34
+   15  1.990435218830378e-03  1.990435218830378e-03  5.574945959454541e-03  25    5   41
+   16  1.990435218830378e-03  3.606553655154849e-03  6.798379766368275e-03  25    5   35
+   17  4.980855396285853e-04  4.980855396285853e-04  6.927018828146161e-03  27   15  180
+   18  4.980855396285853e-04  4.980855396285853e-04  7.441580402798036e-03  29    5   30
+   19  4.980855396285853e-04  1.668133018307288e-03  7.722592473539556e-03  29    5   29
+   20  1.668133018307288e-03  3.660004265101941e-03  8.637154192038343e-03  29    5   44
+   21  3.660004265101941e-03  7.226949406752795e-03  1.050788196949932e-02  29    5   65
+   22  2.276521387614356e-04  2.276521387614356e-04  1.033580293681806e-02  32   20  250
+   23  2.276521387614356e-04  4.412350777869864e-04  1.092527817875175e-02  34    5   25
+   24  4.412350777869864e-04  1.020413899408159e-03  1.113705034977643e-02  34    5   33
+   25  1.020413899408159e-03  1.020413899408159e-03  1.161778510530845e-02  34    5   36
+   26  1.020413899408159e-03  3.914477903991188e-03  1.208650527259153e-02  34    5   38
+   27  3.914477903991188e-03  3.863837123846752e-03  1.377926229263401e-02  34    5   84
+   28  3.863837123846752e-03  1.037407750440344e-02  1.530185459208104e-02  34    5   56
+   29  1.363199179529315e-03  1.363199179529315e-03  1.571851800751950e-02  36   15  253
+   30  1.363199179529315e-03  3.720982558007261e-03  1.621352688371651e-02  36    5   30
+   31  2.839477925818388e-03  2.839477925818388e-03  1.719440430281024e-02  38   10  143
+   32  6.183830642849918e-04  6.183830642849918e-04  1.703962466197268e-02  40   15  265
+   33  6.183830642849918e-04  1.090172276956425e-03  1.723827240506588e-02  40    5   48
+   34  1.090172276956425e-03  3.086897492998023e-03  1.758220670590121e-02  40    5   51
+   35  3.086897492998023e-03  9.189481003520772e-03  1.851386070398507e-02  40    5   92
+   36  2.168294103543354e-03  2.168294103543354e-03  1.913272771008736e-02  40   15  295
+   37  2.168294103543354e-03  1.340384137004741e-02  1.972399583300435e-02  40    5   59
+   38  5.812224498062428e-04  5.812224498062428e-04  1.920177174402561e-02  44   15  260
+   39  5.812224498062428e-04  1.201854341403621e-03  1.935027674784279e-02  44    5   45
+   40  1.201854341403621e-03  1.201854341403621e-03  1.926722357809200e-02  46    5   61
+   41  1.201854341403621e-03  2.707654904718135e-03  1.955647594025218e-02  46    5   49
+   42  2.707654904718135e-03  8.167771971577526e-03  2.018265172686167e-02  46    5   86
+   43  8.167771971577526e-03  2.228884185115612e-02  2.187630679781082e-02  46    5  105
+   44  4.841961314808491e-03  4.841961314808491e-03  2.275719111599154e-02  46   10  210
+   45  4.841961314808491e-03  4.278353117293444e-03  2.341800091318264e-02  48    5  105
+   46  8.666123066596883e-04  8.666123066596883e-04  2.328959407763166e-02  50   15  278
+   47  8.666123066596883e-04  1.577957110996383e-03  2.342157007978272e-02  50    5   61
+   48  1.577957110996383e-03  3.905707245551271e-03  2.365597458798312e-02  50    5   78
+   49  3.905707245551271e-03  6.469519120965484e-03  2.420610770654505e-02  50    5  104
+   50  6.469519120965484e-03  6.469519120965484e-03  2.503182513494434e-02  50    5  105
+   51  6.469519120965484e-03  6.469519120965484e-03  2.576271724610646e-02  50    5  105
+   52  6.469519120965484e-03  6.469519120965484e-03  2.641053106220365e-02  50    5  105
+   53  6.469519120965484e-03  1.108805289708852e-02  2.698543541741437e-02  50    5  105
+   54  1.108805289708852e-02  1.108805289708852e-02  2.782635663999346e-02  50    5  105
+   55  6.835117233020605e-04  6.835117233020605e-04  2.896361477166220e-02  54   15  270
+   56  6.835117233020605e-04  1.151305755085364e-03  2.901108027372151e-02  54    5   46
+   57  1.151305755085364e-03  3.129774748026494e-03  2.908967783906003e-02  54    5   58
+   58  3.129774748026494e-03  8.609429177129353e-03  2.929521478173503e-02  54    5  104
+   59  2.150342527110547e-03  2.150342527110547e-03  2.911324503173272e-02  56   15  294
+   60  2.150342527110547e-03  8.517468909855426e-03  2.924196213506022e-02  56    5   55
+   61  8.517468909855426e-03  1.663331893058921e-02  2.970696982039420e-02  56    5  105
+   62  5.355215538377122e-03  5.355215538377122e-03  2.952512784910986e-02  58   10  210
+   63  5.355215538377122e-03  1.039195128336290e-02  2.927837054319690e-02  60    5  105
+   64  1.039195128336290e-02  1.039195128336290e-02  2.967026863628866e-02  60    5  105
+   65  1.039195128336290e-02  1.039195128336290e-02  3.000116199877719e-02  60    5  105
+   66  1.039195128336290e-02  1.653053729845406e-02  3.028199663378029e-02  60    5  105
+   67  3.490041788063467e-03  3.490041788063467e-03  3.036664137395542e-02  60   10  210
+   68  3.490041788063467e-03  9.321300572970054e-03  3.044694680348070e-02  60    5   92
+   69  9.321300572970054e-03  1.656938599610255e-02  3.064214362027811e-02  60    5  105
+   70  6.689272324485894e-03  6.689272324485894e-03  3.076687087436790e-02  60   10  210
+   71  6.689272324485894e-03  1.173716038088588e-02  3.088038912250233e-02  60    5  105
+   72  6.963861522328313e-03  6.963861522328313e-03  3.098810922732776e-02  60   10  210
+   73  6.963861522328313e-03  6.963861522328313e-03  3.108625384471981e-02  60    5  105
+   74  6.963861522328313e-03  1.742181193729524e-02  3.117602182147214e-02  60    5  105
+   75  1.994783963919660e-03  1.994783963919660e-03  3.120032141537850e-02  60   10  199
+   76  1.994783963919660e-03  1.201253333149048e-02  3.122403696266679e-02  60    5   55
+   77  1.201253333149048e-02  1.998264901013797e-02  3.135545846719004e-02  60    5  105
+   78  1.057571395069471e-02  1.057571395069471e-02  3.145706479095915e-02  60   10  210
+   79  5.338538004115864e-03  5.338538004115864e-03  3.150412713296585e-02  60   10  210
+   80  5.338538004115864e-03  5.338538004115864e-03  3.154849234751519e-02  60    5  105
+   81  5.338538004115864e-03  5.338538004115864e-03  3.159032792334895e-02  60    5  105
+   82  5.338538004115864e-03  5.338538004115864e-03  3.163033837030680e-02  60    5  105
+   83  5.338538004115864e-03  1.081065360661389e-02  3.166822069310911e-02  60    5  105
+   84  1.081065360661389e-02  2.270532797926388e-02  3.173936353608864e-02  60    5  105
+   85  1.407235704745696e-02  1.407235704745696e-02  3.182237047104994e-02  60   10  210
+   86  1.407235704745696e-02  1.407235704745696e-02  3.189628438600168e-02  60    5  105
+   87  1.096924021823070e-02  1.096924021823070e-02  3.194867768991059e-02  60   10  210
+   88  9.062583968230507e-03  9.062583968230507e-03  3.198877459022959e-02  60   10  210
+   89  9.062583968230507e-03  9.062583968230507e-03  3.202649013383122e-02  60    5  105
+   90  9.062583968230507e-03  1.854330009652574e-02  3.206199184251779e-02  60    5  105
+   91  7.275256468734395e-03  7.275256468734395e-03  3.208902134993789e-02  60   10  210
+   92  7.275256468734395e-03  7.275256468734395e-03  3.211479197560889e-02  60    5  105
+   93  7.275256468734395e-03  1.343722073078673e-02  3.213947173436447e-02  60    5  105
+   94  1.343722073078673e-02  1.343722073078673e-02  3.218231923362697e-02  60    5  105
+   95  1.343722073078673e-02  1.343722073078673e-02  3.222198245451283e-02  60    5  105
+   96  8.738504226293461e-03  8.738504226293461e-03  3.224620949591547e-02  60   10  210
+   97  8.738504226293461e-03  8.738504226293461e-03  3.226929216428927e-02  60    5  105
+   98  8.738504226293461e-03  8.738504226293461e-03  3.229133052117475e-02  60    5  105
+   99  8.738504226293461e-03  8.738504226293461e-03  3.231236514966884e-02  60    5  105
+  100  8.738504226293461e-03  8.738504226293461e-03  3.233245143876047e-02  60    5  105
+  101  8.738504226293461e-03  7.554369121202203e-03  3.235162465644394e-02  60    5  105
+  102  7.554369121202203e-03  7.554369121202203e-03  3.236756699844760e-02  60    5  105
+  103  7.554369121202203e-03  1.218417508883314e-02  3.238288479646791e-02  60    5  105
+  104  1.218417508883314e-02  1.155388646205265e-02  3.240634980585942e-02  60    5  105
+  105  1.811171851388263e-03  1.811171851388263e-03  3.240977844911185e-02  60   15  315
+  106  1.811171851388263e-03  3.361886744791586e-03  3.241312772400719e-02  60    5   93
+  107  3.361886744791586e-03  1.033910886872147e-02  3.241925502318792e-02  60    5  103
+  108  1.033910886872147e-02  2.441293522007783e-02  3.243746838367529e-02  60    5  105
+  109  2.441293522007783e-02  2.441293522007783e-02  3.247696962157356e-02  60    5  105
+  110  3.476352863212293e-03  3.476352863212293e-03  3.248220776272515e-02  60   15  315
+  111  3.476352863212293e-03  9.218367100190090e-03  3.248736865746580e-02  60    5   90
+  112  9.218367100190090e-03  1.630545320156485e-02  3.250062717212909e-02  60    5  105
+  113  1.630545320156485e-02  1.630545320156485e-02  3.252268496958285e-02  60    5  105
+  114  1.360173029326723e-02  1.360173029326723e-02  3.253975131902367e-02  60   10  210
+  115  1.360173029326723e-02  1.360173029326723e-02  3.255573928064356e-02  60    5  105
+  116  1.360173029326723e-02  1.360173029326723e-02  3.257081579920346e-02  60    5  105
+  117  2.182769056602851e-03  2.182769056602851e-03  3.257312740529266e-02  60   15  307
+  118  2.182769056602851e-03  4.857547682935582e-03  3.257541930361192e-02  60    5   71
+  119  4.857547682935582e-03  1.734670432583494e-02  3.258043277204955e-02  60    5  102
+  120  9.811407999192901e-03  9.811407999192901e-03  3.259020493932307e-02  60   10  210
+  121  9.811407999192901e-03  2.367114337638019e-02  3.259952477922826e-02  60    5  105
+  122  2.367114337638019e-02  2.367114337638019e-02  3.262022910717802e-02  60    5  105
+  123  1.760105842389832e-02  1.760105842389832e-02  3.263420425186855e-02  60   10  210
+  124  3.600221325534810e-03  3.600221325534810e-03  3.263693770419109e-02  60   15  315
+  125  3.600221325534810e-03  6.936806986533508e-03  3.263960895925759e-02  60    5   94
+  126  6.936806986533508e-03  1.996731602442927e-02  3.264461543200432e-02  60    5   99
+  127  1.996731602442927e-02  5.145062225865121e-02  3.265812226778766e-02  60    5  105
+  128  2.314774589415722e-02  2.314774589415722e-02  3.267234396964767e-02  60   10  210
+  129  1.508691231982707e-02  1.508691231982707e-02  3.268062278955736e-02  60   10  210
+  130  1.508691231982707e-02  1.508691231982707e-02  3.268839122922051e-02  60    5  105
+  131  1.508691231982707e-02  1.299251469251291e-02  3.269569303472316e-02  60    5  105
+  132  1.299251469251291e-02  1.299251469251291e-02  3.270146236885218e-02  60    5  105
+  133  1.299251469251291e-02  1.118215314345060e-02  3.270692011193020e-02  60    5  105
+  134  1.118215314345060e-02  1.007338486346974e-02  3.271137236821686e-02  60    5  105
+  135  1.007338486346974e-02  2.023490392120921e-02  3.271519107389274e-02  60    5  105
+  136  2.023490392120921e-02  2.023490392120921e-02  3.272223473384296e-02  60    5  105
+  137  1.437863853617764e-02  1.437863853617764e-02  3.272694415195673e-02  60   10  210
+  138  1.437863853617764e-02  1.437863853617764e-02  3.273118371869058e-02  60    5  105
+  139  1.437863853617764e-02  1.437863853617764e-02  3.273528474348136e-02  60    5  105
+  140  1.437863853617764e-02  1.437863853617764e-02  3.273901013755619e-02  60    5  105
+  141  1.437863853617764e-02  1.437863853617764e-02  3.274258196530572e-02  60    5  105
+  142  1.123655402508177e-02  1.123655402508177e-02  3.274509621583101e-02  60   10  210
+  143  1.123655402508177e-02  1.806364327875622e-02  3.274757149970708e-02  60    5  105
+  144  1.417319080046484e-02  1.417319080046484e-02  3.275049431206997e-02  60   10  210
+  145  1.417319080046484e-02  1.417319080046484e-02  3.275314358470142e-02  60    5  105
+  146  1.417319080046484e-02  1.417319080046484e-02  3.275568497629092e-02  60    5  105
+  147  1.417319080046484e-02  1.343317405520937e-02  3.275806624214909e-02  60    5  105
+  148  1.343317405520937e-02  1.343317405520937e-02  3.276015109996818e-02  60    5  105
  ----------------------------------------------------------------------------------------
  Final solver statistics:
-   Total number of time steps = 94
-   Total nonlinear iterations = 1187
-   Total linear iterations    = 18988
+   Total number of time steps = 148
+   Total nonlinear iterations = 985
+   Total linear iterations    = 17338
 
diff --git a/examples/arkode/C_serial/ark_robertson.c b/examples/arkode/C_serial/ark_robertson.c
index f6b9bfd..328d887 100644
--- a/examples/arkode/C_serial/ark_robertson.c
+++ b/examples/arkode/C_serial/ark_robertson.c
@@ -29,8 +29,8 @@
  * 
  * This program solves the problem with one of the solvers, ERK, 
  * DIRK or ARK.  For DIRK and ARK, implicit subsystems are solved 
- * using a Newton iteration with the ARKDENSE dense linear solver, 
- * and a user-supplied Jacobian routine.
+ * using a Newton iteration with the dense SUNLinearSolver, and a
+ * user-supplied Jacobian routine.
  *
  * 100 outputs are printed at equal intervals, and run statistics 
  * are printed at the end.
@@ -39,21 +39,34 @@
 /* Header files */
 #include <stdio.h>
 #include <math.h>
-#include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
-#include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_dense.h>      /* prototype for ARKDense solver */
-#include <sundials/sundials_dense.h>  /* defs. of DlsMat and DENSE_ELEM */
-#include <sundials/sundials_types.h>  /* def. of type 'realtype' */
+#include <arkode/arkode.h>              /* prototypes for ARKode fcts., consts. */
+#include <nvector/nvector_serial.h>     /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_dense.h>  /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h>  /* access to dense SUNLinearSolver      */
+#include <arkode/arkode_direct.h>       /* access to ARKDls interface           */
+#include <sundials/sundials_types.h>    /* defs. of 'realtype', 'sunindextype'  */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
+/* Private function to check computed solution */
+static int check_ans(N_Vector y, realtype t, realtype rtol, realtype atol);
+
 /* Main Program */
 int main()
 {
@@ -62,11 +75,13 @@ int main()
   realtype Tf = RCONST(1.e11);   /* final time */
   realtype dTout = (Tf-T0)/100;  /* time between outputs */
   int Nt = ceil(Tf/dTout);       /* number of output times */
-  long int NEQ = 3;              /* number of dependent vars. */
+  sunindextype NEQ = 3;              /* number of dependent vars. */
 
   /* general problem variables */
   int flag;                      /* reusable error-checking flag */
   N_Vector y = NULL;             /* empty vector for storing solution */
+  SUNMatrix A = NULL;            /* empty matrix for linear solver */
+  SUNLinearSolver LS = NULL;     /* empty linear solver object */
   void *arkode_mem = NULL;       /* empty ARKode memory structure */
   FILE *UFID;
   realtype t, tout;
@@ -83,7 +98,7 @@ int main()
 
   /* Initial problem output */
   printf("\nRobertson ODE test problem:\n");
-  printf("    initial conditions:  u0 = %g,  v0 = %g,  w0 = %g\n",u0,v0,w0);
+  printf("    initial conditions:  u0 = %"GSYM",  v0 = %"GSYM",  w0 = %"GSYM"\n",u0,v0,w0);
 
   /* Initialize data structures */
   y = N_VNew_Serial(NEQ);         /* Create serial vector for solution */
@@ -117,18 +132,24 @@ int main()
   flag = ARKodeSStolerances(arkode_mem, reltol, abstol);   /* Specify tolerances */
   if (check_flag(&flag, "ARKodeSStolerances", 1)) return 1;
 
-  /* Linear solver specification */
-  flag = ARKDense(arkode_mem, NEQ);                        /* Specify dense linear solver */
-  if (check_flag(&flag, "ARKDense", 1)) return 1;
-  flag = ARKDlsSetDenseJacFn(arkode_mem, Jac);             /* Set the Jacobian routine */
-  if (check_flag(&flag, "ARKDlsSetDenseJacFn", 1)) return 1;
+  /* Initialize dense matrix data structure and solver */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)A, "SUNDenseMatrix", 0)) return 1;
+  LS = SUNDenseLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return 1;
+
+  /* Linear solver interface */
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);        /* Attach matrix and linear solver */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                 /* Set the Jacobian routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
 
   /* Open output stream for results, output comment line */
   UFID = fopen("solution.txt","w");
   fprintf(UFID,"# t u v w\n");
 
   /* output initial condition to disk */
-  fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+  fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	  T0, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
@@ -137,15 +158,15 @@ int main()
   tout = T0+dTout;
   printf("        t           u           v           w\n");
   printf("   --------------------------------------------------\n");
-  printf("  %10.3e  %12.5e  %12.5e  %12.5e\n",
+  printf("  %10.3"ESYM"  %12.5"ESYM"  %12.5"ESYM"  %12.5"ESYM"\n",
       t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));
   for (iout=0; iout<Nt; iout++) {
 
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);       /* call integrator */
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %10.3e  %12.5e  %12.5e  %12.5e\n",              /* access/print solution */
+    printf("  %10.3"ESYM"  %12.5"ESYM"  %12.5"ESYM"  %12.5"ESYM"\n",              /* access/print solution */
         t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));
-    fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+    fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	    t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
     if (flag >= 0) {                                          /* successful solve: update time */
       tout += dTout;
@@ -189,10 +210,16 @@ int main()
   printf("   Total number of nonlinear solver convergence failures = %li\n", ncfn);
   printf("   Total number of error test failures = %li\n", netf);
 
+  /* check the solution error */
+  flag = check_ans(y, t, reltol, abstol);
+
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);        /* Free y vector */
+  N_VDestroy(y);               /* Free y vector */
   ARKodeFree(&arkode_mem);     /* Free integrator memory */
-  return 0;
+  SUNLinSolFree(LS);           /* Free linear solver */
+  SUNMatDestroy(A);            /* Free A matrix */
+
+  return flag;
 }
 
 /*-------------------------------
@@ -215,24 +242,23 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 }
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype v = NV_Ith_S(y,1);   /* access current solution */
   realtype w = NV_Ith_S(y,2);
-  SetToZero(J);                 /* initialize Jacobian to zero */
+  SUNMatZero(J);                /* initialize Jacobian to zero */
 
   /* Fill in the Jacobian of the ODE RHS function */
-  DENSE_ELEM(J,0,0) = -0.04;
-  DENSE_ELEM(J,0,1) = 1.e4*w;
-  DENSE_ELEM(J,0,2) = 1.e4*v;
+  SM_ELEMENT_D(J,0,0) = -0.04;
+  SM_ELEMENT_D(J,0,1) = 1.e4*w;
+  SM_ELEMENT_D(J,0,2) = 1.e4*v;
 
-  DENSE_ELEM(J,1,0) = 0.04;
-  DENSE_ELEM(J,1,1) = -1.e4*w - 6.e7*v;
-  DENSE_ELEM(J,1,2) = -1.e4*v;
+  SM_ELEMENT_D(J,1,0) = 0.04;
+  SM_ELEMENT_D(J,1,1) = -1.e4*w - 6.e7*v;
+  SM_ELEMENT_D(J,1,2) = -1.e4*v;
 
-  DENSE_ELEM(J,2,1) = 6.e7*v;
+  SM_ELEMENT_D(J,2,1) = 6.e7*v;
 
   return 0;                     /* Return with success */
 }
@@ -276,5 +302,52 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
   return 0;
 }
 
+/* compare the solution at the final time 1e11s to a reference solution computed
+   using a relative tolerance of 1e-8 and absoltue tolerance of 1e-14 */
+static int check_ans(N_Vector y, realtype t, realtype rtol, realtype atol)
+{
+  int      passfail=0;        /* answer pass (0) or fail (1) flag */  
+  N_Vector ref;               /* reference solution vector        */
+  N_Vector ewt;               /* error weight vector              */
+  realtype err;               /* wrms error                       */
+  realtype ZERO=RCONST(0.0);  
+  realtype ONE=RCONST(1.0);  
+
+  /* create reference solution and error weight vectors */
+  ref = N_VClone(y);
+  ewt = N_VClone(y);
+
+  /* set the reference solution data */
+  NV_Ith_S(ref,0) = RCONST(2.0833403356917897e-08);
+  NV_Ith_S(ref,1) = RCONST(8.1470714598028223e-14);
+  NV_Ith_S(ref,2) = RCONST(9.9999997916651040e-01);
+
+  /* compute the error weight vector */
+  N_VAbs(ref, ewt);
+  N_VScale(rtol, ewt, ewt);
+  N_VAddConst(ewt, atol, ewt);
+  if (N_VMin(ewt) <= ZERO) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: check_ans failed - ewt <= 0\n\n");
+    return(-1);
+  }
+  N_VInv(ewt, ewt);   
+
+  /* compute the solution error */
+  N_VLinearSum(ONE, y, -ONE, ref, ref);
+  err = N_VWrmsNorm(ref, ewt);
+
+  /* is the solution within the tolerances? */
+  passfail = (err < ONE) ? 0 : 1; 
+
+  if (passfail) {
+    fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%g \n\n", err);
+  }
+
+  /* Free vectors */
+  N_VDestroy(ref);
+  N_VDestroy(ewt);
+
+  return(passfail);
+}
 
 /*---- end of file ----*/
diff --git a/examples/arkode/C_serial/ark_robertson_root.c b/examples/arkode/C_serial/ark_robertson_root.c
index d3bce8a..f2124c0 100644
--- a/examples/arkode/C_serial/ark_robertson_root.c
+++ b/examples/arkode/C_serial/ark_robertson_root.c
@@ -32,8 +32,8 @@
  * 
  * This program solves the problem with one of the solvers, ERK, 
  * DIRK or ARK.  For DIRK and ARK, implicit subsystems are solved 
- * using a Newton iteration with the ARKDENSE dense linear solver, 
- * and a user-supplied Jacobian routine.
+ * using a Newton iteration with the dense SUNLinearSolver, and a  
+ * user-supplied Jacobian routine.
  *
  * 100 outputs are printed at equal intervals, and run statistics 
  * are printed at the end.
@@ -42,19 +42,28 @@
 /* Header files */
 #include <stdio.h>
 #include <math.h>
-#include <arkode/arkode.h>            /* prototypes for ARKode fcts., consts. */
-#include <nvector/nvector_serial.h>   /* serial N_Vector types, fcts., macros */
-#include <arkode/arkode_dense.h>      /* prototype for ARKDense solver */
-#include <sundials/sundials_dense.h>  /* defs. of DlsMat and DENSE_ELEM */
-#include <sundials/sundials_types.h>  /* def. of type 'realtype' */
+#include <arkode/arkode.h>              /* prototypes for ARKode fcts., consts. */
+#include <nvector/nvector_serial.h>     /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_dense.h>  /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h>  /* access to dense SUNLinearSolver      */
+#include <arkode/arkode_direct.h>       /* access to ARKDls interface           */
+#include <sundials/sundials_types.h>    /* defs. of 'realtype', 'sunindextype'  */
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
 
 /* User-supplied Functions Called by the Solver */
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int g(realtype t, N_Vector y,
-          realtype *gout, void *user_data);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
 /* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -67,7 +76,7 @@ int main()
   realtype T1 = RCONST(0.4);     /* first output time */
   realtype TMult = RCONST(10.0); /* output time multiplication factor */
   int Nt = 12;                   /* total number of output times */
-  long int NEQ = 3;              /* number of dependent vars. */
+  sunindextype NEQ = 3;              /* number of dependent vars. */
   realtype reltol;
   int rootsfound[2];
   long int nst, nst_a, nfe, nfi, nsetups;
@@ -80,6 +89,8 @@ int main()
   /* general problem variables */
   N_Vector y = NULL;             /* empty vector for storing solution */
   N_Vector atols = NULL;         /* empty vector for absolute tolerances */
+  SUNMatrix A = NULL;            /* empty matrix for linear solver */
+  SUNLinearSolver LS = NULL;     /* empty linear solver object */
   void *arkode_mem = NULL;       /* empty ARKode memory structure */
 
   /* set up the initial conditions */
@@ -89,7 +100,7 @@ int main()
 
   /* Initial problem output */
   printf("\nRobertson ODE test problem (with rootfinding):\n");
-  printf("    initial conditions:  u0 = %g,  v0 = %g,  w0 = %g\n",u0,v0,w0);
+  printf("    initial conditions:  u0 = %"GSYM",  v0 = %"GSYM",  w0 = %"GSYM"\n",u0,v0,w0);
 
   /* Initialize data structures */
   y = N_VNew_Serial(NEQ);        /* Create serial vector for solution */
@@ -133,18 +144,24 @@ int main()
   flag = ARKodeRootInit(arkode_mem, 2, g);
   if (check_flag(&flag, "ARKodeRootInit", 1)) return 1;
 
-  /* Linear solver specification */
-  flag = ARKDense(arkode_mem, NEQ);                /* Specify dense linear solver */
-  if (check_flag(&flag, "ARKDense", 1)) return 1;
-  flag = ARKDlsSetDenseJacFn(arkode_mem, Jac);     /* Set the Jacobian routine */
-  if (check_flag(&flag, "ARKDlsSetDenseJacFn", 1)) return 1;
+  /* Initialize dense matrix data structure and solver */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)A, "SUNDenseMatrix", 0)) return 1;
+  LS = SUNDenseLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return 1;
+
+  /* Linear solver interface */
+  flag = ARKDlsSetLinearSolver(arkode_mem, LS, A);        /* Attach matrix and linear solver */
+  if (check_flag(&flag, "ARKDlsSetLinearSolver", 1)) return 1;
+  flag = ARKDlsSetJacFn(arkode_mem, Jac);                 /* Set the Jacobian routine */
+  if (check_flag(&flag, "ARKDlsSetJacFn", 1)) return 1;
 
   /* Open output stream for results, output comment line */
   UFID = fopen("solution.txt","w");
   fprintf(UFID,"# t u v w\n");
 
   /* output initial condition to disk */
-  fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+  fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	  T0, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
 
   /* Main time-stepping loop: calls ARKode to perform the integration, then
@@ -152,7 +169,7 @@ int main()
   t = T0;
   printf("        t             u             v             w\n");
   printf("   -----------------------------------------------------\n");
-  printf("  %12.5e  %12.5e  %12.5e  %12.5e\n",
+  printf("  %12.5"ESYM"  %12.5"ESYM"  %12.5"ESYM"  %12.5"ESYM"\n",
       t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));
   tout = T1;
   iout = 0;
@@ -160,9 +177,9 @@ int main()
 
     flag = ARKode(arkode_mem, tout, y, &t, ARK_NORMAL);     /* call integrator */
     if (check_flag(&flag, "ARKode", 1)) break;
-    printf("  %12.5e  %12.5e  %12.5e  %12.5e\n",  t,        /* access/print solution */
+    printf("  %12.5"ESYM"  %12.5"ESYM"  %12.5"ESYM"  %12.5"ESYM"\n",  t,        /* access/print solution */
         NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));
-    fprintf(UFID," %.16e %.16e %.16e %.16e\n", 
+    fprintf(UFID," %.16"ESYM" %.16"ESYM" %.16"ESYM" %.16"ESYM"\n", 
 	    t, NV_Ith_S(y,0), NV_Ith_S(y,1), NV_Ith_S(y,2));  
     if (flag == ARK_ROOT_RETURN) {                          /* check if a root was found */
       rtflag = ARKodeGetRootInfo(arkode_mem, rootsfound);
@@ -217,8 +234,10 @@ int main()
   printf("   Total number of error test failures = %li\n", netf);
 
   /* Clean up and return with successful completion */
-  N_VDestroy_Serial(y);        /* Free y vector */
+  N_VDestroy(y);               /* Free y vector */
   ARKodeFree(&arkode_mem);     /* Free integrator memory */
+  SUNLinSolFree(LS);           /* Free linear solver */
+  SUNMatDestroy(A);            /* Free A matrix */
   return 0;
 }
 
@@ -242,24 +261,23 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 }
 
 /* Jacobian routine to compute J(t,y) = df/dy. */
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype v = NV_Ith_S(y,1);    /* access current solution */
   realtype w = NV_Ith_S(y,2);
-  SetToZero(J);                  /* initialize Jacobian to zero */
+  SUNMatZero(J);                 /* initialize Jacobian to zero */
 
   /* Fill in the Jacobian of the ODE RHS function */
-  DENSE_ELEM(J,0,0) = -0.04;
-  DENSE_ELEM(J,0,1) = 1.e4*w;
-  DENSE_ELEM(J,0,2) = 1.e4*v;
+  SM_ELEMENT_D(J,0,0) = -0.04;
+  SM_ELEMENT_D(J,0,1) = 1.e4*w;
+  SM_ELEMENT_D(J,0,2) = 1.e4*v;
 
-  DENSE_ELEM(J,1,0) = 0.04;
-  DENSE_ELEM(J,1,1) = -1.e4*w - 6.e7*v;
-  DENSE_ELEM(J,1,2) = -1.e4*v;
+  SM_ELEMENT_D(J,1,0) = 0.04;
+  SM_ELEMENT_D(J,1,1) = -1.e4*w - 6.e7*v;
+  SM_ELEMENT_D(J,1,2) = -1.e4*v;
 
-  DENSE_ELEM(J,2,1) = 6.e7*v;
+  SM_ELEMENT_D(J,2,1) = 6.e7*v;
 
   return 0;                      /* Return with success */
 }
diff --git a/examples/arkode/F77_parallel/CMakeLists.txt b/examples/arkode/F77_parallel/CMakeLists.txt
index 5454a4f..80c45ab 100644
--- a/examples/arkode/F77_parallel/CMakeLists.txt
+++ b/examples/arkode/F77_parallel/CMakeLists.txt
@@ -2,13 +2,13 @@
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,19 +17,20 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for the FARKODE parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable FARKODE_examples with the names of the parallel ARKODE examples
-
+# Examples using SUNDIALS linear solvers
 SET(FARKODE_examples
-  "fark_diag_non_p\;1\;4"
-  "fark_diag_kry_bbd_p\;1\;4"
+  "fark_diag_non_p\;1\;4\;develop"
+  "fark_diag_kry_bbd_p\;1\;4\;develop"
   )
 
-# Add variable ARKODE_extras with the names of auxiliary files to install
-
+# Auxiliary files to install
 SET(ARKODE_extras
   )
 
@@ -37,65 +38,70 @@ SET(ARKODE_extras
 # If yes, then change the Fortran compiler to the MPIF77 script.
 # If not, then add the MPI include directory for MPI headers.
 
-IF(MPI_MPIF77 )
+IF(MPI_MPIF77)
   # use MPI_MPIF77 as the compiler
   SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
-ELSE(MPI_MPIF77)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPIF77)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
   SET(FNVECP_LIB sundials_fnvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
   SET(FNVECP_LIB sundials_fnvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FARKODE_LIB sundials_farkode_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FARKODE_LIB} ${ARKODE_LIB} ${FNVECP_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # Add the build and install targets for each ARKODE example
-
 FOREACH(example_tuple ${FARKODE_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPIF77)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPIF77)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${FARKODE_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -104,36 +110,34 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${ARKODE_extras})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_parallel)
-  ENDFOREACH(extrafile ${ARKODE_extras})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
   SET(SOLVER_FLIB "sundials_farkode")
-  FOREACH(example_tuple ${FARKODE_examples})
-    list(GET example_tuple 0 example)
-    LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${FARKODE_examples})
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(FARKODE_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/F77_parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/F77_parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/F77_parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -146,7 +150,7 @@ IF(EXAMPLES_INSTALL)
     # install the configured Makefile_ex as Makefile
     INSTALL(
       FILES ${PROJECT_BINARY_DIR}/examples/arkode/F77_parallel/Makefile_ex
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_parallel 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_parallel
       RENAME Makefile
       )
   ENDIF(UNIX)
diff --git a/examples/arkode/F77_parallel/README b/examples/arkode/F77_parallel/README
index cfea683..4199c98 100644
--- a/examples/arkode/F77_parallel/README
+++ b/examples/arkode/F77_parallel/README
@@ -8,7 +8,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.f b/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.f
index 24c7a26..0d3d85e 100644
--- a/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.f
+++ b/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.f
@@ -21,6 +21,9 @@ C     ----------------------------------------------------------------
 C     Diagonal ODE example.  Stiff case, with diagonal preconditioner.
 C     Uses FARKODE interfaces and FARKBBD interfaces.
 C     Solves problem twice -- with left and right preconditioning.
+C
+C     Note that this problem should only work with SUNDIALS configured
+C     to use 'realtype' as 'double' and 'sunindextype' as '64bit'
 C     ----------------------------------------------------------------
 C     
 C     Include MPI-Fortran header file for MPI_COMM_WORLD, MPI types.
@@ -113,6 +116,23 @@ C
          CALL MPI_FINALIZE(IER)
          STOP
       ENDIF
+C
+C     initialize SPGMR linear solver module
+      call FSUNSPGMRINIT(4, IPRE, 0, IER)
+      IF (IER .NE. 0) THEN
+         WRITE(6,25) IER
+ 25      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRINIT IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
+C
+      call FSUNSPGMRSETGSTYPE(4, IGS, IER)
+      IF (IER .NE. 0) THEN
+         WRITE(6,27) IER
+ 27      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETGSTYPE IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C     
       CALL FARKMALLOC(T, Y, METH, IATOL, RTOL, ATOL,
      &                IOUT, ROUT, IPAR, RPAR, IER)
@@ -124,14 +144,16 @@ C
          STOP
       ENDIF
 C
-      CALL FARKSPGMR(IPRE, IGS, 0, 0.0D0, IER)
+C     attach linear solver module to ARKSpils interface
+      CALL FARKSPILSINIT(IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,36) IER
- 36      FORMAT(///' SUNDIALS_ERROR: FARKSPGMR returned IER = ', I5)
+         WRITE(6,32) IER
+ 32      FORMAT(///' SUNDIALS_ERROR: FARKSPILSINIT returned IER = ', I5)
          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
          STOP
       ENDIF
-C     
+C
+C     initialize BBD preconditioner (build diagonal preconditioner)
       MUDQ = 0
       MLDQ = 0
       MU = 0
@@ -255,7 +277,7 @@ C
 C
       IPRE = 2
 C
-      CALL FARKBBDREINIT(NLOCAL, MUDQ, MLDQ, 0.0D0, IER) 
+      CALL FARKBBDREINIT(MUDQ, MLDQ, 0.0D0, IER) 
       IF (IER .NE. 0) THEN
          WRITE(6,92) IER
  92      FORMAT(///' SUNDIALS_ERROR: FARKBBDREINIT returned IER = ', I5)
@@ -263,10 +285,10 @@ C
          STOP
       ENDIF
 C
-      CALL FARKSPGMRREINIT(IPRE, IGS, 0.0D0, IER)
+      CALL FSUNSPGMRSETPRECTYPE(4, IPRE, IER)
       IF (IER .NE. 0) THEN
          WRITE(6,93) IER
- 93      FORMAT(///' SUNDIALS_ERROR: FARKSPGMRREINIT returned IER =',I5)
+ 93      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETPRECTYPE IER =',I5)
          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
          STOP
       ENDIF
diff --git a/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.out b/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.out
index 6b777a1..bd90106 100644
--- a/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.out
+++ b/examples/arkode/F77_parallel/fark_diag_kry_bbd_p.out
@@ -41,9 +41,9 @@ Final statistics:
  number of conv. failures.. nonlinear =   0  linear =   0
  number of error test failures =   0
  main solver real/int workspace sizes   =   658  160
- linear solver real/int workspace sizes =   446   80
+ linear solver real/int workspace sizes =   530  106
 In ARKBBDPRE:
- real/int local workspace =    20   10
+ real/int local workspace =   160   72
  number of g evals. =    12
 
 
@@ -81,7 +81,7 @@ Final statistics:
  number of conv. failures.. nonlinear =   0  linear =   0
  number of error test failures =   0
  main solver real/int workspace sizes   =   658  160
- linear solver real/int workspace sizes =   446   80
+ linear solver real/int workspace sizes =   530  106
 In ARKBBDPRE:
- real/int local workspace =    20   10
+ real/int local workspace =   160   72
  number of g evals. =    12
diff --git a/examples/arkode/F77_parallel/fark_diag_non_p.f b/examples/arkode/F77_parallel/fark_diag_non_p.f
index ee37235..70cf8e2 100644
--- a/examples/arkode/F77_parallel/fark_diag_non_p.f
+++ b/examples/arkode/F77_parallel/fark_diag_non_p.f
@@ -44,24 +44,24 @@ C
 C     Get NPES and MYPE.  Requires initialization of MPI.
       CALL MPI_INIT(IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,5) IER
- 5      FORMAT(///' MPI_ERROR: MPI_INIT returned IER = ', I5)
-        STOP
-        ENDIF
+         WRITE(6,5) IER
+ 5       FORMAT(///' MPI_ERROR: MPI_INIT returned IER = ', I5)
+         STOP
+      ENDIF
       CALL MPI_COMM_SIZE(MPI_COMM_WORLD, NPES, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,6) IER
- 6      FORMAT(///' MPI_ERROR: MPI_COMM_SIZE returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,6) IER
+ 6       FORMAT(///' MPI_ERROR: MPI_COMM_SIZE returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
       CALL MPI_COMM_RANK(MPI_COMM_WORLD, MYPE, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,7) IER
- 7      FORMAT(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,7) IER
+ 7       FORMAT(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C
 C     Set input arguments.
       NEQ = NPES * NLOCAL
@@ -81,38 +81,38 @@ C
   10    Y(I) = 1.0D0
 C
       IF (MYPE .EQ. 0) THEN
-        WRITE(6,11) NEQ, NLOCAL, ALPHA
-  11    FORMAT('Diagonal test problem:'//' NEQ = ', I3, /
-     1       ' NLOCAL = ', I3, /
-     2       ' parameter alpha = ', F8.3)
-        WRITE(6,12)
-  12    FORMAT(' ydot_i = -alpha*i * y_i (i = 1,...,NEQ)')
-        WRITE(6,13) RTOL, ATOL
-  13    FORMAT(' RTOL, ATOL = ', 2E10.1)
-        WRITE(6,14)
-  14    FORMAT(' Method is ERK')
-        WRITE(6,15) NPES
-  15    FORMAT(' Number of processors = ', I3//)
-        ENDIF
+         WRITE(6,11) NEQ, NLOCAL, ALPHA
+  11     FORMAT('Diagonal test problem:'//' NEQ = ', I3, /
+     1        ' NLOCAL = ', I3, /
+     2        ' parameter alpha = ', F8.3)
+         WRITE(6,12)
+  12     FORMAT(' ydot_i = -alpha*i * y_i (i = 1,...,NEQ)')
+         WRITE(6,13) RTOL, ATOL
+  13     FORMAT(' RTOL, ATOL = ', 2E10.1)
+         WRITE(6,14)
+  14     FORMAT(' Method is ERK')
+         WRITE(6,15) NPES
+  15     FORMAT(' Number of processors = ', I3//)
+      ENDIF
 C
       CALL FNVINITP(MPI_COMM_WORLD, 4, NLOCAL, NEQ, IER)
 C
       IF (IER .NE. 0) THEN
-        WRITE(6,20) IER
-  20    FORMAT(///' SUNDIALS_ERROR: FNVINITP returned IER = ', I5)
-        CALL MPI_FINALIZE(IER)
-        STOP
-        ENDIF
+         WRITE(6,20) IER
+  20     FORMAT(///' SUNDIALS_ERROR: FNVINITP returned IER = ', I5)
+         CALL MPI_FINALIZE(IER)
+         STOP
+      ENDIF
 C
       CALL FARKMALLOC(T, Y, METH, IATOL, RTOL, ATOL,
-     1               IOUT, ROUT, IPAR, RPAR, IER)
+     1                IOUT, ROUT, IPAR, RPAR, IER)
 C
       IF (IER .NE. 0) THEN
-        WRITE(6,30) IER
-  30    FORMAT(///' SUNDIALS_ERROR: FARKMALLOC returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,30) IER
+  30     FORMAT(///' SUNDIALS_ERROR: FARKMALLOC returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C
 C     Loop through tout values, call solver, print output, test for failure.
       TOUT = DTOUT
@@ -122,17 +122,17 @@ C
 C
         IF (MYPE .EQ. 0) WRITE(6,40) T, IOUT(LNST), IOUT(LNST_ATT), 
      &       IOUT(LNFE), IOUT(LNFI)
-  40    FORMAT(' t = ', D10.2, 5X, 'steps = ', I5, 
+  40    FORMAT(' t = ', D10.2, 5X, 'steps = ', I5,
      &         '  (attempted = ', I5, '),  fe = ', I5, 
      &         '  fi = ', I5)
 C
         IF (IER .NE. 0) THEN
-          WRITE(6,60) IER, IOUT(16)
-  60      FORMAT(///' SUNDIALS_ERROR: FARKODE returned IER = ', I5, /,
-     &           '                 Linear Solver returned IER = ', I5)
-          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-          STOP
-          ENDIF
+           WRITE(6,60) IER, IOUT(16)
+  60       FORMAT(///' SUNDIALS_ERROR: FARKODE returned IER = ', I5, /,
+     &            '                 Linear Solver returned IER = ', I5)
+           CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+           STOP
+        ENDIF
 C
         TOUT = TOUT + DTOUT
   70    CONTINUE
@@ -147,11 +147,11 @@ C     Get global max. error from MPI_REDUCE call.
       CALL MPI_REDUCE(ERMAX, GERMAX, 1, MPI_DOUBLE_PRECISION, MPI_MAX,
      1                0, MPI_COMM_WORLD, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,80) IER
-  80    FORMAT(///' MPI_ERROR: MPI_REDUCE returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,80) IER
+  80     FORMAT(///' MPI_ERROR: MPI_REDUCE returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
       IF (MYPE .EQ. 0) WRITE(6,85) GERMAX
   85  FORMAT(/'Max. absolute error is ', E10.2/)
 C
@@ -178,10 +178,10 @@ C     Free the memory and finalize MPI.
       CALL FARKFREE
       CALL MPI_FINALIZE(IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,95) IER
- 95     FORMAT(///' MPI_ERROR: MPI_FINALIZE returned IER = ', I5)
-        STOP
-        ENDIF
+         WRITE(6,95) IER
+ 95      FORMAT(///' MPI_ERROR: MPI_FINALIZE returned IER = ', I5)
+         STOP
+      ENDIF
 C
       STOP
       END
diff --git a/examples/arkode/F77_serial/CMakeLists.txt b/examples/arkode/F77_serial/CMakeLists.txt
index 7a9c40e..1f002ef 100644
--- a/examples/arkode/F77_serial/CMakeLists.txt
+++ b/examples/arkode/F77_serial/CMakeLists.txt
@@ -1,14 +1,15 @@
 # ---------------------------------------------------------------
-# Programmer:  Daniel R. Reynolds @ SMU
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,86 +18,249 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for the FARKODE F77 serial examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
-# Add variable FARKODE_examples with the names of the serial FARKODE examples
-
+# Examples using SUNDIALS linear solvers
 SET(FARKODE_examples
-  fark_diurnal_kry_bp
+  "fark_diurnal_kry_bp\;develop"
   )
 
-# Add variable FARKODE_bl_examples with the names of the serial FARKODE examples
-# that use Lapack
-
+# Examples using LAPACK linear solvers
 SET(FARKODE_examples_BL
-  fark_roberts_dnsL
+  "fark_roberts_dnsL\;develop"
   )
 
-# Add variable ARKODE_extras with the names of auxiliary files to install
+# Add sparse solvers examples for 64-bit indextype configurations only,
+# not compatible with 32-bit indextype
+IF(SUNDIALS_INDEX_TYPE MATCHES "INT64_T")
+
+  # Examples using KLU linear solver
+  SET(FARKODE_examples_KLU
+    )
 
+  # Examples using SuperLU_MT linear solver
+  SET(FARKODE_examples_SUPERLUMT
+    )
+
+ENDIF()
+
+# Auxiliary files to install
 SET(ARKODE_extras
   )
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECS_LIB sundials_nvecserial_static)
   SET(FNVECS_LIB sundials_fnvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
   SET(FNVECS_LIB sundials_fnvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FARKODE_LIB sundials_farkode_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FARKODE_LIB} ${ARKODE_LIB} ${FNVECS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # Add the build and install targets for each FARKODE example
+FOREACH(example_tuple ${FARKODE_examples})
 
-FOREACH(example ${FARKODE_examples})
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+   # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${FARKODE_examples})
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial)
+  ENDIF()
 
-# Add the build and install targets for each Lapack FARKODE example (if needed)
+ENDFOREACH(example_tuple ${FARKODE_examples})
 
+
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${FARKODE_examples_BL})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static
+      sundials_fsunlinsollapackband_static
+      sundials_fsunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared
+      sundials_fsunlinsollapackband_shared
+      sundials_fsunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${FARKODE_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.f)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+     # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FARKODE_examples_BL})
+      INSTALL(FILES ${example}.f ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FARKODE_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
+
+# Add the build and install targets for each KLU example (if needed)
+IF(KLU_FOUND)
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS
+      sundials_sunlinsolklu_static
+      sundials_fsunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS
+      sundials_sunlinsolklu_shared
+      sundials_fsunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${FARKODE_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+     # install example source and out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.f ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FARKODE_examples_KLU})
+
+ENDIF(KLU_FOUND)
+
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
+IF(SUPERLUMT_FOUND)
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS
+      sundials_sunlinsolsuperlumt_static
+      sundials_fsunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS
+      sundials_sunlinsolsuperlumt_shared
+      sundials_fsunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${FARKODE_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+     # install example source and out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.f ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FARKODE_examples_SUPERLUMT})
+
+ENDIF(SUPERLUMT_FOUND)
+
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -105,38 +269,52 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${ARKODE_extras})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial)
-  ENDFOREACH(extrafile ${ARKODE_extras})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
   SET(SOLVER_FLIB "sundials_farkode")
-  LIST2STRING(FARKODE_examples EXAMPLES)
+
+  EXAMPLES2STRING(FARKODE_examples EXAMPLES)
+
   IF(LAPACK_FOUND)
-    LIST2STRING(FARKODE_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(FARKODE_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  IF(KLU_FOUND)
+    EXAMPLES2STRING(FARKODE_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
+
+  IF(SUPERLUMT_FOUND)
+    EXAMPLES2STRING(FARKODE_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/F77_serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/F77_serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/F77_serial/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -148,8 +326,8 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/arkode/F77_serial/Makefile_ex 
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial 
+      FILES ${PROJECT_BINARY_DIR}/examples/arkode/F77_serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F77_serial
       RENAME Makefile
       )
   ENDIF(UNIX)
diff --git a/examples/arkode/F77_serial/README b/examples/arkode/F77_serial/README
index c728e89..d7c3b56 100644
--- a/examples/arkode/F77_serial/README
+++ b/examples/arkode/F77_serial/README
@@ -8,7 +8,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/F77_serial/fark_diurnal_kry_bp.f b/examples/arkode/F77_serial/fark_diurnal_kry_bp.f
index 62dda2c..3bd0f1e 100644
--- a/examples/arkode/F77_serial/fark_diurnal_kry_bp.f
+++ b/examples/arkode/F77_serial/fark_diurnal_kry_bp.f
@@ -40,7 +40,10 @@ C
 C     The PDE system is treated by central differences on a uniform
 C     10 x 10 mesh, with simple polynomial initial profiles.
 C     The problem is solved with ARKODE, with the DIRK/GMRES method and
-C     using the FARKBP banded preconditioner
+C     using the FARKBP banded preconditioner.
+C
+C     Note that this problem should only work with SUNDIALS configured
+C     to use 'realtype' as 'double' and 'sunindextype' as '64bit'
 C     
 C     The second and third dimensions of U here must match the values of
 C     MX and MY, for consistency with the output statements below.
@@ -90,6 +93,20 @@ C     Initialize vector specification
  20      FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
          STOP
       ENDIF
+C
+C     initialize SPGMR linear solver module
+      call FSUNSPGMRINIT(4, JPRETYPE, MAXL, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRINIT IER = ', I5)
+        STOP
+      ENDIF
+      call FSUNSPGMRSETGSTYPE(4, IGSTYPE, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,27) IER
+ 27     FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETGSTYPE IER = ', I5)
+        STOP
+      ENDIF
 C     
 C     Initialize ARKODE
       CALL FARKMALLOC(T, U, METH, IATOL, RTOL, ATOL,
@@ -106,14 +123,14 @@ C
  35     FORMAT(///' SUNDIALS_ERROR: FARKSETIIN returned IER = ', I5)
         STOP
       ENDIF
-C     
-C     Initialize SPGMR solver
-      CALL FARKSPGMR(JPRETYPE, IGSTYPE, MAXL, DELT, IER) 
+C
+C     attach matrix and linear solver modules to ARKSpils interface
+      CALL FARKSPILSINIT(IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,45) IER
- 45      FORMAT(///' SUNDIALS_ERROR: FARKSPGMR returned IER = ', I5)
-         CALL FARKFREE
-         STOP
+        WRITE(6,40) IER
+ 40     FORMAT(///' SUNDIALS_ERROR: FARKSPILSINIT returned IER = ',I5)
+        CALL FARKFREE
+        STOP
       ENDIF
 C     
 C     Initialize band preconditioner
@@ -121,8 +138,8 @@ C     Initialize band preconditioner
       ML = 2
       CALL FARKBPINIT(NEQ, MU, ML, IER) 
       IF (IER .NE. 0) THEN
-         WRITE(6,40) IER
- 40      FORMAT(///' SUNDIALS_ERROR: FARKBPINIT returned IER = ', I5)
+         WRITE(6,45) IER
+ 45      FORMAT(///' SUNDIALS_ERROR: FARKBPINIT returned IER = ', I5)
          CALL FARKFREE
          STOP
       ENDIF
diff --git a/examples/arkode/F77_serial/fark_diurnal_kry_bp.out b/examples/arkode/F77_serial/fark_diurnal_kry_bp.out
index 0d8370b..fb35eff 100644
--- a/examples/arkode/F77_serial/fark_diurnal_kry_bp.out
+++ b/examples/arkode/F77_serial/fark_diurnal_kry_bp.out
@@ -67,7 +67,7 @@ Final statistics:
  number of conv. failures.. nonlinear =  0 linear =   0
  number of error test failures =  24
  main solver real/int workspace sizes   =  3058   55
- linear solver real/int workspace sizes =  2046   10
+ linear solver real/int workspace sizes =  2450   22
 In ARKBANDPRE:
- real/int workspace sizes =  2400  200
+ real/int workspace sizes =  2800  622
  number of f evaluations  =   600
diff --git a/examples/arkode/F77_serial/fark_roberts_dnsL.f b/examples/arkode/F77_serial/fark_roberts_dnsL.f
index 5397a9f..71b4315 100644
--- a/examples/arkode/F77_serial/fark_roberts_dnsL.f
+++ b/examples/arkode/F77_serial/fark_roberts_dnsL.f
@@ -14,9 +14,6 @@ C
 C     All rights reserved.
 C     For details, see the LICENSE file.
 C     LLNS/SMU Copyright End
-C     Copyright (c) 2013, Southern Methodist University.
-C     All rights reserved.
-C     For details, see the LICENSE file.
 C     ----------------------------------------------------------------
 C     FARKODE Example Problem: Robertson kinetics, Lapack linear solver
 C                             with dense user Jacobian.
@@ -43,6 +40,9 @@ C     Jacobian routine, and prints results at t = .4, 4., ..., 4.e10.
 C     It uses ITOL = 2 and ATOL much smaller for y2 than y1 or y3
 C     because y2 has much smaller values. At the end of the run,
 C     various counters of interest are printed.
+C
+C     Note that this problem should only work with SUNDIALS configured
+C     to use 'realtype' as 'double' and 'sunindextype' as '32bit'
 C     ----------------------------------------------------------------
 C
       IMPLICIT NONE
@@ -50,7 +50,8 @@ C
       INTEGER*4 IER, LNST, LNST_ATT, LNFE, LNFI, LNSETUP, LNNI, LNCF
       INTEGER*4 LNETF, LNJE, LNGE, METH, ITOL, ITASK, JOUT, NOUT
       INTEGER*4 IERROOT, INFO(2)
-      INTEGER*8 I, IOUT(22), IPAR, NEQ, MXSTEPS, MXNLI, PRED, MXETF
+      INTEGER*4 I, NEQ
+      INTEGER*8 IOUT(22), IPAR, MXSTEPS, MXNLI, PRED, MXETF
       DOUBLE PRECISION RTOL, T, T0, TOUT, H0, NLCONV
       DOUBLE PRECISION Y(3), ATOL(3), ROUT(6), RPAR
 C
@@ -90,7 +91,22 @@ C
         STOP
       ENDIF
 C
-
+C     initialize dense matrix module
+      call FSUNDENSEMATINIT(4, NEQ, NEQ, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNDENSEMATINIT IER = ', I5)
+        STOP
+      ENDIF
+C
+C     initialize LAPACK dense linear solver module
+      call FSUNLAPACKDENSEINIT(4, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,28) IER
+ 28     FORMAT(///' SUNDIALS_ERROR: FSUNLAPACKDENSEINIT IER = ', I5)
+        STOP
+      ENDIF
+C
       CALL FARKMALLOC(T0, Y, METH, ITOL, RTOL, ATOL,
      1                IOUT, ROUT, IPAR, RPAR, IER)
       IF (IER .NE. 0) THEN
@@ -139,21 +155,28 @@ C
 c
       CALL FARKROOTINIT(2, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,45) IER
- 45      FORMAT(///' SUNDIALS_ERROR: FARKROOTINIT returned IER = ', I5)
+         WRITE(6,38) IER
+ 38      FORMAT(///' SUNDIALS_ERROR: FARKROOTINIT returned IER = ', I5)
          CALL FARKFREE
          STOP
       ENDIF
 C
-      CALL FARKLAPACKDENSE(NEQ, IER)
+C     attach matrix and linear solver modules to ARKDls interface
+      CALL FARKDLSINIT(IER)
       IF (IER .NE. 0) THEN
         WRITE(6,40) IER
- 40     FORMAT(///' SUNDIALS_ERROR: FARKLAPACKDENSE returned IER = ',I5)
+ 40     FORMAT(///' SUNDIALS_ERROR: FARKDLSINIT returned IER = ',I5)
         CALL FARKFREE
         STOP
       ENDIF
 C
-      CALL FARKLAPACKDENSESETJAC(1, IER)
+      CALL FARKDENSESETJAC(1, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,45) IER
+ 45     FORMAT(///' SUNDIALS_ERROR: FARKDENSESETJAC returned IER = ',I5)
+        CALL FARKFREE
+        STOP
+      ENDIF
 C
       DO WHILE(JOUT .LT. NOUT)
 C
@@ -227,7 +250,8 @@ C     ----------------------------------------------------------------
 C Fortran routine for right-hand side function, fi
       IMPLICIT NONE
 C
-      INTEGER*4 IPAR(*), IER
+      INTEGER*8 IPAR(*)
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
 C
       YDOT(1) = -0.04D0 * Y(1) + 1.0D4 * Y(2) * Y(3)
@@ -245,7 +269,8 @@ C     ----------------------------------------------------------------
 C Fortran routine for right-hand side function, fe
       IMPLICIT NONE
 C
-      INTEGER*4 IPAR(*), IER
+      INTEGER*8 IPAR(*)
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
 C
       YDOT(1) = 0.D0
@@ -264,7 +289,8 @@ C Fortran routine for root finding
       IMPLICIT NONE
 C
       DOUBLE PRECISION T, Y(*), G(*), RPAR(*)
-      INTEGER*4 IPAR(*), IER
+      INTEGER*8 IPAR(*)
+      INTEGER*4 IER
 C
       G(1) = Y(1) - 1.0D-4
       G(2) = Y(3) - 1.0D-2
@@ -281,8 +307,8 @@ C     ----------------------------------------------------------------
 C Fortran routine for dense user-supplied Jacobian.
       IMPLICIT NONE
 C
-      INTEGER*4 IER
-      INTEGER*8 N, IPAR(*)
+      INTEGER*4 IER, N
+      INTEGER*8 IPAR(*)
       DOUBLE PRECISION T, Y(*), FY(*), JAC(N,*), H, RPAR(*)
       DOUBLE PRECISION V1(*), V2(*), V3(*)
 C
diff --git a/examples/arkode/F90_parallel/CMakeLists.txt b/examples/arkode/F90_parallel/CMakeLists.txt
index fca2903..825843f 100644
--- a/examples/arkode/F90_parallel/CMakeLists.txt
+++ b/examples/arkode/F90_parallel/CMakeLists.txt
@@ -2,13 +2,13 @@
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,18 +17,19 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for the ARKODE parallel F90 examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable FARKODE_examples with the names of the parallel ARKODE examples
-
+# Examples using SUNDIALS linear solvers
 SET(FARKODE_examples
-  "fark_heat2D\;1\;2"
+  "fark_heat2D\;1\;2\;develop"
   )
 
-# Add variable FARKODE_extras with the names of auxiliary files to install
-# "name\;nodes\;tasks"
+# Auxiliary files to install
 SET(FARKODE_extras
   plot_heat2D.py
   )
@@ -39,58 +40,67 @@ SET(FARKODE_extras
 IF(MPI_MPIF90)
   # use MPI_MPIF90 as the compiler
   SET(CMAKE_Fortran_COMPILER ${MPI_MPIF90})
-ELSE(MPI_MPIF90)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPIF90)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
   SET(FNVECP_LIB sundials_fnvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
   SET(FNVECP_LIB sundials_fnvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
 SET(FARKODE_LIB sundials_farkode_static)
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${FARKODE_LIB} ${ARKODE_LIB} ${FNVECP_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # Add the build and install targets for each ARKODE example
 FOREACH(example_tuple ${FARKODE_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f90)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPIF90)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPIF90)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f90 ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.f90 ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${FARKODE_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -99,36 +109,34 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${FARKODE_extras})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_parallel)
-  ENDFOREACH(extrafile ${FARKODE_extras})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
   SET(SOLVER_FLIB "sundials_farkode")
-  FOREACH(example_tuple ${FARKODE_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${FARKODE_examples})
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(FARKODE_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F90_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/F90_parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F90_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/F90_parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/F90_parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -141,7 +149,7 @@ IF(EXAMPLES_INSTALL)
     # install the configured Makefile_ex as Makefile
     INSTALL(
       FILES ${PROJECT_BINARY_DIR}/examples/arkode/F90_parallel/Makefile_ex
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_parallel 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_parallel
       RENAME Makefile
       )
   ENDIF(UNIX)
diff --git a/examples/arkode/F90_parallel/README b/examples/arkode/F90_parallel/README
index 013d9bb..3e94445 100644
--- a/examples/arkode/F90_parallel/README
+++ b/examples/arkode/F90_parallel/README
@@ -13,7 +13,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -24,7 +23,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -38,7 +40,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/F90_parallel/fark_heat2D.f90 b/examples/arkode/F90_parallel/fark_heat2D.f90
index 0daeeed..678a740 100644
--- a/examples/arkode/F90_parallel/fark_heat2D.f90
+++ b/examples/arkode/F90_parallel/fark_heat2D.f90
@@ -66,6 +66,7 @@ module UserData
   !      (c) free module data.
   !---------------------------------------------------------------
   implicit none
+  include "sundials/sundials_fconfig.h"
   save
 
   integer*8 :: nx          ! global number of x grid points 
@@ -80,20 +81,20 @@ module UserData
   real*8    :: dy          ! y-directional mesh spacing 
   real*8    :: kx          ! x-directional diffusion coefficient 
   real*8    :: ky          ! y-directional diffusion coefficient 
-  real*8, dimension(:,:), allocatable :: h    ! heat source vector
-  real*8, dimension(:,:), allocatable :: d    ! inverse of Jacobian diagonal
+  real(kind=REALTYPE), dimension(:,:), allocatable :: h    ! heat source vector
+  real(kind=REALTYPE), dimension(:,:), allocatable :: d    ! inverse of Jacobian diagonal
   integer :: comm                             ! communicator object
   integer :: myid                             ! MPI process ID
   integer :: nprocs                           ! total number of MPI processes
   logical :: HaveBdry(2,2)                    ! flags denoting if on physical boundary
-  real*8, dimension(:), allocatable :: Erecv  ! receive buffers for neighbor exchange
-  real*8, dimension(:), allocatable :: Wrecv
-  real*8, dimension(:), allocatable :: Nrecv
-  real*8, dimension(:), allocatable :: Srecv
-  real*8, dimension(:), allocatable :: Esend  ! send buffers for neighbor exchange
-  real*8, dimension(:), allocatable :: Wsend
-  real*8, dimension(:), allocatable :: Nsend
-  real*8, dimension(:), allocatable :: Ssend
+  real(kind=REALTYPE), dimension(:), allocatable :: Erecv  ! receive buffers for neighbor exchange
+  real(kind=REALTYPE), dimension(:), allocatable :: Wrecv
+  real(kind=REALTYPE), dimension(:), allocatable :: Nrecv
+  real(kind=REALTYPE), dimension(:), allocatable :: Srecv
+  real(kind=REALTYPE), dimension(:), allocatable :: Esend  ! send buffers for neighbor exchange
+  real(kind=REALTYPE), dimension(:), allocatable :: Wsend
+  real(kind=REALTYPE), dimension(:), allocatable :: Nsend
+  real(kind=REALTYPE), dimension(:), allocatable :: Ssend
 
 contains
 
@@ -230,7 +231,7 @@ contains
     ! declarations
     implicit none
     include "mpif.h"
-    real*8,  intent(in)  :: y(nxl,nyl)
+    real(kind=REALTYPE),  intent(in)  :: y(nxl,nyl)
     integer, intent(out) :: ierr
     integer :: reqSW, reqSE, reqSS, reqSN, reqRW, reqRE, reqRS, reqRN;
     integer :: stat(MPI_STATUS_SIZE)
@@ -451,9 +452,9 @@ contains
     implicit none
     include "mpif.h"
     integer, intent(out) :: ierr
-    real*8,  intent(in)  :: y(nxl,nyl)
-    real*8,  intent(out) :: yrms
-    real*8 :: lsum, gsum
+    real(kind=REALTYPE),  intent(in)  :: y(nxl,nyl)
+    real(kind=REALTYPE),  intent(out) :: yrms
+    real(kind=REALTYPE) :: lsum, gsum
 
     ! internals
     lsum = sum(y**2)
@@ -487,24 +488,24 @@ program driver
   ! Declarations
   ! general problem parameters
   real*8,    parameter :: pi = 3.1415926535897932d0
-  real*8,    parameter :: T0 = 0.d0     ! initial time 
-  real*8,    parameter :: Tf = 0.3d0    ! final time 
+  real(kind=REALTYPE),    parameter :: T0 = 0.d0     ! initial time 
+  real(kind=REALTYPE),    parameter :: Tf = 0.3d0    ! final time 
   integer,   parameter :: Nt = 20       ! total number of output times 
-  real*8,    parameter :: rtol = 1.d-5  ! relative and absolute tolerances
-  real*8,    parameter :: atol = 1.d-10
+  real(kind=REALTYPE),    parameter :: rtol = 1.d-5  ! relative and absolute tolerances
+  real(kind=REALTYPE),    parameter :: atol = 1.d-10
   integer*8, parameter :: nx_ = 60      ! spatial mesh size
   integer*8, parameter :: ny_ = 120
-  real*8,    parameter :: kx_ = 0.5d0   ! heat conductivity coefficients
-  real*8,    parameter :: ky_ = 0.75d0
-  real*8,    parameter :: nlscoef = 1.d-7   ! nonlinear solver tolerance factor
+  real(kind=REALTYPE),    parameter :: kx_ = 0.5d0   ! heat conductivity coefficients
+  real(kind=REALTYPE),    parameter :: ky_ = 0.75d0
+  real(kind=REALTYPE),    parameter :: nlscoef = 1.d-7   ! nonlinear solver tolerance factor
   integer,   parameter :: PCGpretype = 1    ! enable preconditioner
   integer,   parameter :: PCGmaxl = 20      ! max num. PCG iterations
-  real*8,    parameter :: PCGdelt = 0.d0    ! use default solver tolerance factor
 
   ! solution vector and other local variables
-  real*8, allocatable :: y(:,:)
-  real*8    :: rout(6), rpar, t, dTout, tout, urms
-  integer*8 :: N, Ntot, i, j, iout(22), ipar
+  real(kind=REALTYPE), allocatable :: y(:,:)
+  real(kind=REALTYPE)    :: rout(6), rpar, t, dTout, tout, urms
+  integer(kind=SUNINDEXTYPE) :: N, Ntot, i, j
+  integer*8 :: iout(22), ipar
   integer   :: flag, ioutput
   logical   :: outproc
   character*100 :: outname
@@ -565,6 +566,13 @@ program driver
   allocate(y(nxl,nyl))         ! Create parallel vector for solution 
   y = 0.d0                     ! Set initial conditions 
 
+  ! initialize PCG linear solver module
+  call FSunPCGInit(4, PCGpretype, PCGmaxl, flag)
+  if (flag /= MPI_SUCCESS) then
+     write(0,*) "Error in FSunPCGInit = ", flag
+     call MPI_Finalize(flag)
+  end if
+  
   ! Create the solver memory to use DIRK integrator, scalar tolerances
   call FARKMalloc(T0, y, 0, 1, rtol, atol, iout, rout, ipar, rpar, flag)
   if (flag /= MPI_SUCCESS) then
@@ -592,13 +600,13 @@ program driver
   end if
 
 
-  ! Linear solver specification 
-  call FARKPCG(PCGpretype, PCGmaxl, PCGdelt, flag)  ! Specify the PCG solver 
+  ! attach linear solver module to ARKSpils interface
+  call FARKSpilsInit(flag)
   if (flag < 0) then
-     write(0,*) "Error in FARKPCG = ", flag
+     write(0,*) "Error in FARKSpilsInit = ", flag
      call MPI_Finalize(flag)
   end if
-  call FARKSpilsSetPrec(1, flag)                     ! Enable preconditioning
+  call FARKSpilsSetPrec(1, flag)     ! Signal user-supplied preconditioner
   if (flag < 0) then
      write(0,*) "Error in FARKSpilsSetPrec = ", flag
      call MPI_Finalize(flag)
@@ -720,12 +728,12 @@ subroutine farkifun(t, y, ydot, ipar, rpar, ierr)
   use UserData
   implicit none
   include "mpif.h"
-  real*8,  intent(in)  :: t, rpar
-  integer, intent(in)  :: ipar
+  real(kind=REALTYPE), intent(in)  :: t, rpar
+  real(kind=REALTYPE), intent(in)  :: y(nxl,nyl)
+  real(kind=REALTYPE), intent(out) :: ydot(nxl,nyl)
+  integer*8, intent(in) :: ipar
+  real(kind=REALTYPE) :: c1, c2, c3
   integer, intent(out) :: ierr
-  real*8,  intent(in)  :: y(nxl,nyl)
-  real*8,  intent(out) :: ydot(nxl,nyl)
-  real*8    :: c1, c2, c3
   integer*8 :: i, j
   
   ! internals
@@ -811,11 +819,11 @@ subroutine farkefun(t, y, ydot, ipar, rpar, ierr)
   ! declarations
   use UserData
   implicit none
-  real*8,  intent(in)  :: t, rpar
-  integer, intent(in)  :: ipar
+  real(kind=REALTYPE), intent(in)  :: t, rpar
+  integer*8, intent(in) :: ipar
+  real(kind=REALTYPE), intent(in)  :: y(nxl,nyl)
+  real(kind=REALTYPE), intent(out) :: ydot(nxl,nyl)
   integer, intent(out) :: ierr
-  real*8,  intent(in)  :: y(nxl,nyl)
-  real*8,  intent(out) :: ydot(nxl,nyl)
   
   ! internals
 
@@ -828,19 +836,19 @@ end subroutine farkefun
 
 
 subroutine farkpset(t, y, fy, jok, jcur, gamma, hcur, ipar, &
-                    rpar, v1, v2, v3, ierr)
+                    rpar, ierr)
 !-----------------------------------------------------------------
 ! Preconditioner setup routine (fills inverse of Jacobian diagonal)
 !-----------------------------------------------------------------
   ! declarations
   use UserData
   implicit none
-  real*8,  intent(in)  :: t, gamma, hcur, rpar
-  integer, intent(in)  :: ipar, jok
+  real(kind=REALTYPE), intent(in) :: t, gamma, hcur, rpar
+  real(kind=REALTYPE), intent(in) :: y(nxl,nyl), fy(nxl,nyl)
+  integer*8, intent(in) :: ipar
+  integer, intent(in) :: jok
   integer, intent(out) :: jcur, ierr
-  real*8,  intent(in)  :: y(nxl,nyl), fy(nxl,nyl)
-  real*8               :: v1(nxl,nyl), v2(nxl,nyl), v3(nxl,nyl)
-  real*8 :: c
+  real(kind=REALTYPE) :: c
 
   ! internals
   c = 1.d0 + gamma*2.d0*(kx/dx/dx + ky/dy/dy)
@@ -856,19 +864,19 @@ end subroutine farkpset
 
 
 subroutine farkpsol(t, y, fy, r, z, gamma, delta, lr, &
-                    ipar, rpar, vt, ierr)
+                    ipar, rpar, ierr)
 !-----------------------------------------------------------------
 ! Preconditioner solve routine
 !-----------------------------------------------------------------
   ! declarations
   use UserData
   implicit none
-  real*8,  intent(in)  :: t, gamma, delta, rpar
-  integer, intent(in)  :: lr, ipar
+  real(kind=REALTYPE), intent(in)  :: t, gamma, delta, rpar
+  integer*8, intent(in) :: ipar
+  real(kind=REALTYPE), intent(in)  :: y(nxl,nyl), fy(nxl,nyl), r(nxl,nyl)
+  real(kind=REALTYPE), intent(out) :: z(nxl,nyl)
+  integer, intent(in)  :: lr
   integer, intent(out) :: ierr
-  real*8,  intent(in)  :: y(nxl,nyl), fy(nxl,nyl), r(nxl,nyl)
-  real*8,  intent(out) :: z(nxl,nyl)
-  real*8               :: vt(nxl,nyl)
 
   ! internals
   z = r*d      ! perform Jacobi iteration (whole array operation)
diff --git a/examples/arkode/F90_parallel/fark_heat2D.out b/examples/arkode/F90_parallel/fark_heat2D.out
index 3160697..66a8223 100644
--- a/examples/arkode/F90_parallel/fark_heat2D.out
+++ b/examples/arkode/F90_parallel/fark_heat2D.out
@@ -36,14 +36,14 @@
     ----------------------
    
  Final Solver Statistics:
-   Internal solver steps =     58 (attempted =     60)
-   Total RHS evals:  Fe =      0,  Fi =    604
+   Internal solver steps =     57 (attempted =     59)
+   Total RHS evals:  Fe =      0,  Fi =    594
    Total linear solver setups =     20
-   Total linear iterations =   4963
-   Total number of Jacobian-vector products =   4963
+   Total linear iterations =   5177
+   Total number of Jacobian-vector products =   5177
    Total number of Preconditioner setups =     20
-   Total number of Preconditioner solves =   5142
-   Total number of linear solver convergence failures =    179
-   Total number of Newton iterations =    300
+   Total number of Preconditioner solves =   5424
+   Total number of linear solver convergence failures =    247
+   Total number of Newton iterations =    295
    Total number of nonlinear solver convergence failures =      0
    Total number of error test failures =      2
diff --git a/examples/arkode/F90_serial/CMakeLists.txt b/examples/arkode/F90_serial/CMakeLists.txt
index 62e01db..5e79fa6 100644
--- a/examples/arkode/F90_serial/CMakeLists.txt
+++ b/examples/arkode/F90_serial/CMakeLists.txt
@@ -1,14 +1,15 @@
 # ---------------------------------------------------------------
-# Programmer:  Daniel R. Reynolds
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,108 +18,251 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
-# CMakeLists.txt file for the FARKODE serial examples
-
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the FARKODE F90 serial examples
+# ---------------------------------------------------------------
 
-# Add variable FARKODE_examples with the names of the serial FARKODE examples
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS linear solvers
 SET(FARKODE_examples
-  ark_bruss
+  "ark_bruss\;develop"
   )
 
-# Add variable FARKODE_examples_BL with the names of the serial FARKODE examples
-# that use Lapack
-
+# Examples using LAPACK linear solvers
 SET(FARKODE_examples_BL
   )
 
-# Add variable FARKODE_examples_KLU with the names of the serial FARKODE examples
-# that use KLU
+# Add sparse solvers examples for 64-bit indextype configurations only,
+# not compatible with 32-bit indextype
+IF(SUNDIALS_INDEX_TYPE MATCHES "INT64_T")
 
-SET(FARKODE_examples_KLU
-  ark_bruss1D_FEM_klu
-  )
+  # Examples using KLU linear solver
+  SET(FARKODE_examples_KLU
+    "ark_bruss1D_FEM_klu\;develop"
+    )
+
+  # Examples using SuperLU_MT linear solver
+  SET(FARKODE_examples_SUPERLUMT
+    )
 
-# Add variable ARKODE_extras with the names of auxiliary files to install
+ENDIF()
 
+# Auxiliary files to install
 SET(ARKODE_extras
   plot_sol.py
   plot_brusselator1D_FEM.py
   )
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(ARKODE_LIB sundials_arkode_static)
   SET(NVECS_LIB sundials_nvecserial_static)
   SET(FNVECS_LIB sundials_fnvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(ARKODE_LIB sundials_arkode_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
   SET(FNVECS_LIB sundials_fnvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FARKODE_LIB sundials_farkode_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FARKODE_LIB} ${ARKODE_LIB} ${FNVECS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FARKODE_examples})
 
-# Add the build and install targets for each FARKODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${FARKODE_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f90)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+   # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f90 ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${FARKODE_examples})
+    INSTALL(FILES ${example}.f90 ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${FARKODE_examples})
 
-# Add the build and install targets for each Lapack FARKODE example (if needed)
 
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${FARKODE_examples_BL})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static
+      sundials_fsunlinsollapackband_static
+      sundials_fsunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared
+      sundials_fsunlinsollapackband_shared
+      sundials_fsunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${FARKODE_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.f90)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+     # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f90 ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FARKODE_examples_BL})
+      INSTALL(FILES ${example}.f90 ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FARKODE_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If KLU support is enabled, add the build and install targets for 
-# the examples using KLU
+
+# Add the build and install targets for each KLU example (if needed)
 IF(KLU_FOUND)
-  FOREACH(example ${FARKODE_examples_KLU})
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS
+      sundials_sunlinsolklu_static
+      sundials_fsunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS
+      sundials_sunlinsolklu_shared
+      sundials_fsunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${FARKODE_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.f90)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+     # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f90 ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FARKODE_examples_KLU})
+      INSTALL(FILES ${example}.f90 ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FARKODE_examples_KLU})
+
 ENDIF(KLU_FOUND)
 
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
+IF(SUPERLUMT_FOUND)
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS
+      sundials_sunlinsolsuperlumt_static
+      sundials_fsunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS
+      sundials_sunlinsolsuperlumt_shared
+      sundials_fsunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${FARKODE_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f90)
+
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+     # install example source and out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.f90 ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FARKODE_examples_SUPERLUMT})
+
+ENDIF(SUPERLUMT_FOUND)
+
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -127,44 +271,52 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${ARKODE_extras})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial)
-  ENDFOREACH(extrafile ${ARKODE_extras})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "ARKODE")
   SET(SOLVER_LIB "sundials_arkode")
   SET(SOLVER_FLIB "sundials_farkode")
-  LIST2STRING(FARKODE_examples EXAMPLES)
+
+  EXAMPLES2STRING(FARKODE_examples EXAMPLES)
 
   IF(LAPACK_FOUND)
-    LIST2STRING(FARKODE_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(FARKODE_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
 
   IF(KLU_FOUND)
-    LIST2STRING(FARKODE_examples_KLU EXAMPLES)
-  ENDIF(KLU_FOUND)
-
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+    EXAMPLES2STRING(FARKODE_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
+
+  IF(SUPERLUMT_FOUND)
+    EXAMPLES2STRING(FARKODE_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F90_ex.in
-      ${PROJECT_BINARY_DIR}/examples/arkode/F90_serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F90_ex.in
+    ${PROJECT_BINARY_DIR}/examples/arkode/F90_serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/arkode/F90_serial/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -176,8 +328,8 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/arkode/F90_serial/Makefile_ex 
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial 
+      FILES ${PROJECT_BINARY_DIR}/examples/arkode/F90_serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/arkode/F90_serial
       RENAME Makefile
       )
   ENDIF(UNIX)
diff --git a/examples/arkode/F90_serial/README b/examples/arkode/F90_serial/README
index 5bd2743..6d9c230 100644
--- a/examples/arkode/F90_serial/README
+++ b/examples/arkode/F90_serial/README
@@ -9,7 +9,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -20,7 +19,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -34,7 +36,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/arkode/F90_serial/ark_bruss.f90 b/examples/arkode/F90_serial/ark_bruss.f90
index ca57b8f..b519801 100644
--- a/examples/arkode/F90_serial/ark_bruss.f90
+++ b/examples/arkode/F90_serial/ark_bruss.f90
@@ -38,9 +38,8 @@
 ! 
 ! This program uses the IMEX ARK solver; here the 
 ! implicit systems are solved with a modified Newton iteration
-! with the ARKDENSE dense linear solver.  The Jacobian routine 
-! and right-hand side routines come from the file user-supplied 
-! Jacobian routine.
+! with the SUNDENSE linear solver.  The Jacobian routine and 
+! right-hand side routines are supplied.
 !
 ! Output is printed 10 times throughout the defined time interval.
 ! Run statistics (optional outputs) are printed at the end.
@@ -52,14 +51,15 @@
 program driver
   ! Declarations
   implicit none
+  include "sundials/sundials_fconfig.h"
 
   ! general problem variables
-  integer*8, parameter :: NEQ=3
-  real*8,    parameter :: T0=0.d0, Tf=10.d0
-  real*8    :: dTout, Tout, Tcur, rtol, atol, rout(6)
+  integer(kind=SUNINDEXTYPE), parameter :: NEQ=3
+  real(kind=REALTYPE), parameter :: T0=0.d0, Tf=10.d0
+  real(kind=REALTYPE) :: dTout, Tout, Tcur, rtol, atol, rout(6)
   integer   :: it, Nt, ier
   integer*8 :: iout(22)
-  real*8, dimension(NEQ) :: y
+  real(kind=REALTYPE), dimension(NEQ) :: y
 
   ! real/integer parameters to pass through to supplied functions
   !    ipar(1) -> unused
@@ -67,11 +67,12 @@ program driver
   !    rpar(2) -> "b" parameter 
   !    rpar(3) -> "ep" parameter
   integer*8 :: ipar
-  real*8    :: rpar(3)
+  real(kind=REALTYPE) :: rpar(3)
 
   ! solver parameters
-  integer*8 :: order, adapt_method
-  real*8    :: nlscoef
+  integer :: adapt_method
+  integer(kind=SUNINDEXTYPE) :: order
+  real(kind=REALTYPE) :: nlscoef, adapt_params
 
   !-----------------------
   ! set some solver parameters
@@ -102,6 +103,10 @@ program driver
      stop
   endif
 
+  ! initialize dense matrix and dense linear solver modules
+  call FSunDenseMatInit(4, NEQ, NEQ, ier)
+  call FSunDenseLinSolInit(4, ier)
+  
   ! initialize ARKode solver to use IMEX integrator, scalar tolerances
   call FARKMalloc(T0, y, 2, 1, rtol, atol, &
                   iout, rout, ipar, rpar, ier)
@@ -121,18 +126,21 @@ program driver
      write(0,*) 'Error in FARKSetIin = ',ier
      stop
   endif
-  call FARKSetAdaptivityMethod(adapt_method, 1, 0, 0, ier)
+  adapt_params = 0.d0
+  call FARKSetAdaptivityMethod(adapt_method, 1, 0, adapt_params, ier)
   if (ier < 0) then
      write(0,*) 'Error in FARKSetAdaptMethod = ',ier
      stop
   endif
 
-  ! specify use of dense linear solver
-  call FARKDense(NEQ, ier)
+  ! attach matrix and linear solver modules to ARKDls interface
+  call FARKDlsInit(ier)
   if (ier < 0) then
-     write(0,*) 'Error in FARKDense = ',ier
+     write(0,*) 'Error in FARKDlsInit = ',ier
      stop
   endif
+
+  ! notify ARKDls module of user-supplied Jacobian construction routine
   call FARKDenseSetJac(1, ier)
   if (ier < 0) then
      write(0,*) 'Error in FARKDenseSetJac = ',ier
@@ -201,13 +209,14 @@ subroutine farkifun(t, y, ydot, ipar, rpar, ier)
 
   ! Declarations
   implicit none
+  include "sundials/sundials_fconfig.h"
 
   ! Arguments
-  real*8,    intent(in)  :: t, rpar(3)
-  integer*8, intent(in)  :: ipar(1)
+  real(kind=REALTYPE), intent(in) :: t, rpar(3)
+  integer*8, intent(in) :: ipar(1)
+  real(kind=REALTYPE), intent(in)  :: y(3)
+  real(kind=REALTYPE), intent(out) :: ydot(3)
   integer,   intent(out) :: ier
-  real*8,    intent(in)  :: y(3)
-  real*8,    intent(out) :: ydot(3)
 
   ! temporary variables
   real*8 :: u, v, w, a, b, ep
@@ -236,13 +245,14 @@ subroutine farkefun(t, y, ydot, ipar, rpar, ier)
 
   ! Declarations
   implicit none
+  include "sundials/sundials_fconfig.h"
 
   ! Arguments
-  real*8,    intent(in)  :: t, rpar(3)
-  integer*8, intent(in)  :: ipar(1)
+  real(kind=REALTYPE), intent(in)  :: t, rpar(3)
+  integer*8, intent(in) :: ipar(1)
+  real(kind=REALTYPE), intent(in)  :: y(3)
+  real(kind=REALTYPE), intent(out) :: ydot(3)
   integer,   intent(out) :: ier
-  real*8,    intent(in)  :: y(3)
-  real*8,    intent(out) :: ydot(3)
 
   ! temporary variables
   real*8 :: u, v, w, a, b, ep
@@ -271,13 +281,15 @@ subroutine farkdjac(neq,t,y,fy,DJac,h,ipar,rpar,wk1,wk2,wk3,ier)
 
   ! Declarations
   implicit none
+  include "sundials/sundials_fconfig.h"
 
   ! Arguments
-  real*8,    intent(in)  :: t, h, rpar(3)
-  integer*8, intent(in)  :: neq, ipar(1)
+  real(kind=REALTYPE), intent(in) :: t, h, rpar(3)
+  integer*8, intent(in) :: ipar(1)
+  integer(kind=SUNINDEXTYPE), intent(in) :: neq
   integer,   intent(out) :: ier
-  real*8,    intent(in), dimension(neq) :: y, fy, wk1, wk2, wk3
-  real*8,    intent(out) :: DJac(neq,neq)
+  real(kind=REALTYPE), intent(in), dimension(neq) :: y, fy, wk1, wk2, wk3
+  real(kind=REALTYPE), intent(out) :: DJac(neq,neq)
 
   ! temporary variables
   real*8 :: u, v, w, a, b, ep
diff --git a/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.f90 b/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.f90
index 5694c29..884a8a9 100644
--- a/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.f90
+++ b/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.f90
@@ -47,10 +47,14 @@
 !    a=0.6,  b=2.0,  du=0.025,  dv=0.025,  dw=0.025,  ep=1.d-5
 !
 ! This program solves the problem with the DIRK method, using a 
-! Newton iteration with the ARKKLU and ARKMASSKLU sparse linear 
-! solvers, where we store the Jacobian and mass matrices in 
+! Newton iteration with the SUNKLU sparse linear solvers for both 
+! the system and mass matrices.  These matrices are stored in 
 ! compressed-sparse-row format.
 !
+! This program assumes that SUNDIALS was configured with
+! realtype==double and sunindextype=64bit (should seg-fault
+! otherwise).
+!
 ! Output is printed 10 times throughout the defined time interval.
 ! Run statistics (optional outputs) are printed at the end.
 !-----------------------------------------------------------------
@@ -59,9 +63,10 @@
 ! user data structure
 module UserData
   implicit none
+  include "sundials/sundials_fconfig.h"
   save
   
-  integer :: N                     ! number of intervals
+  integer*8 :: N                   ! number of intervals
   real*8, allocatable :: x(:)      ! mesh node locations
   real*8 :: a                      ! constant forcing on u
   real*8 :: b                      ! steady-state value of w
@@ -163,21 +168,25 @@ end module Quadrature
 ! Main driver program
 !-----------------------------------------------------------------
 program driver
-  use UserData
 
-  ! Declarations
+  ! inclusions
+  use UserData
   implicit none
 
+  ! Declarations
   ! general problem variables
-  real*8, parameter :: T0=0.d0, Tf=10.d0
-  real*8    :: dTout, Tout, Tcur, rtol, atol, pi, h, z, rout(6)
-  integer   :: i, it, Nt, ier, idef, ineq, nnz, ordering, sparsetype
-  integer*8 :: NEQ, iout(29)
-  real*8, allocatable :: y(:,:), umask(:,:), vmask(:,:), wmask(:,:)
+  real(kind=REALTYPE), parameter :: T0=0.d0, Tf=10.d0
+  real(kind=REALTYPE) :: rtol, atol, rout(6), Tout, Tcur
+  real*8    :: dTout, pi, h, z
+  integer   :: i, it, Nt, ier, ordering, sparsetype, time_dep
+  integer*8 :: iout(29)
+  integer(kind=SUNINDEXTYPE) :: NEQ, nnz, Iinput
+  real(kind=REALTYPE), allocatable :: y(:,:), umask(:,:)
+  real(kind=REALTYPE), allocatable :: vmask(:,:), wmask(:,:)
 
   ! dummy real/integer parameters to pass through to supplied functions
   integer*8 :: ipar
-  real*8    :: rpar
+  real(kind=REALTYPE) :: rpar
 
   !-----------------------
 
@@ -239,6 +248,17 @@ program driver
   ! initialize vector module
   call FNVInitS(4, NEQ, ier)
 
+  ! initialize system and mass matrix modules
+  nnz = 15*NEQ     ! integer number of nonzeros           
+  ordering = 0     ! AMD
+  sparsetype = 1   ! CSR
+  call FSunSparseMatInit(4, NEQ, NEQ, nnz, sparsetype, ier)
+  call FSunSparseMassMatInit(NEQ, NEQ, nnz, sparsetype, ier)
+
+  ! initialize KLU system and mass solvers
+  call FSunKLUInit(4, ier)
+  call FSunMassKLUInit(ier)
+  
   ! initialize ARKode solver
   ipar = 0
   rpar = 0.0
@@ -248,18 +268,17 @@ program driver
                   iout, rout, ipar, rpar, ier)
 
   ! set optional inputs
-  call FARKSetIin('IMPLICIT', 1, ier)
-  call FARKSetIin('MAX_NSTEPS', 1000, ier)
+  Iinput = 1
+  call FARKSetIin('IMPLICIT', Iinput, ier)
+  Iinput = 1000
+  call FARKSetIin('MAX_NSTEPS', Iinput, ier)
   call FARKSetResTolerance(1, atol, ier)
 
-  ! specify use of KLU linear solvers
-  ineq = NEQ       ! convert to 'normal' integer type
-  nnz = 15*NEQ     ! integer number of nonzeros           
-  ordering = 0     ! AMD
-  sparsetype = 1   ! CSR
-  call FARKKLU(ineq, nnz, sparsetype, ordering, ier)
+  ! attach matrix and linear solver objects to ARKDls interfaces
+  time_dep = 0
+  call FARKDlsInit(ier)
   call FARKSparseSetJac(ier)
-  call FARKMassKLU(ineq, nnz, sparsetype, ordering, ier)
+  call FARKDlsMassInit(time_dep, ier)
   call FARKSparseSetMass(ier)
 
   ! Open output stream for results
@@ -355,11 +374,11 @@ subroutine FARKIFun(t, y, ydot, ipar, rpar, ier)
   implicit none
 
   ! Arguments
-  real*8,  intent(in)   :: t, rpar(1)
+  real(kind=REALTYPE), intent(in)  :: t, rpar(1)
   integer*8, intent(in) :: ipar(1)
   integer, intent(out)  :: ier
-  real*8,  intent(in)   :: y(3,N)
-  real*8,  intent(out)  :: ydot(3,N)
+  real(kind=REALTYPE), intent(in)  :: y(3,N)
+  real(kind=REALTYPE), intent(out) :: ydot(3,N)
 
   ! Local data
   integer :: ix
@@ -534,11 +553,11 @@ subroutine farkefun(t, y, ydot, ipar, rpar, ier)
   implicit none
 
   ! Arguments
-  real*8,  intent(in)   :: t, rpar(1)
+  real(kind=REALTYPE), intent(in)  :: t, rpar(1)
   integer*8, intent(in) :: ipar(1)
+  real(kind=REALTYPE), intent(in)  :: y(3,N)
+  real(kind=REALTYPE), intent(out) :: ydot(3,N)
   integer, intent(out)  :: ier
-  real*8,  intent(in)   :: y(3,N)
-  real*8,  intent(out)  :: ydot(3,N)
 
   ! return with success (since fully implicit)
   ydot = 0.d0
@@ -562,15 +581,17 @@ subroutine farkspjac(t, y, fy, neq, nnz, Jdata, Jcolvals, &
   implicit none
 
   ! Arguments
-  real*8,    intent(in)  :: t, h, rpar(1)
-  real*8,    intent(in), dimension(3,N) :: y, fy, wk1, wk2, wk3
-  integer,   intent(in)  :: neq, nnz
+  real(kind=REALTYPE), intent(in)  :: t, h, rpar(1)
+  real(kind=REALTYPE), intent(in), dimension(3,N) :: y, fy, wk1, wk2, wk3
+  real(kind=REALTYPE), intent(out) :: Jdata(nnz)
   integer*8, intent(in)  :: ipar(1)
-  real*8,    intent(out) :: Jdata(nnz)
-  integer,   intent(out) :: Jcolvals(nnz), Jrowptrs(neq+1), ier
+  integer(kind=SUNINDEXTYPE), intent(in)  :: neq, nnz
+  integer(kind=SUNINDEXTYPE), intent(out) :: Jcolvals(nnz)
+  integer(kind=SUNINDEXTYPE), intent(out) :: Jrowptrs(neq+1)
+  integer,   intent(out) :: ier
 
   ! Local data
-  integer :: ix, nz
+  integer :: ix, nz, Nint
   real*8  :: ul, uc, ur, vl, vc, vr, wl, wc, wr, xl, xc, xr
   real*8  :: u1, u2, u3, v1, v2, v3, w1, w2, w3
   real*8  :: f1, f2, f3, df1, df2, df3, dQdf1, dQdf2, dQdf3
@@ -583,6 +604,9 @@ subroutine farkspjac(t, y, fy, neq, nnz, Jdata, Jcolvals, &
      return
   endif
 
+  ! set integer*4 version of N for call to idx()
+  Nint = N
+  
   ! clear out Jacobian matrix data
   Jdata = 0.d0
   nz = 0
@@ -968,12 +992,12 @@ subroutine farkspjac(t, y, fy, neq, nnz, Jdata, Jcolvals, &
   enddo
 
   ! Dirichlet boundary at right
-  Jrowptrs(idx(N,1)+1) = nz
-  Jrowptrs(idx(N,2)+1) = nz
-  Jrowptrs(idx(N,3)+1) = nz
+  Jrowptrs(idx(Nint,1)+1) = nz
+  Jrowptrs(idx(Nint,2)+1) = nz
+  Jrowptrs(idx(Nint,3)+1) = nz
  
   ! signal end of data in CSR matrix
-  Jrowptrs(idx(N,3)+2) = nz
+  Jrowptrs(idx(Nint,3)+2) = nz
 
   ier = 0
   return
@@ -996,15 +1020,17 @@ subroutine farkspmass(t, neq, nnz, Mdata, Mcolvals, Mrowptrs, &
   implicit none
 
   ! Arguments
-  real*8,    intent(in)  :: t, rpar(1)
-  real*8,    intent(in), dimension(3,N) :: wk1, wk2, wk3
-  integer,   intent(in)  :: neq, nnz
-  integer*8, intent(in)  :: ipar(1)
-  real*8,    intent(out) :: Mdata(nnz)
-  integer,   intent(out) :: Mcolvals(nnz), Mrowptrs(neq+1), ier
+  real(kind=REALTYPE), intent(in)  :: t, rpar(1)
+  real(kind=REALTYPE), intent(in), dimension(3,N) :: wk1, wk2, wk3
+  real(kind=REALTYPE), intent(out) :: Mdata(nnz)
+  integer*8, intent(in) :: ipar(1)
+  integer(kind=SUNINDEXTYPE), intent(in)  :: neq, nnz
+  integer(kind=SUNINDEXTYPE), intent(out) :: Mcolvals(nnz)
+  integer(kind=SUNINDEXTYPE), intent(out) :: Mrowptrs(neq+1)
+  integer,  intent(out) :: ier
 
   ! Local data
-  integer :: ix, nz
+  integer :: ix, nz, Nint
   real*8  :: xl, xc, xr, Ml, Mc, Mr, ChiL1, ChiL2, ChiL3, ChiR1, ChiR2, ChiR3
   logical :: left, right
 
@@ -1014,11 +1040,14 @@ subroutine farkspmass(t, neq, nnz, Mdata, Mcolvals, Mrowptrs, &
      return
   endif
 
+  ! set integer*4 version of N for call to idx()
+  Nint = N
+  
   ! clear out Jacobian matrix data
   Mdata = 0.d0
+  nz = 0
 
   ! iterate through nodes, filling in matrix by rows
-  nz = 0
   do ix=1,N
 
      ! set booleans to determine whether intervals exist on the left/right */
@@ -1125,7 +1154,7 @@ subroutine farkspmass(t, neq, nnz, Mdata, Mcolvals, Mrowptrs, &
   enddo
 
   ! signal end of data in CSR matrix
-  Mrowptrs(idx(N,3)+2) = nz
+  Mrowptrs(idx(Nint,3)+2) = nz
 
   ier = 0
   return
diff --git a/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.out b/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.out
index bfa0ac3..949136c 100644
--- a/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.out
+++ b/examples/arkode/F90_serial/ark_bruss1D_FEM_klu.out
@@ -52,5 +52,5 @@ ARKode solver parameters:
     Total number of nonlinear iterations =                  1209
     Total number of nonlinear solver convergence failures =                     0
     Total number of error test failures =                     0
-    Total number of mass matrix evaluations =                   157
+    Total number of mass matrix evaluations =                     1
    
diff --git a/examples/cvode/C_openmp/CMakeLists.txt b/examples/cvode/C_openmp/CMakeLists.txt
index ba4e164..2bb065f 100644
--- a/examples/cvode/C_openmp/CMakeLists.txt
+++ b/examples/cvode/C_openmp/CMakeLists.txt
@@ -19,75 +19,81 @@
 # For details, see the LICENSE file.
 # -----------------------------------------------------------------
 # CMakeLists.txt file for CVODE OpenMP examples
+# -----------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if OpenMP is enabled
 IF(OPENMP_FOUND)
 
-# Add variable CVODE_examples_OMP with the names of the openmp CVODE examples
-SET(CVODE_examples_OMP
-  cvAdvDiff_bnd_omp
-  )
+  # Examples using SUNDIALS linear solvers
+  SET(CVODE_examples
+    "cvAdvDiff_bnd_omp\;4\;develop"
+    )
 
 ENDIF(OPENMP_FOUND)
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODE_LIB sundials_cvode_static)
   SET(NVECOMP_LIB sundials_nvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODE_LIB sundials_cvode_shared)
   SET(NVECOMP_LIB sundials_nvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECOMP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # update the compilation flags to include OpenMP support
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 
-# Add the build and install targets for each CVODE example
-FOREACH(example ${CVODE_examples_OMP})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${CVODE_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} TEST_ARGS 4)
+
+  # add to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    TEST_ARGS ${example_args}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/C_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${CVODE_examples_OMP})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/C_openmp)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${CVODE_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
   INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/C_openmp)
 
-  # Install the extra files
-  FOREACH(extrafile ${CVODE_extras_OMP})
-    INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/C_openmp)
-  ENDFOREACH(extrafile ${CVODE_extras_OMP})
-
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "CVODE")
   SET(SOLVER_LIB "sundials_cvode")
-  LIST2STRING(CVODE_examples_OMP EXAMPLES)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
 
+  EXAMPLES2STRING(CVODE_examples EXAMPLES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -95,10 +101,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvode/C_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/C_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/cvode/C_openmp/README b/examples/cvode/C_openmp/README
index d372835..78bfb08 100644
--- a/examples/cvode/C_openmp/README
+++ b/examples/cvode/C_openmp/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvode/C_openmp/cvAdvDiff_bnd_omp.c b/examples/cvode/C_openmp/cvAdvDiff_bnd_omp.c
index 8e90c57..ee61486 100644
--- a/examples/cvode/C_openmp/cvAdvDiff_bnd_omp.c
+++ b/examples/cvode/C_openmp/cvAdvDiff_bnd_omp.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
- * Programmer(s): Ting Yan @ SMU
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds and Ting Yan @ SMU
  *     Based on cvAdvDiff_bnd.c and parallelized with OpenMP
  * -----------------------------------------------------------------
  * Example problem:
  *
  * The following is a simple example problem with a banded Jacobian,
- * with the program for its solution by CVODE.
+ * solved using CVODE.
  * The problem is the semi-discrete form of the advection-diffusion
  * equation in 2-D:
  *   du/dt = d^2 u / dx^2 + .5 du/dx + d^2 u / dy^2
@@ -21,7 +17,7 @@
  * central differencing, and with boundary values eliminated,
  * leaving an ODE system of size NEQ = MX*MY.
  * This program solves the problem with the BDF method, Newton
- * iteration with the CVBAND band linear solver, and a user-supplied
+ * iteration with the SUNBAND linear solver, and a user-supplied
  * Jacobian routine.
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .1, .2, ..., 1.
@@ -34,27 +30,27 @@
  *
  * Execution:
  *
- * If the user want to use the default value or the number of threads 
- * from environment value:
+ * To use the default value or the number of threads from the 
+ * environment value, run without arguments:
  *      % ./cvAdvDiff_bnd_omp 
- * If the user want to specify the number of threads to use
- *      % ./cvAdvDiff_bnd_omp num_threads
- * where num_threads is the number of threads the user want to use 
- * -----------------------------------------------------------------
- */
+ * The environment variable can be over-ridden with a command line
+ * argument specifying the number of threads to use, e.g:
+ *      % ./cvAdvDiff_bnd_omp 5
+ * ----------------------------------------------------------------- */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-/* Header files with a description of contents used in cvbanx.c */
+/* Header files with a description of contents */
 
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts., consts. */
-#include <cvode/cvode_band.h>        /* prototype for CVBand */
-#include <nvector/nvector_openmp.h>  /* serial N_Vector types, fcts., macros */
-#include <sundials/sundials_band.h>  /* definitions of type DlsMat and macros */
-#include <sundials/sundials_types.h> /* definition of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS and EXP */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts. */
+#include <nvector/nvector_openmp.h>    /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver */
+#include <cvode/cvode_direct.h>        /* access to CVDls interface */
+#include <sundials/sundials_types.h>   /* definition of type realtype */
+#include <sundials/sundials_math.h>    /* definition of ABS and EXP */
 
 #ifdef _OPENMP
 #include <omp.h>
@@ -108,15 +104,13 @@ static void PrintFinalStats(void *cvode_mem);
 
 /* Private function to check function return values */
 
-static int check_flag(void *flagvalue, char *funcname, int opt);
+static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /* Functions Called by the Solver */
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector u, N_Vector fu, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /*
  *-------------------------------
@@ -129,6 +123,8 @@ int main(int argc, char *argv[])
   realtype dx, dy, reltol, abstol, t, tout, umax;
   N_Vector u;
   UserData data;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
   long int nst;
@@ -136,6 +132,8 @@ int main(int argc, char *argv[])
 
   u = NULL;
   data = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Set the number of threads to use */
@@ -143,11 +141,10 @@ int main(int argc, char *argv[])
 #ifdef _OPENMP
   num_threads = omp_get_max_threads();  /* Overwrite with OMP_NUM_THREADS environment variable */
 #endif
-  if (argc > 1)        /* overwrithe with command line value, if supplied */
+  if (argc > 1)        /* overwrite with command line value, if supplied */
     num_threads = strtol(argv[1], NULL, 0);
 
-  /* Create a serial vector */
-
+  /* Create an OpenMP vector */
   u = N_VNew_OpenMP(NEQ, num_threads);  /* Allocate u vector */
   if(check_flag((void*)u, "N_VNew_OpenMP", 0)) return(1);
 
@@ -185,13 +182,22 @@ int main(int argc, char *argv[])
   flag = CVodeSetUserData(cvode_mem, data);
   if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVBand to specify the CVBAND band linear solver */
-  flag = CVBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVBand", 1)) return(1);
+  /* Create banded SUNMatrix for use in linear solves -- since this will be factored, 
+     set the storage bandwidth to be the sum of upper and lower bandwidths */
+  A = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver object for use by CVode */
+  LS = SUNBandLinearSolver(u, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+  
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   /* Set the user-supplied Jacobian routine Jac */
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop over output points: call CVode, print results, test for errors */
 
@@ -205,13 +211,15 @@ int main(int argc, char *argv[])
     check_flag(&flag, "CVodeGetNumSteps", 1);
     PrintOutput(t, umax, nst);
   }
- 
+
   PrintFinalStats(cvode_mem);  /* Print some final statistics   */
   printf("num_threads = %i\n\n", num_threads);
    
 
   N_VDestroy_OpenMP(u);   /* Free the u vector */
   CVodeFree(&cvode_mem);  /* Free the integrator memory */
+  SUNLinSolFree(LS);      /* Free the linear solver memory */
+  SUNMatDestroy(A);       /* Free the matrix memory */
   free(data);             /* Free the user data */
 
   return(0);
@@ -270,12 +278,11 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
 
 /* Jacobian routine. Compute J(t,u). */
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector u, N_Vector fu, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype *kthCol, hordc, horac, verdc;
   UserData data;
   
@@ -294,19 +301,19 @@ static int Jac(long int N, long int mu, long int ml,
   horac = data->hacoef;
   verdc = data->vdcoef;
 
-#pragma omp parallel for collapse(2) default(shared) private(j, u, k, kthCol) num_threads(data->nthreads) 
+#pragma omp parallel for collapse(2) default(shared) private(i, j, k, kthCol) num_threads(data->nthreads) 
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
+      kthCol = SUNBandMatrix_Column(J,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = verdc;
     }
   }
 
@@ -427,7 +434,7 @@ static void PrintFinalStats(void *cvode_mem)
      opt == 2 means function allocates memory so check if returned
               NULL pointer */
 
-static int check_flag(void *flagvalue, char *funcname, int opt)
+static int check_flag(void *flagvalue, const char *funcname, int opt)
 {
   int *errflag;
 
diff --git a/examples/cvode/cuda/CMakeLists.txt b/examples/cvode/cuda/CMakeLists.txt
new file mode 100644
index 0000000..b0e2c23
--- /dev/null
+++ b/examples/cvode/cuda/CMakeLists.txt
@@ -0,0 +1,124 @@
+# ---------------------------------------------------------------
+# Programmer:  Slaven Peles @ LLNL
+# ---------------------------------------------------------------
+# Based on CMakeLists.txt in cvode/serial by Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for CVODE cuda examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS linear solvers
+SET(CVODE_examples
+  "cvAdvDiff_kry_cuda\;develop"
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ${CUDA_TOOLKIT_ROOT_DIR}/samples/common/inc)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(CVODE_LIB sundials_cvode_static)
+  SET(NVECS_LIB sundials_nveccuda_static)
+ELSE()
+  SET(CVODE_LIB sundials_cvode_shared)
+  SET(NVECS_LIB sundials_nveccuda_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each CVODE example
+FOREACH(example_tuple ${CVODE_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
+
+  set_source_files_properties(${example}.cu PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
+
+  # example source files
+  CUDA_ADD_EXECUTABLE(${example} ${example}.cu)
+
+  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.cu ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/cuda)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${CVODE_examples})
+
+
+# create Makfile and CMakeLists.txt for examples
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/cuda)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER "CVODE")
+  SET(SOLVER_LIB "sundials_cvode")
+
+  EXAMPLES2STRING(CVODE_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_cuda_CUDA_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/cuda/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/cvode/cuda/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/cuda 
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_cuda_CUDA_ex.in
+      ${PROJECT_BINARY_DIR}/examples/cvode/cuda/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/cvode/cuda/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/cuda 
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvode/cuda/README b/examples/cvode/cuda/README
new file mode 100644
index 0000000..4819fcd
--- /dev/null
+++ b/examples/cvode/cuda/README
@@ -0,0 +1,3 @@
+List of CUDA CVODE examples
+
+  cvAdvDiff_kry_cuda       : 2-D advection-diffusion (nonstiff)
diff --git a/examples/cvode/cuda/cvAdvDiff_kry_cuda.cu b/examples/cvode/cuda/cvAdvDiff_kry_cuda.cu
new file mode 100644
index 0000000..326ce82
--- /dev/null
+++ b/examples/cvode/cuda/cvAdvDiff_kry_cuda.cu
@@ -0,0 +1,496 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * Acknowledgements: This example is based on cvAdvDiff_bnd 
+ *                   example by Scott D. Cohen, Alan C. 
+ *                   Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * Example problem:
+ *
+ * The following is a simple example problem with a banded Jacobian,
+ * with the program for its solution by CVODE.
+ * The problem is the semi-discrete form of the advection-diffusion
+ * equation in 2-D:
+ *   du/dt = d^2 u / dx^2 + .5 du/dx + d^2 u / dy^2
+ * on the rectangle 0 <= x <= 2, 0 <= y <= 1, and the time
+ * interval 0 <= t <= 1. Homogeneous Dirichlet boundary conditions
+ * are posed, and the initial condition is
+ *   u(x,y,t=0) = x(2-x)y(1-y)exp(5xy).
+ * The PDE is discretized on a uniform MX+2 by MY+2 grid with
+ * central differencing, and with boundary values eliminated,
+ * leaving an ODE system of size NEQ = MX*MY.
+ * This program solves the problem with the BDF method, Newton
+ * iteration with the CVBAND band linear solver, and a user-supplied
+ * Jacobian routine.
+ * It uses scalar relative and absolute tolerances.
+ * Output is printed at t = .1, .2, ..., 1.
+ * Run statistics (optional outputs) are printed at the end.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts. */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver     */
+#include <cvode/cvode_spils.h>         /* access to CVSpils interface */
+#include <sundials/sundials_types.h>   /* definition of type realtype */
+#include <sundials/sundials_math.h>    /* definition of ABS and EXP   */
+
+#include <nvector/nvector_cuda.h>
+
+/* Real Constants */
+
+#define ATOL  RCONST(1.0e-5) /* scalar absolute tolerance */
+#define T0    RCONST(0.0)    /* initial time              */
+#define T1    RCONST(0.1)    /* first output time         */
+#define DTOUT RCONST(0.1)    /* output time increment     */
+#define NOUT  10             /* number of output times    */
+
+#define ZERO RCONST(0.0)
+#define HALF RCONST(0.5)
+#define ONE  RCONST(1.0)
+#define TWO  RCONST(2.0)
+#define FIVE RCONST(5.0)
+
+/*
+ * CUDA kernels
+ */
+
+__global__ void fKernel(const realtype *u, realtype *udot,
+                               sunindextype MX, sunindextype MY,
+                               realtype hordc, realtype horac, realtype verdc)
+{
+  realtype uij, udn, uup, ult, urt, hdiff, hadv, vdiff;
+  sunindextype i, j, tid;
+
+  /* Loop over all grid points. */
+  tid = blockDim.x * blockIdx.x + threadIdx.x;
+  
+  if (tid < MX*MY) {
+    i = tid/MY;
+    j = tid%MY;
+    
+    uij = u[tid];
+    udn = (j ==    0) ? ZERO : u[tid - 1];
+    uup = (j == MY-1) ? ZERO : u[tid + 1];
+    ult = (i ==    0) ? ZERO : u[tid - MY];
+    urt = (i == MX-1) ? ZERO : u[tid + MY];
+
+    /* Set diffusion and advection terms and load into udot */
+    
+    hdiff = hordc*(ult - TWO*uij + urt);
+    hadv  = horac*(urt - ult);
+    vdiff = verdc*(uup - TWO*uij + udn);
+    udot[tid] = hdiff + hadv + vdiff;
+  }
+
+}
+
+__global__ void jtvKernel(const realtype *vdata, realtype *Jvdata,
+                          sunindextype MX, sunindextype MY,
+                          realtype hordc, realtype horac, realtype verdc)
+{
+  sunindextype i, j, tid;
+
+  /* Loop over all grid points. */
+  tid = blockDim.x * blockIdx.x + threadIdx.x;
+  
+  if (tid < MX*MY) {
+      
+    i = tid/MY;
+    j = tid%MY;
+      
+      
+    /* set the tid-th element of Jv */
+
+    Jvdata[tid] = -TWO*(verdc+hordc) * vdata[tid];
+    if (i !=    0) Jvdata[tid] += (hordc - horac) * vdata[tid-MY];
+    if (i != MX-1) Jvdata[tid] += (hordc + horac) * vdata[tid+MY];
+    if (j !=    0) Jvdata[tid] += verdc * vdata[tid-1];
+    if (j != MY-1) Jvdata[tid] += verdc * vdata[tid+1];
+
+  }
+
+}
+
+/* Type : _UserData (contains model and discretization parameters) */
+struct _UserData {
+  sunindextype MX, MY, NEQ;
+  realtype dx, dy, XMAX, YMAX;
+  realtype hdcoef, hacoef, vdcoef;
+};
+
+typedef _UserData *UserData;
+
+/* Problem setup and initialization functions */
+static UserData SetUserData(int argc, char** argv);
+static void SetIC(N_Vector u, UserData data);
+
+/* Functions Called by the Solver */
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+static int jtv(N_Vector v, N_Vector Jv, realtype t,
+               N_Vector u, N_Vector fu,
+               void *user_data, N_Vector tmp);
+
+/* Private Helper Functions */
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax, UserData data);
+static void PrintOutput(realtype t, realtype umax, long int nst);
+static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+
+
+/*
+ *-------------------------------
+ * Main Program
+ *-------------------------------
+ */
+
+int main(int argc, char** argv)
+{
+  realtype reltol, abstol, t, tout, umax;
+  N_Vector u;
+  UserData data;
+  SUNLinearSolver LS;
+  void *cvode_mem;
+  int iout, flag;
+  long int nst;
+
+  u = NULL;
+  data = NULL;
+  LS = NULL;
+  cvode_mem = NULL;
+
+  /* Set model parameters */
+  data = SetUserData(argc, argv);
+  if(check_flag((void *)data, "malloc", 2)) return(1);
+
+  reltol = ZERO;  /* Set the tolerances */
+  abstol = ATOL;
+
+  /* Create a CUDA vector with initial values */
+  u = N_VNew_Cuda(data->NEQ);  /* Allocate u vector */
+  if(check_flag((void*)u, "N_VNew_Cuda", 0)) return(1);
+
+  SetIC(u, data);  /* Initialize u vector */
+
+  /* Call CVodeCreate to create the solver memory and specify the 
+   * Backward Differentiation Formula and the use of a Newton iteration */
+  cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+  if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
+
+  /* Call CVodeInit to initialize the integrator memory and specify the
+   * user's right hand side function in u'=f(t,u), the initial time T0, and
+   * the initial dependent variable vector u. */
+  flag = CVodeInit(cvode_mem, f, T0, u);
+  if(check_flag(&flag, "CVodeInit", 1)) return(1);
+
+  /* Call CVodeSStolerances to specify the scalar relative tolerance
+   * and scalar absolute tolerance */
+  flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+  if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+  /* Set the pointer to user-defined data */
+  flag = CVodeSetUserData(cvode_mem, data);
+  if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+  /* Create SPGMR solver structure without preconditioning
+   * and the maximum Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_NONE, 0);
+  if(check_flag(&flag, "SUNSPGMR", 1)) return(1);
+
+  /* Set CVSpils linear solver to LS */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return(1);
+
+  /* Set the JAcobian-times-vector function */
+  flag = CVSpilsSetJacTimes(cvode_mem, NULL, jtv);
+  if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1);
+
+  /* In loop over output points: call CVode, print results, test for errors */
+
+  umax = N_VMaxNorm(u);
+  PrintHeader(reltol, abstol, umax, data);
+  for(iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) {
+    flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
+    if(check_flag(&flag, "CVode", 1)) break;
+    umax = N_VMaxNorm(u);
+    flag = CVodeGetNumSteps(cvode_mem, &nst);
+    check_flag(&flag, "CVodeGetNumSteps", 1);
+    PrintOutput(t, umax, nst);
+  }
+
+  PrintFinalStats(cvode_mem);  /* Print some final statistics   */
+
+  N_VDestroy(u);          /* Free the u vector */
+  CVodeFree(&cvode_mem);  /* Free the integrator memory */
+  free(data);             /* Free the user data */
+
+  return(0);
+}
+
+/*
+ *-------------------------------------------
+ * Problem setup and initialization functions
+ *-------------------------------------------
+ */
+
+/* Set model and discretization parameters */
+
+UserData SetUserData(int argc, char *argv[])
+{
+  const sunindextype MX = 10;
+  const sunindextype MY = 5;
+  const realtype XMAX = RCONST(2.0);    /* domain boundaries         */
+  const realtype YMAX = RCONST(1.0);
+
+  /* Allocate user data structure */
+  UserData ud = (UserData) malloc(sizeof *ud);
+  if(check_flag((void*) ud, "AllocUserData", 2)) return(NULL);
+
+  ud->MX  = MX;
+  ud->MY  = MY;
+  ud->NEQ = MX*MY;
+  ud->XMAX = XMAX;
+  ud->YMAX = YMAX;
+  ud->dx = XMAX/(MX+1);  /* Set grid coefficients in data */
+  ud->dy = YMAX/(MY+1);
+  ud->hdcoef = ONE/(ud->dx*ud->dx);
+  ud->hacoef = HALF/(TWO*ud->dx);
+  ud->vdcoef = ONE/(ud->dy*ud->dy);
+
+  return ud;
+}
+
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, UserData data)
+{
+  /* Extract needed constants from data */
+
+  const realtype dx = data->dx;
+  const realtype dy = data->dy;
+  const realtype xmax = data->XMAX;
+  const realtype ymax = data->YMAX;
+  const sunindextype MY = data->MY;
+  const sunindextype NEQ = data->NEQ;
+
+  /* Extract pointer to solution vector data on the host */
+  realtype *udata = N_VGetHostArrayPointer_Cuda(u);
+
+  sunindextype i, j, tid;
+  realtype x, y;
+
+
+  /* Load initial profile into u vector */
+
+  for (tid=0; tid < NEQ; tid++) {
+    i = tid / MY;
+    j = tid % MY;
+
+    x = (i+1)*dx;
+    y = (j+1)*dy;
+
+    udata[tid] = x*(xmax - x)*y*(ymax - y)*SUNRexp(FIVE*x*y);
+  }
+  N_VCopyToDevice_Cuda(u);
+}
+
+
+/*
+ *-------------------------------
+ * Functions called by the solver
+ *-------------------------------
+ */
+
+/* f routine. Compute f(t,u). */
+
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
+{
+  UserData data = (UserData) user_data;
+
+  /* Extract needed constants from data */
+  const sunindextype MX  = data->MX;
+  const sunindextype MY  = data->MY;
+  const realtype hordc   = data->hdcoef;
+  const realtype horac   = data->hacoef;
+  const realtype verdc   = data->vdcoef;
+
+  /* Extract pointers to vector data */
+  const realtype *udata = N_VGetDeviceArrayPointer_Cuda(u);
+  realtype *dudata      = N_VGetDeviceArrayPointer_Cuda(udot);
+
+  unsigned block = 256;
+  unsigned grid = (MX*MY + block - 1) / block;
+
+  fKernel<<<grid,block>>>(udata, dudata, MX, MY, hordc, horac, verdc);
+
+  return(0);
+}
+
+
+/* Jacobian-times-vector routine. */
+
+static int jtv(N_Vector v, N_Vector Jv, realtype t,
+               N_Vector u, N_Vector fu,
+               void *user_data, N_Vector tmp)
+{
+  UserData data = (UserData) user_data;
+
+  /* Extract needed constants from data */
+  const sunindextype MX  = data->MX;
+  const sunindextype MY  = data->MY;
+  const realtype hordc   = data->hdcoef;
+  const realtype horac   = data->hacoef;
+  const realtype verdc   = data->vdcoef;
+
+  /* Extract pointers to vector data */
+  const realtype *vdata = N_VGetDeviceArrayPointer_Cuda(v);
+  realtype *Jvdata      = N_VGetDeviceArrayPointer_Cuda(Jv);
+
+  unsigned block = 256;
+  unsigned grid = (MX*MY + block - 1) / block;
+
+  N_VConst(ZERO, Jv);
+
+  jtvKernel<<<grid,block>>>(vdata, Jvdata, MX, MY, hordc, horac, verdc);
+
+  return(0);
+}
+
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
+/* Print first lines of output (problem description) */
+
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax, UserData data)
+{
+  printf("\n2-D Advection-Diffusion Equation\n");
+  printf("Mesh dimensions = %d X %d\n", data->MX, data->MY);
+  printf("Total system size = %d\n", data->NEQ);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("Tolerance parameters: reltol = %Lg   abstol = %Lg\n\n",
+         reltol, abstol);
+  printf("At t = %Lg      max.norm(u) =%14.6Le \n", T0, umax);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+  printf("Tolerance parameters: reltol = %g   abstol = %g\n\n",
+         reltol, abstol);
+  printf("At t = %g      max.norm(u) =%14.6e \n", T0, umax);
+#else
+  printf("Tolerance parameters: reltol = %g   abstol = %g\n\n", reltol, abstol);
+  printf("At t = %g      max.norm(u) =%14.6e \n", T0, umax);
+#endif
+
+  return;
+}
+
+/* Print current value */
+
+static void PrintOutput(realtype t, realtype umax, long int nst)
+{
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("At t = %4.2Lf   max.norm(u) =%14.6Le   nst = %4ld\n", t, umax, nst);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+  printf("At t = %4.2f   max.norm(u) =%14.6e   nst = %4ld\n", t, umax, nst);
+#else
+  printf("At t = %4.2f   max.norm(u) =%14.6e   nst = %4ld\n", t, umax, nst);
+#endif
+
+  return;
+}
+
+/* Get and print some final statistics */
+
+static void PrintFinalStats(void *cvode_mem)
+{
+  long lenrw, leniw ;
+  long lenrwLS, leniwLS;
+  long int nst, nfe, nsetups, nni, ncfn, netf;
+  long int nli, npe, nps, ncfl, nfeLS;
+  int flag;
+
+  flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
+  check_flag(&flag, "CVodeGetWorkSpace", 1);
+  flag = CVodeGetNumSteps(cvode_mem, &nst);
+  check_flag(&flag, "CVodeGetNumSteps", 1);
+  flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
+  check_flag(&flag, "CVodeGetNumRhsEvals", 1);
+  flag = CVodeGetNumLinSolvSetups(cvode_mem, &nsetups);
+  check_flag(&flag, "CVodeGetNumLinSolvSetups", 1);
+  flag = CVodeGetNumErrTestFails(cvode_mem, &netf);
+  check_flag(&flag, "CVodeGetNumErrTestFails", 1);
+  flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
+  check_flag(&flag, "CVodeGetNumNonlinSolvIters", 1);
+  flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
+  check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
+
+  flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
+  check_flag(&flag, "CVSpilsGetWorkSpace", 1);
+  flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
+  check_flag(&flag, "CVSpilsGetNumLinIters", 1);
+  flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+  check_flag(&flag, "CVSpilsGetNumPrecEvals", 1);
+  flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+  check_flag(&flag, "CVSpilsGetNumPrecSolves", 1);
+  flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+  check_flag(&flag, "CVSpilsGetNumConvFails", 1);
+  flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeLS);
+  check_flag(&flag, "CVSpilsGetNumRhsEvals", 1);
+
+  printf("\nFinal Statistics.. \n\n");
+  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
+  printf("lenrwLS = %5ld     leniwLS = %5ld\n", lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                  , nst);
+  printf("nfe     = %5ld     nfeLS   = %5ld\n"  , nfe, nfeLS);
+  printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
+  printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
+  printf("npe     = %5ld     nps     = %5ld\n"  , npe, nps);
+  printf("ncfn    = %5ld     ncfl    = %5ld\n\n", ncfn, ncfl);
+
+  return;
+}
+
+/* Check function return value...
+     opt == 0 means SUNDIALS function allocates memory so check if
+              returned NULL pointer
+     opt == 1 means SUNDIALS function returns a flag so check if
+              flag >= 0
+     opt == 2 means function allocates memory so check if returned
+              NULL pointer */
+
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+
+  if (opt == 0 && flagvalue == NULL) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
+            funcname);
+    return(1); }
+
+  /* Check if flag < 0 */
+
+  else if (opt == 1) {
+    errflag = (int *) flagvalue;
+    if (*errflag < 0) {
+      fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
+              funcname, *errflag);
+      return(1); }}
+
+  /* Check if function returned NULL pointer - no memory allocated */
+
+  else if (opt == 2 && flagvalue == NULL) {
+    fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n",
+            funcname);
+    return(1); }
+
+  return(0);
+}
diff --git a/examples/cvode/cuda/cvAdvDiff_kry_cuda.out b/examples/cvode/cuda/cvAdvDiff_kry_cuda.out
new file mode 100644
index 0000000..c90725d
--- /dev/null
+++ b/examples/cvode/cuda/cvAdvDiff_kry_cuda.out
@@ -0,0 +1,29 @@
+
+2-D Advection-Diffusion Equation
+Mesh dimensions = 10 X 5
+Total system size = 50
+Tolerance parameters: reltol = 0   abstol = 1e-05
+
+At t = 0      max.norm(u) =  8.954716e+01 
+At t = 0.10   max.norm(u) =  4.132884e+00   nst =   82
+At t = 0.20   max.norm(u) =  1.039293e+00   nst =  102
+At t = 0.30   max.norm(u) =  2.979816e-01   nst =  112
+At t = 0.40   max.norm(u) =  8.765538e-02   nst =  119
+At t = 0.50   max.norm(u) =  2.625408e-02   nst =  125
+At t = 0.60   max.norm(u) =  7.826077e-03   nst =  129
+At t = 0.70   max.norm(u) =  2.326537e-03   nst =  133
+At t = 0.80   max.norm(u) =  6.891180e-04   nst =  137
+At t = 0.90   max.norm(u) =  2.039853e-04   nst =  140
+At t = 1.00   max.norm(u) =  5.925586e-05   nst =  143
+
+Final Statistics.. 
+
+lenrw   =   589     leniw   =    50
+lenrwLS =   650     leniwLS =    22
+nst     =   143
+nfe     =   207     nfeLS   =     0
+nni     =   203     nli     =   225
+nsetups =     0     netf    =     2
+npe     =     0     nps     =     0
+ncfn    =     0     ncfl    =     0
+
diff --git a/examples/cvode/fcmix_parallel/CMakeLists.txt b/examples/cvode/fcmix_parallel/CMakeLists.txt
index a7f83d6..ae03434 100644
--- a/examples/cvode/fcmix_parallel/CMakeLists.txt
+++ b/examples/cvode/fcmix_parallel/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4957 $
-# $Date: 2016-09-23 12:21:47 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,83 +12,86 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the FCVODE parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable FCVODE_examples with the names of the parallel CVODE examples
-
+# Examples using SUNDIALS linear solvers
 SET(FCVODE_examples
-  "fcvDiag_non_p\;1\;2"
-  "fcvDiag_kry_bbd_p\;1\;2"
-  "fcvDiag_kry_p\;1\;2"
+  "fcvDiag_non_p\;1\;2\;develop"
+  "fcvDiag_kry_bbd_p\;1\;2\;develop"
+  "fcvDiag_kry_p\;1\;2\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the Fortran compiler to the MPIF77 script.
 # If not, then add the MPI include directory for MPI headers.
-
-IF(MPI_MPIF77 )
+IF(MPI_MPIF77)
   # use MPI_MPIF77 as the compiler
   SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
-ELSE(MPI_MPIF77)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPIF77)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODE_LIB sundials_cvode_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
   SET(FNVECP_LIB sundials_fnvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODE_LIB sundials_cvode_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
   SET(FNVECP_LIB sundials_fnvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FCVODE_LIB sundials_fcvode_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FCVODE_LIB} ${CVODE_LIB} ${FNVECP_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-IF(HYPRE_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${HYPRE_LIBRARIES})
-ENDIF(HYPRE_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FCVODE_examples})
 
-# Add the build and install targets for each CVODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
 
-FOREACH(example_tuple ${FCVODE_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPIF77)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPIF77)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${FCVODE_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -101,30 +101,28 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "CVODE")
   SET(SOLVER_LIB "sundials_cvode")
   SET(SOLVER_FLIB "sundials_fcvode")
-  FOREACH(example_tuple ${FCVODE_examples})
-    list(GET example_tuple 0 example)
-    LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${FCVODE_examples})
-  
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+
+  EXAMPLES2STRING(FCVODE_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -137,7 +135,7 @@ IF(EXAMPLES_INSTALL)
     # install the configured Makefile_ex as Makefile
     INSTALL(
       FILES ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_parallel/Makefile_ex
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_parallel
       RENAME Makefile
       )
   ENDIF(UNIX)
diff --git a/examples/cvode/fcmix_parallel/README b/examples/cvode/fcmix_parallel/README
index 91a3525..e61a696 100644
--- a/examples/cvode/fcmix_parallel/README
+++ b/examples/cvode/fcmix_parallel/README
@@ -9,7 +9,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -20,7 +19,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -34,7 +36,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f b/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f
index 59a6168..c70cb53 100644
--- a/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.f
@@ -1,31 +1,27 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4074 $
-C     $Date: 2014-04-23 14:13:52 -0700 (Wed, 23 Apr 2014) $
-C     ----------------------------------------------------------------
-C     Diagonal ODE example.  Stiff case, with diagonal preconditioner.
+C     Diagonal ODE example. Stiff case, with diagonal preconditioner.
 C     Uses FCVODE interfaces and FCVBBD interfaces.
 C     Solves problem twice -- with left and right preconditioning.
 C     ----------------------------------------------------------------
-C     
+C
 C     Include MPI-Fortran header file for MPI_COMM_WORLD, MPI types.
-      
+
       IMPLICIT NONE
 C
       INCLUDE "mpif.h"
 C
 C The following declaration specification should match C type long int.
-      INTEGER*8 NLOCAL, NEQ, IOUT(25), IPAR(2), MUDQ, MLDQ, MU, ML
+      INTEGER*8 NLOCAL, NEQ, I, IOUT(25), IPAR(2), MUDQ, MLDQ, MU, ML
       PARAMETER (NLOCAL=10)   
 C
-      INTEGER NOUT, LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNPE
-      INTEGER LNLI, LNPS, LNCFL, MYPE, IER, NPES, METH, ITMETH
-      INTEGER LLENRW, LLENIW, LLENRWLS, LLENIWLS
-      INTEGER IATOL, ITASK, IPRE, IGS, JOUT
-      INTEGER I, NETF
+      INTEGER*4 NOUT, LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNPE
+      INTEGER*4 LNLI, LNPS, LNCFL, MYPE, IER, NPES, METH, ITMETH
+      INTEGER*4 LLENRW, LLENIW, LLENRWLS, LLENIWLS
+      INTEGER*4 IATOL, ITASK, IPRE, IGS, JOUT
 C The following declaration specification should match C type long int.
       INTEGER*8 LENRWBBD, LENIWBBD, NGEBBD
-      INTEGER NST, NFE, NPSET, NPE, NPS, NNI, NLI, NCFN, NCFL
-      INTEGER LENRW, LENIW, LENRWLS, LENIWLS
+      INTEGER*8 NST, NFE, NPSET, NPE, NPS, NNI, NLI, NCFN, NCFL, NETF
+      INTEGER*8 LENRW, LENIW, LENRWLS, LENIWLS
       DOUBLE PRECISION Y(1024), ROUT(10), RPAR(1)
       DOUBLE PRECISION ALPHA, TOUT, ERMAX, AVDIM
       DOUBLE PRECISION ATOL, ERRI, RTOL, GERMAX, DTOUT, T
@@ -55,8 +51,8 @@ C     Get NPES and MYPE.  Requires initialization of MPI.
  7       FORMAT(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', I5)
          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
          STOP
-      ENDIF      
-C     
+      ENDIF
+C
 C     Set input arguments.
       NEQ = NPES * NLOCAL
       T = 0.0D0
@@ -97,6 +93,23 @@ C
          CALL MPI_FINALIZE(IER)
          STOP
       ENDIF
+C
+C     initialize SPGMR linear solver module
+      call FSUNSPGMRINIT(1, IPRE, 0, IER)
+      IF (IER .NE. 0) THEN
+         WRITE(6,25) IER
+ 25      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRINIT IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
+C
+      call FSUNSPGMRSETGSTYPE(1, IGS, IER)
+      IF (IER .NE. 0) THEN
+         WRITE(6,27) IER
+ 27      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETGSTYPE IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C     
       CALL FCVMALLOC(T, Y, METH, ITMETH, IATOL, RTOL, ATOL,
      &               IOUT, ROUT, IPAR, RPAR, IER)
@@ -108,10 +121,11 @@ C
          STOP
       ENDIF
 C
-      CALL FCVSPGMR(IPRE, IGS, 0, 0.0D0, IER)
+C     attach linear solver module to CVSpils interface
+      CALL FCVSPILSINIT(IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,36) IER
- 36      FORMAT(///' SUNDIALS_ERROR: FCVSPGMR returned IER = ', I5)
+         WRITE(6,32) IER
+ 32      FORMAT(///' SUNDIALS_ERROR: FCVSPILSINIT returned IER = ', I5)
          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
          STOP
       ENDIF
@@ -233,7 +247,7 @@ C
 C
       IPRE = 2
 C
-      CALL FCVBBDREINIT(NLOCAL, MUDQ, MLDQ, 0.0D0, IER) 
+      CALL FCVBBDREINIT(MUDQ, MLDQ, 0.0D0, IER) 
       IF (IER .NE. 0) THEN
          WRITE(6,92) IER
  92      FORMAT(///' SUNDIALS_ERROR: FCVBBDREINIT returned IER = ', I5)
@@ -241,10 +255,10 @@ C
          STOP
       ENDIF
 C
-      CALL FCVSPGMRREINIT(IPRE, IGS, 0.0D0, IER)
+      CALL FSUNSPGMRSETPRECTYPE(1, IPRE, IER)
       IF (IER .NE. 0) THEN
          WRITE(6,93) IER
- 93      FORMAT(///' SUNDIALS_ERROR: FCVSPGMRREINIT returned IER = ',I5)
+ 93      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETPRECTYPE IER = ',I5)
          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
          STOP
       ENDIF
@@ -267,11 +281,11 @@ C     Routine for right-hand side function f
       IMPLICIT NONE
 C
 C The following declaration specification should match C type long int.
-      INTEGER*8 IPAR(*)
-      INTEGER IER, MYPE, I, NLOCAL
+      INTEGER*8 IPAR(*), MYPE, I, NLOCAL
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
       DOUBLE PRECISION ALPHA
-C     
+C
       NLOCAL = IPAR(1)
       MYPE = IPAR(2)
       ALPHA = RPAR(1)
@@ -279,7 +293,7 @@ C
       DO I = 1, NLOCAL
          YDOT(I) = -ALPHA * (MYPE * NLOCAL + I) * Y(I)
       ENDDO
-C     
+C
       IER = 0
 C
       RETURN
@@ -293,18 +307,21 @@ C     Routine to define local approximate function g, here the same as f.
 C
 C The following declaration specification should match C type long int.
       INTEGER*8 NLOC, IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, YLOC(*), GLOC(*), RPAR(*)
-C     
+C
       CALL FCVFUN(T, YLOC, GLOC, IPAR, RPAR, IER)
 C
       RETURN
       END
 C
 C     ------------------------------------------------------------------------
-C      
+C
       SUBROUTINE FCVCOMMFN(NLOC, T, YLOC, IPAR, RPAR, IER)
 C     Routine to perform communication required for evaluation of g.
+      INTEGER*8 NLOC, IPAR(*)
+      INTEGER*4 IER
+      DOUBLE PRECISION T, YLOC(*), RPAR(*)
       IER = 0
       RETURN
       END
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.out b/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.out
index 71026bd..995d875 100644
--- a/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.out
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_bbd_p.out
@@ -1,44 +1,44 @@
 Diagonal test problem:
 
- NEQ =  40
+ NEQ =  20
  parameter alpha =   10.000
  ydot_i = -alpha*i * y_i (i = 1,...,NEQ)
  RTOL, ATOL =    0.1E-04   0.1E-09
  Method is BDF/NEWTON/SPGMR
  Preconditioner is band-block-diagonal, using CVBBDPRE
- Number of processors =   4
+ Number of processors =   2
 
 
 Preconditioning on left
 
- t =   0.10E+00     no. steps =   221   no. f-s =   262
- t =   0.20E+00     no. steps =   265   no. f-s =   308
- t =   0.30E+00     no. steps =   290   no. f-s =   334
- t =   0.40E+00     no. steps =   306   no. f-s =   351
- t =   0.50E+00     no. steps =   319   no. f-s =   365
- t =   0.60E+00     no. steps =   329   no. f-s =   375
- t =   0.70E+00     no. steps =   339   no. f-s =   386
- t =   0.80E+00     no. steps =   345   no. f-s =   392
- t =   0.90E+00     no. steps =   352   no. f-s =   399
- t =   0.10E+01     no. steps =   359   no. f-s =   406
+ t =   0.10E+00     no. steps =   174   no. f-s =   214
+ t =   0.20E+00     no. steps =   222   no. f-s =   263
+ t =   0.30E+00     no. steps =   247   no. f-s =   289
+ t =   0.40E+00     no. steps =   265   no. f-s =   308
+ t =   0.50E+00     no. steps =   278   no. f-s =   322
+ t =   0.60E+00     no. steps =   290   no. f-s =   334
+ t =   0.70E+00     no. steps =   300   no. f-s =   345
+ t =   0.80E+00     no. steps =   307   no. f-s =   352
+ t =   0.90E+00     no. steps =   312   no. f-s =   358
+ t =   0.10E+01     no. steps =   317   no. f-s =   363
 
-Max. absolute error is  0.28E-08
+Max. absolute error is  0.90E-08
 
 
 Final statistics:
 
- number of steps        =   359     number of f evals.     =   406
- number of prec. setups =    38
- number of prec. evals. =     7     number of prec. solves =   728
- number of nonl. iters. =   402     number of lin. iters.  =   364
- average Krylov subspace dimension (NLI/NNI) =   0.9055
+ number of steps        =   317     number of f evals.     =   363
+ number of prec. setups =    33
+ number of prec. evals. =     6     number of prec. solves =   644
+ number of nonl. iters. =   359     number of lin. iters.  =   322
+ average Krylov subspace dimension (NLI/NNI) =   0.8969
  number of conv. failures.. nonlinear =   0  linear =   0
  number of error test failures =   5
- main solver real/int workspace sizes   =   489  120
- linear solver real/int workspace sizes =   446   80
+ main solver real/int workspace sizes   =   289   80
+ linear solver real/int workspace sizes =   290   58
 In CVBBDPRE:
- real/int local workspace =    20   10
- number of g evals. =    14
+ real/int local workspace =   100   60
+ number of g evals. =    12
 
 
 ------------------------------------------------------------
@@ -46,31 +46,31 @@ In CVBBDPRE:
 
 Preconditioning on right
 
- t =   0.10E+00     no. steps =   221   no. f-s =   262
- t =   0.20E+00     no. steps =   265   no. f-s =   308
- t =   0.30E+00     no. steps =   290   no. f-s =   334
- t =   0.40E+00     no. steps =   306   no. f-s =   351
- t =   0.50E+00     no. steps =   319   no. f-s =   365
- t =   0.60E+00     no. steps =   329   no. f-s =   375
- t =   0.70E+00     no. steps =   339   no. f-s =   386
- t =   0.80E+00     no. steps =   345   no. f-s =   392
- t =   0.90E+00     no. steps =   352   no. f-s =   399
- t =   0.10E+01     no. steps =   359   no. f-s =   406
+ t =   0.10E+00     no. steps =   174   no. f-s =   214
+ t =   0.20E+00     no. steps =   222   no. f-s =   263
+ t =   0.30E+00     no. steps =   247   no. f-s =   289
+ t =   0.40E+00     no. steps =   265   no. f-s =   308
+ t =   0.50E+00     no. steps =   278   no. f-s =   322
+ t =   0.60E+00     no. steps =   290   no. f-s =   334
+ t =   0.70E+00     no. steps =   300   no. f-s =   345
+ t =   0.80E+00     no. steps =   307   no. f-s =   352
+ t =   0.90E+00     no. steps =   312   no. f-s =   358
+ t =   0.10E+01     no. steps =   317   no. f-s =   363
 
-Max. absolute error is  0.28E-08
+Max. absolute error is  0.90E-08
 
 
 Final statistics:
 
- number of steps        =   359     number of f evals.     =   406
- number of prec. setups =    38
- number of prec. evals. =     7     number of prec. solves =   728
- number of nonl. iters. =   402     number of lin. iters.  =   364
- average Krylov subspace dimension (NLI/NNI) =   0.9055
+ number of steps        =   317     number of f evals.     =   363
+ number of prec. setups =    33
+ number of prec. evals. =     6     number of prec. solves =   644
+ number of nonl. iters. =   359     number of lin. iters.  =   322
+ average Krylov subspace dimension (NLI/NNI) =   0.8969
  number of conv. failures.. nonlinear =   0  linear =   0
  number of error test failures =   5
- main solver real/int workspace sizes   =   489  120
- linear solver real/int workspace sizes =   446   80
+ main solver real/int workspace sizes   =   289   80
+ linear solver real/int workspace sizes =   290   58
 In CVBBDPRE:
- real/int local workspace =    20   10
- number of g evals. =    14
+ real/int local workspace =   100   60
+ number of g evals. =    12
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_kry_p.f b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.f
index 7decedc..7da8482 100644
--- a/examples/cvode/fcmix_parallel/fcvDiag_kry_p.f
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.f
@@ -1,27 +1,24 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4074 $
-C     $Date: 2014-04-23 14:13:52 -0700 (Wed, 23 Apr 2014) $
-C     ----------------------------------------------------------------
 C     Diagonal ODE example. Stiff case, with BDF/SPGMR, diagonal
 C     preconditioner. Solved with preconditioning on left, then with
 C     preconditioning on right.
 C     ----------------------------------------------------------------
 C
 C     Include MPI-Fortran header file for MPI_COMM_WORLD, MPI types.
-C
+
       IMPLICIT NONE
 C
       INCLUDE "mpif.h"
 C
 C The following declaration specification should match C type long int.
-      INTEGER*8 NLOCAL, NEQ, IOUT(25), IPAR(2)
+      INTEGER*8 NLOCAL, NEQ, I, IOUT(25), IPAR(2)
       PARAMETER (NLOCAL=10)
 C
-      INTEGER LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNPE, LNLI, LNPS
-      INTEGER LNCFL, NOUT, MYPE, NPES, IER, METH, ITMETH, IATOL
-      INTEGER ITASK, IPRE, IGS, JOUT
-      INTEGER I, NST, NFE, NPSET, NPE, NPS, NNI, NLI
-      INTEGER NCFL, NETF, NCFN
+      INTEGER*4 LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNPE, LNLI, LNPS
+      INTEGER*4 LNCFL, NOUT, MYPE, NPES, IER, METH, ITMETH, IATOL
+      INTEGER*4 ITASK, IPRE, IGS, JOUT
+      INTEGER*8 NST, NFE, NPSET, NPE, NPS, NNI, NLI
+      INTEGER*8 NCFL, NETF, NCFN
       DOUBLE PRECISION Y(1024), ROUT(10), RPAR(1)
       DOUBLE PRECISION ATOL, DTOUT, T, ALPHA, RTOL, TOUT, ERMAX, ERRI
       DOUBLE PRECISION GERMAX, AVDIM
@@ -33,24 +30,24 @@ C
 C     Get NPES and MYPE.  Requires initialization of MPI.
       CALL MPI_INIT(IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,5) IER
- 5      FORMAT(///' MPI_ERROR: MPI_INIT returned IER = ', I5)
-        STOP
-        ENDIF
+         WRITE(6,5) IER
+ 5       FORMAT(///' MPI_ERROR: MPI_INIT returned IER = ', I5)
+         STOP
+      ENDIF
       CALL MPI_COMM_SIZE(MPI_COMM_WORLD, NPES, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,6) IER
- 6      FORMAT(///' MPI_ERROR: MPI_COMM_SIZE returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,6) IER
+ 6       FORMAT(///' MPI_ERROR: MPI_COMM_SIZE returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
       CALL MPI_COMM_RANK(MPI_COMM_WORLD, MYPE, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,7) IER
- 7      FORMAT(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,7) IER
+ 7       FORMAT(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C
 C     Set input arguments.
       NEQ = NPES * NLOCAL
@@ -61,7 +58,7 @@ C     Set input arguments.
       ITASK = 1
       IPRE = 1
       IGS = 1
-C     Set parameter alpha.
+C     Set parameter alpha
       ALPHA  = 10.0D0
 C
 C     Load IPAR and RPAR
@@ -94,31 +91,50 @@ C
       CALL FNVINITP(MPI_COMM_WORLD, 1, NLOCAL, NEQ, IER)
 C
       IF (IER .NE. 0) THEN
-        WRITE(6,20) IER
-  20    FORMAT(///' SUNDIALS_ERROR: FNVINITP returned IER = ', I5)
-        CALL MPI_FINALIZE(IER)
-        STOP
-        ENDIF
+         WRITE(6,20) IER
+  20     FORMAT(///' SUNDIALS_ERROR: FNVINITP returned IER = ', I5)
+         CALL MPI_FINALIZE(IER)
+         STOP
+      ENDIF
+C
+C     initialize SPGMR linear solver module
+      call FSUNSPGMRINIT(1, IPRE, 0, IER)
+      IF (IER .NE. 0) THEN
+         WRITE(6,25) IER
+ 25      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRINIT IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
+C
+      call FSUNSPGMRSETGSTYPE(1, IGS, IER)
+      IF (IER .NE. 0) THEN
+         WRITE(6,27) IER
+ 27      FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETGSTYPE IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C
       CALL FCVMALLOC(T, Y, METH, ITMETH, IATOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
 C
       IF (IER .NE. 0) THEN
-        WRITE(6,30) IER
-  30    FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,30) IER
+  30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C
-      CALL FCVSPGMR (IPRE, IGS, 0, 0.0D0, IER)
+C     attach linear solver module to CVSpils interface
+      CALL FCVSPILSINIT(IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,35) IER
-  35    FORMAT(///' SUNDIALS_ERROR: FCVSPGMR returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
-C
-        CALL FCVSPILSSETPREC(1, IER)
+         WRITE(6,32) IER
+ 32      FORMAT(///' SUNDIALS_ERROR: FCVSPILSINIT returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
+C     
+C     attach preconditioner to CVSpils interface
+      CALL FCVSPILSSETPREC(1, IER)
 C
 C     Loop through tout values, call solver, print output, test for failure.
       TOUT = DTOUT
@@ -131,12 +147,12 @@ C
      &         '   no. f-s = ', I5)
 C
         IF (IER .NE. 0) THEN
-          WRITE(6,60) IER, IOUT(15)
-  60      FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
-     &           '                 Linear Solver returned IER = ', I5)
-          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-          STOP
-          ENDIF
+           WRITE(6,60) IER, IOUT(15)
+  60       FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+     &            '                 Linear Solver returned IER = ', I5)
+           CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+           STOP
+        ENDIF
 C
         TOUT = TOUT + DTOUT
   70    CONTINUE
@@ -150,11 +166,11 @@ C     Get global max. error from MPI_REDUCE call.
       CALL MPI_REDUCE(ERMAX, GERMAX, 1, MPI_DOUBLE_PRECISION, MPI_MAX,
      1                0, MPI_COMM_WORLD, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,80) IER
-  80    FORMAT(///' MPI_ERROR: MPI_REDUCE returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,80) IER
+  80     FORMAT(///' MPI_ERROR: MPI_REDUCE returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
       IF (MYPE .EQ. 0) WRITE(6,85) GERMAX
   85  FORMAT(/'Max. absolute error is ', E10.2/)
 C
@@ -198,16 +214,16 @@ C
       CALL FCVREINIT(T, Y, IATOL, RTOL, ATOL, IER)
 C
       IF (IER .NE. 0) THEN
-        WRITE(6,130) IER
- 130    FORMAT(///' SUNDIALS_ERROR: FCVREINIT returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
+         WRITE(6,130) IER
+ 130     FORMAT(///' SUNDIALS_ERROR: FCVREINIT returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
       ENDIF
 C
-      CALL FCVSPGMRREINIT (IPRE, IGS, 0.0D0, IER)
+      CALL FSUNSPGMRSETPRECTYPE(1, IPRE, IER)
       IF (IER .NE. 0) THEN
          WRITE(6,140) IER
- 140     FORMAT(///' SUNDIALS_ERROR: FCVSPGMRREINIT returned IER = ',I5)
+ 140     FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETPRECTYPE IER = ',I5)
          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
          STOP
       ENDIF
@@ -221,10 +237,10 @@ C
         IF (MYPE .EQ. 0) WRITE(6,40) T, IOUT(LNST), IOUT(LNFE)
 C
         IF (IER .NE. 0) THEN
-          WRITE(6,60) IER
-          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-          STOP
-          ENDIF
+           WRITE(6,60) IER
+           CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+           STOP
+        ENDIF
 C
         TOUT = TOUT + DTOUT
  170    CONTINUE
@@ -238,9 +254,9 @@ C     Get global max. error from MPI_REDUCE call.
       CALL MPI_REDUCE(ERMAX, GERMAX, 1, MPI_DOUBLE_PRECISION, MPI_MAX,
      1                0, MPI_COMM_WORLD, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,80) IER
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
+         WRITE(6,80) IER
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
       ENDIF
       IF (MYPE .EQ. 0) WRITE(6,85) GERMAX
 C     
@@ -264,10 +280,10 @@ C     Free the memory and finalize MPI.
       CALL FCVFREE
       CALL MPI_FINALIZE(IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,195) IER
- 195    FORMAT(///' MPI_ERROR: MPI_FINALIZE returned IER = ', I5)
-        STOP
-        ENDIF
+         WRITE(6,195) IER
+ 195     FORMAT(///' MPI_ERROR: MPI_FINALIZE returned IER = ', I5)
+         STOP
+      ENDIF
 C
       STOP
       END
@@ -279,8 +295,8 @@ C     Routine for right-hand side function f
       IMPLICIT NONE
 C
 C The following declaration specification should match C type long int.
-      INTEGER*8 IPAR(*)
-      INTEGER IER, I, MYPE, NLOCAL
+      INTEGER*8 IPAR(*), MYPE, I, NLOCAL
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
       DOUBLE PRECISION ALPHA
 C
@@ -300,7 +316,7 @@ C
 C     ------------------------------------------------------------------------
 C
       SUBROUTINE FCVPSOL(T, Y, FY, R, Z, GAMMA, DELTA, LR,
-     &                   IPAR, RPAR, VTEMP, IER)
+     &                   IPAR, RPAR, IER)
 C     Routine to solve preconditioner linear system
 C     This routine uses a diagonal preconditioner P = I - gamma*J,
 C     where J is a diagonal approximation to the true Jacobian, given by:
@@ -310,11 +326,10 @@ C     local vector segment) is applied to the vector z.
       IMPLICIT NONE
 C
 C The following declaration specification should match C type long int.
-      INTEGER*8 IPAR(*)
-      INTEGER IER, LR, I, MYPE, NLOCAL, ISTART, IBASE 
+      INTEGER*8 IPAR(*), NLOCAL, I, MYPE, ISTART, IBASE
+      INTEGER*4 IER, LR
       DOUBLE PRECISION T, Y(*), FY(*), R(*), Z(*)
       DOUBLE PRECISION GAMMA, DELTA, RPAR(*)
-      DOUBLE PRECISION VTEMP(*)
       DOUBLE PRECISION PSUBI, ALPHA
 C
       NLOCAL = IPAR(1)
@@ -328,8 +343,8 @@ C
       IBASE = MYPE * NLOCAL
       ISTART = MAX(1, 4 - IBASE)
       DO I = ISTART, NLOCAL
-        PSUBI = 1.0D0 + GAMMA * ALPHA * (IBASE + I)
-        Z(I) = Z(I) / PSUBI
+         PSUBI = 1.0D0 + GAMMA * ALPHA * (IBASE + I)
+         Z(I) = Z(I) / PSUBI
       ENDDO
 C
       RETURN
@@ -338,8 +353,15 @@ C
 C     ------------------------------------------------------------------------
 C
       SUBROUTINE FCVPSET(T, Y, FY, JOK, JCUR, GAMMA, H,
-     &                   IPAR, RPAR, V1, V2, V3, IER)
+     &                   IPAR, RPAR, IER)
 C     Empty subroutine. Not needed for the preconditioner, but required
 C     by the FCVODE module.
+      INTEGER*4 IER, JOK, JCUR
+      DOUBLE PRECISION T, Y(*), FY(*), GAMMA, H
+C The following declaration specification should match C type long int
+      INTEGER*8 IPAR(*)
+      DOUBLE PRECISION RPAR(*)
+
+      IER = 0
       RETURN
       END
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_kry_p.out b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.out
index 6d37524..8c6ac76 100644
--- a/examples/cvode/fcmix_parallel/fcvDiag_kry_p.out
+++ b/examples/cvode/fcmix_parallel/fcvDiag_kry_p.out
@@ -1,36 +1,36 @@
 Diagonal test problem:
 
- NEQ =  40 parameter alpha =   10.000
+ NEQ =  20 parameter alpha =   10.000
  ydot_i = -alpha*i * y_i (i = 1,...,NEQ)
  RTOL, ATOL =    0.1E-04   0.1E-09
  Method is BDF/NEWTON/SPGMR
  Diagonal preconditioner uses approximate Jacobian
- Number of processors =   4
+ Number of processors =   2
 
 
 Preconditioning on left
 
- t =   0.10E+00     no. steps =   221   no. f-s =   262
- t =   0.20E+00     no. steps =   265   no. f-s =   308
- t =   0.30E+00     no. steps =   290   no. f-s =   334
- t =   0.40E+00     no. steps =   306   no. f-s =   351
- t =   0.50E+00     no. steps =   319   no. f-s =   365
- t =   0.60E+00     no. steps =   329   no. f-s =   375
- t =   0.70E+00     no. steps =   339   no. f-s =   385
- t =   0.80E+00     no. steps =   346   no. f-s =   393
- t =   0.90E+00     no. steps =   351   no. f-s =   400
- t =   0.10E+01     no. steps =   355   no. f-s =   404
+ t =   0.10E+00     no. steps =   174   no. f-s =   214
+ t =   0.20E+00     no. steps =   222   no. f-s =   263
+ t =   0.30E+00     no. steps =   247   no. f-s =   289
+ t =   0.40E+00     no. steps =   265   no. f-s =   308
+ t =   0.50E+00     no. steps =   279   no. f-s =   323
+ t =   0.60E+00     no. steps =   290   no. f-s =   334
+ t =   0.70E+00     no. steps =   300   no. f-s =   345
+ t =   0.80E+00     no. steps =   307   no. f-s =   352
+ t =   0.90E+00     no. steps =   312   no. f-s =   358
+ t =   0.10E+01     no. steps =   317   no. f-s =   363
 
-Max. absolute error is   0.15E-07
+Max. absolute error is   0.76E-08
 
 
 Final statistics:
 
- number of steps        =   355     number of f evals.     =  404
- number of prec. setups =    37
- number of prec. evals. =     7     number of prec. solves =   727
- number of nonl. iters. =   400     number of lin. iters.  =   367
- average Krylov subspace dimension (NLI/NNI)  =   0.9175
+ number of steps        =   317     number of f evals.     =  363
+ number of prec. setups =    33
+ number of prec. evals. =     6     number of prec. solves =   649
+ number of nonl. iters. =   359     number of lin. iters.  =   327
+ average Krylov subspace dimension (NLI/NNI)  =   0.9109
  number of conv. failures.. nonlinear =   0  linear =   0
  number of error test failures =   5
 
@@ -40,26 +40,26 @@ Final statistics:
 
 Preconditioning on right
 
- t =   0.10E+00     no. steps =   221   no. f-s =   262
- t =   0.20E+00     no. steps =   265   no. f-s =   308
- t =   0.30E+00     no. steps =   290   no. f-s =   334
- t =   0.40E+00     no. steps =   306   no. f-s =   351
- t =   0.50E+00     no. steps =   319   no. f-s =   365
- t =   0.60E+00     no. steps =   329   no. f-s =   375
- t =   0.70E+00     no. steps =   339   no. f-s =   385
- t =   0.80E+00     no. steps =   345   no. f-s =   392
- t =   0.90E+00     no. steps =   352   no. f-s =   399
- t =   0.10E+01     no. steps =   358   no. f-s =   405
+ t =   0.10E+00     no. steps =   174   no. f-s =   214
+ t =   0.20E+00     no. steps =   222   no. f-s =   263
+ t =   0.30E+00     no. steps =   247   no. f-s =   289
+ t =   0.40E+00     no. steps =   265   no. f-s =   308
+ t =   0.50E+00     no. steps =   279   no. f-s =   323
+ t =   0.60E+00     no. steps =   290   no. f-s =   334
+ t =   0.70E+00     no. steps =   300   no. f-s =   345
+ t =   0.80E+00     no. steps =   307   no. f-s =   352
+ t =   0.90E+00     no. steps =   312   no. f-s =   358
+ t =   0.10E+01     no. steps =   317   no. f-s =   363
 
-Max. absolute error is   0.21E-08
+Max. absolute error is   0.77E-08
 
 
 Final statistics:
 
- number of steps        =   358     number of f evals.     =  405
- number of prec. setups =    36
- number of prec. evals. =     6     number of prec. solves =   730
- number of nonl. iters. =   401     number of lin. iters.  =   367
- average Krylov subspace dimension (NLI/NNI)  =   0.9152
+ number of steps        =   317     number of f evals.     =  363
+ number of prec. setups =    33
+ number of prec. evals. =     6     number of prec. solves =   649
+ number of nonl. iters. =   359     number of lin. iters.  =   327
+ average Krylov subspace dimension (NLI/NNI)  =   0.9109
  number of conv. failures.. nonlinear =   0  linear =   0
  number of error test failures =   5
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_non_p.f b/examples/cvode/fcmix_parallel/fcvDiag_non_p.f
index 59fdf85..f896c39 100644
--- a/examples/cvode/fcmix_parallel/fcvDiag_non_p.f
+++ b/examples/cvode/fcmix_parallel/fcvDiag_non_p.f
@@ -1,7 +1,4 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4074 $
-C     $Date: 2014-04-23 14:13:52 -0700 (Wed, 23 Apr 2014) $
-C     ----------------------------------------------------------------
 C     Diagonal ODE example. Nonstiff case: alpha = 10/NEQ.
 C     ----------------------------------------------------------------
 C
@@ -12,12 +9,12 @@ C
       INCLUDE "mpif.h"
 C
 C The following declaration specification should match C type long int.
-      INTEGER*8 NLOCAL, NEQ, IOUT(25), IPAR(2)
+      INTEGER*8 NLOCAL, NEQ, I, IOUT(25), IPAR(2)
       PARAMETER (NLOCAL=2)
 C
-      INTEGER IER, MYPE, NPES, NOUT, LNST, LNFE, LNNI, LNCF, LNETF
-      INTEGER METH, ITMETH, IATOL, ITASK, JOUT
-      INTEGER I, NST, NFE, NNI, NCFN, NETF
+      INTEGER*4 IER, MYPE, NPES, NOUT, LNST, LNFE, LNNI, LNCF, LNETF
+      INTEGER*4 METH, ITMETH, IATOL, ITASK, JOUT
+      INTEGER*8 NST, NFE, NNI, NCFN, NETF
       DOUBLE PRECISION Y(128), ROUT(10), RPAR(1)
       DOUBLE PRECISION ATOL, RTOL, DTOUT, T, ALPHA, TOUT
       DOUBLE PRECISION ERMAX, ERRI, GERMAX
@@ -28,24 +25,24 @@ C
 C     Get NPES and MYPE.  Requires initialization of MPI.
       CALL MPI_INIT(IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,5) IER
- 5      FORMAT(///' MPI_ERROR: MPI_INIT returned IER = ', I5)
-        STOP
-        ENDIF
+         WRITE(6,5) IER
+ 5       FORMAT(///' MPI_ERROR: MPI_INIT returned IER = ', I5)
+         STOP
+      ENDIF
       CALL MPI_COMM_SIZE(MPI_COMM_WORLD, NPES, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,6) IER
- 6      FORMAT(///' MPI_ERROR: MPI_COMM_SIZE returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,6) IER
+ 6       FORMAT(///' MPI_ERROR: MPI_COMM_SIZE returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
       CALL MPI_COMM_RANK(MPI_COMM_WORLD, MYPE, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,7) IER
- 7      FORMAT(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,7) IER
+ 7       FORMAT(///' MPI_ERROR: MPI_COMM_RANK returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C
 C     Set input arguments.
       NEQ = NPES * NLOCAL
@@ -66,37 +63,37 @@ C
   10    Y(I) = 1.0D0
 C
       IF (MYPE .EQ. 0) THEN
-        WRITE(6,11) NEQ, ALPHA
-  11    FORMAT('Diagonal test problem:'//' NEQ = ', I3, /
-     1         ' parameter alpha = ', F8.3)
-        WRITE(6,12)
-  12    FORMAT(' ydot_i = -alpha*i * y_i (i = 1,...,NEQ)')
-        WRITE(6,13) RTOL, ATOL
-  13    FORMAT(' RTOL, ATOL = ', 2E10.1)
-        WRITE(6,14)
-  14    FORMAT(' Method is ADAMS/FUNCTIONAL')
-        WRITE(6,15) NPES
-  15    FORMAT(' Number of processors = ', I3//)
-        ENDIF
+         WRITE(6,11) NEQ, ALPHA
+  11     FORMAT('Diagonal test problem:'//' NEQ = ', I3, /
+     1          ' parameter alpha = ', F8.3)
+         WRITE(6,12)
+  12     FORMAT(' ydot_i = -alpha*i * y_i (i = 1,...,NEQ)')
+         WRITE(6,13) RTOL, ATOL
+  13     FORMAT(' RTOL, ATOL = ', 2E10.1)
+         WRITE(6,14)
+  14     FORMAT(' Method is ADAMS/FUNCTIONAL')
+         WRITE(6,15) NPES
+  15     FORMAT(' Number of processors = ', I3//)
+      ENDIF
 C
       CALL FNVINITP(MPI_COMM_WORLD, 1, NLOCAL, NEQ, IER)
 C
       IF (IER .NE. 0) THEN
-        WRITE(6,20) IER
-  20    FORMAT(///' SUNDIALS_ERROR: FNVINITP returned IER = ', I5)
-        CALL MPI_FINALIZE(IER)
-        STOP
-        ENDIF
+         WRITE(6,20) IER
+  20     FORMAT(///' SUNDIALS_ERROR: FNVINITP returned IER = ', I5)
+         CALL MPI_FINALIZE(IER)
+         STOP
+      ENDIF
 C
       CALL FCVMALLOC(T, Y, METH, ITMETH, IATOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
 C
       IF (IER .NE. 0) THEN
-        WRITE(6,30) IER
-  30    FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,30) IER
+  30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
 C
 C     Loop through tout values, call solver, print output, test for failure.
       TOUT = DTOUT
@@ -109,12 +106,12 @@ C
      &         '   no. f-s = ', I5)
 C
         IF (IER .NE. 0) THEN
-          WRITE(6,60) IER, IOUT(15)
-  60      FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
-     &           '                 Linear Solver returned IER = ', I5)
-          CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-          STOP
-          ENDIF
+           WRITE(6,60) IER, IOUT(15)
+  60       FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+     &            '                 Linear Solver returned IER = ', I5)
+           CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+           STOP
+        ENDIF
 C
         TOUT = TOUT + DTOUT
   70    CONTINUE
@@ -129,11 +126,11 @@ C     Get global max. error from MPI_REDUCE call.
       CALL MPI_REDUCE(ERMAX, GERMAX, 1, MPI_DOUBLE_PRECISION, MPI_MAX,
      1                0, MPI_COMM_WORLD, IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,80) IER
-  80    FORMAT(///' MPI_ERROR: MPI_REDUCE returned IER = ', I5)
-        CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
-        STOP
-        ENDIF
+         WRITE(6,80) IER
+  80     FORMAT(///' MPI_ERROR: MPI_REDUCE returned IER = ', I5)
+         CALL MPI_ABORT(MPI_COMM_WORLD, 1, IER)
+         STOP
+      ENDIF
       IF (MYPE .EQ. 0) WRITE(6,85) GERMAX
   85  FORMAT(/'Max. absolute error is ', E10.2/)
 C
@@ -155,10 +152,10 @@ C     Free the memory and finalize MPI.
       CALL FCVFREE
       CALL MPI_FINALIZE(IER)
       IF (IER .NE. 0) THEN
-        WRITE(6,95) IER
- 95     FORMAT(///' MPI_ERROR: MPI_FINALIZE returned IER = ', I5)
-        STOP
-        ENDIF
+         WRITE(6,95) IER
+ 95      FORMAT(///' MPI_ERROR: MPI_FINALIZE returned IER = ', I5)
+         STOP
+      ENDIF
 C
       STOP
       END
@@ -171,8 +168,8 @@ C
       IMPLICIT NONE
 C
 C The following declaration specification should match C type long int.
-      INTEGER*8 IPAR(*)
-      INTEGER IER, MYPE, NLOCAL, I
+      INTEGER*8 IPAR(*), MYPE, I, NLOCAL
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
       DOUBLE PRECISION ALPHA
 C
diff --git a/examples/cvode/fcmix_parallel/fcvDiag_non_p.out b/examples/cvode/fcmix_parallel/fcvDiag_non_p.out
index 461a677..01c5940 100644
--- a/examples/cvode/fcmix_parallel/fcvDiag_non_p.out
+++ b/examples/cvode/fcmix_parallel/fcvDiag_non_p.out
@@ -1,31 +1,31 @@
 Diagonal test problem:
 
- NEQ =   8
- parameter alpha =    1.250
+ NEQ =   4
+ parameter alpha =    2.500
  ydot_i = -alpha*i * y_i (i = 1,...,NEQ)
  RTOL, ATOL =    0.1E-04   0.1E-09
  Method is ADAMS/FUNCTIONAL
- Number of processors =   4
+ Number of processors =   2
 
 
- t =   0.10D+00     no. steps =    14   no. f-s =    32
+ t =   0.10D+00     no. steps =    15   no. f-s =    33
  t =   0.20D+00     no. steps =    22   no. f-s =    40
- t =   0.30D+00     no. steps =    29   no. f-s =    47
- t =   0.40D+00     no. steps =    37   no. f-s =    55
- t =   0.50D+00     no. steps =    44   no. f-s =    62
- t =   0.60D+00     no. steps =    51   no. f-s =    69
- t =   0.70D+00     no. steps =    59   no. f-s =    78
- t =   0.80D+00     no. steps =    66   no. f-s =    85
- t =   0.90D+00     no. steps =    74   no. f-s =    93
- t =   0.10D+01     no. steps =    81   no. f-s =   100
+ t =   0.30D+00     no. steps =    30   no. f-s =    48
+ t =   0.40D+00     no. steps =    38   no. f-s =    56
+ t =   0.50D+00     no. steps =    46   no. f-s =    64
+ t =   0.60D+00     no. steps =    54   no. f-s =    72
+ t =   0.70D+00     no. steps =    61   no. f-s =    79
+ t =   0.80D+00     no. steps =    69   no. f-s =    87
+ t =   0.90D+00     no. steps =    77   no. f-s =    95
+ t =   0.10D+01     no. steps =    85   no. f-s =   103
 
-Max. absolute error is   0.41E-07
+Max. absolute error is   0.33E-07
 
 
 Final statistics:
 
- number of steps =    81
- number of f evals. =   100
- number of nonlinear iters. =    96
+ number of steps =    85
+ number of f evals. =   103
+ number of nonlinear iters. =    99
  number of nonlinear conv. failures =   0
  number of error test failures =   3
diff --git a/examples/cvode/fcmix_serial/CMakeLists.txt b/examples/cvode/fcmix_serial/CMakeLists.txt
index cde8e0a..ca399c1 100644
--- a/examples/cvode/fcmix_serial/CMakeLists.txt
+++ b/examples/cvode/fcmix_serial/CMakeLists.txt
@@ -1,8 +1,6 @@
 # ---------------------------------------------------------------
-# $Revision: 4957 $
-# $Date: 2016-09-23 12:21:47 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
@@ -15,122 +13,247 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the FCVODE serial examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
-# Add variable FCVODE_examples with the names of the serial FCVODE examples
-
+# Examples using SUNDIALS linear solvers
 SET(FCVODE_examples
-  fcvAdvDiff_bnd
-  fcvDiurnal_kry_bp
-  fcvDiurnal_kry
-  fcvRoberts_dns
+  "fcvAdvDiff_bnd\;develop"
+  "fcvDiurnal_kry_bp\;develop"
+  "fcvDiurnal_kry\;develop"
+  "fcvRoberts_dns\;develop"
   )
 
-SET(FCVODE_examples_KLU
-  fcvRoberts_klu
+# Examples using LAPACK linear solvers
+SET(FCVODE_examples_BL
+  "fcvRoberts_dnsL\;develop"
   )
 
-SET(FCVODE_examples_SUPERLUMT
-  fcvRoberts_sps
-  )
+# Add sparse solvers examples for 64-bit indextype configurations only,
+# not compatible with 32-bit indextype
+IF(SUNDIALS_INDEX_TYPE MATCHES "INT64_T")
 
-# Add variable fcvode_bl_examples with the names of the serial FCVODE examples
-# that use Lapack
+  # Examples using KLU linear solver
+  SET(FCVODE_examples_KLU
+    "fcvRoberts_klu\;develop"
+    )
 
-SET(FCVODE_examples_BL
-  fcvRoberts_dnsL
-  )
+  # Examples using SuperLU_MT linear solver
+  SET(FCVODE_examples_SUPERLUMT
+    "fcvRoberts_sps\;develop"
+    )
+
+ENDIF()
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODE_LIB sundials_cvode_static)
   SET(NVECS_LIB sundials_nvecserial_static)
   SET(FNVECS_LIB sundials_fnvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODE_LIB sundials_cvode_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
   SET(FNVECS_LIB sundials_fnvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FCVODE_LIB sundials_fcvode_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FCVODE_LIB} ${CVODE_LIB} ${FNVECS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-IF(HYPRE_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${HYPRE_LIBRARIES})
-ENDIF(HYPRE_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FCVODE_examples})
 
-# Add the build and install targets for each FCVODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${FCVODE_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+   # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${FCVODE_examples})
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${FCVODE_examples})
 
-# Add the build and install targets for each Lapack FCVODE example (if needed)
 
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${FCVODE_examples_BL})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static
+      sundials_fsunlinsollapackband_static
+      sundials_fsunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared
+      sundials_fsunlinsollapackband_shared
+      sundials_fsunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${FCVODE_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.f)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+     # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FCVODE_examples_BL})
+      INSTALL(FILES ${example}.f ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FCVODE_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If KLU support is enabled, add the build and install targets for
-# the examples using KLU
+
+# Add the build and install targets for each KLU example (if needed)
 IF(KLU_FOUND)
-  FOREACH(example ${FCVODE_examples_KLU})
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS
+      sundials_sunlinsolklu_static
+      sundials_fsunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS
+      sundials_sunlinsolklu_shared
+      sundials_fsunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${FCVODE_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.f)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+     # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FCVODE_examples_KLU})
+      INSTALL(FILES ${example}.f ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FCVODE_examples_KLU})
+
 ENDIF(KLU_FOUND)
 
-# If SUPERLUMT support is enabled, add the build and install targets for
-# the examples using SUPERLUMT
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
 IF(SUPERLUMT_FOUND)
-  FOREACH(example ${FCVODE_examples_SUPERLUMT})
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS
+      sundials_sunlinsolsuperlumt_static
+      sundials_fsunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS
+      sundials_sunlinsolsuperlumt_shared
+      sundials_fsunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${FCVODE_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.f)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+     # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FCVODE_examples_SUPERLUMT})
+      INSTALL(FILES ${example}.f ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/fcmix_serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${FCVODE_examples_SUPERLUMT})
+
 ENDIF(SUPERLUMT_FOUND)
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -140,31 +263,37 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "CVODE")
   SET(SOLVER_LIB "sundials_cvode")
   SET(SOLVER_FLIB "sundials_fcvode")
-  LIST2STRING(FCVODE_examples EXAMPLES)
+
+  EXAMPLES2STRING(FCVODE_examples EXAMPLES)
+
   IF(LAPACK_FOUND)
-    LIST2STRING(FCVODE_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(FCVODE_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
-  
+  ENDIF()
+
   IF(KLU_FOUND)
-    LIST2STRING(FCVODE_examples_KLU EXAMPLES)
-  ENDIF(KLU_FOUND)
-  
+    EXAMPLES2STRING(FCVODE_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
+
   IF(SUPERLUMT_FOUND)
-    LIST2STRING(FCVODE_examples_SUPERLUMT EXAMPLES)
-  ENDIF(SUPERLUMT_FOUND)
-  
+    EXAMPLES2STRING(FCVODE_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
+
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/fcmix_serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/cvode/fcmix_serial/README b/examples/cvode/fcmix_serial/README
index 26be76c..7cce596 100644
--- a/examples/cvode/fcmix_serial/README
+++ b/examples/cvode/fcmix_serial/README
@@ -5,13 +5,14 @@ List of serial CVODE FCMIX examples
   fcvDiurnal_kry     : kinetics-transport example (BDF/SPGMR/User Prec)
   fcvRoberts_dns     : chemical kinetics example (BDF/DENSE)
   fcvRoberts_dnsL    : chemical kinetics example (BDF/DENSE lapack)
+  fcvRoberts_klu     : dense kinetics example with KLU sparse linear solver
+  fcvRoberts_sps     : dense kinetics example with SuperLUMT sparse solver
 
 
 The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -22,7 +23,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -36,7 +40,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f b/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f
index dd4ac45..ce154cb 100644
--- a/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f
+++ b/examples/cvode/fcmix_serial/fcvAdvDiff_bnd.f
@@ -1,9 +1,6 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4294 $
-C     $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
-C     ----------------------------------------------------------------
-C     FCVODE Example Problem: Advection-diffusion, banded user
-C     Jacobian.
+C     FCVODE Example Problem: Advection-diffusion, band linear solver
+C                             with banded user Jacobian.
 C
 C     The following is a simple example problem with a banded
 C     Jacobian. The problem is the semi-discrete form of the
@@ -25,15 +22,15 @@ C     ----------------------------------------------------------------
 C
       IMPLICIT NONE
 C
-      INTEGER MX, MY, MXMY
+      INTEGER*4 MX, MY, MXMY
       PARAMETER (MX=10, MY=5)
       PARAMETER (MXMY=MX*MY)
 C     
       DOUBLE PRECISION XMAX, YMAX
       DATA XMAX/2.0D0/, YMAX/1.0D0/
 C
-      INTEGER LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE
-      INTEGER IER, METH, ITMETH, IATOL, ITASK, JOUT
+      INTEGER*4 LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE
+      INTEGER*4 IER, METH, ITMETH, IATOL, ITASK, JOUT
 C The following declaration specification should match C type long int.
       INTEGER*8 NEQ, IOUT(25), IPAR(2), MU, ML
       DOUBLE PRECISION RTOL, ATOL, T0, T, TOUT, DTOUT, UNORM 
@@ -67,27 +64,50 @@ C
         STOP
       ENDIF
 C
+C     initialize banded matrix module
+      call FSUNBANDMATINIT(1, NEQ, MU, ML, MU+ML, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNBANDEMATINIT IER = ', I5)
+        STOP
+      ENDIF
+C
+C     initialize banded linear solver module
+      call FSUNBANDLINSOLINIT(1, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,28) IER
+ 28     FORMAT(///' SUNDIALS_ERROR: FSUNBANDLINSOLINIT IER = ', I5)
+        STOP
+      ENDIF
+C
       CALL FCVMALLOC(T0, U, METH, ITMETH, IATOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
       IF (IER .NE. 0) THEN
         WRITE(6,30) IER
  30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
         STOP
-        ENDIF
+      ENDIF
 C
-      CALL FCVBAND(NEQ, MU, ML, IER)
+C     attach matrix and linear solver modules to CVDls interface
+      CALL FCVDLSINIT(IER)
       IF (IER .NE. 0) THEN
         WRITE(6,40) IER
- 40     FORMAT(///' SUNDIALS_ERROR: FCVBAND returned IER = ', I5)
+ 40     FORMAT(///' SUNDIALS_ERROR: FCVDLSINIT returned IER = ',I5)
         CALL FCVFREE
         STOP
       ENDIF
 C
       CALL FCVBANDSETJAC(1, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,45) IER
+ 45     FORMAT(///' SUNDIALS_ERROR: FCVDENSESETJAC returned IER = ',I5)
+        CALL FCVFREE
+        STOP
+      ENDIF
 C
       CALL MAXNORM(NEQ, U, UNORM)
-      WRITE(6,45) T0, UNORM
- 45   FORMAT(' At t = ', F6.2, '  max.norm(u) = ', E14.6)
+      WRITE(6,48) T0, UNORM
+ 48   FORMAT(' At t = ', F6.2, '  max.norm(u) = ', E14.6)
 C
       TOUT = DTOUT
       DO 70 JOUT = 1, 10
@@ -132,10 +152,10 @@ C Load IPAR and RPAR with problem constants and U0 with initial values
 C
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
-      INTEGER MX, MY
+      INTEGER*4 MX, MY
       DOUBLE PRECISION XMAX, YMAX, U0(MY,MX), RPAR(*)
 C
-      INTEGER I, J
+      INTEGER*4 I, J
       DOUBLE PRECISION DX, DY, X, Y, HDCOEF, HACOEF, VDCOEF
 C
 C Problem constants
@@ -190,9 +210,9 @@ C
       DOUBLE PRECISION T, U(*), UDOT(*), RPAR(*)
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
 C
-      INTEGER I, MX, IOFF, MY, J, IJ
+      INTEGER*4 I, MX, IOFF, MY, J, IJ
       DOUBLE PRECISION UIJ, UDN, UUP, ULT, URT, HDIFF, HADV, VDIFF
       DOUBLE PRECISION DX, DY, HDCOEF, HACOEF, VDCOEF
 C
@@ -244,12 +264,12 @@ C Load banded Jacobian
 C
 C The following declaration specification should match C type long int.
       INTEGER*8 N, MU, ML, MDIM, IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, U(*), FU(*), BJAC(MDIM,*), H, RPAR(*)
       DOUBLE PRECISION V1(*), V2(*), V3(*)
 C
-      INTEGER MBAND, MX, MY
-      INTEGER I, J, K, IOFF, MU1, MU2
+      INTEGER*4 MBAND, MX, MY
+      INTEGER*4 I, J, K, IOFF, MU1, MU2
       DOUBLE PRECISION DX, DY, HDCOEF, HACOEF, VDCOEF
 C
 C Extract constants from IPAR and RPAR
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry.f b/examples/cvode/fcmix_serial/fcvDiurnal_kry.f
index e823741..a13b514 100644
--- a/examples/cvode/fcmix_serial/fcvDiurnal_kry.f
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry.f
@@ -1,7 +1,4 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4838 $
-C     $Date: 2016-08-03 10:10:51 -0700 (Wed, 03 Aug 2016) $
-C     ----------------------------------------------------------------
 C     FCVODE Example Problem: 2D kinetics-transport, precond. Krylov
 C     solver. 
 C     
@@ -20,6 +17,7 @@ C     The problem is posed on the square
 C     0 .le. x .le. 20,    30 .le. y .le. 50   (all in km),
 C     with homogeneous Neumann boundary conditions, and for time t
 C     in 0 .le. t .le. 86400 sec (1 day).
+C
 C     The PDE system is treated by central differences on a uniform
 C     10 x 10 mesh, with simple polynomial initial profiles.
 C     The problem is solved with CVODE, with the BDF/GMRES method and
@@ -31,24 +29,23 @@ C     of the dense linear solver routines DGEFA and DGESL from LINPACK,
 C     and BLAS routines DCOPY and DSCAL.
 C     
 C     The second and third dimensions of U here must match the values
-C     of MX and MY, for consistency with the output statements
-C     below.
+C     of MX and MY, for consistency with the output statements below.
 C     ----------------------------------------------------------------
 C
       IMPLICIT NONE
 C
-      INTEGER MX, MY
+      INTEGER*4 MX, MY
       PARAMETER (MX=10, MY=10)
-      INTEGER LENIPAR, LENRPAR
+      INTEGER*4 LENIPAR, LENRPAR
       PARAMETER (LENIPAR=6+2*MX*MY, LENRPAR=12+8*MX*MY)
 C
-      INTEGER METH,ITMETH,IATOL,ITASK,IER,LNCFL,LNPS
-      INTEGER LNST,LNFE,LNSETUP,LNNI,LNCF,LQ,LH,LNPE,LNLI,LNETF
-      INTEGER JOUT,JPRETYPE,IGSTYPE,MAXL
+      INTEGER*4 METH,ITMETH,IATOL,ITASK,IER,LNCFL,LNPS
+      INTEGER*4 LNST,LNFE,LNSETUP,LNNI,LNCF,LQ,LH,LNPE,LNLI,LNETF
+      INTEGER*4 JOUT,JPRETYPE,IGSTYPE,MAXL
 C The following declaration specification should match C type long int.
       INTEGER*8 NEQ, IOUT(25), IPAR(LENIPAR)
-      INTEGER NST,NFE,NPSET,NPE,NPS,NNI,NETF
-      INTEGER NLI,NCFN,NCFL
+      INTEGER*4 NST,NFE,NPSET,NPE,NPS,NNI,NETF
+      INTEGER*4 NLI,NCFN,NCFL
       DOUBLE PRECISION ATOL,AVDIM,T,TOUT,TWOHR,RTOL,FLOOR,DELT
       DOUBLE PRECISION U(2,MX,MY),ROUT(10),RPAR(LENRPAR)
 C
@@ -74,6 +71,7 @@ C
  10   FORMAT('Krylov example problem:'//
      &       ' Kinetics-transport, NEQ = ', I4/)
 C
+C     Initialize vector specification
       CALL FNVINITS(1, NEQ, IER)
       IF (IER .NE. 0) THEN
         WRITE(6,20) IER
@@ -81,6 +79,20 @@ C
         STOP
       ENDIF
 C
+C     Initialize SPGMR linear solver module
+      call FSUNSPGMRINIT(1, JPRETYPE, MAXL, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRINIT IER = ', I5)
+        STOP
+      ENDIF
+      call FSUNSPGMRSETGSTYPE(1, IGSTYPE, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,27) IER
+ 27     FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETGSTYPE IER = ', I5)
+        STOP
+      ENDIF
+C     
 C     Initialize CVODE
       CALL FCVMALLOC(T, U, METH, ITMETH, IATOL, RTOL, ATOL,
      &     IOUT, ROUT, IPAR, RPAR, IER)
@@ -88,16 +100,18 @@ C     Initialize CVODE
         WRITE(6,30) IER
  30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
         STOP
-        ENDIF
+      ENDIF
 C
-      CALL FCVSPGMR(JPRETYPE, IGSTYPE, MAXL, DELT, IER)
+C     attach linear solver module to CVSpils interface
+      CALL FCVSPILSINIT(IER)
       IF (IER .NE. 0) THEN
         WRITE(6,40) IER
- 40     FORMAT(///' SUNDIALS_ERROR: FCVSPGMR returned IER = ', I5)
+ 40     FORMAT(///' SUNDIALS_ERROR: FCVSPILSINIT returned IER = ',I5)
         CALL FCVFREE
         STOP
       ENDIF
-C
+C     
+C     attach preconditioner to CVSpils interface
       CALL FCVSPILSSETPREC(1, IER)
 C
 C Loop over output points, call FCVODE, print sample solution values.
@@ -117,7 +131,7 @@ C
          IF (IER .NE. 0) THEN
             WRITE(6,60) IER, IOUT(15)
  60         FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
-     &           '                 Linear Solver returned IER = ', I5)
+     &             '                 Linear Solver returned IER = ', I5)
             CALL FCVFREE
             STOP
          ENDIF
@@ -165,12 +179,12 @@ C     Routine to set problem constants and initial values
 C
       IMPLICIT NONE
 C
-      INTEGER MX, MY
+      INTEGER*4 MX, MY
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
       DOUBLE PRECISION RPAR(*)
 C
-      INTEGER MM, JY, JX, P_IPP, P_BD, P_P
+      INTEGER*4 MM, JY, JX, P_IPP, P_BD, P_P
       DOUBLE PRECISION U0
       DIMENSION U0(2,MX,MY)
       DOUBLE PRECISION Q1, Q2, Q3, Q4, A3, A4, OM, C3, DY, HDCO
@@ -225,18 +239,18 @@ C
 C
 C     Set initial profiles.
       DO JY = 1, MY
-         Y = 30.0D0 + (JY - 1.0D0) * DY
-         CY = (0.1D0 * (Y - 40.0D0))**2
-         CY = 1.0D0 - CY + 0.5D0 * CY**2
-         DO JX = 1, MX
-            X = (JX - 1.0D0) * DX
-            CX = (0.1D0 * (X - 10.0D0))**2
-            CX = 1.0D0 - CX + 0.5D0 * CX**2
-            U0(1,JX,JY) = 1.0D6 * CX * CY
-            U0(2,JX,JY) = 1.0D12 * CX * CY
+        Y = 30.0D0 + (JY - 1.0D0) * DY
+        CY = (0.1D0 * (Y - 40.0D0))**2
+        CY = 1.0D0 - CY + 0.5D0 * CY**2
+        DO JX = 1, MX
+          X = (JX - 1.0D0) * DX
+          CX = (0.1D0 * (X - 10.0D0))**2
+          CX = 1.0D0 - CX + 0.5D0 * CX**2
+          U0(1,JX,JY) = 1.0D6 * CX * CY
+          U0(2,JX,JY) = 1.0D12 * CX * CY
          ENDDO
       ENDDO
-C     
+C
       RETURN
       END
 
@@ -250,10 +264,10 @@ C
       DOUBLE PRECISION T, U(2,*), UDOT(2,*), RPAR(*)
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
 C
-      INTEGER ILEFT, IRIGHT
-      INTEGER JX, JY, MX, MY, MM, IBLOK0, IBLOK, IDN, IUP
+      INTEGER*4 ILEFT, IRIGHT
+      INTEGER*4 JX, JY, MX, MY, MM, IBLOK0, IBLOK, IDN, IUP
       DOUBLE PRECISION Q1, Q2, Q3, Q4, A3, A4, OM, C3, DY, HDCO
       DOUBLE PRECISION VDCO, HACO
       DOUBLE PRECISION C1, C2, C1DN, C2DN, C1UP, C2UP, C1LT, C2LT
@@ -347,19 +361,19 @@ C
 C     ----------------------------------------------------------------
 
       SUBROUTINE FCVPSET(T, U, FU, JOK, JCUR, GAMMA, H,
-     &                   IPAR, RPAR, V1, V2, V3, IER)
+     &                   IPAR, RPAR, IER)
 C     Routine to set and preprocess block-diagonal preconditioner.
 C     Note: The dimensions in /BDJ/ below assume at most 100 mesh points.
 C
       IMPLICIT NONE
 C
-      INTEGER IER, JOK, JCUR
+      INTEGER*4 IER, JOK, JCUR
       DOUBLE PRECISION T, U(2,*), FU(*), GAMMA, H
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
-      DOUBLE PRECISION RPAR(*), V1(*), V2(*), V3(*)
+      DOUBLE PRECISION RPAR(*)
 C
-      INTEGER MX, MY, MM, P_IPP, P_BD, P_P
+      INTEGER*4 MX, MY, MM, P_IPP, P_BD, P_P
       DOUBLE PRECISION Q1, Q2, Q3, Q4, C3, DY, HDCO, VDCO
 C
       IER = 0
@@ -411,19 +425,18 @@ C
 C     ----------------------------------------------------------------
       
       SUBROUTINE FCVPSOL(T, U, FU, R, Z, GAMMA, DELTA, LR,
-     &                   IPAR, RPAR, VTEMP, IER)
+     &                   IPAR, RPAR, IER)
 C     Routine to solve preconditioner linear system.
 C
       IMPLICIT NONE
 C
-      INTEGER IER, LR
+      INTEGER*4 IER, LR
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
       DOUBLE PRECISION T, U(*), FU(*), R(*), Z(2,*)
       DOUBLE PRECISION GAMMA, DELTA, RPAR(*)
-      DOUBLE PRECISION VTEMP(*)
 C
-      INTEGER MM, P_IPP, P_P
+      INTEGER*4 MM, P_IPP, P_P
 C
       IER = 0
 C
@@ -452,11 +465,11 @@ C     Routine to compute diagonal Jacobian blocks
 C
       IMPLICIT NONE
 C
-      INTEGER MX, MY, MM
+      INTEGER*4 MX, MY, MM
       DOUBLE PRECISION U(2,*), BD(2,2,MM)
       DOUBLE PRECISION Q1, Q2, Q3, Q4, C3, DY, HDCO, VDCO
 C
-      INTEGER JY, JX, IBLOK, IBLOK0
+      INTEGER*4 JY, JX, IBLOK, IBLOK0
       DOUBLE PRECISION C1, C2, CYDN, CYUP, DIAG, YDN, YUP
 C
       DO JY = 1, MY
@@ -487,12 +500,12 @@ C     Routine to perform LU decomposition on (P+I)
 C
       IMPLICIT NONE
 C
-      INTEGER IER
-      INTEGER MM
+      INTEGER*4 IER
+      INTEGER*4 MM
       INTEGER*8 IPP(2,MM)
       DOUBLE PRECISION P(2,2,MM)
 C
-      INTEGER I
+      INTEGER*4 I
 C
 C     Add identity matrix and do LU decompositions on blocks, in place.
       DO I = 1, MM
@@ -512,11 +525,11 @@ C     Routine for backsolve
 C
       IMPLICIT NONE
 C
-      INTEGER MM
+      INTEGER*4 MM
       INTEGER*8 IPP(2,MM)
       DOUBLE PRECISION P(2,2,MM), Z(2,MM)
 C      
-      INTEGER I
+      INTEGER*4 I
 C
       DO I = 1, MM
          CALL DGESL(P(1,1,I), 2, 2, IPP(1,I), Z(1,I), 0)
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry.out b/examples/cvode/fcmix_serial/fcvDiurnal_kry.out
index 499269a..7c3cc6b 100644
--- a/examples/cvode/fcmix_serial/fcvDiurnal_kry.out
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry.out
@@ -11,53 +11,53 @@ Krylov example problem:
   c1 (bot.left/middle/top rt.) =   0.665902E+07  0.531602E+07  0.730081E+07
   c2 (bot.left/middle/top rt.) =   0.258192E+12  0.205680E+12  0.283286E+12
 
- t =   0.216E+05   nst =   277  q =  5  h =   0.274587E+03
+ t =   0.216E+05   nst =   277  q =  5  h =   0.274584E+03
   c1 (bot.left/middle/top rt.) =   0.266498E+08  0.103636E+08  0.293077E+08
   c2 (bot.left/middle/top rt.) =   0.299279E+12  0.102810E+12  0.331344E+12
 
- t =   0.288E+05   nst =   312  q =  4  h =   0.367517E+03
+ t =   0.288E+05   nst =   307  q =  4  h =   0.201171E+03
   c1 (bot.left/middle/top rt.) =   0.870209E+07  0.129197E+08  0.965002E+07
   c2 (bot.left/middle/top rt.) =   0.338035E+12  0.502929E+12  0.375096E+12
 
- t =   0.360E+05   nst =   350  q =  4  h =   0.683836E+02
+ t =   0.360E+05   nst =   336  q =  5  h =   0.101863E+03
   c1 (bot.left/middle/top rt.) =   0.140404E+05  0.202903E+05  0.156090E+05
-  c2 (bot.left/middle/top rt.) =   0.338677E+12  0.489443E+12  0.376517E+12
+  c2 (bot.left/middle/top rt.) =   0.338677E+12  0.489443E+12  0.376516E+12
 
- t =   0.432E+05   nst =   407  q =  4  h =   0.383863E+03
-  c1 (bot.left/middle/top rt.) =   0.803367E-06  0.363858E-06  0.889797E-06
+ t =   0.432E+05   nst =   385  q =  4  h =   0.456580E+03
+  c1 (bot.left/middle/top rt.) =   0.522615E-07 -0.607462E-05  0.871309E-07
   c2 (bot.left/middle/top rt.) =   0.338233E+12  0.135487E+12  0.380352E+12
 
- t =   0.504E+05   nst =   436  q =  3  h =   0.215343E+03
-  c1 (bot.left/middle/top rt.) =   0.375001E-05  0.665499E-06  0.454113E-05
-  c2 (bot.left/middle/top rt.) =   0.335816E+12  0.493028E+12  0.386445E+12
+ t =   0.504E+05   nst =   403  q =  4  h =   0.277279E+03
+  c1 (bot.left/middle/top rt.) =  -0.266960E-07 -0.450968E-05 -0.267202E-07
+  c2 (bot.left/middle/top rt.) =   0.335816E+12  0.493033E+12  0.386445E+12
 
- t =   0.576E+05   nst =   454  q =  5  h =   0.428080E+03
-  c1 (bot.left/middle/top rt.) =   0.112301E-08  0.194567E-09  0.136087E-08
-  c2 (bot.left/middle/top rt.) =   0.332031E+12  0.964985E+12  0.390900E+12
+ t =   0.576E+05   nst =   419  q =  5  h =   0.344023E+03
+  c1 (bot.left/middle/top rt.) =  -0.114670E-08 -0.587145E-07 -0.219472E-08
+  c2 (bot.left/middle/top rt.) =   0.332031E+12  0.964981E+12  0.390900E+12
 
- t =   0.648E+05   nst =   466  q =  5  h =   0.690422E+03
-  c1 (bot.left/middle/top rt.) =   0.353041E-08  0.590752E-09  0.428410E-08
+ t =   0.648E+05   nst =   431  q =  5  h =   0.949533E+03
+  c1 (bot.left/middle/top rt.) =   0.379212E-09  0.190141E-07  0.719619E-09
   c2 (bot.left/middle/top rt.) =   0.331303E+12  0.892184E+12  0.396342E+12
 
- t =   0.720E+05   nst =   476  q =  5  h =   0.690422E+03
-  c1 (bot.left/middle/top rt.) =  -0.121418E-09 -0.206756E-10 -0.147240E-09
-  c2 (bot.left/middle/top rt.) =   0.332972E+12  0.618620E+12  0.403885E+12
+ t =   0.720E+05   nst =   441  q =  5  h =   0.700864E+03
+  c1 (bot.left/middle/top rt.) =  -0.187184E-10 -0.936079E-09 -0.355015E-10
+  c2 (bot.left/middle/top rt.) =   0.332972E+12  0.618617E+12  0.403885E+12
 
- t =   0.792E+05   nst =   487  q =  5  h =   0.690422E+03
-  c1 (bot.left/middle/top rt.) =  -0.341376E-11 -0.568210E-12 -0.414339E-11
-  c2 (bot.left/middle/top rt.) =   0.333441E+12  0.666893E+12  0.412026E+12
+ t =   0.792E+05   nst =   451  q =  5  h =   0.700864E+03
+  c1 (bot.left/middle/top rt.) =   0.136509E-12  0.673869E-11  0.258515E-12
+  c2 (bot.left/middle/top rt.) =   0.333441E+12  0.666904E+12  0.412026E+12
 
- t =   0.864E+05   nst =   497  q =  5  h =   0.690422E+03
-  c1 (bot.left/middle/top rt.) =   0.309841E-12  0.526192E-13  0.375773E-12
-  c2 (bot.left/middle/top rt.) =   0.335178E+12  0.910652E+12  0.416251E+12
+ t =   0.864E+05   nst =   461  q =  5  h =   0.700864E+03
+  c1 (bot.left/middle/top rt.) =   0.414351E-13  0.207247E-11  0.786247E-13
+  c2 (bot.left/middle/top rt.) =   0.335178E+12  0.910668E+12  0.416250E+12
 
 
 Final statistics:
 
- number of steps        =   497      number of f evals.     =  651
- number of prec. setups =    91
- number of prec. evals. =     9      number of prec. solves =  1233
- number of nonl. iters. =   647      number of lin. iters.  =   652
- average Krylov subspace dimension (NLI/NNI)  =   0.100773E+01
+ number of steps        =   461      number of f evals.     =  598
+ number of prec. setups =    78
+ number of prec. evals. =     8      number of prec. solves =  1176
+ number of nonl. iters. =   594      number of lin. iters.  =   636
+ average Krylov subspace dimension (NLI/NNI)  =   0.107071E+01
  number of conv. failures.. nonlinear =   0 linear =   0
- number of error test failures =  34
+ number of error test failures =  27
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f
index dd5b57b..fe65cae 100644
--- a/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.f
@@ -1,9 +1,6 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4294 $
-C     $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
-C     ----------------------------------------------------------------
-C     FCVODE Example Problem: 2D kinetics-transport, 
-C     precond. Krylov solver. 
+C     FCVODE Example Problem: 2D kinetics-transport, precond. Krylov
+C     solver. 
 C     
 C     An ODE system is generated from the following 2-species diurnal
 C     kinetics advection-diffusion PDE system in 2 space dimensions:
@@ -18,32 +15,32 @@ C     vary diurnally.
 C
 C     The problem is posed on the square
 C     0 .le. x .le. 20,    30 .le. y .le. 50   (all in km),
-C     with homogeneous Neumann boundary conditions, and for time t in
-C     0 .le. t .le. 86400 sec (1 day).
+C     with homogeneous Neumann boundary conditions, and for time t
+C     in 0 .le. t .le. 86400 sec (1 day).
 C
 C     The PDE system is treated by central differences on a uniform
 C     10 x 10 mesh, with simple polynomial initial profiles.
 C     The problem is solved with CVODE, with the BDF/GMRES method and
-C     using the FCVBP banded preconditioner
+C     using the FCVBP banded preconditioner.
 C     
-C     The second and third dimensions of U here must match the values of
-C     MX and MY, for consistency with the output statements below.
+C     The second and third dimensions of U here must match the values
+C     of MX and MY, for consistency with the output statements below.
 C     ----------------------------------------------------------------
 C
       IMPLICIT NONE
 C
-      INTEGER MX, MY
+      INTEGER*4 MX, MY
       PARAMETER (MX=10, MY=10)
 C
-      INTEGER LNST, LNFE, LNSETUP, LNNI, LNCF, LNPE, LNLI, LNPS
-      INTEGER LNCFL, LH, LQ, METH, ITMETH, IATOL, ITASK
-      INTEGER LNETF, IER, MAXL, JPRETYPE, IGSTYPE, JOUT
-      INTEGER LLENRW, LLENIW, LLENRWLS, LLENIWLS
+      INTEGER*4 LNST, LNFE, LNSETUP, LNNI, LNCF, LNPE, LNLI, LNPS
+      INTEGER*4 LNCFL, LH, LQ, METH, ITMETH, IATOL, ITASK
+      INTEGER*4 LNETF, IER, MAXL, JPRETYPE, IGSTYPE, JOUT
+      INTEGER*4 LLENRW, LLENIW, LLENRWLS, LLENIWLS
 C The following declaration specification should match C type long int.
       INTEGER*8 NEQ, IOUT(25), IPAR(4)
-      INTEGER NST, NFE, NPSET, NPE, NPS, NNI
-      INTEGER NLI, NCFN, NCFL, NETF
-      INTEGER LENRW, LENIW, LENRWLS, LENIWLS
+      INTEGER*4 NST, NFE, NPSET, NPE, NPS, NNI
+      INTEGER*4 NLI, NCFN, NCFL, NETF
+      INTEGER*4 LENRW, LENIW, LENRWLS, LENIWLS
 C The following declaration specification should match C type long int.
       INTEGER*8 MU, ML, LENRWBP, LENIWBP, NFEBP
       DOUBLE PRECISION ATOL, AVDIM, DELT, FLOOR, RTOL, T, TOUT, TWOHR
@@ -56,7 +53,7 @@ C
      1     LNPE/18/, LNLI/20/, LNPS/19/, LNCFL/21/
       DATA LH/2/
 C
-C Load IPAR, RPAR, and initial values
+C     Load problem constants into IPAR, RPAR, and set initial values
       CALL INITKX(MX, MY, U, IPAR, RPAR)
 C
 C     Set other input arguments.
@@ -75,27 +72,41 @@ C
 C     Initialize vector specification
       CALL FNVINITS(1, NEQ, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,20) IER
- 20      FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
-         STOP
+        WRITE(6,20) IER
+ 20     FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
+        STOP
+      ENDIF
+C
+C     Initialize SPGMR linear solver module
+      call FSUNSPGMRINIT(1, JPRETYPE, MAXL, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRINIT IER = ', I5)
+        STOP
+      ENDIF
+      call FSUNSPGMRSETGSTYPE(1, IGSTYPE, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,27) IER
+ 27     FORMAT(///' SUNDIALS_ERROR: FSUNSPGMRSETGSTYPE IER = ', I5)
+        STOP
       ENDIF
 C     
 C     Initialize CVODE
       CALL FCVMALLOC(T, U, METH, ITMETH, IATOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,30) IER
- 30      FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
-         STOP
+        WRITE(6,30) IER
+ 30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
+        STOP
       ENDIF
-C     
-C     Initialize SPGMR solver
-      CALL FCVSPGMR(JPRETYPE, IGSTYPE, MAXL, DELT, IER) 
+C
+C     attach linear solver module to CVSpils interface
+      CALL FCVSPILSINIT(IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,45) IER
- 45      FORMAT(///' SUNDIALS_ERROR: FCVSPGMR returned IER = ', I5)
-         CALL FCVFREE
-         STOP
+        WRITE(6,40) IER
+ 40     FORMAT(///' SUNDIALS_ERROR: FCVSPILSINIT returned IER = ',I5)
+        CALL FCVFREE
+        STOP
       ENDIF
 C     
 C     Initialize band preconditioner
@@ -103,8 +114,8 @@ C     Initialize band preconditioner
       ML = 2
       CALL FCVBPINIT(NEQ, MU, ML, IER) 
       IF (IER .NE. 0) THEN
-         WRITE(6,40) IER
- 40      FORMAT(///' SUNDIALS_ERROR: FCVBPINIT returned IER = ', I5)
+         WRITE(6,45) IER
+ 45      FORMAT(///' SUNDIALS_ERROR: FCVBPINIT returned IER = ', I5)
          CALL FCVFREE
          STOP
       ENDIF
@@ -117,12 +128,12 @@ C
 C     
          WRITE(6,50) T, IOUT(LNST), IOUT(LQ), ROUT(LH)
  50      FORMAT(/' t = ', E14.6, 5X, 'no. steps = ', I5,
-     1        '   order = ', I3, '   stepsize = ', E14.6)
+     1           '   order = ', I3, '   stepsize = ', E14.6)
          WRITE(6,55) U(1,1,1), U(1,5,5), U(1,10,10),
      1               U(2,1,1), U(2,5,5), U(2,10,10)
  55      FORMAT('  c1 (bot.left/middle/top rt.) = ', 3E14.6/
-     1        '  c2 (bot.left/middle/top rt.) = ', 3E14.6)
-C     
+     1          '  c2 (bot.left/middle/top rt.) = ', 3E14.6)
+C
          IF (IER .NE. 0) THEN
             WRITE(6,60) IER, IOUT(15)
  60         FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
@@ -173,23 +184,23 @@ C     Print final statistics.
      &        ' number of f evaluations  = ', I5)
 C     
       CALL FCVFREE
-C     
+C
       STOP
       END
 
 C     ----------------------------------------------------------------
 
       SUBROUTINE INITKX(MX, MY, U0, IPAR, RPAR)
-C Routine to set problem constants and initial values
+C     Routine to set problem constants and initial values
 C
       IMPLICIT NONE
 C
-      INTEGER MX, MY
+      INTEGER*4 MX, MY
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
       DOUBLE PRECISION RPAR(*)
 C
-      INTEGER MM, JY, JX, NEQ
+      INTEGER*8 MM, JY, JX, NEQ
       DOUBLE PRECISION U0
       DIMENSION U0(2,MX,MY)
       DOUBLE PRECISION Q1, Q2, Q3, Q4, A3, A4, OM, C3, DY, HDCO
@@ -199,13 +210,13 @@ C
       DATA DKH/4.0D-6/, VEL/0.001D0/, DKV0/1.0D-8/, HALFDA/4.32D4/,
      1     PI/3.1415926535898D0/
 C
-C Problem constants
+C     Problem constants
       MM = MX * MY
       NEQ = 2 * MM
       Q1 = 1.63D-16
       Q2 = 4.66D-16
-      Q3 = 0.D0
-      Q4 = 0.D0
+      Q3 = 0.0D0
+      Q4 = 0.0D0
       A3 = 22.62D0
       A4 = 7.601D0
       OM = PI / HALFDA
@@ -215,7 +226,8 @@ C Problem constants
       HDCO = DKH / DX**2
       HACO = VEL / (2.0D0 * DX)
       VDCO = (1.0D0 / DY**2) * DKV0
-C Load constants in IPAR and RPAR
+C
+C     Load constants in IPAR and RPAR
       IPAR(1) = MX
       IPAR(2) = MY
       IPAR(3) = MM
@@ -234,7 +246,7 @@ C
       RPAR(11) = VDCO
       RPAR(12) = HACO
 C
-C Set initial profiles.
+C     Set initial profiles.
       DO 20 JY = 1, MY
         Y = 30.0D0 + (JY - 1.0D0) * DY
         CY = (0.1D0 * (Y - 40.0D0))**2
@@ -250,20 +262,21 @@ C Set initial profiles.
 C
       RETURN
       END
-      
+
 C     ----------------------------------------------------------------
 
       SUBROUTINE FCVFUN(T, U, UDOT, IPAR, RPAR, IER)
 C     Routine for right-hand side function f
+C
       IMPLICIT NONE
 C
 C The following declaration specification should match C type long int.
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, U(2,*), UDOT(2,*), RPAR(*)
 C
-      INTEGER ILEFT, IRIGHT
-      INTEGER MX, MY, MM, JY, JX, IBLOK0, IDN, IUP, IBLOK
+      INTEGER*4 ILEFT, IRIGHT
+      INTEGER*8 MX, MY, MM, JY, JX, IBLOK0, IDN, IUP, IBLOK
       DOUBLE PRECISION Q1,Q2,Q3,Q4, A3, A4, OM, C3, DY, HDCO, VDCO, HACO
       DOUBLE PRECISION C1, C2, C1DN, C2DN, C1UP, C2UP, C1LT, C2LT
       DOUBLE PRECISION C1RT, C2RT, CYDN, CYUP, HORD1, HORD2, HORAD1
@@ -287,7 +300,7 @@ C
       HDCO = RPAR(10)
       VDCO = RPAR(11)
       HACO = RPAR(12)
-C     
+C
 C     Set diurnal rate coefficients.
       S = SIN(OM * T)
       IF (S .GT. 0.0D0) THEN
diff --git a/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out
index 63aa199..d9ffbe0 100644
--- a/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out
+++ b/examples/cvode/fcmix_serial/fcvDiurnal_kry_bp.out
@@ -62,7 +62,7 @@ Final statistics:
  number of conv. failures.. nonlinear =  0 linear =   0
  number of error test failures =  28
  main solver real/int workspace sizes   =    2089     50
- linear solver real/int workspace sizes =  2046   10
+ linear solver real/int workspace sizes =  2450   22
 In CVBANDPRE:
- real/int workspace sizes =    2400    200
+ real/int workspace sizes =    2800    622
  number of f evaluations  =    45
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dns.f b/examples/cvode/fcmix_serial/fcvRoberts_dns.f
index e8d8baa..88a11d2 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_dns.f
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dns.f
@@ -1,8 +1,6 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4885 $
-C     $Date: 2016-09-02 08:29:03 -0700 (Fri, 02 Sep 2016) $
-C     ----------------------------------------------------------------
-C     FCVODE Example Problem: Robertson kinetics, dense user Jacobian.
+C     FCVODE Example Problem: Robertson kinetics, direct linear solver
+C                             with dense user Jacobian.
 C
 C     The following is a simple example problem, with the coding
 C     needed for its solution by CVODE. The problem is from chemical
@@ -30,16 +28,16 @@ C     ----------------------------------------------------------------
 C
       IMPLICIT NONE
 C
-      INTEGER IER, I 
-      INTEGER LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
-      INTEGER METH, ITMETH, ITOL, ITASK, JOUT, NOUT, IERROOT
-      INTEGER INFO(2)
-C The following declaration specification should match C type long int.
-      INTEGER*8 IPAR, NEQ, IOUT(25)
+      INTEGER*4 IER, LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
+      INTEGER*4 METH, ITMETH, ITOL, ITASK, JOUT, NOUT, IERROOT
+      INTEGER*4 INFO(2)
+      INTEGER*4 I
+C The following declaration specification should match C type long int
+      INTEGER*8 NEQ, IPAR, IOUT(25)
       DOUBLE PRECISION RTOL, T, T0, TOUT
       DOUBLE PRECISION Y(3), ATOL(3), ROUT(10), RPAR
 C
-      DATA LNST/3/, LNFE/4/, LNETF/5/,  LNCF/6/, LNNI/7/, LNSETUP/8/, 
+      DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/,
      1     LNGE/12/, LNJE/17/
 C
       NEQ = 3
@@ -62,15 +60,35 @@ C
       WRITE(6,10) NEQ
  10   FORMAT('Dense example problem:'//
      1       ' Robertson kinetics, NEQ = ', I2//)
-C
+
+C     create serial vector
       CALL FNVINITS(1, NEQ, IER)
       IF (IER .NE. 0) THEN
         WRITE(6,20) IER
  20     FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
         STOP
       ENDIF
-C
 
+C     initialize dense matrix module
+      CALL FSUNDENSEMATINIT(1, NEQ, NEQ, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNDENSEMATINIT returned IER = ',
+     1         I5)
+        STOP
+      ENDIF
+
+C     initialize dense linear solver module
+      CALL FSUNDENSELINSOLINIT(1, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,28) IER
+ 28     FORMAT(///' SUNDIALS_ERROR: FSUNDENSELINSOLINIT returned IER = '
+     1         , I5)
+        STOP
+      ENDIF
+
+C     Call FCVMALLOC to create the solver memory and specify the 
+C     Backward Differentiation Formula and the use of a Newton iteration
       CALL FCVMALLOC(T0, Y, METH, ITMETH, ITOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
       IF (IER .NE. 0) THEN
@@ -78,26 +96,34 @@ C
  30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
         STOP
       ENDIF
-C
 
+C     Call FCVROOTINIT to specify the root function g with 2 components
       CALL FCVROOTINIT(2, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,45) IER
- 45      FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
-         CALL FCVFREE
-         STOP
+        WRITE(6,35) IER
+ 35     FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
+        CALL FCVFREE
+        STOP
       ENDIF
-C
-      CALL FCVDENSE(NEQ, IER)
+
+C     attach the matrix and linear solver modules to CVDls interface
+      CALL FCVDLSINIT(IER)
       IF (IER .NE. 0) THEN
         WRITE(6,40) IER
- 40     FORMAT(///' SUNDIALS_ERROR: FCVDENSE returned IER = ', I5)
+ 40     FORMAT(///' SUNDIALS_ERROR: FCVDLSINIT returned IER = ', I5)
         CALL FCVFREE
         STOP
       ENDIF
-C
+
+C     indicate a dense Jacobian function is provided
       CALL FCVDENSESETJAC(1, IER)
-C
+      IF (IER .NE. 0) THEN
+        WRITE(6,45) IER
+ 45     FORMAT(///' SUNDIALS_ERROR: FCVDENSESETJAC returned IER = ', I5)
+        CALL FCVFREE
+        STOP
+      ENDIF
+
       DO WHILE(JOUT .LT. NOUT)
 C
         CALL FCVODE(TOUT, T, Y, ITASK, IER)
@@ -106,42 +132,42 @@ C
  50     FORMAT('At t = ', E12.4, '   y = ', 3E14.6)
 C
         IF (IER .LT. 0) THEN
-           WRITE(6,60) IER, IOUT(15)
- 60        FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
-     1            '                 Linear Solver returned IER = ', I5)
-           CALL FCVROOTFREE
-           CALL FCVFREE
-           STOP
+          WRITE(6,60) IER, IOUT(15)
+ 60       FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+     1           '                 Linear Solver returned IER = ', I5)
+          CALL FCVROOTFREE
+          CALL FCVFREE
+          STOP
         ENDIF
 C
         IF (IER .EQ. 2) THEN
-           CALL FCVROOTINFO(2, INFO, IERROOT)
-           IF (IERROOT .LT. 0) THEN
-              WRITE(6,65) IERROOT
- 65           FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
-     1              I5)
-              CALL FCVROOTFREE
-              CALL FCVFREE
-              STOP
-           ENDIF
-           WRITE(6,70) (INFO(I), I = 1, 2)
- 70        FORMAT(5X, 'Above is a root, INFO() = ', 2I3)
-        ENDIF                   
+          CALL FCVROOTINFO(2, INFO, IERROOT)
+          IF (IERROOT .LT. 0) THEN
+            WRITE(6,65) IERROOT
+ 65         FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
+     1             I5)
+            CALL FCVROOTFREE
+            CALL FCVFREE
+            STOP
+          ENDIF
+          WRITE(6,70) (INFO(I), I = 1, 2)
+ 70       FORMAT(5X, 'Above is a root, INFO() = ', 2I3)
+        ENDIF
 C
         IF (IER .EQ. 0) THEN
-           TOUT = TOUT * 10.0D0
-           JOUT = JOUT + 1
+          TOUT = TOUT * 10.0D0
+          JOUT = JOUT + 1
         ENDIF
 C
       ENDDO
 C
       CALL FCVDKY(T, 1, Y, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,80) IER
- 80      FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ', I4)
-         CALL FCVROOTFREE
-         CALL FCVFREE
-         STOP
+        WRITE(6,80) IER
+ 80     FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ', I4)
+        CALL FCVROOTFREE
+        CALL FCVFREE
+        STOP
       ENDIF
       WRITE(6,85) Y(1), Y(2), Y(3)
  85   FORMAT(/'Final value of ydot = ', 3E14.6)
@@ -165,12 +191,12 @@ C
 C     ----------------------------------------------------------------
 
       SUBROUTINE FCVFUN(T, Y, YDOT, IPAR, RPAR, IER)
-C Fortran routine for right-hand side function.
+C     Fortran routine for right-hand side function
       IMPLICIT NONE
 C
-C The following declaration specification should match C type long int.
+C The following declaration specification should match C type long int
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
 C
       YDOT(1) = -0.04D0 * Y(1) + 1.0D4 * Y(2) * Y(3)
@@ -185,13 +211,13 @@ C
 C     ----------------------------------------------------------------
 
       SUBROUTINE FCVROOTFN(T, Y, G, IPAR, RPAR, IER)
-C Fortran routine for root finding
+C     Fortran routine for root finding
       IMPLICIT NONE
 C
       DOUBLE PRECISION T, Y(*), G(*), RPAR(*)
-C The following declaration specification should match C type long int.
+C The following declaration specification should match C type long int
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
 C
       G(1) = Y(1) - 1.0D-4
       G(2) = Y(3) - 1.0D-2
@@ -205,16 +231,16 @@ C     ----------------------------------------------------------------
 
       SUBROUTINE FCVDJAC(N, T, Y, FY, JAC, H, IPAR, RPAR, 
      1                   V1, V2, V3, IER)
-C Fortran routine for dense user-supplied Jacobian.
+C     Fortran routine for dense user-supplied Jacobian
       IMPLICIT NONE
 C
-C The following declaration specification should match C type long int.
+C The following declaration specification should match C type long int
       INTEGER*8 N, IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), FY(*), JAC(N,*), H, RPAR(*)
       DOUBLE PRECISION V1(*), V2(*), V3(*)
 C
-      DOUBLE PRECISION  Y1, Y2, Y3
+      DOUBLE PRECISION Y1, Y2, Y3
 C
       Y1 = Y(1)
       Y2 = Y(2)
@@ -225,7 +251,9 @@ C
       JAC(2,1) =  0.04D0
       JAC(2,2) = -1.0D4 * Y3 - 6.0D7 * Y2
       JAC(2,3) = -1.0D4 * Y2
+      JAC(3,3) = 0.0D0
       JAC(3,2) = 6.0D7 * Y2
+      JAC(3,3) = 0.0D0
 C
       IER = 0
 C
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dns.out b/examples/cvode/fcmix_serial/fcvRoberts_dns.out
index e17fe74..1c93c14 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_dns.out
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dns.out
@@ -7,26 +7,26 @@ At t =   0.2639E+00   y =   0.989965E+00  0.347056E-04  0.100000E-01
      Above is a root, INFO() =   0  1
 At t =   0.4000E+00   y =   0.985164E+00  0.338624E-04  0.148020E-01
 At t =   0.4000E+01   y =   0.905510E+00  0.224034E-04  0.944679E-01
-At t =   0.4000E+02   y =   0.715801E+00  0.918510E-05  0.284190E+00
-At t =   0.4000E+03   y =   0.450544E+00  0.322322E-05  0.549453E+00
-At t =   0.4000E+04   y =   0.183196E+00  0.894205E-06  0.816803E+00
-At t =   0.4000E+05   y =   0.389810E-01  0.162166E-06  0.961019E+00
-At t =   0.4000E+06   y =   0.493867E-02  0.198517E-07  0.995061E+00
-At t =   0.4000E+07   y =   0.516609E-03  0.206750E-08  0.999483E+00
-At t =   0.2080E+08   y =   0.100000E-03  0.400039E-09  0.999900E+00
+At t =   0.4000E+02   y =   0.715802E+00  0.918504E-05  0.284189E+00
+At t =   0.4000E+03   y =   0.450536E+00  0.322327E-05  0.549461E+00
+At t =   0.4000E+04   y =   0.183230E+00  0.894438E-06  0.816769E+00
+At t =   0.4000E+05   y =   0.389890E-01  0.162201E-06  0.961011E+00
+At t =   0.4000E+06   y =   0.493638E-02  0.198422E-07  0.995064E+00
+At t =   0.4000E+07   y =   0.516809E-03  0.206829E-08  0.999483E+00
+At t =   0.2079E+08   y =   0.100000E-03  0.400040E-09  0.999900E+00
      Above is a root, INFO() =  -1  0
-At t =   0.4000E+08   y =   0.520641E-04  0.208267E-09  0.999948E+00
-At t =   0.4000E+09   y =   0.521124E-05  0.208451E-10  0.999995E+00
-At t =   0.4000E+10   y =   0.520052E-06  0.208021E-11  0.999999E+00
-At t =   0.4000E+11   y =   0.569949E-07  0.227979E-12  0.100000E+01
+At t =   0.4000E+08   y =   0.520244E-04  0.208108E-09  0.999948E+00
+At t =   0.4000E+09   y =   0.520106E-05  0.208044E-10  0.999995E+00
+At t =   0.4000E+10   y =   0.525860E-06  0.210344E-11  0.999999E+00
+At t =   0.4000E+11   y =   0.693451E-07  0.277380E-12  0.100000E+01
 
-Final value of ydot =  -0.304816E-17 -0.121927E-22  0.304818E-17
+Final value of ydot =  -0.276733E-18 -0.110693E-23  0.276734E-18
 
 
 Final statistics:
 
- No. steps =  579   No. f-s =  817   No. J-s =   12   No. LU-s =  118
- No. nonlinear iterations =  813
+ No. steps =  542   No. f-s =  755   No. J-s =   11   No. LU-s =  107
+ No. nonlinear iterations =  751
  No. nonlinear convergence failures =    0
- No. error test failures =   31
- No. root function evals =  615
+ No. error test failures =   22
+ No. root function evals =  570
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dnsL.f b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.f
index d7f665d..20029f9 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_dnsL.f
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.f
@@ -1,7 +1,4 @@
 C     ----------------------------------------------------------------
-C     $Revision: 4885 $
-C     $Date: 2016-09-02 08:29:03 -0700 (Fri, 02 Sep 2016) $
-C     ----------------------------------------------------------------
 C     FCVODE Example Problem: Robertson kinetics, Lapack linear solver
 C                             with dense user Jacobian.
 C
@@ -19,7 +16,7 @@ C
 C     y1 = 1.0, y2 = y3 = 0.
 C
 C     The problem is stiff. While integrating the system, we also
-C     employ the root finding feature to find the points at which
+C     enable the root finding feature to find the points at which
 C     y1 = 1.e-4 or at which y3 = 0.01. The following coding solves
 C     this problem with CVODE, using the Fortran/C interface routine
 C     package. This solution uses the BDF method and a user-supplied
@@ -27,26 +24,26 @@ C     Jacobian routine, and prints results at t = .4, 4., ..., 4.e10.
 C     It uses ITOL = 2 and ATOL much smaller for y2 than y1 or y3
 C     because y2 has much smaller values. At the end of the run,
 C     various counters of interest are printed.
+C
+C     Note that this problem should only work with SUNDIALS configured
+C     to use 'realtype' as 'double' and 'sunindextype' as '32bit'
 C     ----------------------------------------------------------------
 C
       IMPLICIT NONE
 C
-      INTEGER IER, I 
-      INTEGER LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
-      INTEGER METH, ITMETH, ITOL, ITASK, JOUT, NOUT, IERROOT
-      INTEGER INFO(2)
+      INTEGER*4 IER, LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
+      INTEGER*4 METH, ITMETH, ITOL, ITASK, JOUT, NOUT, IERROOT
+      INTEGER*4 INFO(2)
+      INTEGER*4 I, NEQ
 C The following declaration specification should match C type long int.
-      INTEGER*8 NEQ, IOUT(25), IPAR
-C The following declaration specification should match C type int.
-      INTEGER*4 NEQL
+      INTEGER*8 IPAR, IOUT(25)
       DOUBLE PRECISION RTOL, T, T0, TOUT
       DOUBLE PRECISION Y(3), ATOL(3), ROUT(10), RPAR
 C
-      DATA LNST/3/, LNFE/4/, LNETF/5/,  LNCF/6/, LNNI/7/, LNSETUP/8/, 
+      DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/,
      1     LNGE/12/, LNJE/17/
 C
       NEQ = 3
-      NEQL = NEQ
       T0 = 0.0D0
       Y(1) = 1.0D0
       Y(2) = 0.0D0
@@ -66,15 +63,35 @@ C
       WRITE(6,10) NEQ
  10   FORMAT('Dense example problem:'//
      1       ' Robertson kinetics, NEQ = ', I2//)
-C
+
+C     create serial vector
       CALL FNVINITS(1, NEQ, IER)
       IF (IER .NE. 0) THEN
         WRITE(6,20) IER
  20     FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
         STOP
       ENDIF
-C
 
+C     initialize dense matrix module
+      CALL FSUNDENSEMATINIT(1, NEQ, NEQ, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNDENSEMATINIT returned IER = ',
+     1         I5)
+        STOP
+      ENDIF
+
+C     initialize LAPACK dense linear solver module
+      CALL FSUNLAPACKDENSEINIT(1, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,28) IER
+ 28     FORMAT(///' SUNDIALS_ERROR: FSUNLAPACKDENSEINIT returned IER = '
+     1         , I5)
+        STOP
+      ENDIF
+
+C     Call FCVMALLOC to create the solver memory and specify the 
+C     Backward Differentiation Formula and the use of a Newton iteration
       CALL FCVMALLOC(T0, Y, METH, ITMETH, ITOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
       IF (IER .NE. 0) THEN
@@ -82,26 +99,34 @@ C
  30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
         STOP
       ENDIF
-C
 
+C     Call FCVROOTINIT to specify the root function g with 2 components
       CALL FCVROOTINIT(2, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,45) IER
- 45      FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
-         CALL FCVFREE
-         STOP
+        WRITE(6,35) IER
+ 35     FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
+        CALL FCVFREE
+        STOP
       ENDIF
-C
-      CALL FCVLAPACKDENSE(NEQL, IER)
+
+C     attach the matrix and linear solver modules to CVDls interface
+      CALL FCVDLSINIT(IER)
       IF (IER .NE. 0) THEN
         WRITE(6,40) IER
- 40     FORMAT(///' SUNDIALS_ERROR: FCVLAPACKDENSE returned IER = ', I5)
+ 40     FORMAT(///' SUNDIALS_ERROR: FCVDLSINIT returned IER = ', I5)
         CALL FCVFREE
         STOP
       ENDIF
-C
-      CALL FCVLAPACKDENSESETJAC(1, IER)
-C
+
+C     indicate a dense Jacobian function is provided
+      CALL FCVDENSESETJAC(1, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,45) IER
+ 45     FORMAT(///' SUNDIALS_ERROR: FCVDENSESETJAC returned IER = ', I5)
+        CALL FCVFREE
+        STOP
+      ENDIF
+
       DO WHILE(JOUT .LT. NOUT)
 C
         CALL FCVODE(TOUT, T, Y, ITASK, IER)
@@ -110,42 +135,42 @@ C
  50     FORMAT('At t = ', E12.4, '   y = ', 3E14.6)
 C
         IF (IER .LT. 0) THEN
-           WRITE(6,60) IER, IOUT(15)
- 60        FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
-     1            '                 Linear Solver returned IER = ', I5)
-           CALL FCVROOTFREE
-           CALL FCVFREE
-           STOP
+          WRITE(6,60) IER, IOUT(15)
+ 60       FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+     1           '                 Linear Solver returned IER = ', I5)
+          CALL FCVROOTFREE
+          CALL FCVFREE
+          STOP
         ENDIF
 C
         IF (IER .EQ. 2) THEN
-           CALL FCVROOTINFO(2, INFO, IERROOT)
-           IF (IERROOT .LT. 0) THEN
-              WRITE(6,65) IERROOT
- 65           FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
-     1              I5)
-              CALL FCVROOTFREE
-              CALL FCVFREE
-              STOP
-           ENDIF
-           WRITE(6,70) (INFO(I), I = 1, 2)
- 70        FORMAT(5X, 'Above is a root, INFO() = ', 2I3)
-        ENDIF                   
+          CALL FCVROOTINFO(2, INFO, IERROOT)
+          IF (IERROOT .LT. 0) THEN
+            WRITE(6,65) IERROOT
+ 65         FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
+     1             I5)
+            CALL FCVROOTFREE
+            CALL FCVFREE
+            STOP
+          ENDIF
+          WRITE(6,70) (INFO(I), I = 1, 2)
+ 70       FORMAT(5X, 'Above is a root, INFO() = ', 2I3)
+        ENDIF
 C
         IF (IER .EQ. 0) THEN
-           TOUT = TOUT * 10.0D0
-           JOUT = JOUT + 1
+          TOUT = TOUT * 10.0D0
+          JOUT = JOUT + 1
         ENDIF
 C
       ENDDO
 C
       CALL FCVDKY(T, 1, Y, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6,80) IER
- 80      FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ', I4)
-         CALL FCVROOTFREE
-         CALL FCVFREE
-         STOP
+        WRITE(6,80) IER
+ 80     FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ', I4)
+        CALL FCVROOTFREE
+        CALL FCVFREE
+        STOP
       ENDIF
       WRITE(6,85) Y(1), Y(2), Y(3)
  85   FORMAT(/'Final value of ydot = ', 3E14.6)
@@ -169,12 +194,12 @@ C
 C     ----------------------------------------------------------------
 
       SUBROUTINE FCVFUN(T, Y, YDOT, IPAR, RPAR, IER)
-C Fortran routine for right-hand side function.
+C     Fortran routine for right-hand side function
       IMPLICIT NONE
 C
-C The following declaration specification should match C type long int.
+C The following declaration specification should match C type long int
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
 C
       YDOT(1) = -0.04D0 * Y(1) + 1.0D4 * Y(2) * Y(3)
@@ -189,13 +214,13 @@ C
 C     ----------------------------------------------------------------
 
       SUBROUTINE FCVROOTFN(T, Y, G, IPAR, RPAR, IER)
-C Fortran routine for root finding
+C     Fortran routine for root finding
       IMPLICIT NONE
 C
       DOUBLE PRECISION T, Y(*), G(*), RPAR(*)
-C The following declaration specification should match C type long int.
+C The following declaration specification should match C type long int
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
 C
       G(1) = Y(1) - 1.0D-4
       G(2) = Y(3) - 1.0D-2
@@ -209,16 +234,16 @@ C     ----------------------------------------------------------------
 
       SUBROUTINE FCVDJAC(N, T, Y, FY, JAC, H, IPAR, RPAR, 
      1                   V1, V2, V3, IER)
-C Fortran routine for dense user-supplied Jacobian.
+C     Fortran routine for dense user-supplied Jacobian
       IMPLICIT NONE
 C
-C The following declaration specification should match C type long int.
+C The following declaration specification should match C type long int
       INTEGER*8 N, IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), FY(*), JAC(N,*), H, RPAR(*)
       DOUBLE PRECISION V1(*), V2(*), V3(*)
 C
-      DOUBLE PRECISION  Y1, Y2, Y3
+      DOUBLE PRECISION Y1, Y2, Y3
 C
       Y1 = Y(1)
       Y2 = Y(2)
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_dnsL.out b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.out
index b4cd08a..1c93c14 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_dnsL.out
+++ b/examples/cvode/fcmix_serial/fcvRoberts_dnsL.out
@@ -7,26 +7,26 @@ At t =   0.2639E+00   y =   0.989965E+00  0.347056E-04  0.100000E-01
      Above is a root, INFO() =   0  1
 At t =   0.4000E+00   y =   0.985164E+00  0.338624E-04  0.148020E-01
 At t =   0.4000E+01   y =   0.905510E+00  0.224034E-04  0.944679E-01
-At t =   0.4000E+02   y =   0.715801E+00  0.918510E-05  0.284190E+00
-At t =   0.4000E+03   y =   0.450544E+00  0.322322E-05  0.549453E+00
-At t =   0.4000E+04   y =   0.183196E+00  0.894205E-06  0.816803E+00
-At t =   0.4000E+05   y =   0.389810E-01  0.162166E-06  0.961019E+00
-At t =   0.4000E+06   y =   0.493868E-02  0.198517E-07  0.995061E+00
-At t =   0.4000E+07   y =   0.517050E-03  0.206925E-08  0.999483E+00
-At t =   0.2081E+08   y =   0.100000E-03  0.400040E-09  0.999900E+00
+At t =   0.4000E+02   y =   0.715802E+00  0.918504E-05  0.284189E+00
+At t =   0.4000E+03   y =   0.450536E+00  0.322327E-05  0.549461E+00
+At t =   0.4000E+04   y =   0.183230E+00  0.894438E-06  0.816769E+00
+At t =   0.4000E+05   y =   0.389890E-01  0.162201E-06  0.961011E+00
+At t =   0.4000E+06   y =   0.493638E-02  0.198422E-07  0.995064E+00
+At t =   0.4000E+07   y =   0.516809E-03  0.206829E-08  0.999483E+00
+At t =   0.2079E+08   y =   0.100000E-03  0.400040E-09  0.999900E+00
      Above is a root, INFO() =  -1  0
-At t =   0.4000E+08   y =   0.520556E-04  0.208233E-09  0.999948E+00
-At t =   0.4000E+09   y =   0.520743E-05  0.208298E-10  0.999995E+00
-At t =   0.4000E+10   y =   0.523126E-06  0.209251E-11  0.999999E+00
-At t =   0.4000E+11   y =   0.500915E-07  0.200366E-12  0.100000E+01
+At t =   0.4000E+08   y =   0.520244E-04  0.208108E-09  0.999948E+00
+At t =   0.4000E+09   y =   0.520106E-05  0.208044E-10  0.999995E+00
+At t =   0.4000E+10   y =   0.525860E-06  0.210344E-11  0.999999E+00
+At t =   0.4000E+11   y =   0.693451E-07  0.277380E-12  0.100000E+01
 
-Final value of ydot =  -0.227814E-17 -0.911257E-23  0.227815E-17
+Final value of ydot =  -0.276733E-18 -0.110693E-23  0.276734E-18
 
 
 Final statistics:
 
- No. steps =  577   No. f-s =  838   No. J-s =   12   No. LU-s =  125
- No. nonlinear iterations =  834
+ No. steps =  542   No. f-s =  755   No. J-s =   11   No. LU-s =  107
+ No. nonlinear iterations =  751
  No. nonlinear convergence failures =    0
- No. error test failures =   33
- No. root function evals =  612
+ No. error test failures =   22
+ No. root function evals =  570
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_klu.f b/examples/cvode/fcmix_serial/fcvRoberts_klu.f
index 51a0961..a42e400 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_klu.f
+++ b/examples/cvode/fcmix_serial/fcvRoberts_klu.f
@@ -1,294 +1,314 @@
-!     ----------------------------------------------------------------
-!     Programmer(s): Ting Yan @ SMU
-!          Based on cvRoberts_klu.c and modified to Fortran 77
-!     ----------------------------------------------------------------
-!     Copyright (c) 2016, Southern Methodist University.
-!     All rights reserved.
-!     For details, see the LICENSE file.
-!     ----------------------------------------------------------------
-!     $Revision: $
-!     $Date: $
-!     ----------------------------------------------------------------
-!     FCVODE Example Problem: Robertson kinetics
-!
-!     The following is a simple example problem, with the coding
-!     needed for its solution by CVODE. The problem is from chemical
-!     kinetics, and consists of the following three rate equations:
-!
-!     dy1/dt = -.04*y1 + 1.e4*y2*y3
-!     dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2
-!     dy3/dt = 3.e7*y2**2
-!
-!     on the interval from t = 0.0 to t = 4.e10, with initial
-!     conditions:
-!
-!     y1 = 1.0, y2 = y3 = 0.
-!
-!     The problem is stiff. While integrating the system, we also
-!     use the root finding feature to find the points at which
-!     y1 = 1.e-4 or at which y3 = 0.01. The following coding solves
-!     this problem with CVODE, using the Fortran/C interface routine
-!     package. This solution uses the BDF method, Newton iteration with
-!     the the FCVKLU sparse direct linear solver,and a user-supplied
-!     Jacobian routine.
-!     It uses a scalar relative tolerance and a vector absolute
-!     tolerance. Output is printed in decades from t = .4 to t = 4.e10.
-!     Run statistics (optional outputs) are printed at the end.
-!     ----------------------------------------------------------------
-!
+C     ----------------------------------------------------------------
+C     Programmer(s): Ting Yan @ SMU
+C          Based on cvRoberts_klu.c and modified to Fortran 77
+C     ----------------------------------------------------------------
+C     Copyright (c) 2016, Southern Methodist University.
+C     All rights reserved.
+C     For details, see the LICENSE file.
+C     ----------------------------------------------------------------
+C     FCVODE Example Problem: Robertson kinetics
+C
+C     The following is a simple example problem, with the coding
+C     needed for its solution by CVODE. The problem is from chemical
+C     kinetics, and consists of the following three rate equations:
+C
+C     dy1/dt = -.04*y1 + 1.e4*y2*y3
+C     dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2
+C     dy3/dt = 3.e7*y2**2
+C
+C     on the interval from t = 0.0 to t = 4.e10, with initial
+C     conditions:
+C
+C     y1 = 1.0, y2 = y3 = 0.
+C
+C     The problem is stiff. While integrating the system, we also
+C     enable the root finding feature to find the points at which
+C     y1 = 1.e-4 or at which y3 = 0.01. The following coding solves
+C     this problem with CVODE, using the Fortran/C interface routine
+C     package. This solution uses the BDF method, Newton iteration with
+C     the the KLU sparse direct linear solver, and a user-supplied
+C     Jacobian routine.
+C     It uses a scalar relative tolerance and a vector absolute
+C     tolerance. Output is printed in decades from t = .4 to t = 4.e10.
+C     Run statistics (optional outputs) are printed at the end.
+C     ----------------------------------------------------------------
+C
       IMPLICIT NONE
-!
-      INTEGER IER, I, IERROOT
-      INTEGER LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
-      INTEGER METH, ITMETH, ITOL, ITASK, JOUT, NOUT
-      INTEGER INFO(2)
-!     The following declaration specification should match C type
-      INTEGER*8 IPAR, NEQ, IOUT(22), IVAL, MXNLI, MXETF
-      INTEGER INEQ, NNZ, SPARSETYPE, ORDERING
+C
+      INTEGER*4 IER, LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
+      INTEGER*4 METH, ITMETH, ITOL, ITASK, JOUT, NOUT, IERROOT
+      INTEGER*4 INFO(2)
+      INTEGER*4 I
+C The following declaration specification should match C type long int
+      INTEGER*8 NEQ, IPAR, IOUT(22), IVAL, MXNLI, MXETF, NNZ
+      INTEGER*4 SPARSETYPE
       DOUBLE PRECISION RTOL, T, T0, TOUT, H0, NLCONV
       DOUBLE PRECISION Y(3), ATOL(3), ROUT(6), RPAR
-!
-      DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/
-      DATA LNGE/12/, LNJE/17/
-
-!     Problem constant
-      NEQ = 3                   ! number of equations
-      Y(1) = 1.0D0              ! initial y components
+C
+      DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/,
+     1     LNGE/12/, LNJE/17/
+C
+C     Problem constants
+C     number of equations
+      NEQ = 3
+C     initial time
+      T0 = 0.0D0
+C     initial y components
+      Y(1) = 1.0D0
       Y(2) = 0.0D0
       Y(3) = 0.0D0
-      METH = 2                  ! basic integration method, 2 for BDF
-      ITMETH = 2                ! nonlinear iteration method, 2 for Newton iteration
-      ITOL = 2                  ! type for absolute tolerance, 2 for array
-      RTOL = 1.0D-4             ! scalar relative tolerance
-      ATOL(1) = 1.0D-6          ! vector absolute tolerance components
+C     basic integration method, 2 for BDF
+      METH = 2
+C     nonlinear iteration method, 2 for Newton iteration
+      ITMETH = 2
+C     type for absolute tolerance, 2 for array
+      ITOL = 2
+C     scalar relative tolerance
+      RTOL = 1.0D-4
+C     vector absolute tolerance components
+      ATOL(1) = 1.0D-6
       ATOL(2) = 1.0D-12
       ATOL(3) = 1.0D-4
-      T0 = 0.0D0                ! initial time
-      TOUT = 0.4D0              ! first output time
-      ITASK = 1                 ! Using in call FCVODE, 1 for normal mode
+C     first output time
+      TOUT = 0.4D0
+C     call CVODE in normal mode
+      ITASK = 1
       JOUT = 0
-      NOUT = 12                 ! number of output times
-!     
+C     number of output times
+      NOUT = 12
+C
       WRITE(6, 10) NEQ
  10   FORMAT('Klu example problem:'//
-     1     'Robertson kinetics, NEQ = ', I2//)
+     1       ' Robertson kinetics, NEQ = ', I2//)
 
-!
-      
-!     Create serial vector of length NEQ for I.C.
+C     create serial vector
       CALL FNVINITS(1, NEQ, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 20) IER
- 20      FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
-         STOP
+        WRITE(6,20) IER
+ 20     FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
+        STOP
+      ENDIF
+
+C     initialize sparse matrix module
+C     maximum number of nonzeros in the sparse Jac
+      NNZ = NEQ * NEQ
+C     CSC
+      SPARSETYPE = 0
+      CALL FSUNSPARSEMATINIT(1, NEQ, NEQ, NNZ, SPARSETYPE, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNSPARSEMATINIT returned IER = ',
+     1         I5)
+        STOP
       ENDIF
-!     
 
-!     Call FCVMALLOC to create the solver memory and specify the 
-!     Backward Differentiation Formula and the use of a Newton iteration
+C     initialize KLU sparse direct linear solver module
+      CALL FSUNKLUINIT(1, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,28) IER
+ 28     FORMAT(///' SUNDIALS_ERROR: FSUNKLUINIT returned IER = ', I5)
+        STOP
+      ENDIF
+
+C     Call FCVMALLOC to create the solver memory and specify the 
+C     Backward Differentiation Formula and the use of a Newton iteration
       CALL FCVMALLOC(T0, Y, METH, ITMETH, ITOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 30) IER
- 30      FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
-         STOP
+        WRITE(6,30) IER
+ 30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
+        STOP
       ENDIF
-!
-!     Set the FCVODE input
-      IVAL = 1000         ! max no. of internal steps before t_out
+
+C     Set the FCVODE input
+C     max no. of internal steps before t_out
+      IVAL = 1000
       CALL FCVSETIIN('MAX_NSTEPS', IVAL, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 31) IER
- 31      FORMAT(///' SUNDIALS_ERROR: FCVSETIIN returned IER = ', I5)
-         STOP
+        WRITE(6,31) IER
+ 31     FORMAT(///' SUNDIALS_ERROR: FCVSETIIN returned IER = ', I5)
+        STOP
       ENDIF
 
-      MXETF = 20          ! max no. of error test failures
+C     max no. of error test failures
+      MXETF = 20
       CALL FCVSETIIN('MAX_ERRFAIL', MXETF, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 31) IER
-         STOP
+        WRITE(6,31) IER
+        STOP
       ENDIF
       
-      H0 = 1.0D-4 * RTOL  ! initial step size
+C     initial step size
+      H0 = 1.0D-4 * RTOL
       CALL FCVSETRIN('INIT_STEP', H0, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 32) IER
- 32      FORMAT(///' SUNDIALS_ERROR: FCVSETRIN returned IER = ', I5)
-         STOP
+        WRITE(6,32) IER
+ 32     FORMAT(///' SUNDIALS_ERROR: FCVSETRIN returned IER = ', I5)
+        STOP
       ENDIF
       
-      NLCONV = 1.0D-4     ! coefficient in the nonlinear convergence test
+C     coefficient in the nonlinear convergence test
+      NLCONV = 1.0D-4
       CALL FCVSETRIN('NLCONV_COEF', NLCONV, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 32) IER
-         STOP
+        WRITE(6,32) IER
+        STOP
       ENDIF
-!
 
-!     Call FCVROOTINIT to specify the root function g with 2 components
+C     Call FCVROOTINIT to specify the root function g with 2 components
       CALL FCVROOTINIT(2, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 45) IER
- 45      FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ' I5)
-         CALL FCVFREE
-         STOP
+        WRITE(6,35) IER
+ 35     FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
+        CALL FCVFREE
+        STOP
       ENDIF
-!
-      
-!     Call FCVKLU to specify the FCVKLU sparse direct linear solver
-      INEQ = NEQ              ! convert to 'normal' integer type
-      NNZ = INEQ * INEQ       ! maximum number of nonzeros in the Jac matrix
-      SPARSETYPE = 0          ! CSC 
-      ORDERING = 1            ! matrix ordering desired, 1=COLAMD
-      CALL FCVKLU(INEQ, NNZ, SPARSETYPE, ORDERING, IER)
+
+C     attach the matrix and linear solver modules to CVDls interface
+      CALL FCVDLSINIT(IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 40) IER
- 40      FORMAT(///' SUNDIALS_ERROR: FCVKLU returned IER = ', I5)
-         CALL FCVFREE
-         STOP
+        WRITE(6,40) IER
+ 40     FORMAT(///' SUNDIALS_ERROR: FCVDLSINIT returned IER = ', I5)
+        CALL FCVFREE
+        STOP
       ENDIF
 
+C     indicate a sparse Jacobian function is provided
       CALL FCVSPARSESETJAC(IER)
-!     
+      IF (IER .NE. 0) THEN
+        WRITE(6,45) IER
+ 45     FORMAT(///' SUNDIALS_ERROR: FCVSPARSESETJAC returned IER = ',
+     1         I5)
+        CALL FCVFREE
+        STOP
+      ENDIF
 
-!     In loop, call FCVODE, print results, and test for error.
+C     In loop, call FCVODE, print results, and test for error.
       DO WHILE(JOUT .LT. NOUT)
-!
-         CALL FCVODE(TOUT, T, Y, ITASK, IER)
-!     
-         WRITE(6, 50) T, Y(1), Y(2), Y(3)
- 50      FORMAT('At t = ', E12.4, '   y = ', 3E14.6)
-!     
-         IF(IER .LT. 0) THEN
-            WRITE(6, 60) IER, IOUT(15)
- 60         FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER =  ', I5, /,
-     1             '                 Linear Solver returned IER = ', I5)
+C
+        CALL FCVODE(TOUT, T, Y, ITASK, IER)
+C
+        WRITE(6,50) T, Y(1), Y(2), Y(3)
+ 50     FORMAT('At t = ', E12.4, '   y = ', 3E14.6)
+C
+        IF (IER .LT. 0) THEN
+          WRITE(6,60) IER, IOUT(15)
+ 60       FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+     1           '                 Linear Solver returned IER = ', I5)
+          CALL FCVROOTFREE
+          CALL FCVFREE
+          STOP
+        ENDIF
+C
+        IF (IER .EQ. 2) THEN
+          CALL FCVROOTINFO(2, INFO, IERROOT)
+          IF (IERROOT .LT. 0) THEN
+            WRITE(6,65) IERROOT
+ 65         FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
+     1             I5)
             CALL FCVROOTFREE
             CALL FCVFREE
             STOP
-         ENDIF
-!
-         IF(IER .EQ. 2) THEN
-            CALL FCVROOTINFO(2, INFO, IERROOT)
-            IF (IERROOT .LT. 0) THEN
-               WRITE(6, 65) IERROOT
- 65            FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
-     1                I5)
-               CALL FCVROOTFREE
-               CALL FCVFREE
-               STOP
-            ENDIF
-            WRITE(6, 70) (INFO(I), I = 1, 2)
- 70         FORMAT(5X, 'rootfound = ', 2I3)
-         ENDIF
-!
-         IF (IER .EQ. 0) THEN
-            TOUT = TOUT * 10.0D0
-            JOUT = JOUT + 1
-         ENDIF
-!
+          ENDIF
+          WRITE(6,70) (INFO(I), I = 1, 2)
+ 70       FORMAT(5X, 'Above is a root, INFO() = ', 2I3)
+        ENDIF
+C
+        IF (IER .EQ. 0) THEN
+          TOUT = TOUT * 10.0D0
+          JOUT = JOUT + 1
+        ENDIF
+C
       ENDDO
 
-!     Obtain a derivative of the solution
-      CAlL FCVDKY(T, 1, Y, IER)
+C     obtain a derivative of the solution
+      CALL FCVDKY(T, 1, Y, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 80) IER
- 80      FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ' I4)
-         CALL FCVROOTFREE
-         CALL FCVFREE
-         STOP
+        WRITE(6,80) IER
+ 80     FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ', I4)
+        CALL FCVROOTFREE
+        CALL FCVFREE
+        STOP
       ENDIF
-      WRITE(6, 85) Y(1), Y(2), Y(3)
+      WRITE(6,85) Y(1), Y(2), Y(3)
  85   FORMAT(/'Final value of ydot = ', 3E14.6)
 
-!     Print out the statistic information
-      WRITE(6, 90) IOUT(LNST), IOUT(LNFE), IOUT(LNJE), IOUT(LNSETUP),
-     1             IOUT(LNNI), IOUT(LNCF), IOUT(LNETF), IOUT(LNGE)
+C     output run statistics
+      WRITE(6,90) IOUT(LNST), IOUT(LNFE), IOUT(LNJE), IOUT(LNSETUP),
+     1            IOUT(LNNI), IOUT(LNCF), IOUT(LNETF), IOUT(LNGE)
  90   FORMAT(//'Final statistics:'//
-     1       ' No. steps = ', I4, '    No. f-s = ', I4
-     2       '   No. J-s = ', I4, '    No. LU-s = ', I4/ 
+     1       ' No. steps = ', I4, '   No. f-s = ', I4,
+     2       '   No. J-s = ', I4, '   No. LU-s = ', I4/
      3       ' No. nonlinear iterations = ', I4/
      4       ' No. nonlinear convergence failures = ', I4/
      5       ' No. error test failures = ', I4/
      6       ' No. root function evals = ', I4)
-!
+C
       CALL FCVROOTFREE
       CALL FCVFREE
-!
+C
       STOP
       END
 
-!     ----------------------------------------------------------------
-      
+C     ----------------------------------------------------------------
+
       SUBROUTINE FCVFUN(T, Y, YDOT, IPAR, RPAR, IER)
-!     Fortran routine for right-hand side function      
+C     Fortran routine for right-hand side function
       IMPLICIT NONE
-      
-!     The following declaration specification should match C type long int
+C
+C The following declaration specification should match C type long int
       INTEGER*8 IPAR(*)
-      INTEGER IER
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
-      DOUBLE PRECISION Y1, Y2, Y3
-
-      Y1 = Y(1)
-      Y2 = Y(2)
-      Y3 = Y(3)
-      
-      YDOT(1) = -0.04D0 * Y1 + 1.0D4 * Y2 * Y3
-      YDOT(3) = 3.0D7 * Y2 * Y2
+C
+      YDOT(1) = -0.04D0 * Y(1) + 1.0D4 * Y(2) * Y(3)
+      YDOT(3) = 3.0D7 * Y(2) * Y(2)
       YDOT(2) = -YDOT(1) - YDOT(3)
-!
+C
       IER = 0
-!
+C
       RETURN
       END
 
-!     ----------------------------------------------------------------
-      
+C     ----------------------------------------------------------------
+
       SUBROUTINE FCVROOTFN(T, Y, G, IPAR, RPAR, IER)
-! Fortran routine for root finding
+C     Fortran routine for root finding
       IMPLICIT NONE
-
-!     The following declaration specification should match C type long int
-      INTEGER*8 IPAR(*)
-      INTEGER IER
+C
       DOUBLE PRECISION T, Y(*), G(*), RPAR(*)
-      DOUBLE PRECISION Y1, Y3
-      
-      Y1 = Y(1)
-      Y3 = Y(3)
-
-      G(1) = Y1 - 1.0D-4
-      G(2) = Y3 - 1.0D-2
-!
+C The following declaration specification should match C type long int
+      INTEGER*8 IPAR(*)
+      INTEGER*4 IER
+C
+      G(1) = Y(1) - 1.0D-4
+      G(2) = Y(3) - 1.0D-2
+C
       IER = 0
-!
+
       RETURN
       END
 
-!     ----------------------------------------------------------------
-      
+C     ----------------------------------------------------------------
+
       SUBROUTINE FCVSPJAC(T, Y, FY, N, NNZ, JDATA, JRVALS,
-     1     JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
-!     Fortran routine for user-supplied CSC format KLU Jacobian
+     1                    JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
+C     Fortran routine for user-supplied CSC format Jacobian
       IMPLICIT NONE
-
-!     The following declaration specification should match C type long int
-      INTEGER*8  IPAR(*)
-      INTEGER N, NNZ, IER
-      INTEGER JRVALS(NNZ), JCPTRS(N+1)
+C
+C The following declaration specification should match C type long int
+      INTEGER*8 N, NNZ, IPAR(*)
+      INTEGER*8 JRVALS(NNZ), JCPTRS(N+1)
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), FY(*), H, RPAR(*)
       DOUBLE PRECISION JDATA(NNZ)
       DOUBLE PRECISION WK1(*), WK2(*), WK3(*)
-      
-      ! Local data     
+C
       DOUBLE PRECISION Y1, Y2, Y3
-
+C
       Y1 = Y(1)
       Y2 = Y(2)
       Y3 = Y(3)
-
       JCPTRS(1) = 0
       JCPTRS(2) = 3
       JCPTRS(3) = 6
@@ -314,11 +334,8 @@
       JRVALS(8) = 1
       JDATA(9) = 0.0D0
       JRVALS(9) = 2
-
+C
       IER = 0
-!
+C
       RETURN
       END
-
-
-!     ------End file------------------
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_klu.out b/examples/cvode/fcmix_serial/fcvRoberts_klu.out
index d894e0e..ce95e33 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_klu.out
+++ b/examples/cvode/fcmix_serial/fcvRoberts_klu.out
@@ -1,10 +1,10 @@
 Klu example problem:
 
-Robertson kinetics, NEQ =  3
+ Robertson kinetics, NEQ =  3
 
 
 At t =   0.2636E+00   y =   0.989965E+00  0.347052E-04  0.100000E-01
-     rootfound =   0  1
+     Above is a root, INFO() =   0  1
 At t =   0.4000E+00   y =   0.985144E+00  0.338588E-04  0.148222E-01
 At t =   0.4000E+01   y =   0.905426E+00  0.223942E-04  0.945515E-01
 At t =   0.4000E+02   y =   0.715830E+00  0.918572E-05  0.284160E+00
@@ -14,7 +14,7 @@ At t =   0.4000E+05   y =   0.389806E-01  0.162165E-06  0.961019E+00
 At t =   0.4000E+06   y =   0.493776E-02  0.198479E-07  0.995062E+00
 At t =   0.4000E+07   y =   0.515949E-03  0.206485E-08  0.999484E+00
 At t =   0.2082E+08   y =   0.100000E-03  0.400040E-09  0.999900E+00
-     rootfound =  -1  0
+     Above is a root, INFO() =  -1  0
 At t =   0.4000E+08   y =   0.514789E-04  0.205926E-09  0.999949E+00
 At t =   0.4000E+09   y =   0.542638E-05  0.217056E-10  0.999995E+00
 At t =   0.4000E+10   y =   0.464797E-06  0.185919E-11  0.100000E+01
@@ -25,7 +25,7 @@ Final value of ydot =  -0.876832E-18 -0.350733E-23  0.876835E-18
 
 Final statistics:
 
- No. steps =  317    No. f-s =  941   No. J-s =   40    No. LU-s =  117
+ No. steps =  317   No. f-s =  941   No. J-s =   40   No. LU-s =  117
  No. nonlinear iterations =  940
  No. nonlinear convergence failures =    2
  No. error test failures =   11
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_sps.f b/examples/cvode/fcmix_serial/fcvRoberts_sps.f
index 31623dd..1ca6089 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_sps.f
+++ b/examples/cvode/fcmix_serial/fcvRoberts_sps.f
@@ -1,279 +1,324 @@
-!     ----------------------------------------------------------------
-!     Programmer(s): Ting Yan @ SMU
-!          Based on cvRoberts_sps.c and modified to Fortran 77
-!     ----------------------------------------------------------------
-!     Copyright (c) 2016, Southern Methodist University.
-!     All rights reserved.
-!     For details, see the LICENSE file.
-!     ----------------------------------------------------------------
-!     $Revision: $
-!     $Date: $
-!     ----------------------------------------------------------------
-!     FCVODE Example Problem: Robertson kinetics
-!
-!     The following is a simple example problem, with the coding
-!     needed for its solution by CVODE. The problem is from chemical
-!     kinetics, and consists of the following three rate equations:
-!
-!     dy1/dt = -.04*y1 + 1.e4*y2*y3
-!     dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2
-!     dy3/dt = 3.e7*y2**2
-!
-!     on the interval from t = 0.0 to t = 4.e10, with initial
-!     conditions:
-!
-!     y1 = 1.0, y2 = y3 = 0.
-!
-!     The problem is stiff. While integrating the system, we also
-!     use the root finding feature to find the points at which
-!     y1 = 1.e-4 or at which y3 = 0.01. The following coding solves
-!     this problem with CVODE, using the Fortran/C interface routine
-!     package. This solution uses the BDF method, Newton iteration with
-!     the the FCVSUPERLUMT sparse direct linear solver,and a user-supplied
-!     Jacobian routine.
-!     It uses a scalar relative tolerance and a vector absolute
-!     tolerance. Output is printed in decades from t = .4 to t = 4.e10.
-!     Run statistics (optional outputs) are printed at the end.
-!     ----------------------------------------------------------------
-!
+C     ----------------------------------------------------------------
+C     Programmer(s): Ting Yan @ SMU
+C          Based on cvRoberts_sps.c and modified to Fortran 77
+C     ----------------------------------------------------------------
+C     Copyright (c) 2016, Southern Methodist University.
+C     All rights reserved.
+C     For details, see the LICENSE file.
+C     ----------------------------------------------------------------
+C     FCVODE Example Problem: Robertson kinetics
+C
+C     The following is a simple example problem, with the coding
+C     needed for its solution by CVODE. The problem is from chemical
+C     kinetics, and consists of the following three rate equations:
+C
+C     dy1/dt = -.04*y1 + 1.e4*y2*y3
+C     dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2
+C     dy3/dt = 3.e7*y2**2
+C
+C     on the interval from t = 0.0 to t = 4.e10, with initial
+C     conditions:
+C
+C     y1 = 1.0, y2 = y3 = 0.
+C
+C     The problem is stiff. While integrating the system, we also
+C     enable the root finding feature to find the points at which
+C     y1 = 1.e-4 or at which y3 = 0.01. The following coding solves
+C     this problem with CVODE, using the Fortran/C interface routine
+C     package. This solution uses the BDF method, Newton iteration with
+C     the the SUPERLUMT sparse direct linear solver, and a user-supplied
+C     Jacobian routine.
+C     It uses a scalar relative tolerance and a vector absolute
+C     tolerance. Output is printed in decades from t = .4 to t = 4.e10.
+C     Run statistics (optional outputs) are printed at the end.
+C     ----------------------------------------------------------------
+C
       IMPLICIT NONE
-!
-      INTEGER IER, I, IERROOT
-      INTEGER LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
-      INTEGER METH, ITMETH, ITOL, ITASK, JOUT, NOUT
-      INTEGER INFO(2)
-!     The following declaration specification should match C type
-      INTEGER*8 IPAR, NEQ, IOUT(25), IVAL, MXNLI, MXETF
-      INTEGER INEQ, NNZ, NTHREADS, ORDERING
+C
+      INTEGER*4 IER, LNST, LNFE, LNSETUP, LNNI, LNCF, LNETF, LNJE, LNGE
+      INTEGER*4 METH, ITMETH, ITOL, ITASK, JOUT, NOUT, IERROOT
+      INTEGER*4 INFO(2)
+      INTEGER*4 I
+C The following declaration specification should match C type long int
+      INTEGER*8 NEQ, IPAR, IOUT(25), IVAL, MXNLI, MXETF, NNZ
+      INTEGER*4 SPARSETYPE, NTHREADS
       DOUBLE PRECISION RTOL, T, T0, TOUT, H0, NLCONV
       DOUBLE PRECISION Y(3), ATOL(3), ROUT(10), RPAR
-!
-      DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/
-      DATA LNGE/12/, LNJE/17/
-
-!     Problem constant
-      NEQ = 3                  ! number of equations
-      Y(1) = 1.0D0             ! initial y components
+C
+      DATA LNST/3/, LNFE/4/, LNETF/5/, LNCF/6/, LNNI/7/, LNSETUP/8/,
+     1     LNGE/12/, LNJE/17/
+C
+C     Problem constants
+C     number of equations
+      NEQ = 3
+C     initial time
+      T0 = 0.0D0
+C     initial y components
+      Y(1) = 1.0D0
       Y(2) = 0.0D0
       Y(3) = 0.0D0
-      METH = 2                 ! basic integration method, 2 for BDF
-      ITMETH =2                ! nonlinear iteration method, 2 for Newton iteration
-      ITOL = 2                 ! type for absolute tolerance, 2 for array
-      RTOL = 1.0D-4            ! scalar relative tolerance
-      ATOL(1) = 1.0D-8         ! vector absolute tolerance components
+C     basic integration method, 2 for BDF
+      METH = 2
+C     nonlinear iteration method, 2 for Newton iteration
+      ITMETH = 2
+C     type for absolute tolerance, 2 for array
+      ITOL = 2
+C     scalar relative tolerance
+      RTOL = 1.0D-4
+C     vector absolute tolerance components
+      ATOL(1) = 1.0D-8
       ATOL(2) = 1.0D-14
       ATOL(3) = 1.0D-6
-      T0 = 0.0D0               ! initial time
-      TOUT = 0.4D0             ! first output time
-      ITASK = 1                ! Using in call FCVODE, 1 for normal mode
+C     first output time
+      TOUT = 0.4D0
+C     call CVODE in normal mode
+      ITASK = 1
       JOUT = 0
-      NOUT = 12                ! number of output times 
-!
+C     number of output times
+      NOUT = 12
+C
       WRITE(6, 10) NEQ
  10   FORMAT('Superlu_mt example problem:'//
-     1       'Robertson kinetics, NEQ = ', I2//)
+     1       ' Robertson kinetics, NEQ = ', I2//)
 
-!
-!     Create serial vector of length NEQ for I.C.
+C     create serial vector
       CALL FNVINITS(1, NEQ, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 20) IER
- 20      FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
-         STOP
+        WRITE(6,20) IER
+ 20     FORMAT(///' SUNDIALS_ERROR: FNVINITS returned IER = ', I5)
+        STOP
+      ENDIF
+
+C     initialize sparse matrix module
+C     maximum number of nonzeros in the sparse Jac
+      NNZ = NEQ * NEQ
+C     CSC
+      SPARSETYPE = 0
+      CALL FSUNSPARSEMATINIT(1, NEQ, NEQ, NNZ, SPARSETYPE, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,25) IER
+ 25     FORMAT(///' SUNDIALS_ERROR: FSUNSPARSEMATINIT returned IER = ',
+     1         I5)
+        STOP
+      ENDIF
+
+C     initialize KLU sparse direct linear solver module
+C     number of threads to use in factorization
+      NTHREADS = 1
+      CALL FSUNSUPERLUMTINIT(1, NTHREADS, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,28) IER
+ 28     FORMAT(///' SUNDIALS_ERROR: FSUNKLUINIT returned IER = ', I5)
+        STOP
       ENDIF
-!
 
-!     Call FCVMALLOC to create the solver memory and specify the 
-!     Backward Differentiation Formula and the use of a Newton iteration
+C     Call FCVMALLOC to create the solver memory and specify the 
+C     Backward Differentiation Formula and the use of a Newton iteration
       CALL FCVMALLOC(T0, Y, METH, ITMETH, ITOL, RTOL, ATOL,
      1               IOUT, ROUT, IPAR, RPAR, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 30) IER
- 30      FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
-         STOP
+        WRITE(6,30) IER
+ 30     FORMAT(///' SUNDIALS_ERROR: FCVMALLOC returned IER = ', I5)
+        STOP
       ENDIF
-!
-!     Set the FCVODE input
-      IVAL = 900000           ! max no. of internal steps before t_out
+
+C     Set the FCVODE input
+C     max no. of internal steps before t_out
+      IVAL = 900000
       CALL FCVSETIIN('MAX_NSTEPS', IVAL, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,31) IER
+ 31     FORMAT(///' SUNDIALS_ERROR: FCVSETIIN returned IER = ', I5)
+        STOP
+      ENDIF
 
+C     max no. of iterations
       MXNLI = 8
       CALL FCVSETIIN('MAX_NITERS', MXNLI, IER)
+      IF (IER .NE. 0) THEN
+         WRITE(6, 31) IER
+         STOP
+      ENDIF
 
+C     max no. of error test failures
       MXETF = 20
       CALL FCVSETIIN('MAX_ERRFAIL', MXETF, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,31) IER
+        STOP
+      ENDIF
       
+C     initial step size
       H0 = 1.0D-4 * RTOL
       CALL FCVSETRIN('INIT_STEP', H0, IER)
-
+      IF (IER .NE. 0) THEN
+        WRITE(6,32) IER
+ 32     FORMAT(///' SUNDIALS_ERROR: FCVSETRIN returned IER = ', I5)
+        STOP
+      ENDIF
+      
+C     coefficient in the nonlinear convergence test
       NLCONV = 1.0D-7
       CALL FCVSETRIN('NLCONV_COEF', NLCONV, IER)
+      IF (IER .NE. 0) THEN
+        WRITE(6,32) IER
+        STOP
+      ENDIF
 
-
-!     Call FCVROOTINIT to specify the root function g with 2 components
+C     Call FCVROOTINIT to specify the root function g with 2 components
       CALL FCVROOTINIT(2, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 45) IER
- 45      FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ' I5)
-         CALL FCVROOTFREE
-         STOP
+        WRITE(6,35) IER
+ 35     FORMAT(///' SUNDIALS_ERROR: FCVROOTINIT returned IER = ', I5)
+        CALL FCVFREE
+        STOP
       ENDIF
-!
 
-!     Call FCVSUPERLUMT to specify the FCVKLU sparse direct linear solver
-      NTHREADS = 1        ! number of threads to use in factorization
-      INEQ = NEQ          ! covert to 'normal' integer type
-      NNZ = INEQ * INEQ   ! maximum number of nonzeros in the sparse Jac
-      ORDERING = 3        ! matrix ordering desired, 3=COLAMD 
-      CALL FCVSUPERLUMT(NTHREADS, INEQ, NNZ, ORDERING, IER)
+C     attach the matrix and linear solver modules to CVDls interface
+      CALL FCVDLSINIT(IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 40) IER
- 40      FORMAT(///' SUNDIALS_ERROR: FCVKLU returned IER = ', I5)
-         CALL FCVFREE
-         STOP
+        WRITE(6,40) IER
+ 40     FORMAT(///' SUNDIALS_ERROR: FCVDLSINIT returned IER = ', I5)
+        CALL FCVFREE
+        STOP
       ENDIF
 
+C     indicate a sparse Jacobian function is provided
       CALL FCVSPARSESETJAC(IER)
-!
+      IF (IER .NE. 0) THEN
+        WRITE(6,45) IER
+ 45     FORMAT(///' SUNDIALS_ERROR: FCVSPARSESETJAC returned IER = ',
+     1         I5)
+        CALL FCVFREE
+        STOP
+      ENDIF
 
-!     In loop, call FCVODE, print results, and test for error.
+C     In loop, call FCVODE, print results, and test for error.
       DO WHILE(JOUT .LT. NOUT)
-!
-         CALL FCVODE(TOUT, T, Y, ITASK, IER)
-!     
-         WRITE(6, 50) T, Y(1), Y(2), Y(3)
- 50      FORMAT('At t = ', E12.4, '   y = ', 3E14.6)
-!
-         IF(IER .LT. 0) THEN
-            WRITE(6, 60) IER, IOUT(15)
- 60         FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
-     1             '                 Linear Solver returned IER = ', I5)
+C
+        CALL FCVODE(TOUT, T, Y, ITASK, IER)
+C
+        WRITE(6,50) T, Y(1), Y(2), Y(3)
+ 50     FORMAT('At t = ', E12.4, '   y = ', 3E14.6)
+C
+        IF (IER .LT. 0) THEN
+          WRITE(6,60) IER, IOUT(15)
+ 60       FORMAT(///' SUNDIALS_ERROR: FCVODE returned IER = ', I5, /,
+     1           '                 Linear Solver returned IER = ', I5)
+          CALL FCVROOTFREE
+          CALL FCVFREE
+          STOP
+        ENDIF
+C
+        IF (IER .EQ. 2) THEN
+          CALL FCVROOTINFO(2, INFO, IERROOT)
+          IF (IERROOT .LT. 0) THEN
+            WRITE(6,65) IERROOT
+ 65         FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
+     1             I5)
             CALL FCVROOTFREE
             CALL FCVFREE
             STOP
-         ENDIF
-!
-         IF(IER .EQ. 2) THEN
-            CALL FCVROOTINFO(2, INFO, IERROOT)
-            IF (IERROOT .LT. 0) THEN
-               WRITE(6, 65) IERROOT
- 65            FORMAT(///' SUNDIALS_ERROR: FCVROOTINFO returned IER = ',
-     1                I5)
-               CALL FCVROOTFREE
-               CALL FCVFREE
-               STOP
-            ENDIF
-            WRITE(6, 70) (INFO(I), I = 1, 2)
- 70         FORMAT(5X, 'Above is a root, INFO() = ', 2I3)
-         ENDIF
-!
-         IF (IER .EQ. 0) THEN
-            TOUT = TOUT * 10.0D0
-            JOUT = JOUT + 1
-         ENDIF
-!
+          ENDIF
+          WRITE(6,70) (INFO(I), I = 1, 2)
+ 70       FORMAT(5X, 'Above is a root, INFO() = ', 2I3)
+        ENDIF
+C
+        IF (IER .EQ. 0) THEN
+          TOUT = TOUT * 10.0D0
+          JOUT = JOUT + 1
+        ENDIF
+C
       ENDDO
 
-!     Print out the derivatives at point the last step taken
+C     obtain a derivative of the solution
       CALL FCVDKY(T, 1, Y, IER)
       IF (IER .NE. 0) THEN
-         WRITE(6, 80) IER
- 80      FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ' I4)
-         CALL FCVROOTFREE
-         CALL FCVFREE
-         STOP
+        WRITE(6,80) IER
+ 80     FORMAT(///' SUNDIALS_ERROR: FCVDKY returned IER = ', I4)
+        CALL FCVROOTFREE
+        CALL FCVFREE
+        STOP
       ENDIF
-      WRITE(6, 85) Y(1), Y(2), Y(3)
+      WRITE(6,85) Y(1), Y(2), Y(3)
  85   FORMAT(/'Final value of ydot = ', 3E14.6)
-!
 
-!     Print out statistic information
-      WRITE(6, 90) IOUT(LNST), IOUT(LNFE), IOUT(LNJE), IOUT(LNSETUP),
-     1             IOUT(LNNI), IOUT(LNCF), IOUT(LNETF), IOUT(LNGE)
+C     output run statistics
+      WRITE(6,90) IOUT(LNST), IOUT(LNFE), IOUT(LNJE), IOUT(LNSETUP),
+     1            IOUT(LNNI), IOUT(LNCF), IOUT(LNETF), IOUT(LNGE)
  90   FORMAT(//'Final statistics:'//
-     1       ' No. steps = ', I4, '    No. f-s = ', I4
-     2       '   No. J-s = ', I4, '    No. LU-s = ', I4/ 
+     1       ' No. steps = ', I4, '   No. f-s = ', I4,
+     2       '   No. J-s = ', I4, '   No. LU-s = ', I4/
      3       ' No. nonlinear iterations = ', I4/
      4       ' No. nonlinear convergence failures = ', I4/
      5       ' No. error test failures = ', I4/
      6       ' No. root function evals = ', I4)
-!
+C
       CALL FCVROOTFREE
       CALL FCVFREE
-!
+C
       STOP
       END
 
-!     ----------------------------------------------------------------
-      
+C     ----------------------------------------------------------------
+
       SUBROUTINE FCVFUN(T, Y, YDOT, IPAR, RPAR, IER)
-! Fortran routine for right-hand side function       
+C     Fortran routine for right-hand side function
       IMPLICIT NONE
-!
-!     The following declaration specification should match C type long int
-      INTEGER*8 IPAR(1)
-      INTEGER IER
-      DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(1)
-      DOUBLE PRECISION Y1, Y2, Y3
-
-      Y1 = Y(1)
-      Y2 = Y(2)
-      Y3 = Y(3)
-      
-      YDOT(1) = -0.04D0 * Y1 + 1.0D4 * Y2 * Y3
-      YDOT(3) = 3.0D7 * Y2 * Y2
+C
+C The following declaration specification should match C type long int
+      INTEGER*8 IPAR(*)
+      INTEGER*4 IER
+      DOUBLE PRECISION T, Y(*), YDOT(*), RPAR(*)
+C
+      YDOT(1) = -0.04D0 * Y(1) + 1.0D4 * Y(2) * Y(3)
+      YDOT(3) = 3.0D7 * Y(2) * Y(2)
       YDOT(2) = -YDOT(1) - YDOT(3)
-!
+C
       IER = 0
-!
+C
       RETURN
       END
 
-!     ----------------------------------------------------------------
-      
+C     ----------------------------------------------------------------
+
       SUBROUTINE FCVROOTFN(T, Y, G, IPAR, RPAR, IER)
-! Fortran routine for root finding
+C     Fortran routine for root finding
       IMPLICIT NONE
-
-!     The following declaration specification should match C type long int
-      INTEGER*8 IPAR(*)
-      INTEGER IER
+C
       DOUBLE PRECISION T, Y(*), G(*), RPAR(*)
-      DOUBLE PRECISION Y1, Y3
-      
-      Y1 = Y(1)
-      Y3 = Y(3)
-
-      G(1) = Y1 - 1.0D-4
-      G(2) = Y3 - 1.0D-2
-!
+C The following declaration specification should match C type long int
+      INTEGER*8 IPAR(*)
+      INTEGER*4 IER
+C
+      G(1) = Y(1) - 1.0D-4
+      G(2) = Y(3) - 1.0D-2
+C
       IER = 0
-!
+
       RETURN
       END
 
-!     ----------------------------------------------------------------
-      
+C     ----------------------------------------------------------------
+
       SUBROUTINE FCVSPJAC(T, Y, FY, N, NNZ, JDATA, JRVALS,
      1                    JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
-! Fortran routine for user-supplied CSC format KLU Jacobian 
+C     Fortran routine for user-supplied CSC format Jacobian
       IMPLICIT NONE
-
-!     The following declaration specification should match C type
-      INTEGER*8 IPAR(*)
-      INTEGER N, NNZ, IER
-      INTEGER JRVALS(NNZ), JCPTRS(N+1)
+C
+C The following declaration specification should match C type long int
+      INTEGER*8 N, NNZ, IPAR(*)
+      INTEGER*8 JRVALS(NNZ), JCPTRS(N+1)
+      INTEGER*4 IER
       DOUBLE PRECISION T, Y(*), FY(*), H, RPAR(*)
       DOUBLE PRECISION JDATA(NNZ)
       DOUBLE PRECISION WK1(*), WK2(*), WK3(*)
-      
-      ! Local data     
+C
       DOUBLE PRECISION Y1, Y2, Y3
-
+C
       Y1 = Y(1)
       Y2 = Y(2)
       Y3 = Y(3)
-
       JCPTRS(1) = 0
       JCPTRS(2) = 3
       JCPTRS(3) = 6
@@ -299,8 +344,8 @@
       JRVALS(8) = 1
       JDATA(9) = 0.0D0
       JRVALS(9) = 2
-!
+C
       IER = 0
-!
+C
       RETURN
       END
diff --git a/examples/cvode/fcmix_serial/fcvRoberts_sps.out b/examples/cvode/fcmix_serial/fcvRoberts_sps.out
index 0b88034..613fe9b 100644
--- a/examples/cvode/fcmix_serial/fcvRoberts_sps.out
+++ b/examples/cvode/fcmix_serial/fcvRoberts_sps.out
@@ -1,6 +1,6 @@
 Superlu_mt example problem:
 
-Robertson kinetics, NEQ =  3
+ Robertson kinetics, NEQ =  3
 
 
 At t =   0.2640E+00   y =   0.989965E+00  0.347056E-04  0.100000E-01
@@ -25,7 +25,7 @@ Final value of ydot =  -0.166627E-17 -0.666508E-23  0.166628E-17
 
 Final statistics:
 
- No. steps =  364    No. f-s = 2056   No. J-s =   18    No. LU-s =   98
+ No. steps =  364   No. f-s = 2056   No. J-s =   18   No. LU-s =   98
  No. nonlinear iterations = 2055
  No. nonlinear convergence failures =    0
  No. error test failures =   13
diff --git a/examples/cvode/parallel/CMakeLists.txt b/examples/cvode/parallel/CMakeLists.txt
index b44b707..59d1382 100644
--- a/examples/cvode/parallel/CMakeLists.txt
+++ b/examples/cvode/parallel/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4957 $
-# $Date: 2016-09-23 12:21:47 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,78 +12,81 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for CVODE parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable CVODE_examples with the names of the parallel CVODE examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(CVODE_examples
-  "cvAdvDiff_diag_p\;2\;4"
-  "cvAdvDiff_non_p\;2\;2"
-  "cvDiurnal_kry_bbd_p\;2\;4"
-  "cvDiurnal_kry_p\;2\;4"
+  "cvAdvDiff_diag_p\;2\;4\;develop"
+  "cvAdvDiff_non_p\;2\;2\;develop"
+  "cvDiurnal_kry_bbd_p\;2\;4\;develop"
+  "cvDiurnal_kry_p\;2\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the C compiler to the MPICC script.
 # If not, then add the MPI include directory for MPI headers.
-
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODE_LIB sundials_cvode_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODE_LIB sundials_cvode_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-IF(HYPRE_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${HYPRE_LIBRARIES})
-ENDIF(HYPRE_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${CVODE_examples})
 
-# Add the build and install targets for each CVODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
 
-FOREACH(example_tuple ${CVODE_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPICC)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${CVODE_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -95,30 +95,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "CVODE")
   SET(SOLVER_LIB "sundials_cvode")
-  FOREACH(example_tuple ${CVODE_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${CVODE_examples})
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(CVODE_example EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvode/parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/cvode/parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/cvode/parallel/README b/examples/cvode/parallel/README
index 0f42964..d3767e3 100644
--- a/examples/cvode/parallel/README
+++ b/examples/cvode/parallel/README
@@ -10,7 +10,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -21,7 +20,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -35,7 +37,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvode/parallel/cvAdvDiff_diag_p.c b/examples/cvode/parallel/cvAdvDiff_diag_p.c
index b431d9a..5241f88 100644
--- a/examples/cvode/parallel/cvAdvDiff_diag_p.c
+++ b/examples/cvode/parallel/cvAdvDiff_diag_p.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George Byrne,
  *                and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -19,7 +16,7 @@
  * The PDE is discretized on a uniform grid of size MX+2 with
  * central differencing, and with boundary values eliminated,
  * leaving an ODE system of size NEQ = MX.
- * This program solves the problem with the ADAMS integration method, 
+ * This program solves the problem with the ADAMS integration method,
  * and with Newton iteration using diagonal approximate Jacobians.
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .5, 1.0, ..., 5.
@@ -34,13 +31,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>              /* prototypes for CVODE fcts. */
-#include <cvode/cvode_diag.h>         /* prototypes for CVODE diagonal solver */
-#include <nvector/nvector_parallel.h> /* definition of N_Vector and macros */
-#include <sundials/sundials_types.h>  /* definition of realtype */
-#include <sundials/sundials_math.h>   /* definition of EXP */
+#include <cvode/cvode.h>                  /* prototypes for CVODE fcts., consts. */
+#include <cvode/cvode_diag.h>             /* prototypes for CVODE diagonal solver */
+#include <nvector/nvector_parallel.h>     /* access to MPI-parallel N_Vector     */
+#include <sundials/sundials_types.h>      /* definition of type realtype         */
+#include <sundials/sundials_math.h>       /* definition of ABS and EXP           */
 
-#include <mpi.h>                      /* MPI constants and types */
+#include <mpi.h> /* MPI constants and types */
 
 /* Problem Constants */
 
@@ -55,7 +52,7 @@
 #define DTOUT RCONST(0.5)    /* output time increment     */
 #define NOUT  10             /* number of output times    */
 
-/* Type : UserData 
+/* Type : UserData
    contains grid constants, parallel machine parameters, work array. */
 
 typedef struct {
@@ -67,8 +64,8 @@ typedef struct {
 
 /* Private Helper Functions */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length,
-                  long int my_base);
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length,
+                  sunindextype my_base);
 
 static void PrintIntro(int npes);
 
@@ -93,7 +90,8 @@ int main(int argc, char *argv[])
   UserData data;
   void *cvode_mem;
   int iout, flag, my_pe, npes;
-  long int local_N, nperpe, nrem, my_base, nst;
+  sunindextype local_N, nperpe, nrem, my_base;
+  long int nst;
 
   MPI_Comm comm;
 
@@ -132,7 +130,7 @@ int main(int argc, char *argv[])
 
   SetIC(u, dx, local_N, my_base);  /* Initialize u vector */
 
-  /* Call CVodeCreate to create the solver memory and specify the 
+  /* Call CVodeCreate to create the solver memory and specify the
    * Adams-Moulton LMM and the use of a functional iteration */
   cvode_mem = CVodeCreate(CV_ADAMS, CV_NEWTON);
   if(check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
@@ -151,8 +149,9 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1);
 
+  /* Call CVDiag to create and attach CVODE-specific diagonal linear solver */
   flag = CVDiag(cvode_mem);
-  if (check_flag(&flag, "CVDiag", 1, my_pe)) return(1);
+  if(check_flag(&flag, "CVDiag", 1, my_pe)) return(1);
 
   if (my_pe == 0) PrintIntro(npes);
 
@@ -174,7 +173,7 @@ int main(int argc, char *argv[])
     if (my_pe == 0) PrintData(t, umax, nst);
   }
 
-  if (my_pe == 0) 
+  if (my_pe == 0)
     PrintFinalStats(cvode_mem);  /* Print some final statistics */
 
   N_VDestroy_Parallel(u);        /* Free the u vector */
@@ -190,16 +189,16 @@ int main(int argc, char *argv[])
 
 /* Set initial conditions in u vector */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length,
-                  long int my_base)
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length,
+                  sunindextype my_base)
 {
   int i;
-  long int iglobal;
+  sunindextype iglobal;
   realtype x;
   realtype *udata;
 
   /* Set pointer to data array and get local length of u. */
-  udata = N_VGetArrayPointer_Parallel(u);
+  udata = N_VGetArrayPointer(u);
   my_length = N_VGetLocalLength_Parallel(u);
 
   /* Load initial profile into u vector */
@@ -207,7 +206,7 @@ static void SetIC(N_Vector u, realtype dx, long int my_length,
     iglobal = my_base + i;
     x = iglobal*dx;
     udata[i-1] = x*(XMAX - x)*SUNRexp(RCONST(2.0)*x);
-  }  
+  }
 }
 
 /* Print problem introduction */
@@ -243,7 +242,7 @@ static void PrintFinalStats(void *cvode_mem)
 {
   long int nst, nfe, nni, ncfn, netf;
   int flag;
-  
+
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1, 0);
   flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
@@ -274,8 +273,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   MPI_Status status;
   MPI_Comm comm;
 
-  udata = N_VGetArrayPointer_Parallel(u);
-  dudata = N_VGetArrayPointer_Parallel(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed problem constants from data */
   data = (UserData) user_data;
@@ -284,9 +283,9 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 
   /* Extract parameters for parallel computation. */
   comm = data->comm;
-  npes = data->npes;           /* Number of processes. */ 
+  npes = data->npes;           /* Number of processes. */
   my_pe = data->my_pe;         /* Current process number. */
-  my_length = N_VGetLocalLength_Parallel(u); /* Number of local elements of u. */ 
+  my_length = N_VGetLocalLength_Parallel(u); /* Number of local elements of u. */
   z = data->z;
 
   /* Compute related parameters. */
@@ -303,7 +302,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
    if (my_pe != 0)
      MPI_Send(&z[1], 1, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm);
    if (my_pe != last_pe)
-     MPI_Send(&z[my_length], 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm);   
+     MPI_Send(&z[my_length], 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm);
 
   /* Receive needed data from processes before and after current process. */
    if (my_pe != 0)
@@ -311,7 +310,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
    else z[0] = ZERO;
    if (my_pe != last_pe)
      MPI_Recv(&z[my_length+1], 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm,
-              &status);   
+              &status);
    else z[my_length + 1] = ZERO;
 
   /* Loop over all grid points in current process. */
diff --git a/examples/cvode/parallel/cvAdvDiff_non_p.c b/examples/cvode/parallel/cvAdvDiff_non_p.c
index 647db70..2d43490 100644
--- a/examples/cvode/parallel/cvAdvDiff_non_p.c
+++ b/examples/cvode/parallel/cvAdvDiff_non_p.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George Byrne,
  *                and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -34,12 +31,12 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>              /* prototypes for CVODE fcts. */
-#include <nvector/nvector_parallel.h> /* definition of N_Vector and macros */
-#include <sundials/sundials_types.h>  /* definition of realtype */
-#include <sundials/sundials_math.h>   /* definition of EXP */
+#include <cvode/cvode.h>              /* prototypes for CVODE fcts., consts.    */
+#include <nvector/nvector_parallel.h> /* access to MPI-parallel N_Vector        */
+#include <sundials/sundials_types.h>  /* definition of type realtype            */
+#include <sundials/sundials_math.h>   /* definition of ABS and EXP              */
 
-#include <mpi.h>                      /* MPI constants and types */
+#include <mpi.h> /* MPI constants and types */
 
 /* Problem Constants */
 
@@ -54,7 +51,7 @@
 #define DTOUT RCONST(0.5)    /* output time increment     */
 #define NOUT  10             /* number of output times    */
 
-/* Type : UserData 
+/* Type : UserData
    contains grid constants, parallel machine parameters, work array. */
 
 typedef struct {
@@ -66,8 +63,8 @@ typedef struct {
 
 /* Private Helper Functions */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length,
-                  long int my_base);
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length,
+                  sunindextype my_base);
 
 static void PrintIntro(int npes);
 
@@ -92,7 +89,8 @@ int main(int argc, char *argv[])
   UserData data;
   void *cvode_mem;
   int iout, flag, my_pe, npes;
-  long int local_N, nperpe, nrem, my_base, nst;
+  sunindextype local_N, nperpe, nrem, my_base;
+  long int nst;
 
   MPI_Comm comm;
 
@@ -131,7 +129,7 @@ int main(int argc, char *argv[])
 
   SetIC(u, dx, local_N, my_base);  /* Initialize u vector */
 
-  /* Call CVodeCreate to create the solver memory and specify the 
+  /* Call CVodeCreate to create the solver memory and specify the
    * Adams-Moulton LMM and the use of a functional iteration */
   cvode_mem = CVodeCreate(CV_ADAMS, CV_FUNCTIONAL);
   if(check_flag((void *)cvode_mem, "CVodeCreate", 0, my_pe)) MPI_Abort(comm, 1);
@@ -170,7 +168,7 @@ int main(int argc, char *argv[])
     if (my_pe == 0) PrintData(t, umax, nst);
   }
 
-  if (my_pe == 0) 
+  if (my_pe == 0)
     PrintFinalStats(cvode_mem);  /* Print some final statistics */
 
   N_VDestroy_Parallel(u);        /* Free the u vector */
@@ -186,16 +184,16 @@ int main(int argc, char *argv[])
 
 /* Set initial conditions in u vector */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length,
-                  long int my_base)
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length,
+                  sunindextype my_base)
 {
   int i;
-  long int iglobal;
+  sunindextype iglobal;
   realtype x;
   realtype *udata;
 
   /* Set pointer to data array and get local length of u. */
-  udata = N_VGetArrayPointer_Parallel(u);
+  udata = N_VGetArrayPointer(u);
   my_length = N_VGetLocalLength_Parallel(u);
 
   /* Load initial profile into u vector */
@@ -203,7 +201,7 @@ static void SetIC(N_Vector u, realtype dx, long int my_length,
     iglobal = my_base + i;
     x = iglobal*dx;
     udata[i-1] = x*(XMAX - x)*SUNRexp(RCONST(2.0)*x);
-  }  
+  }
 }
 
 /* Print problem introduction */
@@ -238,7 +236,7 @@ static void PrintFinalStats(void *cvode_mem)
 {
   long int nst, nfe, nni, ncfn, netf;
   int flag;
-  
+
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1, 0);
   flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
@@ -269,8 +267,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   MPI_Status status;
   MPI_Comm comm;
 
-  udata = N_VGetArrayPointer_Parallel(u);
-  dudata = N_VGetArrayPointer_Parallel(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed problem constants from data */
   data = (UserData) user_data;
@@ -279,9 +277,9 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 
   /* Extract parameters for parallel computation. */
   comm = data->comm;
-  npes = data->npes;           /* Number of processes. */ 
+  npes = data->npes;           /* Number of processes. */
   my_pe = data->my_pe;         /* Current process number. */
-  my_length = N_VGetLocalLength_Parallel(u); /* Number of local elements of u. */ 
+  my_length = N_VGetLocalLength_Parallel(u); /* Number of local elements of u. */
   z = data->z;
 
   /* Compute related parameters. */
@@ -298,7 +296,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
    if (my_pe != 0)
      MPI_Send(&z[1], 1, PVEC_REAL_MPI_TYPE, my_pe_m1, 0, comm);
    if (my_pe != last_pe)
-     MPI_Send(&z[my_length], 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm);   
+     MPI_Send(&z[my_length], 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm);
 
   /* Receive needed data from processes before and after current process. */
    if (my_pe != 0)
@@ -306,7 +304,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
    else z[0] = ZERO;
    if (my_pe != last_pe)
      MPI_Recv(&z[my_length+1], 1, PVEC_REAL_MPI_TYPE, my_pe_p1, 0, comm,
-              &status);   
+              &status);
    else z[my_length + 1] = ZERO;
 
   /* Loop over all grid points in current process. */
diff --git a/examples/cvode/parallel/cvAdvDiff_non_p.out b/examples/cvode/parallel/cvAdvDiff_non_p.out
index be50625..58432f6 100644
--- a/examples/cvode/parallel/cvAdvDiff_non_p.out
+++ b/examples/cvode/parallel/cvAdvDiff_non_p.out
@@ -1,21 +1,21 @@
 
  1-D advection-diffusion equation, mesh size = 10 
 
- Number of PEs =   4 
+ Number of PEs =   2 
 
 At t = 0.00  max.norm(u) =  1.569909e+01  nst =   0 
 At t = 0.50  max.norm(u) =  3.052881e+00  nst = 113 
 At t = 1.00  max.norm(u) =  8.753188e-01  nst = 191 
 At t = 1.50  max.norm(u) =  2.494926e-01  nst = 265 
-At t = 2.00  max.norm(u) =  7.109707e-02  nst = 339 
-At t = 2.50  max.norm(u) =  2.026223e-02  nst = 418 
-At t = 3.00  max.norm(u) =  5.777332e-03  nst = 486 
-At t = 3.50  max.norm(u) =  1.650483e-03  nst = 563 
-At t = 4.00  max.norm(u) =  4.754357e-04  nst = 646 
-At t = 4.50  max.norm(u) =  1.374222e-04  nst = 715 
-At t = 5.00  max.norm(u) =  3.937469e-05  nst = 795 
+At t = 2.00  max.norm(u) =  7.109437e-02  nst = 332 
+At t = 2.50  max.norm(u) =  2.026176e-02  nst = 405 
+At t = 3.00  max.norm(u) =  5.769193e-03  nst = 468 
+At t = 3.50  max.norm(u) =  1.651582e-03  nst = 541 
+At t = 4.00  max.norm(u) =  4.764197e-04  nst = 623 
+At t = 4.50  max.norm(u) =  1.370219e-04  nst = 704 
+At t = 5.00  max.norm(u) =  3.990405e-05  nst = 785 
 
 Final Statistics: 
 
-nst = 795     nfe  = 1465    nni = 1461    ncfn = 146     netf = 5
+nst = 785     nfe  = 1442    nni = 1438    ncfn = 140     netf = 5
  
diff --git a/examples/cvode/parallel/cvDiurnal_kry_bbd_p.c b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.c
index e5a00b6..9497c3f 100644
--- a/examples/cvode/parallel/cvDiurnal_kry_bbd_p.c
+++ b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
  *                Radu Serban  @ LLNL
  * --------------------------------------------------------------------
@@ -32,7 +29,7 @@
  * neq = 2*MX*MY.
  *
  * The solution is done with the BDF/GMRES method (i.e. using the
- * CVSPGMR linear solver) and a block-diagonal matrix with banded
+ * SUNSPGMR linear solver) and a block-diagonal matrix with banded
  * blocks as a preconditioner, using the CVBBDPRE module.
  * Each block is generated using difference quotients, with
  * half-bandwidths mudq = mldq = 2*MXSUB, but the retained banded
@@ -55,14 +52,15 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>              /* prototypes for CVODE fcts. */
-#include <cvode/cvode_spgmr.h>        /* prototypes and constants for CVSPGMR */
-#include <cvode/cvode_bbdpre.h>       /* prototypes for CVBBDPRE module */
-#include <nvector/nvector_parallel.h> /* def. of N_Vector, macro NV_DATA_P */
-#include <sundials/sundials_types.h>  /* definitions of realtype, booleantype */
-#include <sundials/sundials_math.h>   /* definition of macros SUNSQR and EXP */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_parallel.h>  /* access to MPI-parallel N_Vector      */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvode/cvode_spils.h>         /* access to CVSpils interface          */
+#include <cvode/cvode_bbdpre.h>        /* access to CVBBDPRE module            */
+#include <sundials/sundials_types.h>   /* definitions of realtype, booleantype */
+#include <sundials/sundials_math.h>    /* definition of macros SUNSQR and EXP  */
 
-#include <mpi.h>                      /* MPI constants and types */
+#include <mpi.h> /* MPI constants and types */
 
 
 /* Problem Constants */
@@ -116,31 +114,31 @@ typedef struct {
   realtype q4, om, dx, dy, hdco, haco, vdco;
   realtype uext[NVARS*(MXSUB+2)*(MYSUB+2)];
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmxsub2, Nlocal;
+  sunindextype nvmxsub, nvmxsub2, Nlocal;
   MPI_Comm comm;
 } *UserData;
 
 /* Prototypes of private helper functions */
 
-static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+static void InitUserData(int my_pe, sunindextype local_N, MPI_Comm comm,
                          UserData data);
 static void SetInitialProfiles(N_Vector u, UserData data);
-static void PrintIntro(int npes, long int mudq, long int mldq,
-		       long int mukeep, long int mlkeep);
+static void PrintIntro(int npes, sunindextype mudq, sunindextype mldq,
+		       sunindextype mukeep, sunindextype mlkeep);
 static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
                         N_Vector u, realtype t);
 static void PrintFinalStats(void *cvode_mem);
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype uarray[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[]);
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[]);
 
 static void fucomm(realtype t, N_Vector u, void *user_data);
@@ -151,7 +149,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
 /* Prototype of functions called by the CVBBDPRE module */
 
-static int flocal(long int Nlocal, realtype t, N_Vector u,
+static int flocal(sunindextype Nlocal, realtype t, N_Vector u,
                   N_Vector udot, void *user_data);
 
 /* Private function to check function return values */
@@ -163,14 +161,16 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   realtype abstol, reltol, t, tout;
   N_Vector u;
   int iout, my_pe, npes, flag, jpre;
-  long int neq, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype neq, local_N, mudq, mldq, mukeep, mlkeep;
   MPI_Comm comm;
 
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
   u = NULL;
 
@@ -226,17 +226,21 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR with left
-     preconditioning and the default maximum Krylov dimension maxl  */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVBBDSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Create SPGMR solver structure -- use left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+
+  /* Attach SPGMR solver structure to CVSpils interface */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Initialize BBD preconditioner */
   mudq = mldq = NVARS*MXSUB;
   mukeep = mlkeep = NVARS;
   flag = CVBBDPrecInit(cvode_mem, local_N, mudq, mldq, 
                        mukeep, mlkeep, ZERO, flocal, NULL);
-  if(check_flag(&flag, "CVBBDPrecAlloc", 1, my_pe)) MPI_Abort(comm, 1);
+  if(check_flag(&flag, "CVBBDPrecInit", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Print heading */
   if (my_pe == 0) PrintIntro(npes, mudq, mldq, mukeep, mlkeep);
@@ -256,8 +260,8 @@ int main(int argc, char *argv[])
     flag = CVBBDPrecReInit(cvode_mem, mudq, mldq, ZERO);
     if(check_flag(&flag, "CVBBDPrecReInit", 1, my_pe)) MPI_Abort(comm, 1);
 
-    flag = CVSpilsSetPrecType(cvode_mem, PREC_RIGHT);
-    check_flag(&flag, "CVSpilsSetPrecType", 1, my_pe);
+    flag = SUNSPGMRSetPrecType(LS, PREC_RIGHT);
+    check_flag(&flag, "SUNSPGMRSetPrecType", 1, my_pe);
 
     if (my_pe == 0) {
       printf("\n\n-------------------------------------------------------");
@@ -290,6 +294,7 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(u);
   free(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   MPI_Finalize();
 
@@ -300,7 +305,7 @@ int main(int argc, char *argv[])
 
 /* Load constants in data */
 
-static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+static void InitUserData(int my_pe, sunindextype local_N, MPI_Comm comm,
                          UserData data)
 {
   int isubx, isuby;
@@ -333,13 +338,13 @@ static void SetInitialProfiles(N_Vector u, UserData data)
 {
   int isubx, isuby;
   int lx, ly, jx, jy;
-  long int offset;
+  sunindextype offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *uarray;
 
   /* Set pointer to data array in vector u */
 
-  uarray = N_VGetArrayPointer_Parallel(u);
+  uarray = N_VGetArrayPointer(u);
 
   /* Get mesh spacings, and subgrid indices for this PE */
 
@@ -372,16 +377,16 @@ static void SetInitialProfiles(N_Vector u, UserData data)
 
 /* Print problem introduction */
 
-static void PrintIntro(int npes, long int mudq, long int mldq,
-		       long int mukeep, long int mlkeep)
+static void PrintIntro(int npes, sunindextype mudq, sunindextype mldq,
+		       sunindextype mukeep, sunindextype mlkeep)
 {
   printf("\n2-species diurnal advection-diffusion problem\n");
   printf("  %d by %d mesh on %d processors\n", MX, MY, npes);
   printf("  Using CVBBDPRE preconditioner module\n");
   printf("    Difference-quotient half-bandwidths are");
-  printf(" mudq = %ld,  mldq = %ld\n", mudq, mldq);
+  printf(" mudq = %ld,  mldq = %ld\n", (long int) mudq, (long int) mldq);
   printf("    Retained band block half-bandwidths are");
-  printf(" mukeep = %ld,  mlkeep = %ld", mukeep, mlkeep);
+  printf(" mukeep = %ld,  mlkeep = %ld", (long int) mukeep, (long int) mlkeep);
 
   return;
 }
@@ -392,12 +397,13 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
                         N_Vector u, realtype t)
 {
   int qu, flag, npelast;
-  long int i0, i1, nst;
+  long int nst;
+  sunindextype i0, i1;
   realtype hu, *uarray, tempu[2];
   MPI_Status status;
 
   npelast = NPEX*NPEY - 1;
-  uarray = N_VGetArrayPointer_Parallel(u);
+  uarray = N_VGetArrayPointer(u);
 
   /* Send c1,c2 at top right mesh point to PE 0 */
   if (my_pe == npelast) {
@@ -447,8 +453,8 @@ static void PrintFinalStats(void *cvode_mem)
 {
   long int lenrw, leniw ;
   long int lenrwLS, leniwLS;
-  long int lenrwBBDP, leniwBBDP, ngevalsBBDP;
-  long int nst, nfe, nsetups, nni, ncfn, netf;
+  long int lenrwBBDP, leniwBBDP;
+  long int nst, nfe, nsetups, nni, ncfn, netf, ngevalsBBDP;
   long int nli, npe, nps, ncfl, nfeLS;
   int flag;
 
@@ -481,9 +487,9 @@ static void PrintFinalStats(void *cvode_mem)
   check_flag(&flag, "CVSpilsGetNumRhsEvals", 1, 0);
 
   printf("\nFinal Statistics: \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwls = %5ld     leniwls = %5ld\n", lenrwLS, leniwLS);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwls = %5ld     leniwls = %5ld\n"  , lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfels   = %5ld\n"  , nfe, nfeLS);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
   printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
@@ -495,7 +501,7 @@ static void PrintFinalStats(void *cvode_mem)
   flag = CVBBDPrecGetNumGfnEvals(cvode_mem, &ngevalsBBDP);
   check_flag(&flag, "CVBBDPrecGetNumGfnEvals", 1, 0);
   printf("In CVBBDPRE: real/integer local work space sizes = %ld, %ld\n",
-	 lenrwBBDP, leniwBBDP);  
+	 lenrwBBDP, leniwBBDP);
   printf("             no. flocal evals. = %ld\n",ngevalsBBDP);
 }
  
@@ -503,11 +509,11 @@ static void PrintFinalStats(void *cvode_mem)
 
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype uarray[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -557,10 +563,10 @@ static void BSend(MPI_Comm comm,
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
 
@@ -599,11 +605,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[],
 
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
 
@@ -653,11 +659,11 @@ static void fucomm(realtype t, N_Vector u, void *user_data)
   realtype *uarray, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmysub;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
 
   data = (UserData) user_data;
-  uarray = N_VGetArrayPointer_Parallel(u);
+  uarray = N_VGetArrayPointer(u);
 
   /* Get comm, my_pe, subgrid indices, data sizes, extended array uext */
 
@@ -708,7 +714,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
    inter-processor communication of data needed to calculate f has already
    been done, and this data is in the work array uext.                    */
 
-static int flocal(long int Nlocal, realtype t, N_Vector u,
+static int flocal(sunindextype Nlocal, realtype t, N_Vector u,
                   N_Vector udot, void *user_data)
 {
   realtype *uext;
@@ -718,12 +724,12 @@ static int flocal(long int Nlocal, realtype t, N_Vector u,
   realtype q4coef, dely, verdco, hordco, horaco;
   int i, lx, ly, jx, jy;
   int isubx, isuby;
-  long int nvmxsub, nvmxsub2, offsetu, offsetue;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
   UserData data;
   realtype *uarray, *duarray;
 
-  uarray = N_VGetArrayPointer_Parallel(u);
-  duarray = N_VGetArrayPointer_Parallel(udot);
+  uarray = N_VGetArrayPointer(u);
+  duarray = N_VGetArrayPointer(udot);
 
   /* Get subgrid indices, array sizes, extended work array uext */
 
diff --git a/examples/cvode/parallel/cvDiurnal_kry_bbd_p.out b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.out
index 9a72bbb..c4fdb61 100644
--- a/examples/cvode/parallel/cvDiurnal_kry_bbd_p.out
+++ b/examples/cvode/parallel/cvDiurnal_kry_bbd_p.out
@@ -19,55 +19,55 @@ t = 2.16e+04   no. steps = 247   order = 5   stepsize = 3.00e+02
 At bottom left:  c1, c2 =    2.665e+07    2.993e+11 
 At top right:    c1, c2 =    2.931e+07    3.313e+11 
 
-t = 2.88e+04   no. steps = 272   order = 4   stepsize = 4.05e+02
+t = 2.88e+04   no. steps = 272   order = 4   stepsize = 2.13e+02
 At bottom left:  c1, c2 =    8.702e+06    3.380e+11 
 At top right:    c1, c2 =    9.650e+06    3.751e+11 
 
-t = 3.60e+04   no. steps = 309   order = 4   stepsize = 7.53e+01
+t = 3.60e+04   no. steps = 311   order = 4   stepsize = 9.70e+01
 At bottom left:  c1, c2 =    1.404e+04    3.387e+11 
 At top right:    c1, c2 =    1.561e+04    3.765e+11 
 
-t = 4.32e+04   no. steps = 377   order = 4   stepsize = 4.02e+02
-At bottom left:  c1, c2 =    1.908e-07    3.382e+11 
-At top right:    c1, c2 =    2.345e-07    3.804e+11 
+t = 4.32e+04   no. steps = 368   order = 4   stepsize = 3.95e+02
+At bottom left:  c1, c2 =    6.243e-08    3.382e+11 
+At top right:    c1, c2 =    7.021e-08    3.804e+11 
 
-t = 5.04e+04   no. steps = 392   order = 5   stepsize = 3.67e+02
-At bottom left:  c1, c2 =   -6.408e-10    3.358e+11 
-At top right:    c1, c2 =   -6.654e-10    3.864e+11 
+t = 5.04e+04   no. steps = 388   order = 5   stepsize = 4.74e+02
+At bottom left:  c1, c2 =    3.000e-07    3.358e+11 
+At top right:    c1, c2 =    3.306e-07    3.864e+11 
 
-t = 5.76e+04   no. steps = 403   order = 5   stepsize = 4.72e+02
-At bottom left:  c1, c2 =    2.017e-08    3.320e+11 
-At top right:    c1, c2 =    3.353e-08    3.909e+11 
+t = 5.76e+04   no. steps = 401   order = 5   stepsize = 3.61e+02
+At bottom left:  c1, c2 =   -1.096e-10    3.320e+11 
+At top right:    c1, c2 =   -6.268e-11    3.909e+11 
 
-t = 6.48e+04   no. steps = 415   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =   -2.502e-10    3.313e+11 
-At top right:    c1, c2 =    2.005e-10    3.963e+11 
+t = 6.48e+04   no. steps = 414   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =    1.186e-11    3.313e+11 
+At top right:    c1, c2 =    6.568e-14    3.963e+11 
 
-t = 7.20e+04   no. steps = 424   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =    4.217e-12    3.330e+11 
-At top right:    c1, c2 =   -2.693e-12    4.039e+11 
+t = 7.20e+04   no. steps = 425   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =   -7.713e-12    3.330e+11 
+At top right:    c1, c2 =    5.432e-13    4.039e+11 
 
-t = 7.92e+04   no. steps = 434   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =    2.779e-12    3.334e+11 
-At top right:    c1, c2 =   -1.865e-12    4.120e+11 
+t = 7.92e+04   no. steps = 436   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =    2.525e-13    3.334e+11 
+At top right:    c1, c2 =   -2.072e-14    4.120e+11 
 
-t = 8.64e+04   no. steps = 444   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =    2.331e-13    3.352e+11 
-At top right:    c1, c2 =   -1.599e-13    4.163e+11 
+t = 8.64e+04   no. steps = 448   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =    4.758e-15    3.352e+11 
+At top right:    c1, c2 =    7.572e-17    4.163e+11 
 
 
 Final Statistics: 
 
 lenrw   =  2089     leniw   =   120
-lenrwls =  2046     leniwls =    80
-nst     =   444
-nfe     =   581     nfels   =   526
-nni     =   577     nli     =   526
-nsetups =    75     netf    =    28
-npe     =     8     nps     =  1057
+lenrwls =  2450     leniwls =   106
+nst     =   448
+nfe     =   581     nfels   =   509
+nni     =   577     nli     =   509
+nsetups =    76     netf    =    26
+npe     =     8     nps     =  1029
 ncfn    =     0     ncfl    =     0
 
-In CVBBDPRE: real/integer local work space sizes = 600, 50
+In CVBBDPRE: real/integer local work space sizes = 1300, 192
              no. flocal evals. = 176
 
 
@@ -88,53 +88,53 @@ t = 2.16e+04   no. steps = 249   order = 5   stepsize = 4.31e+02
 At bottom left:  c1, c2 =    2.665e+07    2.993e+11 
 At top right:    c1, c2 =    2.931e+07    3.313e+11 
 
-t = 2.88e+04   no. steps = 314   order = 3   stepsize = 9.38e+01
+t = 2.88e+04   no. steps = 309   order = 4   stepsize = 1.32e+02
 At bottom left:  c1, c2 =    8.702e+06    3.380e+11 
 At top right:    c1, c2 =    9.650e+06    3.751e+11 
 
-t = 3.60e+04   no. steps = 350   order = 5   stepsize = 9.78e+01
+t = 3.60e+04   no. steps = 342   order = 5   stepsize = 1.28e+02
 At bottom left:  c1, c2 =    1.404e+04    3.387e+11 
 At top right:    c1, c2 =    1.561e+04    3.765e+11 
 
-t = 4.32e+04   no. steps = 403   order = 4   stepsize = 3.87e+02
-At bottom left:  c1, c2 =    1.504e-09    3.382e+11 
-At top right:    c1, c2 =    1.683e-09    3.804e+11 
+t = 4.32e+04   no. steps = 393   order = 4   stepsize = 3.91e+02
+At bottom left:  c1, c2 =    1.998e-09    3.382e+11 
+At top right:    c1, c2 =    2.210e-09    3.804e+11 
 
-t = 5.04e+04   no. steps = 416   order = 5   stepsize = 5.91e+02
-At bottom left:  c1, c2 =   -1.137e-11    3.358e+11 
-At top right:    c1, c2 =   -1.439e-11    3.864e+11 
+t = 5.04e+04   no. steps = 406   order = 5   stepsize = 6.68e+02
+At bottom left:  c1, c2 =    4.173e-11    3.358e+11 
+At top right:    c1, c2 =    4.509e-11    3.864e+11 
 
-t = 5.76e+04   no. steps = 432   order = 5   stepsize = 1.73e+02
-At bottom left:  c1, c2 =    1.293e-09    3.320e+11 
-At top right:    c1, c2 =    2.448e-10    3.909e+11 
+t = 5.76e+04   no. steps = 421   order = 4   stepsize = 1.46e+02
+At bottom left:  c1, c2 =    1.346e-13    3.320e+11 
+At top right:    c1, c2 =    1.429e-13    3.909e+11 
 
-t = 6.48e+04   no. steps = 447   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =    7.963e-13    3.313e+11 
-At top right:    c1, c2 =   -2.943e-13    3.963e+11 
+t = 6.48e+04   no. steps = 436   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =    4.188e-18    3.313e+11 
+At top right:    c1, c2 =   -4.796e-15    3.963e+11 
 
-t = 7.20e+04   no. steps = 459   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =   -2.414e-12    3.330e+11 
-At top right:    c1, c2 =    2.797e-13    4.039e+11 
+t = 7.20e+04   no. steps = 448   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =   -4.919e-18    3.330e+11 
+At top right:    c1, c2 =    8.770e-17    4.039e+11 
 
-t = 7.92e+04   no. steps = 470   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =   -1.059e-13    3.334e+11 
-At top right:    c1, c2 =    3.557e-14    4.120e+11 
+t = 7.92e+04   no. steps = 460   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =    2.462e-20    3.334e+11 
+At top right:    c1, c2 =   -2.599e-20    4.120e+11 
 
-t = 8.64e+04   no. steps = 481   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =    6.045e-15    3.352e+11 
-At top right:    c1, c2 =   -2.016e-15    4.163e+11 
+t = 8.64e+04   no. steps = 472   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =    3.021e-23    3.352e+11 
+At top right:    c1, c2 =   -3.233e-23    4.163e+11 
 
 
 Final Statistics: 
 
 lenrw   =  2089     leniw   =   120
-lenrwls =  2046     leniwls =    80
-nst     =   481
-nfe     =   622     nfels   =   769
-nni     =   618     nli     =   769
-nsetups =   104     netf    =    33
-npe     =     9     nps     =  1281
+lenrwls =  2450     leniwls =   106
+nst     =   472
+nfe     =   604     nfels   =   758
+nni     =   600     nli     =   758
+nsetups =    94     netf    =    29
+npe     =     9     nps     =  1257
 ncfn    =     0     ncfl    =     0
 
-In CVBBDPRE: real/integer local work space sizes = 600, 50
+In CVBBDPRE: real/integer local work space sizes = 1300, 192
              no. flocal evals. = 198
diff --git a/examples/cvode/parallel/cvDiurnal_kry_p.c b/examples/cvode/parallel/cvDiurnal_kry_p.c
index 0211ac8..8d15e74 100644
--- a/examples/cvode/parallel/cvDiurnal_kry_p.c
+++ b/examples/cvode/parallel/cvDiurnal_kry_p.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
  *                Radu Serban  @ LLNL
  * -----------------------------------------------------------------
@@ -32,7 +29,7 @@
  * neq = 2*MX*MY.
  *
  * The solution is done with the BDF/GMRES method (i.e. using the
- * CVSPGMR linear solver) and the block-diagonal part of the
+ * SUNSPGMR linear solver) and the block-diagonal part of the
  * Newton matrix as a left preconditioner. A copy of the
  * block-diagonal part of the Jacobian is saved and conditionally
  * reused within the preconditioner routine.
@@ -52,14 +49,15 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>               /* prototypes for CVODE fcts. */
-#include <cvode/cvode_spgmr.h>         /* prototypes & constants for CVSPGMR  */
-#include <nvector/nvector_parallel.h>  /* def. of N_Vector, macro NV_DATA_P  */
-#include <sundials/sundials_dense.h>   /* prototypes for small dense fcts. */
-#include <sundials/sundials_types.h>   /* definitions of realtype, booleantype */
-#include <sundials/sundials_math.h>    /* definition of macros SUNSQR and EXP */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts.    */
+#include <nvector/nvector_parallel.h>  /* access to MPI-parallel N_Vector        */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver        */
+#include <sundials/sundials_dense.h>   /* prototypes for small dense fcts.       */
+#include <cvode/cvode_spils.h>         /* access to CVSpils interface            */
+#include <sundials/sundials_types.h>   /* definitions of realtype, booleantype   */
+#include <sundials/sundials_math.h>    /* definition of macros SUNSQR and EXP    */
 
-#include <mpi.h>                       /* MPI constants and types */
+#include <mpi.h> /* MPI constants and types */
 
 /* Problem Constants */
 
@@ -130,7 +128,7 @@ typedef struct {
 
   /* For preconditioner */
   realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
 
 } *UserData;
 
@@ -144,15 +142,15 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
 static void PrintFinalStats(void *cvode_mem);
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype udata[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[]);
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[]);
 static void ucomm(realtype t, N_Vector u, UserData data);
 static void fcalc(realtype t, realtype udata[], realtype dudata[],
@@ -165,13 +163,12 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   realtype gamma, void *user_data);
 
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
                   N_Vector r, N_Vector z, 
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 
 /* Private function to check function return values */
@@ -186,13 +183,15 @@ int main(int argc, char *argv[])
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag, my_pe, npes;
-  long int neq, local_N;
+  sunindextype neq, local_N;
   MPI_Comm comm;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Set problem size neq */
@@ -246,10 +245,14 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR 
-     with left preconditioning and the maximum Krylov dimension maxl */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if (check_flag(&flag, "CVSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Create SPGMR solver structure with left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+
+  /* Attach SPGMR solver structure to CVSpils interface */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Set preconditioner setup and solve routines Precond and PSolve, 
      and the pointer to the user-defined block data */
@@ -273,6 +276,7 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(u);
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   MPI_Finalize();
 
@@ -317,7 +321,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
     for (ly = 0; ly < MYSUB; ly++) {
       (data->P)[lx][ly] = newDenseMat(NVARS, NVARS);
       (data->Jbd)[lx][ly] = newDenseMat(NVARS, NVARS);
-      (data->pivot)[lx][ly] = newLintArray(NVARS);
+      (data->pivot)[lx][ly] = newIndexArray(NVARS);
     }
   }
 }
@@ -344,12 +348,12 @@ static void FreeUserData(UserData data)
 static void SetInitialProfiles(N_Vector u, UserData data)
 {
   int isubx, isuby, lx, ly, jx, jy;
-  long int offset;
+  sunindextype offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *udata;
 
   /* Set pointer to data array in vector u */
-  udata = N_VGetArrayPointer_Parallel(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Get mesh spacings, and subgrid indices for this PE */
   dx = data->dx;         dy = data->dy;
@@ -386,11 +390,12 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
   int qu, flag;
   realtype hu, *udata, tempu[2];
   int npelast;
-  long int i0, i1, nst;
+  long int nst;
+  sunindextype i0, i1;
   MPI_Status status;
 
   npelast = NPEX*NPEY - 1;
-  udata = N_VGetArrayPointer_Parallel(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Send c1,c2 at top right mesh point to PE 0 */
   if (my_pe == npelast) {
@@ -439,7 +444,7 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
 
 static void PrintFinalStats(void *cvode_mem)
 {
-  long int lenrw, leniw ;
+  long int lenrw, leniw;
   long int lenrwLS, leniwLS;
   long int nst, nfe, nsetups, nni, ncfn, netf;
   long int nli, npe, nps, ncfl, nfeLS;
@@ -488,11 +493,11 @@ static void PrintFinalStats(void *cvode_mem)
 
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype udata[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -537,10 +542,10 @@ static void BSend(MPI_Comm comm,
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
 
@@ -578,11 +583,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[],
 
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
 
@@ -632,10 +637,10 @@ static void ucomm(realtype t, N_Vector u, UserData data)
   realtype *udata, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmysub;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
 
-  udata = N_VGetArrayPointer_Parallel(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Get comm, my_pe, subgrid indices, data sizes, extended array uext */
   comm = data->comm;  my_pe = data->my_pe;
@@ -668,7 +673,7 @@ static void fcalc(realtype t, realtype udata[],
   realtype q4coef, dely, verdco, hordco, horaco;
   int i, lx, ly, jx, jy;
   int isubx, isuby;
-  long int nvmxsub, nvmxsub2, offsetu, offsetue;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
 
   /* Get subgrid indices, data sizes, extended work array uext */
   isubx = data->isubx;   isuby = data->isuby;
@@ -797,8 +802,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   realtype *udata, *dudata;
   UserData data;
 
-  udata = N_VGetArrayPointer_Parallel(u);
-  dudata = N_VGetArrayPointer_Parallel(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
   data = (UserData) user_data;
 
   /* Call ucomm to do inter-processor communication */
@@ -813,13 +818,12 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 /* Preconditioner setup routine. Generate and preprocess P. */
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MYSUB], **(*Jbd)[MYSUB];
   int nvmxsub, ier, offset;
-  long int *(*pivot)[MYSUB];
+  sunindextype *(*pivot)[MYSUB];
   int lx, ly, jx, jy, isubx, isuby;
   realtype *udata, **a, **j;
   UserData data;
@@ -830,24 +834,24 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
   P = data->P;
   Jbd = data->Jbd;
   pivot = data->pivot;
-  udata = N_VGetArrayPointer_Parallel(u);
+  udata = N_VGetArrayPointer(u);
   isubx = data->isubx;   isuby = data->isuby;
   nvmxsub = data->nvmxsub;
 
   if (jok) {
 
-  /* jok = TRUE: Copy Jbd to P */
+  /* jok = SUNTRUE: Copy Jbd to P */
     for (ly = 0; ly < MYSUB; ly++)
       for (lx = 0; lx < MXSUB; lx++)
         denseCopy(Jbd[lx][ly], P[lx][ly], NVARS, NVARS);
 
-  *jcurPtr = FALSE;
+  *jcurPtr = SUNFALSE;
 
   }
 
   else {
 
-  /* jok = FALSE: Generate Jbd from scratch and copy to P */
+  /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
 
   /* Make local copies of problem variables, for efficiency */
   q4coef = data->q4;
@@ -879,7 +883,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
 
   }
 
@@ -904,11 +908,11 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
                   N_Vector r, N_Vector z, 
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype **(*P)[MYSUB];
   int nvmxsub;
-  long int *(*pivot)[MYSUB];
+  sunindextype *(*pivot)[MYSUB];
   int lx, ly;
   realtype *zdata, *v;
   UserData data;
@@ -924,7 +928,7 @@ static int PSolve(realtype tn, N_Vector u, N_Vector fu,
   N_VScale(RCONST(1.0), r, z);
 
   nvmxsub = data->nvmxsub;
-  zdata = N_VGetArrayPointer_Parallel(z);
+  zdata = N_VGetArrayPointer(z);
 
   for (lx = 0; lx < MXSUB; lx++) {
     for (ly = 0; ly < MYSUB; ly++) {
diff --git a/examples/cvode/parallel/cvDiurnal_kry_p.out b/examples/cvode/parallel/cvDiurnal_kry_p.out
index 6705776..f4206df 100644
--- a/examples/cvode/parallel/cvDiurnal_kry_p.out
+++ b/examples/cvode/parallel/cvDiurnal_kry_p.out
@@ -13,51 +13,51 @@ t = 2.16e+04   no. steps = 277   order = 5   stepsize = 2.75e+02
 At bottom left:  c1, c2 =    2.665e+07    2.993e+11 
 At top right:    c1, c2 =    2.931e+07    3.313e+11 
 
-t = 2.88e+04   no. steps = 307   order = 4   stepsize = 1.98e+02
+t = 2.88e+04   no. steps = 321   order = 3   stepsize = 5.19e+01
 At bottom left:  c1, c2 =    8.702e+06    3.380e+11 
 At top right:    c1, c2 =    9.650e+06    3.751e+11 
 
-t = 3.60e+04   no. steps = 335   order = 5   stepsize = 1.17e+02
+t = 3.60e+04   no. steps = 384   order = 4   stepsize = 8.70e+01
 At bottom left:  c1, c2 =    1.404e+04    3.387e+11 
 At top right:    c1, c2 =    1.561e+04    3.765e+11 
 
-t = 4.32e+04   no. steps = 388   order = 4   stepsize = 4.48e+02
-At bottom left:  c1, c2 =   -5.732e-07    3.382e+11 
-At top right:    c1, c2 =   -6.367e-07    3.804e+11 
+t = 4.32e+04   no. steps = 456   order = 4   stepsize = 8.77e+02
+At bottom left:  c1, c2 =    1.077e-06    3.382e+11 
+At top right:    c1, c2 =    4.057e-07    3.804e+11 
 
-t = 5.04e+04   no. steps = 406   order = 5   stepsize = 3.97e+02
-At bottom left:  c1, c2 =   -4.317e-09    3.358e+11 
-At top right:    c1, c2 =   -8.233e-09    3.864e+11 
+t = 5.04e+04   no. steps = 471   order = 4   stepsize = 3.29e+02
+At bottom left:  c1, c2 =   -1.176e-08    3.358e+11 
+At top right:    c1, c2 =   -5.053e-08    3.864e+11 
 
-t = 5.76e+04   no. steps = 418   order = 5   stepsize = 4.74e+02
-At bottom left:  c1, c2 =   -2.576e-09    3.320e+11 
-At top right:    c1, c2 =   -1.259e-09    3.909e+11 
+t = 5.76e+04   no. steps = 488   order = 5   stepsize = 3.95e+02
+At bottom left:  c1, c2 =   -9.464e-11    3.320e+11 
+At top right:    c1, c2 =   -3.493e-10    3.909e+11 
 
-t = 6.48e+04   no. steps = 428   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =    3.451e-09    3.313e+11 
-At top right:    c1, c2 =    2.081e-09    3.963e+11 
+t = 6.48e+04   no. steps = 501   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =    5.057e-11    3.313e+11 
+At top right:    c1, c2 =    1.868e-10    3.963e+11 
 
-t = 7.20e+04   no. steps = 437   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =    1.630e-11    3.330e+11 
-At top right:    c1, c2 =    1.843e-11    4.039e+11 
+t = 7.20e+04   no. steps = 512   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =   -4.454e-11    3.330e+11 
+At top right:    c1, c2 =   -1.629e-10    4.039e+11 
 
-t = 7.92e+04   no. steps = 447   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =   -1.704e-11    3.334e+11 
-At top right:    c1, c2 =   -1.131e-11    4.120e+11 
+t = 7.92e+04   no. steps = 524   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =   -2.189e-13    3.334e+11 
+At top right:    c1, c2 =   -8.112e-13    4.120e+11 
 
-t = 8.64e+04   no. steps = 456   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =    1.496e-12    3.352e+11 
-At top right:    c1, c2 =    8.085e-13    4.163e+11 
+t = 8.64e+04   no. steps = 535   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =    1.080e-15    3.352e+11 
+At top right:    c1, c2 =    3.729e-15    4.163e+11 
 
 
 Final Statistics: 
 
 lenrw   =  2089     leniw   =   120
-lenrwls =  2046     leniwls =    80
-nst     =   456
-nfe     =   586     nfels   =   619
-nni     =   582     nli     =   619
-nsetups =    73     netf    =    25
-npe     =     8     nps     =  1149
-ncfn    =     0     ncfl    =     0
+lenrwls =  2450     leniwls =   106
+nst     =   535
+nfe     =   688     nfels   =   668
+nni     =   684     nli     =   668
+nsetups =    92     netf    =    33
+npe     =    10     nps     =  1294
+ncfn    =     0     ncfl    =     1
 
diff --git a/examples/cvode/parhyp/CMakeLists.txt b/examples/cvode/parhyp/CMakeLists.txt
index a07c51c..0475336 100644
--- a/examples/cvode/parhyp/CMakeLists.txt
+++ b/examples/cvode/parhyp/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4341 $
-# $Date: 2015-02-03 10:53:47 -0800 (Tue, 03 Feb 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,79 +12,81 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for CVODE parhyp examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable CVODE_examples with the names of the parhyp CVODE examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(CVODE_examples
-  "cvAdvDiff_non_ph\;2\;2"
-#  "cvDiurnal_kry_bbd_ph\;2\;4"
-#  "cvHeat2D_ph\;2\;2"
+  "cvAdvDiff_non_ph\;2\;2\;develop"
+#  "cvDiurnal_kry_bbd_ph\;2\;4\;develop"
+#  "cvHeat2D_ph\;2\;2\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the C compiler to the MPICC script.
 # If not, then add the MPI include directory for MPI headers.
-
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODE_LIB sundials_cvode_static)
   SET(NVECP_LIB sundials_nvecparhyp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODE_LIB sundials_cvode_shared)
   SET(NVECP_LIB sundials_nvecparhyp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-SET(HYPRE_LIBS ${HYPRE_LIBRARIES})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-IF(HYPRE_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${HYPRE_LIBRARIES})
-ENDIF(HYPRE_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${CVODE_examples})
 
-# Add the build and install targets for each CVODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
 
-FOREACH(example_tuple ${CVODE_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${HYPRE_LIBRARIES})
+
   IF(NOT MPI_MPICC)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  ENDIF()
+
+  # install example
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parhyp)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parhyp)
     #INSTALL(FILES vis.c DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parhyp)
-  ENDIF(EXAMPLES_INSTALL)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${CVODE_examples})
 
+
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -96,30 +95,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "CVODE")
   SET(SOLVER_LIB "sundials_cvode")
-  FOREACH(example_tuple ${CVODE_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${CVODE_examples})
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(CVODE_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parhyp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvode/parhyp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parhyp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/parhyp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/cvode/parhyp/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parhyp 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/parhyp
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/cvode/parhyp/README b/examples/cvode/parhyp/README
index 0f42964..d8f4fd8 100644
--- a/examples/cvode/parhyp/README
+++ b/examples/cvode/parhyp/README
@@ -1,16 +1,12 @@
-List of parallel CVODE examples
+List of parhyp CVODE examples
 
-  cvAdvDiff_non_p       : 1-D advection-diffusion (nonstiff)
-  cvAdvDiff_diag_p      : 1-D advection-diffusion with Adams and diagonal linear solver
-  cvDiurnal_kry_bbd_p   : 2-D 2-species diurnal advection-diffusion with BBD preconditioner
-  cvDiurnal_kry_p       : 2-D 2-species diurnal advection-diffusion
+  cvAdvDiff_non_ph      : 1-D advection-diffusion (nonstiff)
 
 
 The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -21,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -35,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvode/parhyp/cvAdvDiff_non_ph.c b/examples/cvode/parhyp/cvAdvDiff_non_ph.c
index ab72743..5eb9c8d 100644
--- a/examples/cvode/parhyp/cvAdvDiff_non_ph.c
+++ b/examples/cvode/parhyp/cvAdvDiff_non_ph.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision$
- * $Date$
- * -----------------------------------------------------------------
  * Programmer(s): Jean M. Sexton @ SMU
  *                Slaven Peles @ LLNL
  * -----------------------------------------------------------------
@@ -75,8 +72,8 @@ typedef struct {
 
 /* Private Helper Functions */
 
-static void SetIC(HYPRE_IJVector Uij, realtype dx, long int my_length,
-                  long int my_base);
+static void SetIC(HYPRE_IJVector Uij, realtype dx, sunindextype my_length,
+                  sunindextype my_base);
 
 static void PrintIntro(int npes);
 
@@ -144,7 +141,7 @@ int main(int argc, char *argv[])
   data->hdcoef = RCONST(1.0)/(dx*dx);
   data->hacoef = RCONST(0.5)/(RCONST(2.0)*dx);
 
-  /* Initialize solutin vector. */
+  /* Initialize solution vector. */
   SetIC(Uij, dx, local_N, my_base);
   HYPRE_IJVectorAssemble(Uij);
   HYPRE_IJVectorGetObject(Uij, (void**) &Upar);
@@ -208,8 +205,8 @@ int main(int argc, char *argv[])
 
 /* Set initial conditions in u vector */
 
-static void SetIC(HYPRE_IJVector Uij, realtype dx, long int my_length,
-                  long int my_base)
+static void SetIC(HYPRE_IJVector Uij, realtype dx, sunindextype my_length,
+                  sunindextype my_base)
 {
   int i;
   HYPRE_Int *iglobal;
diff --git a/examples/cvode/raja/CMakeLists.txt b/examples/cvode/raja/CMakeLists.txt
new file mode 100644
index 0000000..b544873
--- /dev/null
+++ b/examples/cvode/raja/CMakeLists.txt
@@ -0,0 +1,124 @@
+# ---------------------------------------------------------------
+# Programmer:  Slaven Peles @ LLNL
+# ---------------------------------------------------------------
+# Based on CMakeLists.txt in cvode/serial by Radu Serban @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for CVODE raja examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS linear solvers
+SET(CVODE_examples
+  "cvAdvDiff_kry_raja\;develop"
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ${CUDA_TOOLKIT_ROOT_DIR}/samples/common/inc ${RAJA_INCLUDE_PATH})
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(CVODE_LIB sundials_cvode_static)
+  SET(NVECS_LIB sundials_nvecraja_static)
+ELSE()
+  SET(CVODE_LIB sundials_cvode_shared)
+  SET(NVECS_LIB sundials_nvecraja_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS} -L${RAJA_LIB_PATH} -lRAJA)
+
+
+# Add the build and install targets for each CVODE example
+FOREACH(example_tuple ${CVODE_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
+
+  set_source_files_properties(${example}.cu PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
+
+  # add example source files
+  CUDA_ADD_EXECUTABLE(${example} ${example}.cu)
+
+  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.cu ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/raja)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${CVODE_examples})
+
+
+# create Makfile and CMakeLists.txt for examples
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/raja)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER "CVODE")
+  SET(SOLVER_LIB "sundials_cvode")
+
+  EXAMPLES2STRING(CVODE_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_raja_CUDA_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/raja/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/cvode/raja/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/raja
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_raja_CUDA_ex.in
+      ${PROJECT_BINARY_DIR}/examples/cvode/raja/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/cvode/raja/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/raja
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvode/raja/README b/examples/cvode/raja/README
new file mode 100644
index 0000000..0796952
--- /dev/null
+++ b/examples/cvode/raja/README
@@ -0,0 +1,3 @@
+List of RAJA CVODE examples
+
+  cvAdvDiff_kry_cuda       : 2-D advection-diffusion (nonstiff)
diff --git a/examples/cvode/serial/cvAdvDiff_bnd.c b/examples/cvode/raja/cvAdvDiff_kry_raja.cu
similarity index 50%
copy from examples/cvode/serial/cvAdvDiff_bnd.c
copy to examples/cvode/raja/cvAdvDiff_kry_raja.cu
index eec9cdb..5356c2c 100644
--- a/examples/cvode/serial/cvAdvDiff_bnd.c
+++ b/examples/cvode/raja/cvAdvDiff_kry_raja.cu
@@ -1,10 +1,10 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
+ * Programmer(s): Slaven Peles @ LLNL
  * -----------------------------------------------------------------
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
+ * Acknowledgements: This example is based on cvAdvDiff_bnd 
+ *                   example by Scott D. Cohen, Alan C. 
+ *                   Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
  *
@@ -33,22 +33,18 @@
 #include <stdlib.h>
 #include <math.h>
 
-/* Header files with a description of contents used in cvbanx.c */
+#include <cvode/cvode.h>
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver        */
+#include <cvode/cvode_spils.h>         /* access to CVSpils interface            */
+#include <nvector/nvector_raja.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
 
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts., consts. */
-#include <cvode/cvode_band.h>        /* prototype for CVBand */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <sundials/sundials_band.h>  /* definitions of type DlsMat and macros */
-#include <sundials/sundials_types.h> /* definition of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS and EXP */
+#include <RAJA/RAJA.hpp>
 
-/* Problem Constants */
 
-#define XMAX  RCONST(2.0)    /* domain boundaries         */
-#define YMAX  RCONST(1.0)
-#define MX    10             /* mesh dimensions           */
-#define MY    5
-#define NEQ   MX*MY          /* number of equations       */
+/* Real Constants */
+
 #define ATOL  RCONST(1.0e-5) /* scalar absolute tolerance */
 #define T0    RCONST(0.0)    /* initial time              */
 #define T1    RCONST(0.1)    /* first output time         */
@@ -61,43 +57,34 @@
 #define TWO  RCONST(2.0)
 #define FIVE RCONST(5.0)
 
-/* User-defined vector access macro IJth */
 
-/* IJth is defined in order to isolate the translation from the
-   mathematical 2-dimensional structure of the dependent variable vector
-   to the underlying 1-dimensional storage. 
-   IJth(vdata,i,j) references the element in the vdata array for
-   u at mesh point (i,j), where 1 <= i <= MX, 1 <= j <= MY.
-   The vdata array is obtained via the macro call vdata = N_VGetArrayPointer_Serial(v),
-   where v is an N_Vector. 
-   The variables are ordered by the y index j, then by the x index i. */
+/* Type : _UserData (contains model and discretization parameters) */
+struct _UserData {
+  sunindextype MX, MY, NEQ;
+  realtype dx, dy, XMAX, YMAX;
+  realtype hdcoef, hacoef, vdcoef;
+};
 
-#define IJth(vdata,i,j) (vdata[(j-1) + (i-1)*MY])
+typedef _UserData *UserData;
 
-/* Type : UserData (contains grid constants) */
+/* Problem setup and initialization functions */
+static UserData SetUserData(int argc, char** argv);
+static void SetIC(N_Vector u, UserData data);
 
-typedef struct {
-  realtype dx, dy, hdcoef, hacoef, vdcoef;
-} *UserData;
+/* Functions Called by the Solver */
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
+static int jtv(N_Vector v, N_Vector Jv, realtype t,
+               N_Vector u, N_Vector fu,
+               void *user_data, N_Vector tmp);
 
 /* Private Helper Functions */
-
-static void SetIC(N_Vector u, UserData data);
-static void PrintHeader(realtype reltol, realtype abstol, realtype umax);
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax, UserData data);
 static void PrintOutput(realtype t, realtype umax, long int nst);
 static void PrintFinalStats(void *cvode_mem);
 
 /* Private function to check function return values */
-
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
-/* Functions Called by the Solver */
-
-static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /*
  *-------------------------------
@@ -105,34 +92,32 @@ static int Jac(long int N, long int mu, long int ml,
  *-------------------------------
  */
 
-int main(void)
+int main(int argc, char** argv)
 {
-  realtype dx, dy, reltol, abstol, t, tout, umax;
+  realtype reltol, abstol, t, tout, umax;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
   long int nst;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
-  /* Create a serial vector */
-
-  u = N_VNew_Serial(NEQ);  /* Allocate u vector */
-  if(check_flag((void*)u, "N_VNew_Serial", 0)) return(1);
+  /* Set model parameters */
+  data = SetUserData(argc, argv);
+  if(check_flag((void *)data, "malloc", 2)) return(1);
 
-  reltol = ZERO;  /* Set the tolerances */
+  /* Set the tolerances */
+  reltol = ZERO;
   abstol = ATOL;
 
-  data = (UserData) malloc(sizeof *data);  /* Allocate data memory */
-  if(check_flag((void *)data, "malloc", 2)) return(1);
-  dx = data->dx = XMAX/(MX+1);  /* Set grid coefficients in data */
-  dy = data->dy = YMAX/(MY+1);
-  data->hdcoef = ONE/(dx*dx);
-  data->hacoef = HALF/(TWO*dx);
-  data->vdcoef = ONE/(dy*dy);
+  /* Create a RAJA vector with initial values */
+  u = N_VNew_Raja(data->NEQ);  /* Allocate u vector */
+  if(check_flag((void*)u, "N_VNew_Raja", 0)) return(1);
 
   SetIC(u, data);  /* Initialize u vector */
 
@@ -142,7 +127,7 @@ int main(void)
   if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
 
   /* Call CVodeInit to initialize the integrator memory and specify the
-   * user's right hand side function in u'=f(t,u), the inital time T0, and
+   * user's right hand side function in u'=f(t,u), the initial time T0, and
    * the initial dependent variable vector u. */
   flag = CVodeInit(cvode_mem, f, T0, u);
   if(check_flag(&flag, "CVodeInit", 1)) return(1);
@@ -156,18 +141,23 @@ int main(void)
   flag = CVodeSetUserData(cvode_mem, data);
   if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVBand to specify the CVBAND band linear solver */
-  flag = CVBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVBand", 1)) return(1);
+  /* Create SPGMR solver structure without preconditioning
+   * and the maximum Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_NONE, 0);
+  if(check_flag(&flag, "SUNSPGMR", 1)) return(1);
+
+  /* Set CVSpils linear solver to LS */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return(1);
 
-  /* Set the user-supplied Jacobian routine Jac */
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  /* Set the Jacobian-times-vector function */
+  flag = CVSpilsSetJacTimes(cvode_mem, NULL, jtv);
+  if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1);
 
   /* In loop over output points: call CVode, print results, test for errors */
 
   umax = N_VMaxNorm(u);
-  PrintHeader(reltol, abstol, umax);
+  PrintHeader(reltol, abstol, umax, data);
   for(iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) {
     flag = CVode(cvode_mem, tout, u, &t, CV_NORMAL);
     if(check_flag(&flag, "CVode", 1)) break;
@@ -179,7 +169,7 @@ int main(void)
 
   PrintFinalStats(cvode_mem);  /* Print some final statistics   */
 
-  N_VDestroy_Serial(u);   /* Free the u vector */
+  N_VDestroy(u);          /* Free the u vector */
   CVodeFree(&cvode_mem);  /* Free the integrator memory */
   free(data);             /* Free the user data */
 
@@ -187,141 +177,175 @@ int main(void)
 }
 
 /*
- *-------------------------------
- * Functions called by the solver
- *-------------------------------
+ *-------------------------------------------
+ * Problem setup and initialization functions
+ *-------------------------------------------
  */
 
-/* f routine. Compute f(t,u). */
+/* Set model and discretization parameters */
 
-static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
+UserData SetUserData(int argc, char *argv[])
 {
-  realtype uij, udn, uup, ult, urt, hordc, horac, verdc, hdiff, hadv, vdiff;
-  realtype *udata, *dudata;
-  int i, j;
-  UserData data;
+  const sunindextype MX = 10;
+  const sunindextype MY = 5;
+  const realtype XMAX = RCONST(2.0);    /* domain boundaries         */
+  const realtype YMAX = RCONST(1.0);
+
+  /* Allocate user data structure */
+  UserData ud = (UserData) malloc(sizeof *ud);
+  if(check_flag((void*) ud, "AllocUserData", 2)) return(NULL);
+
+  ud->MX  = MX;
+  ud->MY  = MY;
+  ud->NEQ = MX*MY;
+  ud->XMAX = XMAX;
+  ud->YMAX = YMAX;
+  ud->dx = XMAX/(MX+1);  /* Set grid coefficients in data */
+  ud->dy = YMAX/(MY+1);
+  ud->hdcoef = ONE/(ud->dx*ud->dx);
+  ud->hacoef = HALF/(TWO*ud->dx);
+  ud->vdcoef = ONE/(ud->dy*ud->dy);
+
+  return ud;
+}
 
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
 
+/* Set initial conditions in u vector */
+
+static void SetIC(N_Vector u, UserData data)
+{
   /* Extract needed constants from data */
 
-  data = (UserData) user_data;
-  hordc = data->hdcoef;
-  horac = data->hacoef;
-  verdc = data->vdcoef;
+  const realtype dx = data->dx;
+  const realtype dy = data->dy;
+  const realtype xmax = data->XMAX;
+  const realtype ymax = data->YMAX;
+  const sunindextype MY = data->MY;
+  const sunindextype NEQ = data->NEQ;
 
-  /* Loop over all grid points. */
+  /* Extract pointer to solution vector data on the host */
+  realtype *udata = N_VGetHostArrayPointer_Raja(u);
 
-  for (j=1; j <= MY; j++) {
+  sunindextype i, j, tid;
+  realtype x, y;
 
-    for (i=1; i <= MX; i++) {
 
-      /* Extract u at x_i, y_j and four neighboring points */
+  /* Load initial profile into u vector */
 
-      uij = IJth(udata, i, j);
-      udn = (j == 1)  ? ZERO : IJth(udata, i, j-1);
-      uup = (j == MY) ? ZERO : IJth(udata, i, j+1);
-      ult = (i == 1)  ? ZERO : IJth(udata, i-1, j);
-      urt = (i == MX) ? ZERO : IJth(udata, i+1, j);
+  for (tid=0; tid < NEQ; tid++) {
+    i = tid / MY;
+    j = tid % MY;
 
-      /* Set diffusion and advection terms and load into udot */
+    x = (i+1)*dx;
+    y = (j+1)*dy;
 
-      hdiff = hordc*(ult - TWO*uij + urt);
-      hadv = horac*(urt - ult);
-      vdiff = verdc*(uup - TWO*uij + udn);
-      IJth(dudata, i, j) = hdiff + hadv + vdiff;
-    }
+    udata[tid] = x*(xmax - x)*y*(ymax - y)*SUNRexp(FIVE*x*y);
   }
-
-  return(0);
+  N_VCopyToDevice_Raja(u);
 }
 
-/* Jacobian routine. Compute J(t,u). */
-
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  long int i, j, k;
-  realtype *kthCol, hordc, horac, verdc;
-  UserData data;
-  
-  /*
-    The components of f = udot that depend on u(i,j) are
-    f(i,j), f(i-1,j), f(i+1,j), f(i,j-1), f(i,j+1), with
-      df(i,j)/du(i,j) = -2 (1/dx^2 + 1/dy^2)
-      df(i-1,j)/du(i,j) = 1/dx^2 + .25/dx  (if i > 1)
-      df(i+1,j)/du(i,j) = 1/dx^2 - .25/dx  (if i < MX)
-      df(i,j-1)/du(i,j) = 1/dy^2           (if j > 1)
-      df(i,j+1)/du(i,j) = 1/dy^2           (if j < MY)
-  */
-
-  data = (UserData) user_data;
-  hordc = data->hdcoef;
-  horac = data->hacoef;
-  verdc = data->vdcoef;
-  
-  for (j=1; j <= MY; j++) {
-    for (i=1; i <= MX; i++) {
-      k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
-
-      /* set the kth column of J */
-
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
-    }
-  }
-
-  return(0);
-}
 
 /*
  *-------------------------------
- * Private helper functions
+ * Functions called by the solver
  *-------------------------------
  */
 
-/* Set initial conditions in u vector */
+/* f routine. Compute f(t,u). */
 
-static void SetIC(N_Vector u, UserData data)
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 {
-  int i, j;
-  realtype x, y, dx, dy;
-  realtype *udata;
+  UserData data = (UserData) user_data;
 
   /* Extract needed constants from data */
+  const sunindextype MX  = data->MX;
+  const sunindextype MY  = data->MY;
+  const sunindextype NEQ = data->NEQ;
+  const realtype hordc   = data->hdcoef;
+  const realtype horac   = data->hacoef;
+  const realtype verdc   = data->vdcoef;
 
-  dx = data->dx;
-  dy = data->dy;
+  /* Extract pointers to vector data */
+  const realtype *udata = N_VGetDeviceArrayPointer_Raja(u);
+  realtype *dudata      = N_VGetDeviceArrayPointer_Raja(udot);
 
-  /* Set pointer to data array in vector u. */
+  const sunindextype zero = 0;
 
-  udata = N_VGetArrayPointer_Serial(u);
+  RAJA::forall<RAJA::cuda_exec<256> >(zero, NEQ, [=] __device__(sunindextype index) {
+    sunindextype i = index/MY;
+    sunindextype j = index%MY;
 
-  /* Load initial profile into u vector */
+    realtype uab = udata[index];
+
+    realtype udn = (j == 0)    ? ZERO : udata[index - 1];
+    realtype uup = (j == MY-1) ? ZERO : udata[index + 1];
+    realtype ult = (i == 0)    ? ZERO : udata[index - MY];
+    realtype urt = (i == MX-1) ? ZERO : udata[index + MY];
+
+    /* Set diffusion and advection terms and load into udot */
+
+    realtype hdiff = hordc*(ult -TWO*uab + urt);
+    realtype hadv  = horac*(urt - ult);
+    realtype vdiff = verdc*(udn -TWO*uab + uup);
+
+    dudata[index] = hdiff + hadv + vdiff;
+  });
+
+  return(0);
+}
+
+
+/* Jacobian-times-vector routine. */
+
+static int jtv(N_Vector v, N_Vector Jv, realtype t,
+               N_Vector u, N_Vector fu,
+               void *user_data, N_Vector tmp)
+{
+  UserData data = (UserData) user_data;
+
+  /* Extract needed constants from data */
+  const sunindextype MX  = data->MX;
+  const sunindextype MY  = data->MY;
+  const sunindextype NEQ = data->NEQ;
+  const realtype hordc   = data->hdcoef;
+  const realtype horac   = data->hacoef;
+  const realtype verdc   = data->vdcoef;
+
+  /* Extract pointers to vector data */
+  const realtype *vdata = N_VGetDeviceArrayPointer_Raja(v);
+  realtype *Jvdata      = N_VGetDeviceArrayPointer_Raja(Jv);
+
+  const sunindextype zero = 0;
+
+  N_VConst(ZERO, Jv);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zero, NEQ, [=] __device__(sunindextype index) {
+    sunindextype i = index/MY;
+    sunindextype j = index%MY;
+
+    Jvdata[index] = -TWO*(verdc+hordc) * vdata[index];
+    if (i !=    0) Jvdata[index] += (hordc - horac) * vdata[index-MY];
+    if (i != MX-1) Jvdata[index] += (hordc + horac) * vdata[index+MY];
+    if (j !=    0) Jvdata[index] += verdc * vdata[index-1];
+    if (j != MY-1) Jvdata[index] += verdc * vdata[index+1];
+  });
   
-  for (j=1; j <= MY; j++) {
-    y = j*dy;
-    for (i=1; i <= MX; i++) {
-      x = i*dx;
-      IJth(udata,i,j) = x*(XMAX - x)*y*(YMAX - y)*SUNRexp(FIVE*x*y);
-    }
-  }  
+  return(0);
 }
 
+/*
+ *-------------------------------
+ * Private helper functions
+ *-------------------------------
+ */
+
 /* Print first lines of output (problem description) */
 
-static void PrintHeader(realtype reltol, realtype abstol, realtype umax)
+static void PrintHeader(realtype reltol, realtype abstol, realtype umax, UserData data)
 {
   printf("\n2-D Advection-Diffusion Equation\n");
-  printf("Mesh dimensions = %d X %d\n", MX, MY);
-  printf("Total system size = %d\n", NEQ);
+  printf("Mesh dimensions = %d X %d\n", data->MX, data->MY);
+  printf("Total system size = %d\n", data->NEQ);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters: reltol = %Lg   abstol = %Lg\n\n",
          reltol, abstol);
@@ -357,9 +381,14 @@ static void PrintOutput(realtype t, realtype umax, long int nst)
 
 static void PrintFinalStats(void *cvode_mem)
 {
+  long lenrw, leniw ;
+  long lenrwLS, leniwLS;
+  long int nst, nfe, nsetups, nni, ncfn, netf;
+  long int nli, npe, nps, ncfl, nfeLS;
   int flag;
-  long int nst, nfe, nsetups, netf, nni, ncfn, nje, nfeLS;
 
+  flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
+  check_flag(&flag, "CVodeGetWorkSpace", 1);
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
   flag = CVodeGetNumRhsEvals(cvode_mem, &nfe);
@@ -373,16 +402,28 @@ static void PrintFinalStats(void *cvode_mem)
   flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
   check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
 
-  flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
-  check_flag(&flag, "CVDlsGetNumJacEvals", 1);
-  flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
-  check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
-
-  printf("\nFinal Statistics:\n");
-  printf("nst = %-6ld nfe  = %-6ld nsetups = %-6ld nfeLS = %-6ld nje = %ld\n",
-	 nst, nfe, nsetups, nfeLS, nje);
-  printf("nni = %-6ld ncfn = %-6ld netf = %ld\n \n",
-	 nni, ncfn, netf);
+  flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
+  check_flag(&flag, "CVSpilsGetWorkSpace", 1);
+  flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
+  check_flag(&flag, "CVSpilsGetNumLinIters", 1);
+  flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
+  check_flag(&flag, "CVSpilsGetNumPrecEvals", 1);
+  flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
+  check_flag(&flag, "CVSpilsGetNumPrecSolves", 1);
+  flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
+  check_flag(&flag, "CVSpilsGetNumConvFails", 1);
+  flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeLS);
+  check_flag(&flag, "CVSpilsGetNumRhsEvals", 1);
+
+  printf("\nFinal Statistics.. \n\n");
+  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
+  printf("lenrwLS = %5ld     leniwLS = %5ld\n", lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                  , nst);
+  printf("nfe     = %5ld     nfeLS   = %5ld\n"  , nfe, nfeLS);
+  printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
+  printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
+  printf("npe     = %5ld     nps     = %5ld\n"  , npe, nps);
+  printf("ncfn    = %5ld     ncfl    = %5ld\n\n", ncfn, ncfl);
 
   return;
 }
diff --git a/examples/cvode/raja/cvAdvDiff_kry_raja.out b/examples/cvode/raja/cvAdvDiff_kry_raja.out
new file mode 100644
index 0000000..c90725d
--- /dev/null
+++ b/examples/cvode/raja/cvAdvDiff_kry_raja.out
@@ -0,0 +1,29 @@
+
+2-D Advection-Diffusion Equation
+Mesh dimensions = 10 X 5
+Total system size = 50
+Tolerance parameters: reltol = 0   abstol = 1e-05
+
+At t = 0      max.norm(u) =  8.954716e+01 
+At t = 0.10   max.norm(u) =  4.132884e+00   nst =   82
+At t = 0.20   max.norm(u) =  1.039293e+00   nst =  102
+At t = 0.30   max.norm(u) =  2.979816e-01   nst =  112
+At t = 0.40   max.norm(u) =  8.765538e-02   nst =  119
+At t = 0.50   max.norm(u) =  2.625408e-02   nst =  125
+At t = 0.60   max.norm(u) =  7.826077e-03   nst =  129
+At t = 0.70   max.norm(u) =  2.326537e-03   nst =  133
+At t = 0.80   max.norm(u) =  6.891180e-04   nst =  137
+At t = 0.90   max.norm(u) =  2.039853e-04   nst =  140
+At t = 1.00   max.norm(u) =  5.925586e-05   nst =  143
+
+Final Statistics.. 
+
+lenrw   =   589     leniw   =    50
+lenrwLS =   650     leniwLS =    22
+nst     =   143
+nfe     =   207     nfeLS   =     0
+nni     =   203     nli     =   225
+nsetups =     0     netf    =     2
+npe     =     0     nps     =     0
+ncfn    =     0     ncfl    =     0
+
diff --git a/examples/cvode/serial/CMakeLists.txt b/examples/cvode/serial/CMakeLists.txt
index 1e04c45..c101b6a 100644
--- a/examples/cvode/serial/CMakeLists.txt
+++ b/examples/cvode/serial/CMakeLists.txt
@@ -1,13 +1,11 @@
 # ---------------------------------------------------------------
-# $Revision: 4957 $
-# $Date: 2016-09-23 12:21:47 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,119 +13,231 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for CVODE serial examples
+# ---------------------------------------------------------------
 
-# Add variable CVODE_examples with the names of the serial CVODE examples
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS linear solvers
 SET(CVODE_examples
-  cvAdvDiff_bnd
-  cvDirectDemo_ls
-  cvDiurnal_kry_bp
-  cvDiurnal_kry
-  cvKrylovDemo_ls
-  cvKrylovDemo_prec
-  cvRoberts_dns
-  cvRoberts_dns_uw
+  "cvAdvDiff_bnd\;develop"
+  "cvDirectDemo_ls\;develop"
+  "cvDiurnal_kry_bp\;develop"
+  "cvDiurnal_kry\;develop"
+  "cvKrylovDemo_ls\;develop"
+  "cvKrylovDemo_prec\;develop"
+  "cvRoberts_dns\;"
+  "cvRoberts_dns_uw\;develop"
+  #cvAdvDiffReac_kry\;develop"
   )
 
-SET(CVODE_examples_KLU
-  cvRoberts_klu
+# Examples using LAPACK linear solvers
+SET(CVODE_examples_BL
+  "cvAdvDiff_bndL\;develop"
+  "cvRoberts_dnsL\;develop"
   )
 
-SET(CVODE_examples_SUPERLUMT
-  cvRoberts_sps
+# Examples using KLU linear solver
+SET(CVODE_examples_KLU
+  "cvRoberts_klu\;develop"
   )
 
-# Add variable CVODE_examples_BL with the names of the serial CVODE examples
-# that use Lapack
-
-SET(CVODE_examples_BL
-  cvAdvDiff_bndL
-  cvRoberts_dnsL
+# Examples using SuperLU_MT linear solver
+SET(CVODE_examples_SUPERLUMT
+  "cvRoberts_sps\;develop"
   )
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODE_LIB sundials_cvode_static)
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODE_LIB sundials_cvode_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${CVODE_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-IF(HYPRE_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${HYPRE_LIBRARIES})
-ENDIF(HYPRE_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${CVODE_examples})
 
-# Add the build and install targets for each CVODE example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${CVODE_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${CVODE_examples})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+  ENDIF()
 
-# Add the build and install targets for each Lapack CVODE example (if needed)
+ENDFOREACH(example_tuple ${CVODE_examples})
+
+
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${CVODE_examples_BL})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${CVODE_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${CVODE_examples_BL})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${CVODE_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If KLU support is enabled, add the build and install targets for
-# the examples using KLU
+
+# Add the build and install targets for each KLU example (if needed)
 IF(KLU_FOUND)
-  FOREACH(example ${CVODE_examples_KLU})
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${CVODE_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${CVODE_examples_KLU})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${CVODE_examples_KLU})
+
 ENDIF(KLU_FOUND)
 
-# If SUPERLUMT support is enabled, add the build and install targets for
-# the examples using SUPERLUMT
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
 IF(SUPERLUMT_FOUND)
-  FOREACH(example ${CVODE_examples_SUPERLUMT})
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${CVODE_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${CVODE_examples_SUPERLUMT})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${CVODE_examples_SUPERLUMT})
+
 ENDIF(SUPERLUMT_FOUND)
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -136,24 +246,26 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "CVODE")
   SET(SOLVER_LIB "sundials_cvode")
-  LIST2STRING(CVODE_examples EXAMPLES)
+
+  EXAMPLES2STRING(CVODE_examples EXAMPLES)
 
   IF(LAPACK_FOUND)
-    LIST2STRING(CVODE_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(CVODE_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
 
   IF(KLU_FOUND)
-    LIST2STRING(CVODE_examples_KLU EXAMPLES)
-  ENDIF(KLU_FOUND)
+    EXAMPLES2STRING(CVODE_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
 
   IF(SUPERLUMT_FOUND)
-    LIST2STRING(CVODE_examples_SUPERLUMT EXAMPLES)
-  ENDIF(SUPERLUMT_FOUND)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
+    EXAMPLES2STRING(CVODE_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -161,10 +273,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvode/serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvode/serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
@@ -191,4 +303,8 @@ IF(EXAMPLES_INSTALL)
       )
   ENDIF(UNIX)
 
+  # add test_install target
+  SUNDIALS_ADD_TEST_INSTALL(cvode cvRoberts_dns
+    EXAMPLE_DIR ${EXAMPLES_INSTALL_PATH}/cvode/serial)
+
 ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvode/serial/README b/examples/cvode/serial/README
index c5a0ee2..b9d6c7d 100644
--- a/examples/cvode/serial/README
+++ b/examples/cvode/serial/README
@@ -19,7 +19,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -30,7 +29,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -44,7 +46,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvode/serial/cvAdvDiff_bnd.c b/examples/cvode/serial/cvAdvDiff_bnd.c
index eec9cdb..915545a 100644
--- a/examples/cvode/serial/cvAdvDiff_bnd.c
+++ b/examples/cvode/serial/cvAdvDiff_bnd.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -21,26 +17,24 @@
  * central differencing, and with boundary values eliminated,
  * leaving an ODE system of size NEQ = MX*MY.
  * This program solves the problem with the BDF method, Newton
- * iteration with the CVBAND band linear solver, and a user-supplied
+ * iteration with the SUNBAND linear solver, and a user-supplied
  * Jacobian routine.
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .1, .2, ..., 1.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-/* Header files with a description of contents used in cvbanx.c */
-
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts., consts. */
-#include <cvode/cvode_band.h>        /* prototype for CVBand */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <sundials/sundials_band.h>  /* definitions of type DlsMat and macros */
-#include <sundials/sundials_types.h> /* definition of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS and EXP */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <cvode/cvode_direct.h>        /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
+#include <sundials/sundials_math.h>    /* definition of ABS and EXP            */
 
 /* Problem Constants */
 
@@ -68,7 +62,7 @@
    to the underlying 1-dimensional storage. 
    IJth(vdata,i,j) references the element in the vdata array for
    u at mesh point (i,j), where 1 <= i <= MX, 1 <= j <= MY.
-   The vdata array is obtained via the macro call vdata = N_VGetArrayPointer_Serial(v),
+   The vdata array is obtained via the call vdata = N_VGetArrayPointer(v),
    where v is an N_Vector. 
    The variables are ordered by the y index j, then by the x index i. */
 
@@ -94,9 +88,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 /* Functions Called by the Solver */
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector u, N_Vector fu, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /*
@@ -110,12 +103,16 @@ int main(void)
   realtype dx, dy, reltol, abstol, t, tout, umax;
   N_Vector u;
   UserData data;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
   long int nst;
 
   u = NULL;
   data = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create a serial vector */
@@ -156,13 +153,22 @@ int main(void)
   flag = CVodeSetUserData(cvode_mem, data);
   if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVBand to specify the CVBAND band linear solver */
-  flag = CVBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVBand", 1)) return(1);
+  /* Create banded SUNMatrix for use in linear solves -- since this will be factored, 
+     set the storage bandwidth to be the sum of upper and lower bandwidths */
+  A = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver object for use by CVode */
+  LS = SUNBandLinearSolver(u, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+  
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   /* Set the user-supplied Jacobian routine Jac */
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop over output points: call CVode, print results, test for errors */
 
@@ -179,9 +185,11 @@ int main(void)
 
   PrintFinalStats(cvode_mem);  /* Print some final statistics   */
 
-  N_VDestroy_Serial(u);   /* Free the u vector */
+  N_VDestroy(u);          /* Free the u vector          */
   CVodeFree(&cvode_mem);  /* Free the integrator memory */
-  free(data);             /* Free the user data */
+  SUNLinSolFree(LS);      /* Free linear solver memory  */
+  SUNMatDestroy(A);       /* Free the matrix memory     */
+  free(data);             /* Free the user data         */
 
   return(0);
 }
@@ -201,8 +209,8 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
   int i, j;
   UserData data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata  = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed constants from data */
 
@@ -239,42 +247,42 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
 
 /* Jacobian routine. Compute J(t,u). */
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector u, N_Vector fu, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype *kthCol, hordc, horac, verdc;
   UserData data;
   
   /*
-    The components of f = udot that depend on u(i,j) are
-    f(i,j), f(i-1,j), f(i+1,j), f(i,j-1), f(i,j+1), with
-      df(i,j)/du(i,j) = -2 (1/dx^2 + 1/dy^2)
-      df(i-1,j)/du(i,j) = 1/dx^2 + .25/dx  (if i > 1)
-      df(i+1,j)/du(i,j) = 1/dx^2 - .25/dx  (if i < MX)
-      df(i,j-1)/du(i,j) = 1/dy^2           (if j > 1)
-      df(i,j+1)/du(i,j) = 1/dy^2           (if j < MY)
-  */
+   * The components of f = udot that depend on u(i,j) are
+   * f(i,j), f(i-1,j), f(i+1,j), f(i,j-1), f(i,j+1), with
+   *   df(i,j)/du(i,j) = -2 (1/dx^2 + 1/dy^2)
+   *   df(i-1,j)/du(i,j) = 1/dx^2 + .25/dx  (if i > 1)
+   *   df(i+1,j)/du(i,j) = 1/dx^2 - .25/dx  (if i < MX)
+   *   df(i,j-1)/du(i,j) = 1/dy^2           (if j > 1)
+   *   df(i,j+1)/du(i,j) = 1/dy^2           (if j < MY)
+   */
 
   data = (UserData) user_data;
   hordc = data->hdcoef;
   horac = data->hacoef;
   verdc = data->vdcoef;
-  
+
+  /* set non-zero Jacobian entries */
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
+      kthCol = SUNBandMatrix_Column(J,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = verdc;
     }
   }
 
@@ -302,7 +310,7 @@ static void SetIC(N_Vector u, UserData data)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profile into u vector */
   
@@ -323,12 +331,10 @@ static void PrintHeader(realtype reltol, realtype abstol, realtype umax)
   printf("Mesh dimensions = %d X %d\n", MX, MY);
   printf("Total system size = %d\n", NEQ);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-  printf("Tolerance parameters: reltol = %Lg   abstol = %Lg\n\n",
-         reltol, abstol);
+  printf("Tolerance parameters: reltol = %Lg   abstol = %Lg\n\n", reltol, abstol);
   printf("At t = %Lg      max.norm(u) =%14.6Le \n", T0, umax);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-  printf("Tolerance parameters: reltol = %g   abstol = %g\n\n",
-         reltol, abstol);
+  printf("Tolerance parameters: reltol = %g   abstol = %g\n\n", reltol, abstol);
   printf("At t = %g      max.norm(u) =%14.6e \n", T0, umax);
 #else
   printf("Tolerance parameters: reltol = %g   abstol = %g\n\n", reltol, abstol);
@@ -381,7 +387,7 @@ static void PrintFinalStats(void *cvode_mem)
   printf("\nFinal Statistics:\n");
   printf("nst = %-6ld nfe  = %-6ld nsetups = %-6ld nfeLS = %-6ld nje = %ld\n",
 	 nst, nfe, nsetups, nfeLS, nje);
-  printf("nni = %-6ld ncfn = %-6ld netf = %ld\n \n",
+  printf("nni = %-6ld ncfn = %-6ld netf = %ld\n",
 	 nni, ncfn, netf);
 
   return;
diff --git a/examples/cvode/serial/cvAdvDiff_bndL.c b/examples/cvode/serial/cvAdvDiff_bndL.c
index c9c0625..db6adc3 100644
--- a/examples/cvode/serial/cvAdvDiff_bndL.c
+++ b/examples/cvode/serial/cvAdvDiff_bndL.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -25,19 +21,19 @@
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .1, .2, ..., 1.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-/* Header files with a description of contents used in cvbanx.c */
-
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts. and consts. */
-#include <cvode/cvode_lapack.h>      /* prototype for CVLapackBand */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., and macros */
-#include <sundials/sundials_math.h>  /* definition of ABS and EXP */
+#include <cvode/cvode.h>                     /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>          /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>        /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_lapackband.h>  /* access to band SUNLinearSolver       */
+#include <cvode/cvode_direct.h>              /* access to CVDls interface            */
+#include <sundials/sundials_types.h>         /* definition of type realtype          */
+#include <sundials/sundials_math.h>          /* definition of ABS and EXP            */
 
 /* Problem Constants */
 
@@ -65,7 +61,7 @@
    to the underlying 1-dimensional storage. 
    IJth(vdata,i,j) references the element in the vdata array for
    u at mesh point (i,j), where 1 <= i <= MX, 1 <= j <= MY.
-   The vdata array is obtained via the macro call vdata = N_VGetArrayPointer_Serial(v),
+   The vdata array is obtained via the call vdata = N_VGetArrayPointer(v),
    where v is an N_Vector. 
    The variables are ordered by the y index j, then by the x index i. */
 
@@ -91,9 +87,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 /* Functions Called by the Solver */
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector u, N_Vector fu, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /*
@@ -107,12 +102,16 @@ int main(void)
   realtype dx, dy, reltol, abstol, t, tout, umax;
   N_Vector u;
   UserData data;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
   long int nst;
 
   u = NULL;
   data = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create a serial vector */
@@ -153,15 +152,25 @@ int main(void)
   flag = CVodeSetUserData(cvode_mem, data);
   if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVLapackBand to specify the CVBAND band linear solver */
-  flag = CVLapackBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVLapackBand", 1)) return(1);
+  /* Create banded SUNMatrix for use in linear solves -- since this will be factored, 
+     set the storage bandwidth to be the sum of upper and lower bandwidths */
+  A = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create SUNLapackBand solver object for use by CVode */
+  LS = SUNLapackBand(u, A);
+  if(check_flag((void *)LS, "SUNLapackBand", 0)) return(1);
+  
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   /* Set the user-supplied Jacobian routine Jac */
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop over output points: call CVode, print results, test for errors */
+
   umax = N_VMaxNorm(u);
   PrintHeader(reltol, abstol, umax);
   for(iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) {
@@ -175,7 +184,7 @@ int main(void)
 
   PrintFinalStats(cvode_mem);  /* Print some final statistics   */
 
-  N_VDestroy_Serial(u);   /* Free the u vector */
+  N_VDestroy(u);          /* Free the u vector */
   CVodeFree(&cvode_mem);  /* Free the integrator memory */
   free(data);             /* Free the user data */
 
@@ -197,8 +206,8 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
   int i, j;
   UserData data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata  = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed constants from data */
 
@@ -235,9 +244,8 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
 
 /* Jacobian routine. Compute J(t,u). */
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector u, N_Vector fu, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   int i, j, k;
@@ -263,15 +271,15 @@ static int Jac(long int N, long int mu, long int ml,
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
+      kthCol = SUNBandMatrix_Column(J,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = verdc;
     }
   }
 
@@ -299,7 +307,7 @@ static void SetIC(N_Vector u, UserData data)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profile into u vector */
   
@@ -323,8 +331,8 @@ static void PrintHeader(realtype reltol, realtype abstol, realtype umax)
   printf("Tolerance parameters: reltol = %Lg   abstol = %Lg\n\n", reltol, abstol);
   printf("At t = %Lg      max.norm(u) =%14.6Le \n", T0, umax);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-  printf("Tolerance parameters: reltol = %lg   abstol = %lg\n\n", reltol, abstol);
-  printf("At t = %lg      max.norm(u) =%14.6le \n", T0, umax);
+  printf("Tolerance parameters: reltol = %g   abstol = %g\n\n", reltol, abstol);
+  printf("At t = %g      max.norm(u) =%14.6e \n", T0, umax);
 #else
   printf("Tolerance parameters: reltol = %g   abstol = %g\n\n", reltol, abstol);
   printf("At t = %g      max.norm(u) =%14.6e \n", T0, umax);
@@ -340,7 +348,7 @@ static void PrintOutput(realtype t, realtype umax, long int nst)
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("At t = %4.2Lf   max.norm(u) =%14.6Le   nst = %4ld\n", t, umax, nst);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-  printf("At t = %4.2f   max.norm(u) =%14.6le   nst = %4ld\n", t, umax, nst);
+  printf("At t = %4.2f   max.norm(u) =%14.6e   nst = %4ld\n", t, umax, nst);
 #else
   printf("At t = %4.2f   max.norm(u) =%14.6e   nst = %4ld\n", t, umax, nst);
 #endif
@@ -376,7 +384,7 @@ static void PrintFinalStats(void *cvode_mem)
   printf("\nFinal Statistics:\n");
   printf("nst = %-6ld nfe  = %-6ld nsetups = %-6ld nfeLS = %-6ld nje = %ld\n",
 	 nst, nfe, nsetups, nfeLS, nje);
-  printf("nni = %-6ld ncfn = %-6ld netf = %ld\n \n",
+  printf("nni = %-6ld ncfn = %-6ld netf = %ld\n",
 	 nni, ncfn, netf);
 
   return;
diff --git a/examples/cvode/serial/cvDirectDemo_ls.c b/examples/cvode/serial/cvDirectDemo_ls.c
index f64e1ee..84a85d5 100644
--- a/examples/cvode/serial/cvDirectDemo_ls.c
+++ b/examples/cvode/serial/cvDirectDemo_ls.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -30,42 +26,43 @@
  * called for each of the remaining seven runs.
  *
  * Notes: This program demonstrates the usage of the sequential
- * macros NV_Ith_S, DENSE_ELEM, BAND_COL, and
- * BAND_COL_ELEM. The NV_Ith_S macro is used to reference the
+ * macros NV_Ith_S, SM_ELEMENT_D, SM_COLUMN_B, and
+ * SM_COLUMN_ELEMENT_B. The NV_Ith_S macro is used to reference the
  * components of an N_Vector. It works for any size N=NEQ, but
  * due to efficiency concerns it should only by used when the
  * problem size is small. The Problem 1 right hand side and
  * Jacobian functions f1 and Jac1 both use NV_Ith_S. The 
- * N_VGetArrayPointer_Serial function gives the user access to the 
+ * N_VGetArrayPointer function gives the user access to the 
  * memory used for the component storage of an N_Vector. In the 
  * sequential case, the user may assume that this is one contiguous 
- * array of reals. The N_VGetArrayPointer_Serial function
+ * array of reals. The N_VGetArrayPointer function
  * gives a more efficient means (than the NV_Ith_S macro) to
  * access the components of an N_Vector and should be used when the
  * problem size is large. The Problem 2 right hand side function f2
- * uses the N_VGetArrayPointer_Serial function. The DENSE_ELEM macro 
- * used in Jac1 gives access to an element of a dense matrix of type 
- * DlsMat. It should be used only when the problem size is small (the 
- * size of a DlsMat is NEQ x NEQ) due to efficiency concerns. For
- * larger problem sizes, the macro DENSE_COL can be used in order
- * to work directly with a column of a DlsMat. The BAND_COL and
- * BAND_COL_ELEM allow efficient columnwise access to the elements
- * of a band matrix of type DlsMat. These macros are used in the
- * Jac2 function.
- * -----------------------------------------------------------------
- */
+ * uses the N_VGetArrayPointer function. The SM_ELEMENT_D macro 
+ * used in Jac1 gives access to an element of a dense SUNMatrix. It 
+ * should be used only when the problem size is small (the 
+ * size of a Dense SUNMatrix is NEQ x NEQ) due to efficiency concerns. For
+ * larger problem sizes, the macro SM_COLUMN_D can be used in order
+ * to work directly with a column of a Dense SUNMatrix. The SM_COLUMN_B and
+ * SM_COLUMN_ELEMENT_B allow efficient columnwise access to the elements
+ * of a Banded SUNMatix. These macros are used in the Jac2 function.
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>             /* main integrator header file */
-#include <cvode/cvode_dense.h>       /* use CVDENSE linear solver */
-#include <cvode/cvode_band.h>        /* use CVBAND linear solver */
-#include <cvode/cvode_diag.h>        /* use CVDIAG linear solver */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS, SUNSQR, and EXP*/
+#include <cvode/cvode.h>                  /* prototypes for CVODE fcts., consts.      */
+#include <nvector/nvector_serial.h>       /* access to serial N_Vector                */
+#include <sunmatrix/sunmatrix_dense.h>    /* access to dense SUNMatrix                */
+#include <sunlinsol/sunlinsol_dense.h>    /* access to dense SUNLinearSolver          */
+#include <sunmatrix/sunmatrix_band.h>     /* access to band SUNMatrix                 */
+#include <sunlinsol/sunlinsol_band.h>     /* access to band SUNLinearSolver           */
+#include <cvode/cvode_direct.h>           /* access to CVDls interface                */
+#include <cvode/cvode_diag.h>             /* access to CVDIAG linear solver           */
+#include <sundials/sundials_types.h>      /* definition of realtype                   */
+#include <sundials/sundials_math.h>       /* contains the macros ABS, SUNSQR, and EXP */
 
 /* Shared Problem Constants */
 
@@ -117,8 +114,9 @@ static void PrintIntro2(void);
 static void PrintHeader2(void);
 static void PrintOutput2(realtype t, realtype erm, int qu, realtype hu);
 static realtype MaxError(N_Vector y, realtype t);
-static int PrepareNextRun(void *cvode_mem, int lmm, int miter, long int mu,
-                          long int ml);
+static int PrepareNextRun(void *cvode_mem, int lmm, int miter, N_Vector y, 
+                          SUNMatrix A, sunindextype mu, sunindextype ml,
+                          SUNLinearSolver LS);
 static void PrintErrOutput(realtype tol_factor);
 static void PrintFinalStats(void *cvode_mem, int miter, realtype ero);
 static void PrintErrInfo(int nerr);
@@ -126,14 +124,11 @@ static void PrintErrInfo(int nerr);
 /* Functions Called by the Solver */
 
 static int f1(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac1(long int N, realtype tn,
-                N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
-                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac1(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J,
+                void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
 static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac2(long int N, long int mu, long int ml, 
-                realtype tn, N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
+static int Jac2(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J, void *user_data,
                 N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private function to check function return values */
@@ -158,12 +153,16 @@ static int Problem1(void)
   realtype reltol=RTOL, abstol=ATOL, t, tout, ero, er;
   int miter, flag, temp_flag, iout, nerr=0;
   N_Vector y;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   booleantype firstrun;
   int qu;
   realtype hu;
 
   y = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   y = N_VNew_Serial(P1_NEQ);
@@ -191,7 +190,7 @@ static int Problem1(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
       
-    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, 0, 0);
+    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, y, A, 0, 0, LS);
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader1();
@@ -244,7 +243,7 @@ static int Problem1(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
       
-    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, 0, 0);     
+    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, y, A, 0, 0, LS);     
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader1();
@@ -275,7 +274,7 @@ static int Problem1(void)
   }
 
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
 
   return(nerr);
 }
@@ -331,19 +330,17 @@ static int f1(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   return(0);
 } 
 
-static int Jac1(long int N, realtype tn,
-                N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
-                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac1(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J, 
+                void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y0, y1;
 
   y0 = NV_Ith_S(y,0);
   y1 = NV_Ith_S(y,1);
 
-  DENSE_ELEM(J,0,1) = ONE;
-  DENSE_ELEM(J,1,0) = -TWO * P1_ETA * y0 * y1 - ONE;
-  DENSE_ELEM(J,1,1) = P1_ETA * (ONE - SUNSQR(y0));
+  SM_ELEMENT_D(J,0,1) = ONE;
+  SM_ELEMENT_D(J,1,0) = -TWO * P1_ETA * y0 * y1 - ONE;
+  SM_ELEMENT_D(J,1,1) = P1_ETA * (ONE - SUNSQR(y0));
 
   return(0);
 }
@@ -353,12 +350,16 @@ static int Problem2(void)
   realtype reltol=RTOL, abstol=ATOL, t, tout, er, erm, ero;
   int miter, flag, temp_flag, nerr=0;
   N_Vector y;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   booleantype firstrun;
   int qu, iout;
   realtype hu;
 
   y = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   y = N_VNew_Serial(P2_NEQ);
@@ -388,7 +389,7 @@ static int Problem2(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
       
-    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, P2_MU, P2_ML);
+    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, y, A, P2_MU, P2_ML, LS);
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader2();
@@ -441,7 +442,7 @@ static int Problem2(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
 
-    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, P2_MU, P2_ML);
+    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, y, A, P2_MU, P2_ML, LS);
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader2();
@@ -471,7 +472,7 @@ static int Problem2(void)
   }
 
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
 
   return(nerr);
 }
@@ -514,11 +515,11 @@ static void PrintOutput2(realtype t, realtype erm, int qu, realtype hu)
 
 static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype d, *ydata, *dydata;
   
-  ydata = N_VGetArrayPointer_Serial(y);
-  dydata = N_VGetArrayPointer_Serial(ydot);
+  ydata  = N_VGetArrayPointer(y);
+  dydata = N_VGetArrayPointer(ydot);
 
   /*
      Excluding boundaries, 
@@ -540,10 +541,8 @@ static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   return(0);
 }
 
-static int Jac2(long int N, long int mu, long int ml, 
-                realtype tn, N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
-                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac2(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J, 
+                void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   int i, j, k;
   realtype *kthCol;
@@ -567,10 +566,10 @@ static int Jac2(long int N, long int mu, long int ml,
   for (j=0; j < P2_MESHY; j++) {
     for (i=0; i < P2_MESHX; i++) {
       k = i + j * P2_MESHX;
-      kthCol = BAND_COL(J,k);
-      BAND_COL_ELEM(kthCol,k,k) = -TWO;
-      if (i != P2_MESHX-1) BAND_COL_ELEM(kthCol,k+1,k) = P2_ALPH1;
-      if (j != P2_MESHY-1) BAND_COL_ELEM(kthCol,k+P2_MESHX,k) = P2_ALPH2;
+      kthCol = SM_COLUMN_B(J,k);
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO;
+      if (i != P2_MESHX-1) SM_COLUMN_ELEMENT_B(kthCol,k+1,k) = P2_ALPH1;
+      if (j != P2_MESHY-1) SM_COLUMN_ELEMENT_B(kthCol,k+P2_MESHX,k) = P2_ALPH2;
     }
   }
 
@@ -579,12 +578,12 @@ static int Jac2(long int N, long int mu, long int ml,
 
 static realtype MaxError(N_Vector y, realtype t)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype *ydata, er, ex=ZERO, yt, maxError=ZERO, ifact_inv, jfact_inv=ONE;
   
   if (t == ZERO) return(ZERO);
 
-  ydata = N_VGetArrayPointer_Serial(y);
+  ydata = N_VGetArrayPointer(y);
   if (t <= THIRTY) ex = SUNRexp(-TWO*t);
   
   for (j = 0; j < P2_MESHY; j++) {
@@ -601,8 +600,9 @@ static realtype MaxError(N_Vector y, realtype t)
   return(maxError);
 }
 
-static int PrepareNextRun(void *cvode_mem, int lmm, int miter, 
-                          long int mu, long int ml)
+static int PrepareNextRun(void *cvode_mem, int lmm, int miter, N_Vector y, 
+                          SUNMatrix A, sunindextype mu, sunindextype ml,
+                          SUNLinearSolver LS)
 {
   int flag = CV_SUCCESS;
   
@@ -621,38 +621,96 @@ static int PrepareNextRun(void *cvode_mem, int lmm, int miter,
   } else {
     printf("NEWTON\n");
     printf("Linear Solver           : ");
+
     switch(miter) {
+
     case DENSE_USER : 
       printf("Dense, User-Supplied Jacobian\n");
-      flag = CVDense(cvode_mem, P1_NEQ);
-      check_flag(&flag, "CVDense", 1);
-      if(flag != CV_SUCCESS) break;
-      flag = CVDlsSetDenseJacFn(cvode_mem, Jac1);
-      check_flag(&flag, "CVDlsSetDenseJacFn", 1);
+
+      /* Create dense SUNMatrix for use in linear solves */
+      A = SUNDenseMatrix(P1_NEQ, P1_NEQ);
+      if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+      /* Create dense SUNLinearSolver object for use by CVode */
+      LS = SUNDenseLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Set the user-supplied Jacobian routine Jac */
+      flag = CVDlsSetJacFn(cvode_mem, Jac1);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
       break;
-    case DENSE_DQ   : 
+
+    case DENSE_DQ : 
       printf("Dense, Difference Quotient Jacobian\n");
-      flag = CVDlsSetDenseJacFn(cvode_mem, NULL);
-      check_flag(&flag, "CVDlsSetDenseJacFn", 1);
+
+      /* Create dense SUNMatrix for use in linear solves */
+      A = SUNDenseMatrix(P1_NEQ, P1_NEQ);
+      if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+      /* Create dense SUNLinearSolver object for use by CVode */
+      LS = SUNDenseLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Use a difference quotient Jacobian */
+      flag = CVDlsSetJacFn(cvode_mem, NULL);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
       break;
-    case DIAG       : 
+
+    case DIAG : 
       printf("Diagonal Jacobian\n");
+
+      /* Call CVDiag to create/attach the CVODE-specific diagonal solver */
       flag = CVDiag(cvode_mem);
-      check_flag(&flag, "CVDiag", 1);
+      if(check_flag(&flag, "CVDiag", 1)) return(1);
       break;
-    case BAND_USER  : 
+
+    case BAND_USER : 
       printf("Band, User-Supplied Jacobian\n");
-      flag = CVBand(cvode_mem, P2_NEQ, mu, ml);
-      check_flag(&flag, "CVBand", 1);
-      if(flag != CV_SUCCESS) break;
-      flag = CVDlsSetBandJacFn(cvode_mem, Jac2);
-      check_flag(&flag, "CVDlsSetBandJacFn", 1);
+
+      /* Create band SUNMatrix for use in linear solves */
+      A = SUNBandMatrix(P2_NEQ, mu, ml, mu+ml);
+      if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+      /* Create banded SUNLinearSolver object for use by CVode */
+      LS = SUNBandLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Set the user-supplied Jacobian routine Jac */
+      flag = CVDlsSetJacFn(cvode_mem, Jac2);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
       break;
+
     case BAND_DQ  :   
       printf("Band, Difference Quotient Jacobian\n");
-      flag = CVDlsSetBandJacFn(cvode_mem, NULL);
-      check_flag(&flag, "CVDlsSetBandJacFn", 1);
-      break;    
+
+      /* Create band SUNMatrix for use in linear solves */
+      A = SUNBandMatrix(P2_NEQ, mu, ml, mu+ml);
+      if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+      /* Create banded SUNLinearSolver object for use by CVode */
+      LS = SUNBandLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Use a difference quotient Jacobian */
+      flag = CVDlsSetJacFn(cvode_mem, NULL);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
+      break;
     }
   }
 
@@ -674,8 +732,8 @@ static void PrintErrOutput(realtype tol_factor)
 
 static void PrintFinalStats(void *cvode_mem, int miter, realtype ero)
 {
-  long int lenrw, leniw, nst, nfe, nsetups, nni, ncfn, netf;
-  long int lenrwLS, leniwLS, nje, nfeLS;
+  long int lenrw, leniw, lenrwLS, leniwLS;
+  long int nst, nfe, nsetups, nni, ncfn, netf, nje, nfeLS;
   int flag;
 
   flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
@@ -694,8 +752,8 @@ static void PrintFinalStats(void *cvode_mem, int miter, realtype ero)
   check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
 
   printf("\n Final statistics for this run:\n\n");
-  printf(" CVode real workspace length              = %4ld \n", lenrw);
-  printf(" CVode integer workspace length           = %4ld \n", leniw);
+  printf(" CVode real workspace length              = %4ld \n",  lenrw);
+  printf(" CVode integer workspace length           = %4ld \n",  leniw);
   printf(" Number of steps                          = %4ld \n",  nst);
   printf(" Number of f-s                            = %4ld \n",  nfe);
   printf(" Number of setups                         = %4ld \n",  nsetups);
@@ -704,36 +762,23 @@ static void PrintFinalStats(void *cvode_mem, int miter, realtype ero)
   printf(" Number of error test failures            = %4ld \n\n",netf);
   
   if (miter != FUNC) {
-    switch(miter) {
-    case DENSE_USER :
-    case DENSE_DQ   :
+    if (miter != DIAG) {
       flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
       check_flag(&flag, "CVDlsGetNumJacEvals", 1);
       flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
       check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
       flag = CVDlsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
       check_flag(&flag, "CVDlsGetWorkSpace", 1);
-      break;
-    case BAND_USER  :
-    case BAND_DQ    :
-      flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
-      check_flag(&flag, "CVDlsGetNumJacEvals", 1);
-      flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
-      check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
-      flag = CVDlsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
-      check_flag(&flag, "CVDlsGetWorkSpace", 1);
-      break;  
-    case DIAG       :
+    } else {
       nje = nsetups;
       flag = CVDiagGetNumRhsEvals(cvode_mem, &nfeLS);
       check_flag(&flag, "CVDiagGetNumRhsEvals", 1);
       flag = CVDiagGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
       check_flag(&flag, "CVDiagGetWorkSpace", 1);
-      break;
     }
     printf(" Linear solver real workspace length      = %4ld \n", lenrwLS);
     printf(" Linear solver integer workspace length   = %4ld \n", leniwLS);
-    printf(" Number of Jacobian evaluations           = %4ld  \n", nje);
+    printf(" Number of Jacobian evaluations           = %4ld \n", nje);
     printf(" Number of f evals. in linear solver      = %4ld \n\n", nfeLS);
   }
   
diff --git a/examples/cvode/serial/cvDirectDemo_ls.out b/examples/cvode/serial/cvDirectDemo_ls.out
index 7c8b837..5dfee37 100644
--- a/examples/cvode/serial/cvDirectDemo_ls.out
+++ b/examples/cvode/serial/cvDirectDemo_ls.out
@@ -12,9 +12,9 @@ Iteration               : FUNCTIONAL
 
      t           x              xdot         qu     hu 
    1.39284     1.68010e+00   -2.91056e-01    5    9.8626e-02
-   3.60761    -2.12392e-05   -3.16877e+00    5    2.2756e-02
+   3.60761    -2.12391e-05   -3.16877e+00    5    2.2757e-02
    5.82239    -1.68010e+00    2.91060e-01    4    1.4079e-01
-   8.03716     9.57611e-05    3.16900e+00    5    2.0348e-02
+   8.03716     9.57608e-05    3.16900e+00    5    2.0348e-02
 
  Final statistics for this run:
 
@@ -53,9 +53,9 @@ Linear Solver           : Dense, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   23 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    5  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    5 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 19.908 
@@ -71,7 +71,7 @@ Linear Solver           : Dense, Difference Quotient Jacobian
    1.39284     1.68010e+00   -2.91056e-01    5    6.5835e-02
    3.60761    -2.28046e-05   -3.16879e+00    6    3.1773e-02
    5.82239    -1.68010e+00    2.91059e-01    6    9.3514e-02
-   8.03716    -9.84768e-06    3.16869e+00    6    2.8096e-02
+   8.03716    -9.84742e-06    3.16869e+00    6    2.8096e-02
 
  Final statistics for this run:
 
@@ -84,9 +84,9 @@ Linear Solver           : Dense, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   15 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    4  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    4 
  Number of f evals. in linear solver      =    8 
 
  Error overrun = 22.805 
@@ -101,26 +101,26 @@ Linear Solver           : Diagonal Jacobian
      t           x              xdot         qu     hu 
    1.39284     1.68010e+00   -2.91054e-01    6    5.9553e-02
    3.60761     6.36071e-05   -3.16853e+00    6    2.8912e-02
-   5.82239    -1.68011e+00    2.91057e-01    5    9.8123e-02
-   8.03716    -8.21358e-05    3.16848e+00    6    2.2328e-02
+   5.82239    -1.68011e+00    2.91057e-01    5    9.8149e-02
+   8.03716    -7.70359e-05    3.16847e+00    6    2.3224e-02
 
  Final statistics for this run:
 
  CVode real workspace length              =  123 
  CVode integer workspace length           =   57 
- Number of steps                          =  241 
- Number of f-s                            =  340 
- Number of setups                         =   42 
- Number of nonlinear iterations           =  336 
+ Number of steps                          =  238 
+ Number of f-s                            =  330 
+ Number of setups                         =   40 
+ Number of nonlinear iterations           =  326 
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   20 
 
  Linear solver real workspace length      =    6 
  Linear solver integer workspace length   =    3 
- Number of Jacobian evaluations           =   42  
- Number of f evals. in linear solver      =   42 
+ Number of Jacobian evaluations           =   40 
+ Number of f evals. in linear solver      =   40 
 
- Error overrun = 82.136 
+ Error overrun = 77.036 
 
 
 -------------------------------------------------------------
@@ -171,9 +171,9 @@ Linear Solver           : Dense, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   18 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    5  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    5 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 154.312 
@@ -202,9 +202,9 @@ Linear Solver           : Dense, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   17 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    6  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    6 
  Number of f evals. in linear solver      =   12 
 
  Error overrun = 96.174 
@@ -220,7 +220,7 @@ Linear Solver           : Diagonal Jacobian
    1.39284     1.68010e+00   -2.91056e-01    5    1.1430e-01
    3.60761    -9.83501e-05   -3.16900e+00    5    1.6712e-02
    5.82239    -1.68009e+00    2.91063e-01    4    8.1261e-02
-   8.03716     1.66644e-04    3.16920e+00    4    1.0547e-02
+   8.03716     1.66640e-04    3.16920e+00    4    1.0546e-02
 
  Final statistics for this run:
 
@@ -235,10 +235,10 @@ Linear Solver           : Diagonal Jacobian
 
  Linear solver real workspace length      =    6 
  Linear solver integer workspace length   =    3 
- Number of Jacobian evaluations           =   39  
+ Number of Jacobian evaluations           =   39 
  Number of f evals. in linear solver      =   39 
 
- Error overrun = 166.644 
+ Error overrun = 166.640 
 
 
 -------------------------------------------------------------
@@ -260,16 +260,16 @@ Iteration               : FUNCTIONAL
      0.100    5.2543e-07    4     4.1413e-02
      1.000    1.2207e-06    5     6.8243e-02
     10.000    9.7711e-07    3     2.8481e-01
-   100.000    1.5230e-07    1     6.0816e-01
+   100.000    2.2510e-07    1     6.7722e-01
 
  Final statistics for this run:
 
  CVode real workspace length              =  514 
  CVode integer workspace length           =   57 
  Number of steps                          =  341 
- Number of f-s                            =  601 
+ Number of f-s                            =  602 
  Number of setups                         =    0 
- Number of nonlinear iterations           =  597 
+ Number of nonlinear iterations           =  598 
  Number of nonlinear convergence failures =   79 
  Number of error test failures            =    0 
 
@@ -286,8 +286,8 @@ Linear Solver           : Diagonal Jacobian
      0.010    1.3734e-07    3     1.0327e-02
      0.100    2.4956e-06    3     2.3048e-02
      1.000    4.2328e-06    4     4.3778e-02
-    10.000    9.7335e-07    4     3.1286e-01
-   100.000    8.2265e-10    1     3.9630e+02
+    10.000    9.7303e-07    4     3.1286e-01
+   100.000    1.1241e-09    1     3.7371e+02
 
  Final statistics for this run:
 
@@ -302,7 +302,7 @@ Linear Solver           : Diagonal Jacobian
 
  Linear solver real workspace length      =   75 
  Linear solver integer workspace length   =    3 
- Number of Jacobian evaluations           =   33  
+ Number of Jacobian evaluations           =   33 
  Number of f evals. in linear solver      =   33 
 
  Error overrun = 4.233 
@@ -332,9 +332,9 @@ Linear Solver           : Band, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    6 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 0.608 
@@ -351,7 +351,7 @@ Linear Solver           : Band, Difference Quotient Jacobian
      0.100    5.7337e-07    4     4.2111e-02
      1.000    7.3281e-07    5     6.3684e-02
     10.000    3.8507e-07    5     2.6026e-01
-   100.000    4.1035e-12    1     6.2591e+01
+   100.000    4.1037e-12    1     6.2591e+01
 
  Final statistics for this run:
 
@@ -364,9 +364,9 @@ Linear Solver           : Band, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    1 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =   18 
 
  Error overrun = 0.733 
@@ -382,16 +382,16 @@ Iteration               : FUNCTIONAL
      0.100    5.2896e-06    3     1.7769e-02
      1.000    2.3209e-06    5     7.5291e-02
     10.000    1.2861e-06    5     2.7791e-01
-   100.000    1.6770e-08    1     8.7560e-01
+   100.000    2.8424e-07    1     2.5672e-01
 
  Final statistics for this run:
 
  CVode real workspace length              =  339 
  CVode integer workspace length           =   50 
- Number of steps                          =  377 
- Number of f-s                            =  698 
+ Number of steps                          =  372 
+ Number of f-s                            =  693 
  Number of setups                         =    0 
- Number of nonlinear iterations           =  694 
+ Number of nonlinear iterations           =  689 
  Number of nonlinear convergence failures =   56 
  Number of error test failures            =    1 
 
@@ -408,26 +408,26 @@ Linear Solver           : Diagonal Jacobian
      0.010    5.6365e-07    2     8.1241e-03
      0.100    7.9753e-07    4     1.8910e-02
      1.000    5.9100e-06    5     5.1976e-02
-    10.000    1.1253e-05    4     9.7523e-02
-   100.000    1.1182e-09    1     8.7300e+01
+    10.000    2.1547e-06    4     3.1113e-01
+   100.000    4.2213e-09    1     1.3897e+02
 
  Final statistics for this run:
 
  CVode real workspace length              =  339 
  CVode integer workspace length           =   50 
- Number of steps                          =  202 
- Number of f-s                            =  315 
- Number of setups                         =   63 
- Number of nonlinear iterations           =  311 
- Number of nonlinear convergence failures =    5 
- Number of error test failures            =    7 
+ Number of steps                          =  180 
+ Number of f-s                            =  271 
+ Number of setups                         =   47 
+ Number of nonlinear iterations           =  267 
+ Number of nonlinear convergence failures =    2 
+ Number of error test failures            =    5 
 
  Linear solver real workspace length      =   75 
  Linear solver integer workspace length   =    3 
- Number of Jacobian evaluations           =   63  
- Number of f evals. in linear solver      =   63 
+ Number of Jacobian evaluations           =   47 
+ Number of f evals. in linear solver      =   47 
 
- Error overrun = 11.253 
+ Error overrun = 5.910 
 
 
 -------------------------------------------------------------
@@ -454,9 +454,9 @@ Linear Solver           : Band, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    2 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 5.278 
@@ -486,9 +486,9 @@ Linear Solver           : Band, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    1 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =   18 
 
  Error overrun = 5.997 
diff --git a/examples/cvode/serial/cvDiurnal_kry.c b/examples/cvode/serial/cvDiurnal_kry.c
index 4dd127a..5d035ce 100644
--- a/examples/cvode/serial/cvDiurnal_kry.c
+++ b/examples/cvode/serial/cvDiurnal_kry.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4848 $
- * $Date: 2016-08-03 15:51:16 -0700 (Wed, 03 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -24,24 +20,24 @@
  * The PDE system is treated by central differences on a uniform
  * 10 x 10 mesh, with simple polynomial initial profiles.
  * The problem is solved with CVODE, with the BDF/GMRES
- * method (i.e. using the CVSPGMR linear solver) and the
+ * method (i.e. using the SUNSPGMR linear solver) and the
  * block-diagonal part of the Newton matrix as a left
  * preconditioner. A copy of the block-diagonal part of the
  * Jacobian is saved and conditionally reused within the Precond
  * routine.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>              /* main integrator header file */
-#include <cvode/cvode_spgmr.h>        /* prototypes & constants for CVSPGMR */
-#include <nvector/nvector_serial.h>   /* serial N_Vector types, fct., macros */
-#include <sundials/sundials_dense.h>  /* use generic dense solver in precond. */
-#include <sundials/sundials_types.h>  /* definition of realtype */
-#include <sundials/sundials_math.h>   /* contains the macros ABS, SUNSQR, EXP */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvode/cvode_spils.h>         /* access to CVSpils interface          */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* contains the macros ABS, SUNSQR, EXP */
 
 /* Problem Constants */
 
@@ -98,7 +94,7 @@
    IJKth(vdata,i,j,k) references the element in the vdata array for
    species i at mesh point (j,k), where 1 <= i <= NUM_SPECIES,
    0 <= j <= MX-1, 0 <= k <= MY-1. The vdata array is obtained via
-   the macro call vdata = N_VGetArrayPointer_Serial(v), where v is an N_Vector. 
+   the call vdata = N_VGetArrayPointer(v), where v is an N_Vector. 
    For each mesh point (j,k), the elements for species i and i+1 are
    contiguous within vdata.
 
@@ -115,7 +111,7 @@
 
 typedef struct {
   realtype **P[MX][MY], **Jbd[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   realtype q4, om, dx, dy, hdco, haco, vdco;
 } *UserData;
 
@@ -127,6 +123,8 @@ static void FreeUserData(UserData data);
 static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy);
 static void PrintOutput(void *cvode_mem, N_Vector u, realtype t);
 static void PrintFinalStats(void *cvode_mem);
+
+/* Private function to check function return values */
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /* Functions Called by the Solver */
@@ -137,15 +135,11 @@ static int jtv(N_Vector v, N_Vector Jv, realtype t,
                N_Vector y, N_Vector fy,
                void *user_data, N_Vector tmp);
 
-static int Precond(realtype tn, N_Vector u, N_Vector fu,
-                   booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3);
+static int Precond(realtype tn, N_Vector u, N_Vector fu, booleantype jok, 
+                   booleantype *jcurPtr, realtype gamma, void *user_data);
 
-static int PSolve(realtype tn, N_Vector u, N_Vector fu,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+static int PSolve(realtype tn, N_Vector u, N_Vector fu, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data);
 
 
 /*
@@ -159,11 +153,13 @@ int main()
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
@@ -173,8 +169,8 @@ int main()
   if(check_flag((void *)data, "AllocUserData", 2)) return(1);
   InitUserData(data);
   SetInitialProfiles(u, data->dx, data->dy);
-  abstol=ATOL; 
-  reltol=RTOL;
+  abstol = ATOL; 
+  reltol = RTOL;
 
   /* Call CVodeCreate to create the solver memory and specify the 
    * Backward Differentiation Formula and the use of a Newton iteration */
@@ -196,14 +192,18 @@ int main()
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR 
-   * with left preconditioning and the maximum Krylov dimension maxl */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+  /* Call SUNSPGMR to specify the linear solver SUNSPGMR 
+   * with left preconditioning and the default Krylov dimension */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Call CVSpilsSetLinearSolver to attach the linear sovler to CVode */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
   /* set the JAcobian-times-vector function */
-  flag = CVSpilsSetJacTimesVecFn(cvode_mem, jtv);
-  if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1);
+  flag = CVSpilsSetJacTimes(cvode_mem, NULL, jtv);
+  if(check_flag(&flag, "CVSpilsSetJacTimes", 1)) return(1);
 
   /* Set the preconditioner solve and setup functions */
   flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
@@ -220,9 +220,10 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free memory */
-  N_VDestroy_Serial(u);
+  N_VDestroy(u);
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   return(0);
 }
@@ -246,7 +247,7 @@ static UserData AllocUserData(void)
     for (jy=0; jy < MY; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
       (data->Jbd)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
 
@@ -292,7 +293,7 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profiles of c1 and c2 into u vector */
 
@@ -319,7 +320,7 @@ static void PrintOutput(void *cvode_mem, N_Vector u, realtype t)
   realtype hu, *udata;
   int mxh = MX/2 - 1, myh = MY/2 - 1, mx1 = MX - 1, my1 = MY - 1;
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -391,9 +392,9 @@ static void PrintFinalStats(void *cvode_mem)
   check_flag(&flag, "CVSpilsGetNumRhsEvals", 1);
 
   printf("\nFinal Statistics.. \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwLS = %5ld     leniwLS = %5ld\n", lenrwLS, leniwLS);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwLS = %5ld     leniwLS = %5ld\n"  , lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfeLS   = %5ld\n"  , nfe, nfeLS);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
   printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
@@ -454,9 +455,9 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   int jx, jy, idn, iup, ileft, iright;
   UserData data;
 
-  data = (UserData) user_data;
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  data   = (UserData) user_data;
+  udata  = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Set diurnal rate coefficients. */
 
@@ -465,8 +466,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
     q3 = SUNRexp(-A3/s);
     data->q4 = SUNRexp(-A4/s);
   } else {
-      q3 = ZERO;
-      data->q4 = ZERO;
+    q3 = ZERO;
+    data->q4 = ZERO;
   }
 
   /* Make local copies of problem variables, for efficiency. */
@@ -553,9 +554,9 @@ static int jtv(N_Vector v, N_Vector Jv, realtype t,
 
   data = (UserData) user_data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  vdata = N_VGetArrayPointer_Serial(v);
-  Jvdata = N_VGetArrayPointer_Serial(Jv);
+  udata  = N_VGetArrayPointer(u);
+  vdata  = N_VGetArrayPointer(v);
+  Jvdata = N_VGetArrayPointer(Jv);
 
   /* Set diurnal rate coefficients. */
 
@@ -684,14 +685,12 @@ static int jtv(N_Vector v, N_Vector Jv, realtype t,
 
 /* Preconditioner setup routine. Generate and preprocess P. */
 
-static int Precond(realtype tn, N_Vector u, N_Vector fu,
-                   booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3)
+static int Precond(realtype tn, N_Vector u, N_Vector fu, booleantype jok, 
+                   booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MY], **(*Jbd)[MY];
-  long int *(*pivot)[MY], ier;
+  sunindextype *(*pivot)[MY], ier;
   int jx, jy;
   realtype *udata, **a, **j;
   UserData data;
@@ -702,22 +701,22 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
   P = data->P;
   Jbd = data->Jbd;
   pivot = data->pivot;
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
   
   if (jok) {
     
-    /* jok = TRUE: Copy Jbd to P */
+    /* jok = SUNTRUE: Copy Jbd to P */
     
     for (jy=0; jy < MY; jy++)
       for (jx=0; jx < MX; jx++)
         denseCopy(Jbd[jx][jy], P[jx][jy], NUM_SPECIES, NUM_SPECIES);
     
-    *jcurPtr = FALSE;
+    *jcurPtr = SUNFALSE;
     
   }
   
   else {
-    /* jok = FALSE: Generate Jbd from scratch and copy to P */
+    /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
     
     /* Make local copies of problem variables, for efficiency. */
     
@@ -748,7 +747,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
     
-    *jcurPtr = TRUE;
+    *jcurPtr = SUNTRUE;
     
   }
   
@@ -773,13 +772,11 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 
 /* Preconditioner solve routine */
 
-static int PSolve(realtype tn, N_Vector u, N_Vector fu,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+static int PSolve(realtype tn, N_Vector u, N_Vector fu, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data)
 {
   realtype **(*P)[MY];
-  long int *(*pivot)[MY];
+  sunindextype *(*pivot)[MY];
   int jx, jy;
   realtype *zdata, *v;
   UserData data;
@@ -789,7 +786,7 @@ static int PSolve(realtype tn, N_Vector u, N_Vector fu,
   data = (UserData) user_data;
   P = data->P;
   pivot = data->pivot;
-  zdata = N_VGetArrayPointer_Serial(z);
+  zdata = N_VGetArrayPointer(z);
   
   N_VScale(ONE, r, z);
   
diff --git a/examples/cvode/serial/cvDiurnal_kry.out b/examples/cvode/serial/cvDiurnal_kry.out
index 8b02132..ccc4c42 100644
--- a/examples/cvode/serial/cvDiurnal_kry.out
+++ b/examples/cvode/serial/cvDiurnal_kry.out
@@ -13,51 +13,51 @@ t = 2.16e+04   no. steps = 277   order = 5   stepsize = 2.75e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 301   order = 5   stepsize = 3.87e+02
+t = 2.88e+04   no. steps = 307   order = 4   stepsize = 2.03e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 343   order = 3   stepsize = 2.34e+01
+t = 3.60e+04   no. steps = 338   order = 5   stepsize = 9.92e+01
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 421   order = 4   stepsize = 5.26e+02
-c1 (bot.left/middle/top rt.) =   -4.385e-06    -1.528e-06    -4.905e-06
+t = 4.32e+04   no. steps = 393   order = 4   stepsize = 2.57e+02
+c1 (bot.left/middle/top rt.) =   -7.891e-06    -1.123e-06    -8.723e-06
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 445   order = 3   stepsize = 1.98e+02
-c1 (bot.left/middle/top rt.) =    4.461e-07     1.869e-07     4.842e-07
+t = 5.04e+04   no. steps = 421   order = 5   stepsize = 4.96e+02
+c1 (bot.left/middle/top rt.) =   -1.595e-08    -1.771e-06    -3.117e-08
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 462   order = 5   stepsize = 2.35e+02
-c1 (bot.left/middle/top rt.) =    3.204e-09     1.203e-09     3.555e-09
+t = 5.76e+04   no. steps = 439   order = 4   stepsize = 1.19e+02
+c1 (bot.left/middle/top rt.) =   -2.127e-06    -1.513e-04    -2.951e-06
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 474   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -1.066e-09    -3.409e-10    -1.206e-09
+t = 6.48e+04   no. steps = 458   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =   -1.084e-09    -7.686e-08    -1.499e-09
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 486   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    2.614e-09     9.722e-10     2.904e-09
+t = 7.20e+04   no. steps = 469   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =   -1.093e-10    -7.736e-09    -1.510e-10
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 498   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    4.649e-11     1.729e-11     5.161e-11
+t = 7.92e+04   no. steps = 480   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =   -1.624e-12    -1.151e-10    -2.246e-12
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 510   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -8.856e-14    -3.348e-14    -9.785e-14
+t = 8.64e+04   no. steps = 491   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =    3.501e-14     2.474e-12     4.816e-14
 c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2089     leniw   =    50
-lenrwLS =  2046     leniwLS =    10
-nst     =   510
-nfe     =   675     nfeLS   =   641
-nni     =   671     nli     =   641
-nsetups =    94     netf    =    36
-npe     =     9     nps     =  1243
+lenrwLS =  2450     leniwLS =    22
+nst     =   491
+nfe     =   631     nfeLS   =     0
+nni     =   627     nli     =   643
+nsetups =    82     netf    =    29
+npe     =     9     nps     =  1214
 ncfn    =     0     ncfl    =     0
 
diff --git a/examples/cvode/serial/cvDiurnal_kry_bp.c b/examples/cvode/serial/cvDiurnal_kry_bp.c
index 25643dd..b2311c5 100644
--- a/examples/cvode/serial/cvDiurnal_kry_bp.c
+++ b/examples/cvode/serial/cvDiurnal_kry_bp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @LLNL
  * -----------------------------------------------------------------
@@ -28,19 +24,19 @@
  * preconditioner, generated by difference quotients, using the
  * module CVBANDPRE. The problem is solved with left and right
  * preconditioning.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>             /* main integrator header file */
-#include <cvode/cvode_spgmr.h>       /* prototypes & constants for CVSPGMR solver */
-#include <cvode/cvode_bandpre.h>     /* prototypes & constants for CVBANDPRE module */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS, SUNSQR, and EXP */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvode/cvode_spils.h>         /* access to CVSpils interface          */
+#include <cvode/cvode_bandpre.h>       /* access to CVBANDPRE module           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* contains the macros ABS, SUNSQR, EXP */
 
 /* Problem Constants */
 
@@ -97,12 +93,12 @@
    IJKth(vdata,i,j,k) references the element in the vdata array for
    species i at mesh point (j,k), where 1 <= i <= NUM_SPECIES,
    0 <= j <= MX-1, 0 <= k <= MY-1. The vdata array is obtained via
-   the macro call vdata = N_VGetArrayPointer_Serial(v), where v is an N_Vector. 
+   the call vdata = N_VGetArrayPointer(v), where v is an N_Vector. 
    For each mesh point (j,k), the elements for species i and i+1 are
    contiguous within vdata.
 
    IJth(a,i,j) references the (i,j)th entry of the small matrix realtype **a,
-   where 1 <= i,j <= NUM_SPECIES. The small matrix routines in dense.h
+   where 1 <= i,j <= NUM_SPECIES. The small matrix routines in cvode_bandpre.h
    work with matrices stored by column in a 2-dimensional array. In C,
    arrays are indexed starting at 0, not 1. */
 
@@ -120,7 +116,7 @@ typedef struct {
 
 static void InitUserData(UserData data);
 static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy);
-static void PrintIntro(long int mu, long int ml);
+static void PrintIntro(sunindextype mu, sunindextype ml);
 static void PrintOutput(void *cvode_mem, N_Vector u, realtype t);
 static void PrintFinalStats(void *cvode_mem);
 
@@ -142,12 +138,14 @@ int main()
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, iout, jpre;
-  long int ml, mu;
+  sunindextype ml, mu;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Allocate and initialize u, and set problem data and tolerances */ 
@@ -180,10 +178,14 @@ int main()
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR 
-     with left preconditioning and the maximum Krylov dimension maxl */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+  /* Call SUNSPGMR to specify the linear solver SUNSPGMR 
+   * with left preconditioning and the default Krylov dimension */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Call CVSpilsSetLinearSolver to attach the linear sovler to CVode */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
   /* Call CVBandPreInit to initialize band preconditioner */
   ml = mu = 2;
@@ -205,8 +207,8 @@ int main()
       flag = CVodeReInit(cvode_mem, T0, u);
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
 
-      flag = CVSpilsSetPrecType(cvode_mem, PREC_RIGHT);
-      if(check_flag(&flag, "CVSpilsSetPrecType", 1)) return(1);
+      flag = SUNSPGMRSetPrecType(LS, PREC_RIGHT);
+      if(check_flag(&flag, "SUNSPGMRSetPrecType", 1)) return(1);
 
       flag = CVBandPrecInit(cvode_mem, NEQ, mu, ml);
       if(check_flag(&flag, "CVBandPrecInit", 0)) return(1);
@@ -236,9 +238,10 @@ int main()
   } /* End of jpre loop */
 
   /* Free memory */
-  N_VDestroy_Serial(u);
+  N_VDestroy(u);
   free(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   return(0);
 }
@@ -271,15 +274,15 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profiles of c1 and c2 into u vector */
 
-  for (jy = 0; jy < MY; jy++) {
+  for (jy=0; jy < MY; jy++) {
     y = YMIN + jy*dy;
     cy = SUNSQR(RCONST(0.1)*(y - YMID));
     cy = ONE - cy + RCONST(0.5)*SUNSQR(cy);
-    for (jx = 0; jx < MX; jx++) {
+    for (jx=0; jx < MX; jx++) {
       x = XMIN + jx*dx;
       cx = SUNSQR(RCONST(0.1)*(x - XMID));
       cx = ONE - cx + RCONST(0.5)*SUNSQR(cx);
@@ -289,26 +292,26 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
   }
 }
 
-static void PrintIntro(long int mu, long int ml)
+static void PrintIntro(sunindextype mu, sunindextype ml)
 {
   printf("2-species diurnal advection-diffusion problem, %d by %d mesh\n",
          MX, MY);
   printf("SPGMR solver; band preconditioner; mu = %ld, ml = %ld\n\n",
-         mu, ml);
+         (long int) mu, (long int) ml);
 
   return;
 }
 
 /* Print current t, step count, order, stepsize, and sampled c1,c2 values */
 
-static void PrintOutput(void *cvode_mem, N_Vector u,realtype t)
+static void PrintOutput(void *cvode_mem, N_Vector u, realtype t)
 {
   long int nst;
   int qu, flag;
   realtype hu, *udata;
   int mxh = MX/2 - 1, myh = MY/2 - 1, mx1 = MX - 1, my1 = MY - 1;
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -387,10 +390,10 @@ static void PrintFinalStats(void *cvode_mem)
   check_flag(&flag, "CVBandPrecGetNumRhsEvals", 1);
 
   printf("\nFinal Statistics.. \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwls = %5ld     leniwls = %5ld\n", lenrwLS, leniwLS);
-  printf("lenrwbp = %5ld     leniwbp = %5ld\n", lenrwBP, leniwBP);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwls = %5ld     leniwls = %5ld\n"  , lenrwLS, leniwLS);
+  printf("lenrwbp = %5ld     leniwbp = %5ld\n"  , lenrwBP, leniwBP);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfetot  = %5ld\n"  , nfe, nfe+nfeLS+nfeBP);
   printf("nfeLS   = %5ld     nfeBP   = %5ld\n"  , nfeLS, nfeBP);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
@@ -440,21 +443,21 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
  *-------------------------------
  */
 
-/* f routine. Compute f(t,u). */
+/* f routine. Compute RHS function f(t,u). */
 
-static int f(realtype t, N_Vector u, N_Vector udot,void *user_data)
+static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 {
   realtype q3, c1, c2, c1dn, c2dn, c1up, c2up, c1lt, c2lt;
   realtype c1rt, c2rt, cydn, cyup, hord1, hord2, horad1, horad2;
   realtype qq1, qq2, qq3, qq4, rkin1, rkin2, s, vertd1, vertd2, ydn, yup;
   realtype q4coef, dely, verdco, hordco, horaco;
   realtype *udata, *dudata;
-  int idn, iup, ileft, iright, jx, jy;
+  int jx, jy, idn, iup, ileft, iright;
   UserData data;
 
-  data = (UserData) user_data;
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  data   = (UserData) user_data;
+  udata  = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Set diurnal rate coefficients. */
 
@@ -477,7 +480,7 @@ static int f(realtype t, N_Vector u, N_Vector udot,void *user_data)
 
   /* Loop over all grid points. */
 
-  for (jy = 0; jy < MY; jy++) {
+  for (jy=0; jy < MY; jy++) {
 
     /* Set vertical diffusion coefficients at jy +- 1/2 */
 
@@ -487,7 +490,7 @@ static int f(realtype t, N_Vector u, N_Vector udot,void *user_data)
     cyup = verdco*SUNRexp(RCONST(0.2)*yup);
     idn = (jy == 0) ? 1 : -1;
     iup = (jy == MY-1) ? -1 : 1;
-    for (jx = 0; jx < MX; jx++) {
+    for (jx=0; jx < MX; jx++) {
 
       /* Extract c1 and c2, and set kinetic rate terms. */
 
diff --git a/examples/cvode/serial/cvDiurnal_kry_bp.out b/examples/cvode/serial/cvDiurnal_kry_bp.out
index 2cb79d3..5a9408e 100644
--- a/examples/cvode/serial/cvDiurnal_kry_bp.out
+++ b/examples/cvode/serial/cvDiurnal_kry_bp.out
@@ -17,54 +17,54 @@ t = 2.16e+04   no. steps = 246   order = 5   stepsize = 2.78e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 288   order = 4   stepsize = 1.14e+02
+t = 2.88e+04   no. steps = 298   order = 3   stepsize = 1.33e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 329   order = 4   stepsize = 9.61e+01
+t = 3.60e+04   no. steps = 341   order = 4   stepsize = 6.31e+01
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 401   order = 4   stepsize = 3.13e+02
-c1 (bot.left/middle/top rt.) =   -9.450e-09     3.907e-09    -1.083e-08
+t = 4.32e+04   no. steps = 402   order = 4   stepsize = 4.48e+02
+c1 (bot.left/middle/top rt.) =    1.915e-07    -6.130e-06     4.395e-07
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 416   order = 4   stepsize = 3.68e+02
-c1 (bot.left/middle/top rt.) =    1.195e-10     4.155e-08     2.046e-10
+t = 5.04e+04   no. steps = 422   order = 4   stepsize = 3.17e+02
+c1 (bot.left/middle/top rt.) =   -7.746e-11    -3.073e-08    -3.512e-11
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 430   order = 5   stepsize = 3.78e+02
-c1 (bot.left/middle/top rt.) =   -5.093e-11    -2.114e-08     2.070e-10
+t = 5.76e+04   no. steps = 436   order = 5   stepsize = 3.58e+02
+c1 (bot.left/middle/top rt.) =    1.801e-11     7.177e-09     8.588e-12
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 438   order = 5   stepsize = 8.51e+02
-c1 (bot.left/middle/top rt.) =   -4.172e-14    -6.618e-11     6.513e-13
+t = 6.48e+04   no. steps = 449   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =   -2.845e-14    -1.063e-11    -1.382e-14
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 447   order = 5   stepsize = 8.51e+02
-c1 (bot.left/middle/top rt.) =   -7.090e-20     2.812e-17     1.620e-21
+t = 7.20e+04   no. steps = 461   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =    2.710e-16     1.011e-13     1.307e-16
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 455   order = 5   stepsize = 8.51e+02
-c1 (bot.left/middle/top rt.) =   -7.186e-20    -1.098e-16    -7.199e-22
-c2 (bot.left/middle/top rt.) =    3.334e+11     6.670e+11     4.120e+11
+t = 7.92e+04   no. steps = 473   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =    5.698e-16     2.058e-13     2.690e-16
+c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 464   order = 5   stepsize = 8.51e+02
-c1 (bot.left/middle/top rt.) =   -5.534e-20     1.005e-16     1.567e-21
-c2 (bot.left/middle/top rt.) =    3.352e+11     9.106e+11     4.162e+11
+t = 8.64e+04   no. steps = 485   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =    2.707e-16     1.899e-17     2.156e-15
+c2 (bot.left/middle/top rt.) =    3.352e+11     9.106e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2089     leniw   =    50
-lenrwls =  2046     leniwls =    10
-lenrwbp =  2400     leniwbp =   200
-nst     =   464
-nfe     =   618     nfetot  =  1197
-nfeLS   =   539     nfeBP   =    40
-nni     =   614     nli     =   539
-nsetups =    90     netf    =    34
-npe     =     8     nps     =  1077
+lenrwls =  2450     leniwls =    22
+lenrwbp =  2800     leniwbp =   622
+nst     =   485
+nfe     =   617     nfetot  =  1259
+nfeLS   =   597     nfeBP   =    45
+nni     =   613     nli     =   597
+nsetups =    85     netf    =    28
+npe     =     9     nps     =  1134
 ncfn    =     0     ncfl    =     0
 
 
@@ -86,53 +86,53 @@ t = 2.16e+04   no. steps = 279   order = 5   stepsize = 3.58e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 301   order = 5   stepsize = 2.33e+02
+t = 2.88e+04   no. steps = 303   order = 5   stepsize = 2.67e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 330   order = 5   stepsize = 9.92e+01
+t = 3.60e+04   no. steps = 329   order = 5   stepsize = 1.16e+02
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 382   order = 4   stepsize = 4.44e+02
-c1 (bot.left/middle/top rt.) =   -8.802e-11    -3.760e-09    -4.964e-11
+t = 4.32e+04   no. steps = 381   order = 4   stepsize = 4.67e+02
+c1 (bot.left/middle/top rt.) =    8.674e-09     7.020e-09     9.676e-09
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 403   order = 5   stepsize = 2.59e+02
-c1 (bot.left/middle/top rt.) =    7.139e-09    -2.417e-05     1.332e-07
+t = 5.04e+04   no. steps = 398   order = 4   stepsize = 3.23e+02
+c1 (bot.left/middle/top rt.) =    3.531e-15    -4.895e-12    -1.356e-13
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 418   order = 5   stepsize = 4.03e+02
-c1 (bot.left/middle/top rt.) =    2.831e-11     9.701e-10     2.116e-11
+t = 5.76e+04   no. steps = 411   order = 5   stepsize = 4.75e+02
+c1 (bot.left/middle/top rt.) =    1.279e-13    -4.506e-11    -1.318e-12
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 430   order = 5   stepsize = 6.39e+02
-c1 (bot.left/middle/top rt.) =   -2.128e-19    -7.024e-17     3.263e-16
+t = 6.48e+04   no. steps = 423   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =   -1.113e-17     6.813e-16     1.742e-17
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 442   order = 5   stepsize = 6.39e+02
-c1 (bot.left/middle/top rt.) =    1.300e-20    -4.501e-19    -8.828e-17
+t = 7.20e+04   no. steps = 433   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =   -1.369e-20     3.565e-21    -5.202e-25
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 453   order = 5   stepsize = 6.39e+02
-c1 (bot.left/middle/top rt.) =   -6.029e-20    -4.677e-18     3.192e-16
+t = 7.92e+04   no. steps = 443   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =    1.471e-20    -1.150e-20    -1.118e-25
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 464   order = 5   stepsize = 6.39e+02
-c1 (bot.left/middle/top rt.) =    4.164e-20     4.512e-18     7.737e-16
-c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
+t = 8.64e+04   no. steps = 452   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =    1.949e-20    -1.947e-21     1.946e-25
+c2 (bot.left/middle/top rt.) =    3.352e+11     9.106e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2089     leniw   =    50
-lenrwls =  2046     leniwls =    10
-lenrwbp =  2400     leniwbp =   200
-nst     =   464
-nfe     =   582     nfetot  =  1277
-nfeLS   =   655     nfeBP   =    40
-nni     =   578     nli     =   655
-nsetups =    78     netf    =    23
-npe     =     8     nps     =  1140
+lenrwls =  2450     leniwls =    22
+lenrwbp =  2800     leniwbp =   622
+nst     =   452
+nfe     =   571     nfetot  =  1336
+nfeLS   =   725     nfeBP   =    40
+nni     =   567     nli     =   725
+nsetups =    74     netf    =    23
+npe     =     8     nps     =  1199
 ncfn    =     0     ncfl    =     0
 
diff --git a/examples/cvode/serial/cvKrylovDemo_ls.c b/examples/cvode/serial/cvKrylovDemo_ls.c
index c1a99ed..cf8690d 100644
--- a/examples/cvode/serial/cvKrylovDemo_ls.c
+++ b/examples/cvode/serial/cvKrylovDemo_ls.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4848 $
- * $Date: 2016-08-03 15:51:16 -0700 (Wed, 03 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  *
@@ -27,26 +23,26 @@
  * The PDE system is treated by central differences on a uniform
  * 10 x 10 mesh, with simple polynomial initial profiles.
  * The problem is solved with CVODE, with the BDF/GMRES,
- * BDF/Bi-CGStab, and BDF/TFQMR methods (i.e. using the CVSPGMR,
- * CVSPBCG and CVSPTFQMR linear solvers) and the block-diagonal
+ * BDF/Bi-CGStab, and BDF/TFQMR methods (i.e. using the SUNSPGMR,
+ * SUNSPBCGS and SUNSPTFQMR linear solvers) and the block-diagonal
  * part of the Newton matrix as a left preconditioner. A copy of
  * the block-diagonal part of the Jacobian is saved and
  * conditionally reused within the Precond routine.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>             /* main integrator header file */
-#include <cvode/cvode_spgmr.h>       /* prototypes & constants for CVSPGMR solver */
-#include <cvode/cvode_spbcgs.h>      /* prototypes & constants for CVSPBCG solver */
-#include <cvode/cvode_sptfqmr.h>     /* prototypes & constants for CVSPTFQMR solver */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_dense.h> /* use generic DENSE solver in preconditioning */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS, SUNSQR, and EXP */
+#include <cvode/cvode.h>                 /* main integrator header file       */
+#include <cvode/cvode_spils.h>           /* access to CVSpils interface       */
+#include <sunlinsol/sunlinsol_spgmr.h>   /* access to SPGMR SUNLinearSolver   */
+#include <sunlinsol/sunlinsol_spbcgs.h>  /* access to SPBCGS SUNLinearSolver  */
+#include <sunlinsol/sunlinsol_sptfqmr.h> /* access to SPTFQMR SUNLinearSolver */
+#include <nvector/nvector_serial.h>      /* serial N_Vector types, fct. and macros */
+#include <sundials/sundials_dense.h>     /* use generic DENSE solver in preconditioning */
+#include <sundials/sundials_types.h>     /* definition of realtype */
+#include <sundials/sundials_math.h>      /* contains the macros ABS, SUNSQR, and EXP */
 
 /* Problem Constants */
 
@@ -109,7 +105,7 @@
    IJKth(vdata,i,j,k) references the element in the vdata array for
    species i at mesh point (j,k), where 1 <= i <= NUM_SPECIES,
    0 <= j <= MX-1, 0 <= k <= MY-1. The vdata array is obtained via
-   the macro call vdata = N_VGetArrayPointer_Serial(v), where v is an N_Vector. 
+   the call vdata = N_VGetArrayPointer(v), where v is an N_Vector. 
    For each mesh point (j,k), the elements for species i and i+1 are
    contiguous within vdata.
 
@@ -126,7 +122,7 @@
 
 typedef struct {
   realtype **P[MX][MY], **Jbd[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   realtype q4, om, dx, dy, hdco, haco, vdco;
 } *UserData;
 
@@ -144,15 +140,13 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
-static int Precond(realtype tn, N_Vector u, N_Vector fu,
-                   booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3);
+static int Precond(realtype tn, N_Vector u, N_Vector fu, booleantype jok,
+                   booleantype *jcurPtr, realtype gamma, void *user_data);
 
 static int PSolve(realtype tn, N_Vector u, N_Vector fu,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 
 /*
@@ -166,11 +160,13 @@ int main(void)
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int linsolver, iout, flag;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
@@ -230,10 +226,13 @@ int main(void)
       printf(" \n| SPGMR |\n");
       printf(" -------\n");
 
-      /* Call CVSpgmr to specify the linear solver CVSPGMR 
-	 with left preconditioning and the maximum Krylov dimension maxl */
-      flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-      if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+      /* Call SUNSPGMR to specify the linear solver SPGMR with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPGMR(u, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+      flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+      if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -242,13 +241,16 @@ int main(void)
 
       /* Print header */
       printf(" -------");
-      printf(" \n| SPBCG |\n");
+      printf(" \n| SPBCGS |\n");
       printf(" -------\n");
 
-      /* Call CVSpbcg to specify the linear solver CVSPBCG 
-	 with left preconditioning and the maximum Krylov dimension maxl */
-      flag = CVSpbcg(cvode_mem, PREC_LEFT, 0);
-      if(check_flag(&flag, "CVSpbcg", 1)) return(1);
+      /* Call SUNSPBCGS to specify the linear solver SPBCGS with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPBCGS(u, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPBCGS", 0)) return(1);
+
+      flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+      if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -260,10 +262,13 @@ int main(void)
       printf(" \n| SPTFQMR |\n");
       printf(" ---------\n");
 
-      /* Call CVSptfqmr to specify the linear solver CVSPTFQMR 
-	 with left preconditioning and the maximum Krylov dimension maxl */
-      flag = CVSptfqmr(cvode_mem, PREC_LEFT, 0);
-      if(check_flag(&flag, "CVSptfqmr", 1)) return(1);
+      /* Call SUNSPTFQMR to specify the linear solver SPTFQMR with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPTFQMR(u, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPTFQMR", 0)) return(1);
+
+      flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+      if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -288,9 +293,10 @@ int main(void)
   }  /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
 
   /* Free memory */
-  N_VDestroy_Serial(u);
+  N_VDestroy(u);
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   return(0);
 }
@@ -314,7 +320,7 @@ static UserData AllocUserData(void)
     for (jy=0; jy < MY; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
       (data->Jbd)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
 
@@ -360,7 +366,7 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profiles of c1 and c2 into u vector */
 
@@ -387,7 +393,7 @@ static void PrintOutput(void *cvode_mem, N_Vector u, realtype t)
   realtype hu, *udata;
   int mxh = MX/2 - 1, myh = MY/2 - 1, mx1 = MX - 1, my1 = MY - 1;
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -459,9 +465,9 @@ static void PrintFinalStats(void *cvode_mem, int linsolver)
   check_flag(&flag, "CVSpilsGetNumRhsEvals", 1);
 
   printf("\nFinal Statistics.. \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwLS = %5ld     leniwLS = %5ld\n", lenrwLS, leniwLS);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwLS = %5ld     leniwLS = %5ld\n"  , lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfeLS   = %5ld\n"  , nfe, nfeLS);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
   printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
@@ -525,9 +531,9 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   int jx, jy, idn, iup, ileft, iright;
   UserData data;
 
-  data = (UserData) user_data;
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  data   = (UserData) user_data;
+  udata  = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Set diurnal rate coefficients. */
 
@@ -607,14 +613,12 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 
 /* Preconditioner setup routine. Generate and preprocess P. */
 
-static int Precond(realtype tn, N_Vector u, N_Vector fu,
-                   booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3)
+static int Precond(realtype tn, N_Vector u, N_Vector fu, booleantype jok,
+                   booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MY], **(*Jbd)[MY];
-  long int *(*pivot)[MY], ier;
+  sunindextype *(*pivot)[MY], ier;
   int jx, jy;
   realtype *udata, **a, **j;
   UserData data;
@@ -625,22 +629,22 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
   P = data->P;
   Jbd = data->Jbd;
   pivot = data->pivot;
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
   
   if (jok) {
     
-    /* jok = TRUE: Copy Jbd to P */
+    /* jok = SUNTRUE: Copy Jbd to P */
     
     for (jy=0; jy < MY; jy++)
       for (jx=0; jx < MX; jx++)
         denseCopy(Jbd[jx][jy], P[jx][jy], NUM_SPECIES, NUM_SPECIES);
     
-    *jcurPtr = FALSE;
+    *jcurPtr = SUNFALSE;
     
   }
   
   else {
-    /* jok = FALSE: Generate Jbd from scratch and copy to P */
+    /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
     
     /* Make local copies of problem variables, for efficiency. */
     
@@ -671,7 +675,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
     
-    *jcurPtr = TRUE;
+    *jcurPtr = SUNTRUE;
     
   }
   
@@ -699,10 +703,10 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 static int PSolve(realtype tn, N_Vector u, N_Vector fu,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype **(*P)[MY];
-  long int *(*pivot)[MY];
+  sunindextype *(*pivot)[MY];
   int jx, jy;
   realtype *zdata, *v;
   UserData data;
@@ -712,7 +716,7 @@ static int PSolve(realtype tn, N_Vector u, N_Vector fu,
   data = (UserData) user_data;
   P = data->P;
   pivot = data->pivot;
-  zdata = N_VGetArrayPointer_Serial(z);
+  zdata = N_VGetArrayPointer(z);
   
   N_VScale(ONE, r, z);
   
diff --git a/examples/cvode/serial/cvKrylovDemo_ls.out b/examples/cvode/serial/cvKrylovDemo_ls.out
index 54b2bf2..666c5dd 100644
--- a/examples/cvode/serial/cvKrylovDemo_ls.out
+++ b/examples/cvode/serial/cvKrylovDemo_ls.out
@@ -16,58 +16,58 @@ t = 2.16e+04   no. steps = 277   order = 5   stepsize = 2.75e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 301   order = 5   stepsize = 3.87e+02
+t = 2.88e+04   no. steps = 307   order = 4   stepsize = 2.01e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 343   order = 3   stepsize = 2.34e+01
+t = 3.60e+04   no. steps = 336   order = 5   stepsize = 1.02e+02
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 421   order = 4   stepsize = 5.26e+02
-c1 (bot.left/middle/top rt.) =   -4.385e-06    -1.528e-06    -4.905e-06
+t = 4.32e+04   no. steps = 385   order = 4   stepsize = 4.57e+02
+c1 (bot.left/middle/top rt.) =    5.226e-08    -6.075e-06     8.713e-08
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 445   order = 3   stepsize = 1.98e+02
-c1 (bot.left/middle/top rt.) =    4.461e-07     1.869e-07     4.842e-07
+t = 5.04e+04   no. steps = 403   order = 4   stepsize = 2.77e+02
+c1 (bot.left/middle/top rt.) =   -2.670e-08    -4.510e-06    -2.672e-08
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 462   order = 5   stepsize = 2.35e+02
-c1 (bot.left/middle/top rt.) =    3.204e-09     1.203e-09     3.555e-09
+t = 5.76e+04   no. steps = 419   order = 5   stepsize = 3.44e+02
+c1 (bot.left/middle/top rt.) =   -1.147e-09    -5.871e-08    -2.195e-09
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 474   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -1.066e-09    -3.409e-10    -1.206e-09
+t = 6.48e+04   no. steps = 431   order = 5   stepsize = 9.50e+02
+c1 (bot.left/middle/top rt.) =    3.792e-10     1.901e-08     7.196e-10
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 486   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    2.614e-09     9.722e-10     2.904e-09
+t = 7.20e+04   no. steps = 441   order = 5   stepsize = 7.01e+02
+c1 (bot.left/middle/top rt.) =   -1.872e-11    -9.361e-10    -3.550e-11
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 498   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    4.649e-11     1.729e-11     5.161e-11
+t = 7.92e+04   no. steps = 451   order = 5   stepsize = 7.01e+02
+c1 (bot.left/middle/top rt.) =    1.365e-13     6.739e-12     2.585e-13
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 510   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -8.856e-14    -3.348e-14    -9.785e-14
+t = 8.64e+04   no. steps = 461   order = 5   stepsize = 7.01e+02
+c1 (bot.left/middle/top rt.) =    4.144e-14     2.072e-12     7.862e-14
 c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2089     leniw   =    50
-lenrwLS =  2046     leniwLS =    10
-nst     =   510
-nfe     =   675     nfeLS   =   641
-nni     =   671     nli     =   641
-nsetups =    94     netf    =    36
-npe     =     9     nps     =  1243
+lenrwLS =  2450     leniwLS =    22
+nst     =   461
+nfe     =   598     nfeLS   =   636
+nni     =   594     nli     =   636
+nsetups =    78     netf    =    27
+npe     =     8     nps     =  1176
 ncfn    =     0     ncfl    =     0
 
 ======================================================================
 
  ------- 
-| SPBCG |
+| SPBCGS |
  -------
  
 2-species diurnal advection-diffusion problem
@@ -93,43 +93,43 @@ c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
 t = 4.32e+04   no. steps = 369   order = 4   stepsize = 5.46e+02
-c1 (bot.left/middle/top rt.) =   -1.286e-09    -1.138e-09    -1.297e-09
+c1 (bot.left/middle/top rt.) =   -6.042e-10    -6.057e-10    -5.365e-10
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 385   order = 4   stepsize = 3.54e+02
-c1 (bot.left/middle/top rt.) =    3.396e-14     2.448e-11    -2.220e-14
+t = 5.04e+04   no. steps = 385   order = 4   stepsize = 3.19e+02
+c1 (bot.left/middle/top rt.) =   -1.354e-14     1.127e-12    -4.255e-14
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 399   order = 5   stepsize = 3.72e+02
-c1 (bot.left/middle/top rt.) =    1.607e-14    -1.589e-11     2.156e-13
+t = 5.76e+04   no. steps = 399   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =    3.722e-14     6.444e-12     2.768e-14
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 410   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =   -3.759e-13    -7.684e-12    -3.258e-13
+t = 6.48e+04   no. steps = 411   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -3.190e-14     3.974e-12    -1.259e-13
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 421   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =   -9.205e-14    -1.287e-11     2.328e-13
+t = 7.20e+04   no. steps = 423   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -4.212e-15    -1.602e-13     1.053e-15
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 433   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =   -3.952e-21     9.479e-19    -3.924e-20
+t = 7.92e+04   no. steps = 435   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -3.763e-23    -1.366e-21     1.010e-23
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 444   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =    1.131e-26    -2.041e-22    -7.893e-29
+t = 8.64e+04   no. steps = 447   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -9.994e-27    -1.865e-22    -1.580e-27
 c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2089     leniw   =    50
-lenrwLS =  1800     leniwLS =     9
-nst     =   444
-nfe     =   573     nfeLS   =   968
-nni     =   569     nli     =   484
-nsetups =    76     netf    =    27
-npe     =     8     nps     =  1457
+lenrwLS =  2204     leniwLS =    21
+nst     =   447
+nfe     =   570     nfeLS   =   964
+nni     =   566     nli     =   482
+nsetups =    72     netf    =    25
+npe     =     8     nps     =  1453
 ncfn    =     0     ncfl    =     0
 
 ======================================================================
@@ -148,55 +148,55 @@ t = 1.44e+04   no. steps = 250   order = 5   stepsize = 3.27e+02
 c1 (bot.left/middle/top rt.) =    6.659e+06     5.316e+06     7.301e+06
 c2 (bot.left/middle/top rt.) =    2.582e+11     2.057e+11     2.833e+11
 
-t = 2.16e+04   no. steps = 275   order = 5   stepsize = 3.49e+02
+t = 2.16e+04   no. steps = 275   order = 5   stepsize = 3.50e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 309   order = 4   stepsize = 1.92e+02
+t = 2.88e+04   no. steps = 298   order = 5   stepsize = 2.18e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 337   order = 5   stepsize = 1.24e+02
+t = 3.60e+04   no. steps = 326   order = 5   stepsize = 1.31e+02
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 388   order = 4   stepsize = 5.10e+02
-c1 (bot.left/middle/top rt.) =    9.865e-08     1.252e-05     1.407e-07
+t = 4.32e+04   no. steps = 377   order = 4   stepsize = 3.89e+02
+c1 (bot.left/middle/top rt.) =    5.444e-07    -1.657e-06     6.244e-07
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 405   order = 4   stepsize = 2.84e+02
-c1 (bot.left/middle/top rt.) =   -1.668e-09     5.311e-07    -6.632e-09
+t = 5.04e+04   no. steps = 391   order = 5   stepsize = 6.79e+02
+c1 (bot.left/middle/top rt.) =   -1.730e-09    -6.249e-07    -9.039e-10
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 419   order = 5   stepsize = 5.07e+02
-c1 (bot.left/middle/top rt.) =   -1.792e-09     6.186e-07    -7.318e-09
+t = 5.76e+04   no. steps = 403   order = 5   stepsize = 4.21e+02
+c1 (bot.left/middle/top rt.) =    7.982e-10     2.122e-07    -1.172e-09
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 431   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =    1.682e-11    -9.299e-09     8.107e-11
+t = 6.48e+04   no. steps = 414   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =    1.420e-09     3.489e-07    -2.356e-09
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 441   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =    1.919e-15    -3.196e-13     6.625e-15
+t = 7.20e+04   no. steps = 424   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =    1.045e-12     2.583e-10    -1.763e-12
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 450   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =    2.380e-19    -4.543e-16     1.071e-18
+t = 7.92e+04   no. steps = 435   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =   -2.523e-19     5.442e-16     4.663e-19
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 459   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =   -8.763e-21     5.632e-16    -4.431e-21
-c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
+t = 8.64e+04   no. steps = 445   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =   -1.673e-20    -1.128e-15    -3.081e-21
+c2 (bot.left/middle/top rt.) =    3.352e+11     9.106e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2089     leniw   =    50
-lenrwLS =  2200     leniwLS =    11
-nst     =   459
-nfe     =   582     nfeLS   =  1248
-nni     =   578     nli     =   520
-nsetups =    71     netf    =    23
-npe     =     8     nps     =  1910
+lenrwLS =  2604     leniwLS =    23
+nst     =   445
+nfe     =   559     nfeLS   =  1143
+nni     =   555     nli     =   477
+nsetups =    67     netf    =    21
+npe     =     8     nps     =  1805
 ncfn    =     0     ncfl    =     0
 
diff --git a/examples/cvode/serial/cvKrylovDemo_prec.c b/examples/cvode/serial/cvKrylovDemo_prec.c
index aaa7976..97082f5 100644
--- a/examples/cvode/serial/cvKrylovDemo_prec.c
+++ b/examples/cvode/serial/cvKrylovDemo_prec.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
+/* --------------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * --------------------------------------------------------------------
@@ -49,7 +45,7 @@
  *
  * The resulting ODE system is stiff.
  *
- * The ODE system is solved using Newton iteration and the CVSPGMR
+ * The ODE system is solved using Newton iteration and the SUNSPGMR
  * linear solver (scaled preconditioned GMRES).
  *
  * The preconditioner matrix used is the product of two matrices:
@@ -63,9 +59,10 @@
  * The product preconditoner is applied on the left and on the
  * right. In each case, both the modified and classical Gram-Schmidt
  * options are tested.
- * In the series of runs, CVodeInit and CVSpgmr are called only
- * for the first run, whereas CVodeReInit and CVReInitSpgmr are
- * called for each of the remaining three runs.
+ * In the series of runs, CVodeInit, SUNSPGMR, and 
+ * CVDlsSetLinearSolver are called only for the first run, whereas 
+ * CVodeReInit, SUNSPGMRSetPrecType, and SUNSPGMRSetGSType are called
+ * for each of the remaining three runs.
  *
  * A problem description, performance statistics at selected output
  * times, and final statistics are written to standard output.
@@ -74,30 +71,30 @@
  * but there should be no such messages.
  *
  * Note: This program requires the dense linear solver functions
- * newDenseMat, newLintArray, denseAddIdentity, denseGETRF, denseGETRS, 
+ * newDenseMat, newIndexArray, denseAddIdentity, denseGETRF, denseGETRS, 
  * destroyMat and destroyArray.
  *
  * Note: This program assumes the sequential implementation for the
- * type N_Vector and uses the N_VGetArrayPointer_Serial function to 
- * gain access to the contiguous array of components of an N_Vector.
+ * type N_Vector and uses the N_VGetArrayPointer function to gain
+ * access to the contiguous array of components of an N_Vector.
  * --------------------------------------------------------------------
  * Reference: Peter N. Brown and Alan C. Hindmarsh, Reduced Storage
  * Matrix Methods in Stiff ODE Systems, J. Appl. Math. & Comp., 31
  * (1989), pp. 40-91.  Also available as Lawrence Livermore National
  * Laboratory Report UCRL-95088, Rev. 1, June 1987.
- * --------------------------------------------------------------------
- */
+ * --------------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvode/cvode.h>             /* main integrator header file */
-#include <cvode/cvode_spgmr.h>       /* prototypes & constants for CVSPGMR solver */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_dense.h> /* use generic DENSE solver in preconditioning */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS and SUNSQR */
+#include <cvode/cvode.h>                /* main integrator header file                 */
+#include <sunlinsol/sunlinsol_spgmr.h>  /* access to SPGMR SUNLinearSolver             */
+#include <cvode/cvode_spils.h>          /* access to CVSpils interface                 */
+#include <nvector/nvector_serial.h>     /* serial N_Vector types, fct. and macros      */
+#include <sundials/sundials_dense.h>    /* use generic DENSE solver in preconditioning */
+#include <sundials/sundials_types.h>    /* definition of realtype                      */
+#include <sundials/sundials_math.h>     /* contains the macros ABS and SUNSQR          */
 
 /* Constants */
 
@@ -140,7 +137,7 @@
 #define RTOL RCONST(1.0e-5)
 #define ATOL RCONST(1.0e-5)
 
-/* CVSpgmr Constants */
+/* Spgmr/SPILS Constants */
 
 #define MAXL 0     /* => use default = MIN(NEQ, 5)            */
 #define DELT ZERO  /* => use default = 0.05                   */
@@ -160,7 +157,7 @@
 
 typedef struct {
   realtype **P[NGRP];
-  long int *pivot[NGRP];
+  sunindextype *pivot[NGRP];
   int ns, mxns;
   int mp, mq, mx, my, ngrp, ngx, ngy, mxmp;
   int jgx[NGX+1], jgy[NGY+1], jigx[MX], jigy[MY];
@@ -168,6 +165,7 @@ typedef struct {
   realtype acoef[NS][NS], bcoef[NS], diff[NS];
   realtype cox[NS], coy[NS], dx, dy, srur;
   realtype fsave[NEQ];
+  N_Vector tmp;
   N_Vector rewt;
   void *cvode_mem;
 } *WebData;
@@ -188,7 +186,7 @@ static void WebRates(realtype x, realtype y, realtype t, realtype c[],
 		     realtype rate[], WebData wdata);
 static void fblock (realtype t, realtype cdata[], int jx, int jy,
 		    realtype cdotdata[], WebData wdata);
-static void GSIter(realtype gamma, N_Vector z, N_Vector x,WebData wdata);
+static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata);
 
 /* Small Vector Kernels */
 
@@ -202,15 +200,11 @@ static void v_zero(realtype u[], int n);
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
-static int Precond(realtype tn, N_Vector c, N_Vector fc,
-		   booleantype jok, booleantype *jcurPtr, realtype gamma,
-		   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3);
+static int Precond(realtype tn, N_Vector c, N_Vector fc, booleantype jok, 
+                   booleantype *jcurPtr, realtype gamma, void *user_data);
 
-static int PSolve(realtype tn, N_Vector c, N_Vector fc,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+static int PSolve(realtype tn, N_Vector c, N_Vector fc, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data);
 
 /* Private function to check function return values */
 
@@ -223,6 +217,7 @@ int main()
   realtype abstol=ATOL, reltol=RTOL, t, tout;
   N_Vector c;
   WebData wdata;
+  SUNLinearSolver LS;
   void *cvode_mem;
   booleantype firstrun;
   int jpre, gstype, flag;
@@ -230,6 +225,7 @@ int main()
 
   c = NULL;
   wdata = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Initializations */
@@ -252,7 +248,7 @@ int main()
       CInit(c, wdata);
       PrintHeader(jpre, gstype);
 
-      /* Call CVodeInit or CVodeReInit, then CVSpgmr to set up problem */
+      /* Call CVodeInit or CVodeReInit, then SUNSPGMR to set up problem */
       
       firstrun = (jpre == PREC_LEFT) && (gstype == MODIFIED_GS);
       if (firstrun) {
@@ -268,13 +264,16 @@ int main()
         if(check_flag(&flag, "CVodeInit", 1)) return(1);
 
         flag = CVodeSStolerances(cvode_mem, reltol, abstol);
-        if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+        if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+        LS = SUNSPGMR(c, jpre, MAXL);
+        if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
 
-        flag = CVSpgmr(cvode_mem, jpre, MAXL);
-        if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+        flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+        if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
-        flag = CVSpilsSetGSType(cvode_mem, gstype);
-        if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+        flag = SUNSPGMRSetGSType(LS, gstype);
+        if(check_flag(&flag, "SUNSPGMRSetGSType", 1)) return(1);
 
         flag = CVSpilsSetEpsLin(cvode_mem, DELT);
         if(check_flag(&flag, "CVSpilsSetEpsLin", 1)) return(1);
@@ -287,10 +286,10 @@ int main()
         flag = CVodeReInit(cvode_mem, T0, c);
         if(check_flag(&flag, "CVodeReInit", 1)) return(1);
 
-        flag = CVSpilsSetPrecType(cvode_mem, jpre);
-        check_flag(&flag, "CVSpilsSetPrecType", 1);
-        flag = CVSpilsSetGSType(cvode_mem, gstype);
-        if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+        flag = SUNSPGMRSetPrecType(LS, jpre);
+        check_flag(&flag, "SUNSPGMRSetPrecType", 1);
+        flag = SUNSPGMRSetGSType(LS, gstype);
+        if(check_flag(&flag, "SUNSPGMRSetGSType", 1)) return(1);
 
       }
       
@@ -315,7 +314,8 @@ int main()
 
   /* Free all memory */
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(c);
+  N_VDestroy(c);
+  SUNLinSolFree(LS);
   FreeUserData(wdata);
 
   return(0);
@@ -324,15 +324,16 @@ int main()
 static WebData AllocUserData(void)
 {
   int i, ngrp = NGRP;
-  long int ns = NS;
+  sunindextype ns = NS;
   WebData wdata;
   
   wdata = (WebData) malloc(sizeof *wdata);
   for(i=0; i < ngrp; i++) {
     (wdata->P)[i] = newDenseMat(ns, ns);
-    (wdata->pivot)[i] = newLintArray(ns);
+    (wdata->pivot)[i] = newIndexArray(ns);
   }
   wdata->rewt = N_VNew_Serial(NEQ);
+  wdata->tmp = N_VNew_Serial(NEQ);
   return(wdata);
 }
 
@@ -422,7 +423,7 @@ static void CInit(N_Vector c, WebData wdata)
   int jx, jy, ns, mxns, ioff, iyoff, i, ici;
   realtype argx, argy, x, y, dx, dy, x_factor, y_factor, *cdata;
   
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
   ns = wdata->ns;
   mxns = wdata->mxns;
   dx = wdata->dx;
@@ -448,7 +449,7 @@ static void CInit(N_Vector c, WebData wdata)
 
 static void PrintIntro(void)
 {
-  printf("\n\nDemonstration program for CVODE - CVSPGMR linear solver\n\n");
+  printf("\n\nDemonstration program for CVODE - SPGMR linear solver\n\n");
   printf("Food web problem with ns species, ns = %d\n", NS);
   printf("Predator-prey interaction and diffusion on a 2-D square\n\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -514,7 +515,7 @@ static void PrintAllSpecies(N_Vector c, int ns, int mxns, realtype t)
   int i, jx ,jy;
   realtype *cdata;
   
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("c values at t = %Lg:\n\n", t);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
@@ -609,8 +610,8 @@ static void PrintFinalStats(void *cvode_mem)
   printf("\n\n Final statistics for this run:\n\n");
   printf(" CVode real workspace length           = %4ld \n", lenrw);
   printf(" CVode integer workspace length        = %4ld \n", leniw);
-  printf(" CVSPGMR real workspace length         = %4ld \n", lenrwLS);
-  printf(" CVSPGMR integer workspace length      = %4ld \n", leniwLS);
+  printf(" CVSPILS real workspace length         = %4ld \n", lenrwLS);
+  printf(" CVSPILS integer workspace length      = %4ld \n", leniwLS);
   printf(" Number of steps                       = %4ld \n", nst);
   printf(" Number of f-s                         = %4ld \n", nfe);
   printf(" Number of f-s (SPGMR)                 = %4ld \n", nfeLS);
@@ -644,7 +645,7 @@ static void FreeUserData(WebData wdata)
     destroyMat((wdata->P)[i]);
     destroyArray((wdata->pivot)[i]);
   }
-  N_VDestroy_Serial(wdata->rewt);
+  N_VDestroy(wdata->rewt);
   free(wdata);
 }
 
@@ -661,8 +662,8 @@ static int f(realtype t, N_Vector c, N_Vector cdot,void *user_data)
   WebData wdata;
   
   wdata = (WebData) user_data;
-  cdata = N_VGetArrayPointer_Serial(c);
-  cdotdata = N_VGetArrayPointer_Serial(cdot);
+  cdata = N_VGetArrayPointer(c);
+  cdotdata = N_VGetArrayPointer(cdot);
   
   mxns = wdata->mxns;
   ns = wdata->ns;
@@ -744,17 +745,15 @@ static void WebRates(realtype x, realtype y, realtype t, realtype c[],
  of a block-diagonal preconditioner. The blocks are of size mp, and
  there are ngrp=ngx*ngy blocks computed in the block-grouping scheme.
 */ 
-static int Precond(realtype t, N_Vector c, N_Vector fc,
-		   booleantype jok, booleantype *jcurPtr, realtype gamma,
-		   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3)
+static int Precond(realtype t, N_Vector c, N_Vector fc, booleantype jok,
+                   booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   realtype ***P;
   int ier;
-  long int **pivot;
+  sunindextype **pivot;
   int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
   int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
-  long int mp;
+  sunindextype mp;
   realtype uround, fac, r, r0, save, srur;
   realtype *f1, *fsave, *cdata, *rewtdata;
   WebData wdata;
@@ -763,11 +762,11 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
   
   wdata = (WebData) user_data;
   cvode_mem = wdata->cvode_mem;
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
   rewt = wdata->rewt;
   flag = CVodeGetErrWeights(cvode_mem, rewt);
   if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
-  rewtdata = N_VGetArrayPointer_Serial(rewt);
+  rewtdata = N_VGetArrayPointer(rewt);
 
   uround = UNIT_ROUNDOFF;
 
@@ -787,7 +786,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
      Here, fsave contains the base value of the rate vector and 
      r0 is a minimum increment factor for the difference quotient. */
   
-  f1 = N_VGetArrayPointer_Serial(vtemp1);
+  f1 = N_VGetArrayPointer(wdata->tmp);
   
   fac = N_VWrmsNorm (fc, rewt);
   r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*NEQ*fac;
@@ -825,7 +824,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
     if (ier != 0) return(1);
   }
   
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
   return(0);
 }
 
@@ -857,15 +856,13 @@ static void fblock(realtype t, realtype cdata[], int jx, int jy,
   Then it computes ((I - gamma*Jr)-inverse)*z, using LU factors of the
   blocks in P, and pivot information in pivot, and returns the result in z.
 */
-static int PSolve(realtype tn, N_Vector c, N_Vector fc,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+static int PSolve(realtype tn, N_Vector c, N_Vector fc, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data)
 {
   realtype   ***P;
-  long int **pivot;
+  sunindextype **pivot;
   int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
-  long int mp;
+  sunindextype mp;
   WebData wdata;
   
   wdata = (WebData) user_data;
@@ -874,7 +871,7 @@ static int PSolve(realtype tn, N_Vector c, N_Vector fc,
   
   /* call GSIter for Gauss-Seidel iterations */
   
-  GSIter(gamma, z, vtemp, wdata);
+  GSIter(gamma, z, wdata->tmp, wdata);
   
   /* Do backsolves for inverse of block-diagonal preconditioner factor */
   
@@ -893,7 +890,7 @@ static int PSolve(realtype tn, N_Vector c, N_Vector fc,
     for (jx = 0; jx < mx; jx++) {
       igx = jigx[jx];
       ig = igx + igy*ngx;
-      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer_Serial(z)[iv]));
+      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer(z)[iv]));
       iv += mp;
     }
   }
@@ -917,8 +914,8 @@ static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata)
   realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
   realtype temp, *cox, *coy, *xd, *zd;
   
-  xd = N_VGetArrayPointer_Serial(x);
-  zd = N_VGetArrayPointer_Serial(z);
+  xd = N_VGetArrayPointer(x);
+  zd = N_VGetArrayPointer(z);
   ns = wdata->ns;
   mx = wdata->mx;
   my = wdata->my;
diff --git a/examples/cvode/serial/cvKrylovDemo_prec.out b/examples/cvode/serial/cvKrylovDemo_prec.out
index 66c5396..42d668c 100644
--- a/examples/cvode/serial/cvKrylovDemo_prec.out
+++ b/examples/cvode/serial/cvKrylovDemo_prec.out
@@ -1,6 +1,6 @@
 
 
-Demonstration program for CVODE - CVSPGMR linear solver
+Demonstration program for CVODE - SPGMR linear solver
 
 Food web problem with ns species, ns = 6
 Predator-prey interaction and diffusion on a 2-D square
@@ -12,7 +12,7 @@ Rate parameter alpha = 1
 
 Mesh dimensions (mx,my) are 6, 6.  Total system size is neq = 216 
 
-Tolerances: itol = CV_SS,  reltol = 1e-05, abstol = 1e-05 
+Tolerances: reltol = 1e-05, abstol = 1e-05 
 
 Preconditioning uses a product of:
   (1) Gauss-Seidel iterations with itmax = 5 iterations, and
@@ -248,9 +248,9 @@ Species 6
 
 t =   2.00e+00  nst = 272  nfe = 305  nni = 301  qu = 3  hu =    3.81e-02
 
-t =   3.00e+00  nst = 288  nfe = 322  nni = 318  qu = 3  hu =    6.58e-02
+t =   3.00e+00  nst = 288  nfe = 322  nni = 318  qu = 3  hu =    6.59e-02
 
-t =   4.00e+00  nst = 303  nfe = 338  nni = 334  qu = 3  hu =    6.58e-02
+t =   4.00e+00  nst = 303  nfe = 337  nni = 333  qu = 3  hu =    6.59e-02
 
 c values at t = 4:
 
@@ -260,7 +260,7 @@ Species 1
 1.18657   1.19274   1.20603   1.22174   1.23523   1.24158   
 1.17905   1.18368   1.1939    1.20603   1.21636   1.2211    
 1.17285   1.17613   1.18368   1.19274   1.20035   1.20368   
-1.17033   1.17285   1.17905   1.18657   1.19281   1.19535   
+1.17032   1.17285   1.17905   1.18657   1.19281   1.19535   
 
 Species 2
 1.19539   1.20372   1.22113   1.24161   1.25939   1.26804   
@@ -279,140 +279,140 @@ Species 3
 1.17039   1.17291   1.17911   1.18664   1.19287   1.19542   
 
 Species 4
-35860.6   36110.4   36632.5   37246.5   37779.6   38038.7   
-35784.4   36010.4   36490.5   37056.4   37545.4   37779.6   
-35597.3   35782.1   36180.7   36651.7   37056.4   37246.5   
-35371.5   35510.5   35816.7   36180.7   36490.5   36632.5   
-35185.6   35283.8   35510.5   35782.1   36010.4   36110.4   
-35109.8   35185.6   35371.5   35597.3   35784.4   35860.6   
+35860.8   36110.3   36632.5   37246.5   37779.6   38038.8   
+35784.3   36010.5   36490.5   37056.4   37545.4   37779.6   
+35597.3   35782.1   36180.6   36651.7   37056.4   37246.5   
+35371.5   35510.5   35816.8   36180.6   36490.5   36632.5   
+35185.5   35283.9   35510.5   35782.1   36010.5   36110.3   
+35109.8   35185.5   35371.5   35597.3   35784.3   35860.8   
 
 Species 5
-35860.7   36110.3   36632.5   37246.5   37779.6   38038.7   
-35784.4   36010.5   36490.5   37056.5   37545.4   37779.6   
-35597.3   35782.1   36180.7   36651.7   37056.5   37246.5   
-35371.5   35510.5   35816.7   36180.7   36490.5   36632.5   
-35185.6   35283.8   35510.5   35782.1   36010.5   36110.3   
-35109.8   35185.6   35371.5   35597.3   35784.4   35860.7   
+35860.8   36110.2   36632.5   37246.5   37779.6   38038.8   
+35784.3   36010.5   36490.5   37056.4   37545.4   37779.6   
+35597.4   35782.1   36180.6   36651.7   37056.4   37246.5   
+35371.5   35510.5   35816.8   36180.6   36490.5   36632.5   
+35185.5   35283.9   35510.5   35782.1   36010.5   36110.2   
+35109.8   35185.5   35371.5   35597.4   35784.3   35860.8   
 
 Species 6
-35860.7   36110.3   36632.6   37246.5   37779.6   38038.7   
-35784.3   36010.5   36490.5   37056.5   37545.4   37779.6   
-35597.4   35782.1   36180.7   36651.6   37056.5   37246.5   
-35371.4   35510.5   35816.7   36180.7   36490.5   36632.6   
-35185.6   35283.8   35510.5   35782.1   36010.5   36110.3   
-35109.8   35185.6   35371.4   35597.4   35784.3   35860.7   
+35860.8   36110.2   36632.5   37246.5   37779.6   38038.8   
+35784.3   36010.5   36490.5   37056.4   37545.4   37779.6   
+35597.4   35782.1   36180.7   36651.6   37056.4   37246.5   
+35371.5   35510.5   35816.8   36180.7   36490.5   36632.5   
+35185.6   35283.8   35510.5   35782.1   36010.5   36110.2   
+35109.8   35185.6   35371.5   35597.4   35784.3   35860.8   
 
-t =   5.00e+00  nst = 316  nfe = 351  nni = 347  qu = 3  hu =    1.10e-01
+t =   5.00e+00  nst = 313  nfe = 349  nni = 345  qu = 3  hu =    1.26e-01
 
-t =   6.00e+00  nst = 325  nfe = 361  nni = 357  qu = 3  hu =    1.10e-01
+t =   6.00e+00  nst = 321  nfe = 357  nni = 353  qu = 3  hu =    1.26e-01
 
-t =   7.00e+00  nst = 334  nfe = 371  nni = 367  qu = 3  hu =    1.10e-01
+t =   7.00e+00  nst = 329  nfe = 366  nni = 362  qu = 3  hu =    1.26e-01
 
 c values at t = 7:
 
 Species 1
 1.18854   1.19682   1.21415   1.23453   1.25221   1.26082   
+1.186     1.19351   1.20944   1.22821   1.24444   1.25221   
+1.1798    1.18593   1.19916   1.21479   1.22821   1.23453   
+1.17231   1.17692   1.18708   1.19916   1.20944   1.21415   
+1.16614   1.1694    1.17692   1.18593   1.19351   1.19682   
+1.16363   1.16614   1.17231   1.1798    1.186     1.18854   
+
+Species 2
+1.18854   1.19682   1.21415   1.23453   1.25221   1.26082   
 1.186     1.19351   1.20944   1.22822   1.24444   1.25221   
 1.1798    1.18593   1.19916   1.21479   1.22822   1.23453   
 1.17231   1.17692   1.18708   1.19916   1.20944   1.21415   
 1.16614   1.1694    1.17692   1.18593   1.19351   1.19682   
 1.16363   1.16614   1.17231   1.1798    1.186     1.18854   
 
-Species 2
+Species 3
 1.18854   1.19683   1.21415   1.23453   1.25222   1.26082   
 1.186     1.19351   1.20944   1.22822   1.24444   1.25222   
-1.1798    1.18594   1.19916   1.21479   1.22822   1.23453   
+1.1798    1.18593   1.19916   1.21479   1.22822   1.23453   
 1.17231   1.17692   1.18709   1.19916   1.20944   1.21415   
-1.16614   1.1694    1.17692   1.18594   1.19351   1.19683   
+1.16614   1.1694    1.17692   1.18593   1.19351   1.19683   
 1.16363   1.16614   1.17231   1.1798    1.186     1.18854   
 
-Species 3
-1.18854   1.19683   1.21416   1.23453   1.25222   1.26082   
-1.18601   1.19351   1.20944   1.22822   1.24444   1.25222   
-1.1798    1.18594   1.19916   1.21479   1.22822   1.23453   
-1.17231   1.17692   1.18709   1.19916   1.20944   1.21416   
-1.16614   1.1694    1.17692   1.18594   1.19351   1.19683   
-1.16363   1.16614   1.17231   1.1798    1.18601   1.18854   
-
 Species 4
-35655.3   35903.6   36423.2   37034.1   37564.4   37822.3   
-35579.3   35804.2   36281.9   36844.9   37331.5   37564.4   
-35393.1   35577     35973.5   36442.3   36844.9   37034.1   
-35168.4   35306.6   35611.4   35973.5   36281.9   36423.2   
-34983.3   35081.2   35306.6   35577     35804.2   35903.6   
-34907.9   34983.3   35168.4   35393.1   35579.3   35655.3   
+35655.3   35903.5   36423.2   37034.1   37564.5   37822.3   
+35579.2   35804.3   36281.9   36844.9   37331.4   37564.5   
+35393.1   35577     35973.5   36442.2   36844.9   37034.1   
+35168.3   35306.6   35611.4   35973.5   36281.9   36423.2   
+34983.2   35081.1   35306.6   35577     35804.3   35903.5   
+34907.9   34983.2   35168.3   35393.1   35579.2   35655.3   
 
 Species 5
-35655.3   35903.6   36423.2   37034.1   37564.4   37822.3   
-35579.3   35804.3   36281.9   36844.9   37331.5   37564.4   
-35393.1   35577     35973.5   36442.2   36844.9   37034.1   
-35168.4   35306.7   35611.4   35973.5   36281.9   36423.2   
-34983.3   35081.1   35306.7   35577     35804.3   35903.6   
-34907.9   34983.3   35168.4   35393.1   35579.3   35655.3   
+35655.3   35903.5   36423.3   37034     37564.5   37822.3   
+35579.1   35804.3   36281.8   36845     37331.4   37564.5   
+35393.2   35576.9   35973.5   36442.1   36845     37034     
+35168.3   35306.7   35611.3   35973.5   36281.8   36423.3   
+34983.2   35081.1   35306.7   35576.9   35804.3   35903.5   
+34907.8   34983.2   35168.3   35393.2   35579.1   35655.3   
 
 Species 6
-35655.4   35903.6   36423.2   37034.1   37564.5   37822.3   
-35579.2   35804.3   36281.9   36845     37331.5   37564.5   
-35393.2   35576.9   35973.5   36442.2   36845     37034.1   
-35168.3   35306.7   35611.4   35973.5   36281.9   36423.2   
-34983.3   35081.1   35306.7   35576.9   35804.3   35903.6   
-34907.9   34983.3   35168.3   35393.2   35579.2   35655.4   
+35655.3   35903.5   36423.3   37034     37564.5   37822.2   
+35579.1   35804.3   36281.8   36845     37331.3   37564.5   
+35393.2   35576.9   35973.6   36442.1   36845     37034     
+35168.3   35306.7   35611.3   35973.6   36281.8   36423.3   
+34983.3   35081     35306.7   35576.9   35804.3   35903.5   
+34907.8   34983.3   35168.3   35393.2   35579.1   35655.3   
 
-t =   8.00e+00  nst = 342  nfe = 381  nni = 377  qu = 2  hu =    3.67e-01
+t =   8.00e+00  nst = 337  nfe = 374  nni = 370  qu = 3  hu =    1.26e-01
 
-t =   9.00e+00  nst = 344  nfe = 383  nni = 379  qu = 2  hu =    3.67e-01
+t =   9.00e+00  nst = 345  nfe = 382  nni = 378  qu = 3  hu =    1.26e-01
 
-t =   1.00e+01  nst = 346  nfe = 385  nni = 381  qu = 2  hu =    5.82e-01
+t =   1.00e+01  nst = 353  nfe = 391  nni = 387  qu = 3  hu =    1.26e-01
 
 c values at t = 10:
 
 Species 1
-1.18838   1.19667   1.21399   1.23436   1.25205   1.26065   
+1.18838   1.19667   1.21399   1.23437   1.25205   1.26066   
 1.18585   1.19335   1.20928   1.22805   1.24428   1.25205   
-1.17964   1.18578   1.199     1.21463   1.22805   1.23436   
+1.17964   1.18578   1.199     1.21463   1.22805   1.23437   
 1.17215   1.17676   1.18693   1.199     1.20928   1.21399   
 1.16598   1.16925   1.17676   1.18578   1.19335   1.19667   
 1.16347   1.16598   1.17215   1.17964   1.18585   1.18838   
 
 Species 2
-1.18838   1.19667   1.21399   1.23436   1.25205   1.26065   
+1.18838   1.19667   1.21399   1.23437   1.25205   1.26066   
 1.18585   1.19335   1.20928   1.22805   1.24428   1.25205   
-1.17964   1.18578   1.199     1.21463   1.22805   1.23436   
+1.17964   1.18578   1.199     1.21463   1.22805   1.23437   
 1.17215   1.17676   1.18693   1.199     1.20928   1.21399   
 1.16598   1.16925   1.17676   1.18578   1.19335   1.19667   
 1.16347   1.16598   1.17215   1.17964   1.18585   1.18838   
 
 Species 3
-1.18838   1.19667   1.21399   1.23436   1.25205   1.26065   
+1.18838   1.19667   1.21399   1.23437   1.25205   1.26066   
 1.18585   1.19335   1.20928   1.22805   1.24428   1.25205   
-1.17964   1.18578   1.199     1.21463   1.22805   1.23436   
+1.17964   1.18578   1.199     1.21463   1.22805   1.23437   
 1.17215   1.17676   1.18693   1.199     1.20928   1.21399   
 1.16598   1.16925   1.17676   1.18578   1.19335   1.19667   
 1.16347   1.16598   1.17215   1.17964   1.18585   1.18838   
 
 Species 4
-35651.1   35898.4   36418.5   37029     37559.3   37817.3   
-35574.1   35799.8   36276.8   36840.1   37326.6   37559.3   
-35388.6   35571.9   35968.9   36437.2   36840.1   37029     
-35163.6   35302     35606.4   35968.9   36276.8   36418.5   
-34978.4   35076.6   35302     35571.9   35799.8   35898.4   
-34903.2   34978.4   35163.6   35388.6   35574.1   35651.1   
+35650.6   35898.8   36418.3   37029.3   37559.4   37817.3   
+35574.5   35799.5   36277.1   36840     37326.6   37559.4   
+35388.5   35572.3   35968.7   36437.4   36840     37029.3   
+35163.7   35302     35606.7   35968.7   36277.1   36418.3   
+34978.7   35076.5   35302     35572.3   35799.5   35898.8   
+34903.2   34978.7   35163.7   35388.5   35574.5   35650.6   
 
 Species 5
-35650.8   35898.7   36418.2   37029.3   37559     37817.7   
-35574.5   35799.4   36277.2   36839.8   37326.9   37559     
-35388.3   35572.3   35968.6   36437.6   36839.8   37029.3   
-35163.9   35301.7   35606.8   35968.6   36277.2   36418.2   
-34978     35077     35301.7   35572.3   35799.4   35898.7   
-34903.6   34978     35163.9   35388.3   35574.5   35650.8   
+35650.5   35898.8   36418.3   37029.3   37559.4   37817.4   
+35574.5   35799.5   36277.1   36840     37326.6   37559.4   
+35388.5   35572.3   35968.7   36437.4   36840     37029.3   
+35163.7   35302     35606.7   35968.7   36277.1   36418.3   
+34978.7   35076.5   35302     35572.3   35799.5   35898.8   
+34903.2   34978.7   35163.7   35388.5   35574.5   35650.5   
 
 Species 6
-35650.4   35899     36417.9   37029.6   37558.7   37818     
-35574.8   35799.1   36277.5   36839.5   37327.3   37558.7   
-35388     35572.6   35968.2   36437.9   36839.5   37029.6   
-35164.2   35301.3   35607.1   35968.2   36277.5   36417.9   
-34977.7   35077.3   35301.3   35572.6   35799.1   35899     
-34903.9   34977.7   35164.2   35388     35574.8   35650.4   
+35650.5   35898.8   36418.3   37029.3   37559.4   37817.4   
+35574.5   35799.5   36277.1   36840     37326.6   37559.4   
+35388.4   35572.3   35968.7   36437.4   36840     37029.3   
+35163.7   35302     35606.7   35968.7   36277.1   36418.3   
+34978.6   35076.5   35302     35572.3   35799.5   35898.8   
+34903.2   34978.6   35163.7   35388.4   35574.5   35650.5   
 
 
 
@@ -420,21 +420,21 @@ Species 6
 
  CVode real workspace length           = 2249 
  CVode integer workspace length        =   50 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
- Number of steps                       =  346 
- Number of f-s                         =  385 
- Number of f-s (SPGMR)                 =  550 
- Number of f-s (TOTAL)                 =  935 
- Number of setups                      =   46 
- Number of nonlinear iterations        =  381 
- Number of linear iterations           =  550 
- Number of preconditioner evaluations  =   46 
- Number of preconditioner solves       =  915 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
+ Number of steps                       =  353 
+ Number of f-s                         =  391 
+ Number of f-s (SPGMR)                 =  586 
+ Number of f-s (TOTAL)                 =  977 
+ Number of setups                      =   43 
+ Number of nonlinear iterations        =  387 
+ Number of linear iterations           =  586 
+ Number of preconditioner evaluations  =   43 
+ Number of preconditioner solves       =  957 
  Number of error test failures         =    1 
  Number of nonlinear conv. failures    =    0 
  Number of linear convergence failures =    0 
- Average Krylov subspace dimension     = 1.444 
+ Average Krylov subspace dimension     = 1.514 
 
 
 ----------------------------------------------------------------------------
@@ -466,21 +466,21 @@ t =   1.00e+00  nst = 235  nfe = 265  nni = 261  qu = 4  hu =    2.49e-02
 
 t =   2.00e+00  nst = 272  nfe = 305  nni = 301  qu = 3  hu =    3.80e-02
 
-t =   3.00e+00  nst = 288  nfe = 322  nni = 318  qu = 3  hu =    6.59e-02
+t =   3.00e+00  nst = 288  nfe = 322  nni = 318  qu = 3  hu =    6.58e-02
 
-t =   4.00e+00  nst = 303  nfe = 337  nni = 333  qu = 3  hu =    6.59e-02
+t =   4.00e+00  nst = 303  nfe = 338  nni = 334  qu = 3  hu =    6.58e-02
 
-t =   5.00e+00  nst = 313  nfe = 349  nni = 345  qu = 3  hu =    1.26e-01
+t =   5.00e+00  nst = 316  nfe = 352  nni = 348  qu = 2  hu =    1.02e-01
 
-t =   6.00e+00  nst = 321  nfe = 357  nni = 353  qu = 3  hu =    1.26e-01
+t =   6.00e+00  nst = 324  nfe = 361  nni = 357  qu = 2  hu =    1.65e-01
 
-t =   7.00e+00  nst = 329  nfe = 366  nni = 362  qu = 3  hu =    1.26e-01
+t =   7.00e+00  nst = 330  nfe = 368  nni = 364  qu = 2  hu =    2.63e-01
 
-t =   8.00e+00  nst = 337  nfe = 374  nni = 370  qu = 3  hu =    1.26e-01
+t =   8.00e+00  nst = 334  nfe = 372  nni = 368  qu = 2  hu =    2.63e-01
 
-t =   9.00e+00  nst = 345  nfe = 382  nni = 378  qu = 3  hu =    1.26e-01
+t =   9.00e+00  nst = 338  nfe = 377  nni = 373  qu = 2  hu =    7.46e-01
 
-t =   1.00e+01  nst = 353  nfe = 391  nni = 387  qu = 3  hu =    1.26e-01
+t =   1.00e+01  nst = 339  nfe = 378  nni = 374  qu = 2  hu =    7.46e-01
 
 
 
@@ -488,21 +488,21 @@ t =   1.00e+01  nst = 353  nfe = 391  nni = 387  qu = 3  hu =    1.26e-01
 
  CVode real workspace length           = 2249 
  CVode integer workspace length        =   50 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
- Number of steps                       =  353 
- Number of f-s                         =  391 
- Number of f-s (SPGMR)                 =  581 
- Number of f-s (TOTAL)                 =  972 
- Number of setups                      =   43 
- Number of nonlinear iterations        =  387 
- Number of linear iterations           =  581 
- Number of preconditioner evaluations  =   43 
- Number of preconditioner solves       =  952 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
+ Number of steps                       =  339 
+ Number of f-s                         =  378 
+ Number of f-s (SPGMR)                 =  533 
+ Number of f-s (TOTAL)                 =  911 
+ Number of setups                      =   45 
+ Number of nonlinear iterations        =  374 
+ Number of linear iterations           =  533 
+ Number of preconditioner evaluations  =   45 
+ Number of preconditioner solves       =  891 
  Number of error test failures         =    1 
  Number of nonlinear conv. failures    =    0 
  Number of linear convergence failures =    0 
- Average Krylov subspace dimension     = 1.501 
+ Average Krylov subspace dimension     = 1.425 
 
 
 ----------------------------------------------------------------------------
@@ -528,27 +528,27 @@ t =   1.00e-03  nst = 138  nfe = 163  nni = 159  qu = 2  hu =    4.17e-04
 
 t =   1.00e-02  nst = 146  nfe = 174  nni = 170  qu = 3  hu =    1.64e-03
 
-t =   1.00e-01  nst = 169  nfe = 200  nni = 196  qu = 5  hu =    9.35e-03
+t =   1.00e-01  nst = 169  nfe = 200  nni = 196  qu = 5  hu =    9.36e-03
 
 t =   1.00e+00  nst = 207  nfe = 247  nni = 243  qu = 5  hu =    5.17e-02
 
-t =   2.00e+00  nst = 220  nfe = 262  nni = 258  qu = 5  hu =    7.91e-02
+t =   2.00e+00  nst = 219  nfe = 263  nni = 259  qu = 5  hu =    1.21e-01
 
-t =   3.00e+00  nst = 228  nfe = 271  nni = 267  qu = 5  hu =    1.32e-01
+t =   3.00e+00  nst = 227  nfe = 271  nni = 267  qu = 5  hu =    1.21e-01
 
-t =   4.00e+00  nst = 235  nfe = 278  nni = 274  qu = 5  hu =    1.32e-01
+t =   4.00e+00  nst = 233  nfe = 278  nni = 274  qu = 5  hu =    1.83e-01
 
-t =   5.00e+00  nst = 240  nfe = 284  nni = 280  qu = 4  hu =    2.06e-01
+t =   5.00e+00  nst = 238  nfe = 283  nni = 279  qu = 5  hu =    1.83e-01
 
-t =   6.00e+00  nst = 246  nfe = 294  nni = 290  qu = 4  hu =    8.61e-02
+t =   6.00e+00  nst = 244  nfe = 289  nni = 285  qu = 5  hu =    1.83e-01
 
-t =   7.00e+00  nst = 254  nfe = 306  nni = 302  qu = 2  hu =    2.67e-01
+t =   7.00e+00  nst = 249  nfe = 295  nni = 291  qu = 5  hu =    1.83e-01
 
-t =   8.00e+00  nst = 257  nfe = 310  nni = 306  qu = 3  hu =    4.13e-01
+t =   8.00e+00  nst = 255  nfe = 301  nni = 297  qu = 5  hu =    1.83e-01
 
-t =   9.00e+00  nst = 260  nfe = 315  nni = 311  qu = 3  hu =    4.61e-01
+t =   9.00e+00  nst = 260  nfe = 307  nni = 303  qu = 5  hu =    1.83e-01
 
-t =   1.00e+01  nst = 262  nfe = 321  nni = 317  qu = 3  hu =    2.25e-01
+t =   1.00e+01  nst = 266  nfe = 313  nni = 309  qu = 5  hu =    1.83e-01
 
 
 
@@ -556,21 +556,21 @@ t =   1.00e+01  nst = 262  nfe = 321  nni = 317  qu = 3  hu =    2.25e-01
 
  CVode real workspace length           = 2249 
  CVode integer workspace length        =   50 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
- Number of steps                       =  262 
- Number of f-s                         =  321 
- Number of f-s (SPGMR)                 =  637 
- Number of f-s (TOTAL)                 =  958 
- Number of setups                      =   55 
- Number of nonlinear iterations        =  317 
- Number of linear iterations           =  637 
- Number of preconditioner evaluations  =   55 
- Number of preconditioner solves       =  918 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
+ Number of steps                       =  266 
+ Number of f-s                         =  313 
+ Number of f-s (SPGMR)                 =  600 
+ Number of f-s (TOTAL)                 =  913 
+ Number of setups                      =   41 
+ Number of nonlinear iterations        =  309 
+ Number of linear iterations           =  600 
+ Number of preconditioner evaluations  =   41 
+ Number of preconditioner solves       =  873 
  Number of error test failures         =    3 
- Number of nonlinear conv. failures    =    4 
- Number of linear convergence failures =   48 
- Average Krylov subspace dimension     = 2.009 
+ Number of nonlinear conv. failures    =    0 
+ Number of linear convergence failures =   42 
+ Average Krylov subspace dimension     = 1.942 
 
 
 ----------------------------------------------------------------------------
@@ -600,23 +600,23 @@ t =   1.00e-01  nst = 169  nfe = 200  nni = 196  qu = 5  hu =    9.35e-03
 
 t =   1.00e+00  nst = 207  nfe = 247  nni = 243  qu = 5  hu =    5.18e-02
 
-t =   2.00e+00  nst = 219  nfe = 263  nni = 259  qu = 5  hu =    1.23e-01
+t =   2.00e+00  nst = 219  nfe = 263  nni = 259  qu = 5  hu =    1.22e-01
 
-t =   3.00e+00  nst = 227  nfe = 271  nni = 267  qu = 5  hu =    1.23e-01
+t =   3.00e+00  nst = 227  nfe = 271  nni = 267  qu = 5  hu =    1.22e-01
 
-t =   4.00e+00  nst = 234  nfe = 279  nni = 275  qu = 5  hu =    1.90e-01
+t =   4.00e+00  nst = 233  nfe = 277  nni = 273  qu = 4  hu =    1.83e-01
 
-t =   5.00e+00  nst = 239  nfe = 284  nni = 280  qu = 5  hu =    1.90e-01
+t =   5.00e+00  nst = 238  nfe = 283  nni = 279  qu = 4  hu =    2.94e-01
 
-t =   6.00e+00  nst = 244  nfe = 289  nni = 285  qu = 5  hu =    1.90e-01
+t =   6.00e+00  nst = 242  nfe = 287  nni = 283  qu = 4  hu =    2.94e-01
 
-t =   7.00e+00  nst = 259  nfe = 311  nni = 307  qu = 4  hu =    1.53e-01
+t =   7.00e+00  nst = 246  nfe = 293  nni = 289  qu = 4  hu =    1.11e-01
 
-t =   8.00e+00  nst = 265  nfe = 319  nni = 315  qu = 3  hu =    2.48e-01
+t =   8.00e+00  nst = 251  nfe = 298  nni = 294  qu = 3  hu =    3.43e-01
 
-t =   9.00e+00  nst = 268  nfe = 322  nni = 318  qu = 3  hu =    3.76e-01
+t =   9.00e+00  nst = 254  nfe = 301  nni = 297  qu = 2  hu =    5.23e-01
 
-t =   1.00e+01  nst = 270  nfe = 324  nni = 320  qu = 2  hu =    5.81e-01
+t =   1.00e+01  nst = 256  nfe = 305  nni = 301  qu = 2  hu =    2.03e-01
 
 
 
@@ -624,21 +624,21 @@ t =   1.00e+01  nst = 270  nfe = 324  nni = 320  qu = 2  hu =    5.81e-01
 
  CVode real workspace length           = 2249 
  CVode integer workspace length        =   50 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
- Number of steps                       =  270 
- Number of f-s                         =  324 
- Number of f-s (SPGMR)                 =  626 
- Number of f-s (TOTAL)                 =  950 
- Number of setups                      =   50 
- Number of nonlinear iterations        =  320 
- Number of linear iterations           =  626 
- Number of preconditioner evaluations  =   50 
- Number of preconditioner solves       =  908 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
+ Number of steps                       =  256 
+ Number of f-s                         =  305 
+ Number of f-s (SPGMR)                 =  563 
+ Number of f-s (TOTAL)                 =  868 
+ Number of setups                      =   48 
+ Number of nonlinear iterations        =  301 
+ Number of linear iterations           =  563 
+ Number of preconditioner evaluations  =   48 
+ Number of preconditioner solves       =  828 
  Number of error test failures         =    3 
  Number of nonlinear conv. failures    =    2 
- Number of linear convergence failures =   43 
- Average Krylov subspace dimension     = 1.956 
+ Number of linear convergence failures =   36 
+ Average Krylov subspace dimension     = 1.870 
 
 
 ----------------------------------------------------------------------------
diff --git a/examples/cvode/serial/cvRoberts_dns.c b/examples/cvode/serial/cvRoberts_dns.c
index c63433b..b63468e 100644
--- a/examples/cvode/serial/cvRoberts_dns.c
+++ b/examples/cvode/serial/cvRoberts_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -20,23 +16,21 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVDENSE dense linear solver, and a
+ * Newton iteration with the SUNDENSE dense linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts., consts. */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <cvode/cvode_dense.h>       /* prototype for CVDense */
-#include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
-#include <sundials/sundials_types.h> /* definition of type realtype */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <cvode/cvode_direct.h>        /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macros: Ith, IJth */
 
@@ -50,11 +44,11 @@
 
    IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
    i and j are in the range [1..NEQ]. The IJth macro is defined using the
-   DENSE_ELEM macro in dense.h. DENSE_ELEM numbers rows and columns of a
-   dense matrix starting from 0. */
+   SM_ELEMENT_D macro in dense.h. SM_ELEMENT_D numbers rows and columns of 
+   a dense matrix starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
 
 
 /* Problem Constants */
@@ -72,6 +66,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -79,9 +74,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -96,6 +90,10 @@ static void PrintFinalStats(void *cvode_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
+/* Private function to check computed solution */
+
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol);
+
 
 /*
  *-------------------------------
@@ -107,11 +105,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -152,13 +154,21 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVDense to specify the CVDENSE dense linear solver */
-  flag = CVDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVDense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object for use by CVode */
+  LS = SUNDenseLinearSolver(y, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -187,14 +197,23 @@ int main()
   /* Print some final statistics */
   PrintFinalStats(cvode_mem);
 
+  /* check the solution error */
+  flag = check_ans(y, t, reltol, abstol);
+
   /* Free y and abstol vectors */
-  N_VDestroy_Serial(y);
-  N_VDestroy_Serial(abstol);
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
-  return(0);
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
+  return(flag);
 }
 
 
@@ -240,9 +259,8 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
 
@@ -251,10 +269,14 @@ static int Jac(long int N, realtype t,
   IJth(J,1,1) = RCONST(-0.04);
   IJth(J,1,2) = RCONST(1.0e4)*y3;
   IJth(J,1,3) = RCONST(1.0e4)*y2;
+
   IJth(J,2,1) = RCONST(0.04); 
   IJth(J,2,2) = RCONST(-1.0e4)*y3-RCONST(6.0e7)*y2;
   IJth(J,2,3) = RCONST(-1.0e4)*y2;
+
+  IJth(J,3,1) = ZERO;
   IJth(J,3,2) = RCONST(6.0e7)*y2;
+  IJth(J,3,3) = ZERO;
 
   return(0);
 }
@@ -358,3 +380,49 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
 
   return(0);
 }
+
+/* compare the solution at the final time 4e10s to a reference solution computed
+   using a relative tolerance of 1e-8 and absoltue tolerance of 1e-14 */
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol)
+{
+  int      passfail=0;        /* answer pass (0) or fail (1) flag */  
+  N_Vector ref;               /* reference solution vector        */
+  N_Vector ewt;               /* error weight vector              */
+  realtype err;               /* wrms error                       */
+  realtype ONE=RCONST(1.0);  
+
+  /* create reference solution and error weight vectors */
+  ref = N_VClone(y);
+  ewt = N_VClone(y);
+
+  /* set the reference solution data */
+  NV_Ith_S(ref,0) = RCONST(5.2083495894337328e-08);
+  NV_Ith_S(ref,1) = RCONST(2.0833399429795671e-13);
+  NV_Ith_S(ref,2) = RCONST(9.9999994791629776e-01);
+
+  /* compute the error weight vector, loosen atol */
+  N_VAbs(ref, ewt);
+  N_VLinearSum(rtol, ewt, RCONST(10.0), atol, ewt);
+  if (N_VMin(ewt) <= ZERO) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: check_ans failed - ewt <= 0\n\n");
+    return(-1);
+  }
+  N_VInv(ewt, ewt);   
+
+  /* compute the solution error */
+  N_VLinearSum(ONE, y, -ONE, ref, ref);
+  err = N_VWrmsNorm(ref, ewt);
+
+  /* is the solution within the tolerances? */
+  passfail = (err < ONE) ? 0 : 1; 
+
+  if (passfail) {
+    fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%g \n\n", err);
+  }
+
+  /* Free vectors */
+  N_VDestroy(ref);
+  N_VDestroy(ewt);
+
+  return(passfail);
+}
diff --git a/examples/cvode/serial/cvRoberts_dns.out b/examples/cvode/serial/cvRoberts_dns.out
index c21cc40..be6ded6 100644
--- a/examples/cvode/serial/cvRoberts_dns.out
+++ b/examples/cvode/serial/cvRoberts_dns.out
@@ -5,20 +5,20 @@ At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
 At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
 At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
-At t = 4.0000e+01      y =  7.158009e-01    9.185098e-06    2.841900e-01
-At t = 4.0000e+02      y =  4.505440e-01    3.223217e-06    5.494528e-01
-At t = 4.0000e+03      y =  1.831964e-01    8.942051e-07    8.168027e-01
-At t = 4.0000e+04      y =  3.898104e-02    1.621656e-07    9.610188e-01
-At t = 4.0000e+05      y =  4.938672e-03    1.985172e-08    9.950613e-01
-At t = 4.0000e+06      y =  5.166093e-04    2.067499e-09    9.994834e-01
-At t = 2.0800e+07      y =  1.000000e-04    4.000395e-10    9.999000e-01
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168093e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.206409e-05    2.082671e-10    9.999479e-01
-At t = 4.0000e+08      y =  5.211241e-06    2.084507e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.200520e-07    2.080209e-12    9.999995e-01
-At t = 4.0000e+10      y =  5.699485e-08    2.279794e-13    9.999999e-01
+At t = 4.0000e+07      y =  5.202440e-05    2.081083e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.201061e-06    2.080435e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.258603e-07    2.103442e-12    9.999995e-01
+At t = 4.0000e+10      y =  6.934511e-08    2.773804e-13    9.999999e-01
 
 Final Statistics:
-nst = 579    nfe  = 817    nsetups = 118    nfeLS = 0      nje = 12
-nni = 813    ncfn = 0      netf = 31     nge = 615
+nst = 542    nfe  = 755    nsetups = 107    nfeLS = 0      nje = 11
+nni = 751    ncfn = 0      netf = 22     nge = 570
  
diff --git a/examples/cvode/serial/cvRoberts_dnsL.c b/examples/cvode/serial/cvRoberts_dnsL.c
index c378baf..6beeedf 100644
--- a/examples/cvode/serial/cvRoberts_dnsL.c
+++ b/examples/cvode/serial/cvRoberts_dnsL.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4878 $
- * $Date: 2016-08-31 15:17:31 -0700 (Wed, 31 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -24,16 +20,16 @@
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts. and consts. */
-#include <cvode/cvode_lapack.h>      /* prototype for CVLapackDense */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., and macros */
+#include <cvode/cvode.h>                     /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>          /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h>       /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_lapackdense.h> /* access to dense SUNLinearSolver      */
+#include <cvode/cvode_direct.h>              /* access to CVDls interface            */
+#include <sundials/sundials_types.h>         /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macros: Ith, IJth */
 
@@ -47,11 +43,11 @@
 
    IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
    i and j are in the range [1..NEQ]. The IJth macro is defined using the
-   DENSE_ELEM macro in dense.h. DENSE_ELEM numbers rows and columns of a
-   dense matrix starting from 0. */
+   SM_ELEMENT_D macro in dense.h. SM_ELEMENT_D numbers rows and columns of 
+   a dense matrix starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)              /* Ith numbers components 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
 
 
 /* Problem Constants */
@@ -77,10 +73,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -106,11 +100,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -151,16 +149,24 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVLapackDense to specify the LAPACK dense linear solver */
-  flag = CVLapackDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVLapackDense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Create SUNLapackDense solver object for use by CVode */
+  LS = SUNLapackDense(y, A);
+  if(check_flag((void *)LS, "SUNLapackDense", 0)) return(1);
+
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
-   * Break out of loop when NOUT preset output times have been reached.  */
+     Break out of loop when NOUT preset output times have been reached.  */
   printf(" \n3-species kinetics problem\n\n");
 
   iout = 0;  tout = T1;
@@ -186,13 +192,19 @@ int main()
   /* Print some final statistics */
   PrintFinalStats(cvode_mem);
 
-  /* Free y vector and abstol vectors */
-  N_VDestroy_Serial(y);
-  N_VDestroy_Serial(abstol);
+  /* Free y and abstol vectors */
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -239,10 +251,8 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
 
@@ -274,7 +284,7 @@ static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3)
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("At t = %0.4Le      y =%14.6Le  %14.6Le  %14.6Le\n", t, y1, y2, y3);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-  printf("At t = %0.4le      y =%14.6le  %14.6le  %14.6le\n", t, y1, y2, y3);
+  printf("At t = %0.4e      y =%14.6e  %14.6e  %14.6e\n", t, y1, y2, y3);
 #else
   printf("At t = %0.4e      y =%14.6e  %14.6e  %14.6e\n", t, y1, y2, y3);
 #endif
diff --git a/examples/cvode/serial/cvRoberts_dnsL.out b/examples/cvode/serial/cvRoberts_dnsL.out
index 747ed23..be6ded6 100644
--- a/examples/cvode/serial/cvRoberts_dnsL.out
+++ b/examples/cvode/serial/cvRoberts_dnsL.out
@@ -5,20 +5,20 @@ At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
 At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
 At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
-At t = 4.0000e+01      y =  7.158009e-01    9.185098e-06    2.841900e-01
-At t = 4.0000e+02      y =  4.505440e-01    3.223217e-06    5.494528e-01
-At t = 4.0000e+03      y =  1.831964e-01    8.942051e-07    8.168027e-01
-At t = 4.0000e+04      y =  3.898104e-02    1.621656e-07    9.610188e-01
-At t = 4.0000e+05      y =  4.938681e-03    1.985174e-08    9.950613e-01
-At t = 4.0000e+06      y =  5.170501e-04    2.069253e-09    9.994829e-01
-At t = 2.0809e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168093e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.205557e-05    2.082332e-10    9.999479e-01
-At t = 4.0000e+08      y =  5.207434e-06    2.082985e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.231265e-07    2.092507e-12    9.999995e-01
-At t = 4.0000e+10      y =  5.009148e-08    2.003659e-13    9.999999e-01
+At t = 4.0000e+07      y =  5.202440e-05    2.081083e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.201061e-06    2.080435e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.258603e-07    2.103442e-12    9.999995e-01
+At t = 4.0000e+10      y =  6.934511e-08    2.773804e-13    9.999999e-01
 
 Final Statistics:
-nst = 577    nfe  = 838    nsetups = 125    nfeLS = 0      nje = 12
-nni = 834    ncfn = 0      netf = 33     nge = 612
+nst = 542    nfe  = 755    nsetups = 107    nfeLS = 0      nje = 11
+nni = 751    ncfn = 0      netf = 22     nge = 570
  
diff --git a/examples/cvode/serial/cvRoberts_dns_uw.c b/examples/cvode/serial/cvRoberts_dns_uw.c
index 71921e5..8a80315 100644
--- a/examples/cvode/serial/cvRoberts_dns_uw.c
+++ b/examples/cvode/serial/cvRoberts_dns_uw.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -20,25 +16,23 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVDENSE dense linear solver, and a
+ * Newton iteration with the SUNDENSE dense linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a user-supplied function to compute the error weights
  * required for the WRMS norm calculations.
  * Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used here */
-
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts. and consts. */
-#include <cvode/cvode_dense.h>       /* prototype for CVDense */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, functions, and macros */
-#include <sundials/sundials_dense.h> /* definitions DlsMat and DENSE_ELEM */
-#include <sundials/sundials_types.h> /* definition of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS */
+#include <cvode/cvode.h>               /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <cvode/cvode_direct.h>        /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* definition of ABS                    */
 
 /* User-defined vector and matrix accessor macros: Ith, IJth */
 
@@ -52,11 +46,11 @@
 
    IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
    i and j are in the range [1..NEQ]. The IJth macro is defined using the
-   DENSE_ELEM macro in dense.h. DENSE_ELEM numbers rows and columns of a
-   dense matrix starting from 0. */
+   SM_ELEMENT_D macro in dense.h. SM_ELEMENT_D numbers rows and columns of 
+   a dense matrix starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
 
 
 /* Problem Constants */
@@ -74,6 +68,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -81,9 +76,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 static int ewt(N_Vector y, N_Vector w, void *user_data);
 
@@ -111,11 +105,15 @@ int main()
 {
   realtype t, tout;
   N_Vector y;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout;
   int rootsfound[2];
 
   y = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. */
@@ -146,13 +144,21 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVDense to specify the CVDENSE dense linear solver */
-  flag = CVDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVDense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object for use by CVode */
+  LS = SUNDenseLinearSolver(y, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -165,7 +171,7 @@ int main()
 
     if (flag == CV_ROOT_RETURN) {
       flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
-      check_flag(&flagr, "CVodeGetRootInfo", 1);
+      if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
       PrintRootInfo(rootsfound[0],rootsfound[1]);
     }
 
@@ -182,11 +188,17 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free y vector */
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -211,7 +223,7 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
         Ith(ydot,2) = -yd1 - yd3;
 
-  return(0);      
+  return(0);
 }
 
 /*
@@ -233,9 +245,8 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
 
@@ -244,10 +255,14 @@ static int Jac(long int N, realtype t,
   IJth(J,1,1) = RCONST(-0.04);
   IJth(J,1,2) = RCONST(1.0e4)*y3;
   IJth(J,1,3) = RCONST(1.0e4)*y2;
+
   IJth(J,2,1) = RCONST(0.04); 
   IJth(J,2,2) = RCONST(-1.0e4)*y3-RCONST(6.0e7)*y2;
   IJth(J,2,3) = RCONST(-1.0e4)*y2;
+
+  IJth(J,3,1) = ZERO;
   IJth(J,3,2) = RCONST(6.0e7)*y2;
+  IJth(J,3,3) = ZERO;
 
   return(0);
 }
diff --git a/examples/cvode/serial/cvRoberts_dns_uw.out b/examples/cvode/serial/cvRoberts_dns_uw.out
index ce633e3..be6ded6 100644
--- a/examples/cvode/serial/cvRoberts_dns_uw.out
+++ b/examples/cvode/serial/cvRoberts_dns_uw.out
@@ -5,20 +5,20 @@ At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
 At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
 At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
-At t = 4.0000e+01      y =  7.158010e-01    9.185084e-06    2.841898e-01
-At t = 4.0000e+02      y =  4.504693e-01    3.222618e-06    5.495275e-01
-At t = 4.0000e+03      y =  1.832127e-01    8.943456e-07    8.167865e-01
-At t = 4.0000e+04      y =  3.899386e-02    1.622228e-07    9.610060e-01
-At t = 4.0000e+05      y =  4.937166e-03    1.984537e-08    9.950628e-01
-At t = 4.0000e+06      y =  5.167725e-04    2.068146e-09    9.994832e-01
-At t = 2.0792e+07      y =  1.000000e-04    4.000399e-10    9.999000e-01
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168093e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.201944e-05    2.080885e-10    9.999480e-01
-At t = 4.0000e+08      y =  5.222674e-06    2.089080e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.206257e-07    2.082504e-12    9.999995e-01
-At t = 4.0000e+10      y =  4.244776e-08    1.697910e-13    1.000000e-00
+At t = 4.0000e+07      y =  5.202440e-05    2.081083e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.201061e-06    2.080435e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.258603e-07    2.103442e-12    9.999995e-01
+At t = 4.0000e+10      y =  6.934511e-08    2.773804e-13    9.999999e-01
 
 Final Statistics:
-nst = 545    nfe  = 773    nsetups = 117    nfeLS = 0      nje = 12
-nni = 769    ncfn = 0      netf = 30     nge = 573
+nst = 542    nfe  = 755    nsetups = 107    nfeLS = 0      nje = 11
+nni = 751    ncfn = 0      netf = 22     nge = 570
  
diff --git a/examples/cvode/serial/cvRoberts_klu.c b/examples/cvode/serial/cvRoberts_klu.c
index 3292397..8d41d94 100644
--- a/examples/cvode/serial/cvRoberts_klu.c
+++ b/examples/cvode/serial/cvRoberts_klu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward.
  *      Based on cvRoberts_dns.c and modified to use KLU.
  * -----------------------------------------------------------------
@@ -20,23 +16,21 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVKLU sparse direct linear solver, and a
+ * Newton iteration with the KLU sparse direct linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts., consts. */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <cvode/cvode_klu.h>         /* prototype for CVKLU */
-#include <sundials/sundials_sparse.h> /* definitions SlsMat */
-#include <sundials/sundials_types.h> /* definition of type realtype */
+#include <cvode/cvode.h>                /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>     /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h> /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>    /* access to KLU sparse direct solver   */
+#include <cvode/cvode_direct.h>         /* access to CVDls interface            */
+#include <sundials/sundials_types.h>    /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macro: Ith */
 
@@ -46,16 +40,13 @@
    Ith(v,i) references the ith component of the vector v, where i is in
    the range [1..NEQ] and NEQ is defined below. The Ith macro is defined
    using the N_VIth macro in nvector.h. N_VIth numbers the components of
-   a vector starting from 0.
-*/
+   a vector starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
 
 
 /* Problem Constants */
 
-#define ZERO  RCONST(0.0)
-
 #define NEQ   3                /* number of equations  */
 #define Y1    RCONST(1.0)      /* initial y components */
 #define Y2    RCONST(0.0)
@@ -69,6 +60,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -76,9 +68,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -104,11 +95,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout, nnz;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -149,14 +144,22 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVKLU to specify the CVKLU sparse direct linear solver */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = CVKLU(cvode_mem, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "CVKLU", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU solver object for use by CVode */
+  LS = SUNKLU(y, A);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -186,12 +189,18 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free y and abstol vectors */
-  N_VDestroy_Serial(y);
-  N_VDestroy_Serial(abstol);
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -238,21 +247,17 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
   
-  yval = N_VGetArrayPointer_Serial(y);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data    = JacMat->data;
+  yval = N_VGetArrayPointer(y);
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
@@ -331,8 +336,8 @@ static void PrintFinalStats(void *cvode_mem)
   flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
   check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
 
-  flag = CVSlsGetNumJacEvals(cvode_mem, &nje);
-  check_flag(&flag, "CVSlsGetNumJacEvals", 1);
+  flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
+  check_flag(&flag, "CVDlsGetNumJacEvals", 1);
 
   flag = CVodeGetNumGEvals(cvode_mem, &nge);
   check_flag(&flag, "CVodeGetNumGEvals", 1);
diff --git a/examples/cvode/serial/cvRoberts_klu.out b/examples/cvode/serial/cvRoberts_klu.out
index 776406f..d34a8ee 100644
--- a/examples/cvode/serial/cvRoberts_klu.out
+++ b/examples/cvode/serial/cvRoberts_klu.out
@@ -3,22 +3,22 @@
 
 At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
-At t = 4.0000e-01      y =  9.851640e-01    3.386245e-05    1.480209e-02
-At t = 4.0000e+00      y =  9.055156e-01    2.240441e-05    9.446197e-02
-At t = 4.0000e+01      y =  7.158508e-01    9.186546e-06    2.841400e-01
-At t = 4.0000e+02      y =  4.505784e-01    3.223707e-06    5.494184e-01
-At t = 4.0000e+03      y =  1.832290e-01    8.944054e-07    8.167701e-01
-At t = 4.0000e+04      y =  3.898012e-02    1.621625e-07    9.610197e-01
-At t = 4.0000e+05      y =  4.936714e-03    1.984363e-08    9.950633e-01
-At t = 4.0000e+06      y =  5.164962e-04    2.067039e-09    9.994835e-01
-At t = 2.0784e+07      y =  1.000000e-04    4.000395e-10    9.999000e-01
+At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
+At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168094e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.202874e-05    2.081257e-10    9.999480e-01
-At t = 4.0000e+08      y =  5.206719e-06    2.082698e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.208794e-07    2.083519e-12    9.999995e-01
-At t = 4.0000e+10      y =  5.244455e-08    2.097782e-13    9.999999e-01
+At t = 4.0000e+07      y =  5.202445e-05    2.081085e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.194853e-06    2.077952e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.088353e-07    2.035342e-12    9.999995e-01
+At t = 4.0000e+10      y =  4.817809e-08    1.927124e-13    1.000000e+00
 
 Final Statistics:
-nst = 430    nfe  = 574    nsetups = 98     nje = 78
-nni = 570    ncfn = 0      netf = 23        nge = 466
+nst = 533    nfe  = 744    nsetups = 105    nje = 11
+nni = 740    ncfn = 0      netf = 20        nge = 561
  
diff --git a/examples/cvode/serial/cvRoberts_sps.c b/examples/cvode/serial/cvRoberts_sps.c
index d26954c..d996865 100644
--- a/examples/cvode/serial/cvRoberts_sps.c
+++ b/examples/cvode/serial/cvRoberts_sps.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward.
  *      Based on cvRoberts_dns.c and modified to use SUPERLU_MT.
  * -----------------------------------------------------------------
@@ -20,23 +16,21 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVSUPERLUMT sparse direct linear solver, and a
+ * Newton iteration with the SuperLUMT sparse direct linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvode/cvode.h>             /* prototypes for CVODE fcts., consts. */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <cvode/cvode_superlumt.h>   /* prototype for CVSUPERLUMT */
-#include <sundials/sundials_sparse.h> /* definitions SlsMat */
-#include <sundials/sundials_types.h> /* definition of type realtype */
+#include <cvode/cvode.h>                    /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>         /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>     /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h>  /* access to SuperLUMT linear solver    */
+#include <cvode/cvode_direct.h>             /* access to CVDls interface            */
+#include <sundials/sundials_types.h>        /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macro: Ith */
 
@@ -46,16 +40,13 @@
    Ith(v,i) references the ith component of the vector v, where i is in
    the range [1..NEQ] and NEQ is defined below. The Ith macro is defined
    using the N_VIth macro in nvector.h. N_VIth numbers the components of
-   a vector starting from 0.
-*/
+   a vector starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
 
 
 /* Problem Constants */
 
-#define ZERO  RCONST(0.0)
-
 #define NEQ   3                /* number of equations  */
 #define Y1    RCONST(1.0)      /* initial y components */
 #define Y2    RCONST(0.0)
@@ -69,6 +60,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -76,9 +68,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -104,11 +95,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout, nnz;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -149,14 +144,22 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVSuperLUMT to specify the CVSuperLUMT sparse direct linear solver */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = CVSuperLUMT(cvode_mem, 1, NEQ, nnz);
-  if (check_flag(&flag, "CVSuperLUMT", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT solver object for use by CVode (one thread) */
+  LS = SUNSuperLUMT(y, A, 1);
+  if(check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -186,12 +189,18 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free y and abstol vectors */
-  N_VDestroy_Serial(y);
-  N_VDestroy_Serial(abstol);
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -238,42 +247,42 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int *colptrs = *JacMat->colptrs;
-  int *rowvals = *JacMat->rowvals;
-
-  yval = N_VGetArrayPointer_Serial(y);
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
+  
+  yval = N_VGetArrayPointer(y);
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  JacMat->data[0] = RCONST(-0.04);
+  data[0] = RCONST(-0.04);
   rowvals[0] = 0;
-  JacMat->data[1] = RCONST(0.04);
+  data[1] = RCONST(0.04);
   rowvals[1] = 1;
-  JacMat->data[2] = ZERO;
+  data[2] = ZERO;
   rowvals[2] = 2;
 
-  JacMat->data[3] = RCONST(1.0e4)*yval[2];
+  data[3] = RCONST(1.0e4)*yval[2];
   rowvals[3] = 0;
-  JacMat->data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]);
+  data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]);
   rowvals[4] = 1;
-  JacMat->data[5] = RCONST(6.0e7)*yval[1];
+  data[5] = RCONST(6.0e7)*yval[1];
   rowvals[5] = 2;
 
-  JacMat->data[6] = RCONST(1.0e4)*yval[1];
+  data[6] = RCONST(1.0e4)*yval[1];
   rowvals[6] = 0;
-  JacMat->data[7] = RCONST(-1.0e4)*yval[1];
+  data[7] = RCONST(-1.0e4)*yval[1];
   rowvals[7] = 1;
-  JacMat->data[8] = ZERO;
+  data[8] = ZERO;
   rowvals[8] = 2;
 
   return(0);
@@ -327,8 +336,8 @@ static void PrintFinalStats(void *cvode_mem)
   flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
   check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
 
-  flag = CVSlsGetNumJacEvals(cvode_mem, &nje);
-  check_flag(&flag, "CVSlsGetNumJacEvals", 1);
+  flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
+  check_flag(&flag, "CVDlsGetNumJacEvals", 1);
 
   flag = CVodeGetNumGEvals(cvode_mem, &nge);
   check_flag(&flag, "CVodeGetNumGEvals", 1);
diff --git a/examples/cvodes/C_openmp/CMakeLists.txt b/examples/cvodes/C_openmp/CMakeLists.txt
index 6c0c90e..4f348f4 100644
--- a/examples/cvodes/C_openmp/CMakeLists.txt
+++ b/examples/cvodes/C_openmp/CMakeLists.txt
@@ -1,14 +1,14 @@
 # ---------------------------------------------------------------
-# Programmer:  Ting Yan @ SMU
+# Programmer: Ting Yan @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -17,59 +17,78 @@
 # Copyright (c) 2013, Southern Methodist University.
 # All rights reserved.
 # For details, see the LICENSE file.
-# -----------------------------------------------------------------
+# ---------------------------------------------------------------
 # CMakeLists.txt file for CVODES OpenMP examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if OpenMP is enabled
 IF(OPENMP_FOUND)
 
-# Add variable CVODES_examples_OMP with the names of the openmp CVODES examples
-SET(CVODES_examples_OMP
-  cvsAdvDiff_bnd_omp
-  )
+  # Examples using SUNDIALS linear solvers
+  SET(CVODES_examples_OMP
+    "cvsAdvDiff_bnd_omp\;4\;develop"
+    )
 
 ENDIF(OPENMP_FOUND)
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODES_LIB sundials_cvodes_static)
   SET(NVECOMP_LIB sundials_nvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODES_LIB sundials_cvodes_shared)
   SET(NVECOMP_LIB sundials_nvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${CVODES_LIB} ${NVECOMP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # update the compilation flags to include OpenMP support
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 
-# Add the build and install targets for each CVODES example
-FOREACH(example ${CVODES_examples_OMP})
-  ADD_EXECUTABLE(${example} ${example}.c)
-  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} TEST_ARGS 4)
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${CVODES_examples_OMP})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+    
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    TEST_ARGS ${example_args}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # install example source and .out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/C_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${CVODES_examples_OMP})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/C_openmp)
+  ENDIF()
 
+ENDFOREACH(example_tuple ${CVODES_examples_OMP})
+
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -78,36 +97,33 @@ IF(EXAMPLES_INSTALL)
   # Install the extra files
   FOREACH(extrafile ${CVODES_extras_OMP})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/C_openmp)
-  ENDFOREACH(extrafile ${CVODES_extras_OMP})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "CVODES")
   SET(SOLVER_LIB "sundials_cvodes")
-  LIST2STRING(CVODES_examples_OMP EXAMPLES)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
 
+  EXAMPLES2STRING(CVODES_examples_OMP EXAMPLES)
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvodes/C_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvodes/C_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/cvodes/C_openmp/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/C_openmp 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/C_openmp
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -119,7 +135,7 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/cvodes/C_openmp/Makefile_ex 
+      FILES ${PROJECT_BINARY_DIR}/examples/cvodes/C_openmp/Makefile_ex
       DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/C_openmp
       RENAME Makefile
       )
diff --git a/examples/cvodes/C_openmp/README b/examples/cvodes/C_openmp/README
index 884a0bf..9d46a14 100644
--- a/examples/cvodes/C_openmp/README
+++ b/examples/cvodes/C_openmp/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvodes/C_openmp/cvsAdvDiff_bnd_omp.c b/examples/cvodes/C_openmp/cvsAdvDiff_bnd_omp.c
index 8f4f1fa..4edd90b 100644
--- a/examples/cvodes/C_openmp/cvsAdvDiff_bnd_omp.c
+++ b/examples/cvodes/C_openmp/cvsAdvDiff_bnd_omp.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
- * Programmer(s): Ting Yan @ SMU
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds and Ting Yan @ SMU
  *     Based on cvsAdvDiff_bnd.c and parallelized with OpenMP
  * -----------------------------------------------------------------
  * Example problem:
  *
  * The following is a simple example problem with a banded Jacobian,
- * with the program for its solution by CVODES.
+ * solved using CVODES.
  * The problem is the semi-discrete form of the advection-diffusion
  * equation in 2-D:
  *   du/dt = d^2 u / dx^2 + .5 du/dx + d^2 u / dy^2
@@ -21,7 +17,7 @@
  * central differencing, and with boundary values eliminated,
  * leaving an ODE system of size NEQ = MX*MY.
  * This program solves the problem with the BDF method, Newton
- * iteration with the CVBAND band linear solver, and a user-supplied
+ * iteration with the SUBBAND linear solver, and a user-supplied
  * Jacobian routine.
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .1, .2, ..., 1.
@@ -34,27 +30,27 @@
  *
  * Execution:
  *
- * If the user want to use the default value or the number of threads 
- * from environment value:
+ * To use the default value or the number of threads from the 
+ * environment value, run without arguments:
  *      % ./cvsAdvDiff_bnd_omp 
- * If the user want to specify the number of threads to use
- *      % ./cvsAdvDiff_bnd_omp num_threads
- * where num_threads is the number of threads the user want to use 
- * -----------------------------------------------------------------
- */
+ * The environment variable can be over-ridden with a command line
+ * argument specifying the number of threads to use, e.g:
+ *      % ./cvsAdvDiff_bnd_omp 5
+ * ----------------------------------------------------------------- */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-/* Header files with a description of contents used in cvbanx.c */
+/* Header files with a description of contents */
 
 #include <cvodes/cvodes.h>             /* prototypes for CVODE fcts., consts. */
-#include <cvodes/cvodes_band.h>        /* prototype for CVBand */
-#include <nvector/nvector_openmp.h>  /* serial N_Vector types, fcts., macros */
-#include <sundials/sundials_band.h>  /* definitions of type DlsMat and macros */
-#include <sundials/sundials_types.h> /* definition of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS and EXP */
+#include <nvector/nvector_openmp.h>    /* serial N_Vector types, fcts., macros */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver */
+#include <cvodes/cvodes_direct.h>      /* access to CVDls interface */
+#include <sundials/sundials_types.h>   /* definition of type realtype */
+#include <sundials/sundials_math.h>    /* definition of ABS and EXP */
 
 #ifdef _OPENMP
 #include <omp.h>
@@ -113,10 +109,8 @@ static int check_flag(void *flagvalue, char *funcname, int opt);
 /* Functions Called by the Solver */
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector u, N_Vector fu, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /*
  *-------------------------------
@@ -129,6 +123,8 @@ int main(int argc, char *argv[])
   realtype dx, dy, reltol, abstol, t, tout, umax;
   N_Vector u;
   UserData data;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
   long int nst;
@@ -136,6 +132,8 @@ int main(int argc, char *argv[])
 
   u = NULL;
   data = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Set the number of threads to use */
@@ -143,11 +141,10 @@ int main(int argc, char *argv[])
 #ifdef _OPENMP
   num_threads = omp_get_max_threads();  /* Overwrite with OMP_NUM_THREADS environment variable */
 #endif
-  if (argc > 1)        /* overwrithe with command line value, if supplied */
+  if (argc > 1)        /* overwrite with command line value, if supplied */
     num_threads = strtol(argv[1], NULL, 0);
 
-  /* Create a serial vector */
-
+  /* Create an OpenMP vector */
   u = N_VNew_OpenMP(NEQ, num_threads);  /* Allocate u vector */
   if(check_flag((void*)u, "N_VNew_OpenMP", 0)) return(1);
 
@@ -185,13 +182,22 @@ int main(int argc, char *argv[])
   flag = CVodeSetUserData(cvode_mem, data);
   if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVBand to specify the CVBAND band linear solver */
-  flag = CVBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVBand", 1)) return(1);
+  /* Create banded SUNMatrix for use in linear solves -- since this will be factored, 
+     set the storage bandwidth to be the sum of upper and lower bandwidths */
+  A = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver object for use by CVode */
+  LS = SUNBandLinearSolver(u, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+  
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   /* Set the user-supplied Jacobian routine Jac */
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop over output points: call CVode, print results, test for errors */
 
@@ -212,6 +218,8 @@ int main(int argc, char *argv[])
 
   N_VDestroy_OpenMP(u);   /* Free the u vector */
   CVodeFree(&cvode_mem);  /* Free the integrator memory */
+  SUNLinSolFree(LS);      /* Free the linear solver memory */
+  SUNMatDestroy(A);       /* Free the matrix memory */
   free(data);             /* Free the user data */
 
   return(0);
@@ -270,12 +278,10 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
 
 /* Jacobian routine. Compute J(t,u). */
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector u, N_Vector fu, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype *kthCol, hordc, horac, verdc;
   UserData data;
   
@@ -294,19 +300,19 @@ static int Jac(long int N, long int mu, long int ml,
   horac = data->hacoef;
   verdc = data->vdcoef;
 
-#pragma omp parallel for collapse(2) default(shared) private(j, u, k, kthCol) num_threads(data->nthreads) 
+#pragma omp parallel for collapse(2) default(shared) private(i, j, k, kthCol) num_threads(data->nthreads) 
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
+      kthCol = SUNBandMatrix_Column(J,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = verdc;
     }
   }
 
diff --git a/examples/cvodes/parallel/CMakeLists.txt b/examples/cvodes/parallel/CMakeLists.txt
index 78ea644..49ab683 100644
--- a/examples/cvodes/parallel/CMakeLists.txt
+++ b/examples/cvodes/parallel/CMakeLists.txt
@@ -1,34 +1,33 @@
 # ---------------------------------------------------------------
-# $Revision: 4942 $
-# $Date: 2016-09-21 17:50:22 -0700 (Wed, 21 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for the CVODES parallel examples
+# CMakeLists.txt file for CVODES parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable CVODES_examples with the names of the parallel CVODES examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(CVODES_examples
-  "cvsAdvDiff_ASAp_non_p\;2\;2"
-  "cvsAdvDiff_FSA_non_p\;2\;2\;-sensi stg t"
-  "cvsAdvDiff_FSA_non_p\;2\;2\;-sensi sim t"
-  "cvsAdvDiff_non_p\;2\;2"
-  "cvsAtmDisp_ASAi_kry_bbd_p\;2\;8"
-  "cvsDiurnal_FSA_kry_p\;2\;4\;-sensi stg t"
-  "cvsDiurnal_FSA_kry_p\;2\;4\;-sensi sim t"
-  "cvsDiurnal_kry_bbd_p\;2\;4"
-  "cvsDiurnal_kry_p\;2\;4"
+  "cvsAdvDiff_ASAp_non_p\;\;2\;2\;develop"
+  "cvsAdvDiff_FSA_non_p\;-sensi stg t\;2\;2\;develop"
+  "cvsAdvDiff_FSA_non_p\;-sensi sim t\;2\;2\;develop"
+  "cvsAdvDiff_non_p\;\;2\;2\;develop"
+  "cvsAtmDisp_ASAi_kry_bbd_p\;\;2\;8\;develop"
+  "cvsDiurnal_FSA_kry_p\;-sensi stg t\;2\;4\;develop"
+  "cvsDiurnal_FSA_kry_p\;-sensi sim t\;2\;4\;develop"
+  "cvsDiurnal_kry_bbd_p\;\;2\;4\;develop"
+  "cvsDiurnal_kry_p\;\;2\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
@@ -38,76 +37,80 @@ SET(CVODES_examples
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODES_LIB sundials_cvodes_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODES_LIB sundials_cvodes_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${CVODES_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-# Add the build and install targets for each CVODES example
-
-# SGS is there a way to query CMAKE variable to get added executables 
-# rather than keeping our own list?
-SET(ADDED_EXECUTABLES "")
+# Add the build and install targets for each example
 FOREACH(example_tuple ${CVODES_examples})
-  # first item is example
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-
-  # Only need to add the executable once
-  LIST(FIND ADDED_EXECUTABLES ${example} index)
-  IF(index EQUAL -1)
-    LIST(APPEND ADDED_EXECUTABLES ${example})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
+    # folder to organize targets in an IDE
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  ENDIF(index EQUAL -1)
-
-  # Optional 4th element is test arguments
-  LIST(LENGTH example_tuple n)
-  IF(n EQUAL 4)
-    LIST(GET example_tuple 3 test_args)
-    STRING(REGEX REPLACE " " "_" test_name ${example}_${test_args})
-    SUNDIALS_ADD_TEST(${test_name} ${example} MPI_NPROCS ${number_of_tasks} TEST_ARGS ${test_args})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
   ELSE()
-    SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
   ENDIF()
 
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-  IF(NOT MPI_MPICC)
-    TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${test_name}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # find all .out files for this example
   FILE(GLOB example_out ${example}.out*)
+
+  # install example source and .out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example_out}
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${CVODES_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -116,34 +119,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "CVODES")
   SET(SOLVER_LIB "sundials_cvodes")
-  FOREACH(example_tuple ${CVODES_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${CVODES_examples})
 
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
-  list(REMOVE_DUPLICATES EXAMPLES)
+  EXAMPLES2STRING(CVODES_examples EXAMPLES)
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvodes/parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvodes/parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/cvodes/parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/cvodes/parallel/README b/examples/cvodes/parallel/README
index 3d032b5..d94a4fd 100644
--- a/examples/cvodes/parallel/README
+++ b/examples/cvodes/parallel/README
@@ -26,7 +26,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -37,7 +36,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -51,7 +53,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c
index 314f883..c68b016 100644
--- a/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c
+++ b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -77,9 +74,9 @@ typedef struct {
   realtype p[2];            /* model parameters                         */
   realtype dx;              /* spatial discretization grid              */
   realtype hdcoef, hacoef;  /* diffusion and advection coefficients     */
-  long int local_N;
-  long int npes, my_pe;     /* total number of processes and current ID */
-  long int nperpe, nrem;
+  sunindextype local_N;
+  int npes, my_pe;          /* total number of processes and current ID */
+  sunindextype nperpe, nrem;
   MPI_Comm comm;            /* MPI communicator                         */
   realtype *z1, *z2;        /* work space                               */
 } *UserData;
@@ -92,9 +89,9 @@ static int fB(realtype t, N_Vector u,
 
 /* Prototypes of private functions */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length, long int my_base);
-static void SetICback(N_Vector uB, long int my_base);
-static realtype Xintgr(realtype *z, long int l, realtype dx);
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length, sunindextype my_base);
+static void SetICback(N_Vector uB, sunindextype my_base);
+static realtype Xintgr(realtype *z, sunindextype l, realtype dx);
 static realtype Compute_g(N_Vector u, UserData data);
 static void PrintOutput(realtype g_val, N_Vector uB, UserData data);
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
@@ -119,7 +116,7 @@ int main(int argc, char *argv[])
 
   realtype dx, t, g_val;
   int flag, my_pe, nprocs, npes, ncheck;
-  long int local_N=0, nperpe, nrem, my_base=-1;
+  sunindextype local_N=0, nperpe, nrem, my_base=-1;
 
   MPI_Comm comm;
 
@@ -295,7 +292,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   realtype uLeft, uRight, ui, ult, urt;
   realtype hordc, horac, hdiff, hadv;
   realtype *udata, *dudata;
-  long int i, my_length;
+  sunindextype i, my_length;
   int npes, my_pe, my_pe_m1, my_pe_p1, last_pe, my_last;
   UserData data;
   MPI_Status status;
@@ -369,7 +366,7 @@ static int fB(realtype t, N_Vector u,
   realtype uLeft, uRight, ui, ult, urt;
   realtype dx, hordc, horac, hdiff, hadv;
   realtype *z1, *z2, intgr1, intgr2;
-  long int i, my_length;
+  sunindextype i, my_length;
   int npes, my_pe, my_pe_m1, my_pe_p1, last_pe, my_last;
   UserData data;
   realtype data_in[2], data_out[2];
@@ -500,10 +497,10 @@ static int fB(realtype t, N_Vector u,
  * Set initial conditions in u vector 
  */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length, long int my_base)
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length, sunindextype my_base)
 {
   int i;
-  long int iglobal;
+  sunindextype iglobal;
   realtype x;
   realtype *udata;
 
@@ -523,11 +520,11 @@ static void SetIC(N_Vector u, realtype dx, long int my_length, long int my_base)
  * Set final conditions in uB vector 
  */
 
-static void SetICback(N_Vector uB, long int my_base)
+static void SetICback(N_Vector uB, sunindextype my_base)
 {
   int i;
   realtype *uBdata;
-  long int my_length;
+  sunindextype my_length;
 
   /* Set pointer to data array and get local length of uB */
   uBdata = N_VGetArrayPointer_Parallel(uB);
@@ -542,10 +539,10 @@ static void SetICback(N_Vector uB, long int my_base)
  * Compute local value of the space integral int_x z(x) dx 
  */
 
-static realtype Xintgr(realtype *z, long int l, realtype dx)
+static realtype Xintgr(realtype *z, sunindextype l, realtype dx)
 {
   realtype my_intgr;
-  long int i;
+  sunindextype i;
 
   my_intgr = RCONST(0.5)*(z[0] + z[l-1]);
   for (i = 1; i < l-1; i++)
@@ -562,7 +559,7 @@ static realtype Xintgr(realtype *z, long int l, realtype dx)
 static realtype Compute_g(N_Vector u, UserData data)
 {
   realtype intgr, my_intgr, dx, *udata;
-  long int my_length;
+  sunindextype my_length;
   int npes, my_pe, i;
   MPI_Status status;
   MPI_Comm comm;
@@ -599,7 +596,7 @@ static void PrintOutput(realtype g_val, N_Vector uB, UserData data)
   MPI_Comm comm;
   MPI_Status status;
   int npes, my_pe;
-  long int i, Ni, indx, local_N, nperpe, nrem;
+  sunindextype i, Ni, indx, local_N, nperpe, nrem;
   realtype *uBdata;
   realtype *mu;
 
@@ -639,13 +636,13 @@ static void PrintOutput(realtype g_val, N_Vector uB, UserData data)
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
     for (i=0; i<NEQ; i++)
-      printf("  [%2ld]: %8Le\n", i+1, mu[i]);
+      printf("  [%2ld]: %8Le\n", (long int) i+1, mu[i]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
     for (i=0; i<NEQ; i++)
-      printf("  [%2ld]: %8e\n", i+1, mu[i]);
+      printf("  [%2ld]: %8e\n", (long int) i+1, mu[i]);
 #else
     for (i=0; i<NEQ; i++)
-      printf("  [%2ld]: %8e\n", i+1, mu[i]);
+      printf("  [%2ld]: %8e\n", (long int) i+1, mu[i]);
 #endif
 
     free(mu);
diff --git a/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out
index 63bdf03..8f2ebdb 100644
--- a/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out
+++ b/examples/cvodes/parallel/cvsAdvDiff_ASAp_non_p.out
@@ -1,27 +1,28 @@
-g(tf) = 2.446335e-02
- 
+
+g(tf) = 2.444739e-02
+
 dgdp(tf)
-  [ 1]: -1.502544e-01
-  [ 2]: -1.098456e-02
- 
+  [ 1]: -1.502107e-01
+  [ 2]: -1.097739e-02
+
 mu(t0)
-  [ 1]: 2.775571e-04
-  [ 2]: 5.625276e-04
-  [ 3]: 8.474242e-04
-  [ 4]: 1.127515e-03
-  [ 5]: 1.393257e-03
-  [ 6]: 1.641212e-03
-  [ 7]: 1.860490e-03
-  [ 8]: 2.049401e-03
-  [ 9]: 2.196614e-03
-  [10]: 2.302527e-03
-  [11]: 2.356404e-03
-  [12]: 2.360902e-03
-  [13]: 2.306966e-03
-  [14]: 2.199483e-03
-  [15]: 2.032115e-03
-  [16]: 1.811731e-03
-  [17]: 1.535589e-03
-  [18]: 1.212084e-03
-  [19]: 8.426858e-04
-  [20]: 4.366699e-04
+  [ 1]: 2.776607e-04
+  [ 2]: 5.619775e-04
+  [ 3]: 8.477404e-04
+  [ 4]: 1.126412e-03
+  [ 5]: 1.393777e-03
+  [ 6]: 1.639607e-03
+  [ 7]: 1.861184e-03
+  [ 8]: 2.047397e-03
+  [ 9]: 2.197434e-03
+  [10]: 2.300275e-03
+  [11]: 2.357283e-03
+  [12]: 2.358593e-03
+  [13]: 2.307827e-03
+  [14]: 2.197332e-03
+  [15]: 2.032873e-03
+  [16]: 1.809960e-03
+  [17]: 1.536162e-03
+  [18]: 1.210898e-03
+  [19]: 8.430003e-04
+  [20]: 4.362428e-04
diff --git a/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c
index 9026bad..d50da52 100644
--- a/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c
+++ b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George D. Byrne,
  *                and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -96,7 +93,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 static void ProcessArgs(int argc, char *argv[], int my_pe,
                         booleantype *sensi, int *sensi_meth, booleantype *err_con);
 static void WrongArgs(int my_pe, char *name);
-static void SetIC(N_Vector u, realtype dx, long int my_length, long int my_base);
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length, sunindextype my_base);
 static void PrintOutput(void *cvode_mem, int my_pe, realtype t, N_Vector u);
 static void PrintOutputS(int my_pe, N_Vector *uS);
 static void PrintFinalStats(void *cvode_mem, booleantype sensi); 
@@ -115,7 +112,7 @@ int main(int argc, char *argv[])
   UserData data;
   void *cvode_mem;
   int iout, flag, my_pe, npes;
-  long int local_N, nperpe, nrem, my_base;
+  sunindextype local_N, nperpe, nrem, my_base;
 
   realtype *pbar;
   int is, *plist;
@@ -371,16 +368,16 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 static void ProcessArgs(int argc, char *argv[], int my_pe,
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(my_pe, argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(my_pe, argv[0]);
   
@@ -399,9 +396,9 @@ static void ProcessArgs(int argc, char *argv[], int my_pe,
       WrongArgs(my_pe, argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(my_pe, argv[0]);
   }
@@ -423,11 +420,11 @@ static void WrongArgs(int my_pe, char *name)
  * Set initial conditions in u vector 
  */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length, 
-                  long int my_base)
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length, 
+                  sunindextype my_base)
 {
   int i;
-  long int iglobal;
+  sunindextype iglobal;
   realtype x;
   realtype *udata;
 
diff --git a/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.out b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p_-sensi_sim_t.out
similarity index 56%
rename from examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.out
rename to examples/cvodes/parallel/cvsAdvDiff_FSA_non_p_-sensi_sim_t.out
index 38f7830..a9ed7cd 100644
--- a/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p.out
+++ b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p_-sensi_sim_t.out
@@ -1,71 +1,71 @@
 
 1-D advection-diffusion equation, mesh size = 10 
 
-Number of PEs =   4 
+Number of PEs =   2 
 Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
 
 ============================================================
      T     Q       H      NST                    Max norm   
 ============================================================
-5.000e-01  4  7.656e-03   115
+5.000e-01  4  7.608e-03   115
                                 Solution         3.0529e+00 
                                 Sensitivity 1    3.8668e+00 
                                 Sensitivity 2    6.2020e-01 
 ------------------------------------------------------------
-1.000e+00  4  9.504e-03   182
+1.000e+00  4  3.343e-03   187
                                 Solution         8.7533e-01 
                                 Sensitivity 1    2.1743e+00 
                                 Sensitivity 2    1.8909e-01 
 ------------------------------------------------------------
-1.500e+00  3  4.221e-03   290
+1.500e+00  3  6.242e-03   250
                                 Solution         2.4949e-01 
                                 Sensitivity 1    9.1826e-01 
-                                Sensitivity 2    7.3922e-02 
+                                Sensitivity 2    7.3921e-02 
 ------------------------------------------------------------
-2.000e+00  2  8.301e-03   375
-                                Solution         7.1098e-02 
+2.000e+00  2  4.151e-03   337
+                                Solution         7.1095e-02 
                                 Sensitivity 1    3.4667e-01 
                                 Sensitivity 2    2.8228e-02 
 ------------------------------------------------------------
-2.500e+00  2  5.100e-03   450
-                                Solution         2.0260e-02 
-                                Sensitivity 1    1.2301e-01 
+2.500e+00  2  5.780e-03   408
+                                Solution         2.0259e-02 
+                                Sensitivity 1    1.2300e-01 
                                 Sensitivity 2    1.0085e-02 
 ------------------------------------------------------------
-3.000e+00  2  7.134e-03   514
-                                Solution         5.7728e-03 
-                                Sensitivity 1    4.1956e-02 
+3.000e+00  2  1.097e-02   475
+                                Solution         5.7729e-03 
+                                Sensitivity 1    4.1952e-02 
                                 Sensitivity 2    3.4555e-03 
 ------------------------------------------------------------
-3.500e+00  2  1.657e-02   586
+3.500e+00  2  1.228e-02   546
                                 Solution         1.6450e-03 
-                                Sensitivity 1    1.3921e-02 
+                                Sensitivity 1    1.3919e-02 
                                 Sensitivity 2    1.1669e-03 
 ------------------------------------------------------------
-4.000e+00  2  1.959e-02   656
-                                Solution         4.6877e-04 
-                                Sensitivity 1    4.5290e-03 
-                                Sensitivity 2    3.8631e-04 
+4.000e+00  2  5.824e-03   619
+                                Solution         4.6947e-04 
+                                Sensitivity 1    4.5317e-03 
+                                Sensitivity 2    3.8675e-04 
 ------------------------------------------------------------
-4.500e+00  1  5.326e-03   732
-                                Solution         1.3417e-04 
-                                Sensitivity 1    1.4551e-03 
-                                Sensitivity 2    1.2585e-04 
+4.500e+00  2  7.152e-03   691
+                                Solution         1.3412e-04 
+                                Sensitivity 1    1.4563e-03 
+                                Sensitivity 2    1.2582e-04 
 ------------------------------------------------------------
-5.000e+00  2  9.973e-03   814
-                                Solution         3.8672e-05 
-                                Sensitivity 1    4.6549e-04 
-                                Sensitivity 2    4.0632e-05 
+5.000e+00  1  4.407e-03   769
+                                Solution         3.8657e-05 
+                                Sensitivity 1    4.6496e-04 
+                                Sensitivity 2    4.0618e-05 
 ------------------------------------------------------------
 
 Final Statistics
 
-nst     =   814
+nst     =   769
 
-nfe     =  1462
-netf    =     2    nsetups  =     0
-nni     =  1458    ncfn     =   134
+nfe     =  1377
+netf    =     1    nsetups  =     0
+nni     =  1373    ncfn     =   128
 
-nfSe    =  2924    nfeS     =  5848
+nfSe    =  2754    nfeS     =  5508
 netfs   =     0    nsetupsS =     0
 nniS    =     0    ncfnS    =     0
diff --git a/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p_-sensi_stg_t.out b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p_-sensi_stg_t.out
new file mode 100644
index 0000000..18b236b
--- /dev/null
+++ b/examples/cvodes/parallel/cvsAdvDiff_FSA_non_p_-sensi_stg_t.out
@@ -0,0 +1,71 @@
+
+1-D advection-diffusion equation, mesh size = 10 
+
+Number of PEs =   2 
+Sensitivity: YES ( STAGGERED + FULL ERROR CONTROL )
+
+============================================================
+     T     Q       H      NST                    Max norm   
+============================================================
+5.000e-01  3  3.644e-03   173
+                                Solution         3.0529e+00 
+                                Sensitivity 1    3.8668e+00 
+                                Sensitivity 2    6.2020e-01 
+------------------------------------------------------------
+1.000e+00  3  3.644e-03   311
+                                Solution         8.7533e-01 
+                                Sensitivity 1    2.1743e+00 
+                                Sensitivity 2    1.8909e-01 
+------------------------------------------------------------
+1.500e+00  3  3.644e-03   448
+                                Solution         2.4950e-01 
+                                Sensitivity 1    9.1826e-01 
+                                Sensitivity 2    7.3922e-02 
+------------------------------------------------------------
+2.000e+00  3  3.644e-03   585
+                                Solution         7.1100e-02 
+                                Sensitivity 1    3.4668e-01 
+                                Sensitivity 2    2.8229e-02 
+------------------------------------------------------------
+2.500e+00  3  3.644e-03   722
+                                Solution         2.0258e-02 
+                                Sensitivity 1    1.2301e-01 
+                                Sensitivity 2    1.0086e-02 
+------------------------------------------------------------
+3.000e+00  3  3.644e-03   859
+                                Solution         5.7769e-03 
+                                Sensitivity 1    4.1952e-02 
+                                Sensitivity 2    3.4560e-03 
+------------------------------------------------------------
+3.500e+00  3  3.644e-03   997
+                                Solution         1.6481e-03 
+                                Sensitivity 1    1.3925e-02 
+                                Sensitivity 2    1.1671e-03 
+------------------------------------------------------------
+4.000e+00  3  3.644e-03  1134
+                                Solution         4.6462e-04 
+                                Sensitivity 1    4.5308e-03 
+                                Sensitivity 2    3.8641e-04 
+------------------------------------------------------------
+4.500e+00  3  3.644e-03  1271
+                                Solution         1.3272e-04 
+                                Sensitivity 1    1.4425e-03 
+                                Sensitivity 2    1.2542e-04 
+------------------------------------------------------------
+5.000e+00  3  3.644e-03  1408
+                                Solution         3.9376e-05 
+                                Sensitivity 1    4.5546e-04 
+                                Sensitivity 2    4.0107e-05 
+------------------------------------------------------------
+
+Final Statistics
+
+nst     =  1408
+
+nfe     =  3142
+netf    =     0    nsetups  =     0
+nni     =  1730    ncfn     =     0
+
+nfSe    =  3598    nfeS     =  7196
+netfs   =     0    nsetupsS =     0
+nniS    =  1795    ncfnS    =     0
diff --git a/examples/cvodes/parallel/cvsAdvDiff_non_p.c b/examples/cvodes/parallel/cvsAdvDiff_non_p.c
index 6ae6042..5883216 100644
--- a/examples/cvodes/parallel/cvsAdvDiff_non_p.c
+++ b/examples/cvodes/parallel/cvsAdvDiff_non_p.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George Byrne,
  *                and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -66,8 +63,8 @@ typedef struct {
 
 /* Private Helper Functions */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length,
-                  long int my_base);
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length,
+                  sunindextype my_base);
 
 static void PrintIntro(int npes);
 
@@ -92,7 +89,8 @@ int main(int argc, char *argv[])
   UserData data;
   void *cvode_mem;
   int iout, flag, my_pe, npes;
-  long int local_N, nperpe, nrem, my_base, nst;
+  long int nst;
+  sunindextype local_N, nperpe, nrem, my_base;
 
   MPI_Comm comm;
 
@@ -186,11 +184,11 @@ int main(int argc, char *argv[])
 
 /* Set initial conditions in u vector */
 
-static void SetIC(N_Vector u, realtype dx, long int my_length,
-                  long int my_base)
+static void SetIC(N_Vector u, realtype dx, sunindextype my_length,
+                  sunindextype my_base)
 {
   int i;
-  long int iglobal;
+  sunindextype iglobal;
   realtype x;
   realtype *udata;
 
diff --git a/examples/cvodes/parallel/cvsAdvDiff_non_p.out b/examples/cvodes/parallel/cvsAdvDiff_non_p.out
index be50625..58432f6 100644
--- a/examples/cvodes/parallel/cvsAdvDiff_non_p.out
+++ b/examples/cvodes/parallel/cvsAdvDiff_non_p.out
@@ -1,21 +1,21 @@
 
  1-D advection-diffusion equation, mesh size = 10 
 
- Number of PEs =   4 
+ Number of PEs =   2 
 
 At t = 0.00  max.norm(u) =  1.569909e+01  nst =   0 
 At t = 0.50  max.norm(u) =  3.052881e+00  nst = 113 
 At t = 1.00  max.norm(u) =  8.753188e-01  nst = 191 
 At t = 1.50  max.norm(u) =  2.494926e-01  nst = 265 
-At t = 2.00  max.norm(u) =  7.109707e-02  nst = 339 
-At t = 2.50  max.norm(u) =  2.026223e-02  nst = 418 
-At t = 3.00  max.norm(u) =  5.777332e-03  nst = 486 
-At t = 3.50  max.norm(u) =  1.650483e-03  nst = 563 
-At t = 4.00  max.norm(u) =  4.754357e-04  nst = 646 
-At t = 4.50  max.norm(u) =  1.374222e-04  nst = 715 
-At t = 5.00  max.norm(u) =  3.937469e-05  nst = 795 
+At t = 2.00  max.norm(u) =  7.109437e-02  nst = 332 
+At t = 2.50  max.norm(u) =  2.026176e-02  nst = 405 
+At t = 3.00  max.norm(u) =  5.769193e-03  nst = 468 
+At t = 3.50  max.norm(u) =  1.651582e-03  nst = 541 
+At t = 4.00  max.norm(u) =  4.764197e-04  nst = 623 
+At t = 4.50  max.norm(u) =  1.370219e-04  nst = 704 
+At t = 5.00  max.norm(u) =  3.990405e-05  nst = 785 
 
 Final Statistics: 
 
-nst = 795     nfe  = 1465    nni = 1461    ncfn = 146     netf = 5
+nst = 785     nfe  = 1442    nni = 1438    ncfn = 140     netf = 5
  
diff --git a/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c
index 58cbf00..cd1ab71 100644
--- a/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c
+++ b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.c
@@ -1,10 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4809 $
- * $Date: 2016-07-18 11:16:25 -0700 (Mon, 18 Jul 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Lukas Jager and Radu Serban @ LLNL
- *                Updated by Daniel R. Reynolds @ SMU
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Lukas Jager and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Parallel Krylov adjoint sensitivity example problem.
  * -----------------------------------------------------------------
@@ -16,8 +13,9 @@
 #include <limits.h>
 
 #include <cvodes/cvodes.h>
-#include <cvodes/cvodes_spgmr.h> 
+#include <cvodes/cvodes_spils.h> 
 #include <cvodes/cvodes_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h> 
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
@@ -168,7 +166,7 @@ typedef struct {
  */
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int f_local(long int Nlocal, realtype t, N_Vector y, 
+static int f_local(sunindextype Nlocal, realtype t, N_Vector y, 
                    N_Vector ydot, void *user_data);
 
 static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data);
@@ -176,7 +174,7 @@ static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data);
 
 static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, 
               void *user_dataB);
-static int fB_local(long int NlocalB, realtype t, 
+static int fB_local(sunindextype NlocalB, realtype t, 
                     N_Vector y, N_Vector yB, N_Vector yBdot, 
                     void *user_dataB);
 
@@ -190,9 +188,9 @@ static int fQB(realtype t, N_Vector y, N_Vector yB,
  */
 
 static void SetData(ProblemData d, MPI_Comm comm, int npes, int myId,
-                    long int *neq, long int *l_neq);
+                    sunindextype *neq, sunindextype *l_neq);
 static void SetSource(ProblemData d);
-static void f_comm(long int Nlocal, realtype t, N_Vector y, void *user_data);
+static void f_comm(sunindextype Nlocal, realtype t, N_Vector y, void *user_data);
 static void Load_yext(realtype *src, ProblemData d);
 static void PrintHeader();
 static void PrintFinalStats(void *cvode_mem);
@@ -212,17 +210,18 @@ int main(int argc, char *argv[])
   int npes, npes_needed;
   int myId;
  
-  long int neq, l_neq;
+  sunindextype neq, l_neq;
 
   void *cvode_mem;
+  SUNLinearSolver LS;
   N_Vector y, q;
   realtype abstol, reltol, abstolQ, reltolQ;
-  long int mudq, mldq, mukeep, mlkeep;
+  sunindextype mudq, mldq, mukeep, mlkeep;
 
   int indexB;
   N_Vector yB, qB;
   realtype abstolB, reltolB, abstolQB, reltolQB;
-  long int mudqB, mldqB, mukeepB, mlkeepB;
+  sunindextype mudqB, mldqB, mukeepB, mlkeepB;
 
   realtype tret, *qdata, G;
 
@@ -249,8 +248,8 @@ int main(int argc, char *argv[])
   }
 
   /* Test if matlab output is requested */
-  if (argc > 1) output = TRUE;
-  else          output = FALSE;
+  if (argc > 1) output = SUNTRUE;
+  else          output = SUNFALSE;
 
   /* Allocate and set problem data structure */
   d = (ProblemData) malloc(sizeof *d);
@@ -278,8 +277,9 @@ int main(int argc, char *argv[])
   reltol = RTOL;   
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
 
-  /* attach linear solver */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
+  /* create and attach linear solver */
+  LS = SUNSPGMR(y, PREC_LEFT, 0);
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
   
   /* Attach preconditioner and linear solver modules */
   mudq = mldq = d->l_m[0]+1;
@@ -293,7 +293,7 @@ int main(int argc, char *argv[])
   reltolQ = RTOL_Q;
   flag = CVodeQuadInit(cvode_mem, fQ, q);
   flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ);
-  flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+  flag = CVodeSetQuadErrCon(cvode_mem, SUNTRUE);
 
   /* Allocate space for the adjoint calculation */
   flag = CVodeAdjInit(cvode_mem, STEPS, CV_HERMITE);
@@ -309,8 +309,6 @@ int main(int argc, char *argv[])
   MPI_Allreduce(&qdata[0], &G, 1, PVEC_REAL_MPI_TYPE, MPI_SUM, comm);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   if (myId == 0) printf("  G = %Le\n",G);
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-  if (myId == 0) printf("  G = %e\n",G);
 #else
   if (myId == 0) printf("  G = %e\n",G);
 #endif
@@ -339,7 +337,7 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
 
   /* Attach preconditioner and linear solver modules */
-  flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0); 
+  flag = CVSpilsSetLinearSolverB(cvode_mem, indexB, LS);
   mudqB = mldqB = d->l_m[0]+1;
   mukeepB = mlkeepB = 2;  
   flag = CVBBDPrecInitB(cvode_mem, indexB, l_neq, mudqB, mldqB, 
@@ -350,7 +348,7 @@ int main(int argc, char *argv[])
   reltolQB = RTOL_QB;
   flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB);
   flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolQB, abstolQB);
-  flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE);
+  flag = CVodeSetQuadErrConB(cvode_mem, indexB, SUNTRUE);
 
   /* Integrate backwards */
   if (myId == 0) printf("Begin backward integration... ");
@@ -382,6 +380,7 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(yB);
 
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   MPI_Finalize();
 
@@ -402,7 +401,7 @@ int main(int argc, char *argv[])
  */
 
 static void SetData(ProblemData d, MPI_Comm comm, int npes, int myId,
-                    long int *neq, long int *l_neq)
+                    sunindextype *neq, sunindextype *l_neq)
 {
   int n[DIM], nd[DIM];
   int dim, size;
@@ -571,7 +570,7 @@ static void SetSource(ProblemData d)
  *------------------------------------------------------------------
  */
 
-static void f_comm(long int N_local, realtype t, N_Vector y, void *user_data)
+static void f_comm(sunindextype N_local, realtype t, N_Vector y, void *user_data)
 {
   int id, n[DIM], proc_cond[DIM], nbr[DIM][2];
   ProblemData d;
@@ -684,7 +683,7 @@ static void f_comm(long int N_local, realtype t, N_Vector y, void *user_data)
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
   ProblemData d;
-  long int l_neq=1;
+  sunindextype l_neq=1;
   int dim;
 
   d = (ProblemData) user_data;
@@ -699,7 +698,7 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   return(0);
 }
 
-static int f_local(long int Nlocal, realtype t, N_Vector y, 
+static int f_local(sunindextype Nlocal, realtype t, N_Vector y, 
                    N_Vector ydot, void *user_data)
 {
   realtype *Ydata, *dydata, *pdata;
@@ -823,7 +822,7 @@ static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot,
               void *user_dataB)
 {
   ProblemData d;
-  long int l_neq=1;
+  sunindextype l_neq=1;
   int dim;
 
   d = (ProblemData) user_dataB;
@@ -838,7 +837,7 @@ static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot,
   return(0);
 }
 
-static int fB_local(long int NlocalB, realtype t, 
+static int fB_local(sunindextype NlocalB, realtype t, 
                     N_Vector y, N_Vector yB, N_Vector dyB, 
                     void *user_dataB)
 {
@@ -1016,10 +1015,10 @@ static void PrintHeader()
 
 static void PrintFinalStats(void *cvode_mem)
 {
-  long int lenrw, leniw ;
-  long int lenrwSPGMR, leniwSPGMR;
+  long int lenrw, leniw;
+  long int lenrwLS, leniwLS;
   long int nst, nfe, nsetups, nni, ncfn, netf;
-  long int nli, npe, nps, ncfl, nfeSPGMR;
+  long int nli, npe, nps, ncfl, nfeLS;
   int flag;
 
   flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
@@ -1030,18 +1029,18 @@ static void PrintFinalStats(void *cvode_mem)
   flag = CVodeGetNumNonlinSolvIters(cvode_mem, &nni);
   flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
 
-  flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwSPGMR, &leniwSPGMR);
+  flag = CVSpilsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
   flag = CVSpilsGetNumLinIters(cvode_mem, &nli);
   flag = CVSpilsGetNumPrecEvals(cvode_mem, &npe);
   flag = CVSpilsGetNumPrecSolves(cvode_mem, &nps);
   flag = CVSpilsGetNumConvFails(cvode_mem, &ncfl);
-  flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeSPGMR);
+  flag = CVSpilsGetNumRhsEvals(cvode_mem, &nfeLS);
 
   printf("\nFinal Statistics.. \n\n");
   printf("lenrw   = %6ld     leniw = %6ld\n", lenrw, leniw);
-  printf("llrw    = %6ld     lliw  = %6ld\n", lenrwSPGMR, leniwSPGMR);
+  printf("llrw    = %6ld     lliw  = %6ld\n", lenrwLS, leniwLS);
   printf("nst     = %6ld\n"                  , nst);
-  printf("nfe     = %6ld     nfel  = %6ld\n"  , nfe, nfeSPGMR);
+  printf("nfe     = %6ld     nfel  = %6ld\n"  , nfe, nfeLS);
   printf("nni     = %6ld     nli   = %6ld\n"  , nni, nli);
   printf("nsetups = %6ld     netf  = %6ld\n"  , nsetups, netf);
   printf("npe     = %6ld     nps   = %6ld\n"  , npe, nps);
@@ -1097,8 +1096,6 @@ static void OutputGradient(int myId, N_Vector qB, ProblemData d)
     x[0] = xmin[0] + (m_start[0]+i[0]) * dx[0];
 #if defined(SUNDIALS_EXTENDED_PRECISION)
     fprintf(fid,"x%d(%d,1) = %Le; \n",  myId, i[0]+1, x[0]);
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-    fprintf(fid,"x%d(%d,1) = %le; \n",  myId, i[0]+1, x[0]);
 #else
     fprintf(fid,"x%d(%d,1) = %e; \n",  myId, i[0]+1, x[0]);
 #endif
@@ -1108,8 +1105,6 @@ static void OutputGradient(int myId, N_Vector qB, ProblemData d)
     x[1] = xmin[1] + (m_start[1]+i[1]) * dx[1];
 #if defined(SUNDIALS_EXTENDED_PRECISION)
     fprintf(fid,"y%d(%d,1) = %Le; \n",  myId, i[1]+1, x[1]);
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-    fprintf(fid,"y%d(%d,1) = %le; \n",  myId, i[1]+1, x[1]);
 #else
     fprintf(fid,"y%d(%d,1) = %e; \n",  myId, i[1]+1, x[1]);
 #endif
@@ -1120,8 +1115,6 @@ static void OutputGradient(int myId, N_Vector qB, ProblemData d)
     x[2] = xmin[2] + (m_start[2]+i[2]) * dx[2];
 #if defined(SUNDIALS_EXTENDED_PRECISION)
     fprintf(fid,"z%d(%d,1) = %Le; \n",  myId, i[2]+1, x[2]);
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-    fprintf(fid,"z%d(%d,1) = %le; \n",  myId, i[2]+1, x[2]);
 #else
     fprintf(fid,"z%d(%d,1) = %e; \n",  myId, i[2]+1, x[2]);
 #endif
@@ -1142,9 +1135,6 @@ static void OutputGradient(int myId, N_Vector qB, ProblemData d)
 #if defined(SUNDIALS_EXTENDED_PRECISION)
         fprintf(fid,"p%d(%d,%d,%d) = %Le; \n", myId, i[1]+1, i[0]+1, i[2]+1, p);
         fprintf(fid,"g%d(%d,%d,%d) = %Le; \n", myId, i[1]+1, i[0]+1, i[2]+1, g);
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-        fprintf(fid,"p%d(%d,%d,%d) = %le; \n", myId, i[1]+1, i[0]+1, i[2]+1, p);
-        fprintf(fid,"g%d(%d,%d,%d) = %le; \n", myId, i[1]+1, i[0]+1, i[2]+1, g);
 #else
         fprintf(fid,"p%d(%d,%d,%d) = %e; \n", myId, i[1]+1, i[0]+1, i[2]+1, p);
         fprintf(fid,"g%d(%d,%d,%d) = %e; \n", myId, i[1]+1, i[0]+1, i[2]+1, g);
@@ -1156,9 +1146,6 @@ static void OutputGradient(int myId, N_Vector qB, ProblemData d)
 #if defined(SUNDIALS_EXTENDED_PRECISION)
       fprintf(fid,"p%d(%d,%d) = %Le; \n", myId, i[1]+1, i[0]+1, p);
       fprintf(fid,"g%d(%d,%d) = %Le; \n", myId, i[1]+1, i[0]+1, g);
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-      fprintf(fid,"p%d(%d,%d) = %e; \n", myId, i[1]+1, i[0]+1, p);
-      fprintf(fid,"g%d(%d,%d) = %e; \n", myId, i[1]+1, i[0]+1, g);
 #else
       fprintf(fid,"p%d(%d,%d) = %e; \n", myId, i[1]+1, i[0]+1, p);
       fprintf(fid,"g%d(%d,%d) = %e; \n", myId, i[1]+1, i[0]+1, g);
diff --git a/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out
index cdcb067..16f68cb 100644
--- a/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out
+++ b/examples/cvodes/parallel/cvsAtmDisp_ASAi_kry_bbd_p.out
@@ -13,7 +13,7 @@ Begin forward integration... done.   G = 4.791513e+03
 Final Statistics.. 
 
 lenrw   =  65786     leniw =    372
-llrw    =  65656     lliw  =    160
+llrw    =  78782     lliw  =    202
 nst     =    174
 nfe     =    179     nfel  =    310
 nni     =    175     nli   =    310
@@ -26,7 +26,7 @@ Begin backward integration... done.
 Final Statistics.. 
 
 lenrw   = 131316     leniw =    372
-llrw    =  65656     lliw  =    160
+llrw    =  78782     lliw  =    202
 nst     =    118
 nfe     =    135     nfel  =    277
 nni     =    131     nli   =    277
diff --git a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c
index fcb6787..dbd425c 100644
--- a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c
+++ b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.c
@@ -1,9 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): S. D. Cohen, A. C. Hindmarsh, Radu Serban,
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                S. D. Cohen, A. C. Hindmarsh, Radu Serban,
  *                and M. R. Wittman @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -32,7 +30,7 @@
  * is neq = 2*MX*MY.
  *
  * The solution with CVODES is done with the BDF/GMRES method (i.e.
- * using the CVSPGMR linear solver) and the block-diagonal part of
+ * using the SUNSPGMR linear solver) and the block-diagonal part of
  * the Newton matrix as a left preconditioner. A copy of the
  * block-diagonal part of the Jacobian is saved and conditionally
  * reused within the Precond routine.
@@ -53,7 +51,7 @@
  * Note: This version uses MPI for user routines, and the CVODES
  *       solver. In what follows, N is the number of processors,
  *       N = NPEX*NPEY (see constants below) and it is assumed that
- *       the MPI script mpirun is used to run a paralles
+ *       the MPI script mpirun is used to run a parallel
  *       application.
  * If no sensitivities are desired:
  *    % mpirun -np N cvsDiurnal_FSA_kry_p -nosensi
@@ -69,12 +67,13 @@
 #include <math.h>
 #include <string.h>
 
-#include <cvodes/cvodes.h>            /* main CVODES header file */
-#include <cvodes/cvodes_spgmr.h>      /* defs. for CVSPGMR fcts. and constants */
-#include <nvector/nvector_parallel.h> /* defs of par. NVECTOR fcts. and macros */
-#include <sundials/sundials_dense.h>  /* generic DENSE solver used in prec. */
-#include <sundials/sundials_math.h>   /* contains macros SQR and EXP */
-#include <sundials/sundials_types.h>  /* def. of realtype */
+#include <cvodes/cvodes.h>              /* main CVODES header file */
+#include <cvodes/cvodes_spils.h>        /* defs. for CVSPILS fcts. and constants */
+#include <sunlinsol/sunlinsol_spgmr.h>  /* defs. for SUNSPGMR fcts. and constants */
+#include <nvector/nvector_parallel.h>   /* defs of par. NVECTOR fcts. and macros */
+#include <sundials/sundials_dense.h>    /* generic DENSE solver used in prec. */
+#include <sundials/sundials_math.h>     /* contains macros SQR and EXP */
+#include <sundials/sundials_types.h>    /* def. of realtype */
 
 #include <mpi.h>
 
@@ -142,12 +141,13 @@ typedef struct {
   realtype *p;
   realtype q4, om, dx, dy, hdco, haco, vdco;
   realtype uext[NVARS*(MXSUB+2)*(MYSUB+2)];
-  long int my_pe, isubx, isuby, nvmxsub, nvmxsub2;
+  int my_pe, isubx, isuby;
+  sunindextype nvmxsub, nvmxsub2;
   MPI_Comm comm;
 
   /* For preconditioner */
   realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
 
 } *UserData;
 
@@ -157,13 +157,11 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   realtype gamma, void *user_data);
 
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
-                  N_Vector r, N_Vector z, 
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  N_Vector r, N_Vector z, realtype gamma, 
+                  realtype delta, int lr, void *user_data);
 
 /* Private Helper Functions */
 
@@ -175,15 +173,14 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data);
 static void FreeUserData(UserData data);
 static void SetInitialProfiles(N_Vector u, UserData data);
 
-static void BSend(MPI_Comm comm, int my_pe, long int isubx, 
-                  long int isuby, long int dsizex, 
-                  long int dsizey, realtype udata[]);
+static void BSend(MPI_Comm comm, int my_pe, int isubx, 
+                  int isuby, sunindextype dsizex, 
+                  sunindextype dsizey, realtype udata[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
-                      long int isubx, long int isuby,
-                      long int dsizex, long int dsizey,
-                      realtype uext[], realtype buffer[]);
-static void BRecvWait(MPI_Request request[], long int isubx, long int isuby,
-                      long int dsizex, realtype uext[], realtype buffer[]);
+                      int isubx, int isuby, sunindextype dsizex,
+                      sunindextype dsizey, realtype uext[], realtype buffer[]);
+static void BRecvWait(MPI_Request request[], int isubx, int isuby,
+                      sunindextype dsizex, realtype uext[], realtype buffer[]);
 static void ucomm(realtype t, N_Vector u, UserData data);
 static void fcalc(realtype t, realtype udata[], realtype dudata[], UserData data);
 
@@ -204,9 +201,10 @@ int main(int argc, char *argv[])
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag, my_pe, npes;
-  long int neq, local_N;
+  sunindextype neq, local_N;
   MPI_Comm comm;
 
   realtype *pbar;
@@ -217,6 +215,7 @@ int main(int argc, char *argv[])
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
   pbar = NULL;
   plist = NULL;
@@ -276,9 +275,14 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) MPI_Abort(comm, 1);
 
-  /* Attach linear solver CVSPGMR */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if (check_flag(&flag, "CVSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Create SPGMR solver structure -- use left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+  
+  /* Attach linear solver to CVSpils interface */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
   if (check_flag(&flag, "CVSpilsSetPreconditioner", 1, my_pe)) MPI_Abort(comm, 1);
@@ -368,6 +372,7 @@ int main(int argc, char *argv[])
   }
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   MPI_Finalize();
 
@@ -409,12 +414,11 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MYSUB], **(*Jbd)[MYSUB];
-  long int *(*pivot)[MYSUB], ier, nvmxsub, offset;
+  sunindextype *(*pivot)[MYSUB], ier, nvmxsub, offset;
   int lx, ly, jx, jy, isubx, isuby;
   realtype *udata, **a, **j;
   UserData data;
@@ -440,14 +444,14 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
   VEL = data->p[6];
   KV0 = data->p[7];
 
-  if (jok) {  /* jok = TRUE: Copy Jbd to P */
+  if (jok) {  /* jok = SUNTRUE: Copy Jbd to P */
 
     for (ly = 0; ly < MYSUB; ly++)
       for (lx = 0; lx < MXSUB; lx++)
         denseCopy(Jbd[lx][ly], P[lx][ly], NVARS, NVARS);
-    *jcurPtr = FALSE;
+    *jcurPtr = SUNFALSE;
 
-  } else {    /* jok = FALSE: Generate Jbd from scratch and copy to P */
+  } else {    /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
 
     /* Make local copies of problem variables, for efficiency */
     q4coef = data->q4;
@@ -479,7 +483,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
     
-    *jcurPtr = TRUE;
+    *jcurPtr = SUNTRUE;
 
   }
 
@@ -505,12 +509,11 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
  */
 
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
-                  N_Vector r, N_Vector z, 
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  N_Vector r, N_Vector z, realtype gamma, 
+                  realtype delta, int lr, void *user_data)
 {
   realtype **(*P)[MYSUB];
-  long int *(*pivot)[MYSUB], nvmxsub;
+  sunindextype *(*pivot)[MYSUB], nvmxsub;
   int lx, ly;
   realtype *zdata, *v;
   UserData data;
@@ -551,16 +554,16 @@ static int PSolve(realtype tn, N_Vector u, N_Vector fu,
 static void ProcessArgs(int argc, char *argv[], int my_pe,
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(my_pe, argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(my_pe, argv[0]);
   
@@ -579,9 +582,9 @@ static void ProcessArgs(int argc, char *argv[], int my_pe,
       WrongArgs(my_pe, argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(my_pe, argv[0]);
   }
@@ -606,7 +609,7 @@ static void WrongArgs(int my_pe, char *name)
 
 static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
 {
-  long int isubx, isuby;
+  int isubx, isuby;
   int  lx, ly;
   realtype KH, VEL, KV0;
 
@@ -647,7 +650,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
     for (ly = 0; ly < MYSUB; ly++) {
       (data->P)[lx][ly] = newDenseMat(NVARS, NVARS);
       (data->Jbd)[lx][ly] = newDenseMat(NVARS, NVARS);
-      (data->pivot)[lx][ly] = newLintArray(NVARS);
+      (data->pivot)[lx][ly] = newIndexArray(NVARS);
     }
   }
 }
@@ -679,7 +682,8 @@ static void FreeUserData(UserData data)
 
 static void SetInitialProfiles(N_Vector u, UserData data)
 {
-  long int isubx, isuby, lx, ly, jx, jy, offset;
+  int isubx, isuby;
+  sunindextype lx, ly, jx, jy, offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *udata;
 
@@ -717,12 +721,12 @@ static void SetInitialProfiles(N_Vector u, UserData data)
  * Routine to send boundary data to neighboring PEs.
  */
 
-static void BSend(MPI_Comm comm, int my_pe, long int isubx, 
-                  long int isuby, long int dsizex, long int dsizey, 
+static void BSend(MPI_Comm comm, int my_pe, int isubx, 
+                  int isuby, sunindextype dsizex, sunindextype dsizey, 
                   realtype udata[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -768,11 +772,11 @@ static void BSend(MPI_Comm comm, int my_pe, long int isubx,
  */
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
-                      long int isubx, long int isuby,
-                      long int dsizex, long int dsizey,
+                      int isubx, int isuby,
+                      sunindextype dsizex, sunindextype dsizey,
                       realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
 
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
@@ -811,11 +815,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
  *  2) request should have 4 entries, and should be passed in both calls also. 
  */
 
-static void BRecvWait(MPI_Request request[], long int isubx, long int isuby,
-                      long int dsizex, realtype uext[], realtype buffer[])
+static void BRecvWait(MPI_Request request[], int isubx, int isuby,
+                      sunindextype dsizex, realtype uext[], realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
   
@@ -866,8 +870,8 @@ static void ucomm(realtype t, N_Vector u, UserData data)
 {
   realtype *udata, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
-  int my_pe;
-  long int isubx, isuby, nvmxsub, nvmysub;
+  int my_pe, isubx, isuby;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
 
   udata = N_VGetArrayPointer_Parallel(u);
@@ -902,8 +906,8 @@ static void fcalc(realtype t, realtype udata[], realtype dudata[], UserData data
   realtype c1rt, c2rt, cydn, cyup, hord1, hord2, horad1, horad2;
   realtype qq1, qq2, qq3, qq4, rkin1, rkin2, s, vertd1, vertd2, ydn, yup;
   realtype q4coef, dely, verdco, hordco, horaco;
-  int i, lx, ly, jx, jy;
-  long int isubx, isuby, nvmxsub, nvmxsub2, offsetu, offsetue;
+  int i, lx, ly, jx, jy, isubx, isuby;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
   realtype Q1, Q2, C3, A3, A4, KH, VEL, KV0;
 
   /* Get subgrid indices, data sizes, extended work array uext */
@@ -1041,7 +1045,7 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
   long int nst;
   int qu, flag;
   realtype hu, *udata, tempu[2];
-  long int npelast, i0, i1;
+  sunindextype npelast, i0, i1;
   MPI_Status status;
 
   npelast = NPEX*NPEY - 1;
@@ -1111,7 +1115,7 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
 static void PrintOutputS(int my_pe, MPI_Comm comm, N_Vector *uS)
 {
   realtype *sdata, temps[2];
-  long int npelast, i0, i1;
+  sunindextype npelast, i0, i1;
   MPI_Status status;
 
   npelast = NPEX*NPEY - 1;
diff --git a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p_-sensi_sim_t.out
similarity index 74%
copy from examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out
copy to examples/cvodes/parallel/cvsDiurnal_FSA_kry_p_-sensi_sim_t.out
index 6febb99..93f11b7 100644
--- a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out
+++ b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p_-sensi_sim_t.out
@@ -5,7 +5,7 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
 ========================================================================
      T     Q       H      NST                    Bottom left  Top right 
 ========================================================================
-7.200e+03  3  3.544e+01   415
+7.200e+03  3  3.475e+01   345
                                 Solution         1.0468e+04   1.1185e+04 
                                                  2.5267e+11   2.6998e+11 
                                 ----------------------------------------
@@ -13,19 +13,19 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                                  7.1177e+19   7.6556e+19 
                                 ----------------------------------------
                                 Sensitivity 2   -4.3853e+14  -5.0065e+14 
-                                                -2.4407e+18  -2.7842e+18 
+                                                -2.4407e+18  -2.7843e+18 
 ------------------------------------------------------------------------
-1.440e+04  3  4.903e+01   640
+1.440e+04  3  5.071e+01   862
                                 Solution         6.6590e+06   7.3008e+06 
                                                  2.5819e+11   2.8329e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -4.0848e+22  -4.4785e+22 
-                                                 5.9550e+22   6.7173e+22 
+                                                 5.9549e+22   6.7173e+22 
                                 ----------------------------------------
                                 Sensitivity 2   -4.5235e+17  -5.4318e+17 
-                                                -6.5419e+21  -7.8316e+21 
+                                                -6.5418e+21  -7.8315e+21 
 ------------------------------------------------------------------------
-2.160e+04  2  2.948e+01  1198
+2.160e+04  3  5.422e+01  1115
                                 Solution         2.6650e+07   2.9308e+07 
                                                  2.9928e+11   3.3134e+11 
                                 ----------------------------------------
@@ -33,107 +33,107 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                                  3.8203e+23   4.4991e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -7.6601e+18  -9.4433e+18 
-                                                -7.6459e+22  -9.4502e+22 
+                                                -7.6459e+22  -9.4501e+22 
 ------------------------------------------------------------------------
-2.880e+04  3  4.499e+01  1542
+2.880e+04  3  4.027e+01  1446
                                 Solution         8.7021e+06   9.6501e+06 
                                                  3.3804e+11   3.7510e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -5.3375e+22  -5.9188e+22 
+                                Sensitivity 1   -5.3375e+22  -5.9187e+22 
                                                  5.4487e+23   6.7430e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -4.8855e+18  -6.1040e+18 
                                                 -1.7194e+23  -2.1518e+23 
 ------------------------------------------------------------------------
-3.600e+04  3  1.107e+01  1675
+3.600e+04  4  6.446e+01  1550
                                 Solution         1.4040e+04   1.5609e+04 
                                                  3.3868e+11   3.7652e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -8.6141e+19  -9.5761e+19 
+                                Sensitivity 1   -8.6141e+19  -9.5762e+19 
                                                  5.2718e+23   6.6030e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -8.4328e+15  -1.0549e+16 
                                                 -1.8439e+23  -2.3096e+23 
 ------------------------------------------------------------------------
-4.320e+04  4  8.016e+01  3146
-                                Solution        -2.5802e-07  -2.3679e-07 
+4.320e+04  4  1.552e+02  1802
+                                Solution        -6.7943e-09  -1.7531e-08 
                                                  3.3823e+11   3.8035e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -3.4238e+08  -3.8876e+08 
+                                Sensitivity 1    1.5377e+08  -1.8226e+09 
                                                  5.2753e+23   6.7448e+23 
                                 ----------------------------------------
-                                Sensitivity 2    5.4404e+03   6.6262e+03 
+                                Sensitivity 2    4.9296e+03  -1.7707e+04 
                                                 -1.8454e+23  -2.3595e+23 
 ------------------------------------------------------------------------
-5.040e+04  4  2.431e+02  3194
-                                Solution         8.0708e-08   7.0502e-08 
+5.040e+04  4  1.552e+02  1848
+                                Solution        -3.3333e-09  -1.0074e-08 
                                                  3.3582e+11   3.8645e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -4.5550e+10  -3.9697e+10 
+                                Sensitivity 1    7.6593e+08   2.3212e+09 
                                                  5.2067e+23   6.9664e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -5.5727e+08  -5.5845e+08 
-                                                -1.8214e+23  -2.4371e+23 
+                                Sensitivity 2    3.2953e+07   1.2254e+08 
+                                                -1.8214e+23  -2.4370e+23 
 ------------------------------------------------------------------------
-5.760e+04  4  2.523e+02  3216
-                                Solution        -1.8957e-11  -1.6762e-11 
+5.760e+04  5  2.333e+02  1871
+                                Solution        -8.0165e-13  -2.6806e-12 
                                                  3.3203e+11   3.9090e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -1.5940e+06  -1.4035e+06 
+                                Sensitivity 1   -1.3115e+05  -4.2823e+05 
                                                  5.0825e+23   7.1205e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -2.2867e+02  -2.2722e+02 
+                                Sensitivity 2    6.8742e+01   1.6059e+02 
                                                 -1.7780e+23  -2.4910e+23 
 ------------------------------------------------------------------------
-6.480e+04  4  2.820e+02  3254
-                                Solution        -7.8717e-10  -6.7017e-10 
+6.480e+04  5  2.801e+02  1893
+                                Solution        -2.8173e-08  -9.8429e-08 
                                                  3.3130e+11   3.9634e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -3.4373e+07  -2.1671e+07 
+                                Sensitivity 1    2.2918e+09   7.9585e+09 
                                                  5.0442e+23   7.3274e+23 
                                 ----------------------------------------
-                                Sensitivity 2    1.3198e+08   1.3575e+08 
+                                Sensitivity 2    7.1238e+05   2.7790e+06 
                                                 -1.7646e+23  -2.5633e+23 
 ------------------------------------------------------------------------
-7.200e+04  4  3.810e+02  3276
-                                Solution        -4.4006e-09  -3.7463e-09 
+7.200e+04  4  1.003e+02  2580
+                                Solution        -1.1403e-08  -6.9110e-08 
                                                  3.3297e+11   4.0389e+11 
                                 ----------------------------------------
-                                Sensitivity 1    4.5106e+09   3.8200e+09 
+                                Sensitivity 1    6.8126e+08   4.1340e+09 
                                                  5.0783e+23   7.6382e+23 
                                 ----------------------------------------
-                                Sensitivity 2    2.0264e+05   2.0791e+05 
+                                Sensitivity 2   -3.8340e+07  -2.6839e+08 
                                                 -1.7765e+23  -2.6721e+23 
 ------------------------------------------------------------------------
-7.920e+04  5  6.406e+02  3291
-                                Solution        -1.8328e-11  -1.5666e-11 
+7.920e+04  4  4.453e+02  2608
+                                Solution         4.8775e-18   2.7563e-17 
                                                  3.3344e+11   4.1203e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.3650e+07   1.1729e+07 
+                                Sensitivity 1    1.2984e+02   7.7701e+02 
                                                  5.0730e+23   7.9960e+23 
                                 ----------------------------------------
-                                Sensitivity 2    6.1764e+01   6.8476e+01 
+                                Sensitivity 2   -4.4037e-01  -3.1248e+00 
                                                 -1.7747e+23  -2.7972e+23 
 ------------------------------------------------------------------------
-8.640e+04  5  6.406e+02  3302
-                                Solution        -2.0206e-13  -1.7557e-13 
+8.640e+04  5  7.396e+02  2619
+                                Solution        -2.5590e-20  -1.5317e-19 
                                                  3.3518e+11   4.1625e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.1323e+06   9.7319e+05 
+                                Sensitivity 1    1.6342e+00   9.8016e+00 
                                                  5.1171e+23   8.2142e+23 
                                 ----------------------------------------
-                                Sensitivity 2    7.6632e+00   8.2818e+00 
+                                Sensitivity 2   -5.6895e-03  -4.0306e-02 
                                                 -1.7901e+23  -2.8736e+23 
 ------------------------------------------------------------------------
 
 Final Statistics
 
-nst     =  3302
+nst     =  2619
 
-nfe     =  4387
-netf    =   165    nsetups  =   508
-nni     =  4383    ncfn     =     7
+nfe     =  3583
+netf    =   150    nsetups  =   436
+nni     =  3580    ncfn     =     6
 
-nfSe    =  8774    nfeS     = 17548
+nfSe    =  7166    nfeS     = 14332
 netfs   =     0    nsetupsS =     0
 nniS    =     0    ncfnS    =     0
diff --git a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p_-sensi_stg_t.out
similarity index 68%
rename from examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out
rename to examples/cvodes/parallel/cvsDiurnal_FSA_kry_p_-sensi_stg_t.out
index 6febb99..e9c2087 100644
--- a/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p.out
+++ b/examples/cvodes/parallel/cvsDiurnal_FSA_kry_p_-sensi_stg_t.out
@@ -1,31 +1,31 @@
 
 2-species diurnal advection-diffusion problem
-Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+Sensitivity: YES ( STAGGERED + FULL ERROR CONTROL )
 
 ========================================================================
      T     Q       H      NST                    Bottom left  Top right 
 ========================================================================
-7.200e+03  3  3.544e+01   415
+7.200e+03  4  3.901e+01   463
                                 Solution         1.0468e+04   1.1185e+04 
                                                  2.5267e+11   2.6998e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -6.4201e+19  -6.8598e+19 
-                                                 7.1177e+19   7.6556e+19 
+                                                 7.1178e+19   7.6557e+19 
                                 ----------------------------------------
                                 Sensitivity 2   -4.3853e+14  -5.0065e+14 
-                                                -2.4407e+18  -2.7842e+18 
+                                                -2.4408e+18  -2.7843e+18 
 ------------------------------------------------------------------------
-1.440e+04  3  4.903e+01   640
+1.440e+04  3  1.314e+02   528
                                 Solution         6.6590e+06   7.3008e+06 
                                                  2.5819e+11   2.8329e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -4.0848e+22  -4.4785e+22 
-                                                 5.9550e+22   6.7173e+22 
+                                                 5.9549e+22   6.7173e+22 
                                 ----------------------------------------
-                                Sensitivity 2   -4.5235e+17  -5.4318e+17 
-                                                -6.5419e+21  -7.8316e+21 
+                                Sensitivity 2   -4.5235e+17  -5.4317e+17 
+                                                -6.5418e+21  -7.8315e+21 
 ------------------------------------------------------------------------
-2.160e+04  2  2.948e+01  1198
+2.160e+04  4  1.341e+02   609
                                 Solution         2.6650e+07   2.9308e+07 
                                                  2.9928e+11   3.3134e+11 
                                 ----------------------------------------
@@ -35,7 +35,7 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                 Sensitivity 2   -7.6601e+18  -9.4433e+18 
                                                 -7.6459e+22  -9.4502e+22 
 ------------------------------------------------------------------------
-2.880e+04  3  4.499e+01  1542
+2.880e+04  4  1.717e+02   660
                                 Solution         8.7021e+06   9.6501e+06 
                                                  3.3804e+11   3.7510e+11 
                                 ----------------------------------------
@@ -45,95 +45,95 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                 Sensitivity 2   -4.8855e+18  -6.1040e+18 
                                                 -1.7194e+23  -2.1518e+23 
 ------------------------------------------------------------------------
-3.600e+04  3  1.107e+01  1675
+3.600e+04  4  6.657e+01   709
                                 Solution         1.4040e+04   1.5609e+04 
                                                  3.3868e+11   3.7652e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -8.6141e+19  -9.5761e+19 
+                                Sensitivity 1   -8.6141e+19  -9.5762e+19 
                                                  5.2718e+23   6.6030e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -8.4328e+15  -1.0549e+16 
                                                 -1.8439e+23  -2.3096e+23 
 ------------------------------------------------------------------------
-4.320e+04  4  8.016e+01  3146
-                                Solution        -2.5802e-07  -2.3679e-07 
+4.320e+04  3  7.880e+01   783
+                                Solution        -3.8234e-09  -2.8269e-08 
                                                  3.3823e+11   3.8035e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -3.4238e+08  -3.8876e+08 
+                                Sensitivity 1    2.6858e+07   1.8140e+08 
                                                  5.2753e+23   6.7448e+23 
                                 ----------------------------------------
-                                Sensitivity 2    5.4404e+03   6.6262e+03 
-                                                -1.8454e+23  -2.3595e+23 
+                                Sensitivity 2    6.2362e+05   9.0367e+05 
+                                                -1.8455e+23  -2.3595e+23 
 ------------------------------------------------------------------------
-5.040e+04  4  2.431e+02  3194
-                                Solution         8.0708e-08   7.0502e-08 
+5.040e+04  4  3.196e+02   836
+                                Solution        -4.1375e-16  -1.0519e-15 
                                                  3.3582e+11   3.8645e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -4.5550e+10  -3.9697e+10 
-                                                 5.2067e+23   6.9664e+23 
+                                Sensitivity 1   -3.9513e+08  -1.1101e+09 
+                                                 5.2067e+23   6.9665e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -5.5727e+08  -5.5845e+08 
+                                Sensitivity 2    2.6920e+06   3.1515e+06 
                                                 -1.8214e+23  -2.4371e+23 
 ------------------------------------------------------------------------
-5.760e+04  4  2.523e+02  3216
-                                Solution        -1.8957e-11  -1.6762e-11 
+5.760e+04  5  3.771e+02   853
+                                Solution         3.6773e-19   9.5216e-19 
                                                  3.3203e+11   3.9090e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -1.5940e+06  -1.4035e+06 
-                                                 5.0825e+23   7.1205e+23 
+                                Sensitivity 1   -1.1148e+05  -3.1344e+05 
+                                                 5.0825e+23   7.1206e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -2.2867e+02  -2.2722e+02 
+                                Sensitivity 2   -4.8215e+05  -5.6349e+05 
                                                 -1.7780e+23  -2.4910e+23 
 ------------------------------------------------------------------------
-6.480e+04  4  2.820e+02  3254
-                                Solution        -7.8717e-10  -6.7017e-10 
+6.480e+04  5  3.560e+02   890
+                                Solution        -5.0783e-09  -1.3227e-08 
                                                  3.3130e+11   3.9634e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -3.4373e+07  -2.1671e+07 
+                                Sensitivity 1    3.1033e+07   8.0824e+07 
                                                  5.0442e+23   7.3274e+23 
                                 ----------------------------------------
-                                Sensitivity 2    1.3198e+08   1.3575e+08 
+                                Sensitivity 2    2.8698e+08   3.4626e+08 
                                                 -1.7646e+23  -2.5633e+23 
 ------------------------------------------------------------------------
-7.200e+04  4  3.810e+02  3276
-                                Solution        -4.4006e-09  -3.7463e-09 
+7.200e+04  3  1.979e+02   932
+                                Solution         2.6622e-12   6.9771e-12 
                                                  3.3297e+11   4.0389e+11 
                                 ----------------------------------------
-                                Sensitivity 1    4.5106e+09   3.8200e+09 
-                                                 5.0783e+23   7.6382e+23 
+                                Sensitivity 1    4.2760e+08   1.0895e+09 
+                                                 5.0784e+23   7.6382e+23 
                                 ----------------------------------------
-                                Sensitivity 2    2.0264e+05   2.0791e+05 
-                                                -1.7765e+23  -2.6721e+23 
+                                Sensitivity 2    3.5387e+08   6.9760e+08 
+                                                -1.7766e+23  -2.6721e+23 
 ------------------------------------------------------------------------
-7.920e+04  5  6.406e+02  3291
-                                Solution        -1.8328e-11  -1.5666e-11 
+7.920e+04  5  5.363e+02   951
+                                Solution         7.6032e-12  -6.8644e-12 
                                                  3.3344e+11   4.1203e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.3650e+07   1.1729e+07 
-                                                 5.0730e+23   7.9960e+23 
+                                Sensitivity 1   -1.6504e+08  -4.1309e+08 
+                                                 5.0731e+23   7.9960e+23 
                                 ----------------------------------------
-                                Sensitivity 2    6.1764e+01   6.8476e+01 
+                                Sensitivity 2   -1.3631e+08  -2.7650e+08 
                                                 -1.7747e+23  -2.7972e+23 
 ------------------------------------------------------------------------
-8.640e+04  5  6.406e+02  3302
-                                Solution        -2.0206e-13  -1.7557e-13 
+8.640e+04  5  5.363e+02   965
+                                Solution         4.5357e-13  -1.3786e-12 
                                                  3.3518e+11   4.1625e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.1323e+06   9.7319e+05 
-                                                 5.1171e+23   8.2142e+23 
+                                Sensitivity 1   -6.1339e+06  -1.5394e+07 
+                                                 5.1171e+23   8.2143e+23 
                                 ----------------------------------------
-                                Sensitivity 2    7.6632e+00   8.2818e+00 
+                                Sensitivity 2   -5.2285e+06  -1.0563e+07 
                                                 -1.7901e+23  -2.8736e+23 
 ------------------------------------------------------------------------
 
 Final Statistics
 
-nst     =  3302
+nst     =   965
 
-nfe     =  4387
-netf    =   165    nsetups  =   508
-nni     =  4383    ncfn     =     7
+nfe     =  2092
+netf    =    12    nsetups  =   146
+nni     =  1092    ncfn     =     0
 
-nfSe    =  8774    nfeS     = 17548
-netfs   =     0    nsetupsS =     0
-nniS    =     0    ncfnS    =     0
+nfSe    =  2288    nfeS     =  4576
+netfs   =    32    nsetupsS =     0
+nniS    =  1141    ncfnS    =     0
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c
index c167b8c..32b7c51 100644
--- a/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.c
@@ -1,9 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
  *                Radu Serban  @ LLNL
  * --------------------------------------------------------------------
  * Example problem:
@@ -32,7 +30,7 @@
  * neq = 2*MX*MY.
  *
  * The solution is done with the BDF/GMRES method (i.e. using the
- * CVSPGMR linear solver) and a block-diagonal matrix with banded
+ * SUNSPGMR linear solver) and a block-diagonal matrix with banded
  * blocks as a preconditioner, using the CVBBDPRE module.
  * Each block is generated using difference quotients, with
  * half-bandwidths mudq = mldq = 2*MXSUB, but the retained banded
@@ -55,14 +53,15 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>            /* prototypes for CVODE fcts. */
-#include <cvodes/cvodes_spgmr.h>      /* prototypes and constants for CVSPGMR solver */
-#include <cvodes/cvodes_bbdpre.h>     /* prototypes for CVBBDPRE module */
-#include <nvector/nvector_parallel.h> /* definition N_Vector and macro NV_DATA_P */
-#include <sundials/sundials_types.h>  /* definitions of realtype, booleantype */
-#include <sundials/sundials_math.h>   /* definition of macros SUNSQR and EXP */
+#include <cvodes/cvodes.h>              /* prototypes for CVODE fcts. */
+#include <cvodes/cvodes_spils.h>        /* prototypes and constants for CVSpils interface */
+#include <cvodes/cvodes_bbdpre.h>       /* prototypes for CVBBDPRE module */
+#include <sunlinsol/sunlinsol_spgmr.h>  /* prototypes and constants for SUNSPGMR solver */
+#include <nvector/nvector_parallel.h>   /* definition N_Vector */
+#include <sundials/sundials_types.h>    /* definitions of realtype, booleantype */
+#include <sundials/sundials_math.h>     /* definition of macros SUNSQR and EXP */
 
-#include <mpi.h>                      /* MPI constants and types */
+#include <mpi.h>                        /* MPI constants and types */
 
 
 /* Problem Constants */
@@ -116,31 +115,31 @@ typedef struct {
   realtype q4, om, dx, dy, hdco, haco, vdco;
   realtype uext[NVARS*(MXSUB+2)*(MYSUB+2)];
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmxsub2, Nlocal;
+  sunindextype nvmxsub, nvmxsub2, Nlocal;
   MPI_Comm comm;
 } *UserData;
 
 /* Prototypes of private helper functions */
 
-static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+static void InitUserData(int my_pe, sunindextype local_N, MPI_Comm comm,
                          UserData data);
 static void SetInitialProfiles(N_Vector u, UserData data);
-static void PrintIntro(int npes, long int mudq, long int mldq,
-		       long int mukeep, long int mlkeep);
+static void PrintIntro(int npes, sunindextype mudq, sunindextype mldq,
+		       sunindextype mukeep, sunindextype mlkeep);
 static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
                         N_Vector u, realtype t);
 static void PrintFinalStats(void *cvode_mem);
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype uarray[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[]);
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[]);
 
 static void fucomm(realtype t, N_Vector u, void *user_data);
@@ -151,7 +150,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
 /* Prototype of functions called by the CVBBDPRE module */
 
-static int flocal(long int Nlocal, realtype t, N_Vector u,
+static int flocal(sunindextype Nlocal, realtype t, N_Vector u,
                   N_Vector udot, void *user_data);
 
 /* Private function to check function return values */
@@ -163,14 +162,16 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   realtype abstol, reltol, t, tout;
   N_Vector u;
   int iout, my_pe, npes, flag, jpre;
-  long int neq, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype neq, local_N, mudq, mldq, mukeep, mlkeep;
   MPI_Comm comm;
 
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
   u = NULL;
 
@@ -226,10 +227,14 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR with left
-     preconditioning and the default maximum Krylov dimension maxl  */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVBBDSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Create SPGMR solver structure -- use left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+  
+  /* Attach the linear solver to the CVSpils interface */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if(check_flag(&flag, "CVSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Initialize BBD preconditioner */
   mudq = mldq = NVARS*MXSUB;
@@ -244,7 +249,8 @@ int main(int argc, char *argv[])
   /* Loop over jpre (= PREC_LEFT, PREC_RIGHT), and solve the problem */
   for (jpre = PREC_LEFT; jpre <= PREC_RIGHT; jpre++) {
 
-  /* On second run, re-initialize u, the integrator, CVBBDPRE, and CVSPGMR */
+  /* On second run, re-initialize u, the integrator, CVBBDPRE, 
+     and preconditioning type */
 
   if (jpre == PREC_RIGHT) {
 
@@ -256,8 +262,8 @@ int main(int argc, char *argv[])
     flag = CVBBDPrecReInit(cvode_mem, mudq, mldq, ZERO);
     if(check_flag(&flag, "CVBBDPrecReInit", 1, my_pe)) MPI_Abort(comm, 1);
 
-    flag = CVSpilsSetPrecType(cvode_mem, PREC_RIGHT);
-    check_flag(&flag, "CVSpilsSetPrecType", 1, my_pe);
+    flag = SUNSPGMRSetPrecType(LS, PREC_RIGHT);
+    check_flag(&flag, "SUNSPGMRSetPrecType", 1, my_pe);
 
     if (my_pe == 0) {
       printf("\n\n-------------------------------------------------------");
@@ -290,6 +296,7 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(u);
   free(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   MPI_Finalize();
 
@@ -300,7 +307,7 @@ int main(int argc, char *argv[])
 
 /* Load constants in data */
 
-static void InitUserData(int my_pe, long int local_N, MPI_Comm comm,
+static void InitUserData(int my_pe, sunindextype local_N, MPI_Comm comm,
                          UserData data)
 {
   int isubx, isuby;
@@ -333,7 +340,7 @@ static void SetInitialProfiles(N_Vector u, UserData data)
 {
   int isubx, isuby;
   int lx, ly, jx, jy;
-  long int offset;
+  sunindextype offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *uarray;
 
@@ -372,16 +379,16 @@ static void SetInitialProfiles(N_Vector u, UserData data)
 
 /* Print problem introduction */
 
-static void PrintIntro(int npes, long int mudq, long int mldq,
-		       long int mukeep, long int mlkeep)
+static void PrintIntro(int npes, sunindextype mudq, sunindextype mldq,
+		       sunindextype mukeep, sunindextype mlkeep)
 {
   printf("\n2-species diurnal advection-diffusion problem\n");
   printf("  %d by %d mesh on %d processors\n", MX, MY, npes);
   printf("  Using CVBBDPRE preconditioner module\n");
   printf("    Difference-quotient half-bandwidths are");
-  printf(" mudq = %ld,  mldq = %ld\n", mudq, mldq);
+  printf(" mudq = %ld,  mldq = %ld\n", (long int) mudq, (long int) mldq);
   printf("    Retained band block half-bandwidths are");
-  printf(" mukeep = %ld,  mlkeep = %ld", mukeep, mlkeep);
+  printf(" mukeep = %ld,  mlkeep = %ld", (long int) mukeep, (long int) mlkeep);
 
   return;
 }
@@ -392,7 +399,8 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
                         N_Vector u, realtype t)
 {
   int qu, flag, npelast;
-  long int i0, i1, nst;
+  sunindextype i0, i1;
+  long int nst;
   realtype hu, *uarray, tempu[2];
   MPI_Status status;
 
@@ -447,9 +455,9 @@ static void PrintFinalStats(void *cvode_mem)
 {
   long int lenrw, leniw ;
   long int lenrwLS, leniwLS;
-  long int lenrwBBDP, leniwBBDP, ngevalsBBDP;
+  long int lenrwBBDP, leniwBBDP;
   long int nst, nfe, nsetups, nni, ncfn, netf;
-  long int nli, npe, nps, ncfl, nfeLS;
+  long int nli, npe, nps, ncfl, nfeLS, ngevalsBBDP;
   int flag;
 
   flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
@@ -481,9 +489,9 @@ static void PrintFinalStats(void *cvode_mem)
   check_flag(&flag, "CVSpilsGetNumRhsEvals", 1, 0);
 
   printf("\nFinal Statistics: \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwls = %5ld     leniwls = %5ld\n", lenrwLS, leniwLS);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwls = %5ld     leniwls = %5ld\n"  , lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfels   = %5ld\n"  , nfe, nfeLS);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
   printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
@@ -503,11 +511,11 @@ static void PrintFinalStats(void *cvode_mem)
 
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype uarray[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -557,10 +565,10 @@ static void BSend(MPI_Comm comm,
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
 
@@ -599,11 +607,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[],
 
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
 
@@ -653,7 +661,7 @@ static void fucomm(realtype t, N_Vector u, void *user_data)
   realtype *uarray, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmysub;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
 
   data = (UserData) user_data;
@@ -708,7 +716,7 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
    inter-processor communication of data needed to calculate f has already
    been done, and this data is in the work array uext.                    */
 
-static int flocal(long int Nlocal, realtype t, N_Vector u,
+static int flocal(sunindextype Nlocal, realtype t, N_Vector u,
                   N_Vector udot, void *user_data)
 {
   realtype *uext;
@@ -718,7 +726,7 @@ static int flocal(long int Nlocal, realtype t, N_Vector u,
   realtype q4coef, dely, verdco, hordco, horaco;
   int i, lx, ly, jx, jy;
   int isubx, isuby;
-  long int nvmxsub, nvmxsub2, offsetu, offsetue;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
   UserData data;
   realtype *uarray, *duarray;
 
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out
index 9388508..aa33d8e 100644
--- a/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_bbd_p.out
@@ -19,55 +19,55 @@ t = 2.16e+04   no. steps = 247   order = 5   stepsize = 3.00e+02
 At bottom left:  c1, c2 =    2.665e+07    2.993e+11 
 At top right:    c1, c2 =    2.931e+07    3.313e+11 
 
-t = 2.88e+04   no. steps = 272   order = 4   stepsize = 4.05e+02
+t = 2.88e+04   no. steps = 272   order = 4   stepsize = 2.13e+02
 At bottom left:  c1, c2 =    8.702e+06    3.380e+11 
 At top right:    c1, c2 =    9.650e+06    3.751e+11 
 
-t = 3.60e+04   no. steps = 309   order = 4   stepsize = 7.53e+01
+t = 3.60e+04   no. steps = 311   order = 4   stepsize = 9.70e+01
 At bottom left:  c1, c2 =    1.404e+04    3.387e+11 
 At top right:    c1, c2 =    1.561e+04    3.765e+11 
 
-t = 4.32e+04   no. steps = 377   order = 4   stepsize = 4.02e+02
-At bottom left:  c1, c2 =    1.908e-07    3.382e+11 
-At top right:    c1, c2 =    2.345e-07    3.804e+11 
+t = 4.32e+04   no. steps = 368   order = 4   stepsize = 3.95e+02
+At bottom left:  c1, c2 =    6.243e-08    3.382e+11 
+At top right:    c1, c2 =    7.021e-08    3.804e+11 
 
-t = 5.04e+04   no. steps = 392   order = 5   stepsize = 3.67e+02
-At bottom left:  c1, c2 =   -6.408e-10    3.358e+11 
-At top right:    c1, c2 =   -6.654e-10    3.864e+11 
+t = 5.04e+04   no. steps = 388   order = 5   stepsize = 4.74e+02
+At bottom left:  c1, c2 =    3.000e-07    3.358e+11 
+At top right:    c1, c2 =    3.306e-07    3.864e+11 
 
-t = 5.76e+04   no. steps = 403   order = 5   stepsize = 4.72e+02
-At bottom left:  c1, c2 =    2.017e-08    3.320e+11 
-At top right:    c1, c2 =    3.353e-08    3.909e+11 
+t = 5.76e+04   no. steps = 401   order = 5   stepsize = 3.61e+02
+At bottom left:  c1, c2 =   -1.096e-10    3.320e+11 
+At top right:    c1, c2 =   -6.268e-11    3.909e+11 
 
-t = 6.48e+04   no. steps = 415   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =   -2.502e-10    3.313e+11 
-At top right:    c1, c2 =    2.005e-10    3.963e+11 
+t = 6.48e+04   no. steps = 414   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =    1.186e-11    3.313e+11 
+At top right:    c1, c2 =    6.568e-14    3.963e+11 
 
-t = 7.20e+04   no. steps = 424   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =    4.217e-12    3.330e+11 
-At top right:    c1, c2 =   -2.693e-12    4.039e+11 
+t = 7.20e+04   no. steps = 425   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =   -7.713e-12    3.330e+11 
+At top right:    c1, c2 =    5.432e-13    4.039e+11 
 
-t = 7.92e+04   no. steps = 434   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =    2.779e-12    3.334e+11 
-At top right:    c1, c2 =   -1.865e-12    4.120e+11 
+t = 7.92e+04   no. steps = 436   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =    2.525e-13    3.334e+11 
+At top right:    c1, c2 =   -2.072e-14    4.120e+11 
 
-t = 8.64e+04   no. steps = 444   order = 5   stepsize = 7.47e+02
-At bottom left:  c1, c2 =    2.331e-13    3.352e+11 
-At top right:    c1, c2 =   -1.599e-13    4.163e+11 
+t = 8.64e+04   no. steps = 448   order = 5   stepsize = 6.38e+02
+At bottom left:  c1, c2 =    4.758e-15    3.352e+11 
+At top right:    c1, c2 =    7.572e-17    4.163e+11 
 
 
 Final Statistics: 
 
 lenrw   =  2096     leniw   =   132
-lenrwls =  2046     leniwls =    80
-nst     =   444
-nfe     =   581     nfels   =   526
-nni     =   577     nli     =   526
-nsetups =    75     netf    =    28
-npe     =     8     nps     =  1057
+lenrwls =  2450     leniwls =   106
+nst     =   448
+nfe     =   581     nfels   =   509
+nni     =   577     nli     =   509
+nsetups =    76     netf    =    26
+npe     =     8     nps     =  1029
 ncfn    =     0     ncfl    =     0
 
-In CVBBDPRE: real/integer local work space sizes = 600, 50
+In CVBBDPRE: real/integer local work space sizes = 1300, 192
              no. flocal evals. = 176
 
 
@@ -88,53 +88,53 @@ t = 2.16e+04   no. steps = 249   order = 5   stepsize = 4.31e+02
 At bottom left:  c1, c2 =    2.665e+07    2.993e+11 
 At top right:    c1, c2 =    2.931e+07    3.313e+11 
 
-t = 2.88e+04   no. steps = 314   order = 3   stepsize = 9.38e+01
+t = 2.88e+04   no. steps = 309   order = 4   stepsize = 1.32e+02
 At bottom left:  c1, c2 =    8.702e+06    3.380e+11 
 At top right:    c1, c2 =    9.650e+06    3.751e+11 
 
-t = 3.60e+04   no. steps = 350   order = 5   stepsize = 9.78e+01
+t = 3.60e+04   no. steps = 342   order = 5   stepsize = 1.28e+02
 At bottom left:  c1, c2 =    1.404e+04    3.387e+11 
 At top right:    c1, c2 =    1.561e+04    3.765e+11 
 
-t = 4.32e+04   no. steps = 403   order = 4   stepsize = 3.87e+02
-At bottom left:  c1, c2 =    1.504e-09    3.382e+11 
-At top right:    c1, c2 =    1.683e-09    3.804e+11 
+t = 4.32e+04   no. steps = 393   order = 4   stepsize = 3.91e+02
+At bottom left:  c1, c2 =    1.998e-09    3.382e+11 
+At top right:    c1, c2 =    2.210e-09    3.804e+11 
 
-t = 5.04e+04   no. steps = 416   order = 5   stepsize = 5.91e+02
-At bottom left:  c1, c2 =   -1.137e-11    3.358e+11 
-At top right:    c1, c2 =   -1.439e-11    3.864e+11 
+t = 5.04e+04   no. steps = 406   order = 5   stepsize = 6.68e+02
+At bottom left:  c1, c2 =    4.173e-11    3.358e+11 
+At top right:    c1, c2 =    4.509e-11    3.864e+11 
 
-t = 5.76e+04   no. steps = 432   order = 5   stepsize = 1.73e+02
-At bottom left:  c1, c2 =    1.293e-09    3.320e+11 
-At top right:    c1, c2 =    2.448e-10    3.909e+11 
+t = 5.76e+04   no. steps = 421   order = 4   stepsize = 1.46e+02
+At bottom left:  c1, c2 =    1.346e-13    3.320e+11 
+At top right:    c1, c2 =    1.429e-13    3.909e+11 
 
-t = 6.48e+04   no. steps = 447   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =    7.963e-13    3.313e+11 
-At top right:    c1, c2 =   -2.943e-13    3.963e+11 
+t = 6.48e+04   no. steps = 436   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =    4.188e-18    3.313e+11 
+At top right:    c1, c2 =   -4.796e-15    3.963e+11 
 
-t = 7.20e+04   no. steps = 459   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =   -2.414e-12    3.330e+11 
-At top right:    c1, c2 =    2.797e-13    4.039e+11 
+t = 7.20e+04   no. steps = 448   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =   -4.919e-18    3.330e+11 
+At top right:    c1, c2 =    8.770e-17    4.039e+11 
 
-t = 7.92e+04   no. steps = 470   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =   -1.059e-13    3.334e+11 
-At top right:    c1, c2 =    3.557e-14    4.120e+11 
+t = 7.92e+04   no. steps = 460   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =    2.462e-20    3.334e+11 
+At top right:    c1, c2 =   -2.599e-20    4.120e+11 
 
-t = 8.64e+04   no. steps = 481   order = 5   stepsize = 6.38e+02
-At bottom left:  c1, c2 =    6.045e-15    3.352e+11 
-At top right:    c1, c2 =   -2.016e-15    4.163e+11 
+t = 8.64e+04   no. steps = 472   order = 4   stepsize = 5.90e+02
+At bottom left:  c1, c2 =    3.021e-23    3.352e+11 
+At top right:    c1, c2 =   -3.233e-23    4.163e+11 
 
 
 Final Statistics: 
 
 lenrw   =  2096     leniw   =   132
-lenrwls =  2046     leniwls =    80
-nst     =   481
-nfe     =   622     nfels   =   769
-nni     =   618     nli     =   769
-nsetups =   104     netf    =    33
-npe     =     9     nps     =  1281
+lenrwls =  2450     leniwls =   106
+nst     =   472
+nfe     =   604     nfels   =   758
+nni     =   600     nli     =   758
+nsetups =    94     netf    =    29
+npe     =     9     nps     =  1257
 ncfn    =     0     ncfl    =     0
 
-In CVBBDPRE: real/integer local work space sizes = 600, 50
+In CVBBDPRE: real/integer local work space sizes = 1300, 192
              no. flocal evals. = 198
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_p.c b/examples/cvodes/parallel/cvsDiurnal_kry_p.c
index d2a9ac1..eddefc0 100644
--- a/examples/cvodes/parallel/cvsDiurnal_kry_p.c
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_p.c
@@ -1,9 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
+ * Programmer(s): Daniel R. Reynolds
+ *                S. D. Cohen, A. C. Hindmarsh, M. R. Wittman, and
  *                Radu Serban  @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -32,7 +30,7 @@
  * neq = 2*MX*MY.
  *
  * The solution is done with the BDF/GMRES method (i.e. using the
- * CVSPGMR linear solver) and the block-diagonal part of the
+ * SUNSPGMR linear solver) and the block-diagonal part of the
  * Newton matrix as a left preconditioner. A copy of the
  * block-diagonal part of the Jacobian is saved and conditionally
  * reused within the preconditioner routine.
@@ -52,12 +50,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>             /* prototypes for CVODE fcts. */
-#include <cvodes/cvodes_spgmr.h>       /* prototypes and constants for CVSPGMR solver */
-#include <nvector/nvector_parallel.h>  /* definition N_Vector and macro NV_DATA_P  */
-#include <sundials/sundials_dense.h>   /* prototypes for small dense matrix fcts. */
-#include <sundials/sundials_types.h>   /* definitions of realtype, booleantype */
-#include <sundials/sundials_math.h>    /* definition of macros SUNSQR and EXP */
+#include <cvodes/cvodes.h>              /* prototypes for CVODE fcts. */
+#include <cvodes/cvodes_spils.h>        /* prototypes and constants for CVSpils interface */
+#include <sunlinsol/sunlinsol_spgmr.h>  /* prototypes and constants for SUNSPGMR solver */
+#include <nvector/nvector_parallel.h>   /* definition N_Vector  */
+#include <sundials/sundials_dense.h>    /* prototypes for small dense matrix fcts. */
+#include <sundials/sundials_types.h>    /* definitions of realtype, booleantype */
+#include <sundials/sundials_math.h>     /* definition of macros SUNSQR and EXP */
 
 #include <mpi.h>                       /* MPI constants and types */
 
@@ -125,12 +124,12 @@ typedef struct {
   realtype q4, om, dx, dy, hdco, haco, vdco;
   realtype uext[NVARS*(MXSUB+2)*(MYSUB+2)];
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmxsub2;
+  sunindextype nvmxsub, nvmxsub2;
   MPI_Comm comm;
 
   /* For preconditioner */
   realtype **P[MXSUB][MYSUB], **Jbd[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
 
 } *UserData;
 
@@ -144,15 +143,15 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
 static void PrintFinalStats(void *cvode_mem);
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype udata[]);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[]);
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[]);
 static void ucomm(realtype t, N_Vector u, UserData data);
 static void fcalc(realtype t, realtype udata[], realtype dudata[],
@@ -165,13 +164,11 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   realtype gamma, void *user_data);
 
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
-                  N_Vector r, N_Vector z, 
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  N_Vector r, N_Vector z, realtype gamma, 
+                  realtype delta, int lr, void *user_data);
 
 
 /* Private function to check function return values */
@@ -186,13 +183,15 @@ int main(int argc, char *argv[])
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag, my_pe, npes;
-  long int neq, local_N;
+  sunindextype neq, local_N;
   MPI_Comm comm;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Set problem size neq */
@@ -246,10 +245,14 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1, my_pe)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR 
-     with left preconditioning and the maximum Krylov dimension maxl */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if (check_flag(&flag, "CVSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Create SPGMR solver structure -- use left preconditioning 
+     and the default Krylov dimension maxl */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+  
+  /* Attach the linear solver to the CVSpils interface */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if(check_flag(&flag, "CVSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Set preconditioner setup and solve routines Precond and PSolve, 
      and the pointer to the user-defined block data */
@@ -273,6 +276,7 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(u);
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   MPI_Finalize();
 
@@ -317,7 +321,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
     for (ly = 0; ly < MYSUB; ly++) {
       (data->P)[lx][ly] = newDenseMat(NVARS, NVARS);
       (data->Jbd)[lx][ly] = newDenseMat(NVARS, NVARS);
-      (data->pivot)[lx][ly] = newLintArray(NVARS);
+      (data->pivot)[lx][ly] = newIndexArray(NVARS);
     }
   }
 }
@@ -344,7 +348,7 @@ static void FreeUserData(UserData data)
 static void SetInitialProfiles(N_Vector u, UserData data)
 {
   int isubx, isuby, lx, ly, jx, jy;
-  long int offset;
+  sunindextype offset;
   realtype dx, dy, x, y, cx, cy, xmid, ymid;
   realtype *udata;
 
@@ -386,7 +390,8 @@ static void PrintOutput(void *cvode_mem, int my_pe, MPI_Comm comm,
   int qu, flag;
   realtype hu, *udata, tempu[2];
   int npelast;
-  long int i0, i1, nst;
+  long int  nst;
+  sunindextype i0, i1;
   MPI_Status status;
 
   npelast = NPEX*NPEY - 1;
@@ -474,9 +479,9 @@ static void PrintFinalStats(void *cvode_mem)
   check_flag(&flag, "CVSpilsGetNumRhsEvals", 1, 0);
 
   printf("\nFinal Statistics: \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwls = %5ld     leniwls = %5ld\n", lenrwLS, leniwLS);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwls = %5ld     leniwls = %5ld\n"  , lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfels   = %5ld\n"  , nfe, nfeLS);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
   printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
@@ -488,11 +493,11 @@ static void PrintFinalStats(void *cvode_mem)
 
 static void BSend(MPI_Comm comm, 
                   int my_pe, int isubx, int isuby, 
-                  long int dsizex, long int dsizey,
+                  sunindextype dsizex, sunindextype dsizey,
                   realtype udata[])
 {
   int i, ly;
-  long int offsetu, offsetbuf;
+  sunindextype offsetu, offsetbuf;
   realtype bufleft[NVARS*MYSUB], bufright[NVARS*MYSUB];
 
   /* If isuby > 0, send data from bottom x-line of u */
@@ -537,10 +542,10 @@ static void BSend(MPI_Comm comm,
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], 
                       int my_pe, int isubx, int isuby,
-		      long int dsizex, long int dsizey,
+		      sunindextype dsizex, sunindextype dsizey,
 		      realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer */
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
 
@@ -578,11 +583,11 @@ static void BRecvPost(MPI_Comm comm, MPI_Request request[],
 
 static void BRecvWait(MPI_Request request[], 
                       int isubx, int isuby, 
-                      long int dsizex, realtype uext[],
+                      sunindextype dsizex, realtype uext[],
                       realtype buffer[])
 {
   int i, ly;
-  long int dsizex2, offsetue, offsetbuf;
+  sunindextype dsizex2, offsetue, offsetbuf;
   realtype *bufleft = buffer, *bufright = buffer+NVARS*MYSUB;
   MPI_Status status;
 
@@ -632,7 +637,7 @@ static void ucomm(realtype t, N_Vector u, UserData data)
   realtype *udata, *uext, buffer[2*NVARS*MYSUB];
   MPI_Comm comm;
   int my_pe, isubx, isuby;
-  long int nvmxsub, nvmysub;
+  sunindextype nvmxsub, nvmysub;
   MPI_Request request[4];
 
   udata = N_VGetArrayPointer_Parallel(u);
@@ -668,7 +673,7 @@ static void fcalc(realtype t, realtype udata[],
   realtype q4coef, dely, verdco, hordco, horaco;
   int i, lx, ly, jx, jy;
   int isubx, isuby;
-  long int nvmxsub, nvmxsub2, offsetu, offsetue;
+  sunindextype nvmxsub, nvmxsub2, offsetu, offsetue;
 
   /* Get subgrid indices, data sizes, extended work array uext */
   isubx = data->isubx;   isuby = data->isuby;
@@ -813,13 +818,12 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 /* Preconditioner setup routine. Generate and preprocess P. */
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data, 
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MYSUB], **(*Jbd)[MYSUB];
-  long int nvmxsub, offset;
-  long int *(*pivot)[MYSUB], ier;
+  sunindextype nvmxsub, offset;
+  sunindextype *(*pivot)[MYSUB], ier;
   int lx, ly, jx, jy, isubx, isuby;
   realtype *udata, **a, **j;
   UserData data;
@@ -836,18 +840,18 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 
   if (jok) {
 
-  /* jok = TRUE: Copy Jbd to P */
+  /* jok = SUNTRUE: Copy Jbd to P */
     for (ly = 0; ly < MYSUB; ly++)
       for (lx = 0; lx < MXSUB; lx++)
         denseCopy(Jbd[lx][ly], P[lx][ly], NVARS, NVARS);
 
-  *jcurPtr = FALSE;
+  *jcurPtr = SUNFALSE;
 
   }
 
   else {
 
-  /* jok = FALSE: Generate Jbd from scratch and copy to P */
+  /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
 
   /* Make local copies of problem variables, for efficiency */
   q4coef = data->q4;
@@ -879,7 +883,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
 
   }
 
@@ -902,13 +906,12 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 
 /* Preconditioner solve routine */
 static int PSolve(realtype tn, N_Vector u, N_Vector fu, 
-                  N_Vector r, N_Vector z, 
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  N_Vector r, N_Vector z, realtype gamma, 
+                  realtype delta, int lr, void *user_data)
 {
   realtype **(*P)[MYSUB];
-  long int nvmxsub;
-  long int *(*pivot)[MYSUB];
+  sunindextype nvmxsub;
+  sunindextype *(*pivot)[MYSUB];
   int lx, ly;
   realtype *zdata, *v;
   UserData data;
diff --git a/examples/cvodes/parallel/cvsDiurnal_kry_p.out b/examples/cvodes/parallel/cvsDiurnal_kry_p.out
index 484e635..1eab0cc 100644
--- a/examples/cvodes/parallel/cvsDiurnal_kry_p.out
+++ b/examples/cvodes/parallel/cvsDiurnal_kry_p.out
@@ -13,51 +13,51 @@ t = 2.16e+04   no. steps = 277   order = 5   stepsize = 2.75e+02
 At bottom left:  c1, c2 =    2.665e+07    2.993e+11 
 At top right:    c1, c2 =    2.931e+07    3.313e+11 
 
-t = 2.88e+04   no. steps = 307   order = 4   stepsize = 1.98e+02
+t = 2.88e+04   no. steps = 321   order = 3   stepsize = 5.19e+01
 At bottom left:  c1, c2 =    8.702e+06    3.380e+11 
 At top right:    c1, c2 =    9.650e+06    3.751e+11 
 
-t = 3.60e+04   no. steps = 335   order = 5   stepsize = 1.17e+02
+t = 3.60e+04   no. steps = 384   order = 4   stepsize = 8.70e+01
 At bottom left:  c1, c2 =    1.404e+04    3.387e+11 
 At top right:    c1, c2 =    1.561e+04    3.765e+11 
 
-t = 4.32e+04   no. steps = 388   order = 4   stepsize = 4.48e+02
-At bottom left:  c1, c2 =   -5.732e-07    3.382e+11 
-At top right:    c1, c2 =   -6.367e-07    3.804e+11 
+t = 4.32e+04   no. steps = 456   order = 4   stepsize = 8.77e+02
+At bottom left:  c1, c2 =    1.077e-06    3.382e+11 
+At top right:    c1, c2 =    4.057e-07    3.804e+11 
 
-t = 5.04e+04   no. steps = 406   order = 5   stepsize = 3.97e+02
-At bottom left:  c1, c2 =   -4.317e-09    3.358e+11 
-At top right:    c1, c2 =   -8.233e-09    3.864e+11 
+t = 5.04e+04   no. steps = 471   order = 4   stepsize = 3.29e+02
+At bottom left:  c1, c2 =   -1.176e-08    3.358e+11 
+At top right:    c1, c2 =   -5.053e-08    3.864e+11 
 
-t = 5.76e+04   no. steps = 418   order = 5   stepsize = 4.74e+02
-At bottom left:  c1, c2 =   -2.576e-09    3.320e+11 
-At top right:    c1, c2 =   -1.259e-09    3.909e+11 
+t = 5.76e+04   no. steps = 488   order = 5   stepsize = 3.95e+02
+At bottom left:  c1, c2 =   -9.464e-11    3.320e+11 
+At top right:    c1, c2 =   -3.493e-10    3.909e+11 
 
-t = 6.48e+04   no. steps = 428   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =    3.451e-09    3.313e+11 
-At top right:    c1, c2 =    2.081e-09    3.963e+11 
+t = 6.48e+04   no. steps = 501   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =    5.057e-11    3.313e+11 
+At top right:    c1, c2 =    1.868e-10    3.963e+11 
 
-t = 7.20e+04   no. steps = 437   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =    1.630e-11    3.330e+11 
-At top right:    c1, c2 =    1.843e-11    4.039e+11 
+t = 7.20e+04   no. steps = 512   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =   -4.454e-11    3.330e+11 
+At top right:    c1, c2 =   -1.629e-10    4.039e+11 
 
-t = 7.92e+04   no. steps = 447   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =   -1.704e-11    3.334e+11 
-At top right:    c1, c2 =   -1.131e-11    4.120e+11 
+t = 7.92e+04   no. steps = 524   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =   -2.189e-13    3.334e+11 
+At top right:    c1, c2 =   -8.112e-13    4.120e+11 
 
-t = 8.64e+04   no. steps = 456   order = 5   stepsize = 7.70e+02
-At bottom left:  c1, c2 =    1.496e-12    3.352e+11 
-At top right:    c1, c2 =    8.085e-13    4.163e+11 
+t = 8.64e+04   no. steps = 535   order = 5   stepsize = 6.20e+02
+At bottom left:  c1, c2 =    1.080e-15    3.352e+11 
+At top right:    c1, c2 =    3.729e-15    4.163e+11 
 
 
 Final Statistics: 
 
 lenrw   =  2096     leniw   =   132
-lenrwls =  2046     leniwls =    80
-nst     =   456
-nfe     =   586     nfels   =   619
-nni     =   582     nli     =   619
-nsetups =    73     netf    =    25
-npe     =     8     nps     =  1149
-ncfn    =     0     ncfl    =     0
+lenrwls =  2450     leniwls =   106
+nst     =   535
+nfe     =   688     nfels   =   668
+nni     =   684     nli     =   668
+nsetups =    92     netf    =    33
+npe     =    10     nps     =  1294
+ncfn    =     0     ncfl    =     1
 
diff --git a/examples/cvodes/serial/CMakeLists.txt b/examples/cvodes/serial/CMakeLists.txt
index ea409c7..bad7e68 100644
--- a/examples/cvodes/serial/CMakeLists.txt
+++ b/examples/cvodes/serial/CMakeLists.txt
@@ -1,13 +1,11 @@
 # ---------------------------------------------------------------
-# $Revision: 4824 $
-# $Date: 2016-07-24 16:39:04 -0700 (Sun, 24 Jul 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,188 +13,312 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for CVODES serial examples
+# ---------------------------------------------------------------
 
-# Add variable CVODES_examples with the names of the serial CVODES examples
-# This is a list of tuples, first element is example name.
-# Optional second argument is test arguments
-SET(CVODES_examples 
-   cvsAdvDiff_ASAi_bnd
-   cvsAdvDiff_bnd
-  "cvsAdvDiff_FSA_non\;-sensi stg t"
-  "cvsAdvDiff_FSA_non\;-sensi sim t"
-   cvsDirectDemo_ls
-  "cvsDiurnal_FSA_kry\;-sensi stg t"
-  "cvsDiurnal_FSA_kry\;-sensi sim t"
-   cvsDiurnal_kry_bp
-   cvsDiurnal_kry
-   cvsFoodWeb_ASAi_kry
-   cvsFoodWeb_ASAp_kry
-   cvsHessian_ASA_FSA
-   cvsKrylovDemo_ls
-   cvsKrylovDemo_prec
-   cvsRoberts_ASAi_dns
-   cvsRoberts_dns
-   cvsRoberts_dns_uw
-   "cvsRoberts_FSA_dns\;-sensi stg1 t"
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS linear solvers
+SET(CVODES_examples
+  "cvsAdvDiff_ASAi_bnd\;\;develop"
+  "cvsAdvDiff_bnd\;\;develop"
+  "cvsAdvDiff_FSA_non\;-sensi stg t\;develop"
+  "cvsAdvDiff_FSA_non\;-sensi sim t\;develop"
+  "cvsDirectDemo_ls\;\;develop"
+  "cvsDiurnal_FSA_kry\;-sensi stg t\;develop"
+  "cvsDiurnal_FSA_kry\;-sensi sim t\;develop"
+  "cvsDiurnal_kry_bp\;\;develop"
+  "cvsDiurnal_kry\;\;develop"
+  "cvsFoodWeb_ASAi_kry\;\;develop"
+  "cvsFoodWeb_ASAp_kry\;\;develop"
+  "cvsHessian_ASA_FSA\;\;develop"
+  "cvsKrylovDemo_ls\;\;develop"
+  "cvsKrylovDemo_prec\;\;develop"
+  "cvsRoberts_ASAi_dns\;\;develop"
+  "cvsRoberts_dns\;\;"
+  "cvsRoberts_dns_uw\;\;develop"
+  "cvsRoberts_FSA_dns\;-sensi stg1 t\;develop"
   )
 
-# Add variable CVODES_examples_BL with the names of the serial CVODES examples
-# that use Lapack
+# Examples using LAPACK linear solvers
 SET(CVODES_examples_BL
-  cvsAdvDiff_bndL
-  cvsRoberts_dnsL
+  "cvsAdvDiff_bndL\;\;develop"
+  "cvsRoberts_dnsL\;\;develop"
   )
 
+# Examples using KLU linear solver
 SET(CVODES_examples_KLU
-  cvsRoberts_klu
-  cvsRoberts_ASAi_klu
-  "cvsRoberts_FSA_klu\;-sensi stg1 t"
+  "cvsRoberts_klu\;\;develop"
+  "cvsRoberts_ASAi_klu\;\;develop"
+  "cvsRoberts_FSA_klu\;-sensi stg1 t\;develop"
   )
- 
+
+# Examples using SuperLU_MT linear solver
 SET(CVODES_examples_SUPERLUMT
-  cvsRoberts_sps
-  cvsRoberts_ASAi_sps
-  "cvsRoberts_FSA_sps\;-sensi stg1 t"
+  "cvsRoberts_sps\;\;develop"
+  "cvsRoberts_ASAi_sps\;\;develop"
+  "cvsRoberts_FSA_sps\;-sensi stg1 t\;develop"
   )
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(CVODES_LIB sundials_cvodes_static)
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(CVODES_LIB sundials_cvodes_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${CVODES_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-# Add the build and install targets for each CVODES example
-
-# SGS is there a way to query CMAKE variable to get added executables 
-# rather than keeping our own list?
-SET(ADDED_EXECUTABLES "")
+# Add the build and install targets for each example
 FOREACH(example_tuple ${CVODES_examples})
+
+  # parse the example tuple
   LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
 
-  # Only need to add the executable once
-  LIST(FIND ADDED_EXECUTABLES ${example} index)
-  IF(index EQUAL -1)
-    LIST(APPEND ADDED_EXECUTABLES ${example})
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
+    # folder to organize targets in an IDE
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  ENDIF(index EQUAL -1)
+    
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
 
-  LIST(LENGTH example_tuple n)
-  IF(n EQUAL 2)
-    LIST(GET example_tuple 1 test_args)
-    STRING(REGEX REPLACE " " "_" test_name ${example}_${test_args})
-    SUNDIALS_ADD_TEST(${test_name} ${example} TEST_ARGS ${test_args})
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
   ELSE()
-    SUNDIALS_ADD_TEST(${example} ${example})
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
   ENDIF()
 
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${test_name}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # find all .out files for this example
   FILE(GLOB example_out ${example}.out*)
+
+  # install example source and .out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example_out}
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${CVODES_examples})
 
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
 
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${CVODES_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.c)
-    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${CVODES_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_args)
+    LIST(GET example_tuple 2 example_type)
+
+    # check if this example has already been added, only need to add
+    # example source files once for testing with different inputs
+    IF(NOT TARGET ${example})
+      # example source files
+      ADD_EXECUTABLE(${example} ${example}.c)
+
+      # folder to organize targets in an IDE
+      SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+      # libraries to link against
+      TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+    ENDIF()
+
+    # check if example args are provided and set the test name
+    IF("${example_args}" STREQUAL "")
+      SET(test_name ${example})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+    ENDIF()
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${test_name} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${test_name}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # find all .out files for this example
     FILE(GLOB example_out ${example}.out*)
+
+    # install example source and .out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${CVODES_examples_BL})
+      INSTALL(FILES ${example}.c ${example_out}
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${CVODES_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If KLU support is enabled, add the build and install targets for
-# the examples using KLU
+
+# Add the build and install targets for each KLU example (if needed)
 IF(KLU_FOUND)
-  SET(ADDED_EXECUTABLES "")
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
   FOREACH(example_tuple ${CVODES_examples_KLU})
+
+    # parse the example tuple
     LIST(GET example_tuple 0 example)
-  
-    # Only need to add the executable once
-    LIST(FIND ADDED_EXECUTABLES ${example} index)
-    IF(index EQUAL -1)
-      LIST(APPEND ADDED_EXECUTABLES ${example})
+    LIST(GET example_tuple 1 example_args)
+    LIST(GET example_tuple 2 example_type)
+
+    # check if this example has already been added, only need to add
+    # example source files once for testing with different inputs
+    IF(NOT TARGET ${example})
+      # add example source files
       ADD_EXECUTABLE(${example} ${example}.c)
+
+      # folder to organize targets in an IDE
       SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    ENDIF(index EQUAL -1)
-  
-    LIST(LENGTH example_tuple n)
-    IF(n EQUAL 2)
-      LIST(GET example_tuple 1 test_args)
-      STRING(REGEX REPLACE " " "_" test_name ${example}_${test_args})
-      SUNDIALS_ADD_TEST(${test_name} ${example} TEST_ARGS ${test_args})
+
+      # libraries to link against
+      TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+    ENDIF()
+
+    # check if example args are provided and set the test name
+    IF("${example_args}" STREQUAL "")
+      SET(test_name ${example})
     ELSE()
-      SUNDIALS_ADD_TEST(${example} ${example})
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
     ENDIF()
-  
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${test_name} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${test_name}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # find all .out files for this example
     FILE(GLOB example_out ${example}.out*)
+
+    # install example source and .out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
-    ENDIF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.c ${example_out}
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+    ENDIF()
+
   ENDFOREACH(example_tuple ${CVODES_examples_KLU})
+
 ENDIF(KLU_FOUND)
 
-# If SUPERLUMT support is enabled, add the build and install targets for
-# the examples using SUPERLUMT
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
 IF(SUPERLUMT_FOUND)
-  SET(ADDED_EXECUTABLES "")
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
   FOREACH(example_tuple ${CVODES_examples_SUPERLUMT})
+
+    # parse the example tuple
     LIST(GET example_tuple 0 example)
-  
-    # Only need to add the executable once
-    LIST(FIND ADDED_EXECUTABLES ${example} index)
-    IF(index EQUAL -1)
-      LIST(APPEND ADDED_EXECUTABLES ${example})
+    LIST(GET example_tuple 1 example_args)
+    LIST(GET example_tuple 2 example_type)
+
+    # check if this example has already been added, only need to add
+    # example source files once for testing with different inputs
+    IF(NOT TARGET ${example})
+      # add example source files
       ADD_EXECUTABLE(${example} ${example}.c)
+
+      # folder to organize targets in an IDE
       SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    ENDIF(index EQUAL -1)
-  
-    LIST(LENGTH example_tuple n)
-    IF(n EQUAL 2)
-      LIST(GET example_tuple 1 test_args)
-      STRING(REGEX REPLACE " " "_" test_name ${example}_${test_args})
-      SUNDIALS_ADD_TEST(${test_name} ${example} TEST_ARGS ${test_args})
+
+      # libraries to link against
+      TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+    ENDIF()
+
+    # check if example args are provided and set the test name
+    IF("${example_args}" STREQUAL "")
+      SET(test_name ${example})
     ELSE()
-      SUNDIALS_ADD_TEST(${example} ${example})
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
     ENDIF()
-  
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${test_name} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${test_name}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # find all .out files for this example
     FILE(GLOB example_out ${example}.out*)
+
+    # install example source and .out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example_out} DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
-    ENDIF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.c ${example_out}
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+    ENDIF()
+
   ENDFOREACH(example_tuple ${CVODES_examples_SUPERLUMT})
+
 ENDIF(SUPERLUMT_FOUND)
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -205,54 +327,46 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "CVODES")
   SET(SOLVER_LIB "sundials_cvodes")
-  FOREACH(example_tuple ${CVODES_examples})
-    list(GET example_tuple 0 example)
-    LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${CVODES_examples})
+
+  EXAMPLES2STRING(CVODES_examples EXAMPLES)
 
   IF(LAPACK_FOUND)
-    LIST2STRING(CVODES_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(CVODES_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
 
   IF(KLU_FOUND)
-    FOREACH(example_tuple ${CVODES_examples_KLU})
-      list(GET example_tuple 0 example)
-      LIST2STRING(example EXAMPLES)
-    ENDFOREACH(example_tuple ${CVODES_examples_KLU})
-  ENDIF(KLU_FOUND)
+    EXAMPLES2STRING(CVODES_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
 
   IF(SUPERLUMT_FOUND)
-    FOREACH(example_tuple ${CVODES_examples_SUPERLUMT})
-      list(GET example_tuple 0 example)
-      LIST2STRING(example EXAMPLES)
-    ENDFOREACH(example_tuple ${CVODES_examples_SUPERLUMT})
-  ENDIF(SUPERLUMT_FOUND)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
-  list(REMOVE_DUPLICATES EXAMPLES)
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+    EXAMPLES2STRING(CVODES_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMTU "")
+  ENDIF()
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/cvodes/serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/cvodes/serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/cvodes/serial/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -264,10 +378,14 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/cvodes/serial/Makefile_ex 
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial 
+      FILES ${PROJECT_BINARY_DIR}/examples/cvodes/serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/cvodes/serial
       RENAME Makefile
       )
   ENDIF(UNIX)
 
+  # add test_install target
+  SUNDIALS_ADD_TEST_INSTALL(cvodes cvsRoberts_dns
+    EXAMPLE_DIR ${EXAMPLES_INSTALL_PATH}/cvodes/serial)
+
 ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/cvodes/serial/README b/examples/cvodes/serial/README
index 92bdb82..d590341 100644
--- a/examples/cvodes/serial/README
+++ b/examples/cvodes/serial/README
@@ -9,7 +9,7 @@ List of serial CVODES examples
   cvsDiurnal_kry        : Krylov example
   cvsKrylovDemo_ls      : demonstration program with 3 Krylov solvers
   cvsKrylovDemo_prec    : demonstration program for Krylov methods
-  cvsRoberts_dns        : dense example
+  cvsRoberts_dns        : chemical kinetics example - BDF Newton/dense
   cvsRoberts_dnsL       : dense example (Lapack)
   cvsRoberts_dns_uw     : dense example with user ewt function
   cvsRoberts_klu        : dense example with KLU sparse linear solver
@@ -21,8 +21,9 @@ List of serial CVODES examples
                           Adams with Functional iteration
   cvsDiurnal_FSA_kry    : 2-D 2-species diurnal advection-diffusion PDE -
                           BDF with Newton GMRES
-  cvsRoberts_FSA_dns    : chemical kinetics ODEs -
-                          BDF with Newton Dense
+  cvsRoberts_FSA_dns    : chemical kinetics ODEs - BDF with Newton Dense
+  cvsRoberts_FSA_klu    : kinetics ODEs - FSA with KLU sparse linear solver
+  cvsRoberts_FSA_sps    : kinetics ODEs - FSA with SuperLUMT sparse solver
 
 (3) Adjoint sensitivity
 
@@ -31,13 +32,14 @@ List of serial CVODES examples
   cvsFoodWeb_ASAp_kry   : food web - adjoint sensitivity for g
   cvsHessian_ASA_FSA    : ASA example for computing Hessian
   cvsRoberts_ASAi_dns   : chemical kinetics - adjoint sensitivity
+  cvsRoberts_ASAi_klu   : kinetics - ASA with KLU sparse linear solver
+  cvsRoberts_ASAi_sps   : kinetics - ASA with SuperLUMT sparse linear solver
 
 
 The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -48,7 +50,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -62,7 +67,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c b/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c
index b35e6d3..08bbd6c 100644
--- a/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c
+++ b/examples/cvodes/serial/cvsAdvDiff_ASAi_bnd.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Adjoint sensitivity example problem:
@@ -20,7 +16,7 @@
  * central differencing, and with boundary values eliminated,
  * leaving an ODE system of size NEQ = MX*MY.
  * This program solves the problem with the BDF method, Newton
- * iteration with the CVODE band linear solver, and a user-supplied
+ * iteration with the SUNBAND linear solver, and a user-supplied
  * Jacobian routine.
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .1, .2, ..., 1.
@@ -43,11 +39,15 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>
-#include <cvodes/cvodes_band.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+/* Header files with a description of contents */
+
+#include <cvodes/cvodes.h>             /* prototypes for CVODES fcts., consts. */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <cvodes/cvodes_direct.h>      /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
+#include <sundials/sundials_math.h>    /* definition of SUNRabs and SUNRexp    */
 
 /* Problem Constants */
 
@@ -76,7 +76,7 @@
    to the underlying 1-dimensional storage. 
    IJth(vdata,i,j) references the element in the vdata array for
    u at mesh point (i,j), where 1 <= i <= MX, 1 <= j <= MY.
-   The vdata array is obtained via the macro call vdata = N_VDATA(v),
+   The vdata array is obtained via the call vdata = N_VGetArrayPointer(v),
    where v is an N_Vector. 
    The variables are ordered by the y index j, then by the x index i. */
 
@@ -93,18 +93,13 @@ typedef struct {
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); 
+static int Jac(realtype t, N_Vector u, N_Vector fu, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); 
 
 static int fB(realtype tB, N_Vector u, N_Vector uB, N_Vector uBdot, void *user_dataB);
 
-static int JacB(long int NB, long int muB, long int mlB,
-                realtype tB, N_Vector u, 
-                N_Vector uB, N_Vector fuB,
-                DlsMat JB, void *user_dataB,
-                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); 
+static int JacB(realtype tB, N_Vector u, N_Vector uB, N_Vector fuB, SUNMatrix JB,
+                void *user_dataB, N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B); 
 
 /* Prototypes of private functions */
 
@@ -123,6 +118,8 @@ int main(int argc, char *argv[])
   UserData data;
 
   void *cvode_mem;
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
 
   realtype dx, dy, reltol, abstol, t;
   N_Vector u;
@@ -137,6 +134,8 @@ int main(int argc, char *argv[])
   data = NULL;
   cvode_mem = NULL;
   u = uB = NULL;
+  LS = LSB = NULL;
+  A = AB = NULL;
 
   /* Allocate and initialize user data memory */
 
@@ -176,13 +175,21 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Call CVBand with  bandwidths ml = mu = MY, */
+  /* Create banded SUNMatrix for the forward problem */
+  A = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
 
-  flag = CVBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVBand", 1)) return(1);
+  /* Create banded SUNLinearSolver for the forward problem */
+  LS = SUNBandLinearSolver(u, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
 
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine for the forward problem */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* Allocate global memory */
 
@@ -223,12 +230,22 @@ int main(int argc, char *argv[])
 
   flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
   if(check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);
+ 
+  /* Create banded SUNMatrix for the backward problem */
+  AB = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)AB, "SUNBandMatrix", 0)) return(1);
 
-  flag = CVBandB(cvode_mem, indexB, NEQ, MY, MY);
-  if(check_flag(&flag, "CVBandB", 1)) return(1);
-  
-  flag = CVDlsSetBandJacFnB(cvode_mem, indexB, JacB);
-  if(check_flag(&flag, "CVDlsSetBandJacFnB", 1)) return(1);
+  /* Create banded SUNLinearSolver for the backward problem */
+  LSB = SUNBandLinearSolver(uB, AB);
+  if(check_flag((void *)LSB, "SUNBandLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolverB(cvode_mem, indexB, LSB, AB);
+  if(check_flag(&flag, "CVDlsSetLinearSolverB", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine for the backward problem */
+  flag = CVDlsSetJacFnB(cvode_mem, indexB, JacB);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* Perform backward integration */
   printf("\nBackward integration\n");
@@ -240,9 +257,13 @@ int main(int argc, char *argv[])
 
   PrintOutput(uB, data);
 
-  N_VDestroy_Serial(u);   /* Free the u vector */
-  N_VDestroy_Serial(uB);  /* Free the uB vector */
-  CVodeFree(&cvode_mem);  /* Free the CVODE problem memory */
+  N_VDestroy(u);   /* Free the u vector                      */
+  N_VDestroy(uB);  /* Free the uB vector                     */
+  CVodeFree(&cvode_mem);  /* Free the CVODE problem memory          */
+  SUNLinSolFree(LS);      /* Free the forward linear solver memory  */
+  SUNMatDestroy(A);       /* Free the forward matrix memory         */
+  SUNLinSolFree(LSB);     /* Free the backward linear solver memory */
+  SUNMatDestroy(AB);      /* Free the backward matrix memory        */
 
   free(data);             /* Free the user data */
 
@@ -266,8 +287,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   int i, j;
   UserData data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed constants from data */
 
@@ -306,10 +327,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
  * Jac function. Jacobian of forward ODE.
  */
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector u, N_Vector fu, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   int i, j, k;
   realtype *kthCol, hordc, horac, verdc;
@@ -333,15 +352,15 @@ static int Jac(long int N, long int mu, long int ml,
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
+      kthCol = SUNBandMatrix_Column(J,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = verdc;
     }
   }
 
@@ -362,8 +381,8 @@ static int fB(realtype tB, N_Vector u, N_Vector uB, N_Vector uBdot,
   realtype hdiffB, hadvB, vdiffB;
   int i, j;
 
-  uBdata = N_VGetArrayPointer_Serial(uB);
-  duBdata = N_VGetArrayPointer_Serial(uBdot);
+  uBdata = N_VGetArrayPointer(uB);
+  duBdata = N_VGetArrayPointer(uBdot);
 
   /* Extract needed constants from data */
 
@@ -402,11 +421,8 @@ static int fB(realtype tB, N_Vector u, N_Vector uB, N_Vector uBdot,
  * JacB function. Jacobian of backward ODE
  */
 
-static int JacB(long int NB, long int muB, long int mlB,
-                realtype tB, N_Vector u, 
-                N_Vector uB, N_Vector fuB,
-                DlsMat JB, void *user_dataB,
-                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+static int JacB(realtype tB, N_Vector u, N_Vector uB, N_Vector fuB, SUNMatrix JB,
+                void *user_dataB, N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   int i, j, k;
   realtype *kthCol, hordc, horac, verdc;
@@ -422,15 +438,15 @@ static int JacB(long int NB, long int muB, long int mlB,
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(JB,k);
+      kthCol = SUNBandMatrix_Column(JB,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = - hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = - hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = - verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = - verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = - hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = - hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = - verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = - verdc;
     }
   }
 
@@ -460,7 +476,7 @@ static void SetIC(N_Vector u, UserData data)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profile into u vector */
 
@@ -488,7 +504,7 @@ static void PrintOutput(N_Vector uB, UserData data)
   dx = data->dx;
   dy = data->dy;
 
-  uBdata = N_VGetArrayPointer_Serial(uB);
+  uBdata = N_VGetArrayPointer(uB);
 
   uBmax = ZERO;
   for(j=1; j<= MY; j++) {
diff --git a/examples/cvodes/serial/cvsAdvDiff_FSA_non.c b/examples/cvodes/serial/cvsAdvDiff_FSA_non.c
index 1667246..63f9b94 100644
--- a/examples/cvodes/serial/cvsAdvDiff_FSA_non.c
+++ b/examples/cvodes/serial/cvsAdvDiff_FSA_non.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4956 $
- * $Date: 2016-09-23 11:15:59 -0700 (Fri, 23 Sep 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, George D. Byrne,
  *              and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -40,8 +36,7 @@
  *    % cvsAdvDiff_FSA_non -sensi sensi_meth err_con
  * where sensi_meth is one of {sim, stg, stg1} and err_con is one of
  * {t, f}.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -167,8 +162,8 @@ int main(int argc, char *argv[])
     if(check_flag((void *)pbar, "malloc", 2)) return(1);
     for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]];
 
-    uS = N_VCloneVectorArray_Serial(NS, u);
-    if(check_flag((void *)uS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    uS = N_VCloneVectorArray(NS, u);
+    if(check_flag((void *)uS, "N_VCloneVectorArray", 0)) return(1);
     for(is=0;is<NS;is++)
       N_VConst(ZERO, uS[is]);
 
@@ -225,9 +220,9 @@ int main(int argc, char *argv[])
   PrintFinalStats(cvode_mem, sensi);
 
   /* Free memory */
-  N_VDestroy_Serial(u);
+  N_VDestroy(u);
   if (sensi) {
-    N_VDestroyVectorArray_Serial(uS, NS);
+    N_VDestroyVectorArray(uS, NS);
     free(plist);
     free(pbar);
   }
@@ -256,8 +251,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   int i;
   UserData data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed problem constants from data */
   data = (UserData) user_data;
@@ -301,16 +296,16 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -329,9 +324,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -358,7 +353,7 @@ static void SetIC(N_Vector u, realtype dx)
   realtype *udata;
 
   /* Set pointer to data array and get local length of u. */
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profile into u vector */
   for (i=0; i<NEQ; i++) {
diff --git a/examples/cvodes/serial/cvsAdvDiff_FSA_non.out b/examples/cvodes/serial/cvsAdvDiff_FSA_non_-sensi_sim_t.out
similarity index 55%
rename from examples/cvodes/serial/cvsAdvDiff_FSA_non.out
rename to examples/cvodes/serial/cvsAdvDiff_FSA_non_-sensi_sim_t.out
index 4cb83ad..05d38f8 100644
--- a/examples/cvodes/serial/cvsAdvDiff_FSA_non.out
+++ b/examples/cvodes/serial/cvsAdvDiff_FSA_non_-sensi_sim_t.out
@@ -5,65 +5,65 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
 ============================================================
      T     Q       H      NST                    Max norm   
 ============================================================
-5.000e-01  4  7.656e-03   115
+5.000e-01  4  7.577e-03   115
                                 Solution         3.0529e+00 
                                 Sensitivity 1    3.8668e+00 
                                 Sensitivity 2    6.2020e-01 
 ------------------------------------------------------------
-1.000e+00  4  9.525e-03   182
+1.000e+00  3  4.126e-03   187
                                 Solution         8.7533e-01 
                                 Sensitivity 1    2.1743e+00 
                                 Sensitivity 2    1.8909e-01 
 ------------------------------------------------------------
-1.500e+00  3  1.040e-02   255
-                                Solution         2.4949e-01 
+1.500e+00  2  1.181e-02   265
+                                Solution         2.4948e-01 
                                 Sensitivity 1    9.1825e-01 
-                                Sensitivity 2    7.3922e-02 
+                                Sensitivity 2    7.3921e-02 
 ------------------------------------------------------------
-2.000e+00  2  1.271e-02   330
-                                Solution         7.1097e-02 
-                                Sensitivity 1    3.4667e-01 
+2.000e+00  2  9.433e-03   328
+                                Solution         7.1095e-02 
+                                Sensitivity 1    3.4666e-01 
                                 Sensitivity 2    2.8228e-02 
 ------------------------------------------------------------
-2.500e+00  2  1.629e-02   402
-                                Solution         2.0260e-02 
-                                Sensitivity 1    1.2301e-01 
+2.500e+00  2  3.946e-03   398
+                                Solution         2.0259e-02 
+                                Sensitivity 1    1.2300e-01 
                                 Sensitivity 2    1.0085e-02 
 ------------------------------------------------------------
-3.000e+00  2  3.820e-03   473
-                                Solution         5.7734e-03 
-                                Sensitivity 1    4.1956e-02 
+3.000e+00  2  9.370e-03   470
+                                Solution         5.7731e-03 
+                                Sensitivity 1    4.1958e-02 
                                 Sensitivity 2    3.4556e-03 
 ------------------------------------------------------------
-3.500e+00  2  8.988e-03   540
+3.500e+00  2  1.010e-02   540
                                 Solution         1.6451e-03 
                                 Sensitivity 1    1.3922e-02 
                                 Sensitivity 2    1.1669e-03 
 ------------------------------------------------------------
-4.000e+00  2  1.199e-02   617
-                                Solution         4.6945e-04 
-                                Sensitivity 1    4.5300e-03 
-                                Sensitivity 2    3.8674e-04 
+4.000e+00  2  4.255e-03   638
+                                Solution         4.6881e-04 
+                                Sensitivity 1    4.5275e-03 
+                                Sensitivity 2    3.8633e-04 
 ------------------------------------------------------------
-4.500e+00  3  4.744e-03   680
-                                Solution         1.3422e-04 
-                                Sensitivity 1    1.4548e-03 
-                                Sensitivity 2    1.2589e-04 
+4.500e+00  1  5.757e-03   716
+                                Solution         1.3404e-04 
+                                Sensitivity 1    1.4539e-03 
+                                Sensitivity 2    1.2576e-04 
 ------------------------------------------------------------
-5.000e+00  1  4.010e-03   757
-                                Solution         3.8656e-05 
-                                Sensitivity 1    4.6451e-04 
-                                Sensitivity 2    4.0616e-05 
+5.000e+00  1  6.420e-03   798
+                                Solution         3.8640e-05 
+                                Sensitivity 1    4.6496e-04 
+                                Sensitivity 2    4.0583e-05 
 ------------------------------------------------------------
 
 Final Statistics
 
-nst     =   757
+nst     =   798
 
-nfe     =  1373
+nfe     =  1409
 netf    =     1    nsetups  =     0
-nni     =  1369    ncfn     =   117
+nni     =  1405    ncfn     =   125
 
-nfSe    =  2746    nfeS     =  5492
+nfSe    =  2818    nfeS     =  5636
 netfs   =     0    nsetupsS =     0
 nniS    =     0    ncfnS    =     0
diff --git a/examples/cvodes/serial/cvsAdvDiff_FSA_non_-sensi_stg_t.out b/examples/cvodes/serial/cvsAdvDiff_FSA_non_-sensi_stg_t.out
new file mode 100644
index 0000000..50e3076
--- /dev/null
+++ b/examples/cvodes/serial/cvsAdvDiff_FSA_non_-sensi_stg_t.out
@@ -0,0 +1,69 @@
+
+1-D advection-diffusion equation, mesh size = 10
+Sensitivity: YES ( STAGGERED + FULL ERROR CONTROL )
+
+============================================================
+     T     Q       H      NST                    Max norm   
+============================================================
+5.000e-01  3  3.873e-03   163
+                                Solution         3.0529e+00 
+                                Sensitivity 1    3.8668e+00 
+                                Sensitivity 2    6.2020e-01 
+------------------------------------------------------------
+1.000e+00  3  3.873e-03   292
+                                Solution         8.7533e-01 
+                                Sensitivity 1    2.1743e+00 
+                                Sensitivity 2    1.8909e-01 
+------------------------------------------------------------
+1.500e+00  3  3.873e-03   421
+                                Solution         2.4950e-01 
+                                Sensitivity 1    9.1827e-01 
+                                Sensitivity 2    7.3922e-02 
+------------------------------------------------------------
+2.000e+00  3  3.873e-03   550
+                                Solution         7.1107e-02 
+                                Sensitivity 1    3.4668e-01 
+                                Sensitivity 2    2.8229e-02 
+------------------------------------------------------------
+2.500e+00  3  3.873e-03   679
+                                Solution         2.0257e-02 
+                                Sensitivity 1    1.2301e-01 
+                                Sensitivity 2    1.0086e-02 
+------------------------------------------------------------
+3.000e+00  3  3.873e-03   808
+                                Solution         5.7782e-03 
+                                Sensitivity 1    4.1960e-02 
+                                Sensitivity 2    3.4560e-03 
+------------------------------------------------------------
+3.500e+00  3  3.873e-03   938
+                                Solution         1.6513e-03 
+                                Sensitivity 1    1.3927e-02 
+                                Sensitivity 2    1.1671e-03 
+------------------------------------------------------------
+4.000e+00  3  3.873e-03  1067
+                                Solution         4.6359e-04 
+                                Sensitivity 1    4.5228e-03 
+                                Sensitivity 2    3.8639e-04 
+------------------------------------------------------------
+4.500e+00  3  3.873e-03  1196
+                                Solution         1.3607e-04 
+                                Sensitivity 1    1.4450e-03 
+                                Sensitivity 2    1.2543e-04 
+------------------------------------------------------------
+5.000e+00  3  3.873e-03  1325
+                                Solution         4.3250e-05 
+                                Sensitivity 1    4.6197e-04 
+                                Sensitivity 2    4.0128e-05 
+------------------------------------------------------------
+
+Final Statistics
+
+nst     =  1325
+
+nfe     =  2988
+netf    =     0    nsetups  =     0
+nni     =  1659    ncfn     =     0
+
+nfSe    =  3464    nfeS     =  6928
+netfs   =     0    nsetupsS =     0
+nniS    =  1728    ncfnS    =     0
diff --git a/examples/cvodes/serial/cvsAdvDiff_bnd.c b/examples/cvodes/serial/cvsAdvDiff_bnd.c
index 22c3a1f..ff1bfe0 100644
--- a/examples/cvodes/serial/cvsAdvDiff_bnd.c
+++ b/examples/cvodes/serial/cvsAdvDiff_bnd.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -21,13 +17,12 @@
  * central differencing, and with boundary values eliminated,
  * leaving an ODE system of size NEQ = MX*MY.
  * This program solves the problem with the BDF method, Newton
- * iteration with the CVBAND band linear solver, and a user-supplied
+ * iteration with the SUNBAND band linear solver, and a user-supplied
  * Jacobian routine.
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .1, .2, ..., 1.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,12 +30,13 @@
 
 /* Header files with a description of contents used */
 
-#include <cvodes/cvodes.h>           /* prototypes for CVODE fcts. and consts. */
-#include <cvodes/cvodes_band.h>      /* prototype for CVBand */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., and macros */
-#include <sundials/sundials_band.h>  /* definitions of type DlsMat and macros */
-#include <sundials/sundials_types.h> /* definition of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS and EXP */
+#include <cvodes/cvodes.h>             /* prototypes for CVODES fcts., consts. */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <cvodes/cvodes_direct.h>      /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
+#include <sundials/sundials_math.h>    /* definition of SUNRabs and SUNRexp    */
 
 /* Problem Constants */
 
@@ -68,7 +64,7 @@
    to the underlying 1-dimensional storage. 
    IJth(vdata,i,j) references the element in the vdata array for
    u at mesh point (i,j), where 1 <= i <= MX, 1 <= j <= MY.
-   The vdata array is obtained via the macro call vdata = N_VGetArrayPointer_Serial(v),
+   The vdata array is obtained via the call vdata = N_VGetArrayPointer(v),
    where v is an N_Vector. 
    The variables are ordered by the y index j, then by the x index i. */
 
@@ -94,10 +90,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 /* Functions Called by the Solver */
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector u, N_Vector fu, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /*
  *-------------------------------
@@ -111,12 +105,16 @@ int main(void)
   N_Vector u;
   UserData data;
   void *cvode_mem;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   int iout, flag;
   long int nst;
 
   u = NULL;
   data = NULL;
   cvode_mem = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Create a serial vector */
 
@@ -156,13 +154,21 @@ int main(void)
   flag = CVodeSetUserData(cvode_mem, data);
   if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVBand to specify the CVBAND band linear solver */
-  flag = CVBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVBand", 1)) return(1);
+  /* Create banded SUNMatrix */
+  A = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver */
+  LS = SUNBandLinearSolver(u, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
-  /* Set the user-supplied Jacobian routine Jac */
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  /* Set the user-supplied Jacobian routine */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop over output points: call CVode, print results, test for errors */
 
@@ -179,8 +185,10 @@ int main(void)
 
   PrintFinalStats(cvode_mem);  /* Print some final statistics   */
 
-  N_VDestroy_Serial(u);   /* Free the u vector */
+  N_VDestroy(u);   /* Free the u vector */
   CVodeFree(&cvode_mem);  /* Free the integrator memory */
+  SUNLinSolFree(LS);      /* Free the linear solver memory */
+  SUNMatDestroy(A);       /* Free the matrix memory */
   free(data);             /* Free the user data */
 
   return(0);
@@ -201,8 +209,8 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
   int i, j;
   UserData data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed constants from data */
 
@@ -239,12 +247,10 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
 
 /* Jacobian routine. Compute J(t,u). */
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector u, N_Vector fu, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype *kthCol, hordc, horac, verdc;
   UserData data;
   
@@ -266,15 +272,15 @@ static int Jac(long int N, long int mu, long int ml,
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
+      kthCol = SUNBandMatrix_Column(J,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = verdc;
     }
   }
 
@@ -302,7 +308,7 @@ static void SetIC(N_Vector u, UserData data)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profile into u vector */
   
diff --git a/examples/cvodes/serial/cvsAdvDiff_bndL.c b/examples/cvodes/serial/cvsAdvDiff_bndL.c
index c61c643..0776b7f 100644
--- a/examples/cvodes/serial/cvsAdvDiff_bndL.c
+++ b/examples/cvodes/serial/cvsAdvDiff_bndL.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -25,19 +21,19 @@
  * It uses scalar relative and absolute tolerances.
  * Output is printed at t = .1, .2, ..., 1.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-/* Header files with a description of contents used */
-
-#include <cvodes/cvodes.h>           /* prototypes for CVODE fcts. and consts. */
-#include <cvodes/cvodes_lapack.h>    /* prototype for CVLapackBand */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., and macros */
-#include <sundials/sundials_math.h>  /* definition of ABS and EXP */
+#include <cvodes/cvodes.h>                   /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>          /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>        /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_lapackband.h>  /* access to band SUNLinearSolver       */
+#include <cvodes/cvodes_direct.h>            /* access to CVDls interface            */
+#include <sundials/sundials_types.h>         /* definition of type realtype          */
+#include <sundials/sundials_math.h>          /* definition of ABS and EXP            */
 
 /* Problem Constants */
 
@@ -65,7 +61,7 @@
    to the underlying 1-dimensional storage. 
    IJth(vdata,i,j) references the element in the vdata array for
    u at mesh point (i,j), where 1 <= i <= MX, 1 <= j <= MY.
-   The vdata array is obtained via the macro call vdata = N_VGetArrayPointer_Serial(v),
+   The vdata array is obtained via the call vdata = N_VGetArrayPointer(v),
    where v is an N_Vector. 
    The variables are ordered by the y index j, then by the x index i. */
 
@@ -91,9 +87,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 /* Functions Called by the Solver */
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector u, N_Vector fu, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /*
@@ -107,12 +102,16 @@ int main(void)
   realtype dx, dy, reltol, abstol, t, tout, umax;
   N_Vector u;
   UserData data;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
   long int nst;
 
   u = NULL;
   data = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create a serial vector */
@@ -153,15 +152,25 @@ int main(void)
   flag = CVodeSetUserData(cvode_mem, data);
   if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVLapackBand to specify the CVBAND band linear solver */
-  flag = CVLapackBand(cvode_mem, NEQ, MY, MY);
-  if(check_flag(&flag, "CVLapackBand", 1)) return(1);
+  /* Create banded SUNMatrix for use in linear solves -- since this will be factored, 
+     set the storage bandwidth to be the sum of upper and lower bandwidths */
+  A = SUNBandMatrix(NEQ, MY, MY, 2*MY);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create SUNLapackBand solver object for use by CVode */
+  LS = SUNLapackBand(u, A);
+  if(check_flag((void *)LS, "SUNLapackBand", 0)) return(1);
+  
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   /* Set the user-supplied Jacobian routine Jac */
-  flag = CVDlsSetBandJacFn(cvode_mem, Jac);
-  if(check_flag(&flag, "CVDlsSetBandJacFn", 1)) return(1);
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop over output points: call CVode, print results, test for errors */
+
   umax = N_VMaxNorm(u);
   PrintHeader(reltol, abstol, umax);
   for(iout=1, tout=T1; iout <= NOUT; iout++, tout += DTOUT) {
@@ -175,7 +184,7 @@ int main(void)
 
   PrintFinalStats(cvode_mem);  /* Print some final statistics   */
 
-  N_VDestroy_Serial(u);   /* Free the u vector */
+  N_VDestroy(u);          /* Free the u vector */
   CVodeFree(&cvode_mem);  /* Free the integrator memory */
   free(data);             /* Free the user data */
 
@@ -197,8 +206,8 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
   int i, j;
   UserData data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata  = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Extract needed constants from data */
 
@@ -235,9 +244,8 @@ static int f(realtype t, N_Vector u,N_Vector udot, void *user_data)
 
 /* Jacobian routine. Compute J(t,u). */
 
-static int Jac(long int N, long int mu, long int ml,
-               realtype t, N_Vector u, N_Vector fu, 
-               DlsMat J, void *user_data,
+static int Jac(realtype t, N_Vector u, N_Vector fu, 
+               SUNMatrix J, void *user_data,
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   int i, j, k;
@@ -263,15 +271,15 @@ static int Jac(long int N, long int mu, long int ml,
   for (j=1; j <= MY; j++) {
     for (i=1; i <= MX; i++) {
       k = j-1 + (i-1)*MY;
-      kthCol = BAND_COL(J,k);
+      kthCol = SUNBandMatrix_Column(J,k);
 
       /* set the kth column of J */
 
-      BAND_COL_ELEM(kthCol,k,k) = -TWO*(verdc+hordc);
-      if (i != 1)  BAND_COL_ELEM(kthCol,k-MY,k) = hordc + horac;
-      if (i != MX) BAND_COL_ELEM(kthCol,k+MY,k) = hordc - horac;
-      if (j != 1)  BAND_COL_ELEM(kthCol,k-1,k)  = verdc;
-      if (j != MY) BAND_COL_ELEM(kthCol,k+1,k)  = verdc;
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO*(verdc+hordc);
+      if (i != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-MY,k) = hordc + horac;
+      if (i != MX) SM_COLUMN_ELEMENT_B(kthCol,k+MY,k) = hordc - horac;
+      if (j != 1)  SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = verdc;
+      if (j != MY) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = verdc;
     }
   }
 
@@ -299,7 +307,7 @@ static void SetIC(N_Vector u, UserData data)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profile into u vector */
   
diff --git a/examples/cvodes/serial/cvsDirectDemo_ls.c b/examples/cvodes/serial/cvsDirectDemo_ls.c
index 923e032..2b02f1b 100644
--- a/examples/cvodes/serial/cvsDirectDemo_ls.c
+++ b/examples/cvodes/serial/cvsDirectDemo_ls.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -30,28 +26,27 @@
  * called for each of the remaining seven runs.
  *
  * Notes: This program demonstrates the usage of the sequential
- * macros NV_Ith_S, DENSE_ELEM, BAND_COL, and
- * BAND_COL_ELEM. The NV_Ith_S macro is used to reference the
+ * macros NV_Ith_S, SM_ELEMENT_D, SM_COLUMN_B, and
+ * SM_COLUMN_ELEMENT_B. The NV_Ith_S macro is used to reference the
  * components of an N_Vector. It works for any size N=NEQ, but
  * due to efficiency concerns it should only by used when the
  * problem size is small. The Problem 1 right hand side and
  * Jacobian functions f1 and Jac1 both use NV_Ith_S. The 
- * N_VGetArrayPointer_Serial function gives the user access to the 
+ * N_VGetArrayPointer function gives the user access to the 
  * memory used for the component storage of an N_Vector. In the 
  * sequential case, the user may assume that this is one contiguous 
- * array of reals. The N_VGetArrayPointer_Serial function
+ * array of reals. The N_VGetArrayPointer function
  * gives a more efficient means (than the NV_Ith_S macro) to
  * access the components of an N_Vector and should be used when the
  * problem size is large. The Problem 2 right hand side function f2
- * uses the N_VGetArrayPointer_Serial function. The DENSE_ELEM macro 
- * used in Jac1 gives access to an element of a dense matrix of type 
- * DlsMat. It should be used only when the problem size is small (the 
- * size of a DlsMat is NEQ x NEQ) due to efficiency concerns. For
- * larger problem sizes, the macro DENSE_COL can be used in order
- * to work directly with a column of a DlsMat. The BAND_COL and
- * BAND_COL_ELEM allow efficient columnwise access to the elements
- * of a band matrix of type DlsMat. These macros are used in the
- * Jac2 function.
+ * uses the N_VGetArrayPointer function. The SM_ELEMENT_D macro 
+ * used in Jac1 gives access to an element of a dense SUNMatrix. It 
+ * should be used only when the problem size is small (the 
+ * size of a Dense SUNMatrix is NEQ x NEQ) due to efficiency concerns. For
+ * larger problem sizes, the macro SM_COLUMN_D can be used in order
+ * to work directly with a column of a Dense SUNMatrix. The SM_COLUMN_B and
+ * SM_COLUMN_ELEMENT_B allow efficient columnwise access to the elements
+ * of a Banded SUNMatix. These macros are used in the Jac2 function.
  * -----------------------------------------------------------------
  */
 
@@ -59,13 +54,16 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>             /* main integrator header file */
-#include <cvodes/cvodes_dense.h>       /* use CVDENSE linear solver */
-#include <cvodes/cvodes_band.h>        /* use CVBAND linear solver */
-#include <cvodes/cvodes_diag.h>        /* use CVDIAG linear solver */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS, SUNSQR, and EXP*/
+#include <cvodes/cvodes.h>                /* prototypes for CVODE fcts., consts.      */
+#include <nvector/nvector_serial.h>       /* access to serial N_Vector                */
+#include <sunmatrix/sunmatrix_dense.h>    /* access to dense SUNMatrix                */
+#include <sunlinsol/sunlinsol_dense.h>    /* access to dense SUNLinearSolver          */
+#include <sunmatrix/sunmatrix_band.h>     /* access to band SUNMatrix                 */
+#include <sunlinsol/sunlinsol_band.h>     /* access to band SUNLinearSolver           */
+#include <cvodes/cvodes_direct.h>         /* access to CVDls interface                */
+#include <cvodes/cvodes_diag.h>           /* access to CVDIAG linear solver interface */
+#include <sundials/sundials_types.h>      /* definition of realtype                   */
+#include <sundials/sundials_math.h>       /* contains the macros ABS, SUNSQR, and EXP */
 
 /* Shared Problem Constants */
 
@@ -117,8 +115,9 @@ static void PrintIntro2(void);
 static void PrintHeader2(void);
 static void PrintOutput2(realtype t, realtype erm, int qu, realtype hu);
 static realtype MaxError(N_Vector y, realtype t);
-static int PrepareNextRun(void *cvode_mem, int lmm, int miter, long int mu,
-                          long int ml);
+static int PrepareNextRun(void *cvode_mem, int lmm, int miter, N_Vector y, 
+                          SUNMatrix A, sunindextype mu, sunindextype ml,
+                          SUNLinearSolver LS);
 static void PrintErrOutput(realtype tol_factor);
 static void PrintFinalStats(void *cvode_mem, int miter, realtype ero);
 static void PrintErrInfo(int nerr);
@@ -126,14 +125,11 @@ static void PrintErrInfo(int nerr);
 /* Functions Called by the Solver */
 
 static int f1(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac1(long int N, realtype tn,
-                N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
-                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac1(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J,
+                void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
 static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac2(long int N, long int mu, long int ml, 
-                realtype tn, N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
+static int Jac2(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J, void *user_data,
                 N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private function to check function return values */
@@ -158,12 +154,16 @@ static int Problem1(void)
   realtype reltol=RTOL, abstol=ATOL, t, tout, ero, er;
   int miter, flag, temp_flag, iout, nerr=0;
   N_Vector y;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   booleantype firstrun;
   int qu;
   realtype hu;
 
   y = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   y = N_VNew_Serial(P1_NEQ);
@@ -191,7 +191,7 @@ static int Problem1(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
       
-    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, 0, 0);
+    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, y, A, 0, 0, LS);
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader1();
@@ -244,7 +244,7 @@ static int Problem1(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
       
-    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, 0, 0);     
+    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, y, A, 0, 0, LS);     
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader1();
@@ -275,7 +275,7 @@ static int Problem1(void)
   }
 
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
 
   return(nerr);
 }
@@ -331,19 +331,17 @@ static int f1(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   return(0);
 } 
 
-static int Jac1(long int N, realtype tn,
-                N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
-                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac1(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J, 
+                void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y0, y1;
 
   y0 = NV_Ith_S(y,0);
   y1 = NV_Ith_S(y,1);
 
-  DENSE_ELEM(J,0,1) = ONE;
-  DENSE_ELEM(J,1,0) = -TWO * P1_ETA * y0 * y1 - ONE;
-  DENSE_ELEM(J,1,1) = P1_ETA * (ONE - SUNSQR(y0));
+  SM_ELEMENT_D(J,0,1) = ONE;
+  SM_ELEMENT_D(J,1,0) = -TWO * P1_ETA * y0 * y1 - ONE;
+  SM_ELEMENT_D(J,1,1) = P1_ETA * (ONE - SUNSQR(y0));
 
   return(0);
 }
@@ -353,16 +351,20 @@ static int Problem2(void)
   realtype reltol=RTOL, abstol=ATOL, t, tout, er, erm, ero;
   int miter, flag, temp_flag, nerr=0;
   N_Vector y;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   booleantype firstrun;
   int qu, iout;
   realtype hu;
 
   y = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   y = N_VNew_Serial(P2_NEQ);
-  if(check_flag((void *)y, "N_VNew", 0)) return(1);
+  if(check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
 
   PrintIntro2();
 
@@ -388,7 +390,7 @@ static int Problem2(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
       
-    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, P2_MU, P2_ML);
+    flag = PrepareNextRun(cvode_mem, CV_ADAMS, miter, y, A, P2_MU, P2_ML, LS);
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader2();
@@ -441,7 +443,7 @@ static int Problem2(void)
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
     }
 
-    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, P2_MU, P2_ML);
+    flag = PrepareNextRun(cvode_mem, CV_BDF, miter, y, A, P2_MU, P2_ML, LS);
     if(check_flag(&flag, "PrepareNextRun", 1)) return(1);
 
     PrintHeader2();
@@ -471,7 +473,7 @@ static int Problem2(void)
   }
 
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
 
   return(nerr);
 }
@@ -515,11 +517,11 @@ static void PrintOutput2(realtype t, realtype erm, int qu, realtype hu)
 
 static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype d, *ydata, *dydata;
   
-  ydata = N_VGetArrayPointer_Serial(y);
-  dydata = N_VGetArrayPointer_Serial(ydot);
+  ydata = N_VGetArrayPointer(y);
+  dydata = N_VGetArrayPointer(ydot);
 
   /*
      Excluding boundaries, 
@@ -541,10 +543,8 @@ static int f2(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   return(0);
 }
 
-static int Jac2(long int N, long int mu, long int ml, 
-                realtype tn, N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
-                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac2(realtype tn, N_Vector y, N_Vector fy, SUNMatrix J, 
+                void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   int i, j, k;
   realtype *kthCol;
@@ -568,10 +568,10 @@ static int Jac2(long int N, long int mu, long int ml,
   for (j=0; j < P2_MESHY; j++) {
     for (i=0; i < P2_MESHX; i++) {
       k = i + j * P2_MESHX;
-      kthCol = BAND_COL(J,k);
-      BAND_COL_ELEM(kthCol,k,k) = -TWO;
-      if (i != P2_MESHX-1) BAND_COL_ELEM(kthCol,k+1,k) = P2_ALPH1;
-      if (j != P2_MESHY-1) BAND_COL_ELEM(kthCol,k+P2_MESHX,k) = P2_ALPH2;
+      kthCol = SM_COLUMN_B(J,k);
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -TWO;
+      if (i != P2_MESHX-1) SM_COLUMN_ELEMENT_B(kthCol,k+1,k) = P2_ALPH1;
+      if (j != P2_MESHY-1) SM_COLUMN_ELEMENT_B(kthCol,k+P2_MESHX,k) = P2_ALPH2;
     }
   }
 
@@ -580,12 +580,12 @@ static int Jac2(long int N, long int mu, long int ml,
 
 static realtype MaxError(N_Vector y, realtype t)
 {
-  long int i, j, k;
+  sunindextype i, j, k;
   realtype *ydata, er, ex=ZERO, yt, maxError=ZERO, ifact_inv, jfact_inv=ONE;
   
   if (t == ZERO) return(ZERO);
 
-  ydata = N_VGetArrayPointer_Serial(y);
+  ydata = N_VGetArrayPointer(y);
   if (t <= THIRTY) ex = SUNRexp(-TWO*t);
   
   for (j = 0; j < P2_MESHY; j++) {
@@ -602,8 +602,9 @@ static realtype MaxError(N_Vector y, realtype t)
   return(maxError);
 }
 
-static int PrepareNextRun(void *cvode_mem, int lmm, int miter, 
-                          long int mu, long int ml)
+static int PrepareNextRun(void *cvode_mem, int lmm, int miter, N_Vector y, 
+                          SUNMatrix A, sunindextype mu, sunindextype ml,
+                          SUNLinearSolver LS)
 {
   int flag = CV_SUCCESS;
   
@@ -622,38 +623,96 @@ static int PrepareNextRun(void *cvode_mem, int lmm, int miter,
   } else {
     printf("NEWTON\n");
     printf("Linear Solver           : ");
+
     switch(miter) {
+
     case DENSE_USER : 
       printf("Dense, User-Supplied Jacobian\n");
-      flag = CVDense(cvode_mem, P1_NEQ);
-      check_flag(&flag, "CVDense", 1);
-      if(flag != CV_SUCCESS) break;
-      flag = CVDlsSetDenseJacFn(cvode_mem, Jac1);
-      check_flag(&flag, "CVDlsSetDenseJacFn", 1);
+
+      /* Create dense SUNMatrix for use in linear solves */
+      A = SUNDenseMatrix(P1_NEQ, P1_NEQ);
+      if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+      /* Create dense SUNLinearSolver object for use by CVode */
+      LS = SUNDenseLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Set the user-supplied Jacobian routine Jac */
+      flag = CVDlsSetJacFn(cvode_mem, Jac1);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
       break;
-    case DENSE_DQ   : 
+
+    case DENSE_DQ : 
       printf("Dense, Difference Quotient Jacobian\n");
-      flag = CVDlsSetDenseJacFn(cvode_mem, NULL);
-      check_flag(&flag, "CVDlsSetDenseJacFn", 1);
+
+      /* Create dense SUNMatrix for use in linear solves */
+      A = SUNDenseMatrix(P1_NEQ, P1_NEQ);
+      if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+      /* Create dense SUNLinearSolver object for use by CVode */
+      LS = SUNDenseLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Use a difference quotient Jacobian */
+      flag = CVDlsSetJacFn(cvode_mem, NULL);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
       break;
-    case DIAG       : 
+
+    case DIAG : 
       printf("Diagonal Jacobian\n");
+     
+      /* Call CVDiag to initialize and attach the CVode-specific diagonal linear solver */
       flag = CVDiag(cvode_mem);
-      check_flag(&flag, "CVDiag", 1);
+      if(check_flag(&flag, "CVDiag", 1)) return(1);
       break;
-    case BAND_USER  : 
+
+    case BAND_USER : 
       printf("Band, User-Supplied Jacobian\n");
-      flag = CVBand(cvode_mem, P2_NEQ, mu, ml);
-      check_flag(&flag, "CVBand", 1);
-      if(flag != CV_SUCCESS) break;
-      flag = CVDlsSetBandJacFn(cvode_mem, Jac2);
-      check_flag(&flag, "CVDlsSetBandJacFn", 1);
+
+      /* Create band SUNMatrix for use in linear solves */
+      A = SUNBandMatrix(P2_NEQ, mu, ml, mu+ml);
+      if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+      /* Create banded SUNLinearSolver object for use by CVode */
+      LS = SUNBandLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Set the user-supplied Jacobian routine Jac */
+      flag = CVDlsSetJacFn(cvode_mem, Jac2);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
       break;
+
     case BAND_DQ  :   
       printf("Band, Difference Quotient Jacobian\n");
-      flag = CVDlsSetBandJacFn(cvode_mem, NULL);
-      check_flag(&flag, "CVDlsSetBandJacFn", 1);
-      break;    
+
+      /* Create band SUNMatrix for use in linear solves */
+      A = SUNBandMatrix(P2_NEQ, mu, ml, mu+ml);
+      if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+      /* Create banded SUNLinearSolver object for use by CVode */
+      LS = SUNBandLinearSolver(y, A);
+      if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+      /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+      flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+      if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+      /* Use a difference quotient Jacobian */
+      flag = CVDlsSetJacFn(cvode_mem, NULL);
+      if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
+      break;
     }
   }
 
@@ -675,8 +734,8 @@ static void PrintErrOutput(realtype tol_factor)
 
 static void PrintFinalStats(void *cvode_mem, int miter, realtype ero)
 {
-  long int lenrw, leniw, nst, nfe, nsetups, nni, ncfn, netf;
-  long int lenrwLS, leniwLS, nje, nfeLS;
+  long int lenrw, leniw, lenrwLS, leniwLS;
+  long int nst, nfe, nsetups, nni, ncfn, netf, nje, nfeLS;
   int flag;
 
   flag = CVodeGetWorkSpace(cvode_mem, &lenrw, &leniw);
@@ -695,8 +754,8 @@ static void PrintFinalStats(void *cvode_mem, int miter, realtype ero)
   check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
 
   printf("\n Final statistics for this run:\n\n");
-  printf(" CVode real workspace length              = %4ld \n", lenrw);
-  printf(" CVode integer workspace length           = %4ld \n", leniw);
+  printf(" CVode real workspace length              = %4ld \n",  lenrw);
+  printf(" CVode integer workspace length           = %4ld \n",  leniw);
   printf(" Number of steps                          = %4ld \n",  nst);
   printf(" Number of f-s                            = %4ld \n",  nfe);
   printf(" Number of setups                         = %4ld \n",  nsetups);
@@ -705,36 +764,23 @@ static void PrintFinalStats(void *cvode_mem, int miter, realtype ero)
   printf(" Number of error test failures            = %4ld \n\n",netf);
   
   if (miter != FUNC) {
-    switch(miter) {
-    case DENSE_USER :
-    case DENSE_DQ   :
+    if (miter != DIAG) {
       flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
       check_flag(&flag, "CVDlsGetNumJacEvals", 1);
       flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
       check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
       flag = CVDlsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
       check_flag(&flag, "CVDlsGetWorkSpace", 1);
-      break;
-    case BAND_USER  :
-    case BAND_DQ    :
-      flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
-      check_flag(&flag, "CVDlsGetNumJacEvals", 1);
-      flag = CVDlsGetNumRhsEvals(cvode_mem, &nfeLS);
-      check_flag(&flag, "CVDlsGetNumRhsEvals", 1);
-      flag = CVDlsGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
-      check_flag(&flag, "CVDlsGetWorkSpace", 1);
-      break;  
-    case DIAG       :
+    } else {
       nje = nsetups;
       flag = CVDiagGetNumRhsEvals(cvode_mem, &nfeLS);
       check_flag(&flag, "CVDiagGetNumRhsEvals", 1);
       flag = CVDiagGetWorkSpace(cvode_mem, &lenrwLS, &leniwLS);
       check_flag(&flag, "CVDiagGetWorkSpace", 1);
-      break;
     }
     printf(" Linear solver real workspace length      = %4ld \n", lenrwLS);
     printf(" Linear solver integer workspace length   = %4ld \n", leniwLS);
-    printf(" Number of Jacobian evaluations           = %4ld  \n", nje);
+    printf(" Number of Jacobian evaluations           = %4ld \n", nje);
     printf(" Number of f evals. in linear solver      = %4ld \n\n", nfeLS);
   }
   
diff --git a/examples/cvodes/serial/cvsDirectDemo_ls.out b/examples/cvodes/serial/cvsDirectDemo_ls.out
index 9aa156f..0f00812 100644
--- a/examples/cvodes/serial/cvsDirectDemo_ls.out
+++ b/examples/cvodes/serial/cvsDirectDemo_ls.out
@@ -12,9 +12,9 @@ Iteration               : FUNCTIONAL
 
      t           x              xdot         qu     hu 
    1.39284     1.68010e+00   -2.91056e-01    5    9.8626e-02
-   3.60761    -2.12392e-05   -3.16877e+00    5    2.2756e-02
+   3.60761    -2.12391e-05   -3.16877e+00    5    2.2757e-02
    5.82239    -1.68010e+00    2.91060e-01    4    1.4079e-01
-   8.03716     9.57612e-05    3.16900e+00    5    2.0348e-02
+   8.03716     9.57608e-05    3.16900e+00    5    2.0348e-02
 
  Final statistics for this run:
 
@@ -53,9 +53,9 @@ Linear Solver           : Dense, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   23 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    5  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    5 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 19.908 
@@ -71,7 +71,7 @@ Linear Solver           : Dense, Difference Quotient Jacobian
    1.39284     1.68010e+00   -2.91056e-01    5    6.5835e-02
    3.60761    -2.28046e-05   -3.16879e+00    6    3.1773e-02
    5.82239    -1.68010e+00    2.91059e-01    6    9.3514e-02
-   8.03716    -9.84882e-06    3.16869e+00    6    2.8095e-02
+   8.03716    -9.84742e-06    3.16869e+00    6    2.8096e-02
 
  Final statistics for this run:
 
@@ -84,9 +84,9 @@ Linear Solver           : Dense, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   15 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    4  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    4 
  Number of f evals. in linear solver      =    8 
 
  Error overrun = 22.805 
@@ -101,26 +101,26 @@ Linear Solver           : Diagonal Jacobian
      t           x              xdot         qu     hu 
    1.39284     1.68010e+00   -2.91054e-01    6    5.9553e-02
    3.60761     6.36071e-05   -3.16853e+00    6    2.8912e-02
-   5.82239    -1.68011e+00    2.91057e-01    5    9.8199e-02
-   8.03716    -3.15637e-05    3.16849e+00    6    1.5418e-02
+   5.82239    -1.68011e+00    2.91057e-01    5    9.8149e-02
+   8.03716    -7.70359e-05    3.16847e+00    6    2.3224e-02
 
  Final statistics for this run:
 
  CVode real workspace length              =  130 
  CVode integer workspace length           =   69 
- Number of steps                          =  241 
- Number of f-s                            =  340 
- Number of setups                         =   42 
- Number of nonlinear iterations           =  336 
+ Number of steps                          =  238 
+ Number of f-s                            =  330 
+ Number of setups                         =   40 
+ Number of nonlinear iterations           =  326 
  Number of nonlinear convergence failures =    0 
- Number of error test failures            =   21 
+ Number of error test failures            =   20 
 
  Linear solver real workspace length      =    6 
  Linear solver integer workspace length   =    3 
- Number of Jacobian evaluations           =   42  
- Number of f evals. in linear solver      =   42 
+ Number of Jacobian evaluations           =   40  
+ Number of f evals. in linear solver      =   40 
 
- Error overrun = 63.607 
+ Error overrun = 77.036 
 
 
 -------------------------------------------------------------
@@ -171,9 +171,9 @@ Linear Solver           : Dense, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   18 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    5  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    5 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 154.312 
@@ -202,9 +202,9 @@ Linear Solver           : Dense, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =   17 
 
- Linear solver real workspace length      =    8 
- Linear solver integer workspace length   =    2 
- Number of Jacobian evaluations           =    6  
+ Linear solver real workspace length      =    6 
+ Linear solver integer workspace length   =   10 
+ Number of Jacobian evaluations           =    6 
  Number of f evals. in linear solver      =   12 
 
  Error overrun = 96.174 
@@ -220,7 +220,7 @@ Linear Solver           : Diagonal Jacobian
    1.39284     1.68010e+00   -2.91056e-01    5    1.1430e-01
    3.60761    -9.83501e-05   -3.16900e+00    5    1.6712e-02
    5.82239    -1.68009e+00    2.91063e-01    4    8.1261e-02
-   8.03716     1.66641e-04    3.16920e+00    4    1.0547e-02
+   8.03716     1.66640e-04    3.16920e+00    4    1.0546e-02
 
  Final statistics for this run:
 
@@ -238,7 +238,7 @@ Linear Solver           : Diagonal Jacobian
  Number of Jacobian evaluations           =   39  
  Number of f evals. in linear solver      =   39 
 
- Error overrun = 166.641 
+ Error overrun = 166.640 
 
 
 -------------------------------------------------------------
@@ -262,17 +262,17 @@ Iteration               : FUNCTIONAL
      0.100    5.2543e-07    4     4.1413e-02
      1.000    1.2207e-06    5     6.8243e-02
     10.000    9.7711e-07    3     2.8481e-01
-   100.000    2.1231e-07    1     1.3200e-01
+   100.000    2.2510e-07    1     6.7722e-01
 
  Final statistics for this run:
 
  CVode real workspace length              =  521 
  CVode integer workspace length           =   69 
- Number of steps                          =  339 
+ Number of steps                          =  341 
  Number of f-s                            =  602 
  Number of setups                         =    0 
  Number of nonlinear iterations           =  598 
- Number of nonlinear convergence failures =   80 
+ Number of nonlinear convergence failures =   79 
  Number of error test failures            =    0 
 
  Error overrun = 1.221 
@@ -288,8 +288,8 @@ Linear Solver           : Diagonal Jacobian
      0.010    1.3734e-07    3     1.0327e-02
      0.100    2.4956e-06    3     2.3048e-02
      1.000    4.2328e-06    4     4.3778e-02
-    10.000    9.7310e-07    4     3.1286e-01
-   100.000    1.0443e-09    1     3.7883e+02
+    10.000    9.7303e-07    4     3.1286e-01
+   100.000    1.1241e-09    1     3.7371e+02
 
  Final statistics for this run:
 
@@ -334,9 +334,9 @@ Linear Solver           : Band, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    6 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 0.608 
@@ -353,7 +353,7 @@ Linear Solver           : Band, Difference Quotient Jacobian
      0.100    5.7337e-07    4     4.2111e-02
      1.000    7.3281e-07    5     6.3684e-02
     10.000    3.8507e-07    5     2.6026e-01
-   100.000    4.1035e-12    1     6.2591e+01
+   100.000    4.1037e-12    1     6.2591e+01
 
  Final statistics for this run:
 
@@ -366,9 +366,9 @@ Linear Solver           : Band, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    1 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =   18 
 
  Error overrun = 0.733 
@@ -384,17 +384,17 @@ Iteration               : FUNCTIONAL
      0.100    5.2896e-06    3     1.7769e-02
      1.000    2.3209e-06    5     7.5291e-02
     10.000    1.2861e-06    5     2.7791e-01
-   100.000    2.0520e-07    1     8.3614e-01
+   100.000    2.8424e-07    1     2.5672e-01
 
  Final statistics for this run:
 
  CVode real workspace length              =  346 
  CVode integer workspace length           =   62 
- Number of steps                          =  373 
- Number of f-s                            =  690 
+ Number of steps                          =  372 
+ Number of f-s                            =  693 
  Number of setups                         =    0 
- Number of nonlinear iterations           =  686 
- Number of nonlinear convergence failures =   55 
+ Number of nonlinear iterations           =  689 
+ Number of nonlinear convergence failures =   56 
  Number of error test failures            =    1 
 
  Error overrun = 5.290 
@@ -410,24 +410,24 @@ Linear Solver           : Diagonal Jacobian
      0.010    5.6365e-07    2     8.1241e-03
      0.100    7.9753e-07    4     1.8910e-02
      1.000    5.9100e-06    5     5.1976e-02
-    10.000    2.1569e-06    4     3.1156e-01
-   100.000    6.3727e-10    1     1.6301e+02
+    10.000    2.1547e-06    4     3.1113e-01
+   100.000    4.2213e-09    1     1.3897e+02
 
  Final statistics for this run:
 
  CVode real workspace length              =  346 
  CVode integer workspace length           =   62 
- Number of steps                          =  177 
- Number of f-s                            =  259 
- Number of setups                         =   46 
- Number of nonlinear iterations           =  255 
+ Number of steps                          =  180 
+ Number of f-s                            =  271 
+ Number of setups                         =   47 
+ Number of nonlinear iterations           =  267 
  Number of nonlinear convergence failures =    2 
  Number of error test failures            =    5 
 
  Linear solver real workspace length      =   75 
  Linear solver integer workspace length   =    3 
- Number of Jacobian evaluations           =   46  
- Number of f evals. in linear solver      =   46 
+ Number of Jacobian evaluations           =   47  
+ Number of f evals. in linear solver      =   47 
 
  Error overrun = 5.910 
 
@@ -456,9 +456,9 @@ Linear Solver           : Band, User-Supplied Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    2 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =    0 
 
  Error overrun = 5.278 
@@ -488,9 +488,9 @@ Linear Solver           : Band, Difference Quotient Jacobian
  Number of nonlinear convergence failures =    0 
  Number of error test failures            =    1 
 
- Linear solver real workspace length      =  425 
- Linear solver integer workspace length   =   25 
- Number of Jacobian evaluations           =    3  
+ Linear solver real workspace length      =  300 
+ Linear solver integer workspace length   =   60 
+ Number of Jacobian evaluations           =    3 
  Number of f evals. in linear solver      =   18 
 
  Error overrun = 5.997 
diff --git a/examples/cvodes/serial/cvsDiurnal_FSA_kry.c b/examples/cvodes/serial/cvsDiurnal_FSA_kry.c
index c6b620c..895f004 100644
--- a/examples/cvodes/serial/cvsDiurnal_FSA_kry.c
+++ b/examples/cvodes/serial/cvsDiurnal_FSA_kry.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -24,7 +20,7 @@
  * The PDE system is treated by central differences on a uniform
  * 10 x 10 mesh, with simple polynomial initial profiles.
  * The problem is solved with CVODES, with the BDF/GMRES method
- * (i.e. using the CVSPGMR linear solver) and the block-diagonal
+ * (i.e. using the SUNSPGMR linear solver) and the block-diagonal
  * part of the Newton matrix as a left preconditioner. A copy of
  * the block-diagonal part of the Jacobian is saved and
  * conditionally reused within the Precond routine.
@@ -44,20 +40,20 @@
  *    % cvsDiurnal_FSA_kry -sensi sensi_meth err_con
  * where sensi_meth is one of {sim, stg, stg1} and err_con is one of
  * {t, f}.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>            /* main CVODES header file */
-#include <cvodes/cvodes_spgmr.h>      /* use CVSPGMR linear */
-#include <nvector/nvector_serial.h>   /* definitions N_Vector */
-#include <sundials/sundials_dense.h>  /* use generic DENSE solver for prec. */
-#include <sundials/sundials_types.h>  /* definition of realtype */
-#include <sundials/sundials_math.h>   /* contains macros SUNSQR and EXP */
+#include <cvodes/cvodes.h>             /* main CVODES header file              */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvodes/cvodes_spils.h>       /* access to CVSpils interface          */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* contains the macros ABS, SUNSQR, EXP */
 
 /* Problem Constants */
 
@@ -108,7 +104,7 @@
    IJKth(vdata,i,j,k) references the element in the vdata array for
    species i at mesh point (j,k), where 1 <= i <= NUM_SPECIES,
    0 <= j <= MX-1, 0 <= k <= MZ-1. The vdata array is obtained via
-   the macro call vdata = N_VGetArrayPointer_Serial(v), where v is an N_Vector. 
+   the call vdata = N_VGetArrayPointer(v), where v is an N_Vector. 
    For each mesh point (j,k), the elements for species i and i+1 are
    contiguous within vdata.
 
@@ -127,7 +123,7 @@
 typedef struct {
   realtype *p;
   realtype **P[MX][MZ], **Jbd[MX][MZ];
-  long int *pivot[MX][MZ];
+  sunindextype *pivot[MX][MZ];
   realtype q4, om, dx, dz, hdco, haco, vdco;
 } *UserData;
 
@@ -137,13 +133,12 @@ typedef struct {
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int Precond(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
-                   booleantype *jcurPtr, realtype gamma, void *user_data,
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   booleantype *jcurPtr, realtype gamma, void *user_data);
 
 static int PSolve(realtype tn, N_Vector y, N_Vector fy,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 /* Prototypes of private functions */
 
@@ -168,6 +163,7 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 int main(int argc, char *argv[])
 {
   void *cvode_mem;
+  SUNLinearSolver LS;
   UserData data;
   realtype abstol, reltol, t, tout;
   N_Vector y;
@@ -185,6 +181,7 @@ int main(int argc, char *argv[])
   y = NULL;
   data = NULL;
   cvode_mem = NULL;
+  LS = NULL;
 
   /* Process arguments */
   ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
@@ -220,10 +217,16 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Attach CVSPGMR linear solver */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+  /* Create the SUNSPGMR linear solver with left
+     preconditioning and the default Krylov dimension */
+  LS = SUNSPGMR(y, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Attach the linear sovler */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
+  /* Set the preconditioner solve and setup functions */
   flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
   if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
 
@@ -240,8 +243,8 @@ int main(int argc, char *argv[])
     if(check_flag((void *)pbar, "malloc", 2)) return(1);
     for(is=0; is<NS; is++) pbar[is] = data->p[plist[is]];
 
-    uS = N_VCloneVectorArray_Serial(NS, y);
-    if(check_flag((void *)uS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    uS = N_VCloneVectorArray(NS, y);
+    if(check_flag((void *)uS, "N_VCloneVectorArray", 0)) return(1);
     for(is=0;is<NS;is++)
       N_VConst(ZERO,uS[is]);
 
@@ -300,14 +303,15 @@ int main(int argc, char *argv[])
   PrintFinalStats(cvode_mem, sensi);
 
   /* Free memory */
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
   if (sensi) {
-    N_VDestroyVectorArray_Serial(uS, NS);
+    N_VDestroyVectorArray(uS, NS);
     free(pbar);
     free(plist);
   }
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   return(0);
 }
@@ -334,8 +338,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   realtype Q1, Q2, C3, A3, A4, KH, VEL, KV0;
 
   data = (UserData) user_data;
-  ydata = N_VGetArrayPointer_Serial(y);
-  dydata = N_VGetArrayPointer_Serial(ydot);
+  ydata = N_VGetArrayPointer(y);
+  dydata = N_VGetArrayPointer(ydot);
 
   /* Load problem coefficients and parameters */
 
@@ -429,12 +433,11 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
  */
 
 static int Precond(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
-                   booleantype *jcurPtr, realtype gamma, void *user_data,
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   realtype c1, c2, czdn, czup, diag, zdn, zup, q4coef, delz, verdco, hordco;
   realtype **(*P)[MZ], **(*Jbd)[MZ];
-  long int *(*pivot)[MZ];
+  sunindextype *(*pivot)[MZ];
   int ier, jx, jz;
   realtype *ydata, **a, **j;
   UserData data;
@@ -445,7 +448,7 @@ static int Precond(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
   P = data->P;
   Jbd = data->Jbd;
   pivot = data->pivot;
-  ydata = N_VGetArrayPointer_Serial(y);
+  ydata = N_VGetArrayPointer(y);
 
   /* Load problem coefficients and parameters */
   Q1 = data->p[0];
@@ -459,18 +462,18 @@ static int Precond(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
 
   if (jok) {
 
-  /* jok = TRUE: Copy Jbd to P */
+  /* jok = SUNTRUE: Copy Jbd to P */
 
     for (jz=0; jz < MZ; jz++)
       for (jx=0; jx < MX; jx++)
         denseCopy(Jbd[jx][jz], P[jx][jz], NUM_SPECIES, NUM_SPECIES);
 
-  *jcurPtr = FALSE;
+  *jcurPtr = SUNFALSE;
 
   }
 
   else {
-  /* jok = FALSE: Generate Jbd from scratch and copy to P */
+  /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
 
   /* Make local copies of problem variables, for efficiency. */
 
@@ -501,7 +504,7 @@ static int Precond(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
       }
     }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
 
   }
 
@@ -531,10 +534,10 @@ static int Precond(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
 static int PSolve(realtype tn, N_Vector y, N_Vector fy,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype **(*P)[MZ];
-  long int *(*pivot)[MZ];
+  sunindextype *(*pivot)[MZ];
   int jx, jz;
   realtype *zdata, *v;
   UserData data;
@@ -544,7 +547,7 @@ static int PSolve(realtype tn, N_Vector y, N_Vector fy,
   data = (UserData) user_data;
   P = data->P;
   pivot = data->pivot;
-  zdata = N_VGetArrayPointer_Serial(z);
+  zdata = N_VGetArrayPointer(z);
 
   N_VScale(ONE, r, z);
 
@@ -574,16 +577,16 @@ static int PSolve(realtype tn, N_Vector y, N_Vector fy,
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -602,9 +605,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -635,7 +638,7 @@ static UserData AllocUserData(void)
     for (jz=0; jz < MZ; jz++) {
       (data->P)[jx][jz] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
       (data->Jbd)[jx][jz] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jz] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jz] = newIndexArray(NUM_SPECIES);
     }
   }
 
@@ -712,7 +715,7 @@ static void SetInitialProfiles(N_Vector y, realtype dx, realtype dz)
 
   /* Set pointer to data array in vector y. */
 
-  ydata = N_VGetArrayPointer_Serial(y);
+  ydata = N_VGetArrayPointer(y);
 
   /* Load initial profiles of c1 and c2 into y vector */
 
@@ -741,7 +744,7 @@ static void PrintOutput(void *cvode_mem, realtype t, N_Vector y)
   realtype hu;
   realtype *ydata;
 
-  ydata = N_VGetArrayPointer_Serial(y);
+  ydata = N_VGetArrayPointer(y);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -784,7 +787,7 @@ static void PrintOutputS(N_Vector *uS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(uS[0]);
+  sdata = N_VGetArrayPointer(uS[0]);
 
   printf("                                ----------------------------------------\n"); 
   printf("                                Sensitivity 1  ");
@@ -804,7 +807,7 @@ static void PrintOutputS(N_Vector *uS)
   printf("%12.4e %12.4e \n", IJKth(sdata,2,0,0), IJKth(sdata,2,MX-1,MZ-1));
 #endif
 
-  sdata = N_VGetArrayPointer_Serial(uS[1]);
+  sdata = N_VGetArrayPointer(uS[1]);
 
   printf("                                ----------------------------------------\n"); 
   printf("                                Sensitivity 2  ");
diff --git a/examples/cvodes/serial/cvsDiurnal_FSA_kry.out b/examples/cvodes/serial/cvsDiurnal_FSA_kry_-sensi_sim_t.out
similarity index 73%
copy from examples/cvodes/serial/cvsDiurnal_FSA_kry.out
copy to examples/cvodes/serial/cvsDiurnal_FSA_kry_-sensi_sim_t.out
index ac1d121..a5a2a71 100644
--- a/examples/cvodes/serial/cvsDiurnal_FSA_kry.out
+++ b/examples/cvodes/serial/cvsDiurnal_FSA_kry_-sensi_sim_t.out
@@ -5,7 +5,7 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
 ========================================================================
      T     Q       H      NST                    Bottom left  Top right 
 ========================================================================
-7.200e+03  3  3.039e+01   552
+7.200e+03  3  3.239e+01   644
                                 Solution         1.0593e+04   1.1152e+04 
                                                  2.5567e+11   2.6917e+11 
                                 ----------------------------------------
@@ -15,17 +15,17 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                 Sensitivity 2   -4.4900e+14  -4.9768e+14 
                                                 -2.5039e+18  -2.7672e+18 
 ------------------------------------------------------------------------
-1.440e+04  3  2.312e+01  1032
+1.440e+04  2  2.205e+01  1009
                                 Solution         6.9172e+06   7.2517e+06 
                                                  2.6829e+11   2.8137e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -4.2432e+22  -4.4483e+22 
-                                                 6.2762e+22   6.6563e+22 
+                                                 6.2762e+22   6.6564e+22 
                                 ----------------------------------------
                                 Sensitivity 2   -4.8955e+17  -5.3580e+17 
-                                                -7.1116e+21  -7.7236e+21 
+                                                -7.1116e+21  -7.7237e+21 
 ------------------------------------------------------------------------
-2.160e+04  3  4.952e+01  1884
+2.160e+04  2  4.049e+01  1600
                                 Solution         2.7558e+07   2.9196e+07 
                                                  3.1024e+11   3.3000e+11 
                                 ----------------------------------------
@@ -33,9 +33,9 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                                  4.0588e+23   4.4683e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -8.2851e+18  -9.3611e+18 
-                                                -8.2851e+22  -9.3662e+22 
+                                                -8.2852e+22  -9.3662e+22 
 ------------------------------------------------------------------------
-2.880e+04  3  7.302e+01  2213
+2.880e+04  3  6.108e+01  1899
                                 Solution         8.9631e+06   9.8602e+06 
                                                  3.4824e+11   3.8331e+11 
                                 ----------------------------------------
@@ -45,98 +45,98 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                 Sensitivity 2   -5.2367e+18  -6.4007e+18 
                                                 -1.8450e+23  -2.2574e+23 
 ------------------------------------------------------------------------
-3.600e+04  4  3.366e+01  2302
+3.600e+04  3  3.424e+01  2018
                                 Solution         1.4433e+04   1.6660e+04 
                                                  3.4814e+11   4.0186e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -8.8547e+19  -1.0220e+20 
-                                                 5.6473e+23   7.6273e+23 
+                                                 5.6474e+23   7.6273e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -9.0220e+15  -1.2170e+16 
                                                 -1.9753e+23  -2.6679e+23 
 ------------------------------------------------------------------------
-4.320e+04  4  4.497e+02  2522
-                                Solution        -6.3095e-09  -6.9919e-09 
+4.320e+04  4  3.490e+02  2538
+                                Solution         2.5038e-13   2.7023e-13 
                                                  3.4900e+11   4.0867e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.1669e+08  -1.4148e+08 
+                                Sensitivity 1   -1.5796e+05  -2.3807e+05 
                                                  5.7083e+23   7.9553e+23 
                                 ----------------------------------------
-                                Sensitivity 2    1.0171e+05   1.1062e+05 
+                                Sensitivity 2   -1.7187e+00  -5.1787e+01 
                                                 -1.9969e+23  -2.7830e+23 
 ------------------------------------------------------------------------
-5.040e+04  4  4.497e+02  2538
-                                Solution         2.7652e-09   2.9811e-09 
+5.040e+04  4  3.490e+02  2559
+                                Solution        -6.0654e-16  -1.7637e-15 
                                                  3.5570e+11   4.1225e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -1.7614e+07  -1.8570e+07 
+                                Sensitivity 1   -1.0195e+03  -2.4393e+03 
                                                  5.9553e+23   8.1823e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -3.9136e+03  -4.6763e+03 
+                                Sensitivity 2   -1.0096e-02  -2.7454e-02 
                                                 -2.0833e+23  -2.8624e+23 
 ------------------------------------------------------------------------
-5.760e+04  3  3.862e+01  2580
-                                Solution         4.0865e-09   1.2653e-08 
+5.760e+04  4  1.634e+02  2584
+                                Solution         4.4474e-08   1.1903e-07 
                                                  3.6425e+11   4.1628e+11 
                                 ----------------------------------------
-                                Sensitivity 1    9.5471e+08   2.9501e+09 
+                                Sensitivity 1   -1.8179e+09  -4.8687e+09 
                                                  6.2592e+23   8.4334e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -1.2170e+04  -2.7099e+04 
+                                Sensitivity 2   -1.7780e+04  -5.4422e+04 
                                                 -2.1896e+23  -2.9502e+23 
 ------------------------------------------------------------------------
-6.480e+04  4  1.536e+02  2636
-                                Solution         3.6356e-08   1.1341e-07 
+6.480e+04  3  9.518e+01  2636
+                                Solution        -3.1083e-09  -1.3895e-08 
                                                  3.6334e+11   4.2182e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -2.9344e+09  -9.1186e+09 
+                                Sensitivity 1   -5.8937e+08  -2.6001e+09 
                                                  6.2461e+23   8.7310e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -8.4752e+03  -3.0885e+04 
-                                                -2.1850e+23  -3.0543e+23 
+                                Sensitivity 2   -5.2314e+03  -2.6357e+04 
+                                                -2.1851e+23  -3.0544e+23 
 ------------------------------------------------------------------------
-7.200e+04  4  1.536e+02  2683
-                                Solution         4.3358e-09   1.5100e-08 
+7.200e+04  4  1.729e+02  2699
+                                Solution        -1.8227e-08   5.8153e-08 
                                                  3.6192e+11   4.3354e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -2.7350e+08  -9.6001e+08 
+                                Sensitivity 1    1.2752e+09  -4.6275e+09 
                                                  6.2310e+23   9.2797e+23 
                                 ----------------------------------------
-                                Sensitivity 2    3.7283e+07   1.2247e+08 
+                                Sensitivity 2    8.7152e+06  -4.0981e+07 
                                                 -2.1798e+23  -3.2463e+23 
 ------------------------------------------------------------------------
-7.920e+04  4  4.008e+02  2711
-                                Solution        -2.1912e-15  -7.8117e-15 
+7.920e+04  4  1.729e+02  2741
+                                Solution        -1.1560e-08   8.4429e-09 
                                                  3.6148e+11   4.4474e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.0220e+04   3.6486e+04 
+                                Sensitivity 1   -3.9209e+09   3.0221e+09 
                                                  6.2481e+23   9.8067e+23 
                                 ----------------------------------------
-                                Sensitivity 2    1.2136e+00   4.0255e+00 
+                                Sensitivity 2    2.4469e+07  -1.1022e+07 
                                                 -2.1858e+23  -3.4307e+23 
 ------------------------------------------------------------------------
-8.640e+04  4  4.008e+02  2729
-                                Solution         1.3608e-20   4.5805e-20 
+8.640e+04  4  1.729e+02  2783
+                                Solution        -2.0626e-09   3.2649e-10 
                                                  3.6318e+11   4.4524e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.2856e-02   5.0845e-02 
-                                                 6.3248e+23   9.8819e+23 
+                                Sensitivity 1   -3.1145e+09   6.7710e+08 
+                                                 6.3248e+23   9.8820e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -3.1311e-05  -9.6668e-05 
+                                Sensitivity 2   -2.1820e+07  -4.8408e+06 
                                                 -2.2126e+23  -3.4570e+23 
 ------------------------------------------------------------------------
 
 Final Statistics
 
-nst     =  2729
+nst     =  2783
 
-nfe     =  4101
-netf    =   203    nsetups  =   542
-nni     =  4097    ncfn     =     9
+nfe     =  3956
+netf    =   186    nsetups  =   534
+nni     =  3952    ncfn     =    12
 
-nfSe    =  8202    nfeS     = 16404
+nfSe    =  7912    nfeS     = 15824
 netfs   =     0    nsetupsS =     0
 nniS    =     0    ncfnS    =     0
 
-nli     =  8349    ncfl     =     0
-npe     =    63    nps      = 17946
+nli     =  8402    ncfl     =     0
+npe     =    69    nps      = 18230
diff --git a/examples/cvodes/serial/cvsDiurnal_FSA_kry.out b/examples/cvodes/serial/cvsDiurnal_FSA_kry_-sensi_stg_t.out
similarity index 72%
rename from examples/cvodes/serial/cvsDiurnal_FSA_kry.out
rename to examples/cvodes/serial/cvsDiurnal_FSA_kry_-sensi_stg_t.out
index ac1d121..e26fb27 100644
--- a/examples/cvodes/serial/cvsDiurnal_FSA_kry.out
+++ b/examples/cvodes/serial/cvsDiurnal_FSA_kry_-sensi_stg_t.out
@@ -1,11 +1,11 @@
 
 2-species diurnal advection-diffusion problem
-Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+Sensitivity: YES ( STAGGERED + FULL ERROR CONTROL )
 
 ========================================================================
      T     Q       H      NST                    Bottom left  Top right 
 ========================================================================
-7.200e+03  3  3.039e+01   552
+7.200e+03  3  2.785e+01   492
                                 Solution         1.0593e+04   1.1152e+04 
                                                  2.5567e+11   2.6917e+11 
                                 ----------------------------------------
@@ -15,7 +15,7 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                 Sensitivity 2   -4.4900e+14  -4.9768e+14 
                                                 -2.5039e+18  -2.7672e+18 
 ------------------------------------------------------------------------
-1.440e+04  3  2.312e+01  1032
+1.440e+04  3  5.375e+01   617
                                 Solution         6.9172e+06   7.2517e+06 
                                                  2.6829e+11   2.8137e+11 
                                 ----------------------------------------
@@ -23,120 +23,120 @@ Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
                                                  6.2762e+22   6.6563e+22 
                                 ----------------------------------------
                                 Sensitivity 2   -4.8955e+17  -5.3580e+17 
-                                                -7.1116e+21  -7.7236e+21 
+                                                -7.1115e+21  -7.7236e+21 
 ------------------------------------------------------------------------
-2.160e+04  3  4.952e+01  1884
+2.160e+04  2  1.830e+01   759
                                 Solution         2.7558e+07   2.9196e+07 
                                                  3.1024e+11   3.3000e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -1.6903e+23  -1.7907e+23 
                                                  4.0588e+23   4.4683e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -8.2851e+18  -9.3611e+18 
+                                Sensitivity 2   -8.2851e+18  -9.3610e+18 
                                                 -8.2851e+22  -9.3662e+22 
 ------------------------------------------------------------------------
-2.880e+04  3  7.302e+01  2213
+2.880e+04  5  2.525e+02   833
                                 Solution         8.9631e+06   9.8602e+06 
                                                  3.4824e+11   3.8331e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -5.4975e+22  -6.0476e+22 
-                                                 5.8239e+23   7.0579e+23 
+                                                 5.8239e+23   7.0578e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -5.2367e+18  -6.4007e+18 
                                                 -1.8450e+23  -2.2574e+23 
 ------------------------------------------------------------------------
-3.600e+04  4  3.366e+01  2302
+3.600e+04  5  1.766e+02   862
                                 Solution         1.4433e+04   1.6660e+04 
                                                  3.4814e+11   4.0186e+11 
                                 ----------------------------------------
                                 Sensitivity 1   -8.8547e+19  -1.0220e+20 
-                                                 5.6473e+23   7.6273e+23 
+                                                 5.6474e+23   7.6273e+23 
                                 ----------------------------------------
                                 Sensitivity 2   -9.0220e+15  -1.2170e+16 
                                                 -1.9753e+23  -2.6679e+23 
 ------------------------------------------------------------------------
-4.320e+04  4  4.497e+02  2522
-                                Solution        -6.3095e-09  -6.9919e-09 
+4.320e+04  4  3.385e+02   913
+                                Solution         1.2273e-07   1.4964e-07 
                                                  3.4900e+11   4.0867e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.1669e+08  -1.4148e+08 
+                                Sensitivity 1   -2.7444e+09  -3.2648e+09 
                                                  5.7083e+23   7.9553e+23 
                                 ----------------------------------------
-                                Sensitivity 2    1.0171e+05   1.1062e+05 
+                                Sensitivity 2    1.3958e+06   3.1732e+06 
                                                 -1.9969e+23  -2.7830e+23 
 ------------------------------------------------------------------------
-5.040e+04  4  4.497e+02  2538
-                                Solution         2.7652e-09   2.9811e-09 
+5.040e+04  5  5.094e+02   927
+                                Solution         9.3338e-09   1.1392e-08 
                                                  3.5570e+11   4.1225e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -1.7614e+07  -1.8570e+07 
+                                Sensitivity 1   -4.1050e+08  -4.9484e+08 
                                                  5.9553e+23   8.1823e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -3.9136e+03  -4.6763e+03 
+                                Sensitivity 2   -9.0890e+07  -2.0488e+08 
                                                 -2.0833e+23  -2.8624e+23 
 ------------------------------------------------------------------------
-5.760e+04  3  3.862e+01  2580
-                                Solution         4.0865e-09   1.2653e-08 
+5.760e+04  4  1.971e+02   954
+                                Solution        -8.1495e-06  -9.8457e-06 
                                                  3.6425e+11   4.1628e+11 
                                 ----------------------------------------
-                                Sensitivity 1    9.5471e+08   2.9501e+09 
+                                Sensitivity 1    4.6030e+10   5.5619e+10 
                                                  6.2592e+23   8.4334e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -1.2170e+04  -2.7099e+04 
+                                Sensitivity 2   -6.1436e+06  -1.4104e+07 
                                                 -2.1896e+23  -2.9502e+23 
 ------------------------------------------------------------------------
-6.480e+04  4  1.536e+02  2636
-                                Solution         3.6356e-08   1.1341e-07 
+6.480e+04  4  1.580e+02  1004
+                                Solution        -3.2225e-06   3.3806e-06 
                                                  3.6334e+11   4.2182e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -2.9344e+09  -9.1186e+09 
+                                Sensitivity 1   -3.0936e+10   3.2585e+10 
                                                  6.2461e+23   8.7310e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -8.4752e+03  -3.0885e+04 
-                                                -2.1850e+23  -3.0543e+23 
+                                Sensitivity 2    2.4428e+08  -2.4126e+08 
+                                                -2.1851e+23  -3.0543e+23 
 ------------------------------------------------------------------------
-7.200e+04  4  1.536e+02  2683
-                                Solution         4.3358e-09   1.5100e-08 
+7.200e+04  5  5.669e+02  1032
+                                Solution         3.6701e-09  -3.6971e-09 
                                                  3.6192e+11   4.3354e+11 
                                 ----------------------------------------
-                                Sensitivity 1   -2.7350e+08  -9.6001e+08 
+                                Sensitivity 1   -2.1888e+09   2.2725e+09 
                                                  6.2310e+23   9.2797e+23 
                                 ----------------------------------------
-                                Sensitivity 2    3.7283e+07   1.2247e+08 
+                                Sensitivity 2    4.4906e+07  -4.4215e+07 
                                                 -2.1798e+23  -3.2463e+23 
 ------------------------------------------------------------------------
-7.920e+04  4  4.008e+02  2711
-                                Solution        -2.1912e-15  -7.8117e-15 
+7.920e+04  5  5.669e+02  1044
+                                Solution         8.6071e-10  -8.7030e-10 
                                                  3.6148e+11   4.4474e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.0220e+04   3.6486e+04 
+                                Sensitivity 1    1.2182e+08  -1.2723e+08 
                                                  6.2481e+23   9.8067e+23 
                                 ----------------------------------------
-                                Sensitivity 2    1.2136e+00   4.0255e+00 
-                                                -2.1858e+23  -3.4307e+23 
+                                Sensitivity 2   -3.3266e+06   3.2681e+06 
+                                                -2.1858e+23  -3.4306e+23 
 ------------------------------------------------------------------------
-8.640e+04  4  4.008e+02  2729
-                                Solution         1.3608e-20   4.5805e-20 
+8.640e+04  5  5.669e+02  1057
+                                Solution        -2.1232e-10   2.1440e-10 
                                                  3.6318e+11   4.4524e+11 
                                 ----------------------------------------
-                                Sensitivity 1    1.2856e-02   5.0845e-02 
-                                                 6.3248e+23   9.8819e+23 
+                                Sensitivity 1   -6.7197e+08   6.8617e+08 
+                                                 6.3248e+23   9.8820e+23 
                                 ----------------------------------------
-                                Sensitivity 2   -3.1311e-05  -9.6668e-05 
+                                Sensitivity 2   -5.1456e+06   4.7983e+06 
                                                 -2.2126e+23  -3.4570e+23 
 ------------------------------------------------------------------------
 
 Final Statistics
 
-nst     =  2729
+nst     =  1057
 
-nfe     =  4101
-netf    =   203    nsetups  =   542
-nni     =  4097    ncfn     =     9
+nfe     =  2253
+netf    =     7    nsetups  =   173
+nni     =  1154    ncfn     =     0
 
-nfSe    =  8202    nfeS     = 16404
-netfs   =     0    nsetupsS =     0
-nniS    =     0    ncfnS    =     0
+nfSe    =  2544    nfeS     =  5088
+netfs   =    39    nsetupsS =     0
+nniS    =  1269    ncfnS    =     0
 
-nli     =  8349    ncfl     =     0
-npe     =    63    nps      = 17946
+nli     =  3331    ncfl     =     0
+npe     =    19    nps      =  6690
diff --git a/examples/cvodes/serial/cvsDiurnal_kry.c b/examples/cvodes/serial/cvsDiurnal_kry.c
index 353f44d..3382858 100644
--- a/examples/cvodes/serial/cvsDiurnal_kry.c
+++ b/examples/cvodes/serial/cvsDiurnal_kry.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4849 $
- * $Date: 2016-08-03 16:00:06 -0700 (Wed, 03 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -24,24 +20,24 @@
  * The PDE system is treated by central differences on a uniform
  * 10 x 10 mesh, with simple polynomial initial profiles.
  * The problem is solved with CVODES, with the BDF/GMRES
- * method (i.e. using the CVSPGMR linear solver) and the
+ * method (i.e. using the SUNSPGMR linear solver) and the
  * block-diagonal part of the Newton matrix as a left
  * preconditioner. A copy of the block-diagonal part of the
  * Jacobian is saved and conditionally reused within the Precond
  * routine.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>            /* main integrator header file */
-#include <cvodes/cvodes_spgmr.h>      /* prototypes & constants for CVSPGMR solver */
-#include <nvector/nvector_serial.h>   /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_dense.h>  /* use generic DENSE solver in preconditioning */
-#include <sundials/sundials_types.h>  /* definition of realtype */
-#include <sundials/sundials_math.h>   /* contains the macros ABS, SUNSQR, and EXP */
+#include <cvodes/cvodes.h>             /* main integrator header file          */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvodes/cvodes_spils.h>       /* access to CVSpils interface          */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* contains the macros ABS, SUNSQR, EXP */
 
 /* Problem Constants */
 
@@ -98,7 +94,7 @@
    IJKth(vdata,i,j,k) references the element in the vdata array for
    species i at mesh point (j,k), where 1 <= i <= NUM_SPECIES,
    0 <= j <= MX-1, 0 <= k <= MY-1. The vdata array is obtained via
-   the macro call vdata = N_VGetArrayPointer_Serial(v), where v is an N_Vector. 
+   the call vdata = N_VGetArrayPointer(v), where v is an N_Vector. 
    For each mesh point (j,k), the elements for species i and i+1 are
    contiguous within vdata.
 
@@ -115,7 +111,7 @@
 
 typedef struct {
   realtype **P[MX][MY], **Jbd[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   realtype q4, om, dx, dy, hdco, haco, vdco;
 } *UserData;
 
@@ -139,13 +135,12 @@ static int jtv(N_Vector v, N_Vector Jv, realtype t,
 
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3);
+                   void *user_data);
 
 static int PSolve(realtype tn, N_Vector u, N_Vector fu,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 
 /*
@@ -159,11 +154,13 @@ int main()
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int iout, flag;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
@@ -196,14 +193,18 @@ int main()
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR 
-   * with left preconditioning and the maximum Krylov dimension maxl */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+  /* Call SUNSPGMR to specify the linear solver SUNSPGMR 
+   * with left preconditioning and the default Krylov dimension */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Call CVSpilsSetLinearSolver to attach the linear sovler to CVode */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
   /* set the JAcobian-times-vector function */
-  flag = CVSpilsSetJacTimesVecFn(cvode_mem, jtv);
-  if(check_flag(&flag, "CVSpilsSetJacTimesVecFn", 1)) return(1);
+  flag = CVSpilsSetJacTimes(cvode_mem, NULL, jtv);
+  if(check_flag(&flag, "CVSpilsSetJacTimes", 1)) return(1);
 
   /* Set the preconditioner solve and setup functions */
   flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
@@ -220,9 +221,10 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free memory */
-  N_VDestroy_Serial(u);
+  N_VDestroy(u);
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   return(0);
 }
@@ -246,7 +248,7 @@ static UserData AllocUserData(void)
     for (jy=0; jy < MY; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
       (data->Jbd)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
 
@@ -292,7 +294,7 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profiles of c1 and c2 into u vector */
 
@@ -319,7 +321,7 @@ static void PrintOutput(void *cvode_mem, N_Vector u, realtype t)
   realtype hu, *udata;
   int mxh = MX/2 - 1, myh = MY/2 - 1, mx1 = MX - 1, my1 = MY - 1;
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -391,9 +393,9 @@ static void PrintFinalStats(void *cvode_mem)
   check_flag(&flag, "CVSpilsGetNumRhsEvals", 1);
 
   printf("\nFinal Statistics.. \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwLS = %5ld     leniwLS = %5ld\n", lenrwLS, leniwLS);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwLS = %5ld     leniwLS = %5ld\n"  , lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfeLS   = %5ld\n"  , nfe, nfeLS);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
   printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
@@ -455,8 +457,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   UserData data;
 
   data = (UserData) user_data;
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Set diurnal rate coefficients. */
 
@@ -553,9 +555,9 @@ static int jtv(N_Vector v, N_Vector Jv, realtype t,
 
   data = (UserData) user_data;
 
-  udata = N_VGetArrayPointer_Serial(u);
-  vdata = N_VGetArrayPointer_Serial(v);
-  Jvdata = N_VGetArrayPointer_Serial(Jv);
+  udata = N_VGetArrayPointer(u);
+  vdata = N_VGetArrayPointer(v);
+  Jvdata = N_VGetArrayPointer(Jv);
 
   /* Set diurnal rate coefficients. */
 
@@ -686,12 +688,11 @@ static int jtv(N_Vector v, N_Vector Jv, realtype t,
 
 static int Precond(realtype tn, N_Vector u, N_Vector fu,
                    booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3)
+                   void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MY], **(*Jbd)[MY];
-  long int *(*pivot)[MY], ier;
+  sunindextype *(*pivot)[MY], ier;
   int jx, jy;
   realtype *udata, **a, **j;
   UserData data;
@@ -702,22 +703,22 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
   P = data->P;
   Jbd = data->Jbd;
   pivot = data->pivot;
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
   
   if (jok) {
     
-    /* jok = TRUE: Copy Jbd to P */
+    /* jok = SUNTRUE: Copy Jbd to P */
     
     for (jy=0; jy < MY; jy++)
       for (jx=0; jx < MX; jx++)
         denseCopy(Jbd[jx][jy], P[jx][jy], NUM_SPECIES, NUM_SPECIES);
     
-    *jcurPtr = FALSE;
+    *jcurPtr = SUNFALSE;
     
   }
   
   else {
-    /* jok = FALSE: Generate Jbd from scratch and copy to P */
+    /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
     
     /* Make local copies of problem variables, for efficiency. */
     
@@ -748,7 +749,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
     
-    *jcurPtr = TRUE;
+    *jcurPtr = SUNTRUE;
     
   }
   
@@ -776,10 +777,10 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 static int PSolve(realtype tn, N_Vector u, N_Vector fu,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype **(*P)[MY];
-  long int *(*pivot)[MY];
+  sunindextype *(*pivot)[MY];
   int jx, jy;
   realtype *zdata, *v;
   UserData data;
@@ -789,7 +790,7 @@ static int PSolve(realtype tn, N_Vector u, N_Vector fu,
   data = (UserData) user_data;
   P = data->P;
   pivot = data->pivot;
-  zdata = N_VGetArrayPointer_Serial(z);
+  zdata = N_VGetArrayPointer(z);
   
   N_VScale(ONE, r, z);
   
diff --git a/examples/cvodes/serial/cvsDiurnal_kry.out b/examples/cvodes/serial/cvsDiurnal_kry.out
index 7edac66..b55d0c4 100644
--- a/examples/cvodes/serial/cvsDiurnal_kry.out
+++ b/examples/cvodes/serial/cvsDiurnal_kry.out
@@ -13,51 +13,51 @@ t = 2.16e+04   no. steps = 277   order = 5   stepsize = 2.75e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 301   order = 5   stepsize = 3.87e+02
+t = 2.88e+04   no. steps = 307   order = 4   stepsize = 2.03e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 343   order = 3   stepsize = 2.34e+01
+t = 3.60e+04   no. steps = 338   order = 5   stepsize = 9.92e+01
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 421   order = 4   stepsize = 5.26e+02
-c1 (bot.left/middle/top rt.) =   -4.385e-06    -1.528e-06    -4.905e-06
+t = 4.32e+04   no. steps = 393   order = 4   stepsize = 2.57e+02
+c1 (bot.left/middle/top rt.) =   -7.891e-06    -1.123e-06    -8.723e-06
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 445   order = 3   stepsize = 1.98e+02
-c1 (bot.left/middle/top rt.) =    4.461e-07     1.869e-07     4.842e-07
+t = 5.04e+04   no. steps = 421   order = 5   stepsize = 4.96e+02
+c1 (bot.left/middle/top rt.) =   -1.595e-08    -1.771e-06    -3.117e-08
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 462   order = 5   stepsize = 2.35e+02
-c1 (bot.left/middle/top rt.) =    3.204e-09     1.203e-09     3.555e-09
+t = 5.76e+04   no. steps = 439   order = 4   stepsize = 1.19e+02
+c1 (bot.left/middle/top rt.) =   -2.127e-06    -1.513e-04    -2.951e-06
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 474   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -1.066e-09    -3.409e-10    -1.206e-09
+t = 6.48e+04   no. steps = 458   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =   -1.084e-09    -7.686e-08    -1.499e-09
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 486   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    2.614e-09     9.722e-10     2.904e-09
+t = 7.20e+04   no. steps = 469   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =   -1.093e-10    -7.736e-09    -1.510e-10
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 498   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    4.649e-11     1.729e-11     5.161e-11
+t = 7.92e+04   no. steps = 480   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =   -1.624e-12    -1.151e-10    -2.246e-12
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 510   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -8.856e-14    -3.348e-14    -9.785e-14
+t = 8.64e+04   no. steps = 491   order = 5   stepsize = 6.60e+02
+c1 (bot.left/middle/top rt.) =    3.501e-14     2.474e-12     4.816e-14
 c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2096     leniw   =    62
-lenrwLS =  2046     leniwLS =    10
-nst     =   510
-nfe     =   675     nfeLS   =   641
-nni     =   671     nli     =   641
-nsetups =    94     netf    =    36
-npe     =     9     nps     =  1243
+lenrwLS =  2450     leniwLS =    22
+nst     =   491
+nfe     =   631     nfeLS   =     0
+nni     =   627     nli     =   643
+nsetups =    82     netf    =    29
+npe     =     9     nps     =  1214
 ncfn    =     0     ncfl    =     0
 
diff --git a/examples/cvodes/serial/cvsDiurnal_kry_bp.c b/examples/cvodes/serial/cvsDiurnal_kry_bp.c
index f7058f3..e931079 100644
--- a/examples/cvodes/serial/cvsDiurnal_kry_bp.c
+++ b/examples/cvodes/serial/cvsDiurnal_kry_bp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @LLNL
  * -----------------------------------------------------------------
@@ -24,7 +20,7 @@
  * The PDE system is treated by central differences on a uniform
  * 10 x 10 mesh, with simple polynomial initial profiles.
  * The problem is solved with CVODES, with the BDF/GMRES
- * method (i.e. using the CVSPGMR linear solver) and a banded
+ * method (i.e. using the SUNSPGMR linear solver) and a banded
  * preconditioner, generated by difference quotients, using the
  * module CVBANDPRE. The problem is solved with left and right
  * preconditioning.
@@ -35,12 +31,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>           /* main integrator header file */
-#include <cvodes/cvodes_spgmr.h>     /* prototypes & constants for CVSPGMR solver */
-#include <cvodes/cvodes_bandpre.h>   /* prototypes & constants for CVBANDPRE module */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS, SUNSQR, and EXP */
+#include <cvodes/cvodes.h>             /* main integrator header file          */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvodes/cvodes_spils.h>       /* access to CVSpils interface          */
+#include <cvodes/cvodes_bandpre.h>     /* access to CVBANDPRE module           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* contains the macros ABS, SUNSQR, EXP */
 
 /* Problem Constants */
 
@@ -97,7 +94,7 @@
    IJKth(vdata,i,j,k) references the element in the vdata array for
    species i at mesh point (j,k), where 1 <= i <= NUM_SPECIES,
    0 <= j <= MX-1, 0 <= k <= MY-1. The vdata array is obtained via
-   the macro call vdata = N_VGetArrayPointer_Serial(v), where v is an N_Vector. 
+   the call vdata = N_VGetArrayPointer(v), where v is an N_Vector. 
    For each mesh point (j,k), the elements for species i and i+1 are
    contiguous within vdata.
 
@@ -120,7 +117,7 @@ typedef struct {
 
 static void InitUserData(UserData data);
 static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy);
-static void PrintIntro(long int mu, long int ml);
+static void PrintIntro(sunindextype mu, sunindextype ml);
 static void PrintOutput(void *cvode_mem, N_Vector u, realtype t);
 static void PrintFinalStats(void *cvode_mem);
 
@@ -142,12 +139,14 @@ int main()
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, iout, jpre;
-  long int ml, mu;
+  sunindextype ml, mu;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Allocate and initialize u, and set problem data and tolerances */ 
@@ -180,10 +179,14 @@ int main()
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Call CVSpgmr to specify the linear solver CVSPGMR 
-     with left preconditioning and the maximum Krylov dimension maxl */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+  /* Call SUNSPGMR to specify the linear solver SUNSPGMR 
+   * with left preconditioning and the default Krylov dimension */
+  LS = SUNSPGMR(u, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Call CVSpilsSetLinearSolver to attach the linear sovler to CVode */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
   /* Call CVBandPreInit to initialize band preconditioner */
   ml = mu = 2;
@@ -205,8 +208,11 @@ int main()
       flag = CVodeReInit(cvode_mem, T0, u);
       if(check_flag(&flag, "CVodeReInit", 1)) return(1);
 
-      flag = CVSpilsSetPrecType(cvode_mem, PREC_RIGHT);
-      check_flag(&flag, "CVSpilsSetPrecType", 1);
+      flag = SUNSPGMRSetPrecType(LS, PREC_RIGHT);
+      if(check_flag(&flag, "SUNSPGMRSetPrecType", 1)) return(1);
+
+      flag = CVBandPrecInit(cvode_mem, NEQ, mu, ml);
+      if(check_flag(&flag, "CVBandPrecInit", 0)) return(1);
       
       printf("\n\n-------------------------------------------------------");
       printf("------------\n");
@@ -233,9 +239,10 @@ int main()
   } /* End of jpre loop */
 
   /* Free memory */
-  N_VDestroy_Serial(u);
+  N_VDestroy(u);
   free(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   return(0);
 }
@@ -268,7 +275,7 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profiles of c1 and c2 into u vector */
 
@@ -286,12 +293,12 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
   }
 }
 
-static void PrintIntro(long int mu, long int ml)
+static void PrintIntro(sunindextype mu, sunindextype ml)
 {
   printf("2-species diurnal advection-diffusion problem, %d by %d mesh\n",
          MX, MY);
   printf("SPGMR solver; band preconditioner; mu = %ld, ml = %ld\n\n",
-         mu, ml);
+         (long int) mu, (long int) ml);
 
   return;
 }
@@ -305,7 +312,7 @@ static void PrintOutput(void *cvode_mem, N_Vector u,realtype t)
   realtype hu, *udata;
   int mxh = MX/2 - 1, myh = MY/2 - 1, mx1 = MX - 1, my1 = MY - 1;
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -384,10 +391,10 @@ static void PrintFinalStats(void *cvode_mem)
   check_flag(&flag, "CVBandPrecGetNumRhsEvals", 1);
 
   printf("\nFinal Statistics.. \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwls = %5ld     leniwls = %5ld\n", lenrwLS, leniwLS);
-  printf("lenrwbp = %5ld     leniwbp = %5ld\n", lenrwBP, leniwBP);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwls = %5ld     leniwls = %5ld\n"  , lenrwLS, leniwLS);
+  printf("lenrwbp = %5ld     leniwbp = %5ld\n"  , lenrwBP, leniwBP);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfetot  = %5ld\n"  , nfe, nfe+nfeLS+nfeBP);
   printf("nfeLS   = %5ld     nfeBP   = %5ld\n"  , nfeLS, nfeBP);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
@@ -450,8 +457,8 @@ static int f(realtype t, N_Vector u, N_Vector udot,void *user_data)
   UserData data;
 
   data = (UserData) user_data;
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Set diurnal rate coefficients. */
 
diff --git a/examples/cvodes/serial/cvsDiurnal_kry_bp.out b/examples/cvodes/serial/cvsDiurnal_kry_bp.out
index 6a49f52..448f305 100644
--- a/examples/cvodes/serial/cvsDiurnal_kry_bp.out
+++ b/examples/cvodes/serial/cvsDiurnal_kry_bp.out
@@ -17,54 +17,54 @@ t = 2.16e+04   no. steps = 246   order = 5   stepsize = 2.78e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 291   order = 4   stepsize = 1.14e+02
+t = 2.88e+04   no. steps = 298   order = 3   stepsize = 1.33e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 331   order = 4   stepsize = 8.86e+01
+t = 3.60e+04   no. steps = 341   order = 4   stepsize = 6.31e+01
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 402   order = 4   stepsize = 4.15e+02
-c1 (bot.left/middle/top rt.) =   -5.769e-09     3.421e-09    -3.866e-09
+t = 4.32e+04   no. steps = 402   order = 4   stepsize = 4.48e+02
+c1 (bot.left/middle/top rt.) =    1.915e-07    -6.130e-06     4.395e-07
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 415   order = 5   stepsize = 4.58e+02
-c1 (bot.left/middle/top rt.) =   -4.979e-18    -7.193e-15    -2.653e-15
+t = 5.04e+04   no. steps = 422   order = 4   stepsize = 3.17e+02
+c1 (bot.left/middle/top rt.) =   -7.746e-11    -3.073e-08    -3.512e-11
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 430   order = 4   stepsize = 2.19e+02
-c1 (bot.left/middle/top rt.) =    1.611e-17     4.587e-16    -4.704e-18
+t = 5.76e+04   no. steps = 436   order = 5   stepsize = 3.58e+02
+c1 (bot.left/middle/top rt.) =    1.801e-11     7.177e-09     8.588e-12
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 444   order = 4   stepsize = 5.79e+02
-c1 (bot.left/middle/top rt.) =    9.505e-16     1.154e-14    -2.316e-16
+t = 6.48e+04   no. steps = 449   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =   -2.845e-14    -1.063e-11    -1.382e-14
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 457   order = 4   stepsize = 5.79e+02
-c1 (bot.left/middle/top rt.) =    3.910e-16    -4.848e-14     2.545e-15
+t = 7.20e+04   no. steps = 461   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =    2.710e-16     1.011e-13     1.307e-16
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 469   order = 4   stepsize = 5.79e+02
-c1 (bot.left/middle/top rt.) =   -2.903e-15     2.152e-13     3.551e-16
+t = 7.92e+04   no. steps = 473   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =    5.698e-16     2.058e-13     2.690e-16
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 481   order = 4   stepsize = 5.79e+02
-c1 (bot.left/middle/top rt.) =    2.358e-23     2.316e-18    -6.007e-16
-c2 (bot.left/middle/top rt.) =    3.352e+11     9.108e+11     4.162e+11
+t = 8.64e+04   no. steps = 485   order = 5   stepsize = 5.95e+02
+c1 (bot.left/middle/top rt.) =    2.707e-16     1.899e-17     2.156e-15
+c2 (bot.left/middle/top rt.) =    3.352e+11     9.106e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2096     leniw   =    62
-lenrwls =  2046     leniwls =    10
-lenrwbp =  2400     leniwbp =   200
-nst     =   481
-nfe     =   620     nfetot  =  1226
-nfeLS   =   561     nfeBP   =    45
-nni     =   616     nli     =   561
-nsetups =    88     netf    =    28
-npe     =     9     nps     =  1096
+lenrwls =  2450     leniwls =    22
+lenrwbp =  2800     leniwbp =   622
+nst     =   485
+nfe     =   617     nfetot  =  1259
+nfeLS   =   597     nfeBP   =    45
+nni     =   613     nli     =   597
+nsetups =    85     netf    =    28
+npe     =     9     nps     =  1134
 ncfn    =     0     ncfl    =     0
 
 
@@ -86,53 +86,53 @@ t = 2.16e+04   no. steps = 279   order = 5   stepsize = 3.58e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 301   order = 5   stepsize = 2.40e+02
+t = 2.88e+04   no. steps = 303   order = 5   stepsize = 2.67e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 330   order = 5   stepsize = 1.31e+02
+t = 3.60e+04   no. steps = 329   order = 5   stepsize = 1.16e+02
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 381   order = 4   stepsize = 3.91e+02
-c1 (bot.left/middle/top rt.) =    3.125e-10     2.750e-10     3.496e-10
+t = 4.32e+04   no. steps = 381   order = 4   stepsize = 4.67e+02
+c1 (bot.left/middle/top rt.) =    8.674e-09     7.020e-09     9.676e-09
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 395   order = 5   stepsize = 4.06e+02
-c1 (bot.left/middle/top rt.) =   -3.259e-14    -1.715e-12    -6.477e-14
+t = 5.04e+04   no. steps = 398   order = 4   stepsize = 3.23e+02
+c1 (bot.left/middle/top rt.) =    3.531e-15    -4.895e-12    -1.356e-13
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 408   order = 5   stepsize = 4.57e+02
-c1 (bot.left/middle/top rt.) =    2.382e-14     5.871e-12     6.950e-14
+t = 5.76e+04   no. steps = 411   order = 5   stepsize = 4.75e+02
+c1 (bot.left/middle/top rt.) =    1.279e-13    -4.506e-11    -1.318e-12
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 420   order = 5   stepsize = 7.04e+02
-c1 (bot.left/middle/top rt.) =    1.493e-18     1.862e-17    -7.080e-16
+t = 6.48e+04   no. steps = 423   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =   -1.113e-17     6.813e-16     1.742e-17
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 430   order = 5   stepsize = 7.04e+02
-c1 (bot.left/middle/top rt.) =   -1.345e-20     1.847e-18    -6.157e-16
+t = 7.20e+04   no. steps = 433   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =   -1.369e-20     3.565e-21    -5.202e-25
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 440   order = 5   stepsize = 7.04e+02
-c1 (bot.left/middle/top rt.) =    3.617e-20    -3.355e-18    -7.407e-16
+t = 7.92e+04   no. steps = 443   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =    1.471e-20    -1.150e-20    -1.118e-25
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 450   order = 5   stepsize = 7.04e+02
-c1 (bot.left/middle/top rt.) =   -5.505e-20     3.704e-18    -2.929e-15
+t = 8.64e+04   no. steps = 452   order = 5   stepsize = 7.28e+02
+c1 (bot.left/middle/top rt.) =    1.949e-20    -1.947e-21     1.946e-25
 c2 (bot.left/middle/top rt.) =    3.352e+11     9.106e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2096     leniw   =    62
-lenrwls =  2046     leniwls =    10
-lenrwbp =  2400     leniwbp =   200
-nst     =   450
-nfe     =   564     nfetot  =  1319
-nfeLS   =   670     nfeBP   =    85
-nni     =   560     nli     =   670
-nsetups =    71     netf    =    21
-npe     =     8     nps     =  1140
+lenrwls =  2450     leniwls =    22
+lenrwbp =  2800     leniwbp =   622
+nst     =   452
+nfe     =   571     nfetot  =  1336
+nfeLS   =   725     nfeBP   =    40
+nni     =   567     nli     =   725
+nsetups =    74     netf    =    23
+npe     =     8     nps     =  1199
 ncfn    =     0     ncfl    =     0
 
diff --git a/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c
index b371559..d7b8dc8 100644
--- a/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * This program solves a stiff ODE system that arises from a system
@@ -46,7 +42,7 @@
  * mesh. The resulting ODE system is stiff.
  *
  * The ODE system is solved by CVODES using Newton iteration and
- * the CVSPGMR linear solver (scaled preconditioned GMRES).
+ * the SUNSPGMR linear solver (scaled preconditioned GMRES).
  *
  * The preconditioner matrix used is the product of two matrices:
  * (1) A matrix, only defined implicitly, based on a fixed number
@@ -79,19 +75,19 @@
  * Matrix Methods in Stiff ODE Systems, J. Appl. Math. & Comp., 31
  * (1989), pp. 40-91.  Also available as Lawrence Livermore National
  * Laboratory Report UCRL-95088, Rev. 1, June 1987.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>
-#include <cvodes/cvodes_spgmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <cvodes/cvodes.h>             /* main integrator header file          */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvodes/cvodes_spils.h>       /* access to CVSpils interface          */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* contains the macros ABS, SUNSQR, EXP */
 
 #define ZERO RCONST(0.0)
 #define ONE  RCONST(1.0)
@@ -144,7 +140,7 @@
 
 typedef struct {
   realtype **P[NGRP];
-  long int *pivot[NGRP];
+  sunindextype *pivot[NGRP];
   int ns,  mxns, mp, mq, mx, my, ngrp, ngx, ngy, mxmp;
   int jgx[NGX+1], jgy[NGY+1], jigx[MX], jigy[MY];
   int jxr[NGX], jyr[NGY];
@@ -153,6 +149,7 @@ typedef struct {
   realtype fsave[NEQ];
   realtype fBsave[NEQ];
   N_Vector rewt;
+  N_Vector vtemp;
   void *cvode_mem;
   int indexB;
 } *WebData;
@@ -169,13 +166,12 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int Precond(realtype t, N_Vector c, N_Vector fc,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data,
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   realtype gamma, void *user_data);
 
 static int PSolve(realtype t, N_Vector c, N_Vector fc,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 static int fB(realtype t, N_Vector c, N_Vector cB, 
                N_Vector cBdot, void *user_data);
@@ -183,14 +179,13 @@ static int fB(realtype t, N_Vector c, N_Vector cB,
 static int PrecondB(realtype t, N_Vector c, 
                     N_Vector cB, N_Vector fcB, booleantype jok, 
                     booleantype *jcurPtr, realtype gamma,
-                    void *user_data,
-                    N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                    void *user_data);
 
 static int PSolveB(realtype t, N_Vector c, 
                    N_Vector cB, N_Vector fcB, 
                    N_Vector r, N_Vector z,
                    realtype gamma, realtype delta, 
-                   int lr, void *user_data, N_Vector vtemp);
+                   int lr, void *user_data);
 
 /* Prototypes for private functions */
 
@@ -230,6 +225,7 @@ int main(int argc, char *argv[])
   N_Vector c;
   WebData wdata;
   void *cvode_mem;
+  SUNLinearSolver LS, LSB;
 
   int flag, ncheck;
   
@@ -242,6 +238,7 @@ int main(int argc, char *argv[])
   cB = NULL;
   wdata = NULL;
   cvode_mem = NULL;
+  LS = LSB = NULL;
 
   /* Allocate and initialize user data */
 
@@ -268,9 +265,15 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Call CVSpgmr for forward run */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+  /* Create SUNSPGMR linear solver for forward run */
+  LS = SUNSPGMR(c, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Attach the linear sovler */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
+
+  /* Set the preconditioner solve and setup functions */
   flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
   if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
 
@@ -291,10 +294,10 @@ int main(int argc, char *argv[])
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("\n   G = int_t int_x int_y c%d(t,x,y) dx dy dt = %Lf \n\n", 
-         ISPEC, N_VGetArrayPointer_Serial(c)[NEQ]);
+         ISPEC, N_VGetArrayPointer(c)[NEQ]);
 #else
   printf("\n   G = int_t int_x int_y c%d(t,x,y) dx dy dt = %f \n\n", 
-         ISPEC, N_VGetArrayPointer_Serial(c)[NEQ]);
+         ISPEC, N_VGetArrayPointer(c)[NEQ]);
 #endif
 
   /* Set-up backward problem */
@@ -320,9 +323,15 @@ int main(int argc, char *argv[])
 
   wdata->indexB = indexB;
 
-  /* Call CVSpgmr */
-  flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmrB", 1)) return(1);
+  /* Create SUNSPGMR linear solver for backward run */
+  LSB = SUNSPGMR(cB, PREC_LEFT, 0);
+  if(check_flag((void *)LSB, "SUNSPGMR", 0)) return(1);
+
+  /* Attach the linear sovler */
+  flag = CVSpilsSetLinearSolverB(cvode_mem, indexB, LSB);
+  if (check_flag(&flag, "CVSpilsSetLinearSolverB", 1)) return 1;
+
+  /* Set the preconditioner solve and setup functions */
   flag = CVSpilsSetPreconditionerB(cvode_mem, indexB, PrecondB, PSolveB);
   if(check_flag(&flag, "CVSpilsSetPreconditionerB", 1)) return(1);
 
@@ -340,8 +349,10 @@ int main(int argc, char *argv[])
   /* Free all memory */
   CVodeFree(&cvode_mem);
 
-  N_VDestroy_Serial(c);
-  N_VDestroy_Serial(cB);
+  N_VDestroy(c);
+  N_VDestroy(cB);
+  SUNLinSolFree(LS);
+  SUNLinSolFree(LSB);
 
   FreeUserData(wdata);
 
@@ -368,8 +379,8 @@ static int f(realtype t, N_Vector c, N_Vector cdot, void *user_data)
   WebData wdata;
   
   wdata = (WebData) user_data;
-  cdata = N_VGetArrayPointer_Serial(c);
-  cdotdata = N_VGetArrayPointer_Serial(cdot);
+  cdata = N_VGetArrayPointer(c);
+  cdotdata = N_VGetArrayPointer(cdot);
   
   mxns = wdata->mxns;
   ns = wdata->ns;
@@ -430,15 +441,14 @@ static int f(realtype t, N_Vector c, N_Vector cdot, void *user_data)
  
 static int Precond(realtype t, N_Vector c, N_Vector fc,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data,
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   realtype gamma, void *user_data)
 {
   int N;
   realtype ***P;
-  long int **pivot, ier;
+  sunindextype **pivot, ier;
   int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
   int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
-  long int mp;
+  sunindextype mp;
   realtype uround, fac, r, r0, save, srur;
   realtype *f1, *fsave, *cdata, *rewtdata;
   void *cvode_mem;
@@ -451,8 +461,8 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
   flag = CVodeGetErrWeights(cvode_mem, rewt);
   if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
 
-  cdata = N_VGetArrayPointer_Serial(c);
-  rewtdata = N_VGetArrayPointer_Serial(rewt);
+  cdata = N_VGetArrayPointer(c);
+  rewtdata = N_VGetArrayPointer(rewt);
 
   uround = UNIT_ROUNDOFF;
 
@@ -472,7 +482,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
      Here, fsave contains the base value of the rate vector and 
      r0 is a minimum increment factor for the difference quotient. */
 
-  f1 = N_VGetArrayPointer_Serial(vtemp1);
+  f1 = N_VGetArrayPointer(wdata->vtemp);
 
   fac = N_VWrmsNorm (fc, rewt);
   N = NEQ+1;
@@ -511,7 +521,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
      if (ier != 0) return(1);
    }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
   return(0);
 }
 
@@ -529,12 +539,12 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
 static int PSolve(realtype t, N_Vector c, N_Vector fc,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype ***P;
-  long int **pivot;
+  sunindextype **pivot;
   int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
-  long int mp;
+  sunindextype mp;
   WebData wdata;
 
   wdata = (WebData) user_data;
@@ -543,7 +553,7 @@ static int PSolve(realtype t, N_Vector c, N_Vector fc,
 
   /* call GSIter for Gauss-Seidel iterations */
 
-  GSIter(gamma, z, vtemp, wdata);
+  GSIter(gamma, z, wdata->vtemp, wdata);
 
   /* Do backsolves for inverse of block-diagonal preconditioner factor */
  
@@ -562,13 +572,13 @@ static int PSolve(realtype t, N_Vector c, N_Vector fc,
     for (jx = 0; jx < mx; jx++) {
       igx = jigx[jx];
       ig = igx + igy*ngx;
-      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer_Serial(z)[iv]));
+      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer(z)[iv]));
       iv += mp;
     }
   }
 
   /* Solve for the quadrature variable */
-  N_VGetArrayPointer_Serial(z)[NEQ] = N_VGetArrayPointer_Serial(r)[NEQ] + gamma*doubleIntgr(z,ISPEC,wdata);
+  N_VGetArrayPointer(z)[NEQ] = N_VGetArrayPointer(r)[NEQ] + gamma*doubleIntgr(z,ISPEC,wdata);
 
   return(0);
 }
@@ -591,9 +601,9 @@ static int fB(realtype t, N_Vector c, N_Vector cB,
   realtype gu[NS];
 
   wdata = (WebData) user_data;
-  cdata = N_VGetArrayPointer_Serial(c);
-  cBdata = N_VGetArrayPointer_Serial(cB);
-  cBdotdata = N_VGetArrayPointer_Serial(cBdot);
+  cdata = N_VGetArrayPointer(c);
+  cBdata = N_VGetArrayPointer(cB);
+  cBdotdata = N_VGetArrayPointer(cBdot);
 
   mxns = wdata->mxns;
   ns = wdata->ns;
@@ -647,15 +657,14 @@ static int fB(realtype t, N_Vector c, N_Vector cB,
 static int PrecondB(realtype t, N_Vector c, 
                     N_Vector cB, N_Vector fcB, booleantype jok, 
                     booleantype *jcurPtr, realtype gamma,
-                    void *user_data,
-                    N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                    void *user_data)
 {
   int N;
   realtype ***P;
-  long int **pivot, ier;
+  sunindextype **pivot, ier;
   int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
   int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
-  long int mp;
+  sunindextype mp;
   realtype uround, fac, r, r0, save, srur;
   realtype *f1, *fsave, *cdata, *rewtdata;
   void *cvode_mem;
@@ -669,8 +678,8 @@ static int PrecondB(realtype t, N_Vector c,
   flag = CVodeGetErrWeights(cvode_mem, rewt);
   if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
 
-  cdata = N_VGetArrayPointer_Serial(c);
-  rewtdata = N_VGetArrayPointer_Serial(rewt);
+  cdata = N_VGetArrayPointer(c);
+  rewtdata = N_VGetArrayPointer(rewt);
 
   uround = UNIT_ROUNDOFF;
 
@@ -690,7 +699,7 @@ static int PrecondB(realtype t, N_Vector c,
      Here, fsave contains the base value of the rate vector and 
      r0 is a minimum increment factor for the difference quotient. */
 
-  f1 = N_VGetArrayPointer_Serial(vtemp1);
+  f1 = N_VGetArrayPointer(wdata->vtemp);
   fac = N_VWrmsNorm (fcB, rewt);
   N = NEQ;
   r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*N*fac;
@@ -728,7 +737,7 @@ static int PrecondB(realtype t, N_Vector c,
      if (ier != 0) return(1);
    }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
   return(0);
 }
 
@@ -740,12 +749,12 @@ static int PSolveB(realtype t, N_Vector c,
                    N_Vector cB, N_Vector fcB, 
                    N_Vector r, N_Vector z,
                    realtype gamma, realtype delta, 
-                   int lr, void *user_data, N_Vector vtemp)
+                   int lr, void *user_data)
 {
   realtype ***P;
-  long int **pivot;
+  sunindextype **pivot;
   int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
-  long int mp;
+  sunindextype mp;
   WebData wdata;
 
   wdata = (WebData) user_data;
@@ -754,7 +763,7 @@ static int PSolveB(realtype t, N_Vector c,
 
   /* call GSIter for Gauss-Seidel iterations (same routine but with gamma=-gamma) */
 
-  GSIter(-gamma, z, vtemp, wdata);
+  GSIter(-gamma, z, wdata->vtemp, wdata);
 
   /* Do backsolves for inverse of block-diagonal preconditioner factor */
  
@@ -773,7 +782,7 @@ static int PSolveB(realtype t, N_Vector c,
     for (jx = 0; jx < mx; jx++) {
       igx = jigx[jx];
       ig = igx + igy*ngx;
-      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer_Serial(z)[iv]));
+      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer(z)[iv]));
       iv += mp;
     }
   }
@@ -799,9 +808,11 @@ static WebData AllocUserData(void)
   wdata = (WebData) malloc(sizeof *wdata);
   for(i=0; i < ngrp; i++) {
     (wdata->P)[i] = newDenseMat(ns, ns);
-    (wdata->pivot)[i] = newLintArray(ns);
+    (wdata->pivot)[i] = newIndexArray(ns);
   }
-  wdata->rewt = N_VNew_Serial(NEQ+1);
+  wdata->rewt  = N_VNew_Serial(NEQ+1);
+  wdata->vtemp = N_VNew_Serial(NEQ+1);
+
   return(wdata);
 }
 
@@ -899,7 +910,7 @@ static void CInit(N_Vector c, WebData wdata)
   int i, ici, ioff, iyoff, jx, jy, ns, mxns;
   realtype argx, argy, x, y, dx, dy, x_factor, y_factor, *cdata;
   
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
   ns = wdata->ns;
   mxns = wdata->mxns;
   dx = wdata->dx;
@@ -1029,8 +1040,8 @@ static void GSIter(realtype gamma, N_Vector z, N_Vector x,
   realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
   realtype temp, *cox, *coy, *xd, *zd;
 
-  xd = N_VGetArrayPointer_Serial(x);
-  zd = N_VGetArrayPointer_Serial(z);
+  xd = N_VGetArrayPointer(x);
+  zd = N_VGetArrayPointer(z);
   ns = wdata->ns;
   mx = wdata->mx;
   my = wdata->my;
@@ -1211,7 +1222,7 @@ static void PrintOutput(N_Vector cB, int ns, int mxns, WebData wdata)
 
   x = y = ZERO;
 
-  cdata = N_VGetArrayPointer_Serial(cB);
+  cdata = N_VGetArrayPointer(cB);
 
   for (i=1; i <= ns; i++) {
 
@@ -1261,7 +1272,7 @@ static realtype doubleIntgr(N_Vector c, int i, WebData wdata)
   realtype intgr_xy, intgr_x;
   int jx, jy;
 
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
 
   ns   = wdata->ns;
   mx   = wdata->mx;
@@ -1321,7 +1332,8 @@ static void FreeUserData(WebData wdata)
     destroyMat((wdata->P)[i]);
     destroyArray((wdata->pivot)[i]);
   }
-  N_VDestroy_Serial(wdata->rewt);
+  N_VDestroy(wdata->rewt);
+  N_VDestroy(wdata->vtemp);
   free(wdata);
 }
 
diff --git a/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out
index 9d51c3e..4d9c6d2 100644
--- a/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAi_kry.out
@@ -5,9 +5,9 @@ Allocate global memory
 
 Forward integration
 
-ncheck = 2
+ncheck = 1
 
-   G = int_t int_x int_y c6(t,x,y) dx dy dt = 422295.963896 
+   G = int_t int_x int_y c6(t,x,y) dx dy dt = 422295.485891 
 
 
 Create and allocate CVODES memory for backward run
@@ -15,37 +15,37 @@ Create and allocate CVODES memory for backward run
 Backward integration
 
 Maximum sensitivity with respect to I.C. of species 1
-  lambda max = 9.569148e+02
+  lambda max = 9.567445e+02
 at
   x = 1.000000e+00
   y = 1.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 2
-  lambda max = 9.379464e+02
+  lambda max = 9.377778e+02
 at
   x = 1.000000e+00
   y = 1.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 3
-  lambda max = 9.200243e+02
+  lambda max = 9.198574e+02
 at
   x = 1.000000e+00
   y = 1.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 4
-  lambda max = -4.942530e-03
+  lambda max = -4.419783e-03
 at
   x = 1.000000e+00
   y = 0.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 5
-  lambda max = -4.939374e-03
+  lambda max = -4.394964e-03
 at
   x = 1.000000e+00
   y = 0.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 6
-  lambda max = 3.566293e-01
+  lambda max = 3.252876e-01
 at
   x = 0.000000e+00
   y = 0.000000e+00
diff --git a/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.c b/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.c
index 6d86f65..5ab324b 100644
--- a/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.c
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * This program solves a stiff ODE system that arises from a system
@@ -46,7 +42,7 @@
  * MY mesh. The resulting ODE system is stiff.
  *
  * The ODE system is solved by CVODES using Newton iteration and
- * the CVSPGMR linear solver (scaled preconditioned GMRES).
+ * the SUNSPGMR linear solver (scaled preconditioned GMRES).
  *
  * The preconditioner matrix used is the product of two matrices:
  * (1) A matrix, only defined implicitly, based on a fixed number
@@ -79,12 +75,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>
-#include <cvodes/cvodes_spgmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <cvodes/cvodes.h>             /* main integrator header file          */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <cvodes/cvodes_spils.h>       /* access to CVSpils interface          */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* contains the macros ABS, SUNSQR, EXP */
 
 #define ZERO  RCONST(0.0)
 #define ONE   RCONST(1.0)
@@ -138,7 +135,7 @@
 
 typedef struct {
   realtype **P[NGRP];
-  long int *pivot[NGRP];
+  sunindextype *pivot[NGRP];
   int ns, mxns, mp, mq, mx, my, ngrp, ngx, ngy, mxmp;
   int jgx[NGX+1], jgy[NGY+1], jigx[MX], jigy[MY];
   int jxr[NGX], jyr[NGY];
@@ -147,6 +144,7 @@ typedef struct {
   realtype fsave[NEQ];
   realtype fBsave[NEQ];
   N_Vector rewt;
+  N_Vector vtemp;
   void *cvode_mem;
   int indexB;
 } *WebData;
@@ -162,13 +160,12 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int Precond(realtype t, N_Vector c, N_Vector fc,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data,
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                   realtype gamma, void *user_data);
 
 static int PSolve(realtype t, N_Vector c, N_Vector fc,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 static int fB(realtype t, N_Vector c, N_Vector cB, 
                N_Vector cBdot, void *user_data);
@@ -176,14 +173,13 @@ static int fB(realtype t, N_Vector c, N_Vector cB,
 static int PrecondB(realtype t, N_Vector c, 
                     N_Vector cB, N_Vector fcB, booleantype jok, 
                     booleantype *jcurPtr, realtype gamma,
-                    void *user_data,
-                    N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+                    void *user_data);
 
 static int PSolveB(realtype t, N_Vector c, 
                    N_Vector cB, N_Vector fcB, 
                    N_Vector r, N_Vector z,
                    realtype gamma, realtype delta, 
-                   int lr, void *user_data, N_Vector vtemp);
+                   int lr, void *user_data);
 
 /* Prototypes for private functions */
 
@@ -224,6 +220,7 @@ int main(int argc, char *argv[])
   N_Vector c;
   WebData wdata;
   void *cvode_mem;
+  SUNLinearSolver LS, LSB;
 
   int flag, ncheck;
 
@@ -235,6 +232,7 @@ int main(int argc, char *argv[])
   c = cB = NULL;
   wdata = NULL;
   cvode_mem = NULL;
+  LS = LSB = NULL;
 
   /* Allocate and initialize user data */
 
@@ -261,9 +259,15 @@ int main(int argc, char *argv[])
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
   if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
 
-  /* Call CVSpgmr for forward run */
-  flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+  /* Create SUNSPGMR linear solver for forward run */
+  LS = SUNSPGMR(c, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Attach the linear sovler */
+  flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+  if (check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
+
+  /* Set the preconditioner solve and setup functions */
   flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
   if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
 
@@ -311,9 +315,15 @@ int main(int argc, char *argv[])
 
   wdata->indexB = indexB;
 
-  /* Call CVSpgmr */
-  flag = CVSpgmrB(cvode_mem, indexB, PREC_LEFT, 0);
-  if(check_flag(&flag, "CVSpgmrB", 1)) return(1);
+  /* Create SUNSPGMR linear solver for backward run */
+  LSB = SUNSPGMR(cB, PREC_LEFT, 0);
+  if(check_flag((void *)LSB, "SUNSPGMR", 0)) return(1);
+
+  /* Attach the linear sovler */
+  flag = CVSpilsSetLinearSolverB(cvode_mem, indexB, LSB);
+  if (check_flag(&flag, "CVSpilsSetLinearSolverB", 1)) return 1;
+
+  /* Set the preconditioner solve and setup functions */
   flag = CVSpilsSetPreconditionerB(cvode_mem, indexB, PrecondB, PSolveB);
   if(check_flag(&flag, "CVSpilsSetPreconditionerB", 1)) return(1);
 
@@ -331,8 +341,10 @@ int main(int argc, char *argv[])
   /* Free all memory */
   CVodeFree(&cvode_mem);
 
-  N_VDestroy_Serial(c);
-  N_VDestroy_Serial(cB);
+  N_VDestroy(c);
+  N_VDestroy(cB);
+  SUNLinSolFree(LS);
+  SUNLinSolFree(LSB);
 
   FreeUserData(wdata);
 
@@ -359,8 +371,8 @@ static int f(realtype t, N_Vector c, N_Vector cdot, void *user_data)
   WebData wdata;
   
   wdata = (WebData) user_data;
-  cdata = N_VGetArrayPointer_Serial(c);
-  cdotdata = N_VGetArrayPointer_Serial(cdot);
+  cdata = N_VGetArrayPointer(c);
+  cdotdata = N_VGetArrayPointer(cdot);
   
   mxns = wdata->mxns;
   ns = wdata->ns;
@@ -418,14 +430,13 @@ static int f(realtype t, N_Vector c, N_Vector cdot, void *user_data)
  
 static int Precond(realtype t, N_Vector c, N_Vector fc,
                    booleantype jok, booleantype *jcurPtr, 
-                   realtype gamma, void *user_data,
-                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                   realtype gamma, void *user_data)
 {
   realtype ***P;
-  long int **pivot, ier;
+  sunindextype **pivot, ier;
   int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
   int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
-  long int mp;
+  sunindextype mp;
   realtype uround, fac, r, r0, save, srur;
   realtype *f1, *fsave, *cdata, *rewtdata;
   WebData wdata;
@@ -436,8 +447,8 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
   flag = CVodeGetErrWeights(wdata->cvode_mem, rewt);
   if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
 
-  cdata = N_VGetArrayPointer_Serial(c);
-  rewtdata = N_VGetArrayPointer_Serial(rewt);
+  cdata = N_VGetArrayPointer(c);
+  rewtdata = N_VGetArrayPointer(rewt);
 
   uround = UNIT_ROUNDOFF;
 
@@ -457,7 +468,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
      Here, fsave contains the base value of the rate vector and 
      r0 is a minimum increment factor for the difference quotient. */
 
-  f1 = N_VGetArrayPointer_Serial(vtemp1);
+  f1 = N_VGetArrayPointer(wdata->vtemp);
 
   fac = N_VWrmsNorm (fc, rewt);
   r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*NEQ*fac;
@@ -495,7 +506,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
      if (ier != 0) return(1);
    }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
   return(0);
 }
 
@@ -513,10 +524,10 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
 static int PSolve(realtype t, N_Vector c, N_Vector fc,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype   ***P;
-  long int **pivot;
+  sunindextype **pivot;
   int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx, mp;
   WebData wdata;
 
@@ -526,7 +537,7 @@ static int PSolve(realtype t, N_Vector c, N_Vector fc,
 
   /* call GSIter for Gauss-Seidel iterations */
 
-  GSIter(gamma, z, vtemp, wdata);
+  GSIter(gamma, z, wdata->vtemp, wdata);
 
   /* Do backsolves for inverse of block-diagonal preconditioner factor */
  
@@ -545,7 +556,7 @@ static int PSolve(realtype t, N_Vector c, N_Vector fc,
     for (jx = 0; jx < mx; jx++) {
       igx = jigx[jx];
       ig = igx + igy*ngx;
-      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer_Serial(z)[iv]));
+      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer(z)[iv]));
       iv += mp;
     }
   }
@@ -569,9 +580,9 @@ static int fB(realtype t, N_Vector c, N_Vector cB,
   WebData wdata;
 
   wdata = (WebData) user_data;
-  cdata = N_VGetArrayPointer_Serial(c);
-  cBdata = N_VGetArrayPointer_Serial(cB);
-  cBdotdata = N_VGetArrayPointer_Serial(cBdot);
+  cdata = N_VGetArrayPointer(c);
+  cBdata = N_VGetArrayPointer(cB);
+  cBdotdata = N_VGetArrayPointer(cBdot);
 
   mxns = wdata->mxns;
   ns = wdata->ns;
@@ -621,11 +632,10 @@ static int fB(realtype t, N_Vector c, N_Vector cB,
 static int PrecondB(realtype t, N_Vector c, 
                     N_Vector cB, N_Vector fcB, booleantype jok, 
                     booleantype *jcurPtr, realtype gamma,
-                    void *user_data,
-                    N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+                    void *user_data)
 {
   realtype ***P;
-  long int **pivot, ier;
+  sunindextype **pivot, ier;
   int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
   int *jxr, *jyr, mp, ngrp, ngx, ngy, mxmp, flag;
   realtype uround, fac, r, r0, save, srur;
@@ -641,8 +651,8 @@ static int PrecondB(realtype t, N_Vector c,
   flag = CVodeGetErrWeights(cvode_mem, rewt);
   if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
 
-  cdata = N_VGetArrayPointer_Serial(c);
-  rewtdata = N_VGetArrayPointer_Serial(rewt);
+  cdata = N_VGetArrayPointer(c);
+  rewtdata = N_VGetArrayPointer(rewt);
 
   uround = UNIT_ROUNDOFF;
 
@@ -662,7 +672,7 @@ static int PrecondB(realtype t, N_Vector c,
      Here, fsave contains the base value of the rate vector and 
      r0 is a minimum increment factor for the difference quotient. */
 
-  f1 = N_VGetArrayPointer_Serial(vtemp1);
+  f1 = N_VGetArrayPointer(wdata->vtemp);
 
   fac = N_VWrmsNorm (fcB, rewt);
   r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*NEQ*fac;
@@ -700,7 +710,7 @@ static int PrecondB(realtype t, N_Vector c,
      if (ier != 0) return(1);
    }
 
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
   return(0);
 }
 
@@ -712,12 +722,12 @@ static int PSolveB(realtype t, N_Vector c,
                    N_Vector cB, N_Vector fcB, 
                    N_Vector r, N_Vector z,
                    realtype gamma, realtype delta, 
-                   int lr, void *user_data, N_Vector vtemp)
+                   int lr, void *user_data)
 {
   realtype ***P;
-  long int **pivot;
+  sunindextype **pivot;
   int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
-  long int mp;
+  sunindextype mp;
   WebData wdata;
 
   wdata = (WebData) user_data;
@@ -726,7 +736,7 @@ static int PSolveB(realtype t, N_Vector c,
 
   /* call GSIter for Gauss-Seidel iterations (same routine but with gamma=-gamma) */
 
-  GSIter(-gamma, z, vtemp, wdata);
+  GSIter(-gamma, z, wdata->vtemp, wdata);
 
   /* Do backsolves for inverse of block-diagonal preconditioner factor */
  
@@ -745,7 +755,7 @@ static int PSolveB(realtype t, N_Vector c,
     for (jx = 0; jx < mx; jx++) {
       igx = jigx[jx];
       ig = igx + igy*ngx;
-      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer_Serial(z)[iv]));
+      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer(z)[iv]));
       iv += mp;
     }
   }
@@ -766,15 +776,17 @@ static int PSolveB(realtype t, N_Vector c,
 static WebData AllocUserData(void)
 {
   int i, ngrp = NGRP;
-  long int ns = NS;
+  sunindextype ns = NS;
   WebData wdata;
 
   wdata = (WebData) malloc(sizeof *wdata);
   for(i=0; i < ngrp; i++) {
     (wdata->P)[i] = newDenseMat(ns, ns);
-    (wdata->pivot)[i] = newLintArray(ns);
+    (wdata->pivot)[i] = newIndexArray(ns);
   }
-  wdata->rewt = N_VNew_Serial(NEQ);
+  wdata->rewt  = N_VNew_Serial(NEQ);
+  wdata->vtemp = N_VNew_Serial(NEQ);
+
   return(wdata);
 }
 
@@ -872,7 +884,7 @@ static void CInit(N_Vector c, WebData wdata)
   int i, ici, ioff, iyoff, jx, jy, ns, mxns;
   realtype argx, argy, x, y, dx, dy, x_factor, y_factor, *cdata;
   
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
   ns = wdata->ns;
   mxns = wdata->mxns;
   dx = wdata->dx;
@@ -907,7 +919,7 @@ static void CbInit(N_Vector c, int is, WebData wdata)
 
   realtype gu[NS];
 
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
   ns = wdata->ns;
   mxns = wdata->mxns;
 
@@ -1025,8 +1037,8 @@ static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata)
   realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
   realtype temp, *cox, *coy, *xd, *zd;
 
-  xd = N_VGetArrayPointer_Serial(x);
-  zd = N_VGetArrayPointer_Serial(z);
+  xd = N_VGetArrayPointer(x);
+  zd = N_VGetArrayPointer(z);
   ns = wdata->ns;
   mx = wdata->mx;
   my = wdata->my;
@@ -1207,7 +1219,7 @@ static void PrintOutput(N_Vector cB, int ns, int mxns, WebData wdata)
 
   x = y = ZERO;
 
-  cdata = N_VGetArrayPointer_Serial(cB);
+  cdata = N_VGetArrayPointer(cB);
 
   for (i=1; i <= ns; i++) {
 
@@ -1257,7 +1269,7 @@ static realtype doubleIntgr(N_Vector c, int i, WebData wdata)
   realtype intgr_xy, intgr_x;
   int jx, jy;
 
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
 
   ns   = wdata->ns;
   mx   = wdata->mx;
@@ -1317,7 +1329,8 @@ static void FreeUserData(WebData wdata)
     destroyMat((wdata->P)[i]);
     destroyArray((wdata->pivot)[i]);
   }
-  N_VDestroy_Serial(wdata->rewt);
+  N_VDestroy(wdata->rewt);
+  N_VDestroy(wdata->vtemp);
   free(wdata);
 }
 
diff --git a/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out b/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out
index f822e64..e2741ad 100644
--- a/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out
+++ b/examples/cvodes/serial/cvsFoodWeb_ASAp_kry.out
@@ -5,9 +5,9 @@ Allocate global memory
 
 Forward integration
 
-ncheck = 11
+ncheck = 10
 
-   g = int_x int_y c6(Tfinal,x,y) dx dy = 35988.914996 
+   g = int_x int_y c6(Tfinal,x,y) dx dy = 35988.915465 
 
 
 Create and allocate CVODES memory for backward run
@@ -15,37 +15,37 @@ Create and allocate CVODES memory for backward run
 Backward integration
 
 Maximum sensitivity with respect to I.C. of species 1
-  mu max = 5.105006e-04
+  mu max = 5.079649e-04
 at
   x = 1.000000e+00
   y = 1.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 2
-  mu max = 4.865450e-04
+  mu max = 4.839950e-04
 at
   x = 1.000000e+00
   y = 1.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 3
-  mu max = 4.644767e-04
+  mu max = 4.619138e-04
 at
   x = 1.000000e+00
   y = 1.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 4
-  mu max = 3.447561e-12
+  mu max = -3.479276e-13
 at
   x = 1.000000e+00
-  y = 8.421053e-01
+  y = 0.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 5
-  mu max = 3.434214e-12
+  mu max = -3.477829e-13
 at
   x = 1.000000e+00
-  y = 8.421053e-01
+  y = 0.000000e+00
 
 Maximum sensitivity with respect to I.C. of species 6
-  mu max = 6.326559e-12
+  mu max = -1.870030e-13
 at
   x = 1.000000e+00
   y = 0.000000e+00
diff --git a/examples/cvodes/serial/cvsHessian_ASA_FSA.c b/examples/cvodes/serial/cvsHessian_ASA_FSA.c
index 1372a2f..cec3d5f 100644
--- a/examples/cvodes/serial/cvsHessian_ASA_FSA.c
+++ b/examples/cvodes/serial/cvsHessian_ASA_FSA.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4956 $
- * $Date: 2016-09-23 11:15:59 -0700 (Fri, 23 Sep 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -35,16 +31,17 @@
  *
  * See D.B. Ozyurt and P.I. Barton, SISC 26(5) 1725-1743, 2005.
  *
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <cvodes/cvodes.h>
-#include <cvodes/cvodes_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <cvodes/cvodes.h>              /* prototypes for CVODES fcts., consts. */
+#include <nvector/nvector_serial.h>     /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_dense.h>  /* access to band SUNLinearSolver       */
+#include <cvodes/cvodes_direct.h>       /* access to CVDls interface            */
+#include <sundials/sundials_math.h>     /* definition of SUNRabs, SUNRexp, etc. */
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)
 
@@ -82,6 +79,10 @@ static int fQB2(realtype t, N_Vector y, N_Vector *yS,
 void PrintFwdStats(void *cvode_mem);
 void PrintBckStats(void *cvode_mem, int idx);
 
+/* Private function to check function return values */
+
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+
 /*
  *--------------------------------------------------------------------
  * MAIN PROGRAM
@@ -92,9 +93,11 @@ int main(int argc, char *argv[])
 {
   UserData data;
 
+  SUNMatrix A, AB1, AB2;
+  SUNLinearSolver LS, LSB1, LSB2;
   void *cvode_mem;
 
-  long int Neq, Np2;
+  sunindextype Neq, Np2;
   int Np;
 
   realtype t0, tf;
@@ -118,6 +121,14 @@ int main(int argc, char *argv[])
   realtype grdG_fwd[2], grdG_bck[2], grdG_cntr[2];
   realtype H11, H22;
 
+  data = NULL;
+  y = yQ = NULL;
+  yB1 = yB2 = NULL;
+  yQB1 = yQB2 = NULL;
+  A = AB1 = AB2 = NULL;
+  LS = LSB1 = LSB2 = NULL;
+  cvode_mem = NULL;
+
   /* User data structure */
 
   data = (UserData) malloc(sizeof *data);
@@ -144,46 +155,81 @@ int main(int argc, char *argv[])
   /* Initializations for forward problem */
 
   y = N_VNew_Serial(Neq);
+  if (check_flag((void *)y, "N_VNew_Serial", 0)) return(1);
   N_VConst(ONE, y);
 
   yQ = N_VNew_Serial(1);
+  if (check_flag((void *)yQ, "N_VNew_Serial", 0)) return(1);
   N_VConst(ZERO, yQ);
 
-  yS = N_VCloneVectorArray_Serial(Np, y);
+  yS = N_VCloneVectorArray(Np, y);
+  if (check_flag((void *)yS, "N_VCloneVectorArray", 0)) return(1);
   N_VConst(ZERO, yS[0]);
   N_VConst(ZERO, yS[1]);
 
-  yQS = N_VCloneVectorArray_Serial(Np, yQ);
+  yQS = N_VCloneVectorArray(Np, yQ);
+  if (check_flag((void *)yQS, "N_VCloneVectorArray", 0)) return(1);
   N_VConst(ZERO, yQS[0]);
   N_VConst(ZERO, yQS[1]);
 
   /* Create and initialize forward problem */
 
   cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
+  if(check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
 
   flag = CVodeInit(cvode_mem, f, t0, y);
+  if(check_flag(&flag, "CVodeInit", 1)) return(1);
+
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+  if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
   flag = CVodeSetUserData(cvode_mem, data);
+  if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+  /* Create a dense SUNMatrix */
+  A = SUNDenseMatrix(Neq, Neq);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
 
-  flag = CVDense(cvode_mem, Neq);
+  /* Create banded SUNLinearSolver for the forward problem */
+  LS = SUNDenseLinearSolver(y, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   flag = CVodeQuadInit(cvode_mem, fQ, yQ);
+  if(check_flag(&flag, "CVodeQuadInit", 1)) return(1);
+
   flag = CVodeQuadSStolerances(cvode_mem, reltol, abstolQ);
-  flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+  if(check_flag(&flag, "CVodeQuadSStolerances", 1)) return(1);
+
+  flag = CVodeSetQuadErrCon(cvode_mem, SUNTRUE);
+  if(check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1);
 
   flag = CVodeSensInit(cvode_mem, Np, CV_SIMULTANEOUS, fS, yS);
+  if(check_flag(&flag, "CVodeSensInit", 1)) return(1);
+
   flag = CVodeSensEEtolerances(cvode_mem);
-  flag = CVodeSetSensErrCon(cvode_mem, TRUE);
+  if(check_flag(&flag, "CVodeSensEEtolerances", 1)) return(1);
+
+  flag = CVodeSetSensErrCon(cvode_mem, SUNTRUE);
+  if(check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1);
 
   flag = CVodeQuadSensInit(cvode_mem, fQS, yQS);
+  if(check_flag(&flag, "CVodeQuadSensInit", 1)) return(1);
 
   flag = CVodeQuadSensEEtolerances(cvode_mem);
-  flag = CVodeSetQuadSensErrCon(cvode_mem, TRUE);
+  if(check_flag(&flag, "CVodeQuadSensEEtolerances", 1)) return(1);
+
+  flag = CVodeSetQuadSensErrCon(cvode_mem, SUNTRUE);
+  if(check_flag(&flag, "CVodeSetQuadSensErrCon", 1)) return(1);
 
   /* Initialize ASA */
 
   steps = 100;
   flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL);
+  if(check_flag(&flag, "CVodeAdjInit", 1)) return(1);
 
   /* Forward integration */
 
@@ -192,16 +238,30 @@ int main(int argc, char *argv[])
   printf("-------------------\n\n");
 
   flag = CVodeF(cvode_mem, tf, y, &time, CV_NORMAL, &ncheck);
+  if(check_flag(&flag, "CVodeF", 1)) return(1);
 
   flag = CVodeGetQuad(cvode_mem, &time, yQ);
+  if(check_flag(&flag, "CVodeGetQuad", 1)) return(1);
+
   G = Ith(yQ,1);
 
   flag = CVodeGetSens(cvode_mem, &time, yS);
+  if(check_flag(&flag, "CVodeGetSens", 1)) return(1);
 
   flag = CVodeGetQuadSens(cvode_mem, &time, yQS);
+  if(check_flag(&flag, "CVodeGetQuadSens", 1)) return(1);
 
   printf("ncheck = %d\n", ncheck);
   printf("\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("     y:    %12.4Le %12.4Le %12.4Le", Ith(y,1), Ith(y,2), Ith(y,3));
+  printf("     G:    %12.4Le\n", Ith(yQ,1));
+  printf("\n");
+  printf("     yS1:  %12.4Le %12.4Le %12.4Le\n", Ith(yS[0],1), Ith(yS[0],2), Ith(yS[0],3));
+  printf("     yS2:  %12.4Le %12.4Le %12.4Le\n", Ith(yS[1],1), Ith(yS[1],2), Ith(yS[1],3));
+  printf("\n");
+  printf("   dG/dp:  %12.4Le %12.4Le\n", Ith(yQS[0],1), Ith(yQS[1],1));
+#else
   printf("     y:    %12.4e %12.4e %12.4e", Ith(y,1), Ith(y,2), Ith(y,3));
   printf("     G:    %12.4e\n", Ith(yQ,1));
   printf("\n");
@@ -209,6 +269,7 @@ int main(int argc, char *argv[])
   printf("     yS2:  %12.4e %12.4e %12.4e\n", Ith(yS[1],1), Ith(yS[1],2), Ith(yS[1],3));
   printf("\n");
   printf("   dG/dp:  %12.4e %12.4e\n", Ith(yQS[0],1), Ith(yQS[1],1));
+#endif
   printf("\n");
 
   printf("Final Statistics for forward pb.\n");
@@ -219,36 +280,96 @@ int main(int argc, char *argv[])
   /* Initializations for backward problems */
 
   yB1 = N_VNew_Serial(2*Neq);
+  if (check_flag((void *)yB1, "N_VNew_Serial", 0)) return(1);
   N_VConst(ZERO, yB1);
 
   yQB1 = N_VNew_Serial(Np2);
+  if (check_flag((void *)yQB1, "N_VNew_Serial", 0)) return(1);
   N_VConst(ZERO, yQB1);
 
   yB2 = N_VNew_Serial(2*Neq);
+  if (check_flag((void *)yB2, "N_VNew_Serial", 0)) return(1);
   N_VConst(ZERO, yB2);
 
   yQB2 = N_VNew_Serial(Np2);
+  if (check_flag((void *)yQB2, "N_VNew_Serial", 0)) return(1);
   N_VConst(ZERO, yQB2);
 
   /* Create and initialize backward problems (one for each column of the Hessian) */
 
+  /* -------------------------
+     First backward problem
+     -------------------------*/
+
   flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB1);
+  if(check_flag(&flag, "CVodeCreateB", 1)) return(1);
+
   flag = CVodeInitBS(cvode_mem, indexB1, fB1, tf, yB1);
+  if(check_flag(&flag, "CVodeInitBS", 1)) return(1);
+
   flag = CVodeSStolerancesB(cvode_mem, indexB1, reltol, abstolB);
+  if(check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);
+
   flag = CVodeSetUserDataB(cvode_mem, indexB1, data);
+  if(check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
+
   flag = CVodeQuadInitBS(cvode_mem, indexB1, fQB1, yQB1);
+  if(check_flag(&flag, "CVodeQuadInitBS", 1)) return(1);
+
   flag = CVodeQuadSStolerancesB(cvode_mem, indexB1, reltol, abstolQB);
-  flag = CVodeSetQuadErrConB(cvode_mem, indexB1, TRUE);
-  flag = CVDenseB(cvode_mem, indexB1, 2*Neq);
+  if(check_flag(&flag, "CVodeQuadSStolerancesB", 1)) return(1);
+
+  flag = CVodeSetQuadErrConB(cvode_mem, indexB1, SUNTRUE);
+  if(check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1);
+
+  /* Create a dense SUNMatrix */
+  AB1 = SUNDenseMatrix(2*Neq, 2*Neq);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver for the forward problem */
+  LSB1 = SUNDenseLinearSolver(yB1, AB1);
+  if(check_flag((void *)LSB1, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolverB(cvode_mem, indexB1, LSB1, AB1);
+  if(check_flag(&flag, "CVDlsSetLinearSolverB", 1)) return(1);
+
+  /* -------------------------
+     Second backward problem
+     -------------------------*/
 
   flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB2);
+  if(check_flag(&flag, "CVodeCreateB", 1)) return(1);
+
   flag = CVodeInitBS(cvode_mem, indexB2, fB2, tf, yB2);
+  if(check_flag(&flag, "CVodeInitBS", 1)) return(1);
+
   flag = CVodeSStolerancesB(cvode_mem, indexB2, reltol, abstolB);
+  if(check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);
+
   flag = CVodeSetUserDataB(cvode_mem, indexB2, data);
+  if(check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
+
   flag = CVodeQuadInitBS(cvode_mem, indexB2, fQB2, yQB2);
+  if(check_flag(&flag, "CVodeQuadInitBS", 1)) return(1);
+
   flag = CVodeQuadSStolerancesB(cvode_mem, indexB2, reltol, abstolQB);
-  flag = CVodeSetQuadErrConB(cvode_mem, indexB2, TRUE);
-  flag = CVDenseB(cvode_mem, indexB2, 2*Neq);
+  if(check_flag(&flag, "CVodeQuadSStolerancesB", 1)) return(1);
+
+  flag = CVodeSetQuadErrConB(cvode_mem, indexB2, SUNTRUE);
+  if(check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1);
+
+  /* Create a dense SUNMatrix */
+  AB2 = SUNDenseMatrix(2*Neq, 2*Neq);
+  if(check_flag((void *)AB2, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver for the forward problem */
+  LSB2 = SUNDenseLinearSolver(yB2, AB2);
+  if(check_flag((void *)LSB2, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolverB(cvode_mem, indexB2, LSB2, AB2);
+  if(check_flag(&flag, "CVDlsSetLinearSolverB", 1)) return(1);
 
   /* Backward integration */
 
@@ -257,20 +378,37 @@ int main(int argc, char *argv[])
   printf("---------------------------------------------\n\n");
 
   flag = CVodeB(cvode_mem, t0, CV_NORMAL);
+  if(check_flag(&flag, "CVodeB", 1)) return(1);
 
   flag = CVodeGetB(cvode_mem, indexB1, &time, yB1);
+  if(check_flag(&flag, "CVodeGetB", 1)) return(1);
+
   flag = CVodeGetQuadB(cvode_mem, indexB1, &time, yQB1);
+  if(check_flag(&flag, "CVodeGetQuadB", 1)) return(1);
 
   flag = CVodeGetB(cvode_mem, indexB2, &time, yB2);
+  if(check_flag(&flag, "CVodeGetB", 1)) return(1);
+
   flag = CVodeGetQuadB(cvode_mem, indexB2, &time, yQB2);
+  if(check_flag(&flag, "CVodeGetQuadB", 1)) return(1);
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le   (from backward pb. 1)\n", -Ith(yQB1,1), -Ith(yQB1,2));
+  printf("           %12.4Le %12.4Le   (from backward pb. 2)\n", -Ith(yQB2,1), -Ith(yQB2,2));
+#else
   printf("   dG/dp:  %12.4e %12.4e   (from backward pb. 1)\n", -Ith(yQB1,1), -Ith(yQB1,2));
   printf("           %12.4e %12.4e   (from backward pb. 2)\n", -Ith(yQB2,1), -Ith(yQB2,2));
+#endif  
   printf("\n");
   printf("   H = d2G/dp2:\n");
   printf("        (1)            (2)\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("  %12.4Le   %12.4Le\n", -Ith(yQB1,3) , -Ith(yQB2,3));
+  printf("  %12.4Le   %12.4Le\n", -Ith(yQB1,4) , -Ith(yQB2,4));
+#else
   printf("  %12.4e   %12.4e\n", -Ith(yQB1,3) , -Ith(yQB2,3));
   printf("  %12.4e   %12.4e\n", -Ith(yQB1,4) , -Ith(yQB2,4));
+#endif
   printf("\n");
 
   printf("Final Statistics for backward pb. 1\n");
@@ -281,9 +419,15 @@ int main(int argc, char *argv[])
   printf("-----------------------------------\n");
   PrintBckStats(cvode_mem, indexB2);
 
-  /* Free CVODES memory */
+  /* Free memory */
 
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB1);
+  SUNMatDestroy(AB1);
+  SUNLinSolFree(LSB2);
+  SUNMatDestroy(AB2);
 
   /* Finite difference tests */
 
@@ -293,40 +437,86 @@ int main(int argc, char *argv[])
   printf("Finite Difference tests\n");
   printf("-----------------------\n\n");
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("del_p = %Lg\n\n",dp);
+#else
   printf("del_p = %g\n\n",dp);
+#endif
 
   cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
 
   N_VConst(ONE, y);
   N_VConst(ZERO, yQ);
+
   flag = CVodeInit(cvode_mem, f, t0, y);
+  if(check_flag(&flag, "CVodeInit", 1)) return(1);
+
   flag = CVodeSStolerances(cvode_mem, reltol, abstol);
+  if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
   flag = CVodeSetUserData(cvode_mem, data);
-  flag = CVDense(cvode_mem, Neq);
+  if(check_flag(&flag, "CVodeSetUserData", 1)) return(1);
+
+  /* Create a dense SUNMatrix */
+  A = SUNDenseMatrix(Neq, Neq);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver for the forward problem */
+  LS = SUNDenseLinearSolver(y, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
   flag = CVodeQuadInit(cvode_mem, fQ, yQ);
+  if(check_flag(&flag, "CVodeQuadInit", 1)) return(1);
+
   flag = CVodeQuadSStolerances(cvode_mem, reltol, abstolQ);
-  flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+  if(check_flag(&flag, "CVodeQuadSStolerances", 1)) return(1);
+
+  flag = CVodeSetQuadErrCon(cvode_mem, SUNTRUE);
+  if(check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1);
 
   data->p1 += dp;
 
   flag = CVode(cvode_mem, tf, y, &time, CV_NORMAL);
+  if(check_flag(&flag, "CVode", 1)) return(1);
+
   flag = CVodeGetQuad(cvode_mem, &time, yQ);
+  if(check_flag(&flag, "CVodeGetQuad", 1)) return(1);
+
   Gp = Ith(yQ,1);
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("p1+  y:   %12.4Le %12.4Le %12.4Le", Ith(y,1), Ith(y,2), Ith(y,3));
+  printf("     G:   %12.4Le\n",Ith(yQ,1));
+#else
   printf("p1+  y:   %12.4e %12.4e %12.4e", Ith(y,1), Ith(y,2), Ith(y,3));
   printf("     G:   %12.4e\n",Ith(yQ,1));
-
+#endif  
   data->p1 -= 2.0*dp;
 
   N_VConst(ONE, y);
   N_VConst(ZERO, yQ);
+
   CVodeReInit(cvode_mem, t0, y);
   CVodeQuadReInit(cvode_mem, yQ);
+
   flag = CVode(cvode_mem, tf, y, &time, CV_NORMAL);
+  if(check_flag(&flag, "CVode", 1)) return(1);
+
   flag = CVodeGetQuad(cvode_mem, &time, yQ);
+  if(check_flag(&flag, "CVodeGetQuad", 1)) return(1);
+
   Gm = Ith(yQ,1);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("p1-  y:   %12.4Le %12.4Le %12.4Le", Ith(y,1), Ith(y,2), Ith(y,3));
+  printf("     G:   %12.4Le\n",Ith(yQ,1));
+#else
   printf("p1-  y:   %12.4e %12.4e %12.4e", Ith(y,1), Ith(y,2), Ith(y,3));
   printf("     G:   %12.4e\n",Ith(yQ,1));
- 
+#endif
   data->p1 += dp;
 
   grdG_fwd[0] = (Gp-G)/dp;
@@ -338,26 +528,46 @@ int main(int argc, char *argv[])
 
   N_VConst(ONE, y);
   N_VConst(ZERO, yQ);
+
   CVodeReInit(cvode_mem, t0, y);
   CVodeQuadReInit(cvode_mem, yQ);
+
   flag = CVode(cvode_mem, tf, y, &time, CV_NORMAL);
+  if(check_flag(&flag, "CVode", 1)) return(1);
+
   flag = CVodeGetQuad(cvode_mem, &time, yQ);
+  if(check_flag(&flag, "CVodeGetQuad", 1)) return(1);
+
   Gp = Ith(yQ,1);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("p2+  y:   %12.4Le %12.4Le %12.4Le", Ith(y,1), Ith(y,2), Ith(y,3));
+  printf("     G:   %12.4Le\n",Ith(yQ,1));
+#else
   printf("p2+  y:   %12.4e %12.4e %12.4e", Ith(y,1), Ith(y,2), Ith(y,3));
   printf("     G:   %12.4e\n",Ith(yQ,1));
- 
+#endif
   data->p2 -= 2.0*dp;
 
   N_VConst(ONE, y);
   N_VConst(ZERO, yQ);
+
   CVodeReInit(cvode_mem, t0, y);
   CVodeQuadReInit(cvode_mem, yQ);
+
   flag = CVode(cvode_mem, tf, y, &time, CV_NORMAL);
+  if(check_flag(&flag, "CVode", 1)) return(1);
+
   flag = CVodeGetQuad(cvode_mem, &time, yQ);
+  if(check_flag(&flag, "CVodeGetQuad", 1)) return(1);
+
   Gm = Ith(yQ,1);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("p2-  y:   %12.4Le %12.4Le %12.4Le", Ith(y,1), Ith(y,2), Ith(y,3));
+  printf("     G:   %12.4Le\n",Ith(yQ,1));
+#else
   printf("p2-  y:   %12.4e %12.4e %12.4e", Ith(y,1), Ith(y,2), Ith(y,3));
   printf("     G:   %12.4e\n",Ith(yQ,1));
-
+#endif  
   data->p2 += dp;
 
   grdG_fwd[1] = (Gp-G)/dp;
@@ -367,28 +577,38 @@ int main(int argc, char *argv[])
 
   printf("\n");
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le   (fwd FD)\n", grdG_fwd[0], grdG_fwd[1]);
+  printf("           %12.4Le %12.4Le   (bck FD)\n", grdG_bck[0], grdG_bck[1]);
+  printf("           %12.4Le %12.4Le   (cntr FD)\n", grdG_cntr[0], grdG_cntr[1]);
+  printf("\n");
+  printf("  H(1,1):  %12.4Le\n", H11);
+  printf("  H(2,2):  %12.4Le\n", H22);
+#else
   printf("   dG/dp:  %12.4e %12.4e   (fwd FD)\n", grdG_fwd[0], grdG_fwd[1]);
   printf("           %12.4e %12.4e   (bck FD)\n", grdG_bck[0], grdG_bck[1]);
   printf("           %12.4e %12.4e   (cntr FD)\n", grdG_cntr[0], grdG_cntr[1]);
   printf("\n");
   printf("  H(1,1):  %12.4e\n", H11);
   printf("  H(2,2):  %12.4e\n", H22);
-
+#endif  
 
   /* Free memory */
 
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
 
-  N_VDestroy_Serial(y);
-  N_VDestroy_Serial(yQ);
+  N_VDestroy(y);
+  N_VDestroy(yQ);
 
-  N_VDestroyVectorArray_Serial(yS, Np);
-  N_VDestroyVectorArray_Serial(yQS, Np);
+  N_VDestroyVectorArray(yS, Np);
+  N_VDestroyVectorArray(yQS, Np);
 
-  N_VDestroy_Serial(yB1);
-  N_VDestroy_Serial(yQB1);
-  N_VDestroy_Serial(yB2);
-  N_VDestroy_Serial(yQB2);
+  N_VDestroy(yB1);
+  N_VDestroy(yQB1);
+  N_VDestroy(yB2);
+  N_VDestroy(yQB2);
 
   free(data);
 
@@ -782,3 +1002,41 @@ void PrintBckStats(void *cvode_mem, int idx)
 
 
 }
+
+/*
+ * Check function return value...
+ *   opt == 0 means SUNDIALS function allocates memory so check if
+ *            returned NULL pointer
+ *   opt == 1 means SUNDIALS function returns a flag so check if
+ *            flag >= 0
+ *   opt == 2 means function allocates memory so check if returned
+ *            NULL pointer 
+ */
+
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+  if (opt == 0 && flagvalue == NULL) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return(1); }
+
+  /* Check if flag < 0 */
+  else if (opt == 1) {
+    errflag = (int *) flagvalue;
+    if (*errflag < 0) {
+      fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return(1); }}
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  else if (opt == 2 && flagvalue == NULL) {
+    fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return(1); }
+
+  return(0);
+}
+
diff --git a/examples/cvodes/serial/cvsKrylovDemo_ls.c b/examples/cvodes/serial/cvsKrylovDemo_ls.c
index ec6f764..7346da2 100644
--- a/examples/cvodes/serial/cvsKrylovDemo_ls.c
+++ b/examples/cvodes/serial/cvsKrylovDemo_ls.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4849 $
- * $Date: 2016-08-03 16:00:06 -0700 (Wed, 03 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  *
@@ -26,27 +22,27 @@
  *   0 <= t <= 86400 sec (1 day).
  * The PDE system is treated by central differences on a uniform
  * 10 x 10 mesh, with simple polynomial initial profiles.
- * The problem is solved with CVODES, with the BDF/GMRES,
- * BDF/Bi-CGStab, and BDF/TFQMR methods (i.e. using the CVSPGMR,
- * CVSPBCG and CVSPTFQMR linear solvers) and the block-diagonal
+ * The problem is solved with CVODE, with the BDF/GMRES,
+ * BDF/Bi-CGStab, and BDF/TFQMR methods (i.e. using the SUNSPGMR,
+ * SUNSPBCGS and SUNSPTFQMR linear solvers) and the block-diagonal
  * part of the Newton matrix as a left preconditioner. A copy of
  * the block-diagonal part of the Jacobian is saved and
  * conditionally reused within the Precond routine.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>           /* main integrator header file */
-#include <cvodes/cvodes_spgmr.h>     /* prototypes & constants for CVSPGMR solver */
-#include <cvodes/cvodes_spbcgs.h>    /* prototypes & constants for CVSPBCG solver */
-#include <cvodes/cvodes_sptfqmr.h>   /* prototypes & constants for CVSPTFQMR solver */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_dense.h> /* use generic DENSE solver in preconditioning */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS, SUNSQR, and EXP */
+#include <cvodes/cvodes.h>               /* main integrator header file       */
+#include <cvodes/cvodes_spils.h>         /* access to CVSpils interface       */
+#include <sunlinsol/sunlinsol_spgmr.h>   /* access to SPGMR SUNLinearSolver   */
+#include <sunlinsol/sunlinsol_spbcgs.h>  /* access to SPBCGS SUNLinearSolver  */
+#include <sunlinsol/sunlinsol_sptfqmr.h> /* access to SPTFQMR SUNLinearSolver */
+#include <nvector/nvector_serial.h>      /* serial N_Vector types, fct. and macros */
+#include <sundials/sundials_dense.h>     /* use generic DENSE solver in preconditioning */
+#include <sundials/sundials_types.h>     /* definition of realtype */
+#include <sundials/sundials_math.h>      /* contains the macros ABS, SUNSQR, and EXP */
 
 /* Problem Constants */
 
@@ -109,7 +105,7 @@
    IJKth(vdata,i,j,k) references the element in the vdata array for
    species i at mesh point (j,k), where 1 <= i <= NUM_SPECIES,
    0 <= j <= MX-1, 0 <= k <= MY-1. The vdata array is obtained via
-   the macro call vdata = N_VGetArrayPointer_Serial(v), where v is an N_Vector. 
+   the call vdata = N_VGetArrayPointer(v), where v is an N_Vector. 
    For each mesh point (j,k), the elements for species i and i+1 are
    contiguous within vdata.
 
@@ -126,7 +122,7 @@
 
 typedef struct {
   realtype **P[MX][MY], **Jbd[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   realtype q4, om, dx, dy, hdco, haco, vdco;
 } *UserData;
 
@@ -144,15 +140,13 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 static int f(realtype t, N_Vector u, N_Vector udot, void *user_data);
 
-static int Precond(realtype tn, N_Vector u, N_Vector fu,
-                   booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3);
+static int Precond(realtype tn, N_Vector u, N_Vector fu, booleantype jok,
+                   booleantype *jcurPtr, realtype gamma, void *user_data);
 
 static int PSolve(realtype tn, N_Vector u, N_Vector fu,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+                  int lr, void *user_data);
 
 
 /*
@@ -166,11 +160,13 @@ int main(void)
   realtype abstol, reltol, t, tout;
   N_Vector u;
   UserData data;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int linsolver, iout, flag;
 
   u = NULL;
   data = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
@@ -230,10 +226,13 @@ int main(void)
       printf(" \n| SPGMR |\n");
       printf(" -------\n");
 
-      /* Call CVSpgmr to specify the linear solver CVSPGMR 
-	 with left preconditioning and the maximum Krylov dimension maxl */
-      flag = CVSpgmr(cvode_mem, PREC_LEFT, 0);
-      if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+      /* Call SUNSPGMR to specify the linear solver SPGMR 
+	 with left preconditioning and the default Krylov dimension */
+      LS = SUNSPGMR(u, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+      flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+      if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -242,13 +241,16 @@ int main(void)
 
       /* Print header */
       printf(" -------");
-      printf(" \n| SPBCG |\n");
+      printf(" \n| SPBCGS |\n");
       printf(" -------\n");
 
-      /* Call CVSpbcg to specify the linear solver CVSPBCG 
+      /* Call SUNSPBCGS to specify the linear solver SPBCGS
 	 with left preconditioning and the maximum Krylov dimension maxl */
-      flag = CVSpbcg(cvode_mem, PREC_LEFT, 0);
-      if(check_flag(&flag, "CVSpbcg", 1)) return(1);
+      LS = SUNSPBCGS(u, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPBCGS", 0)) return(1);
+
+      flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+      if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -260,17 +262,21 @@ int main(void)
       printf(" \n| SPTFQMR |\n");
       printf(" ---------\n");
 
-      /* Call CVSptfqmr to specify the linear solver CVSPTFQMR 
+      /* Call SUNSPTFQMR to specify the linear solver SPTFQMR 
 	 with left preconditioning and the maximum Krylov dimension maxl */
-      flag = CVSptfqmr(cvode_mem, PREC_LEFT, 0);
-      if(check_flag(&flag, "CVSptfqmr", 1)) return(1);
+      LS = SUNSPTFQMR(u, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPTFQMR", 0)) return(1);
+
+      flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+      if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
     }
 
 
-    /* Set preconditioner setup and solve routines Precond and PSolve. */
+    /* Set preconditioner setup and solve routines Precond and PSolve,
+       and the pointer to the user-defined block data */
     flag = CVSpilsSetPreconditioner(cvode_mem, Precond, PSolve);
     if(check_flag(&flag, "CVSpilsSetPreconditioner", 1)) return(1);
 
@@ -287,9 +293,10 @@ int main(void)
   }  /* END: Loop through SPGMR, SPBCG and SPTFQMR linear solver modules */
 
   /* Free memory */
-  N_VDestroy_Serial(u);
+  N_VDestroy(u);
   FreeUserData(data);
   CVodeFree(&cvode_mem);
+  SUNLinSolFree(LS);
 
   return(0);
 }
@@ -313,7 +320,7 @@ static UserData AllocUserData(void)
     for (jy=0; jy < MY; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
       (data->Jbd)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
 
@@ -359,7 +366,7 @@ static void SetInitialProfiles(N_Vector u, realtype dx, realtype dy)
 
   /* Set pointer to data array in vector u. */
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   /* Load initial profiles of c1 and c2 into u vector */
 
@@ -386,7 +393,7 @@ static void PrintOutput(void *cvode_mem, N_Vector u, realtype t)
   realtype hu, *udata;
   int mxh = MX/2 - 1, myh = MY/2 - 1, mx1 = MX - 1, my1 = MY - 1;
 
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -458,9 +465,9 @@ static void PrintFinalStats(void *cvode_mem, int linsolver)
   check_flag(&flag, "CVSpilsGetNumRhsEvals", 1);
 
   printf("\nFinal Statistics.. \n\n");
-  printf("lenrw   = %5ld     leniw   = %5ld\n", lenrw, leniw);
-  printf("lenrwLS = %5ld     leniwLS = %5ld\n", lenrwLS, leniwLS);
-  printf("nst     = %5ld\n"                  , nst);
+  printf("lenrw   = %5ld     leniw   = %5ld\n"  , lenrw, leniw);
+  printf("lenrwLS = %5ld     leniwLS = %5ld\n"  , lenrwLS, leniwLS);
+  printf("nst     = %5ld\n"                     , nst);
   printf("nfe     = %5ld     nfeLS   = %5ld\n"  , nfe, nfeLS);
   printf("nni     = %5ld     nli     = %5ld\n"  , nni, nli);
   printf("nsetups = %5ld     netf    = %5ld\n"  , nsetups, netf);
@@ -525,8 +532,8 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
   UserData data;
 
   data = (UserData) user_data;
-  udata = N_VGetArrayPointer_Serial(u);
-  dudata = N_VGetArrayPointer_Serial(udot);
+  udata = N_VGetArrayPointer(u);
+  dudata = N_VGetArrayPointer(udot);
 
   /* Set diurnal rate coefficients. */
 
@@ -606,14 +613,12 @@ static int f(realtype t, N_Vector u, N_Vector udot, void *user_data)
 
 /* Preconditioner setup routine. Generate and preprocess P. */
 
-static int Precond(realtype tn, N_Vector u, N_Vector fu,
-                   booleantype jok, booleantype *jcurPtr, realtype gamma,
-                   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3)
+static int Precond(realtype tn, N_Vector u, N_Vector fu, booleantype jok,
+                   booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   realtype c1, c2, cydn, cyup, diag, ydn, yup, q4coef, dely, verdco, hordco;
   realtype **(*P)[MY], **(*Jbd)[MY];
-  long int *(*pivot)[MY], ier;
+  sunindextype *(*pivot)[MY], ier;
   int jx, jy;
   realtype *udata, **a, **j;
   UserData data;
@@ -624,22 +629,22 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
   P = data->P;
   Jbd = data->Jbd;
   pivot = data->pivot;
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
   
   if (jok) {
     
-    /* jok = TRUE: Copy Jbd to P */
+    /* jok = SUNTRUE: Copy Jbd to P */
     
     for (jy=0; jy < MY; jy++)
       for (jx=0; jx < MX; jx++)
         denseCopy(Jbd[jx][jy], P[jx][jy], NUM_SPECIES, NUM_SPECIES);
     
-    *jcurPtr = FALSE;
+    *jcurPtr = SUNFALSE;
     
   }
   
   else {
-    /* jok = FALSE: Generate Jbd from scratch and copy to P */
+    /* jok = SUNFALSE: Generate Jbd from scratch and copy to P */
     
     /* Make local copies of problem variables, for efficiency. */
     
@@ -670,7 +675,7 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
       }
     }
     
-    *jcurPtr = TRUE;
+    *jcurPtr = SUNTRUE;
     
   }
   
@@ -698,10 +703,10 @@ static int Precond(realtype tn, N_Vector u, N_Vector fu,
 static int PSolve(realtype tn, N_Vector u, N_Vector fu,
                   N_Vector r, N_Vector z,
                   realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+                  int lr, void *user_data)
 {
   realtype **(*P)[MY];
-  long int *(*pivot)[MY];
+  sunindextype *(*pivot)[MY];
   int jx, jy;
   realtype *zdata, *v;
   UserData data;
@@ -711,7 +716,7 @@ static int PSolve(realtype tn, N_Vector u, N_Vector fu,
   data = (UserData) user_data;
   P = data->P;
   pivot = data->pivot;
-  zdata = N_VGetArrayPointer_Serial(z);
+  zdata = N_VGetArrayPointer(z);
   
   N_VScale(ONE, r, z);
   
diff --git a/examples/cvodes/serial/cvsKrylovDemo_ls.out b/examples/cvodes/serial/cvsKrylovDemo_ls.out
index 5e386da..002b671 100644
--- a/examples/cvodes/serial/cvsKrylovDemo_ls.out
+++ b/examples/cvodes/serial/cvsKrylovDemo_ls.out
@@ -16,58 +16,58 @@ t = 2.16e+04   no. steps = 277   order = 5   stepsize = 2.75e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 301   order = 5   stepsize = 3.87e+02
+t = 2.88e+04   no. steps = 307   order = 4   stepsize = 2.01e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 343   order = 3   stepsize = 2.34e+01
+t = 3.60e+04   no. steps = 336   order = 5   stepsize = 1.02e+02
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 421   order = 4   stepsize = 5.26e+02
-c1 (bot.left/middle/top rt.) =   -4.385e-06    -1.528e-06    -4.905e-06
+t = 4.32e+04   no. steps = 385   order = 4   stepsize = 4.57e+02
+c1 (bot.left/middle/top rt.) =    5.226e-08    -6.075e-06     8.713e-08
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 445   order = 3   stepsize = 1.98e+02
-c1 (bot.left/middle/top rt.) =    4.461e-07     1.869e-07     4.842e-07
+t = 5.04e+04   no. steps = 403   order = 4   stepsize = 2.77e+02
+c1 (bot.left/middle/top rt.) =   -2.670e-08    -4.510e-06    -2.672e-08
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 462   order = 5   stepsize = 2.35e+02
-c1 (bot.left/middle/top rt.) =    3.204e-09     1.203e-09     3.555e-09
+t = 5.76e+04   no. steps = 419   order = 5   stepsize = 3.44e+02
+c1 (bot.left/middle/top rt.) =   -1.147e-09    -5.871e-08    -2.195e-09
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 474   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -1.066e-09    -3.409e-10    -1.206e-09
+t = 6.48e+04   no. steps = 431   order = 5   stepsize = 9.50e+02
+c1 (bot.left/middle/top rt.) =    3.792e-10     1.901e-08     7.196e-10
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 486   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    2.614e-09     9.722e-10     2.904e-09
+t = 7.20e+04   no. steps = 441   order = 5   stepsize = 7.01e+02
+c1 (bot.left/middle/top rt.) =   -1.872e-11    -9.361e-10    -3.550e-11
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 498   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =    4.649e-11     1.729e-11     5.161e-11
+t = 7.92e+04   no. steps = 451   order = 5   stepsize = 7.01e+02
+c1 (bot.left/middle/top rt.) =    1.365e-13     6.739e-12     2.585e-13
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 510   order = 5   stepsize = 6.02e+02
-c1 (bot.left/middle/top rt.) =   -8.856e-14    -3.348e-14    -9.785e-14
+t = 8.64e+04   no. steps = 461   order = 5   stepsize = 7.01e+02
+c1 (bot.left/middle/top rt.) =    4.144e-14     2.072e-12     7.862e-14
 c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2096     leniw   =    62
-lenrwLS =  2046     leniwLS =    10
-nst     =   510
-nfe     =   675     nfeLS   =   641
-nni     =   671     nli     =   641
-nsetups =    94     netf    =    36
-npe     =     9     nps     =  1243
+lenrwLS =  2450     leniwLS =    22
+nst     =   461
+nfe     =   598     nfeLS   =   636
+nni     =   594     nli     =   636
+nsetups =    78     netf    =    27
+npe     =     8     nps     =  1176
 ncfn    =     0     ncfl    =     0
 
 ======================================================================
 
  ------- 
-| SPBCG |
+| SPBCGS |
  -------
  
 2-species diurnal advection-diffusion problem
@@ -93,43 +93,43 @@ c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
 t = 4.32e+04   no. steps = 369   order = 4   stepsize = 5.46e+02
-c1 (bot.left/middle/top rt.) =   -1.286e-09    -1.138e-09    -1.297e-09
+c1 (bot.left/middle/top rt.) =   -6.042e-10    -6.057e-10    -5.365e-10
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 385   order = 4   stepsize = 3.54e+02
-c1 (bot.left/middle/top rt.) =    3.396e-14     2.448e-11    -2.220e-14
+t = 5.04e+04   no. steps = 385   order = 4   stepsize = 3.19e+02
+c1 (bot.left/middle/top rt.) =   -1.354e-14     1.127e-12    -4.255e-14
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 399   order = 5   stepsize = 3.72e+02
-c1 (bot.left/middle/top rt.) =    1.607e-14    -1.589e-11     2.156e-13
+t = 5.76e+04   no. steps = 399   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =    3.722e-14     6.444e-12     2.768e-14
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 410   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =   -3.759e-13    -7.684e-12    -3.258e-13
+t = 6.48e+04   no. steps = 411   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -3.190e-14     3.974e-12    -1.259e-13
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 421   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =   -9.205e-14    -1.287e-11     2.328e-13
+t = 7.20e+04   no. steps = 423   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -4.212e-15    -1.602e-13     1.053e-15
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 433   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =   -3.952e-21     9.479e-19    -3.924e-20
+t = 7.92e+04   no. steps = 435   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -3.763e-23    -1.366e-21     1.010e-23
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 444   order = 5   stepsize = 6.46e+02
-c1 (bot.left/middle/top rt.) =    1.131e-26    -2.041e-22    -7.893e-29
+t = 8.64e+04   no. steps = 447   order = 5   stepsize = 5.96e+02
+c1 (bot.left/middle/top rt.) =   -9.994e-27    -1.865e-22    -1.580e-27
 c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2096     leniw   =    62
-lenrwLS =  1800     leniwLS =     9
-nst     =   444
-nfe     =   573     nfeLS   =   968
-nni     =   569     nli     =   484
-nsetups =    76     netf    =    27
-npe     =     8     nps     =  1457
+lenrwLS =  2204     leniwLS =    21
+nst     =   447
+nfe     =   570     nfeLS   =   964
+nni     =   566     nli     =   482
+nsetups =    72     netf    =    25
+npe     =     8     nps     =  1453
 ncfn    =     0     ncfl    =     0
 
 ======================================================================
@@ -148,55 +148,55 @@ t = 1.44e+04   no. steps = 250   order = 5   stepsize = 3.27e+02
 c1 (bot.left/middle/top rt.) =    6.659e+06     5.316e+06     7.301e+06
 c2 (bot.left/middle/top rt.) =    2.582e+11     2.057e+11     2.833e+11
 
-t = 2.16e+04   no. steps = 275   order = 5   stepsize = 3.49e+02
+t = 2.16e+04   no. steps = 275   order = 5   stepsize = 3.50e+02
 c1 (bot.left/middle/top rt.) =    2.665e+07     1.036e+07     2.931e+07
 c2 (bot.left/middle/top rt.) =    2.993e+11     1.028e+11     3.313e+11
 
-t = 2.88e+04   no. steps = 309   order = 4   stepsize = 1.92e+02
+t = 2.88e+04   no. steps = 298   order = 5   stepsize = 2.18e+02
 c1 (bot.left/middle/top rt.) =    8.702e+06     1.292e+07     9.650e+06
 c2 (bot.left/middle/top rt.) =    3.380e+11     5.029e+11     3.751e+11
 
-t = 3.60e+04   no. steps = 337   order = 5   stepsize = 1.24e+02
+t = 3.60e+04   no. steps = 326   order = 5   stepsize = 1.31e+02
 c1 (bot.left/middle/top rt.) =    1.404e+04     2.029e+04     1.561e+04
 c2 (bot.left/middle/top rt.) =    3.387e+11     4.894e+11     3.765e+11
 
-t = 4.32e+04   no. steps = 388   order = 4   stepsize = 5.10e+02
-c1 (bot.left/middle/top rt.) =    9.865e-08     1.252e-05     1.407e-07
+t = 4.32e+04   no. steps = 377   order = 4   stepsize = 3.89e+02
+c1 (bot.left/middle/top rt.) =    5.444e-07    -1.657e-06     6.244e-07
 c2 (bot.left/middle/top rt.) =    3.382e+11     1.355e+11     3.804e+11
 
-t = 5.04e+04   no. steps = 405   order = 4   stepsize = 2.84e+02
-c1 (bot.left/middle/top rt.) =   -1.668e-09     5.311e-07    -6.632e-09
+t = 5.04e+04   no. steps = 391   order = 5   stepsize = 6.79e+02
+c1 (bot.left/middle/top rt.) =   -1.730e-09    -6.249e-07    -9.039e-10
 c2 (bot.left/middle/top rt.) =    3.358e+11     4.930e+11     3.864e+11
 
-t = 5.76e+04   no. steps = 419   order = 5   stepsize = 5.07e+02
-c1 (bot.left/middle/top rt.) =   -1.792e-09     6.186e-07    -7.318e-09
+t = 5.76e+04   no. steps = 403   order = 5   stepsize = 4.21e+02
+c1 (bot.left/middle/top rt.) =    7.982e-10     2.122e-07    -1.172e-09
 c2 (bot.left/middle/top rt.) =    3.320e+11     9.650e+11     3.909e+11
 
-t = 6.48e+04   no. steps = 431   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =    1.682e-11    -9.299e-09     8.107e-11
+t = 6.48e+04   no. steps = 414   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =    1.420e-09     3.489e-07    -2.356e-09
 c2 (bot.left/middle/top rt.) =    3.313e+11     8.922e+11     3.963e+11
 
-t = 7.20e+04   no. steps = 441   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =    1.919e-15    -3.196e-13     6.625e-15
+t = 7.20e+04   no. steps = 424   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =    1.045e-12     2.583e-10    -1.763e-12
 c2 (bot.left/middle/top rt.) =    3.330e+11     6.186e+11     4.039e+11
 
-t = 7.92e+04   no. steps = 450   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =    2.380e-19    -4.543e-16     1.071e-18
+t = 7.92e+04   no. steps = 435   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =   -2.523e-19     5.442e-16     4.663e-19
 c2 (bot.left/middle/top rt.) =    3.334e+11     6.669e+11     4.120e+11
 
-t = 8.64e+04   no. steps = 459   order = 5   stepsize = 7.73e+02
-c1 (bot.left/middle/top rt.) =   -8.763e-21     5.632e-16    -4.431e-21
-c2 (bot.left/middle/top rt.) =    3.352e+11     9.107e+11     4.163e+11
+t = 8.64e+04   no. steps = 445   order = 5   stepsize = 6.89e+02
+c1 (bot.left/middle/top rt.) =   -1.673e-20    -1.128e-15    -3.081e-21
+c2 (bot.left/middle/top rt.) =    3.352e+11     9.106e+11     4.163e+11
 
 
 Final Statistics.. 
 
 lenrw   =  2096     leniw   =    62
-lenrwLS =  2200     leniwLS =    11
-nst     =   459
-nfe     =   582     nfeLS   =  1248
-nni     =   578     nli     =   520
-nsetups =    71     netf    =    23
-npe     =     8     nps     =  1910
+lenrwLS =  2604     leniwLS =    23
+nst     =   445
+nfe     =   559     nfeLS   =  1143
+nni     =   555     nli     =   477
+nsetups =    67     netf    =    21
+npe     =     8     nps     =  1805
 ncfn    =     0     ncfl    =     0
 
diff --git a/examples/cvodes/serial/cvsKrylovDemo_prec.c b/examples/cvodes/serial/cvsKrylovDemo_prec.c
index a640118..d7d75de 100644
--- a/examples/cvodes/serial/cvsKrylovDemo_prec.c
+++ b/examples/cvodes/serial/cvsKrylovDemo_prec.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4868 $
- * $Date: 2016-08-19 10:16:31 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
+/* --------------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * --------------------------------------------------------------------
@@ -49,7 +45,7 @@
  *
  * The resulting ODE system is stiff.
  *
- * The ODE system is solved using Newton iteration and the CVSPGMR
+ * The ODE system is solved using Newton iteration and the SUNSPGMR
  * linear solver (scaled preconditioned GMRES).
  *
  * The preconditioner matrix used is the product of two matrices:
@@ -63,9 +59,10 @@
  * The product preconditoner is applied on the left and on the
  * right. In each case, both the modified and classical Gram-Schmidt
  * options are tested.
- * In the series of runs, CVodeInit and CVSpgmr are called only
- * for the first run, whereas CVodeReInit and CVReInitSpgmr are
- * called for each of the remaining three runs.
+ * In the series of runs, CVodeInit, SUNSPGMR, and 
+ * CVDlsSetLinearSolver are called only for the first run, whereas 
+ * CVodeReInit, SUNSPGMRSetPrecType, and SUNSPGMRSetGSType are called
+ * for each of the remaining three runs.
  *
  * A problem description, performance statistics at selected output
  * times, and final statistics are written to standard output.
@@ -74,30 +71,30 @@
  * but there should be no such messages.
  *
  * Note: This program requires the dense linear solver functions
- * newDenseMat, newLintArray, denseAddIdentity, denseGETRF, denseGETRS, 
+ * newDenseMat, newIndexArray, denseAddIdentity, denseGETRF, denseGETRS, 
  * destroyMat and destroyArray.
  *
  * Note: This program assumes the sequential implementation for the
- * type N_Vector and uses the N_VGetArrayPointer_Serial function to 
- * gain access to the contiguous array of components of an N_Vector.
+ * type N_Vector and uses the N_VGetArrayPointer function to gain
+ * access to the contiguous array of components of an N_Vector.
  * --------------------------------------------------------------------
  * Reference: Peter N. Brown and Alan C. Hindmarsh, Reduced Storage
  * Matrix Methods in Stiff ODE Systems, J. Appl. Math. & Comp., 31
  * (1989), pp. 40-91.  Also available as Lawrence Livermore National
  * Laboratory Report UCRL-95088, Rev. 1, June 1987.
- * --------------------------------------------------------------------
- */
+ * --------------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <cvodes/cvodes.h>           /* main integrator header file */
-#include <cvodes/cvodes_spgmr.h>     /* prototypes & constants for CVSPGMR solver */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fct. and macros */
-#include <sundials/sundials_dense.h> /* use generic DENSE solver in preconditioning */
-#include <sundials/sundials_types.h> /* definition of realtype */
-#include <sundials/sundials_math.h>  /* contains the macros ABS and SUNSQR */
+#include <cvodes/cvodes.h>                /* main integrator header file                 */
+#include <sunlinsol/sunlinsol_spgmr.h>  /* access to SPGMR SUNLinearSolver             */
+#include <cvodes/cvodes_spils.h>          /* access to CVSpils interface                 */
+#include <nvector/nvector_serial.h>     /* serial N_Vector types, fct. and macros      */
+#include <sundials/sundials_dense.h>    /* use generic DENSE solver in preconditioning */
+#include <sundials/sundials_types.h>    /* definition of realtype                      */
+#include <sundials/sundials_math.h>     /* contains the macros ABS and SUNSQR          */
 
 /* Constants */
 
@@ -140,7 +137,7 @@
 #define RTOL RCONST(1.0e-5)
 #define ATOL RCONST(1.0e-5)
 
-/* CVSpgmr Constants */
+/* Spgmr/SPILS Constants */
 
 #define MAXL 0     /* => use default = MIN(NEQ, 5)            */
 #define DELT ZERO  /* => use default = 0.05                   */
@@ -160,7 +157,7 @@
 
 typedef struct {
   realtype **P[NGRP];
-  long int *pivot[NGRP];
+  sunindextype *pivot[NGRP];
   int ns, mxns;
   int mp, mq, mx, my, ngrp, ngx, ngy, mxmp;
   int jgx[NGX+1], jgy[NGY+1], jigx[MX], jigy[MY];
@@ -168,6 +165,7 @@ typedef struct {
   realtype acoef[NS][NS], bcoef[NS], diff[NS];
   realtype cox[NS], coy[NS], dx, dy, srur;
   realtype fsave[NEQ];
+  N_Vector tmp;
   N_Vector rewt;
   void *cvode_mem;
 } *WebData;
@@ -188,7 +186,7 @@ static void WebRates(realtype x, realtype y, realtype t, realtype c[],
 		     realtype rate[], WebData wdata);
 static void fblock (realtype t, realtype cdata[], int jx, int jy,
 		    realtype cdotdata[], WebData wdata);
-static void GSIter(realtype gamma, N_Vector z, N_Vector x,WebData wdata);
+static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata);
 
 /* Small Vector Kernels */
 
@@ -202,15 +200,11 @@ static void v_zero(realtype u[], int n);
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
-static int Precond(realtype tn, N_Vector c, N_Vector fc,
-		   booleantype jok, booleantype *jcurPtr, realtype gamma,
-		   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3);
+static int Precond(realtype tn, N_Vector c, N_Vector fc, booleantype jok, 
+                   booleantype *jcurPtr, realtype gamma, void *user_data);
 
-static int PSolve(realtype tn, N_Vector c, N_Vector fc,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp);
+static int PSolve(realtype tn, N_Vector c, N_Vector fc, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data);
 
 /* Private function to check function return values */
 
@@ -223,6 +217,7 @@ int main()
   realtype abstol=ATOL, reltol=RTOL, t, tout;
   N_Vector c;
   WebData wdata;
+  SUNLinearSolver LS;
   void *cvode_mem;
   booleantype firstrun;
   int jpre, gstype, flag;
@@ -230,6 +225,7 @@ int main()
 
   c = NULL;
   wdata = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Initializations */
@@ -252,7 +248,7 @@ int main()
       CInit(c, wdata);
       PrintHeader(jpre, gstype);
 
-      /* Call CVodeInit or CVodeReInit, then CVSpgmr to set up problem */
+      /* Call CVodeInit or CVodeReInit, then SUNSPGMR to set up problem */
       
       firstrun = (jpre == PREC_LEFT) && (gstype == MODIFIED_GS);
       if (firstrun) {
@@ -268,13 +264,16 @@ int main()
         if(check_flag(&flag, "CVodeInit", 1)) return(1);
 
         flag = CVodeSStolerances(cvode_mem, reltol, abstol);
-        if (check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+        if(check_flag(&flag, "CVodeSStolerances", 1)) return(1);
+
+        LS = SUNSPGMR(c, jpre, MAXL);
+        if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
 
-        flag = CVSpgmr(cvode_mem, jpre, MAXL);
-        if(check_flag(&flag, "CVSpgmr", 1)) return(1);
+        flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+        if(check_flag(&flag, "CVSpilsSetLinearSolver", 1)) return 1;
 
-        flag = CVSpilsSetGSType(cvode_mem, gstype);
-        if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+        flag = SUNSPGMRSetGSType(LS, gstype);
+        if(check_flag(&flag, "SUNSPGMRSetGSType", 1)) return(1);
 
         flag = CVSpilsSetEpsLin(cvode_mem, DELT);
         if(check_flag(&flag, "CVSpilsSetEpsLin", 1)) return(1);
@@ -287,10 +286,10 @@ int main()
         flag = CVodeReInit(cvode_mem, T0, c);
         if(check_flag(&flag, "CVodeReInit", 1)) return(1);
 
-        flag = CVSpilsSetPrecType(cvode_mem, jpre);
-        check_flag(&flag, "CVSpilsSetPrecType", 1);
-        flag = CVSpilsSetGSType(cvode_mem, gstype);
-        if(check_flag(&flag, "CVSpilsSetGSType", 1)) return(1);
+        flag = SUNSPGMRSetPrecType(LS, jpre);
+        check_flag(&flag, "SUNSPGMRSetPrecType", 1);
+        flag = SUNSPGMRSetGSType(LS, gstype);
+        if(check_flag(&flag, "SUNSPGMRSetGSType", 1)) return(1);
 
       }
       
@@ -315,7 +314,8 @@ int main()
 
   /* Free all memory */
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(c);
+  N_VDestroy(c);
+  SUNLinSolFree(LS);
   FreeUserData(wdata);
 
   return(0);
@@ -324,15 +324,16 @@ int main()
 static WebData AllocUserData(void)
 {
   int i, ngrp = NGRP;
-  long int ns = NS;
+  sunindextype ns = NS;
   WebData wdata;
   
   wdata = (WebData) malloc(sizeof *wdata);
   for(i=0; i < ngrp; i++) {
     (wdata->P)[i] = newDenseMat(ns, ns);
-    (wdata->pivot)[i] = newLintArray(ns);
+    (wdata->pivot)[i] = newIndexArray(ns);
   }
   wdata->rewt = N_VNew_Serial(NEQ);
+  wdata->tmp = N_VNew_Serial(NEQ);
   return(wdata);
 }
 
@@ -422,7 +423,7 @@ static void CInit(N_Vector c, WebData wdata)
   int jx, jy, ns, mxns, ioff, iyoff, i, ici;
   realtype argx, argy, x, y, dx, dy, x_factor, y_factor, *cdata;
   
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
   ns = wdata->ns;
   mxns = wdata->mxns;
   dx = wdata->dx;
@@ -448,7 +449,7 @@ static void CInit(N_Vector c, WebData wdata)
 
 static void PrintIntro(void)
 {
-  printf("\n\nDemonstration program for CVODES - CVSPGMR linear solver\n\n");
+  printf("\n\nDemonstration program for CVODES - SPGMR linear solver\n\n");
   printf("Food web problem with ns species, ns = %d\n", NS);
   printf("Predator-prey interaction and diffusion on a 2-D square\n\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -514,7 +515,7 @@ static void PrintAllSpecies(N_Vector c, int ns, int mxns, realtype t)
   int i, jx ,jy;
   realtype *cdata;
   
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("c values at t = %Lg:\n\n", t);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
@@ -609,8 +610,8 @@ static void PrintFinalStats(void *cvode_mem)
   printf("\n\n Final statistics for this run:\n\n");
   printf(" CVode real workspace length           = %4ld \n", lenrw);
   printf(" CVode integer workspace length        = %4ld \n", leniw);
-  printf(" CVSPGMR real workspace length         = %4ld \n", lenrwLS);
-  printf(" CVSPGMR integer workspace length      = %4ld \n", leniwLS);
+  printf(" CVSPILS real workspace length         = %4ld \n", lenrwLS);
+  printf(" CVSPILS integer workspace length      = %4ld \n", leniwLS);
   printf(" Number of steps                       = %4ld \n", nst);
   printf(" Number of f-s                         = %4ld \n", nfe);
   printf(" Number of f-s (SPGMR)                 = %4ld \n", nfeLS);
@@ -644,7 +645,8 @@ static void FreeUserData(WebData wdata)
     destroyMat((wdata->P)[i]);
     destroyArray((wdata->pivot)[i]);
   }
-  N_VDestroy_Serial(wdata->rewt);
+  N_VDestroy(wdata->rewt);
+  N_VDestroy(wdata->tmp);
   free(wdata);
 }
 
@@ -661,8 +663,8 @@ static int f(realtype t, N_Vector c, N_Vector cdot,void *user_data)
   WebData wdata;
   
   wdata = (WebData) user_data;
-  cdata = N_VGetArrayPointer_Serial(c);
-  cdotdata = N_VGetArrayPointer_Serial(cdot);
+  cdata = N_VGetArrayPointer(c);
+  cdotdata = N_VGetArrayPointer(cdot);
   
   mxns = wdata->mxns;
   ns = wdata->ns;
@@ -744,16 +746,15 @@ static void WebRates(realtype x, realtype y, realtype t, realtype c[],
  of a block-diagonal preconditioner. The blocks are of size mp, and
  there are ngrp=ngx*ngy blocks computed in the block-grouping scheme.
 */ 
-static int Precond(realtype t, N_Vector c, N_Vector fc,
-		   booleantype jok, booleantype *jcurPtr, realtype gamma,
-		   void *user_data, N_Vector vtemp1, N_Vector vtemp2,
-                   N_Vector vtemp3)
+static int Precond(realtype t, N_Vector c, N_Vector fc, booleantype jok,
+                   booleantype *jcurPtr, realtype gamma, void *user_data)
 {
   realtype ***P;
-  long int **pivot, ier;
+  int ier;
+  sunindextype **pivot;
   int i, if0, if00, ig, igx, igy, j, jj, jx, jy;
   int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag;
-  long int mp;
+  sunindextype mp;
   realtype uround, fac, r, r0, save, srur;
   realtype *f1, *fsave, *cdata, *rewtdata;
   WebData wdata;
@@ -762,11 +763,11 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
   
   wdata = (WebData) user_data;
   cvode_mem = wdata->cvode_mem;
-  cdata = N_VGetArrayPointer_Serial(c);
+  cdata = N_VGetArrayPointer(c);
   rewt = wdata->rewt;
   flag = CVodeGetErrWeights(cvode_mem, rewt);
   if(check_flag(&flag, "CVodeGetErrWeights", 1)) return(1);
-  rewtdata = N_VGetArrayPointer_Serial(rewt);
+  rewtdata = N_VGetArrayPointer(rewt);
 
   uround = UNIT_ROUNDOFF;
 
@@ -786,7 +787,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
      Here, fsave contains the base value of the rate vector and 
      r0 is a minimum increment factor for the difference quotient. */
   
-  f1 = N_VGetArrayPointer_Serial(vtemp1);
+  f1 = N_VGetArrayPointer(wdata->tmp);
   
   fac = N_VWrmsNorm (fc, rewt);
   r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*NEQ*fac;
@@ -824,7 +825,7 @@ static int Precond(realtype t, N_Vector c, N_Vector fc,
     if (ier != 0) return(1);
   }
   
-  *jcurPtr = TRUE;
+  *jcurPtr = SUNTRUE;
   return(0);
 }
 
@@ -856,15 +857,13 @@ static void fblock(realtype t, realtype cdata[], int jx, int jy,
   Then it computes ((I - gamma*Jr)-inverse)*z, using LU factors of the
   blocks in P, and pivot information in pivot, and returns the result in z.
 */
-static int PSolve(realtype tn, N_Vector c, N_Vector fc,
-                  N_Vector r, N_Vector z,
-                  realtype gamma, realtype delta,
-                  int lr, void *user_data, N_Vector vtemp)
+static int PSolve(realtype tn, N_Vector c, N_Vector fc, N_Vector r, N_Vector z,
+                  realtype gamma, realtype delta, int lr, void *user_data)
 {
   realtype   ***P;
-  long int **pivot;
+  sunindextype **pivot;
   int jx, jy, igx, igy, iv, ig, *jigx, *jigy, mx, my, ngx;
-  long int mp;
+  sunindextype mp;
   WebData wdata;
   
   wdata = (WebData) user_data;
@@ -873,7 +872,7 @@ static int PSolve(realtype tn, N_Vector c, N_Vector fc,
   
   /* call GSIter for Gauss-Seidel iterations */
   
-  GSIter(gamma, z, vtemp, wdata);
+  GSIter(gamma, z, wdata->tmp, wdata);
   
   /* Do backsolves for inverse of block-diagonal preconditioner factor */
   
@@ -892,7 +891,7 @@ static int PSolve(realtype tn, N_Vector c, N_Vector fc,
     for (jx = 0; jx < mx; jx++) {
       igx = jigx[jx];
       ig = igx + igy*ngx;
-      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer_Serial(z)[iv]));
+      denseGETRS(P[ig], mp, pivot[ig], &(N_VGetArrayPointer(z)[iv]));
       iv += mp;
     }
   }
@@ -916,8 +915,8 @@ static void GSIter(realtype gamma, N_Vector z, N_Vector x, WebData wdata)
   realtype beta[NS], beta2[NS], cof1[NS], gam[NS], gam2[NS];
   realtype temp, *cox, *coy, *xd, *zd;
   
-  xd = N_VGetArrayPointer_Serial(x);
-  zd = N_VGetArrayPointer_Serial(z);
+  xd = N_VGetArrayPointer(x);
+  zd = N_VGetArrayPointer(z);
   ns = wdata->ns;
   mx = wdata->mx;
   my = wdata->my;
diff --git a/examples/cvodes/serial/cvsKrylovDemo_prec.out b/examples/cvodes/serial/cvsKrylovDemo_prec.out
index eee5b2b..5e24468 100644
--- a/examples/cvodes/serial/cvsKrylovDemo_prec.out
+++ b/examples/cvodes/serial/cvsKrylovDemo_prec.out
@@ -1,6 +1,6 @@
 
 
-Demonstration program for CVODES - CVSPGMR linear solver
+Demonstration program for CVODES - SPGMR linear solver
 
 Food web problem with ns species, ns = 6
 Predator-prey interaction and diffusion on a 2-D square
@@ -246,7 +246,7 @@ Species 6
 46877.1   47001.6   47286.6   47627.5   47914.5   48040.8   
 46782.3   46877.1   47109     47390.2   47623.3   47718.9   
 
-t =   2.00e+00  nst = 272  nfe = 305  nni = 301  qu = 3  hu =    3.80e-02
+t =   2.00e+00  nst = 272  nfe = 305  nni = 301  qu = 3  hu =    3.81e-02
 
 t =   3.00e+00  nst = 288  nfe = 322  nni = 318  qu = 3  hu =    6.59e-02
 
@@ -336,9 +336,9 @@ Species 3
 
 Species 4
 35655.3   35903.5   36423.2   37034.1   37564.5   37822.3   
-35579.2   35804.3   36281.8   36844.9   37331.4   37564.5   
+35579.2   35804.3   36281.9   36844.9   37331.4   37564.5   
 35393.1   35577     35973.5   36442.2   36844.9   37034.1   
-35168.3   35306.6   35611.4   35973.5   36281.8   36423.2   
+35168.3   35306.6   35611.4   35973.5   36281.9   36423.2   
 34983.2   35081.1   35306.6   35577     35804.3   35903.5   
 34907.9   34983.2   35168.3   35393.1   35579.2   35655.3   
 
@@ -391,28 +391,28 @@ Species 3
 1.16347   1.16598   1.17215   1.17964   1.18585   1.18838   
 
 Species 4
-35650.5   35898.8   36418.4   37029.3   37559.4   37817.4   
+35650.6   35898.8   36418.3   37029.3   37559.4   37817.3   
 35574.5   35799.5   36277.1   36840     37326.6   37559.4   
 35388.5   35572.3   35968.7   36437.4   36840     37029.3   
-35163.7   35302     35606.7   35968.7   36277.1   36418.4   
-34978.5   35076.5   35302     35572.3   35799.5   35898.8   
-34903.3   34978.5   35163.7   35388.5   35574.5   35650.5   
+35163.7   35302     35606.7   35968.7   36277.1   36418.3   
+34978.7   35076.5   35302     35572.3   35799.5   35898.8   
+34903.2   34978.7   35163.7   35388.5   35574.5   35650.6   
 
 Species 5
-35650.5   35898.8   36418.4   37029.3   37559.4   37817.4   
+35650.5   35898.8   36418.3   37029.3   37559.4   37817.4   
 35574.5   35799.5   36277.1   36840     37326.6   37559.4   
 35388.5   35572.3   35968.7   36437.4   36840     37029.3   
-35163.7   35302     35606.7   35968.7   36277.1   36418.4   
-34978.5   35076.5   35302     35572.3   35799.5   35898.8   
-34903.3   34978.5   35163.7   35388.5   35574.5   35650.5   
+35163.7   35302     35606.7   35968.7   36277.1   36418.3   
+34978.7   35076.5   35302     35572.3   35799.5   35898.8   
+34903.2   34978.7   35163.7   35388.5   35574.5   35650.5   
 
 Species 6
-35650.5   35898.8   36418.4   37029.3   37559.4   37817.4   
+35650.5   35898.8   36418.3   37029.3   37559.4   37817.4   
 35574.5   35799.5   36277.1   36840     37326.6   37559.4   
-35388.5   35572.3   35968.7   36437.4   36840     37029.3   
-35163.7   35302     35606.7   35968.7   36277.1   36418.4   
-34978.5   35076.5   35302     35572.3   35799.5   35898.8   
-34903.3   34978.5   35163.7   35388.5   35574.5   35650.5   
+35388.4   35572.3   35968.7   36437.4   36840     37029.3   
+35163.7   35302     35606.7   35968.7   36277.1   36418.3   
+34978.6   35076.5   35302     35572.3   35799.5   35898.8   
+34903.2   34978.6   35163.7   35388.4   35574.5   35650.5   
 
 
 
@@ -420,21 +420,21 @@ Species 6
 
  CVode real workspace length           = 2256 
  CVode integer workspace length        =   62 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
  Number of steps                       =  353 
  Number of f-s                         =  391 
- Number of f-s (SPGMR)                 =  585 
- Number of f-s (TOTAL)                 =  976 
+ Number of f-s (SPGMR)                 =  586 
+ Number of f-s (TOTAL)                 =  977 
  Number of setups                      =   43 
  Number of nonlinear iterations        =  387 
- Number of linear iterations           =  585 
+ Number of linear iterations           =  586 
  Number of preconditioner evaluations  =   43 
- Number of preconditioner solves       =  956 
+ Number of preconditioner solves       =  957 
  Number of error test failures         =    1 
  Number of nonlinear conv. failures    =    0 
  Number of linear convergence failures =    0 
- Average Krylov subspace dimension     = 1.512 
+ Average Krylov subspace dimension     = 1.514 
 
 
 ----------------------------------------------------------------------------
@@ -470,17 +470,17 @@ t =   3.00e+00  nst = 288  nfe = 322  nni = 318  qu = 3  hu =    6.58e-02
 
 t =   4.00e+00  nst = 303  nfe = 338  nni = 334  qu = 3  hu =    6.58e-02
 
-t =   5.00e+00  nst = 316  nfe = 352  nni = 348  qu = 2  hu =    1.06e-01
+t =   5.00e+00  nst = 316  nfe = 352  nni = 348  qu = 2  hu =    1.02e-01
 
-t =   6.00e+00  nst = 323  nfe = 359  nni = 355  qu = 3  hu =    1.94e-01
+t =   6.00e+00  nst = 324  nfe = 361  nni = 357  qu = 2  hu =    1.65e-01
 
-t =   7.00e+00  nst = 326  nfe = 364  nni = 360  qu = 3  hu =    4.05e-01
+t =   7.00e+00  nst = 330  nfe = 368  nni = 364  qu = 2  hu =    2.63e-01
 
-t =   8.00e+00  nst = 328  nfe = 366  nni = 362  qu = 3  hu =    4.05e-01
+t =   8.00e+00  nst = 334  nfe = 372  nni = 368  qu = 2  hu =    2.63e-01
 
-t =   9.00e+00  nst = 331  nfe = 369  nni = 365  qu = 3  hu =    4.05e-01
+t =   9.00e+00  nst = 338  nfe = 377  nni = 373  qu = 2  hu =    7.46e-01
 
-t =   1.00e+01  nst = 333  nfe = 371  nni = 367  qu = 3  hu =    4.05e-01
+t =   1.00e+01  nst = 339  nfe = 378  nni = 374  qu = 2  hu =    7.46e-01
 
 
 
@@ -488,21 +488,21 @@ t =   1.00e+01  nst = 333  nfe = 371  nni = 367  qu = 3  hu =    4.05e-01
 
  CVode real workspace length           = 2256 
  CVode integer workspace length        =   62 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
- Number of steps                       =  333 
- Number of f-s                         =  371 
- Number of f-s (SPGMR)                 =  534 
- Number of f-s (TOTAL)                 =  905 
- Number of setups                      =   44 
- Number of nonlinear iterations        =  367 
- Number of linear iterations           =  534 
- Number of preconditioner evaluations  =   44 
- Number of preconditioner solves       =  885 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
+ Number of steps                       =  339 
+ Number of f-s                         =  378 
+ Number of f-s (SPGMR)                 =  533 
+ Number of f-s (TOTAL)                 =  911 
+ Number of setups                      =   45 
+ Number of nonlinear iterations        =  374 
+ Number of linear iterations           =  533 
+ Number of preconditioner evaluations  =   45 
+ Number of preconditioner solves       =  891 
  Number of error test failures         =    1 
  Number of nonlinear conv. failures    =    0 
- Number of linear convergence failures =    4 
- Average Krylov subspace dimension     = 1.455 
+ Number of linear convergence failures =    0 
+ Average Krylov subspace dimension     = 1.425 
 
 
 ----------------------------------------------------------------------------
@@ -528,27 +528,27 @@ t =   1.00e-03  nst = 138  nfe = 163  nni = 159  qu = 2  hu =    4.17e-04
 
 t =   1.00e-02  nst = 146  nfe = 174  nni = 170  qu = 3  hu =    1.64e-03
 
-t =   1.00e-01  nst = 169  nfe = 200  nni = 196  qu = 5  hu =    9.35e-03
+t =   1.00e-01  nst = 169  nfe = 200  nni = 196  qu = 5  hu =    9.36e-03
 
 t =   1.00e+00  nst = 207  nfe = 247  nni = 243  qu = 5  hu =    5.17e-02
 
-t =   2.00e+00  nst = 218  nfe = 262  nni = 258  qu = 5  hu =    1.36e-01
+t =   2.00e+00  nst = 219  nfe = 263  nni = 259  qu = 5  hu =    1.21e-01
 
-t =   3.00e+00  nst = 226  nfe = 270  nni = 266  qu = 5  hu =    1.36e-01
+t =   3.00e+00  nst = 227  nfe = 271  nni = 267  qu = 5  hu =    1.21e-01
 
-t =   4.00e+00  nst = 233  nfe = 277  nni = 273  qu = 5  hu =    1.36e-01
+t =   4.00e+00  nst = 233  nfe = 278  nni = 274  qu = 5  hu =    1.83e-01
 
-t =   5.00e+00  nst = 241  nfe = 285  nni = 281  qu = 5  hu =    1.36e-01
+t =   5.00e+00  nst = 238  nfe = 283  nni = 279  qu = 5  hu =    1.83e-01
 
-t =   6.00e+00  nst = 248  nfe = 292  nni = 288  qu = 5  hu =    1.36e-01
+t =   6.00e+00  nst = 244  nfe = 289  nni = 285  qu = 5  hu =    1.83e-01
 
-t =   7.00e+00  nst = 255  nfe = 299  nni = 295  qu = 5  hu =    1.36e-01
+t =   7.00e+00  nst = 249  nfe = 295  nni = 291  qu = 5  hu =    1.83e-01
 
-t =   8.00e+00  nst = 260  nfe = 305  nni = 301  qu = 5  hu =    2.06e-01
+t =   8.00e+00  nst = 255  nfe = 301  nni = 297  qu = 5  hu =    1.83e-01
 
-t =   9.00e+00  nst = 270  nfe = 319  nni = 315  qu = 5  hu =    5.14e-02
+t =   9.00e+00  nst = 260  nfe = 307  nni = 303  qu = 5  hu =    1.83e-01
 
-t =   1.00e+01  nst = 278  nfe = 328  nni = 324  qu = 3  hu =    3.01e-01
+t =   1.00e+01  nst = 266  nfe = 313  nni = 309  qu = 5  hu =    1.83e-01
 
 
 
@@ -556,21 +556,21 @@ t =   1.00e+01  nst = 278  nfe = 328  nni = 324  qu = 3  hu =    3.01e-01
 
  CVode real workspace length           = 2256 
  CVode integer workspace length        =   62 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
- Number of steps                       =  278 
- Number of f-s                         =  328 
- Number of f-s (SPGMR)                 =  666 
- Number of f-s (TOTAL)                 =  994 
- Number of setups                      =   46 
- Number of nonlinear iterations        =  324 
- Number of linear iterations           =  666 
- Number of preconditioner evaluations  =   46 
- Number of preconditioner solves       =  954 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
+ Number of steps                       =  266 
+ Number of f-s                         =  313 
+ Number of f-s (SPGMR)                 =  600 
+ Number of f-s (TOTAL)                 =  913 
+ Number of setups                      =   41 
+ Number of nonlinear iterations        =  309 
+ Number of linear iterations           =  600 
+ Number of preconditioner evaluations  =   41 
+ Number of preconditioner solves       =  873 
  Number of error test failures         =    3 
- Number of nonlinear conv. failures    =    1 
- Number of linear convergence failures =   55 
- Average Krylov subspace dimension     = 2.056 
+ Number of nonlinear conv. failures    =    0 
+ Number of linear convergence failures =   42 
+ Average Krylov subspace dimension     = 1.942 
 
 
 ----------------------------------------------------------------------------
@@ -600,23 +600,23 @@ t =   1.00e-01  nst = 169  nfe = 200  nni = 196  qu = 5  hu =    9.35e-03
 
 t =   1.00e+00  nst = 207  nfe = 247  nni = 243  qu = 5  hu =    5.18e-02
 
-t =   2.00e+00  nst = 219  nfe = 263  nni = 259  qu = 5  hu =    1.21e-01
+t =   2.00e+00  nst = 219  nfe = 263  nni = 259  qu = 5  hu =    1.22e-01
 
-t =   3.00e+00  nst = 227  nfe = 271  nni = 267  qu = 5  hu =    1.21e-01
+t =   3.00e+00  nst = 227  nfe = 271  nni = 267  qu = 5  hu =    1.22e-01
 
-t =   4.00e+00  nst = 233  nfe = 278  nni = 274  qu = 5  hu =    1.85e-01
+t =   4.00e+00  nst = 233  nfe = 277  nni = 273  qu = 4  hu =    1.83e-01
 
-t =   5.00e+00  nst = 238  nfe = 283  nni = 279  qu = 5  hu =    1.85e-01
+t =   5.00e+00  nst = 238  nfe = 283  nni = 279  qu = 4  hu =    2.94e-01
 
-t =   6.00e+00  nst = 248  nfe = 298  nni = 294  qu = 5  hu =    7.06e-02
+t =   6.00e+00  nst = 242  nfe = 287  nni = 283  qu = 4  hu =    2.94e-01
 
-t =   7.00e+00  nst = 255  nfe = 305  nni = 301  qu = 4  hu =    2.07e-01
+t =   7.00e+00  nst = 246  nfe = 293  nni = 289  qu = 4  hu =    1.11e-01
 
-t =   8.00e+00  nst = 258  nfe = 308  nni = 304  qu = 3  hu =    3.42e-01
+t =   8.00e+00  nst = 251  nfe = 298  nni = 294  qu = 3  hu =    3.43e-01
 
-t =   9.00e+00  nst = 261  nfe = 311  nni = 307  qu = 3  hu =    3.42e-01
+t =   9.00e+00  nst = 254  nfe = 301  nni = 297  qu = 2  hu =    5.23e-01
 
-t =   1.00e+01  nst = 263  nfe = 313  nni = 309  qu = 3  hu =    5.33e-01
+t =   1.00e+01  nst = 256  nfe = 305  nni = 301  qu = 2  hu =    2.03e-01
 
 
 
@@ -624,21 +624,21 @@ t =   1.00e+01  nst = 263  nfe = 313  nni = 309  qu = 3  hu =    5.33e-01
 
  CVode real workspace length           = 2256 
  CVode integer workspace length        =   62 
- CVSPGMR real workspace length         = 2206 
- CVSPGMR integer workspace length      =   10 
- Number of steps                       =  263 
- Number of f-s                         =  313 
- Number of f-s (SPGMR)                 =  594 
- Number of f-s (TOTAL)                 =  907 
- Number of setups                      =   47 
- Number of nonlinear iterations        =  309 
- Number of linear iterations           =  594 
- Number of preconditioner evaluations  =   47 
- Number of preconditioner solves       =  867 
+ CVSPILS real workspace length         = 2642 
+ CVSPILS integer workspace length      =   22 
+ Number of steps                       =  256 
+ Number of f-s                         =  305 
+ Number of f-s (SPGMR)                 =  563 
+ Number of f-s (TOTAL)                 =  868 
+ Number of setups                      =   48 
+ Number of nonlinear iterations        =  301 
+ Number of linear iterations           =  563 
+ Number of preconditioner evaluations  =   48 
+ Number of preconditioner solves       =  828 
  Number of error test failures         =    3 
- Number of nonlinear conv. failures    =    1 
- Number of linear convergence failures =   42 
- Average Krylov subspace dimension     = 1.922 
+ Number of nonlinear conv. failures    =    2 
+ Number of linear convergence failures =   36 
+ Average Krylov subspace dimension     = 1.870 
 
 
 ----------------------------------------------------------------------------
diff --git a/examples/cvodes/serial/cvsRoberts_ASAi_dns.c b/examples/cvodes/serial/cvsRoberts_ASAi_dns.c
index 79a1896..d65bd0f 100644
--- a/examples/cvodes/serial/cvsRoberts_ASAi_dns.c
+++ b/examples/cvodes/serial/cvsRoberts_ASAi_dns.c
@@ -1,14 +1,10 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -54,22 +50,23 @@
  * where
  *   d(phi)/dt = g(t,y,p)
  *   phi(t1) = 0
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <cvodes/cvodes.h>
-#include <cvodes/cvodes_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <cvodes/cvodes.h>             /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <cvodes/cvodes_direct.h>      /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component, i=1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* (i,j)-th matrix el., i,j=1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* i-th vector component, i=1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* (i,j)-th matrix el., i,j=1..NEQ */
 
 /* Problem Constants */
 
@@ -107,19 +104,15 @@ typedef struct {
 /* Prototypes of user-supplied functions */
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data);
 static int ewt(N_Vector y, N_Vector w, void *user_data);
 
 static int fB(realtype t, N_Vector y, 
               N_Vector yB, N_Vector yBdot, void *user_dataB);
-static int JacB(long int NB, realtype t,
-                N_Vector y, N_Vector yB, N_Vector fyB,
-                DlsMat JB, void *user_dataB,
-                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+static int JacB(realtype t, N_Vector y, N_Vector yB, N_Vector fyB, SUNMatrix JB,
+                void *user_dataB, N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
 static int fQB(realtype t, N_Vector y, N_Vector yB, 
                N_Vector qBdot, void *user_dataB);
 
@@ -141,6 +134,8 @@ int main(int argc, char *argv[])
 {
   UserData data;
 
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
   void *cvode_mem;
 
   realtype reltolQ, abstolQ;
@@ -161,6 +156,8 @@ int main(int argc, char *argv[])
   CVadjCheckPointRec *ckpnt;
 
   data = NULL;
+  A = AB = NULL;
+  LS = LSB = NULL;
   cvode_mem = NULL;
   ckpnt = NULL;
   y = yB = qB = NULL;
@@ -201,36 +198,64 @@ int main(int argc, char *argv[])
   /* Create and allocate CVODES memory for forward run */
   printf("Create and allocate CVODES memory for forward runs\n");
 
+  /* Call CVodeCreate to create the solver memory and specify the 
+     Backward Differentiation Formula and the use of a Newton iteration */
   cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
   if (check_flag((void *)cvode_mem, "CVodeCreate", 0)) return(1);
 
+  /* Call CVodeInit to initialize the integrator memory and specify the
+     user's right hand side function in y'=f(t,y), the initial time T0, and
+     the initial dependent variable vector y. */
   flag = CVodeInit(cvode_mem, f, T0, y);
   if (check_flag(&flag, "CVodeInit", 1)) return(1);
 
+  /* Call CVodeWFtolerances to specify a user-supplied function ewt that sets
+     the multiplicative error weights w_i for use in the weighted RMS norm */
   flag = CVodeWFtolerances(cvode_mem, ewt);
   if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1);
 
+  /* Attach user data */
   flag = CVodeSetUserData(cvode_mem, data);
   if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  flag = CVDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVDense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
 
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
 
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if (check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if (check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
+
+  /* Call CVodeQuadInit to allocate initernal memory and initialize
+     quadrature integration*/
   flag = CVodeQuadInit(cvode_mem, fQ, q);
   if (check_flag(&flag, "CVodeQuadInit", 1)) return(1);
 
+  /* Call CVodeSetQuadErrCon to specify whether or not the quadrature variables
+     are to be used in the step size control mechanism within CVODES. Call
+     CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration
+     tolerances for the quadrature variables. */
+  flag = CVodeSetQuadErrCon(cvode_mem, SUNTRUE);
+  if (check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1);
+
+  /* Call CVodeQuadSStolerances to specify scalar relative and absolute
+     tolerances. */
   flag = CVodeQuadSStolerances(cvode_mem, reltolQ, abstolQ);
   if (check_flag(&flag, "CVodeQuadSStolerances", 1)) return(1);
 
-  flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
-  if (check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1);
-
   /* Allocate global memory */
 
-  steps = STEPS;
+  /* Call CVodeAdjInit to update CVODES memory block by allocting the internal 
+     memory needed for backward integration.*/
+  steps = STEPS; /* no. of integration steps between two consecutive ckeckpoints*/
   flag = CVodeAdjInit(cvode_mem, steps, CV_HERMITE);
   /*
   flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL);
@@ -239,7 +264,9 @@ int main(int argc, char *argv[])
 
   /* Perform forward run */
   printf("Forward integration ... ");
-  
+
+  /* Call CVodeF to integrate the forward problem over an interval in time and
+     saves checkpointing data */
   flag = CVodeF(cvode_mem, TOUT, y, &time, CV_NORMAL, &ncheck);
   if (check_flag(&flag, "CVodeF", 1)) return(1);
   flag = CVodeGetNumSteps(cvode_mem, &nst);
@@ -310,45 +337,73 @@ int main(int argc, char *argv[])
   /* Create and allocate CVODES memory for backward run */
   printf("Create and allocate CVODES memory for backward run\n");
 
+  /* Call CVodeCreateB to specify the solution method for the backward 
+     problem. */
   flag = CVodeCreateB(cvode_mem, CV_BDF, CV_NEWTON, &indexB);
   if (check_flag(&flag, "CVodeCreateB", 1)) return(1);
 
+  /* Call CVodeInitB to allocate internal memory and initialize the 
+     backward problem. */
   flag = CVodeInitB(cvode_mem, indexB, fB, TB1, yB);
   if (check_flag(&flag, "CVodeInitB", 1)) return(1);
 
+  /* Set the scalar relative and absolute tolerances. */
   flag = CVodeSStolerancesB(cvode_mem, indexB, reltolB, abstolB);
   if (check_flag(&flag, "CVodeSStolerancesB", 1)) return(1);
 
+  /* Attach the user data for backward problem. */
   flag = CVodeSetUserDataB(cvode_mem, indexB, data);
   if (check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
 
-  flag = CVDenseB(cvode_mem, indexB, NEQ);
-  if (check_flag(&flag, "CVDenseB", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  AB = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)AB, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LSB = SUNDenseLinearSolver(yB, AB);
+  if (check_flag((void *)LSB, "SUNDenseLinearSolver", 0)) return(1);
 
-  flag = CVDlsSetDenseJacFnB(cvode_mem, indexB, JacB);
-  if (check_flag(&flag, "CVDlsSetDenseJacFnB", 1)) return(1);
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolverB(cvode_mem, indexB, LSB, AB);
+  if (check_flag(&flag, "CVDlsSetLinearSolverB", 1)) return(1);
 
+  /* Set the user-supplied Jacobian routine JacB */
+  flag = CVDlsSetJacFnB(cvode_mem, indexB, JacB);
+  if (check_flag(&flag, "CVDlsSetJacFnB", 1)) return(1);
+
+  /* Call CVodeQuadInitB to allocate internal memory and initialize backward
+     quadrature integration. */
   flag = CVodeQuadInitB(cvode_mem, indexB, fQB, qB);
   if (check_flag(&flag, "CVodeQuadInitB", 1)) return(1);
 
+  /* Call CVodeSetQuadErrCon to specify whether or not the quadrature variables
+     are to be used in the step size control mechanism within CVODES. Call
+     CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration
+     tolerances for the quadrature variables. */
+  flag = CVodeSetQuadErrConB(cvode_mem, indexB, SUNTRUE);
+  if (check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1);
+
+  /* Call CVodeQuadSStolerancesB to specify the scalar relative and absolute tolerances
+     for the backward problem. */
   flag = CVodeQuadSStolerancesB(cvode_mem, indexB, reltolB, abstolQB);
   if (check_flag(&flag, "CVodeQuadSStolerancesB", 1)) return(1);
 
-  flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE);
-  if (check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1);
-
   /* Backward Integration */
 
   PrintHead(TB1);
 
   /* First get results at t = TBout1 */
 
+  /* Call CVodeB to integrate the backward ODE problem. */
   flag = CVodeB(cvode_mem, TBout1, CV_NORMAL);
   if (check_flag(&flag, "CVodeB", 1)) return(1);
 
+  /* Call CVodeGetB to get yB of the backward ODE problem. */
   flag = CVodeGetB(cvode_mem, indexB, &time, yB);
   if (check_flag(&flag, "CVodeGetB", 1)) return(1);
 
+  /* Call CVodeGetAdjY to get the interpolated value of the forward solution
+     y during a backward integration. */
   flag = CVodeGetAdjY(cvode_mem, TBout1, y);
   if (check_flag(&flag, "CVodeGetAdjY", 1)) return(1);
 
@@ -364,6 +419,8 @@ int main(int argc, char *argv[])
   flag = CVodeGetB(cvode_mem, indexB, &time, yB);
   if (check_flag(&flag, "CVodeGetB", 1)) return(1);
 
+  /* Call CVodeGetQuadB to get the quadrature solution vector after a 
+     successful return from CVodeB. */
   flag = CVodeGetQuadB(cvode_mem, indexB, &time, qB);
   if (check_flag(&flag, "CVodeGetQuadB", 1)) return(1);
 
@@ -427,10 +484,14 @@ int main(int argc, char *argv[])
   printf("Free memory\n\n");
 
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(y); 
-  N_VDestroy_Serial(q);
-  N_VDestroy_Serial(yB);
-  N_VDestroy_Serial(qB);
+  N_VDestroy(y); 
+  N_VDestroy(q);
+  N_VDestroy(yB);
+  N_VDestroy(qB);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB);
+  SUNMatDestroy(AB);
 
   if (ckpnt != NULL) free(ckpnt);
   free(data);
@@ -470,10 +531,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
  * Jacobian routine. Compute J(t,y). 
 */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
   UserData data;
@@ -485,7 +544,7 @@ static int Jac(long int N, realtype t,
  
   IJth(J,1,1) = -p1;  IJth(J,1,2) = p2*y3;          IJth(J,1,3) = p2*y2;
   IJth(J,2,1) =  p1;  IJth(J,2,2) = -p2*y3-2*p3*y2; IJth(J,2,3) = -p2*y2;
-                      IJth(J,3,2) = 2*p3*y2;
+  IJth(J,3,1) = ZERO; IJth(J,3,2) = 2*p3*y2;        IJth(J,3,3) = ZERO;
 
   return(0);
 }
@@ -565,10 +624,8 @@ static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, void *user_da
  * JacB routine. Compute JB(t,y,yB). 
  */
 
-static int JacB(long int NB, realtype t,
-                N_Vector y, N_Vector yB, N_Vector fyB,
-                DlsMat JB, void *user_dataB,
-                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+static int JacB(realtype t, N_Vector y, N_Vector yB, N_Vector fyB, SUNMatrix JB,
+                void *user_dataB, N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   UserData data;
   realtype y1, y2, y3;
@@ -583,10 +640,9 @@ static int JacB(long int NB, realtype t,
   y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
 
   /* Load JB */
-  IJth(JB,1,1) = p1;     IJth(JB,1,2) = -p1; 
-  IJth(JB,2,1) = -p2*y3; IJth(JB,2,2) = p2*y3+2.0*p3*y2;
-                         IJth(JB,2,3) = RCONST(-2.0)*p3*y2;
-  IJth(JB,3,1) = -p2*y2; IJth(JB,3,2) = p2*y2;
+  IJth(JB,1,1) = p1;     IJth(JB,1,2) = -p1;             IJth(JB,1,3) = ZERO;
+  IJth(JB,2,1) = -p2*y3; IJth(JB,2,2) = p2*y3+2.0*p3*y2; IJth(JB,2,3) = RCONST(-2.0)*p3*y2;
+  IJth(JB,3,1) = -p2*y2; IJth(JB,3,2) = p2*y2;           IJth(JB,3,3) = ZERO;
 
   return(0);
 }
@@ -598,17 +654,10 @@ static int JacB(long int NB, realtype t,
 static int fQB(realtype t, N_Vector y, N_Vector yB, 
                N_Vector qBdot, void *user_dataB)
 {
-  UserData data;
   realtype y1, y2, y3;
-  realtype p1, p2, p3;
   realtype l1, l2, l3;
   realtype l21, l32, y23;
 
-  data = (UserData) user_dataB;
-
-  /* The p vector */
-  p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
-
   /* The y vector */
   y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
   
diff --git a/examples/cvodes/serial/cvsRoberts_ASAi_dns.out b/examples/cvodes/serial/cvsRoberts_ASAi_dns.out
index dfe6540..dc39518 100644
--- a/examples/cvodes/serial/cvsRoberts_ASAi_dns.out
+++ b/examples/cvodes/serial/cvsRoberts_ASAi_dns.out
@@ -12,7 +12,7 @@ Find dG/dp for
 
 
 Create and allocate CVODES memory for forward runs
-Forward integration ... done ( nst = 830 )
+Forward integration ... done ( nst = 766 )
 
 ncheck = 5
 
@@ -27,15 +27,15 @@ Backward integration from tB0 =   4.0000e+07
 returned t:   4.0000e+01
 tout:         4.0000e+01
 lambda(t):    3.9967e+07   3.9967e+07   3.9967e+07
-y(t):         7.1583e-01   9.1856e-06   2.8416e-01
+y(t):         7.1583e-01   9.1855e-06   2.8416e-01
 --------------------------------------------------------
 
-Done ( nst = 267 )
+Done ( nst = 212 )
 --------------------------------------------------------
 returned t:   0.0000e+00
 lambda(t0):   3.9967e+07   3.9967e+07   3.9967e+07
 y(t0):        1.0000e+00   0.0000e+00   0.0000e+00
-dG/dp:        7.6836e+05  -3.0688e+00   5.1143e-04
+dG/dp:        7.6842e+05  -3.0691e+00   5.1144e-04
 --------------------------------------------------------
 
 Re-initialize CVODES memory for backward run
@@ -45,15 +45,15 @@ Backward integration from tB0 =   5.0000e+01
 returned t:   4.0000e+01
 tout:         4.0000e+01
 lambda(t):    2.8959e-01   1.7624e+00   9.3567e+00
-y(t):         7.1583e-01   9.1856e-06   2.8416e-01
+y(t):         7.1583e-01   9.1855e-06   2.8416e-01
 --------------------------------------------------------
 
-Done ( nst = 158 )
+Done ( nst = 186 )
 --------------------------------------------------------
 returned t:   0.0000e+00
-lambda(t0):   8.4191e+00   1.6097e+01   1.6097e+01
+lambda(t0):   8.4190e+00   1.6097e+01   1.6097e+01
 y(t0):        1.0000e+00   0.0000e+00   0.0000e+00
-dG/dp:        1.7341e+02  -5.0591e-04   8.4323e-08
+dG/dp:        1.7341e+02  -5.0590e-04   8.4321e-08
 --------------------------------------------------------
 
 Free memory
diff --git a/examples/cvodes/serial/cvsRoberts_ASAi_klu.c b/examples/cvodes/serial/cvsRoberts_ASAi_klu.c
index 6ab9cf3..0032b64 100644
--- a/examples/cvodes/serial/cvsRoberts_ASAi_klu.c
+++ b/examples/cvodes/serial/cvsRoberts_ASAi_klu.c
@@ -1,13 +1,22 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * ----------------------------------------------------------------- 
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
  *      Based on cvsRoberts_ASAi_dns.c and modified to use KLU
  * -----------------------------------------------------------------
- * Adjoint sensitivity example problem:
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2015, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence
+ * Livermore National Laboratory.
  *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Adjoint sensitivity example problem.
  * The following is a simple example problem, with the coding
  * needed for its solution by CVODES. The problem is from chemical
  * kinetics, and consists of the following three rate equations.
@@ -46,24 +55,22 @@
  * where
  *   d(phi)/dt = g(t,y,p)
  *   phi(t1) = 0
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-/* Header files with a description of contents used */
-#include <cvodes/cvodes.h>              /* prototypes for CVODES fcts. and consts. */
-#include <cvodes/cvodes_klu.h>          /* prototypes for CVKLU fcts. and constants */
-#include <sundials/sundials_sparse.h>   /* definitions SlsMat */
-#include <nvector/nvector_serial.h>     /* defs. of serial NVECTOR fcts. and macros */
-#include <sundials/sundials_types.h>    /* def. of type realtype */
-#include <sundials/sundials_math.h>     /* definition of ABS */
+#include <cvodes/cvodes.h>              /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>     /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h> /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>    /* access to KLU SUNLinearSolver        */
+#include <cvodes/cvodes_direct.h>       /* access to CVDls interface            */
+#include <sundials/sundials_types.h>    /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>     /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 /* These macros are defined in order to write code with which exactly matched
-   the mathematical problem description given above.
-*/
+   the mathematical problem description given above. */
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component, i=1..NEQ */
 
@@ -103,18 +110,15 @@ typedef struct {
 /* Prototypes of user-supplied functions */
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data);
 static int ewt(N_Vector y, N_Vector w, void *user_data);
 
 static int fB(realtype t, N_Vector y, 
               N_Vector yB, N_Vector yBdot, void *user_dataB);
-static int JacB(realtype t,
-                N_Vector y, N_Vector yB, N_Vector fyB,
-                SlsMat JacMatB, void *user_dataB,
-                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+static int JacB(realtype t, N_Vector y, N_Vector yB, N_Vector fyB, SUNMatrix JB,
+                void *user_dataB, N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
 static int fQB(realtype t, N_Vector y, N_Vector yB, 
                N_Vector qBdot, void *user_dataB);
 
@@ -136,6 +140,8 @@ int main(int argc, char *argv[])
 {
   UserData data;
 
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
   void *cvode_mem;
 
   realtype reltolQ, abstolQ;
@@ -156,6 +162,8 @@ int main(int argc, char *argv[])
   CVadjCheckPointRec *ckpnt;
 
   data = NULL;
+  A = AB = NULL;
+  LS = LSB = NULL;
   cvode_mem = NULL;
   ckpnt = NULL;
   y = yB = qB = NULL;
@@ -208,7 +216,7 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "CVodeInit", 1)) return(1);
 
   /* Call CVodeWFtolerances to specify a user-supplied function ewt that sets
-     the multiplicative error weights W_i for use in the weighted RMS norm */
+     the multiplicative error weights w_i for use in the weighted RMS norm */
   flag = CVodeWFtolerances(cvode_mem, ewt);
   if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1);
 
@@ -216,14 +224,22 @@ int main(int argc, char *argv[])
   flag = CVodeSetUserData(cvode_mem, data);
   if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVKLU to specify the CVKLU sparse direct linear solver */
-  nnz = NEQ * NEQ;              /* max no. of nonzeros entries in the Jac */
-  flag = CVKLU(cvode_mem, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "CVKLU", 1)) return(1);
+  /* Create sparse SUNMatrix for use in linear solves */
+  nnz = NEQ * NEQ; /* max no. of nonzeros entries in the Jac */
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object */
+  LS = SUNKLU(y, A);
+  if (check_flag((void *)LS, "SUNKLU", 0)) return(1);
+
+  /* Attach the matrix and linear solver for the forward problem */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if (check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  /* Set the user-supplied Jacobian routine for the forward problem */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if (check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* Call CVodeQuadInit to allocate initernal memory and initialize
      quadrature integration*/
@@ -234,7 +250,7 @@ int main(int argc, char *argv[])
      are to be used in the step size control mechanism within CVODES. Call
      CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration
      tolerances for the quadrature variables. */
-  flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+  flag = CVodeSetQuadErrCon(cvode_mem, SUNTRUE);
   if (check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1);
 
   /* Call CVodeQuadSStolerances to specify scalar relative and absolute
@@ -246,8 +262,7 @@ int main(int argc, char *argv[])
 
   /* Call CVodeAdjInit to update CVODES memory block by allocting the internal 
      memory needed for backward integration.*/
-  steps = STEPS;             /* no. of integration steps between two
-                               consecutive ckeckpoints*/
+  steps = STEPS; /* no. of integration steps between two consecutive ckeckpoints*/
   flag = CVodeAdjInit(cvode_mem, steps, CV_HERMITE);
   /*
   flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL);
@@ -347,14 +362,21 @@ int main(int argc, char *argv[])
   flag = CVodeSetUserDataB(cvode_mem, indexB, data);
   if (check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
 
-  /* Call CVKLUB to initialize the CVKLU sparse linear solver for the backward 
-     problem. */
-  flag = CVKLUB(cvode_mem, indexB, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "CVKLUB", 1)) return(1);
+/* Create sparse SUNMatrix for use in linear solves */
+  AB = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object */
+  LSB = SUNKLU(yB, AB);
+  if (check_flag((void *)LSB, "SUNKLU", 0)) return(1);
+
+  /* Attach the matrix and linear solver for the backward problem */
+  flag = CVDlsSetLinearSolverB(cvode_mem, indexB, LSB, AB);
+  if (check_flag(&flag, "CVDlsSetLinearSolverB", 1)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) for the backward problem */
-  flag = CVSlsSetSparseJacFnB(cvode_mem, indexB, JacB);
-  if (check_flag(&flag, "CVSlsSetSparseJacFnB", 1)) return(1);
+  /* Set the user-supplied Jacobian routine for the backward problem */
+  flag = CVDlsSetJacFnB(cvode_mem, indexB, JacB);
+  if (check_flag(&flag, "CVDlsSetJacFnB", 1)) return(1);
 
   /* Call CVodeQuadInitB to allocate internal memory and initialize backward
      quadrature integration. */
@@ -365,7 +387,7 @@ int main(int argc, char *argv[])
      are to be used in the step size control mechanism within CVODES. Call
      CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration
      tolerances for the quadrature variables. */
-  flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE);
+  flag = CVodeSetQuadErrConB(cvode_mem, indexB, SUNTRUE);
   if (check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1);
 
   /* Call CVodeQuadSStolerancesB to specify the scalar relative and absolute tolerances
@@ -469,10 +491,14 @@ int main(int argc, char *argv[])
   printf("Free memory\n\n");
 
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(y); 
-  N_VDestroy_Serial(q);
-  N_VDestroy_Serial(yB);
-  N_VDestroy_Serial(qB);
+  N_VDestroy(y); 
+  N_VDestroy(q);
+  N_VDestroy(yB);
+  N_VDestroy(qB);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB);
+  SUNMatDestroy(AB);
 
   if (ckpnt != NULL) free(ckpnt);
   free(data);
@@ -512,42 +538,48 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
  * Jacobian routine. Compute J(t,y). 
 */
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(y);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(y);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
   
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = -p1;                          rowvals[0] = 0;
-  data[1] = p1;                           rowvals[1] = 1;
-  data[2] = ZERO;                         rowvals[2] = 2;
-
-  data[3] = p2*yval[2];                   rowvals[3] = 0;
-  data[4] = -p2*yval[2]-2*p3*yval[1];     rowvals[4] = 1;
-  data[5] = 2*yval[1];                    rowvals[5] = 2;
+  data[0] = -p1;
+  rowvals[0] = 0;
+  data[1] = p1;
+  rowvals[1] = 1;
+  data[2] = ZERO;
+  rowvals[2] = 2;
+
+  data[3] = p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = -p2*yval[2]-2*p3*yval[1];
+  rowvals[4] = 1;
+  data[5] = 2*yval[1];
+  rowvals[5] = 2;
   
-  data[6] = p2*yval[1];                   rowvals[6] = 0;
-  data[7] = -p2*yval[1];                  rowvals[7] = 1;
-  data[8] = ZERO;                         rowvals[8] = 2;
+  data[6] = p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = -p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ZERO;
+  rowvals[8] = 2;
 
   return(0);
 }
@@ -604,7 +636,7 @@ static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, void *user_da
   /* The p vector */
   p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
 
-  /* The y vector */ 
+  /* The y vector */
   y2 = Ith(y,2); y3 = Ith(y,3);
   
   /* The lambda vector */
@@ -628,44 +660,48 @@ static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, void *user_da
 
 static int JacB(realtype t,
                 N_Vector y, N_Vector yB, N_Vector fyB,
-                SlsMat JacMatB, void *user_dataB,
+                SUNMatrix JB, void *user_dataB,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   realtype *yvalB;
-  int* colptrsB;
-  int* rowvalsB;
-  realtype* dataB;
+  sunindextype *colptrsB = SUNSparseMatrix_IndexPointers(JB);
+  sunindextype *rowvalsB = SUNSparseMatrix_IndexValues(JB);
+  realtype *dataB = SUNSparseMatrix_Data(JB);
   UserData userdata;
   realtype p1, p2, p3;
 
-  yvalB = N_VGetArrayPointer_Serial(y);
-  colptrsB = (*JacMatB->colptrs);
-  rowvalsB = (*JacMatB->rowvals);
-  dataB = JacMatB->data;
-  userdata = (UserData) user_dataB;
+  yvalB = N_VGetArrayPointer(y);
 
-  /* The p vector */
+  userdata = (UserData) user_dataB;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMatB);
+  SUNMatZero(JB);
   
-  /* Load JB */
   colptrsB[0] = 0;
   colptrsB[1] = 3;
   colptrsB[2] = 6;
   colptrsB[3] = 9;
 
-  dataB[0] = p1;                           rowvalsB[0] = 0;
-  dataB[1] = -p2*yvalB[2];                 rowvalsB[1] = 1;
-  dataB[2] = -p2*yvalB[1];                 rowvalsB[2] = 2;
-
-  dataB[3] =-p1;                           rowvalsB[3] = 0;
-  dataB[4] = p2*yvalB[2]+2*p3*yvalB[1];    rowvalsB[4] = 1;
-  dataB[5] = p2*yvalB[1];                  rowvalsB[5] = 2;
+  dataB[0] = p1;
+  rowvalsB[0] = 0;
+  dataB[1] = -p2*yvalB[2];
+  rowvalsB[1] = 1;
+  dataB[2] = -p2*yvalB[1];
+  rowvalsB[2] = 2;
+
+  dataB[3] =-p1;
+  rowvalsB[3] = 0;
+  dataB[4] = p2*yvalB[2]+2*p3*yvalB[1];
+  rowvalsB[4] = 1;
+  dataB[5] = p2*yvalB[1];
+  rowvalsB[5] = 2;
   
-  dataB[6] = ZERO;                         rowvalsB[6] = 0;
-  dataB[7] = RCONST(-2.0)*p3*yvalB[1];     rowvalsB[7] = 1;
-  dataB[8] = ZERO;                         rowvalsB[8] = 2;
+  dataB[6] = ZERO;
+  rowvalsB[6] = 0;
+  dataB[7] = RCONST(-2.0)*p3*yvalB[1];
+  rowvalsB[7] = 1;
+  dataB[8] = ZERO;
+  rowvalsB[8] = 2;
 
   return(0);
 }
diff --git a/examples/cvodes/serial/cvsRoberts_ASAi_sps.c b/examples/cvodes/serial/cvsRoberts_ASAi_sps.c
index 8dce1df..f0f2424 100644
--- a/examples/cvodes/serial/cvsRoberts_ASAi_sps.c
+++ b/examples/cvodes/serial/cvsRoberts_ASAi_sps.c
@@ -1,13 +1,22 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * ----------------------------------------------------------------- 
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
  *      Based on cvsRoberts_ASAi_dns.c and modified to use SuperLUMT
  * -----------------------------------------------------------------
- * Adjoint sensitivity example problem:
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2015, Southern Methodist University and 
+ * Lawrence Livermore National Security
  *
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Adjoint sensitivity example problem.
  * The following is a simple example problem, with the coding
  * needed for its solution by CVODES. The problem is from chemical
  * kinetics, and consists of the following three rate equations.
@@ -18,8 +27,8 @@
  * conditions: y1 = 1.0, y2 = y3 = 0. The reaction rates are:
  * p1=0.04, p2=1e4, and p3=3e7. The problem is stiff.
  * This program solves the problem with the BDF method, Newton
- * iteration with the CVODE SuperLU_MT linear solver, and a 
- * user-supplied Jacobian routine.
+ * iteration with the CVODE SuperLU_MT linear solver, and a user-supplied
+ * Jacobian routine.
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance.
  * Output is printed in decades from t = .4 to t = 4.e10.
@@ -46,24 +55,22 @@
  * where
  *   d(phi)/dt = g(t,y,p)
  *   phi(t1) = 0
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-/* Header files with a description of contents used */
-#include <cvodes/cvodes.h>              /* prototypes for CVODES fcts. and consts. */
-#include <cvodes/cvodes_superlumt.h>    /* prototypes for CVSUPERLUMT fcts. and constants */
-#include <sundials/sundials_sparse.h>   /* definitions SlsMat */
-#include <nvector/nvector_serial.h>     /* defs. of serial NVECTOR fcts. and macros */
-#include <sundials/sundials_types.h>    /* def. of type realtype */
-#include <sundials/sundials_math.h>     /* definition of ABS */
+#include <cvodes/cvodes.h>                 /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h> /* access to SuperLUMT SUNLinearSolver  */
+#include <cvodes/cvodes_direct.h>          /* access to CVDls interface            */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 /* These macros are defined in order to write code with which exactly matched
-   the mathematical problem description given above.
-*/
+   the mathematical problem description given above. */
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component, i=1..NEQ */
 
@@ -103,18 +110,15 @@ typedef struct {
 /* Prototypes of user-supplied functions */
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data);
 static int ewt(N_Vector y, N_Vector w, void *user_data);
 
 static int fB(realtype t, N_Vector y, 
               N_Vector yB, N_Vector yBdot, void *user_dataB);
-static int JacB(realtype t,
-                N_Vector y, N_Vector yB, N_Vector fyB,
-                SlsMat JacMatB, void *user_dataB,
-                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+static int JacB(realtype t, N_Vector y, N_Vector yB, N_Vector fyB, SUNMatrix JB,
+                void *user_dataB, N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
 static int fQB(realtype t, N_Vector y, N_Vector yB, 
                N_Vector qBdot, void *user_dataB);
 
@@ -136,6 +140,8 @@ int main(int argc, char *argv[])
 {
   UserData data;
 
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
   void *cvode_mem;
 
   realtype reltolQ, abstolQ;
@@ -156,6 +162,8 @@ int main(int argc, char *argv[])
   CVadjCheckPointRec *ckpnt;
 
   data = NULL;
+  A = AB = NULL;
+  LS = LSB = NULL;
   cvode_mem = NULL;
   ckpnt = NULL;
   y = yB = qB = NULL;
@@ -208,7 +216,7 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "CVodeInit", 1)) return(1);
 
   /* Call CVodeWFtolerances to specify a user-supplied function ewt that sets
-     the multiplicative error weights W_i for use in the weighted RMS norm */
+     the multiplicative error weights w_i for use in the weighted RMS norm */
   flag = CVodeWFtolerances(cvode_mem, ewt);
   if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1);
 
@@ -216,15 +224,23 @@ int main(int argc, char *argv[])
   flag = CVodeSetUserData(cvode_mem, data);
   if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVKLU to specify the CVKLU sparse direct linear solver */
-  nthreads = 1;                 /* no. of threads use when factoring the system */
-  nnz = NEQ * NEQ;              /* max no. of nonzeros entries in the Jac */
-  flag = CVSuperLUMT(cvode_mem, nthreads, NEQ, nnz);
-  if (check_flag(&flag, "CVSuperLUMT", 1)) return(1);
+  /* Create sparse SUNMatrix for use in linear solves */
+  nnz = NEQ * NEQ; /* max no. of nonzeros entries in the Jac */
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  /* Create SuperLUMT SUNLinearSolver object */
+  nthreads = 1; /* no. of threads use when factoring the system */
+  LS = SUNSuperLUMT(y, A, nthreads);
+  if (check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
+
+  /* Attach the matrix and linear solver for the forward problem */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if (check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine for the forward problem */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if (check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* Call CVodeQuadInit to allocate initernal memory and initialize
      quadrature integration*/
@@ -235,7 +251,7 @@ int main(int argc, char *argv[])
      are to be used in the step size control mechanism within CVODES. Call
      CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration
      tolerances for the quadrature variables. */
-  flag = CVodeSetQuadErrCon(cvode_mem, TRUE);
+  flag = CVodeSetQuadErrCon(cvode_mem, SUNTRUE);
   if (check_flag(&flag, "CVodeSetQuadErrCon", 1)) return(1);
 
   /* Call CVodeQuadSStolerances to specify scalar relative and absolute
@@ -247,8 +263,7 @@ int main(int argc, char *argv[])
 
   /* Call CVodeAdjInit to update CVODES memory block by allocting the internal 
      memory needed for backward integration.*/
-  steps = STEPS;             /* no. of integration steps between two
-                               consecutive ckeckpoints*/
+  steps = STEPS; /* no. of integration steps between two consecutive ckeckpoints*/
   flag = CVodeAdjInit(cvode_mem, steps, CV_HERMITE);
   /*
   flag = CVodeAdjInit(cvode_mem, steps, CV_POLYNOMIAL);
@@ -348,14 +363,21 @@ int main(int argc, char *argv[])
   flag = CVodeSetUserDataB(cvode_mem, indexB, data);
   if (check_flag(&flag, "CVodeSetUserDataB", 1)) return(1);
 
-  /* Call CVKLUB to initialize the CVKLU sparse linear solver for the backward 
-     problem. */
-  flag = CVSuperLUMTB(cvode_mem, indexB, nthreads, NEQ, nnz);
-  if (check_flag(&flag, "CVSuperLUMTb", 1)) return(1);
+/* Create sparse SUNMatrix for use in linear solves */
+  AB = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) for the backward problem */
-  flag = CVSlsSetSparseJacFnB(cvode_mem, indexB, JacB);
-  if (check_flag(&flag, "CVSlsSetSparseJacFnB", 1)) return(1);
+  /* Create SuperLUMT SUNLinearSolver object */
+  LSB = SUNSuperLUMT(yB, AB, nthreads);
+  if (check_flag((void *)LSB, "SUNSuperLUMT", 0)) return(1);
+
+  /* Attach the matrix and linear solver for the backward problem */
+  flag = CVDlsSetLinearSolverB(cvode_mem, indexB, LSB, AB);
+  if (check_flag(&flag, "CVDlsSetLinearSolverB", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine for the backward problem */
+  flag = CVDlsSetJacFnB(cvode_mem, indexB, JacB);
+  if (check_flag(&flag, "CVDlsSetJacFnB", 1)) return(1);
 
   /* Call CVodeQuadInitB to allocate internal memory and initialize backward
      quadrature integration. */
@@ -366,7 +388,7 @@ int main(int argc, char *argv[])
      are to be used in the step size control mechanism within CVODES. Call
      CVodeQuadSStolerances or CVodeQuadSVtolerances to specify the integration
      tolerances for the quadrature variables. */
-  flag = CVodeSetQuadErrConB(cvode_mem, indexB, TRUE);
+  flag = CVodeSetQuadErrConB(cvode_mem, indexB, SUNTRUE);
   if (check_flag(&flag, "CVodeSetQuadErrConB", 1)) return(1);
 
   /* Call CVodeQuadSStolerancesB to specify the scalar relative and absolute tolerances
@@ -470,10 +492,14 @@ int main(int argc, char *argv[])
   printf("Free memory\n\n");
 
   CVodeFree(&cvode_mem);
-  N_VDestroy_Serial(y); 
-  N_VDestroy_Serial(q);
-  N_VDestroy_Serial(yB);
-  N_VDestroy_Serial(qB);
+  N_VDestroy(y); 
+  N_VDestroy(q);
+  N_VDestroy(yB);
+  N_VDestroy(qB);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB);
+  SUNMatDestroy(AB);
 
   if (ckpnt != NULL) free(ckpnt);
   free(data);
@@ -490,7 +516,7 @@ int main(int argc, char *argv[])
 
 /*
  * f routine. Compute f(t,y). 
-*/
+ */
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 {
@@ -511,59 +537,65 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
 
 /* 
  * Jacobian routine. Compute J(t,y). 
-*/
+ */
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(y);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(y);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
   
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = -p1;                          rowvals[0] = 0;
-  data[1] = p1;                           rowvals[1] = 1;
-  data[2] = ZERO;                         rowvals[2] = 2;
-
-  data[3] = p2*yval[2];                   rowvals[3] = 0;
-  data[4] = -p2*yval[2]-2*p3*yval[1];     rowvals[4] = 1;
-  data[5] = 2*yval[1];                    rowvals[5] = 2;
+  data[0] = -p1;
+  rowvals[0] = 0;
+  data[1] = p1;
+  rowvals[1] = 1;
+  data[2] = ZERO;
+  rowvals[2] = 2;
+
+  data[3] = p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = -p2*yval[2]-2*p3*yval[1];
+  rowvals[4] = 1;
+  data[5] = 2*yval[1];
+  rowvals[5] = 2;
   
-  data[6] = p2*yval[1];                   rowvals[6] = 0;
-  data[7] = -p2*yval[1];                  rowvals[7] = 1;
-  data[8] = ZERO;                         rowvals[8] = 2;
+  data[6] = p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = -p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ZERO;
+  rowvals[8] = 2;
 
   return(0);
 }
 
 /* 
  * fQ routine. Compute fQ(t,y). 
-*/
+ */
 
 static int fQ(realtype t, N_Vector y, N_Vector qdot, void *user_data)
 {
-  Ith(qdot,1) = Ith(y,3);  
+  Ith(qdot,1) = Ith(y,3);
 
   return(0);
 }
- 
+
 /*
  * EwtSet function. Computes the error weights at the current solution.
  */
@@ -590,7 +622,7 @@ static int ewt(N_Vector y, N_Vector w, void *user_data)
 
 /* 
  * fB routine. Compute fB(t,y,yB). 
-*/
+ */
 
 static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, void *user_dataB)
 {
@@ -605,7 +637,7 @@ static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, void *user_da
   /* The p vector */
   p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
 
-  /* The y vector */ 
+  /* The y vector */
   y2 = Ith(y,2); y3 = Ith(y,3);
   
   /* The lambda vector */
@@ -629,51 +661,55 @@ static int fB(realtype t, N_Vector y, N_Vector yB, N_Vector yBdot, void *user_da
 
 static int JacB(realtype t,
                 N_Vector y, N_Vector yB, N_Vector fyB,
-                SlsMat JacMatB, void *user_dataB,
+                SUNMatrix JB, void *user_dataB,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   realtype *yvalB;
-  int* colptrsB;
-  int* rowvalsB;
-  realtype* dataB;
+  sunindextype *colptrsB = SUNSparseMatrix_IndexPointers(JB);
+  sunindextype *rowvalsB = SUNSparseMatrix_IndexValues(JB);
+  realtype *dataB = SUNSparseMatrix_Data(JB);
   UserData userdata;
   realtype p1, p2, p3;
 
-  yvalB = N_VGetArrayPointer_Serial(y);
-  colptrsB = (*JacMatB->colptrs);
-  rowvalsB = (*JacMatB->rowvals);
-  dataB = JacMatB->data;
-  userdata = (UserData) user_dataB;
+  yvalB = N_VGetArrayPointer(y);
 
-  /* The p vector */
+  userdata = (UserData) user_dataB;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMatB);
+  SUNMatZero(JB);
   
-  /* Load JB */
   colptrsB[0] = 0;
   colptrsB[1] = 3;
   colptrsB[2] = 6;
   colptrsB[3] = 9;
 
-  dataB[0] = p1;                           rowvalsB[0] = 0;
-  dataB[1] = -p2*yvalB[2];                 rowvalsB[1] = 1;
-  dataB[2] = -p2*yvalB[1];                 rowvalsB[2] = 2;
-
-  dataB[3] =-p1;                           rowvalsB[3] = 0;
-  dataB[4] = p2*yvalB[2]+2*p3*yvalB[1];    rowvalsB[4] = 1;
-  dataB[5] = p2*yvalB[1];                  rowvalsB[5] = 2;
+  dataB[0] = p1;
+  rowvalsB[0] = 0;
+  dataB[1] = -p2*yvalB[2];
+  rowvalsB[1] = 1;
+  dataB[2] = -p2*yvalB[1];
+  rowvalsB[2] = 2;
+
+  dataB[3] =-p1;
+  rowvalsB[3] = 0;
+  dataB[4] = p2*yvalB[2]+2*p3*yvalB[1];
+  rowvalsB[4] = 1;
+  dataB[5] = p2*yvalB[1];
+  rowvalsB[5] = 2;
   
-  dataB[6] = ZERO;                         rowvalsB[6] = 0;
-  dataB[7] = RCONST(-2.0)*p3*yvalB[1];     rowvalsB[7] = 1;
-  dataB[8] = ZERO;                         rowvalsB[8] = 2;
+  dataB[6] = ZERO;
+  rowvalsB[6] = 0;
+  dataB[7] = RCONST(-2.0)*p3*yvalB[1];
+  rowvalsB[7] = 1;
+  dataB[8] = ZERO;
+  rowvalsB[8] = 2;
 
   return(0);
 }
 
 /*
  * fQB routine. Compute integrand for quadratures 
-*/
+ */
 
 static int fQB(realtype t, N_Vector y, N_Vector yB, 
                N_Vector qBdot, void *user_dataB)
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_dns.c b/examples/cvodes/serial/cvsRoberts_FSA_dns.c
index 7d6aa08..0c59733 100644
--- a/examples/cvodes/serial/cvsRoberts_FSA_dns.c
+++ b/examples/cvodes/serial/cvsRoberts_FSA_dns.c
@@ -1,16 +1,13 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
  *
  * The following is a simple example problem, with the coding
- * needed for its solution by CVODES. The problem is from chemical
- * kinetics, and consists of the following three rate equations:
+ * needed for its solution by CVODES for Forward Sensitivity 
+ * Analysis. The problem is from chemical kinetics, and consists
+ * of the following three rate equations:
  *    dy1/dt = -p1*y1 + p2*y2*y3
  *    dy2/dt =  p1*y1 - p2*y2*y3 - p3*(y2)^2
  *    dy3/dt =  p3*(y2)^2
@@ -31,7 +28,7 @@
  * user routine fS (of type SensRhs1Fn).
  * Any of three sensitivity methods (SIMULTANEOUS, STAGGERED, and
  * STAGGERED1) can be used and sensitivities may be included in the
- * error test or not (error control set on TRUE or FALSE,
+ * error test or not (error control set on SUNTRUE or SUNFALSE,
  * respectively).
  *
  * Execution:
@@ -42,23 +39,24 @@
  *    % cvsRoberts_FSA_dns -sensi sensi_meth err_con
  * where sensi_meth is one of {sim, stg, stg1} and err_con is one of
  * {t, f}.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <cvodes/cvodes.h>           /* prototypes for CVODES fcts. and consts. */
-#include <cvodes/cvodes_dense.h>     /* prototype for CVDENSE fcts. and constants */
-#include <nvector/nvector_serial.h>  /* defs. of serial NVECTOR fcts. and macros  */
-#include <sundials/sundials_types.h> /* def. of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS */
+#include <cvodes/cvodes.h>             /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <cvodes/cvodes_direct.h>      /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* definition of ABS */
 
 /* Accessor macros */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i=1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* (i,j)-th matrix component i,j=1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* i-th vector component i=1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* (i,j)-th matrix component i,j=1..NEQ */
 
 /* Problem Constants */
 
@@ -90,13 +88,11 @@ typedef struct {
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
-static int fS(int Ns, realtype t, N_Vector y, N_Vector ydot, 
-              int iS, N_Vector yS, N_Vector ySdot, 
+static int fS(int Ns, realtype t, N_Vector y, N_Vector ydot,
+              int iS, N_Vector yS, N_Vector ySdot,
               void *user_data, N_Vector tmp1, N_Vector tmp2);
 
 static int ewt(N_Vector y, N_Vector w, void *user_data);
@@ -120,6 +116,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 int main(int argc, char *argv[])
 {
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   UserData data;
   realtype t, tout;
@@ -134,8 +132,10 @@ int main(int argc, char *argv[])
 
   cvode_mem = NULL;
   data      = NULL;
-  y         =  NULL;
+  y         = NULL;
   yS        = NULL;
+  A         = NULL;
+  LS        = NULL;
 
   /* Process arguments */
   ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
@@ -171,35 +171,58 @@ int main(int argc, char *argv[])
   flag = CVodeSetUserData(cvode_mem, data);
   if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Attach linear solver */
-  flag = CVDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVDense", 1)) return(1);
+  /* Create dense SUNMatrix */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if (check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver */
+  LS = SUNDenseLinearSolver(y, A);
+  if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if (check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if (check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   printf("\n3-species chemical kinetics problem\n");
 
   /* Sensitivity-related settings */
   if (sensi) {
 
+    /* Set parameter scaling factor */
     pbar[0] = data->p[0];
     pbar[1] = data->p[1];
     pbar[2] = data->p[2];
 
-    yS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)yS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    /* Set sensitivity initial conditions */
+    yS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)yS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);
 
+    /* Call CVodeSensInit1 to activate forward sensitivity computations
+       and allocate internal memory for COVEDS related to sensitivity
+       calculations. Computes the right-hand sides of the sensitivity
+       ODE, one at a time */
     flag = CVodeSensInit1(cvode_mem, NS, sensi_meth, fS, yS);
     if(check_flag(&flag, "CVodeSensInit", 1)) return(1);
 
+    /* Call CVodeSensEEtolerances to estimate tolerances for sensitivity 
+       variables based on the rolerances supplied for states variables and 
+       the scaling factor pbar */
     flag = CVodeSensEEtolerances(cvode_mem);
     if(check_flag(&flag, "CVodeSensEEtolerances", 1)) return(1);
 
+    /* Set sensitivity analysis optional inputs */
+    /* Call CVodeSetSensErrCon to specify the error control strategy for 
+       sensitivity variables */
     flag = CVodeSetSensErrCon(cvode_mem, err_con);
     if (check_flag(&flag, "CVodeSetSensErrCon", 1)) return(1);
 
+    /* Call CVodeSetSensParams to specify problem parameter information for 
+       sensitivity calculations */
     flag = CVodeSetSensParams(cvode_mem, NULL, pbar, NULL);
     if (check_flag(&flag, "CVodeSetSensParams", 1)) return(1);
 
@@ -235,6 +258,8 @@ int main(int argc, char *argv[])
 
     PrintOutput(cvode_mem, t, y);
 
+    /* Call CVodeGetSens to get the sensitivity solution vector after a
+       successful return from CVode */
     if (sensi) {
       flag = CVodeGetSens(cvode_mem, &t, yS);
       if (check_flag(&flag, "CVodeGetSens", 1)) break;
@@ -250,12 +275,14 @@ int main(int argc, char *argv[])
 
   /* Free memory */
 
-  N_VDestroy_Serial(y);                    /* Free y vector */
+  N_VDestroy(y);                    /* Free y vector */
   if (sensi) {
-    N_VDestroyVectorArray_Serial(yS, NS);  /* Free yS vector */
+    N_VDestroyVectorArray(yS, NS);  /* Free yS vector */
   }
   free(data);                              /* Free user data */
   CVodeFree(&cvode_mem);                   /* Free CVODES memory */
+  SUNLinSolFree(LS);                       /* Free the linear solver memory */
+  SUNMatDestroy(A);                        /* Free the matrix memory */
 
   return(0);
 }
@@ -292,10 +319,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
  * Jacobian routine. Compute J(t,y). 
  */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
   UserData data;
@@ -395,16 +420,16 @@ static int ewt(N_Vector y, N_Vector w, void *user_data)
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -423,9 +448,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -451,7 +476,7 @@ static void PrintOutput(void *cvode_mem, realtype t, N_Vector u)
   int qu, flag;
   realtype hu, *udata;
   
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -488,7 +513,7 @@ static void PrintOutputS(N_Vector *uS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(uS[0]);
+  sdata = N_VGetArrayPointer(uS[0]);
   printf("                  Sensitivity 1  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -499,7 +524,7 @@ static void PrintOutputS(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
   
-  sdata = N_VGetArrayPointer_Serial(uS[1]);
+  sdata = N_VGetArrayPointer(uS[1]);
   printf("                  Sensitivity 2  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -510,7 +535,7 @@ static void PrintOutputS(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
 
-  sdata = N_VGetArrayPointer_Serial(uS[2]);
+  sdata = N_VGetArrayPointer(uS[2]);
   printf("                  Sensitivity 3  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_dns.out b/examples/cvodes/serial/cvsRoberts_FSA_dns_-sensi_sim_t.out
similarity index 100%
rename from examples/cvodes/serial/cvsRoberts_FSA_dns.out
rename to examples/cvodes/serial/cvsRoberts_FSA_dns_-sensi_sim_t.out
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_dns_-sensi_stg1_t.out b/examples/cvodes/serial/cvsRoberts_FSA_dns_-sensi_stg1_t.out
new file mode 100644
index 0000000..15341b1
--- /dev/null
+++ b/examples/cvodes/serial/cvsRoberts_FSA_dns_-sensi_stg1_t.out
@@ -0,0 +1,93 @@
+
+3-species chemical kinetics problem
+Sensitivity: YES ( STAGGERED1 + FULL ERROR CONTROL )
+
+=======================================================================
+     T     Q       H      NST           y1           y2           y3    
+=======================================================================
+4.000e-01  3  5.346e-02   105
+                  Solution         9.8517e-01   3.3864e-05   1.4794e-02 
+                  Sensitivity 1   -3.5595e-01   3.9025e-04   3.5556e-01 
+                  Sensitivity 2    9.5428e-08  -2.1310e-10  -9.5215e-08 
+                  Sensitivity 3   -1.5833e-11  -5.2901e-13   1.6362e-11 
+-----------------------------------------------------------------------
+4.000e+00  4  2.676e-01   140
+                  Solution         9.0552e-01   2.2405e-05   9.4457e-02 
+                  Sensitivity 1   -1.8760e+00   1.7923e-04   1.8758e+00 
+                  Sensitivity 2    2.9615e-06  -5.8302e-10  -2.9610e-06 
+                  Sensitivity 3   -4.9337e-10  -2.7627e-13   4.9364e-10 
+-----------------------------------------------------------------------
+4.000e+01  2  1.483e+00   256
+                  Solution         7.1582e-01   9.1851e-06   2.8417e-01 
+                  Sensitivity 1   -4.2477e+00   4.5907e-05   4.2476e+00 
+                  Sensitivity 2    1.3732e-05  -2.3569e-10  -1.3731e-05 
+                  Sensitivity 3   -2.2885e-09  -1.1380e-13   2.2886e-09 
+-----------------------------------------------------------------------
+4.000e+02  2  8.856e+00   386
+                  Solution         4.5047e-01   3.2223e-06   5.4953e-01 
+                  Sensitivity 1   -5.9588e+00   3.5358e-06   5.9588e+00 
+                  Sensitivity 2    2.2740e-05  -2.2567e-11  -2.2740e-05 
+                  Sensitivity 3   -3.7900e-09  -4.9944e-14   3.7901e-09 
+-----------------------------------------------------------------------
+4.000e+03  3  1.673e+02   533
+                  Solution         1.8317e-01   8.9408e-07   8.1683e-01 
+                  Sensitivity 1   -4.7500e+00  -5.9955e-06   4.7500e+00 
+                  Sensitivity 2    1.8809e-05   2.3132e-11  -1.8809e-05 
+                  Sensitivity 3   -3.1348e-09  -1.8757e-14   3.1348e-09 
+-----------------------------------------------------------------------
+4.000e+04  3  1.994e+03   629
+                  Solution         3.8992e-02   1.6221e-07   9.6101e-01 
+                  Sensitivity 1   -1.5752e+00  -2.7620e-06   1.5752e+00 
+                  Sensitivity 2    6.2882e-06   1.1002e-11  -6.2882e-06 
+                  Sensitivity 3   -1.0480e-09  -4.5372e-15   1.0480e-09 
+-----------------------------------------------------------------------
+4.000e+05  4  1.219e+04   678
+                  Solution         4.9392e-03   1.9853e-08   9.9506e-01 
+                  Sensitivity 1   -2.3634e-01  -4.5834e-07   2.3634e-01 
+                  Sensitivity 2    9.4507e-07   1.8324e-12  -9.4507e-07 
+                  Sensitivity 3   -1.5753e-10  -6.3636e-16   1.5753e-10 
+-----------------------------------------------------------------------
+4.000e+06  5  9.487e+04   735
+                  Solution         5.1683e-04   2.0684e-09   9.9948e-01 
+                  Sensitivity 1   -2.5661e-02  -5.1039e-08   2.5661e-02 
+                  Sensitivity 2    1.0262e-07   2.0408e-13  -1.0262e-07 
+                  Sensitivity 3   -1.7111e-11  -6.8512e-17   1.7111e-11 
+-----------------------------------------------------------------------
+4.000e+07  4  1.995e+06   788
+                  Solution         5.2060e-05   2.0825e-10   9.9995e-01 
+                  Sensitivity 1   -2.5995e-03  -5.1927e-09   2.5995e-03 
+                  Sensitivity 2    1.0395e-08   2.0760e-14  -1.0395e-08 
+                  Sensitivity 3   -1.7340e-12  -6.9367e-18   1.7340e-12 
+-----------------------------------------------------------------------
+4.000e+08  5  2.372e+07   835
+                  Solution         5.2135e-06   2.0854e-11   9.9999e-01 
+                  Sensitivity 1   -2.6031e-04  -5.1992e-10   2.6031e-04 
+                  Sensitivity 2    1.0412e-09   2.0793e-15  -1.0412e-09 
+                  Sensitivity 3   -1.7376e-13  -6.9506e-19   1.7376e-13 
+-----------------------------------------------------------------------
+4.000e+09  3  4.792e+08   895
+                  Solution         5.1887e-07   2.0755e-12   1.0000e+00 
+                  Sensitivity 1   -2.6036e-05  -5.2257e-11   2.6036e-05 
+                  Sensitivity 2    1.0415e-10   2.0906e-16  -1.0415e-10 
+                  Sensitivity 3   -1.7316e-14  -6.9265e-20   1.7316e-14 
+-----------------------------------------------------------------------
+4.000e+10  3  1.237e+09   930
+                  Solution         5.1573e-08   2.0629e-13   1.0000e+00 
+                  Sensitivity 1   -2.6618e-06  -5.4901e-12   2.6619e-06 
+                  Sensitivity 2    1.0763e-11   2.2422e-17  -1.0763e-11 
+                  Sensitivity 3   -1.7339e-15  -6.9355e-21   1.7339e-15 
+-----------------------------------------------------------------------
+
+Final Statistics
+
+nst     =   930
+
+nfe     =  2105
+netf    =     0    nsetups  =   182
+nni     =  1105    ncfn     =     0
+
+nfSe    =  3567    nfeS     =     0
+netfs   =    66    nsetupsS =     0
+nniS    =  3555    ncfnS    =     0
+
+nje    =    17    nfeLS     =     0
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_klu.c b/examples/cvodes/serial/cvsRoberts_FSA_klu.c
index cac5025..12ba006 100644
--- a/examples/cvodes/serial/cvsRoberts_FSA_klu.c
+++ b/examples/cvodes/serial/cvsRoberts_FSA_klu.c
@@ -1,13 +1,22 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date: $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
  *      Based on cvsRoberts_FSA_dns.c and modified to use KLU
  * -----------------------------------------------------------------
- * Example problem:
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2015, Southern Methodist University and 
+ * Lawrence Livermore National Security
  *
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Adjoint sensitivity example problem.
  * The following is a simple example problem, with the coding
  * needed for its solution by CVODES for Forward Sensitivity 
  * Analysis. The problem is from chemical kinetics, and consists
@@ -32,7 +41,7 @@
  * user routine fS (of type SensRhs1Fn).
  * Any of three sensitivity methods (SIMULTANEOUS, STAGGERED, and
  * STAGGERED1) can be used and sensitivities may be included in the
- * error test or not (error control set on TRUE or FALSE,
+ * error test or not (error control set on SUNTRUE or SUNFALSE,
  * respectively).
  *
  * Execution:
@@ -50,21 +59,19 @@
 #include <stdlib.h>
 #include <string.h>
 
-/* Header files with a description of contents used */
-
-#include <cvodes/cvodes.h>             /* prototypes for CVODES fcts. and consts. */
-#include <cvodes/cvodes_klu.h>         /* prototypes for CVKLU fcts. and constants */
-#include <sundials/sundials_sparse.h>  /* definitions SlsMat */
-#include <nvector/nvector_serial.h>    /* defs. of serial NVECTOR fcts. and macros */
-#include <sundials/sundials_types.h>   /* def. of type realtype */
-#include <sundials/sundials_math.h>    /* definition of ABS */
+#include <cvodes/cvodes.h>              /* prototypes for CVODE fcts., consts. */
+#include <nvector/nvector_serial.h>     /* access to serial N_Vector           */
+#include <sunmatrix/sunmatrix_sparse.h> /* access to sparse SUNMatrix          */
+#include <sunlinsol/sunlinsol_klu.h>    /* access to KLU SUNLinearSolver       */
+#include <cvodes/cvodes_direct.h>       /* access to CVDls interface           */
+#include <sundials/sundials_types.h>    /* defs. of realtype, sunindextype     */
+#include <sundials/sundials_math.h>     /* defs. of SUNRabs, SUNRexp, etc.     */
 
 /* Accessor macros */
 /* These macros are defined in order to write code with which exactly matched
-   the mathematical problem description given above.
-*/
+   the mathematical problem description given above. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i=1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component, i=1..NEQ */
 
 /* Problem Constants */
 
@@ -92,16 +99,15 @@ typedef struct {
   realtype p[3];           /* problem parameters */
 } *UserData;
 
-/* Prototypes of functions by CVODES */
+/* Prototypes of user-supplied functions */
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
-static int fS(int Ns, realtype t, N_Vector y, N_Vector ydot, 
-              int iS, N_Vector yS, N_Vector ySdot, 
+static int fS(int Ns, realtype t, N_Vector y, N_Vector ydot,
+              int iS, N_Vector yS, N_Vector ySdot,
               void *user_data, N_Vector tmp1, N_Vector tmp2);
 
 static int ewt(N_Vector y, N_Vector w, void *user_data);
@@ -125,6 +131,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 int main(int argc, char *argv[])
 {
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   UserData data;
   realtype t, tout;
@@ -141,6 +149,8 @@ int main(int argc, char *argv[])
   data      = NULL;
   y         = NULL;
   yS        = NULL;
+  A         = NULL;
+  LS        = NULL;
 
   /* Process arguments */
   ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
@@ -172,22 +182,30 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "CVodeInit", 1)) return(1);
 
   /* Call CVodeWFtolerances to specify a user-supplied function ewt that sets
-     the multiplicative error weights W_i for use in the weighted RMS norm */
+     the multiplicative error weights w_i for use in the weighted RMS norm */
   flag = CVodeWFtolerances(cvode_mem, ewt);
-  if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1);
+  if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1);
 
   /* Attach user data */
   flag = CVodeSetUserData(cvode_mem, data);
   if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVKLU to specify the CVKLU sparse direct linear solver */
-  nnz = NEQ * NEQ;              /* max no. of nonzeros entries in the Jac */
-  flag = CVKLU(cvode_mem, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "CVKLU", 1)) return(1);
+  /* Create sparse SUNMatrix for use in linear solves */
+  nnz = NEQ * NEQ; /* max no. of nonzeros entries in the Jac */
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object */
+  LS = SUNKLU(y, A);
+  if (check_flag((void *)LS, "SUNKLU", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if (check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if (check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   printf("\n3-species chemical kinetics problem\n");
 
@@ -200,8 +218,8 @@ int main(int argc, char *argv[])
     pbar[2] = data->p[2];
 
     /* Set sensitivity initial conditions */
-    yS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)yS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    yS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)yS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);
 
     /* Call CVodeSensInit1 to activate forward sensitivity computations
@@ -277,12 +295,14 @@ int main(int argc, char *argv[])
 
   /* Free memory */
 
-  N_VDestroy_Serial(y);                    /* Free y vector */
+  N_VDestroy(y);                    /* Free y vector */
   if (sensi) {
-    N_VDestroyVectorArray_Serial(yS, NS);  /* Free yS vector */
+    N_VDestroyVectorArray(yS, NS);  /* Free yS vector */
   }
   free(data);                              /* Free user data */
   CVodeFree(&cvode_mem);                   /* Free CVODES memory */
+  SUNLinSolFree(LS);                       /* Free the linear solver memory */
+  SUNMatDestroy(A);                        /* Free the matrix memory */
 
   return(0);
 }
@@ -314,51 +334,56 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   return(0);
 }
 
-
 /* 
  * Jacobian routine. Compute J(t,y). 
  */
 
-static int Jac(realtype t,
-	       N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(y);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(y);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
   
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = -p1;                          rowvals[0] = 0;
-  data[1] = p1;                           rowvals[1] = 1;
-  data[2] = ZERO;                         rowvals[2] = 2;
-
-  data[3] = p2*yval[2];                   rowvals[3] = 0;
-  data[4] = -p2*yval[2]-2*p3*yval[1];     rowvals[4] = 1;
-  data[5] = 2*yval[1];                    rowvals[5] = 2;
+  data[0] = -p1;
+  rowvals[0] = 0;
+  data[1] = p1;
+  rowvals[1] = 1;
+  data[2] = ZERO;
+  rowvals[2] = 2;
+
+  data[3] = p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = -p2*yval[2]-2*p3*yval[1];
+  rowvals[4] = 1;
+  data[5] = 2*yval[1];
+  rowvals[5] = 2;
   
-  data[6] = p2*yval[1];                   rowvals[6] = 0;
-  data[7] = -p2*yval[1];                  rowvals[7] = 1;
-  data[8] = ZERO;                         rowvals[8] = 2;
- 
+  data[6] = p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = -p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ZERO;
+  rowvals[8] = 2;
+
   return(0);
 }
- 
+
 /* 
  * fS routine. Compute sensitivity r.h.s. CVSensRhs1Fn is compatible with any
  * valid value of the argument ism to CVodeSensInit and CVodeSensInit1
@@ -443,16 +468,16 @@ static int ewt(N_Vector y, N_Vector w, void *user_data)
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -471,9 +496,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -499,7 +524,7 @@ static void PrintOutput(void *cvode_mem, realtype t, N_Vector u)
   int qu, flag;
   realtype hu, *udata;
   
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -536,7 +561,7 @@ static void PrintOutputS(N_Vector *uS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(uS[0]);
+  sdata = N_VGetArrayPointer(uS[0]);
   printf("                  Sensitivity 1  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -547,7 +572,7 @@ static void PrintOutputS(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
   
-  sdata = N_VGetArrayPointer_Serial(uS[1]);
+  sdata = N_VGetArrayPointer(uS[1]);
   printf("                  Sensitivity 2  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -558,7 +583,7 @@ static void PrintOutputS(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
 
-  sdata = N_VGetArrayPointer_Serial(uS[2]);
+  sdata = N_VGetArrayPointer(uS[2]);
   printf("                  Sensitivity 3  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -610,7 +635,7 @@ static void PrintFinalStats(void *cvode_mem, booleantype sensi)
     check_flag(&flag, "CVodeGetSensNumNonlinSolvConvFails", 1);
   }
 
-  flag = CVSlsGetNumJacEvals(cvode_mem, &nje);
+  flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
   check_flag(&flag, "CVDlsGetNumJacEvals", 1);
 
   printf("\nFinal Statistics\n\n");
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_klu.out b/examples/cvodes/serial/cvsRoberts_FSA_klu_-sensi_stg1_t.out
similarity index 100%
rename from examples/cvodes/serial/cvsRoberts_FSA_klu.out
rename to examples/cvodes/serial/cvsRoberts_FSA_klu_-sensi_stg1_t.out
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_sps.c b/examples/cvodes/serial/cvsRoberts_FSA_sps.c
index 9644ead..1045017 100644
--- a/examples/cvodes/serial/cvsRoberts_FSA_sps.c
+++ b/examples/cvodes/serial/cvsRoberts_FSA_sps.c
@@ -1,13 +1,22 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date: $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
  *      Based on cvsRoberts_FSA_dns.c and modified to use SUPERLU_MT
  * -----------------------------------------------------------------
- * Example problem:
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2015, Southern Methodist University and 
+ * Lawrence Livermore National Security
  *
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Adjoint sensitivity example problem.
  * The following is a simple example problem, with the coding
  * needed for its solution by CVODES for Forward Sensitivity 
  * Analysis. The problem is from chemical kinetics, and consists
@@ -32,7 +41,7 @@
  * user routine fS (of type SensRhs1Fn).
  * Any of three sensitivity methods (SIMULTANEOUS, STAGGERED, and
  * STAGGERED1) can be used and sensitivities may be included in the
- * error test or not (error control set on TRUE or FALSE,
+ * error test or not (error control set on SUNTRUE or SUNFALSE,
  * respectively).
  *
  * Execution:
@@ -43,28 +52,25 @@
  *    % cvsRoberts_FSA_sps -sensi sensi_meth err_con
  * where sensi_meth is one of {sim, stg, stg1} and err_con is one of
  * {t, f}.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-/* Header files with a description of contents used */
-
-#include <cvodes/cvodes.h>             /* prototypes for CVODES fcts. and consts. */
-#include <cvodes/cvodes_superlumt.h>   /* prototypes for CVSUPERLUMT fcts. and constants */
-#include <sundials/sundials_sparse.h>  /* definitions SlsMat */
-#include <nvector/nvector_serial.h>    /* defs. of serial NVECTOR fcts. and macros */
-#include <sundials/sundials_types.h>   /* def. of type realtype */
-#include <sundials/sundials_math.h>    /* definition of ABS */
+#include <cvodes/cvodes.h>                 /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h> /* access to SuperLUMT SUNLinearSolver  */
+#include <cvodes/cvodes_direct.h>          /* access to CVDls interface            */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 /* These macros are defined in order to write code with which exactly matched
-   the mathematical problem description given above.
-*/
+   the mathematical problem description given above. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i=1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component, i=1..NEQ */
 
 /* Problem Constants */
 
@@ -92,16 +98,15 @@ typedef struct {
   realtype p[3];           /* problem parameters */
 } *UserData;
 
-/* Prototypes of functions by CVODES */
+/* Prototypes of user-supplied functions */
 
 static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
-static int fS(int Ns, realtype t, N_Vector y, N_Vector ydot, 
-              int iS, N_Vector yS, N_Vector ySdot, 
+static int fS(int Ns, realtype t, N_Vector y, N_Vector ydot,
+              int iS, N_Vector yS, N_Vector ySdot,
               void *user_data, N_Vector tmp1, N_Vector tmp2);
 
 static int ewt(N_Vector y, N_Vector w, void *user_data);
@@ -125,6 +130,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 int main(int argc, char *argv[])
 {
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   UserData data;
   realtype t, tout;
@@ -139,8 +146,10 @@ int main(int argc, char *argv[])
 
   cvode_mem = NULL;
   data      = NULL;
-  y         =  NULL;
+  y         = NULL;
   yS        = NULL;
+  A         = NULL;
+  LS        = NULL;
 
   /* Process arguments */
   ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
@@ -172,23 +181,31 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "CVodeInit", 1)) return(1);
 
   /* Call CVodeWFtolerances to specify a user-supplied function ewt that sets
-     the multiplicative error weights W_i for use in the weighted RMS norm */
+     the multiplicative error weights w_i for use in the weighted RMS norm */
   flag = CVodeWFtolerances(cvode_mem, ewt);
-  if (check_flag(&flag, "CVodeSetEwtFn", 1)) return(1);
+  if (check_flag(&flag, "CVodeWFtolerances", 1)) return(1);
 
   /* Attach user data */
   flag = CVodeSetUserData(cvode_mem, data);
   if (check_flag(&flag, "CVodeSetUserData", 1)) return(1);
 
-  /* Call CVKLU to specify the CVKLU sparse direct linear solver */
-  nthreads = 1;                 /* no. of threads to use when factoring the system*/
-  nnz = NEQ * NEQ;              /* max no. of nonzeros entries in the Jac */
-  flag = CVSuperLUMT(cvode_mem, nthreads, NEQ, nnz);
-  if (check_flag(&flag, "CVSuperLUMT", 1)) return(1);
+  /* Create sparse SUNMatrix for use in linear solves */
+  nnz = NEQ * NEQ; /* max no. of nonzeros entries in the Jac */
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if (check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT SUNLinearSolver object */
+  nthreads = 1; /* no. of threads use when factoring the system */
+  LS = SUNSuperLUMT(y, A, nthreads);
+  if (check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if (check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
   /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if (check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   printf("\n3-species chemical kinetics problem\n");
 
@@ -201,8 +218,8 @@ int main(int argc, char *argv[])
     pbar[2] = data->p[2];
 
     /* Set sensitivity initial conditions */
-    yS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)yS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    yS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)yS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);
 
     /* Call CVodeSensInit1 to activate forward sensitivity computations
@@ -278,12 +295,14 @@ int main(int argc, char *argv[])
 
   /* Free memory */
 
-  N_VDestroy_Serial(y);                    /* Free y vector */
+  N_VDestroy(y);                    /* Free y vector */
   if (sensi) {
-    N_VDestroyVectorArray_Serial(yS, NS);  /* Free yS vector */
+    N_VDestroyVectorArray(yS, NS);  /* Free yS vector */
   }
   free(data);                              /* Free user data */
   CVodeFree(&cvode_mem);                   /* Free CVODES memory */
+  SUNLinSolFree(LS);                       /* Free the linear solver memory */
+  SUNMatDestroy(A);                        /* Free the matrix memory */
 
   return(0);
 }
@@ -315,51 +334,56 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   return(0);
 }
 
-
 /* 
  * Jacobian routine. Compute J(t,y). 
  */
 
-static int Jac(realtype t,
-	       N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(y);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(y);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
   
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = -p1;                          rowvals[0] = 0;
-  data[1] = p1;                           rowvals[1] = 1;
-  data[2] = ZERO;                         rowvals[2] = 2;
-
-  data[3] = p2*yval[2];                   rowvals[3] = 0;
-  data[4] = -p2*yval[2]-2*p3*yval[1];     rowvals[4] = 1;
-  data[5] = 2*yval[1];                    rowvals[5] = 2;
+  data[0] = -p1;
+  rowvals[0] = 0;
+  data[1] = p1;
+  rowvals[1] = 1;
+  data[2] = ZERO;
+  rowvals[2] = 2;
+
+  data[3] = p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = -p2*yval[2]-2*p3*yval[1];
+  rowvals[4] = 1;
+  data[5] = 2*yval[1];
+  rowvals[5] = 2;
   
-  data[6] = p2*yval[1];                   rowvals[6] = 0;
-  data[7] = -p2*yval[1];                  rowvals[7] = 1;
-  data[8] = ZERO;                         rowvals[8] = 2;
- 
+  data[6] = p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = -p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ZERO;
+  rowvals[8] = 2;
+
   return(0);
 }
- 
+
 /* 
  * fS routine. Compute sensitivity r.h.s. CVSensRhs1Fn is compatible with any
  * valid value of the argument ism to CVodeSensInit and CVodeSensInit1
@@ -444,16 +468,16 @@ static int ewt(N_Vector y, N_Vector w, void *user_data)
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -472,9 +496,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -500,7 +524,7 @@ static void PrintOutput(void *cvode_mem, realtype t, N_Vector u)
   int qu, flag;
   realtype hu, *udata;
   
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = CVodeGetNumSteps(cvode_mem, &nst);
   check_flag(&flag, "CVodeGetNumSteps", 1);
@@ -537,7 +561,7 @@ static void PrintOutputS(N_Vector *uS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(uS[0]);
+  sdata = N_VGetArrayPointer(uS[0]);
   printf("                  Sensitivity 1  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -548,7 +572,7 @@ static void PrintOutputS(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
   
-  sdata = N_VGetArrayPointer_Serial(uS[1]);
+  sdata = N_VGetArrayPointer(uS[1]);
   printf("                  Sensitivity 2  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -559,7 +583,7 @@ static void PrintOutputS(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
 
-  sdata = N_VGetArrayPointer_Serial(uS[2]);
+  sdata = N_VGetArrayPointer(uS[2]);
   printf("                  Sensitivity 3  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -611,7 +635,7 @@ static void PrintFinalStats(void *cvode_mem, booleantype sensi)
     check_flag(&flag, "CVodeGetSensNumNonlinSolvConvFails", 1);
   }
 
-  flag = CVSlsGetNumJacEvals(cvode_mem, &nje);
+  flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
   check_flag(&flag, "CVDlsGetNumJacEvals", 1);
 
   printf("\nFinal Statistics\n\n");
diff --git a/examples/cvodes/serial/cvsRoberts_FSA_sps.out b/examples/cvodes/serial/cvsRoberts_FSA_sps_-sensi_stg1_t.out
similarity index 100%
rename from examples/cvodes/serial/cvsRoberts_FSA_sps.out
rename to examples/cvodes/serial/cvsRoberts_FSA_sps_-sensi_stg1_t.out
diff --git a/examples/cvodes/serial/cvsRoberts_dns.c b/examples/cvodes/serial/cvsRoberts_dns.c
index c5293bb..9d2d3a7 100644
--- a/examples/cvodes/serial/cvsRoberts_dns.c
+++ b/examples/cvodes/serial/cvsRoberts_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -20,23 +16,21 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVDENSE dense linear solver, and a
+ * Newton iteration with the SUNDENSE dense linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvodes/cvodes.h>           /* prototypes for CVODE fcts. and consts. */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., and macros */
-#include <cvodes/cvodes_dense.h>     /* prototype for CVDense */
-#include <sundials/sundials_dense.h> /* definitions DlsMat DENSE_ELEM */
-#include <sundials/sundials_types.h> /* definition of type realtype */
+#include <cvodes/cvodes.h>             /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <cvodes/cvodes_direct.h>      /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macros: Ith, IJth */
 
@@ -50,11 +44,11 @@
 
    IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
    i and j are in the range [1..NEQ]. The IJth macro is defined using the
-   DENSE_ELEM macro in dense.h. DENSE_ELEM numbers rows and columns of a
-   dense matrix starting from 0. */
+   SM_ELEMENT_D macro in dense.h. SM_ELEMENT_D numbers rows and columns of 
+   a dense matrix starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
 
 
 /* Problem Constants */
@@ -72,6 +66,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -79,9 +74,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -96,6 +90,10 @@ static void PrintFinalStats(void *cvode_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
+/* Private function to check computed solution */
+
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol);
+
 
 /*
  *-------------------------------
@@ -107,11 +105,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -152,13 +154,21 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVDense to specify the CVDENSE dense linear solver */
-  flag = CVDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVDense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object for use by CVode */
+  LS = SUNDenseLinearSolver(y, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -187,13 +197,23 @@ int main()
   /* Print some final statistics */
   PrintFinalStats(cvode_mem);
 
-  /* Free y vector */
-  N_VDestroy_Serial(y);
+  /* check the solution error */
+  flag = check_ans(y, t, reltol, abstol);
+
+  /* Free y and abstol vectors */
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
-  return(0);
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
+  return(flag);
 }
 
 
@@ -239,9 +259,8 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
 
@@ -250,10 +269,14 @@ static int Jac(long int N, realtype t,
   IJth(J,1,1) = RCONST(-0.04);
   IJth(J,1,2) = RCONST(1.0e4)*y3;
   IJth(J,1,3) = RCONST(1.0e4)*y2;
+
   IJth(J,2,1) = RCONST(0.04); 
   IJth(J,2,2) = RCONST(-1.0e4)*y3-RCONST(6.0e7)*y2;
   IJth(J,2,3) = RCONST(-1.0e4)*y2;
+
+  IJth(J,3,1) = ZERO;
   IJth(J,3,2) = RCONST(6.0e7)*y2;
+  IJth(J,3,3) = ZERO;
 
   return(0);
 }
@@ -357,3 +380,49 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
 
   return(0);
 }
+
+/* compare the solution at the final time 4e10s to a reference solution computed
+   using a relative tolerance of 1e-8 and absoltue tolerance of 1e-14 */
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol)
+{
+  int      passfail=0;        /* answer pass (0) or fail (1) flag */  
+  N_Vector ref;               /* reference solution vector        */
+  N_Vector ewt;               /* error weight vector              */
+  realtype err;               /* wrms error                       */
+  realtype ONE=RCONST(1.0);  
+
+  /* create reference solution and error weight vectors */
+  ref = N_VClone(y);
+  ewt = N_VClone(y);
+
+  /* set the reference solution data */
+  NV_Ith_S(ref,0) = RCONST(5.2083495894337328e-08);
+  NV_Ith_S(ref,1) = RCONST(2.0833399429795671e-13);
+  NV_Ith_S(ref,2) = RCONST(9.9999994791629776e-01);
+
+  /* compute the error weight vector, loosen atol */
+  N_VAbs(ref, ewt);
+  N_VLinearSum(rtol, ewt, RCONST(10.0), atol, ewt);
+  if (N_VMin(ewt) <= ZERO) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: check_ans failed - ewt <= 0\n\n");
+    return(-1);
+  }
+  N_VInv(ewt, ewt);   
+
+  /* compute the solution error */
+  N_VLinearSum(ONE, y, -ONE, ref, ref);
+  err = N_VWrmsNorm(ref, ewt);
+
+  /* is the solution within the tolerances? */
+  passfail = (err < ONE) ? 0 : 1; 
+
+  if (passfail) {
+    fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%g \n\n", err);
+  }
+
+  /* Free vectors */
+  N_VDestroy(ref);
+  N_VDestroy(ewt);
+
+  return(passfail);
+}
diff --git a/examples/cvodes/serial/cvsRoberts_dns.out b/examples/cvodes/serial/cvsRoberts_dns.out
index 8ef3495..be6ded6 100644
--- a/examples/cvodes/serial/cvsRoberts_dns.out
+++ b/examples/cvodes/serial/cvsRoberts_dns.out
@@ -5,20 +5,20 @@ At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
 At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
 At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
-At t = 4.0000e+01      y =  7.158010e-01    9.185084e-06    2.841898e-01
-At t = 4.0000e+02      y =  4.504693e-01    3.222627e-06    5.495274e-01
-At t = 4.0000e+03      y =  1.832126e-01    8.943459e-07    8.167865e-01
-At t = 4.0000e+04      y =  3.897839e-02    1.621552e-07    9.610214e-01
-At t = 4.0000e+05      y =  4.940533e-03    1.985905e-08    9.950594e-01
-At t = 4.0000e+06      y =  5.170046e-04    2.069075e-09    9.994830e-01
-At t = 2.0803e+07      y =  1.000000e-04    4.000395e-10    9.999000e-01
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168093e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.199610e-05    2.079951e-10    9.999480e-01
-At t = 4.0000e+08      y =  5.200133e-06    2.080064e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.131179e-07    2.052473e-12    9.999995e-01
-At t = 4.0000e+10      y =  5.470287e-08    2.188115e-13    9.999999e-01
+At t = 4.0000e+07      y =  5.202440e-05    2.081083e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.201061e-06    2.080435e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.258603e-07    2.103442e-12    9.999995e-01
+At t = 4.0000e+10      y =  6.934511e-08    2.773804e-13    9.999999e-01
 
 Final Statistics:
-nst = 566    nfe  = 817    nsetups = 119    nfeLS = 0      nje = 12
-nni = 813    ncfn = 0      netf = 32     nge = 600
+nst = 542    nfe  = 755    nsetups = 107    nfeLS = 0      nje = 11
+nni = 751    ncfn = 0      netf = 22     nge = 570
  
diff --git a/examples/cvodes/serial/cvsRoberts_dnsL.c b/examples/cvodes/serial/cvsRoberts_dnsL.c
index d369f1b..d1beb49 100644
--- a/examples/cvodes/serial/cvsRoberts_dnsL.c
+++ b/examples/cvodes/serial/cvsRoberts_dnsL.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -24,16 +20,16 @@
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvodes/cvodes.h>           /* prototypes for CVODE fcts. and consts. */
-#include <cvodes/cvodes_lapack.h>    /* prototype for CVLapackDense */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., and macros */
+#include <cvodes/cvodes.h>                   /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>          /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h>       /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_lapackdense.h> /* access to dense SUNLinearSolver      */
+#include <cvodes/cvodes_direct.h>            /* access to CVDls interface            */
+#include <sundials/sundials_types.h>         /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macros: Ith, IJth */
 
@@ -47,11 +43,11 @@
 
    IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
    i and j are in the range [1..NEQ]. The IJth macro is defined using the
-   DENSE_ELEM macro in dense.h. DENSE_ELEM numbers rows and columns of a
-   dense matrix starting from 0. */
+   SM_ELEMENT_D macro in dense.h. SM_ELEMENT_D numbers rows and columns of 
+   a dense matrix starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)              /* Ith numbers components 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
 
 
 /* Problem Constants */
@@ -77,10 +73,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -106,11 +100,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -151,16 +149,24 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVLapackDense to specify the LAPACK dense linear solver */
-  flag = CVLapackDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVLapackDense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create SUNLapackDense solver object for use by CVode */
+  LS = SUNLapackDense(y, A);
+  if(check_flag((void *)LS, "SUNLapackDense", 0)) return(1);
+
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
-   * Break out of loop when NOUT preset output times have been reached.  */
+     Break out of loop when NOUT preset output times have been reached.  */
   printf(" \n3-species kinetics problem\n\n");
 
   iout = 0;  tout = T1;
@@ -186,12 +192,19 @@ int main()
   /* Print some final statistics */
   PrintFinalStats(cvode_mem);
 
-  /* Free y vector */
-  N_VDestroy_Serial(y);
+  /* Free y and abstol vectors */
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -238,10 +251,8 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
 
diff --git a/examples/cvodes/serial/cvsRoberts_dnsL.out b/examples/cvodes/serial/cvsRoberts_dnsL.out
index 0e27ff1..be6ded6 100644
--- a/examples/cvodes/serial/cvsRoberts_dnsL.out
+++ b/examples/cvodes/serial/cvsRoberts_dnsL.out
@@ -5,20 +5,20 @@ At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
 At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
 At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
-At t = 4.0000e+01      y =  7.158010e-01    9.185084e-06    2.841898e-01
-At t = 4.0000e+02      y =  4.504693e-01    3.222627e-06    5.495274e-01
-At t = 4.0000e+03      y =  1.832126e-01    8.943459e-07    8.167865e-01
-At t = 4.0000e+04      y =  3.897839e-02    1.621552e-07    9.610214e-01
-At t = 4.0000e+05      y =  4.940533e-03    1.985905e-08    9.950594e-01
-At t = 4.0000e+06      y =  5.170046e-04    2.069075e-09    9.994830e-01
-At t = 2.0803e+07      y =  1.000000e-04    4.000395e-10    9.999000e-01
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168093e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.199601e-05    2.079947e-10    9.999480e-01
-At t = 4.0000e+08      y =  5.221400e-06    2.088571e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.217838e-07    2.087137e-12    9.999995e-01
-At t = 4.0000e+10      y =  5.466519e-08    2.186608e-13    9.999999e-01
+At t = 4.0000e+07      y =  5.202440e-05    2.081083e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.201061e-06    2.080435e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.258603e-07    2.103442e-12    9.999995e-01
+At t = 4.0000e+10      y =  6.934511e-08    2.773804e-13    9.999999e-01
 
 Final Statistics:
-nst = 595    nfe  = 857    nsetups = 125    nfeLS = 0      nje = 12
-nni = 853    ncfn = 0      netf = 34     nge = 629
+nst = 542    nfe  = 755    nsetups = 107    nfeLS = 0      nje = 11
+nni = 751    ncfn = 0      netf = 22     nge = 570
  
diff --git a/examples/cvodes/serial/cvsRoberts_dns_uw.c b/examples/cvodes/serial/cvsRoberts_dns_uw.c
index c90efd5..527a479 100644
--- a/examples/cvodes/serial/cvsRoberts_dns_uw.c
+++ b/examples/cvodes/serial/cvsRoberts_dns_uw.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -20,25 +16,23 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVDENSE dense linear solver, and a
+ * Newton iteration with the SUNDENSE dense linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a user-supplied function to compute the error weights
  * required for the WRMS norm calculations.
  * Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used here */
-
-#include <cvodes/cvodes.h>           /* prototypes for CVODE fcts. and consts. */
-#include <cvodes/cvodes_dense.h>     /* prototype for CVDense */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, functions, and macros */
-#include <sundials/sundials_dense.h> /* definitions DlsMat and DENSE_ELEM */
-#include <sundials/sundials_types.h> /* definition of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS */
+#include <cvodes/cvodes.h>             /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <cvodes/cvodes_direct.h>      /* access to CVDls interface            */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* definition of ABS                    */
 
 /* User-defined vector and matrix accessor macros: Ith, IJth */
 
@@ -52,11 +46,11 @@
 
    IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
    i and j are in the range [1..NEQ]. The IJth macro is defined using the
-   DENSE_ELEM macro in dense.h. DENSE_ELEM numbers rows and columns of a
-   dense matrix starting from 0. */
+   SM_ELEMENT_D macro in dense.h. SM_ELEMENT_D numbers rows and columns of 
+   a dense matrix starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* IJth numbers rows,cols 1..NEQ */
 
 
 /* Problem Constants */
@@ -74,6 +68,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -81,9 +76,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 static int ewt(N_Vector y, N_Vector w, void *user_data);
 
@@ -111,11 +105,15 @@ int main()
 {
   realtype t, tout;
   N_Vector y;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout;
   int rootsfound[2];
 
   y = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. */
@@ -146,13 +144,21 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVDense to specify the CVDENSE dense linear solver */
-  flag = CVDense(cvode_mem, NEQ);
-  if (check_flag(&flag, "CVDense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object for use by CVode */
+  LS = SUNDenseLinearSolver(y, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVDlsSetDenseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVDlsSetDenseJacFn", 1)) return(1);
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -165,7 +171,7 @@ int main()
 
     if (flag == CV_ROOT_RETURN) {
       flagr = CVodeGetRootInfo(cvode_mem, rootsfound);
-      check_flag(&flagr, "CVodeGetRootInfo", 1);
+      if (check_flag(&flagr, "CVodeGetRootInfo", 1)) return(1);
       PrintRootInfo(rootsfound[0],rootsfound[1]);
     }
 
@@ -182,11 +188,17 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free y vector */
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -211,7 +223,7 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
   yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
         Ith(ydot,2) = -yd1 - yd3;
 
-  return(0);      
+  return(0);
 }
 
 /*
@@ -233,9 +245,8 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(long int N, realtype t,
-               N_Vector y, N_Vector fy, DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y1, y2, y3;
 
@@ -244,10 +255,14 @@ static int Jac(long int N, realtype t,
   IJth(J,1,1) = RCONST(-0.04);
   IJth(J,1,2) = RCONST(1.0e4)*y3;
   IJth(J,1,3) = RCONST(1.0e4)*y2;
+
   IJth(J,2,1) = RCONST(0.04); 
   IJth(J,2,2) = RCONST(-1.0e4)*y3-RCONST(6.0e7)*y2;
   IJth(J,2,3) = RCONST(-1.0e4)*y2;
+
+  IJth(J,3,1) = ZERO;
   IJth(J,3,2) = RCONST(6.0e7)*y2;
+  IJth(J,3,3) = ZERO;
 
   return(0);
 }
diff --git a/examples/cvodes/serial/cvsRoberts_dns_uw.out b/examples/cvodes/serial/cvsRoberts_dns_uw.out
index 14add0b..be6ded6 100644
--- a/examples/cvodes/serial/cvsRoberts_dns_uw.out
+++ b/examples/cvodes/serial/cvsRoberts_dns_uw.out
@@ -5,20 +5,20 @@ At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
 At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
 At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
-At t = 4.0000e+01      y =  7.158010e-01    9.185084e-06    2.841898e-01
-At t = 4.0000e+02      y =  4.504693e-01    3.222627e-06    5.495274e-01
-At t = 4.0000e+03      y =  1.832126e-01    8.943459e-07    8.167865e-01
-At t = 4.0000e+04      y =  3.897840e-02    1.621553e-07    9.610214e-01
-At t = 4.0000e+05      y =  4.941626e-03    1.986351e-08    9.950584e-01
-At t = 4.0000e+06      y =  5.162295e-04    2.065971e-09    9.994838e-01
-At t = 2.0789e+07      y =  1.000000e-04    4.000395e-10    9.999000e-01
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168093e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.201354e-05    2.080648e-10    9.999480e-01
-At t = 4.0000e+08      y =  5.215272e-06    2.086119e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.213021e-07    2.085210e-12    9.999995e-01
-At t = 4.0000e+10      y =  4.958738e-08    1.983495e-13    1.000000e-00
+At t = 4.0000e+07      y =  5.202440e-05    2.081083e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.201061e-06    2.080435e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.258603e-07    2.103442e-12    9.999995e-01
+At t = 4.0000e+10      y =  6.934511e-08    2.773804e-13    9.999999e-01
 
 Final Statistics:
-nst = 534    nfe  = 796    nsetups = 127    nfeLS = 0      nje = 12
-nni = 792    ncfn = 0      netf = 35     nge = 564
+nst = 542    nfe  = 755    nsetups = 107    nfeLS = 0      nje = 11
+nni = 751    ncfn = 0      netf = 22     nge = 570
  
diff --git a/examples/cvodes/serial/cvsRoberts_klu.c b/examples/cvodes/serial/cvsRoberts_klu.c
index 0d1106c..bbd08e4 100644
--- a/examples/cvodes/serial/cvsRoberts_klu.c
+++ b/examples/cvodes/serial/cvsRoberts_klu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward.
  *      Based on cvRoberts_dns.c and modified to use KLU.
  * -----------------------------------------------------------------
@@ -20,23 +16,21 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVKLU sparse direct linear solver, and a
+ * Newton iteration with the KLU sparse direct linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvodes/cvodes.h>             /* prototypes for CVODE fcts., consts. */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <cvodes/cvodes_klu.h>         /* prototype for CVKLU */
-#include <sundials/sundials_sparse.h> /* definitions SlsMat */
-#include <sundials/sundials_types.h> /* definition of type realtype */
+#include <cvodes/cvodes.h>              /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>     /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h> /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>    /* access to KLU sparse direct solver   */
+#include <cvodes/cvodes_direct.h>       /* access to CVDls interface            */
+#include <sundials/sundials_types.h>    /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macro: Ith */
 
@@ -46,16 +40,13 @@
    Ith(v,i) references the ith component of the vector v, where i is in
    the range [1..NEQ] and NEQ is defined below. The Ith macro is defined
    using the N_VIth macro in nvector.h. N_VIth numbers the components of
-   a vector starting from 0.
-*/
+   a vector starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
 
 
 /* Problem Constants */
 
-#define ZERO  RCONST(0.0)
-
 #define NEQ   3                /* number of equations  */
 #define Y1    RCONST(1.0)      /* initial y components */
 #define Y2    RCONST(0.0)
@@ -69,6 +60,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -76,9 +68,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -104,11 +95,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout, nnz;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -149,14 +144,22 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVKLU to specify the CVKLU sparse direct linear solver */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = CVKLU(cvode_mem, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "CVKLU", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU solver object for use by CVode */
+  LS = SUNKLU(y, A);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -186,12 +189,18 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free y and abstol vectors */
-  N_VDestroy_Serial(y);
-  N_VDestroy_Serial(abstol);
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -238,21 +247,17 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
   
-  yval = N_VGetArrayPointer_Serial(y);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data    = JacMat->data;
+  yval = N_VGetArrayPointer(y);
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
@@ -331,8 +336,8 @@ static void PrintFinalStats(void *cvode_mem)
   flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
   check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
 
-  flag = CVSlsGetNumJacEvals(cvode_mem, &nje);
-  check_flag(&flag, "CVSlsGetNumJacEvals", 1);
+  flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
+  check_flag(&flag, "CVDlsGetNumJacEvals", 1);
 
   flag = CVodeGetNumGEvals(cvode_mem, &nge);
   check_flag(&flag, "CVodeGetNumGEvals", 1);
diff --git a/examples/cvodes/serial/cvsRoberts_klu.out b/examples/cvodes/serial/cvsRoberts_klu.out
index 776406f..d34a8ee 100644
--- a/examples/cvodes/serial/cvsRoberts_klu.out
+++ b/examples/cvodes/serial/cvsRoberts_klu.out
@@ -3,22 +3,22 @@
 
 At t = 2.6391e-01      y =  9.899653e-01    3.470564e-05    1.000000e-02
     rootsfound[] =   0   1
-At t = 4.0000e-01      y =  9.851640e-01    3.386245e-05    1.480209e-02
-At t = 4.0000e+00      y =  9.055156e-01    2.240441e-05    9.446197e-02
-At t = 4.0000e+01      y =  7.158508e-01    9.186546e-06    2.841400e-01
-At t = 4.0000e+02      y =  4.505784e-01    3.223707e-06    5.494184e-01
-At t = 4.0000e+03      y =  1.832290e-01    8.944054e-07    8.167701e-01
-At t = 4.0000e+04      y =  3.898012e-02    1.621625e-07    9.610197e-01
-At t = 4.0000e+05      y =  4.936714e-03    1.984363e-08    9.950633e-01
-At t = 4.0000e+06      y =  5.164962e-04    2.067039e-09    9.994835e-01
-At t = 2.0784e+07      y =  1.000000e-04    4.000395e-10    9.999000e-01
+At t = 4.0000e-01      y =  9.851641e-01    3.386242e-05    1.480205e-02
+At t = 4.0000e+00      y =  9.055097e-01    2.240338e-05    9.446793e-02
+At t = 4.0000e+01      y =  7.158017e-01    9.185037e-06    2.841892e-01
+At t = 4.0000e+02      y =  4.505360e-01    3.223271e-06    5.494608e-01
+At t = 4.0000e+03      y =  1.832299e-01    8.944378e-07    8.167692e-01
+At t = 4.0000e+04      y =  3.898902e-02    1.622006e-07    9.610108e-01
+At t = 4.0000e+05      y =  4.936383e-03    1.984224e-08    9.950636e-01
+At t = 4.0000e+06      y =  5.168094e-04    2.068293e-09    9.994832e-01
+At t = 2.0790e+07      y =  1.000000e-04    4.000397e-10    9.999000e-01
     rootsfound[] =  -1   0
-At t = 4.0000e+07      y =  5.202874e-05    2.081257e-10    9.999480e-01
-At t = 4.0000e+08      y =  5.206719e-06    2.082698e-11    9.999948e-01
-At t = 4.0000e+09      y =  5.208794e-07    2.083519e-12    9.999995e-01
-At t = 4.0000e+10      y =  5.244455e-08    2.097782e-13    9.999999e-01
+At t = 4.0000e+07      y =  5.202445e-05    2.081085e-10    9.999480e-01
+At t = 4.0000e+08      y =  5.194853e-06    2.077952e-11    9.999948e-01
+At t = 4.0000e+09      y =  5.088353e-07    2.035342e-12    9.999995e-01
+At t = 4.0000e+10      y =  4.817809e-08    1.927124e-13    1.000000e+00
 
 Final Statistics:
-nst = 430    nfe  = 574    nsetups = 98     nje = 78
-nni = 570    ncfn = 0      netf = 23        nge = 466
+nst = 533    nfe  = 744    nsetups = 105    nje = 11
+nni = 740    ncfn = 0      netf = 20        nge = 561
  
diff --git a/examples/cvodes/serial/cvsRoberts_sps.c b/examples/cvodes/serial/cvsRoberts_sps.c
index 46ef255..eb207e3 100644
--- a/examples/cvodes/serial/cvsRoberts_sps.c
+++ b/examples/cvodes/serial/cvsRoberts_sps.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Rev $
- * $Date $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward.
  *      Based on cvRoberts_dns.c and modified to use SUPERLU_MT.
  * -----------------------------------------------------------------
@@ -20,23 +16,21 @@
  * While integrating the system, we also use the rootfinding
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01. This program solves the problem with the BDF method,
- * Newton iteration with the CVSUPERLUMT sparse direct linear solver, and a
+ * Newton iteration with the SuperLUMT sparse direct linear solver, and a
  * user-supplied Jacobian routine.
  * It uses a scalar relative tolerance and a vector absolute
  * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
  * Run statistics (optional outputs) are printed at the end.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 
-/* Header files with a description of contents used */
-
-#include <cvodes/cvodes.h>             /* prototypes for CVODE fcts., consts. */
-#include <nvector/nvector_serial.h>  /* serial N_Vector types, fcts., macros */
-#include <cvodes/cvodes_superlumt.h>   /* prototype for CVSUPERLUMT */
-#include <sundials/sundials_sparse.h> /* definitions SlsMat */
-#include <sundials/sundials_types.h> /* definition of type realtype */
+#include <cvodes/cvodes.h>                  /* prototypes for CVODE fcts., consts.  */
+#include <nvector/nvector_serial.h>         /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>     /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h>  /* access to SuperLUMT linear solver    */
+#include <cvodes/cvodes_direct.h>           /* access to CVDls interface            */
+#include <sundials/sundials_types.h>        /* defs. of realtype, sunindextype      */
 
 /* User-defined vector and matrix accessor macro: Ith */
 
@@ -46,16 +40,13 @@
    Ith(v,i) references the ith component of the vector v, where i is in
    the range [1..NEQ] and NEQ is defined below. The Ith macro is defined
    using the N_VIth macro in nvector.h. N_VIth numbers the components of
-   a vector starting from 0.
-*/
+   a vector starting from 0. */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* Ith numbers components 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* Ith numbers components 1..NEQ */
 
 
 /* Problem Constants */
 
-#define ZERO  RCONST(0.0)
-
 #define NEQ   3                /* number of equations  */
 #define Y1    RCONST(1.0)      /* initial y components */
 #define Y2    RCONST(0.0)
@@ -69,6 +60,7 @@
 #define TMULT RCONST(10.0)     /* output time factor     */
 #define NOUT  12               /* number of output times */
 
+#define ZERO  RCONST(0.0)
 
 /* Functions Called by the Solver */
 
@@ -76,9 +68,8 @@ static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
 
 static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 /* Private functions to output results */
 
@@ -104,11 +95,15 @@ int main()
 {
   realtype reltol, t, tout;
   N_Vector y, abstol;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   void *cvode_mem;
   int flag, flagr, iout, nnz;
   int rootsfound[2];
 
   y = abstol = NULL;
+  A = NULL;
+  LS = NULL;
   cvode_mem = NULL;
 
   /* Create serial vector of length NEQ for I.C. and abstol */
@@ -149,14 +144,22 @@ int main()
   flag = CVodeRootInit(cvode_mem, 2, g);
   if (check_flag(&flag, "CVodeRootInit", 1)) return(1);
 
-  /* Call CVSuperLUMT to specify the CVSuperLUMT sparse direct linear solver */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = CVSuperLUMT(cvode_mem, 1, NEQ, nnz);
-  if (check_flag(&flag, "CVSuperLUMT", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT solver object for use by CVode (one thread) */
+  LS = SUNSuperLUMT(y, A, 1);
+  if(check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
 
-  /* Set the Jacobian routine to Jac (user-supplied) */
-  flag = CVSlsSetSparseJacFn(cvode_mem, Jac);
-  if (check_flag(&flag, "CVSlsSetSparseJacFn", 1)) return(1);
+  /* Call CVDlsSetLinearSolver to attach the matrix and linear solver to CVode */
+  flag = CVDlsSetLinearSolver(cvode_mem, LS, A);
+  if(check_flag(&flag, "CVDlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine Jac */
+  flag = CVDlsSetJacFn(cvode_mem, Jac);
+  if(check_flag(&flag, "CVDlsSetJacFn", 1)) return(1);
 
   /* In loop, call CVode, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached.  */
@@ -186,12 +189,18 @@ int main()
   PrintFinalStats(cvode_mem);
 
   /* Free y and abstol vectors */
-  N_VDestroy_Serial(y);
-  N_VDestroy_Serial(abstol);
+  N_VDestroy(y);
+  N_VDestroy(abstol);
 
   /* Free integrator memory */
   CVodeFree(&cvode_mem);
 
+  /* Free the linear solver memory */
+  SUNLinSolFree(LS);
+
+  /* Free the matrix memory */
+  SUNMatDestroy(A);
+
   return(0);
 }
 
@@ -238,42 +247,42 @@ static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
  * Jacobian routine. Compute J(t,y) = df/dy. *
  */
 
-static int Jac(realtype t,
-               N_Vector y, N_Vector fy, SlsMat JacMat, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J, 
+               void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int *colptrs = *JacMat->colptrs;
-  int *rowvals = *JacMat->rowvals;
-
-  yval = N_VGetArrayPointer_Serial(y);
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
+  
+  yval = N_VGetArrayPointer(y);
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(J);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  JacMat->data[0] = RCONST(-0.04);
+  data[0] = RCONST(-0.04);
   rowvals[0] = 0;
-  JacMat->data[1] = RCONST(0.04);
+  data[1] = RCONST(0.04);
   rowvals[1] = 1;
-  JacMat->data[2] = ZERO;
+  data[2] = ZERO;
   rowvals[2] = 2;
 
-  JacMat->data[3] = RCONST(1.0e4)*yval[2];
+  data[3] = RCONST(1.0e4)*yval[2];
   rowvals[3] = 0;
-  JacMat->data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]);
+  data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]);
   rowvals[4] = 1;
-  JacMat->data[5] = RCONST(6.0e7)*yval[1];
+  data[5] = RCONST(6.0e7)*yval[1];
   rowvals[5] = 2;
 
-  JacMat->data[6] = RCONST(1.0e4)*yval[1];
+  data[6] = RCONST(1.0e4)*yval[1];
   rowvals[6] = 0;
-  JacMat->data[7] = RCONST(-1.0e4)*yval[1];
+  data[7] = RCONST(-1.0e4)*yval[1];
   rowvals[7] = 1;
-  JacMat->data[8] = ZERO;
+  data[8] = ZERO;
   rowvals[8] = 2;
 
   return(0);
@@ -327,8 +336,8 @@ static void PrintFinalStats(void *cvode_mem)
   flag = CVodeGetNumNonlinSolvConvFails(cvode_mem, &ncfn);
   check_flag(&flag, "CVodeGetNumNonlinSolvConvFails", 1);
 
-  flag = CVSlsGetNumJacEvals(cvode_mem, &nje);
-  check_flag(&flag, "CVSlsGetNumJacEvals", 1);
+  flag = CVDlsGetNumJacEvals(cvode_mem, &nje);
+  check_flag(&flag, "CVDlsGetNumJacEvals", 1);
 
   flag = CVodeGetNumGEvals(cvode_mem, &nge);
   check_flag(&flag, "CVodeGetNumGEvals", 1);
diff --git a/examples/ida/C_openmp/CMakeLists.txt b/examples/ida/C_openmp/CMakeLists.txt
index 2ed6996..eedb069 100644
--- a/examples/ida/C_openmp/CMakeLists.txt
+++ b/examples/ida/C_openmp/CMakeLists.txt
@@ -1,95 +1,93 @@
 # ---------------------------------------------------------------
-# $Revision:  $
-# $Date:  $
-# ---------------------------------------------------------------
 # Programmer: Ting Yan @ SMU
 # ---------------------------------------------------------------
-# LLNS Copyright Start
-# Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
-# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2015, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
-# LLNS Copyright End
-# ---------------------------------------------------------------
-# CMakeLists.txt file for the IDA OpenMP examples
+# LLNS/SMU Copyright End
+# Copyright (c) 2013, Southern Methodist University.
+# All rights reserved.
+# For details, see the LICENSE file.
+# -----------------------------------------------------------------
+# CMakeLists.txt file for IDA OpenMP examples
+# -----------------------------------------------------------------
 
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if OpenMP is enabled
 IF(OPENMP_FOUND)
-  # Add variable ida_examples with the names of the openmp IDA examples
+
+  # Examples using SUNDIALS linear solvers
   SET(IDA_examples
-    idaFoodWeb_bnd_omp
-    idaFoodWeb_kry_omp
+    "idaFoodWeb_bnd_omp\;4\;develop"
+    "idaFoodWeb_kry_omp\;4\;develop"
     )
 
-  SET(IDA_examples_BL
-  )
 ENDIF(OPENMP_FOUND)
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECS_LIB sundials_nvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECS_LIB sundials_nvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
-
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${IDA_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-IF(PETSC_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_FOUND)
 
+# update the compilation flags to include OpenMP support
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 
-# Add the build and install targets for each IDA example
 
-FOREACH(example ${IDA_examples})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${IDA_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} TEST_ARGS 4)
+
+  IF (NOT ${example} MATCHES "idaFoodWeb_kry_omp")
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+  ENDIF()
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/C_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${IDA_examples})
-
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
-
-IF(LAPACK_FOUND)
-  FOREACH(example ${IDA_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.c)
-    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example} TEST_ARGS 4)
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-    IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/C_openmp)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${IDA_examples_BL})
-ENDIF(LAPACK_FOUND)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/C_openmp)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${IDA_examples})
+
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -98,33 +96,30 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
-  LIST2STRING(IDA_examples EXAMPLES)
-  IF(LAPACK_FOUND)
-    LIST2STRING(IDA_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
-    SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
-  
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
-  
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+
+  EXAMPLES2STRING(IDA_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/C_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/C_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/C_openmp/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/C_openmp 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/C_openmp
     )
 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
   IF(UNIX)
     # generate Makefile and place it in the binary dir
     CONFIGURE_FILE(
@@ -134,7 +129,7 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/ida/C_openmp/Makefile_ex 
+      FILES ${PROJECT_BINARY_DIR}/examples/ida/C_openmp/Makefile_ex
       DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/C_openmp
       RENAME Makefile
       )
diff --git a/examples/ida/C_openmp/README b/examples/ida/C_openmp/README
index e2b5f94..44a1a0a 100644
--- a/examples/ida/C_openmp/README
+++ b/examples/ida/C_openmp/README
@@ -8,7 +8,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/ida/C_openmp/idaFoodWeb_bnd_omp.c b/examples/ida/C_openmp/idaFoodWeb_bnd_omp.c
index 5250a6d..a8190bb 100644
--- a/examples/ida/C_openmp/idaFoodWeb_bnd_omp.c
+++ b/examples/ida/C_openmp/idaFoodWeb_bnd_omp.c
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
- * Programmer(s): Ting Yan @ SMU
+ * Programmer(s): Daniel R. Reynolds and Ting Yan @ SMU
  *      Based on idaFoodWeb_bnd.c and parallelized with OpenMP
  * -----------------------------------------------------------------
  * Example program for IDA: Food web problem.
  *
- * This example program (OpenMP version) uses the IDABAND linear 
+ * This example program (OpenMP version) uses the SUNBAND linear 
  * solver, and IDACalcIC for initial condition calculation.
  *
  * The mathematical problem solved in this example is a DAE system
@@ -62,7 +59,7 @@
  * The PDEs are discretized by central differencing on a MX by MY
  * mesh.
  *
- * The DAE system is solved by IDA using the IDABAND linear solver.
+ * The DAE system is solved by IDA using the SUNBAND linear solver.
  * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
  *
  * Optionally, we can set the number of threads from environment 
@@ -72,12 +69,12 @@
  *
  * Execution:
  *
- * If the user want to use the default value or the number of threads 
- * from environment value:
+ * To use the default value for the number of threads from 
+ * the OMP_NUM_THREADS environment value:
  *      % ./idaFoodWeb_bnd_omp 
- * If the user want to specify the number of threads to use
+ * To specify the number of threads at the command line, use
  *      % ./idaFoodWeb_bnd_omp num_threads
- * where num_threads is the number of threads the user want to use 
+ * where num_threads is the desired number of threads. 
  *
  * -----------------------------------------------------------------
  * References:
@@ -103,9 +100,11 @@
 #include <math.h>
 
 #include <ida/ida.h>
-#include <ida/ida_band.h>
+#include <ida/ida_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 #include <nvector/nvector_openmp.h>
-#include <sundials/sundials_dense.h>
+#include <sundials/sundials_direct.h>
 #include <sundials/sundials_types.h>
 
 #ifdef _OPENMP
@@ -155,7 +154,7 @@
 /* Type: UserData.  Contains problem constants, etc. */
 
 typedef struct {
-  long int Neq, ns, np, mx, my;
+  sunindextype Neq, ns, np, mx, my;
   realtype dx, dy, **acoef;
   realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
   N_Vector rates;
@@ -172,13 +171,13 @@ static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval,
 static void InitUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata);
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol);
-static void PrintOutput(void *mem, N_Vector c, realtype t);
-static void PrintFinalStats(void *mem);
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol);
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t);
+static void PrintFinalStats(void *ida_mem);
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate, UserData webdata);
 static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                      UserData webdata);
-static realtype dotprod(long int size, realtype *x1, realtype *x2);
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, char *funcname, int opt);
 
 /*
@@ -189,15 +188,19 @@ static int check_flag(void *flagvalue, char *funcname, int opt);
 
 int main(int argc, char *argv[])
 { 
-  void *mem;
+  void *ida_mem;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   UserData webdata;
   N_Vector cc, cp, id;
   int iout, retval;
-  long int mu, ml;
+  sunindextype mu, ml, smu;
   realtype rtol, atol, t0, tout, tret;
   int num_threads;
 
-  mem = NULL;
+  ida_mem = NULL;
+  A = NULL;
+  LS = NULL;
   webdata = NULL;
   cc = cp = id = NULL;
 
@@ -239,46 +242,51 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize IDA. */
   
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+  ida_mem = IDACreate();
+  if(check_flag((void *) ida_mem, "IDACreate", 0)) return(1);
 
-  retval = IDASetUserData(mem, webdata);
+  retval = IDASetUserData(ida_mem, webdata);
   if(check_flag(&retval, "IDASetUserData", 1)) return(1);
 
-  retval = IDASetId(mem, id);
+  retval = IDASetId(ida_mem, id);
   if(check_flag(&retval, "IDASetId", 1)) return(1);
 
-  retval = IDAInit(mem, resweb, t0, cc, cp);
+  retval = IDAInit(ida_mem, resweb, t0, cc, cp);
   if(check_flag(&retval, "IDAInit", 1)) return(1);
 
-  retval = IDASStolerances(mem, rtol, atol);
+  retval = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1)) return(1);
 
-  /* Call IDABand to specify the IDA linear solver. */
+  /* Setup band matrix and linear solver, and attach to IDA. */
 
   mu = ml = NSMX;
-  retval = IDABand(mem, NEQ, mu, ml);
-  if(check_flag(&retval, "IDABand", 1)) return(1);
+  smu = mu+ml;
+  A = SUNBandMatrix(NEQ, mu, ml, smu);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+  LS = SUNBandLinearSolver(cc, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+  retval = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
   tout = RCONST(0.001);
-  retval = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  retval = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&retval, "IDACalcIC", 1)) return(1);
   
   /* Print heading, basic parameters, and initial values. */
 
   PrintHeader(mu, ml, rtol, atol);
-  PrintOutput(mem, cc, ZERO);
+  PrintOutput(ida_mem, cc, ZERO);
   
   /* Loop over iout, call IDASolve (normal mode), print selected output. */
   
   for (iout = 1; iout <= NOUT; iout++) {
     
-    retval = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    retval = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if(check_flag(&retval, "IDASolve", 1)) return(retval);
     
-    PrintOutput(mem, cc, tret);
+    PrintOutput(ida_mem, cc, tret);
     
     if (iout < 3) tout *= TMULT; else tout += TADD;
     
@@ -286,13 +294,15 @@ int main(int argc, char *argv[])
   
   /* Print final statistics and free memory. */  
   
-  PrintFinalStats(mem);
+  PrintFinalStats(ida_mem);
   printf("num_threads = %i\n\n", num_threads);
 
   /* Free memory */
 
-  IDAFree(&mem);
-
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  
   N_VDestroy_OpenMP(cc);
   N_VDestroy_OpenMP(cp);
   N_VDestroy_OpenMP(id);
@@ -328,7 +338,7 @@ int main(int argc, char *argv[])
 static int resweb(realtype tt, N_Vector cc, N_Vector cp, 
                   N_Vector res,  void *user_data)
 {
-  long int jx, jy, is, yloc, loc, np;
+  sunindextype jx, jy, is, yloc, loc, np;
   realtype *resv, *cpv;
   UserData webdata;
   
@@ -343,7 +353,7 @@ static int resweb(realtype tt, N_Vector cc, N_Vector cp,
   
   /* Loop over all grid points, setting residual values appropriately
      for differential or algebraic components.                        */
-#pragma omp parallel for default(shared) private(jy, yloc, jx, loc, is) schedule(static) 
+#pragma omp parallel for default(shared) private(jy, yloc, jx, loc, is) schedule(static) num_threads(webdata->nthreads)
   for (jy = 0; jy < MY; jy++) {
     yloc = NSMX * jy;
     for (jx = 0; jx < MX; jx++) {
@@ -424,7 +434,7 @@ static void InitUserData(UserData webdata)
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata)
 {
-  long int loc, yloc, is, jx, jy, np;
+  sunindextype loc, yloc, is, jx, jy, np;
   realtype xx, yy, xyfactor;
   realtype *ccv, *cpv, *idv;
   
@@ -475,7 +485,7 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol)
 {
   printf("\nidaFoodWeb_bnd_omp: Predator-prey DAE OpenMP example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
@@ -488,7 +498,8 @@ static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDABAND,  Band parameters mu = %ld, ml = %ld\n",mu,ml);
+  printf("Linear solver: SUNBAND,  Band parameters mu = %ld, ml = %ld\n",
+         (long int) mu, (long int) ml);
   printf("CalcIC called to correct initial predator concentrations.\n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -503,17 +514,17 @@ static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
  * are printed for the bottom left and top right grid points only.  
  */
 
-static void PrintOutput(void *mem, N_Vector c, realtype t)
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t)
 {
   int i, kused, flag;
   long int nst;
   realtype *c_bl, *c_tr, hused;
 
-  flag = IDAGetLastOrder(mem, &kused);
+  flag = IDAGetLastOrder(ida_mem, &kused);
   check_flag(&flag, "IDAGetLastOrder", 1);
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDAGetLastStep(mem, &hused);
+  flag = IDAGetLastStep(ida_mem, &hused);
   check_flag(&flag, "IDAGetLastStep", 1);
   
   c_bl = IJ_Vptr(c,0,0);
@@ -543,24 +554,24 @@ static void PrintOutput(void *mem, N_Vector c, realtype t)
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 { 
   long int nst, nre, nreLS, nni, nje, netf, ncfn;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1);
-  flag = IDADlsGetNumJacEvals(mem, &nje);
+  flag = IDADlsGetNumJacEvals(ida_mem, &nje);
   check_flag(&flag, "IDADlsGetNumJacEvals", 1);
-  flag = IDADlsGetNumResEvals(mem, &nreLS);
+  flag = IDADlsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDADlsGetNumResEvals", 1);
 
   printf("-----------------------------------------------------------\n");
@@ -584,7 +595,7 @@ static void PrintFinalStats(void *mem)
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,  
                  UserData webdata)
 { 
-  long int jx, jy, is, idyu, idyl, idxu, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxu, idxl;
   realtype xx, yy, *cxy, *ratesxy, *cratexy, dcyli, dcyui, dcxli, dcxui;
   
   /* Loop over grid points, evaluate interaction vector (length ns),
@@ -607,7 +618,7 @@ static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,
       WebRates(xx, yy, cxy, ratesxy, webdata);
       
       /* Loop over species, do differencing, load crate segment. */
-#pragma omp parallel for default(shared) private(is, dcyli, dcyui, dcxli, dcxui) schedule(static)
+#pragma omp parallel for default(shared) private(is, dcyli, dcyui, dcxli, dcxui) schedule(static) num_threads(webdata->nthreads)
       for (is = 0; is < NUM_SPECIES; is++) {
         
         /* Differencing in y. */
@@ -653,9 +664,9 @@ static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
  * dotprod: dot product routine for realtype arrays, for use by WebRates.    
  */
 
-static realtype dotprod(long int size, realtype *x1, realtype *x2)
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
diff --git a/examples/ida/C_openmp/idaFoodWeb_bnd_omp.out b/examples/ida/C_openmp/idaFoodWeb_bnd_omp.out
index b7f432d..31992d1 100644
--- a/examples/ida/C_openmp/idaFoodWeb_bnd_omp.out
+++ b/examples/ida/C_openmp/idaFoodWeb_bnd_omp.out
@@ -3,7 +3,7 @@ idaFoodWeb_bnd_omp: Predator-prey DAE OpenMP example problem for IDA
 
 Number of species ns: 2     Mesh dimensions: 20 x 20     System size: 800
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDABAND,  Band parameters mu = 40, ml = 40
+Linear solver: SUNBAND,  Band parameters mu = 40, ml = 40
 CalcIC called to correct initial predator concentrations.
 
 -----------------------------------------------------------
diff --git a/examples/ida/C_openmp/idaFoodWeb_kry_omp.c b/examples/ida/C_openmp/idaFoodWeb_kry_omp.c
index dfc4c27..d440314 100644
--- a/examples/ida/C_openmp/idaFoodWeb_kry_omp.c
+++ b/examples/ida/C_openmp/idaFoodWeb_kry_omp.c
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
- * Programmer(s): Ting Yan @ SMU
+ * Programmer(s): Daniel R. Reynolds and Ting Yan @ SMU
  * -----------------------------------------------------------------
  * Example program for IDA: Food web problem, OpenMP, GMRES, 
  * user-supplied preconditioner
  *
- * This example program uses the IDASPGMR as the linear 
+ * This example program uses SUNSPGMR as the linear 
  * solver, and IDACalcIC for initial condition calculation.
  *
  * The mathematical problem solved in this example is a DAE system
@@ -62,7 +59,7 @@
  * The PDEs are discretized by central differencing on a MX by MY
  * mesh.
  *
- * The DAE system is solved by IDA using the IDABAND linear solver.
+ * The DAE system is solved by IDA using the SUNSPGMR linear solver.
  * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
  *
  * Optionally, we can set the number of threads from environment 
@@ -72,12 +69,12 @@
  *
  * Execution:
  *
- * If the user want to use the default value or the number of threads 
- * from environment value:
+ * To use the default value for the number of threads from 
+ * the OMP_NUM_THREADS environment value:
  *      % ./idaFoodWeb_kry_omp 
- * If the user want to specify the number of threads to use
+ * To specify the number of threads at the command line, use
  *      % ./idaFoodWeb_kry_omp num_threads
- * where num_threads is the number of threads the user want to use 
+ * where num_threads is the desired number of threads. 
  *
  * -----------------------------------------------------------------
  * References:
@@ -103,7 +100,8 @@
 #include <math.h>
 
 #include <ida/ida.h>
-#include <ida/ida_spgmr.h>
+#include <ida/ida_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_openmp.h>
 #include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
@@ -156,11 +154,11 @@
 /* Type: UserData.  Contains problem constants, etc. */
 
 typedef struct {
-  long int Neq, ns, np, mx, my;
+  sunindextype Neq, ns, np, mx, my;
   realtype dx, dy, **acoef;
   realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
   realtype **PP[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   N_Vector rates;
   N_Vector ewt;
   void *ida_mem;
@@ -172,29 +170,25 @@ typedef struct {
 static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval, 
                   void *user_data);
 
-static int Precond(realtype tt,
-		   N_Vector cc, N_Vector cp, N_Vector rr, 
-		   realtype cj, void *user_data,
-		   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Precond(realtype tt, N_Vector cc, N_Vector cp,
+                   N_Vector rr, realtype cj, void *user_data);
 
-static int PSolve(realtype tt, 
-		  N_Vector cc, N_Vector cp, N_Vector rr,
-		  N_Vector rvec, N_Vector zvec,
-		  realtype cj, realtype delta, void *user_data,
-		  N_Vector tmp);
+static int PSolve(realtype tt, N_Vector cc, N_Vector cp,
+                  N_Vector rr, N_Vector rvec, N_Vector zvec,
+		  realtype cj, realtype delta, void *user_data);
 
 /* Prototypes for private Helper Functions. */
 
 static void InitUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata);
-static void PrintHeader(long int maxl, realtype rtol, realtype atol);
-static void PrintOutput(void *mem, N_Vector c, realtype t);
-static void PrintFinalStats(void *mem);
+static void PrintHeader(int maxl, realtype rtol, realtype atol);
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t);
+static void PrintFinalStats(void *ida_mem);
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate, UserData webdata);
 static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                      UserData webdata);
-static realtype dotprod(long int size, realtype *x1, realtype *x2);
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, char *funcname, int opt);
 
 /*
@@ -205,15 +199,17 @@ static int check_flag(void *flagvalue, char *funcname, int opt);
 
 int main(int argc, char *argv[])
 { 
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData webdata;
   N_Vector cc, cp, id;
   int iout, jx, jy, flag;
-  long int maxl;
+  int maxl;
   realtype rtol, atol, t0, tout, tret;
   int num_threads;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   webdata = NULL;
   cc = cp = id = NULL;
 
@@ -233,7 +229,7 @@ int main(int argc, char *argv[])
   webdata->ewt = N_VNew_OpenMP(NEQ, num_threads);
   for (jx = 0; jx < MX; jx++) {
     for (jy = 0; jy < MY; jy++) {
-      (webdata->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (webdata->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
       (webdata->PP)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
     }
   }
@@ -262,51 +258,55 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize IDA. */
   
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0)) return(1);
 
-  flag = IDASetUserData(mem, webdata);
+  flag = IDASetUserData(ida_mem, webdata);
   if(check_flag(&flag, "IDASetUserData", 1)) return(1);
 
-  flag = IDASetId(mem, id);
+  flag = IDASetId(ida_mem, id);
   if(check_flag(&flag, "IDASetId", 1)) return(1);
 
-  flag = IDAInit(mem, resweb, t0, cc, cp);
+  flag = IDAInit(ida_mem, resweb, t0, cc, cp);
   if(check_flag(&flag, "IDAInit", 1)) return(1);
 
-  flag = IDASStolerances(mem, rtol, atol);
+  flag = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&flag, "IDASStolerances", 1)) return(1);
 
-  webdata->ida_mem = mem;
+  webdata->ida_mem = ida_mem;
 
-  /* Call IDASpgmr to specify the IDA linear solver. */
+  /* Create SUNSPGMR linear solver, attach to IDA, and set 
+     preconditioning routines. */
 
-  maxl = 16;                    /* max dimension of the Krylov subspace */
-  flag = IDASpgmr(mem, maxl);
-  if(check_flag(&flag, "IDASpgmr", 1)) return(1);
+  maxl = 16;                               /* max dimension of the Krylov subspace */
+  LS = SUNSPGMR(cc, PREC_LEFT, maxl);      /* IDA only allows left preconditioning */
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
 
-  flag = IDASpilsSetPreconditioner(mem, Precond, PSolve);
+  flag = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&flag, "IDASpilsSetLinearSolver", 1)) return(1);
+
+  flag = IDASpilsSetPreconditioner(ida_mem, Precond, PSolve);
   if(check_flag(&flag, "IDASpilsSetPreconditioner", 1)) return(1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
   tout = RCONST(0.001);
-  flag = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  flag = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&flag, "IDACalcIC", 1)) return(1);
   
   /* Print heading, basic parameters, and initial values. */
 
   PrintHeader(maxl, rtol, atol);
-  PrintOutput(mem, cc, ZERO);
+  PrintOutput(ida_mem, cc, ZERO);
   
   /* Loop over iout, call IDASolve (normal mode), print selected output. */
   
   for (iout = 1; iout <= NOUT; iout++) {
     
-    flag = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    flag = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if(check_flag(&flag, "IDASolve", 1)) return(flag);
     
-    PrintOutput(mem, cc, tret);
+    PrintOutput(ida_mem, cc, tret);
     
     if (iout < 3) tout *= TMULT; else tout += TADD;
     
@@ -314,12 +314,13 @@ int main(int argc, char *argv[])
   
   /* Print final statistics and free memory. */  
   
-  PrintFinalStats(mem);
+  PrintFinalStats(ida_mem);
   printf("num_threads = %i\n\n", num_threads);
 
   /* Free memory */
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   N_VDestroy_OpenMP(cc);
   N_VDestroy_OpenMP(cp);
@@ -363,7 +364,7 @@ int main(int argc, char *argv[])
 static int resweb(realtype tt, N_Vector cc, N_Vector cp, 
                   N_Vector res,  void *user_data)
 {
-  long int jx, jy, is, yloc, loc, np;
+  sunindextype jx, jy, is, yloc, loc, np;
   realtype *resv, *cpv;
   UserData webdata;
   
@@ -397,17 +398,15 @@ static int resweb(realtype tt, N_Vector cc, N_Vector cp,
 }
 
 
-static int Precond(realtype tt, 
-		   N_Vector cc, N_Vector cp, N_Vector rr, 
-		   realtype cj, void *user_data,
-		   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Precond(realtype tt, N_Vector cc, N_Vector cp,
+                   N_Vector rr, realtype cj, void *user_data)
 {
   int flag;
   realtype uround, xx, yy, del_x, del_y;
   realtype **Pxy, *ratesxy, *Pxycol, *cxy, *cpxy, *ewtxy, cctmp;
   realtype inc, fac, sqru, perturb_rates[NUM_SPECIES];
   int is, js, jx, jy, ret;
-  void *mem;
+  void *ida_mem;
   N_Vector ewt;
   realtype hh;
   UserData webdata;
@@ -419,11 +418,11 @@ static int Precond(realtype tt,
   uround = UNIT_ROUNDOFF;
   sqru = SUNRsqrt(uround);
 
-  mem = webdata->ida_mem;
+  ida_mem = webdata->ida_mem;
   ewt = webdata->ewt;
-  flag = IDAGetErrWeights(mem, ewt);
+  flag = IDAGetErrWeights(ida_mem, ewt);
   if(check_flag(&flag, "IDAGetErrWeights", 1)) return(1);
-  flag = IDAGetCurrentStep(mem, &hh);
+  flag = IDAGetCurrentStep(ida_mem, &hh);
   if(check_flag(&flag, "IDAGetCurrentStep", 1)) return(1);
 
   for (jy = 0; jy < MY; jy++) {
@@ -466,14 +465,12 @@ static int Precond(realtype tt,
 }
 
 
-static int PSolve(realtype tt, 
-		  N_Vector cc, N_Vector cp, N_Vector rr, 
-		  N_Vector rvec, N_Vector zvec,
-		  realtype cj, realtype dalta, 
-		  void *user_data, N_Vector tmp) 
+static int PSolve(realtype tt, N_Vector cc, N_Vector cp,
+                  N_Vector rr, N_Vector rvec, N_Vector zvec,
+		  realtype cj, realtype dalta, void *user_data) 
 {
   realtype **Pxy, *zxy;
-  long int *pivot;
+  sunindextype *pivot;
   int jx, jy;
   UserData webdata;
   
@@ -560,7 +557,7 @@ static void InitUserData(UserData webdata)
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata)
 {
-  long int loc, yloc, is, jx, jy, np;
+  sunindextype loc, yloc, is, jx, jy, np;
   realtype xx, yy, xyfactor;
   realtype *ccv, *cpv, *idv;
   
@@ -611,7 +608,7 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int maxl, realtype rtol, realtype atol)
+static void PrintHeader(int maxl, realtype rtol, realtype atol)
 {
   printf("\nidaFoodWeb_kry_omp: Predator-prey DAE OpenMP example problem using Krylov solver for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
@@ -624,7 +621,7 @@ static void PrintHeader(long int maxl, realtype rtol, realtype atol)
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASpgmr,  Spgmr parameters maxl = %ld\n",maxl);
+  printf("Linear solver: SUNSPGMR, maxl = %d\n",maxl);
   printf("CalcIC called to correct initial predator concentrations.\n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -639,17 +636,17 @@ static void PrintHeader(long int maxl, realtype rtol, realtype atol)
  * are printed for the bottom left and top right grid points only.  
  */
 
-static void PrintOutput(void *mem, N_Vector c, realtype t)
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t)
 {
   int i, kused, flag;
   long int nst;
   realtype *c_bl, *c_tr, hused;
 
-  flag = IDAGetLastOrder(mem, &kused);
+  flag = IDAGetLastOrder(ida_mem, &kused);
   check_flag(&flag, "IDAGetLastOrder", 1);
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDAGetLastStep(mem, &hused);
+  flag = IDAGetLastStep(ida_mem, &hused);
   check_flag(&flag, "IDAGetLastStep", 1);
   
   c_bl = IJ_Vptr(c,0,0);
@@ -679,24 +676,24 @@ static void PrintOutput(void *mem, N_Vector c, realtype t)
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 { 
   long int nst, nre, sli, netf, nps, npevals, nrevalsLS;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDASpilsGetNumLinIters(mem, &sli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &sli);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1);
-  flag = IDASpilsGetNumPrecEvals(mem, &npevals);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npevals);
   check_flag(&flag, "IDADlsGetNumJacEvals", 1);
-  flag = IDASpilsGetNumResEvals(mem, &nrevalsLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nrevalsLS);
   check_flag(&flag, "IDADlsGetNumResEvals", 1);
 
   printf("-----------------------------------------------------------\n");
@@ -720,7 +717,7 @@ static void PrintFinalStats(void *mem)
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,  
                  UserData webdata)
 { 
-  long int jx, jy, is, idyu, idyl, idxu, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxu, idxl;
   realtype xx, yy, *cxy, *ratesxy, *cratexy, dcyli, dcyui, dcxli, dcxui;
   
   /* Loop over grid points, evaluate interaction vector (length ns),
@@ -789,9 +786,9 @@ static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
  * dotprod: dot product routine for realtype arrays, for use by WebRates.    
  */
 
-static realtype dotprod(long int size, realtype *x1, realtype *x2)
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
diff --git a/examples/ida/fcmix_openmp/CMakeLists.txt b/examples/ida/fcmix_openmp/CMakeLists.txt
index 92c4829..5b89ae0 100644
--- a/examples/ida/fcmix_openmp/CMakeLists.txt
+++ b/examples/ida/fcmix_openmp/CMakeLists.txt
@@ -1,104 +1,88 @@
 # ---------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for the FIDA opemp examples
+# CMakeLists.txt file for FIDA opemp examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if OpenMP is enabled
 IF(OPENMP_FOUND)
 
-# Add variable ida_examples with the names of the openmp FIDA examples
-SET(FIDA_examples
-  fidaRoberts_dns_openmp
-  )
-
-# Add variable FIDA_examples_BL with the names of the openmp FIDA examples
-# that use Lapack
+  # Examples using SUNDIALS linear solvers
+  SET(FIDA_examples
+    "fidaRoberts_dns_openmp\;\;develop"
+    )
 
-SET(FIDA_examples_BL
-  )
 ENDIF(OPENMP_FOUND)
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECS_LIB sundials_nvecopenmp_static)
   SET(FNVECS_LIB sundials_fnvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECS_LIB sundials_nvecopenmp_shared)
   SET(FNVECS_LIB sundials_fnvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FIDA_LIB sundials_fida_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FIDA_LIB} ${IDA_LIB} ${FNVECS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-IF(PETSC_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_FOUND)
 
+# update the compilation flags to include OpenMP support
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 
-# Add the build and install targets for each FIDA example
 
-FOREACH(example ${FIDA_examples})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FIDA_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    TEST_ARGS ${example_args}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${FIDA_examples})
-
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
-
-IF(LAPACK_FOUND)
-  FOREACH(example ${FIDA_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.f)
-    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-    IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_openmp)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FIDA_examples_BL})
-ENDIF(LAPACK_FOUND)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_openmp)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${FIDA_examples})
+
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -108,30 +92,30 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
   SET(SOLVER_FLIB "sundials_fida")
-  LIST2STRING(FIDA_examples EXAMPLES)
-  IF(LAPACK_FOUND)
-    LIST2STRING(FIDA_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
-    SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+
+  EXAMPLES2STRING(FIDA_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/fcmix_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/fcmix_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_openmp/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_openmp 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_openmp
     )
 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
   IF(UNIX)
     # generate Makefile and place it in the binary dir
     CONFIGURE_FILE(
@@ -141,7 +125,7 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_openmp/Makefile_ex 
+      FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_openmp/Makefile_ex
       DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_openmp
       RENAME Makefile
       )
diff --git a/examples/ida/fcmix_openmp/README b/examples/ida/fcmix_openmp/README
index dbbf3af..c49ad5c 100644
--- a/examples/ida/fcmix_openmp/README
+++ b/examples/ida/fcmix_openmp/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/ida/fcmix_openmp/fidaRoberts_dns_openmp.f b/examples/ida/fcmix_openmp/fidaRoberts_dns_openmp.f
index 834309f..6d1936e 100644
--- a/examples/ida/fcmix_openmp/fidaRoberts_dns_openmp.f
+++ b/examples/ida/fcmix_openmp/fidaRoberts_dns_openmp.f
@@ -1,6 +1,20 @@
-c     ----------------------------------------------------------------
-c     $Revision: 4392 $
-c     $Date: 2015-02-25 17:22:27 -0800 (Wed, 25 Feb 2015) $
+C     ----------------------------------------------------------------
+C     Programmer(s): Daniel R. Reynolds @ SMU
+C                 Steve Smith, Eddy Banks and Alan C. Hindmarsh @ LLNL      
+C     ----------------------------------------------------------------
+C     LLNS/SMU Copyright Start
+C     Copyright (c) 2017, Southern Methodist University and 
+C     Lawrence Livermore National Security
+C
+C     This work was performed under the auspices of the U.S. Department 
+C     of Energy by Southern Methodist University and Lawrence Livermore 
+C     National Laboratory under Contract DE-AC52-07NA27344.
+C     Produced at Southern Methodist University and the Lawrence 
+C     Livermore National Laboratory.
+C
+C     All rights reserved.
+C     For details, see the LICENSE file.
+C     LLNS/SMU Copyright End
 c     ----------------------------------------------------------------
 c     This simple example problem for FIDA, due to Robertson, is from 
 c     chemical kinetics, and consists of the following three equations:
@@ -25,8 +39,7 @@ c
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*8 neq
-      integer*8 iout(25), ipar
+      integer*8 neq, iout(25), ipar
       integer ier, ierroot, info(2)
       double precision rout(10), rpar
       integer iatol, nout, jout, itask
@@ -88,10 +101,36 @@ c Initialize rootfinding problem
          stop
       endif
 c
-c Attach dense linear solver
+c Attach dense matrix and linear solver
 c
-      call fidadense(neq, ier)
+      call fsundensematinit(2, neq, neq, ier)
+      if (ier .ne. 0) then
+         write(6,30) ier
+ 30      format(///' SUNDIALS_ERROR: FSUNDENSEMATINIT IER = ', i5)
+         call fidafree
+         stop
+      endif
+      call fsundenselinsolinit(2, ier)
+      if (ier .ne. 0) then
+         write(6,33) ier
+ 33      format(///' SUNDIALS_ERROR: FSUNDENSELINSOLINIT IER = ', i5)
+         call fidafree
+         stop
+      endif
+      call fidadlsinit(ier)
+      if (ier .ne. 0) then
+         write(6,35) ier
+ 35      format(///' SUNDIALS_ERROR: FIDADLSINIT returned IER = ', i5)
+         call fidafree
+         stop
+      endif
       call fidadensesetjac(1, ier)
+      if (ier .ne. 0) then
+         write(6,37) ier
+ 37      format(///' SUNDIALS_ERROR: FIDADENSESETJAC IER = ', i5)
+         call fidafree
+         stop
+      endif
 c
 c Print header
 c
@@ -121,7 +160,7 @@ c
         if (ier .eq. 2) then
           call fidarootinfo(2, info, ierroot)
           if (ierroot .lt. 0) then
-            write(6,55) ier
+            write(6,55) ierroot
  55         format(///' SUNDIALS_ERROR: FIDAROOTINFO returned IER = ',
      1             i5)
             call fidarootfree
@@ -158,7 +197,7 @@ c
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*4 ipar(*)
+      integer*8 ipar(*)
       integer reserr
       double precision tres, rpar(*)
       double precision y(*), yp(*), res(*)
@@ -181,7 +220,7 @@ c
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*4 neq, ipar(*)
+      integer*8 neq, ipar(*)
       integer djacerr
       double precision t, h, cj, rpar(*)
       double precision y(*), yp(*), r(*), ewt(*), jac(neq,neq)
@@ -209,7 +248,7 @@ c Fortran routine for rootfinding
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*4 ipar(*)
+      integer*8 ipar(*)
       integer ier
       double precision t, y(*), yp(*), g(*), rpar(*)
 c
diff --git a/examples/ida/fcmix_parallel/CMakeLists.txt b/examples/ida/fcmix_parallel/CMakeLists.txt
index e3104a8..efeb1e9 100644
--- a/examples/ida/fcmix_parallel/CMakeLists.txt
+++ b/examples/ida/fcmix_parallel/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,81 +12,83 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the FIDA parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable ida_examples with the names of the parallel IDA examples
-
+# Examples using SUNDIALS linear solvers
 SET(FIDA_examples
-  "fidaHeat2D_kry_bbd_p\;1\;4"
+  "fidaHeat2D_kry_bbd_p\;1\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the Fortran compiler to the MPIF77 script.
 # If not, then add the MPI include directory for MPI headers.
-
-IF(MPI_MPIF77 )
+IF(MPI_MPIF77)
   # use MPI_MPIF77 as the compiler
   SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
-ELSE(MPI_MPIF77)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPIF77)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
   SET(FNVECP_LIB sundials_fnvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
   SET(FNVECP_LIB sundials_fnvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FIDA_LIB sundials_fida_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FIDA_LIB} ${IDA_LIB} ${FNVECP_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-IF(PETSC_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_FOUND)
-
-# Add the build and install targets for each IDA example
 
+# Add the build and install targets for each example
 FOREACH(example_tuple ${FIDA_examples})
+
   list(GET example_tuple 0 example)
   list(GET example_tuple 1 number_of_nodes)
   list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  list(GET example_tuple 3 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPIF77)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPIF77)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${FIDA_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -99,30 +98,28 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
   SET(SOLVER_FLIB "sundials_fida")
-  FOREACH(example_tuple ${FIDA_examples})
-    list(GET example_tuple 0 example)
-    LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${FIDA_examples})
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(FIDA_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/fcmix_parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/fcmix_parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -135,7 +132,7 @@ IF(EXAMPLES_INSTALL)
     # install the configured Makefile_ex as Makefile
     INSTALL(
       FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_parallel/Makefile_ex
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_parallel
       RENAME Makefile
       )
   ENDIF(UNIX)
diff --git a/examples/ida/fcmix_parallel/README b/examples/ida/fcmix_parallel/README
index 1c065c8..9eddae9 100644
--- a/examples/ida/fcmix_parallel/README
+++ b/examples/ida/fcmix_parallel/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f
index 00083ea..8721287 100644
--- a/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f
+++ b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.f
@@ -1,12 +1,26 @@
-c     ----------------------------------------------------------------
-c     $Revision: 4830 $
-c     $Date: 2016-07-27 17:50:35 -0700 (Wed, 27 Jul 2016) $
+C     ----------------------------------------------------------------
+C     Programmer(s): Daniel R. Reynolds @ SMU
+C                 Radu Serban and Alan C. Hindmarsh @ LLNL      
+C     ----------------------------------------------------------------
+C     LLNS/SMU Copyright Start
+C     Copyright (c) 2017, Southern Methodist University and 
+C     Lawrence Livermore National Security
+C
+C     This work was performed under the auspices of the U.S. Department 
+C     of Energy by Southern Methodist University and Lawrence Livermore 
+C     National Laboratory under Contract DE-AC52-07NA27344.
+C     Produced at Southern Methodist University and the Lawrence 
+C     Livermore National Laboratory.
+C
+C     All rights reserved.
+C     For details, see the LICENSE file.
+C     LLNS/SMU Copyright End
 c     ----------------------------------------------------------------
 c     Example problem for FIDA: 2D heat equation, parallel, GMRES,
 c     IDABBDPRE.
 c
 c     This example solves a discretized 2D heat equation problem.
-c     This version uses the Krylov solver IDASPGMR and BBD
+c     This version uses the Krylov solver SUNSPGMR and BBD
 c     preconditioning.
 c
 c     The DAE system solved is a spatial discretization of the PDE
@@ -23,7 +37,7 @@ c     processor, with an MXSUB by MYSUB mesh on each of NPEX * NPEY
 c     processors.
 c
 c     The system is solved with FIDA using the Krylov linear solver
-c     IDASPGMR in conjunction with the preconditioner module IDABBDPRE.
+c     SUNSPGMR in conjunction with the preconditioner module IDABBDPRE.
 c     The preconditioner uses a tridiagonal approximation
 c     (half-bandwidths = 1). The constraints u >= 0 are posed for all
 c     components. Local error testing on the boundary values is
@@ -51,10 +65,10 @@ c The following declaration specification should match C type long int.
       double precision rout(10), rpar(1)
       integer nout, ier
       parameter (nout = 11)
-      integer npes, inopt, maxl, gstype, maxrs, itask, iatol
+      integer npes, inopt, maxl, maxrs, itask, iatol
       integer nlocalg
       parameter (nlocalg = mxsubg*mysubg)
-      double precision t0, t1, tout, tret, dqrely, eplifac, dqincfac
+      double precision t0, t1, tout, tret, dqrely
       double precision atol, rtol
       double precision constr(nlocalg), uu(nlocalg), up(nlocalg)
       double precision res(nlocalg), id(nlocalg)
@@ -84,10 +98,7 @@ c
       mlkeep = 1
       dqrely = 0.0d0
       maxl = 0
-      gstype = 0
       maxrs = 0
-      eplifac = 0.0d0
-      dqincfac = 0.0d0
       itask = 1
       iatol = 1
 c
@@ -157,22 +168,37 @@ c
       call fidasetiin('SUPPRESS_ALG', 1, ier)
       call fidasetvin('ID_VEC', id, ier)
       call fidasetvin('CONSTR_VEC', constr, ier)
-
 c
-c Initialize and attach BBDSPGMR module
+c Initialize and attach SUNSPGMR solver
 c
-      call fidaspgmr(maxl, gstype, maxrs, eplifac, dqincfac, ier)
+      call fsunspgmrinit(2, 1, maxl, ier)
+      if (ier .ne. 0) then
+         write(*,8) ier
+ 8       format(///' SUNDIALS_ERROR: FSUNSPGMRINIT returned IER = ', i5)
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+      call fsunspgmrsetmaxrs(2, 5, ier)
       if (ier .ne. 0) then
          write(*,9) ier
- 9       format(///' SUNDIALS_ERROR: FIDABBDSPGMR returned IER = ', i5)
+ 9       format(///' SUNDIALS_ERROR: FSUNSPGMRSETMAXRS IER = ', i5)
          call mpi_abort(mpi_comm_world, 1, ier)
          stop
       endif
+      call fidaspilsinit(ier)
+      if (ier .ne. 0) then
+         write(*,10) ier
+ 10       format(///' SUNDIALS_ERROR: FIDASPILSINIT IER = ', i5)
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+c
+c Initialize and attach BBD preconditioner module
 c
       call fidabbdinit(nlocal, mudq, mldq, mukeep, mlkeep, dqrely, ier)
       if (ier .ne. 0) then
-         write(*,8) ier
- 8       format(///' SUNDIALS_ERROR: FIDABBDINIT returned IER = ', i5)
+         write(*,11) ier
+ 11       format(///' SUNDIALS_ERROR: FIDABBDINIT returned IER = ', i5)
          call mpi_abort(mpi_comm_world, 1, ier)
          stop
       endif
@@ -185,22 +211,22 @@ c
       endif
 c
       tout = t1
-      do 10 jout = 1, nout
+      do 12 jout = 1, nout
 c
          call fidasolve(tout, tret, uu, up, itask, ier)
 c
          call prntoutput(tret, uu, iout, rout)
 c
          if (ier .ne. 0) then
-            write(*,11) ier
- 11         format(///' SUNDIALS_ERROR: FIDASOLVE returned IER = ', i5)
+            write(*,13) ier
+ 13         format(///' SUNDIALS_ERROR: FIDASOLVE returned IER = ', i5)
             call fidafree
             stop
          endif
 c
          tout = tout*2.0d0
 c
- 10   continue
+ 12   continue
 c
 c Print statistics
 c
@@ -217,14 +243,14 @@ c
 c
       call fidareinit(t0, uu, up, iatol, rtol, atol, ier)
       if (ier .ne. 0) then
-         write(*,33) ier
- 33      format(///' SUNDIALS_ERROR: FIDAREINIT returned IER = ', i5)
+         write(*,43) ier
+ 43      format(///' SUNDIALS_ERROR: FIDAREINIT returned IER = ', i5)
       endif
 c
       call fidabbdreinit(nlocal, mudq, mldq, dqrely, ier)
       if (ier .ne. 0) then
-         write(*,34) ier
- 34      format(///' SUNDIALS_ERROR: FIDABBDREINIT returned IER = ', i5)
+         write(*,44) ier
+ 44      format(///' SUNDIALS_ERROR: FIDABBDREINIT returned IER = ', i5)
          call fidafree
          stop
       endif
@@ -236,22 +262,22 @@ c
       endif
 c
       tout = t1
-      do 12 jout = 1, nout
+      do 14 jout = 1, nout
 c
          call fidasolve(tout, tret, uu, up, itask, ier)
 c
          call prntoutput(tret, uu, iout, rout)
 c
          if (ier .ne. 0) then
-            write(*,13) ier
- 13         format(///' SUNDIALS_ERROR: FIDASOLVE returned IER = ', i5)
+            write(*,15) ier
+ 15         format(///' SUNDIALS_ERROR: FIDASOLVE returned IER = ', i5)
             call fidafree
             stop
          endif
 c
          tout = tout*2.0d0
 c
- 12   continue
+ 14   continue
 c
 c Print statistics
 c
@@ -308,16 +334,16 @@ c
       jybegin = mysub*jysub
       jyend = mysub*(jysub+1)-1
 c
-      do 14 i = 1, nlocal
+      do 16 i = 1, nlocal
          id(i) = 1.0d0
- 14   continue
+ 16   continue
 c
       jloc = 0
-      do 15 j = jybegin, jyend
+      do 17 j = jybegin, jyend
          yfact = dy*dble(j)
          offset = jloc*mxsub
          iloc = 0
-         do 16 i = ixbegin, ixend
+         do 18 i = ixbegin, ixend
             xfact = dx*dble(i)
             loc = offset+iloc
             uu(loc+1) = 16.0d0*xfact*(1.0d0-xfact)*yfact*(1.0d0-yfact)
@@ -328,20 +354,20 @@ c
                id(loc+1) = 0.0d0
             endif
             iloc = iloc+1
- 16      continue
+ 18      continue
          jloc = jloc+1
- 15   continue
+ 17   continue
 c
-      do 17 i = 1, nlocal
+      do 19 i = 1, nlocal
          up(i) = 0.0d0
          constr(i) = 1.0d0
- 17   continue
+ 19   continue
 c
       call fidaresfun(0.0d0, uu, up, res, ipar, rpar, reserr)
 c
-      do 18 i = 1, nlocal
+      do 20 i = 1, nlocal
          up(i) = -1.0d0*res(i)
- 18   continue
+ 20   continue
 c
       return
       end
@@ -449,19 +475,19 @@ c
 c
       mxsub2 = mxsub+2
 c
-      do 19 i = 1, nlocal
+      do 21 i = 1, nlocal
          res(i) = u(i)
- 19   continue
+ 21   continue
 c
       offsetu = 0
       offsetue = mxsub2+1
-      do 20 ly = 0, mysub-1
-         do 21 lx = 0, mxsub-1
+      do 22 ly = 0, mysub-1
+         do 23 lx = 0, mxsub-1
             uext(offsetue+lx+1) = u(offsetu+lx+1)
- 21      continue
+ 23      continue
          offsetu = offsetu+mxsub
          offsetue = offsetue+mxsub2
- 20   continue
+ 22   continue
 c
       ixbegin = 0
       ixend = mxsub-1
@@ -480,16 +506,16 @@ c
          jyend = jyend-1
       endif
 c
-      do 22 ly = jybegin, jyend
-         do 23 lx = ixbegin, ixend
+      do 24 ly = jybegin, jyend
+         do 25 lx = ixbegin, ixend
             locu = lx+ly*mxsub
             locue = (lx+1)+(ly+1)*mxsub2
             termx = coeffx*(uext(locue)+uext(locue+2))
             termy = coeffy*(uext(locue-mxsub2+1)+uext(locue+mxsub2+1))
             termctr = coeffxy*uext(locue+1)
             res(locu+1) = up(locu+1)-(termx+termy-termctr)
- 23      continue
- 22   continue
+ 25      continue
+ 24   continue
 c
       return
       end
@@ -534,19 +560,19 @@ c
       endif
 c
       if (ixsub .ne. 0) then
-         do 24 ly = 0, mysub-1
+         do 26 ly = 0, mysub-1
             offsetu = ly*dsizex
             bufleft(ly+1) = uarray(offsetu+1)
- 24      continue
+ 26      continue
          call mpi_send(bufleft(1), dsizey, mpi_double_precision,
      &                 thispe-1, 0, mpi_comm_world, ier)
       endif
 c
       if (ixsub .ne. npex-1) then
-         do 25 ly = 0, mysub-1
+         do 27 ly = 0, mysub-1
             offsetu = ly*mxsub+(mxsub-1)
             bufright(ly+1) = uarray(offsetu+1)
- 25      continue
+ 27      continue
          call mpi_send(bufright(1), dsizey, mpi_double_precision,
      &                 thispe+1, 0, mpi_comm_world, ier)
       endif
@@ -650,18 +676,18 @@ c
 c
       if (ixsub .ne. 0) then
          call mpi_wait(request(3), status, ier)
-         do 26 ly = 0, mysub-1
+         do 28 ly = 0, mysub-1
             offsetue = (ly+1)*dsizex2
             uext(offsetue+1) = buffer(ly+1)
- 26      continue
+ 28      continue
       endif
 c
       if (ixsub .ne. npex-1) then
          call mpi_wait(request(4), status, ier)
-         do 27 ly = 0, mysub-1
+         do 29 ly = 0, mysub-1
             offsetue = (ly+2)*dsizex2-1
             uext(offsetue+1) = buffer(ly+mysub+1)
- 27      continue
+ 29      continue
       endif
 c
       return
@@ -695,10 +721,10 @@ c
 c
       if (thispe .eq. 0) then
          call fidabbdopt(lenrwbbd, leniwbbd, ngebbd)
-         write(*,28) tret, umax, iout(9), iout(3), iout(7),
+         write(*,30) tret, umax, iout(9), iout(3), iout(7),
      &               iout(20), iout(4), iout(16), ngebbd, rout(2),
      &               iout(18), iout(19)
- 28      format(' ', e10.4, ' ', e13.5, '  ', i1, '  ', i2,
+ 30      format(' ', e10.4, ' ', e13.5, '  ', i1, '  ', i2,
      &          '  ', i3, '  ', i3, '  ', i2,'+',i2, '  ',
      &          i3, '  ', e9.2, '  ', i2, '  ', i3)
       endif
@@ -733,9 +759,9 @@ c
 c
       temp = 0.0d0
 c
-      do 29 i = 1, nlocal
+      do 31 i = 1, nlocal
          temp = max(abs(u(i)), temp)
- 29   continue
+ 31   continue
 c
       call mpi_allreduce(temp, unorm, 1, mpi_double_precision,
      &                   mpi_max, mpi_comm_world, ier)
@@ -767,8 +793,8 @@ c
      &              nlocal, neq, mx, my, mxsub, mysub, npex, npey,
      &              ixsub, jysub, thispe
 c
-      write(*,30) mx, my, neq, mxsub, mysub, npex, npey, rtol, atol
- 30   format(/'fidaHeat2D_kry_bbd_p: Heat equation, parallel example',
+      write(*,32) mx, my, neq, mxsub, mysub, npex, npey, rtol, atol
+ 32   format(/'fidaHeat2D_kry_bbd_p: Heat equation, parallel example',
      &     ' for FIDA', /, 16x,'Discretized heat equation',
      &     ' on 2D unit square.', /, 16x,'Zero boundary',
      &     ' conditions, polynomial conditions.', /,
@@ -778,7 +804,7 @@ c
      &     '           Processor array: ', i2, ' x ', i2, /,
      &     'Tolerance parameters: rtol = ', e8.2, '   atol = ',
      &     e8.2, /, 'Constraints set to force all solution',
-     &     ' components >= 0.', /, 'SUPPRESSALG = TRUE to remove',
+     &     ' components >= 0.', /, 'SUPPRESSALG = SUNTRUE to remove',
      &     ' boundary components from the error test.', /,
      &     'Linear solver: SPGMR.    Preconditioner: BBDPRE - ',
      &     'Banded-block-diagonal.')
@@ -796,8 +822,8 @@ c The following declaration specification should match C type long int.
       integer*8 mudq, mukeep
       integer num
 c
-      write(*,31) num, mudq, mukeep
- 31   format(//, 'Case ', i2, /, '  Difference quotient half-',
+      write(*,33) num, mudq, mukeep
+ 33   format(//, 'Case ', i2, /, '  Difference quotient half-',
      &     'bandwidths =', i2, /, '  Retained matrix half-bandwidths =',
      &     i2, //, 'Output Summary',/,'  umax = max-norm of solution',
      &     /,'  nre = nre + nreLS (total number of RES evals.)',
@@ -818,8 +844,8 @@ c
 c The following declaration specification should match C type long int.
       integer*8 iout(*)
 c
-      write(*,32) iout(5), iout(6), iout(21)
- 32   format(/, 'Error test failures            =', i3, /,
+      write(*,34) iout(5), iout(6), iout(21)
+ 34   format(/, 'Error test failures            =', i3, /,
      &     'Nonlinear convergence failures =', i3, /,
      &     'Linear convergence failures    =', i3)
 c
diff --git a/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out
index 45d222e..c08f568 100644
--- a/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out
+++ b/examples/ida/fcmix_parallel/fidaHeat2D_kry_bbd_p.out
@@ -1,5 +1,5 @@
 
-fidaHeat2D_kry_bbd_p: Heat equation, parallel example problem for FIDA
+fidaHeat2D_kry_bbd_p: Heat equation, parallel example for FIDA
                 Discretized heat equation on 2D unit square.
                 Zero boundary conditions, polynomial conditions.
                 Mesh dimensions: 10 x 10         Total system size: 100
@@ -7,7 +7,7 @@ fidaHeat2D_kry_bbd_p: Heat equation, parallel example problem for FIDA
 Subgrid dimensions:  5 x  5           Processor array:  2 x  2
 Tolerance parameters: rtol = 0.00E+00   atol = 0.10E-02
 Constraints set to force all solution components >= 0.
-SUPPRESSALG = TRUE to remove boundary components from the error test.
+SUPPRESSALG = SUNTRUE to remove boundary components from the error test.
 Linear solver: SPGMR.    Preconditioner: BBDPRE - Banded-block-diagonal.
 
 
@@ -26,12 +26,12 @@ Output Summary
  0.4000E-01   0.47075E+00  3  18   24   22  24+22  108   0.66E-02   9   46
  0.8000E-01   0.21660E+00  3  22   29   30  29+30  108   0.13E-01   9   59
  0.1600E+00   0.45659E-01  4  28   37   43  37+43  120   0.26E-01  10   80
- 0.3200E+00   0.21096E-02  4  35   45   59  45+59  120   0.24E-01  10  104
- 0.6400E+00   0.55368E-04  1  40   54   71  54+71  156   0.19E+00  13  125
- 0.1280E+01   0.15597E-18  1  42   56   71  56+71  180   0.76E+00  15  127
- 0.2560E+01   0.33865E-20  1  43   57   71  57+71  192   0.15E+01  16  128
- 0.5120E+01   0.86074E-20  1  44   58   71  58+71  204   0.30E+01  17  129
- 0.1024E+02   0.16630E-19  1  45   59   71  59+71  216   0.61E+01  18  130
+ 0.3200E+00   0.21097E-02  4  35   45   59  45+59  120   0.24E-01  10  104
+ 0.6400E+00   0.31625E-04  1  40   54   73  54+73  156   0.19E+00  13  127
+ 0.1280E+01   0.43719E-18  1  42   56   73  56+73  180   0.76E+00  15  129
+ 0.2560E+01   0.94789E-20  1  43   57   73  57+73  192   0.15E+01  16  130
+ 0.5120E+01   0.16907E-19  1  44   58   73  58+73  204   0.30E+01  17  131
+ 0.1024E+02   0.26411E-19  1  45   59   73  59+73  216   0.61E+01  18  132
 
 Error test failures            =  1
 Nonlinear convergence failures =  0
@@ -54,11 +54,11 @@ Output Summary
  0.8000E-01   0.21655E+00  3  23   27   32  27+32   36   0.10E-01   9   59
  0.1600E+00   0.45225E-01  4  27   33   44  33+44   40   0.20E-01  10   77
  0.3200E+00   0.21868E-02  3  34   41   67  41+67   44   0.41E-01  11  108
- 0.6400E+00   0.48847E-18  1  39   49   86  49+86   52   0.16E+00  13  135
- 0.1280E+01   0.53982E-18  1  41   51   86  51+86   60   0.66E+00  15  137
- 0.2560E+01   0.74194E-17  1  42   52   86  52+86   64   0.13E+01  16  138
- 0.5120E+01   0.61081E-16  1  43   53   86  53+86   68   0.26E+01  17  139
- 0.1024E+02   0.40536E-15  1  44   54   86  54+86   72   0.52E+01  18  140
+ 0.6400E+00   0.32511E-18  1  39   49   86  49+86   52   0.16E+00  13  135
+ 0.1280E+01   0.16662E-18  1  41   51   86  51+86   60   0.66E+00  15  137
+ 0.2560E+01   0.10630E-17  1  42   52   86  52+86   64   0.13E+01  16  138
+ 0.5120E+01   0.89378E-17  1  43   53   86  53+86   68   0.26E+01  17  139
+ 0.1024E+02   0.69966E-16  1  44   54   86  54+86   72   0.52E+01  18  140
 
 Error test failures            =  0
 Nonlinear convergence failures =  0
diff --git a/examples/ida/fcmix_pthreads/CMakeLists.txt b/examples/ida/fcmix_pthreads/CMakeLists.txt
index 93a5696..bd178b6 100644
--- a/examples/ida/fcmix_pthreads/CMakeLists.txt
+++ b/examples/ida/fcmix_pthreads/CMakeLists.txt
@@ -1,100 +1,83 @@
 # ---------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer: Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for the FIDA opemp examples
+# CMakeLists.txt file for FIDA PThread examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if Pthreads is enabled
 IF(PTHREADS_FOUND)
 
-# Add variable ida_examples with the names of the pthreads FIDA examples
-SET(FIDA_examples
-  fidaRoberts_dns_pthreads
-  )
-
-# Add variable FIDA_examples_BL with the names of the pthreads FIDA examples
-# that use Lapack
+  # Examples using SUNDIALS linear solvers
+  SET(FIDA_examples
+    "fidaRoberts_dns_pthreads\;\;develop"
+    )
 
-SET(FIDA_examples_BL
-  )
 ENDIF(PTHREADS_FOUND)
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECS_LIB sundials_nvecpthreads_static)
   SET(FNVECS_LIB sundials_fnvecpthreads_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECS_LIB sundials_nvecpthreads_shared)
   SET(FNVECS_LIB sundials_fnvecpthreads_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FIDA_LIB sundials_fida_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FIDA_LIB} ${IDA_LIB} ${FNVECS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-IF(PETSC_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FIDA_examples})
 
-# Add the build and install targets for each FIDA example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
 
-FOREACH(example ${FIDA_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
-  SUNDIALS_ADD_TEST(${example} ${example})
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    TEST_ARGS ${example_args}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+   # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_pthreads)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${FIDA_examples})
-
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
-
-IF(LAPACK_FOUND)
-  FOREACH(example ${FIDA_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.f)
-    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-    IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_pthreads)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FIDA_examples_BL})
-ENDIF(LAPACK_FOUND)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_pthreads)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${FIDA_examples})
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -104,30 +87,30 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
   SET(SOLVER_FLIB "sundials_fida")
-  LIST2STRING(FIDA_examples EXAMPLES)
-  IF(LAPACK_FOUND)
-    LIST2STRING(FIDA_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
-    SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+
+  EXAMPLES2STRING(FIDA_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_pthreads_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/fcmix_pthreads/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_pthreads_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/fcmix_pthreads/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_pthreads/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_pthreads 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_pthreads
     )
 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
   IF(UNIX)
     # generate Makefile and place it in the binary dir
     CONFIGURE_FILE(
@@ -137,7 +120,7 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_pthreads/Makefile_ex 
+      FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_pthreads/Makefile_ex
       DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_pthreads
       RENAME Makefile
       )
diff --git a/examples/ida/fcmix_pthreads/README b/examples/ida/fcmix_pthreads/README
index 8e3d451..3e3c014 100644
--- a/examples/ida/fcmix_pthreads/README
+++ b/examples/ida/fcmix_pthreads/README
@@ -8,7 +8,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/ida/fcmix_pthreads/fidaRoberts_dns_pthreads.f b/examples/ida/fcmix_pthreads/fidaRoberts_dns_pthreads.f
index 2c7c092..b6987b5 100644
--- a/examples/ida/fcmix_pthreads/fidaRoberts_dns_pthreads.f
+++ b/examples/ida/fcmix_pthreads/fidaRoberts_dns_pthreads.f
@@ -1,6 +1,20 @@
-c     ----------------------------------------------------------------
-c     $Revision: 4392 $
-c     $Date: 2015-02-25 17:22:27 -0800 (Wed, 25 Feb 2015) $
+C     ----------------------------------------------------------------
+C     Programmer(s): Daniel R. Reynolds @ SMU
+C                 Steve Smith, Eddy Banks and Alan C. Hindmarsh @ LLNL      
+C     ----------------------------------------------------------------
+C     LLNS/SMU Copyright Start
+C     Copyright (c) 2017, Southern Methodist University and 
+C     Lawrence Livermore National Security
+C
+C     This work was performed under the auspices of the U.S. Department 
+C     of Energy by Southern Methodist University and Lawrence Livermore 
+C     National Laboratory under Contract DE-AC52-07NA27344.
+C     Produced at Southern Methodist University and the Lawrence 
+C     Livermore National Laboratory.
+C
+C     All rights reserved.
+C     For details, see the LICENSE file.
+C     LLNS/SMU Copyright End
 c     ----------------------------------------------------------------
 c     This simple example problem for FIDA, due to Robertson, is from 
 c     chemical kinetics, and consists of the following three equations:
@@ -25,8 +39,7 @@ c
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*8 neq
-      integer*8 iout(25), ipar
+      integer*8 neq, iout(25), ipar
       integer ier, ierroot, info(2)
       double precision rout(10), rpar
       integer iatol, nout, jout, itask
@@ -88,10 +101,36 @@ c Initialize rootfinding problem
          stop
       endif
 c
-c Attach dense linear solver
+c Attach dense matrix and linear solver
 c
-      call fidadense(neq, ier)
+      call fsundensematinit(2, neq, neq, ier)
+      if (ier .ne. 0) then
+         write(6,30) ier
+ 30      format(///' SUNDIALS_ERROR: FSUNDENSEMATINIT IER = ', i5)
+         call fidafree
+         stop
+      endif
+      call fsundenselinsolinit(2, ier)
+      if (ier .ne. 0) then
+         write(6,33) ier
+ 33      format(///' SUNDIALS_ERROR: FSUNDENSELINSOLINIT IER = ', i5)
+         call fidafree
+         stop
+      endif
+      call fidadlsinit(ier)
+      if (ier .ne. 0) then
+         write(6,35) ier
+ 35      format(///' SUNDIALS_ERROR: FIDADLSINIT returned IER = ', i5)
+         call fidafree
+         stop
+      endif
       call fidadensesetjac(1, ier)
+      if (ier .ne. 0) then
+         write(6,37) ier
+ 37      format(///' SUNDIALS_ERROR: FIDADENSESETJAC IER = ', i5)
+         call fidafree
+         stop
+      endif
 c
 c Print header
 c
@@ -121,7 +160,7 @@ c
         if (ier .eq. 2) then
           call fidarootinfo(2, info, ierroot)
           if (ierroot .lt. 0) then
-            write(6,55) ier
+            write(6,55) ierroot
  55         format(///' SUNDIALS_ERROR: FIDAROOTINFO returned IER = ',
      1             i5)
             call fidarootfree
@@ -158,7 +197,7 @@ c
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*4 ipar(*)
+      integer*8 ipar(*)
       integer reserr
       double precision tres, rpar(*)
       double precision y(*), yp(*), res(*)
@@ -181,7 +220,7 @@ c
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*4 neq, ipar(*)
+      integer*8 neq, ipar(*)
       integer djacerr
       double precision t, h, cj, rpar(*)
       double precision y(*), yp(*), r(*), ewt(*), jac(neq,neq)
@@ -209,7 +248,7 @@ c Fortran routine for rootfinding
       implicit none
 c
 c The following declaration specification should match C type long int.
-      integer*4 ipar(*)
+      integer*8 ipar(*)
       integer ier
       double precision t, y(*), yp(*), g(*), rpar(*)
 c
diff --git a/examples/ida/fcmix_serial/CMakeLists.txt b/examples/ida/fcmix_serial/CMakeLists.txt
index 69d381e..86ec7d1 100644
--- a/examples/ida/fcmix_serial/CMakeLists.txt
+++ b/examples/ida/fcmix_serial/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer: Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,83 +12,65 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the FIDA serial examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
-# Add variable ida_examples with the names of the serial FIDA examples
-
+# Examples using SUNDIALS linear solvers
 SET(FIDA_examples
-  fidaRoberts_dns
-  )
-
-# Add variable FIDA_examples_BL with the names of the serial FIDA examples
-# that use Lapack
-
-SET(FIDA_examples_BL
+  "fidaRoberts_dns\;develop"
   )
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECS_LIB sundials_nvecserial_static)
   SET(FNVECS_LIB sundials_fnvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
   SET(FNVECS_LIB sundials_fnvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FIDA_LIB sundials_fida_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FIDA_LIB} ${IDA_LIB} ${FNVECS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-IF(PETSC_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FIDA_examples})
 
-# Add the build and install targets for each FIDA example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${FIDA_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+   # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${FIDA_examples})
-
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
-
-IF(LAPACK_FOUND)
-  FOREACH(example ${FIDA_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.f)
-    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-    IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FIDA_examples_BL})
-ENDIF(LAPACK_FOUND)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${FIDA_examples})
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -101,32 +80,28 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
   SET(SOLVER_FLIB "sundials_fida")
-  LIST2STRING(FIDA_examples EXAMPLES)
-  IF(LAPACK_FOUND)
-    LIST2STRING(FIDA_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
-    SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+
+  EXAMPLES2STRING(FIDA_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/fcmix_serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/fcmix_serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_serial/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -138,8 +113,8 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_serial/Makefile_ex 
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial 
+      FILES ${PROJECT_BINARY_DIR}/examples/ida/fcmix_serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/fcmix_serial
       RENAME Makefile
       )
   ENDIF(UNIX)
diff --git a/examples/ida/fcmix_serial/README b/examples/ida/fcmix_serial/README
index 44b9491..0d44536 100644
--- a/examples/ida/fcmix_serial/README
+++ b/examples/ida/fcmix_serial/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -31,7 +33,6 @@ The following CMake command was used to configure SUNDIALS:
 -DHYPRE_LIBRARY=/usr/casc/sundials/apps/rh6/hypre/2.11.1/lib/libHYPRE.a \
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
--DFCMIX_ENABLE=ON \
 -DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
diff --git a/examples/ida/fcmix_serial/fidaRoberts_dns.f b/examples/ida/fcmix_serial/fidaRoberts_dns.f
index 8ded4b3..7157d34 100644
--- a/examples/ida/fcmix_serial/fidaRoberts_dns.f
+++ b/examples/ida/fcmix_serial/fidaRoberts_dns.f
@@ -1,6 +1,20 @@
-c     ----------------------------------------------------------------
-c     $Revision: 4885 $
-c     $Date: 2016-09-02 08:29:03 -0700 (Fri, 02 Sep 2016) $
+C     ----------------------------------------------------------------
+C     Programmer(s): Daniel R. Reynolds @ SMU
+C                    Alan C. Hindmarsh and Radu Serban @ LLNL      
+C     ----------------------------------------------------------------
+C     LLNS/SMU Copyright Start
+C     Copyright (c) 2017, Southern Methodist University and 
+C     Lawrence Livermore National Security
+C
+C     This work was performed under the auspices of the U.S. Department 
+C     of Energy by Southern Methodist University and Lawrence Livermore 
+C     National Laboratory under Contract DE-AC52-07NA27344.
+C     Produced at Southern Methodist University and the Lawrence 
+C     Livermore National Laboratory.
+C
+C     All rights reserved.
+C     For details, see the LICENSE file.
+C     LLNS/SMU Copyright End
 c     ----------------------------------------------------------------
 c     This simple example problem for FIDA, due to Robertson, is from 
 c     chemical kinetics, and consists of the following three equations:
@@ -84,10 +98,36 @@ c Initialize rootfinding problem
          stop
       endif
 c
-c Attach dense linear solver
+c Attach dense matrix and linear solver
 c
-      call fidadense(neq, ier)
+      call fsundensematinit(2, neq, neq, ier)
+      if (ier .ne. 0) then
+         write(6,30) ier
+ 30      format(///' SUNDIALS_ERROR: FSUNDENSEMATINIT IER = ', i5)
+         call fidafree
+         stop
+      endif
+      call fsundenselinsolinit(2, ier)
+      if (ier .ne. 0) then
+         write(6,33) ier
+ 33      format(///' SUNDIALS_ERROR: FSUNDENSELINSOLINIT IER = ', i5)
+         call fidafree
+         stop
+      endif
+      call fidadlsinit(ier)
+      if (ier .ne. 0) then
+         write(6,35) ier
+ 35      format(///' SUNDIALS_ERROR: FIDADLSINIT returned IER = ', i5)
+         call fidafree
+         stop
+      endif
       call fidadensesetjac(1, ier)
+      if (ier .ne. 0) then
+         write(6,37) ier
+ 37      format(///' SUNDIALS_ERROR: FIDADENSESETJAC IER = ', i5)
+         call fidafree
+         stop
+      endif
 c
 c Print header
 c
diff --git a/examples/ida/parallel/CMakeLists.txt b/examples/ida/parallel/CMakeLists.txt
index 21b1e14..e0fa4c9 100644
--- a/examples/ida/parallel/CMakeLists.txt
+++ b/examples/ida/parallel/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,78 +12,80 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for IDA parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable IDA_examples with the names of the parallel IDA examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(IDA_examples
-  "idaFoodWeb_kry_bbd_p\;1\;4"
-  "idaFoodWeb_kry_p\;1\;4"
-  "idaHeat2D_kry_bbd_p\;1\;4"
-  "idaHeat2D_kry_p\;1\;4"
+  "idaFoodWeb_kry_bbd_p\;1\;4\;develop"
+  "idaFoodWeb_kry_p\;1\;4\;develop"
+  "idaHeat2D_kry_bbd_p\;1\;4\;develop"
+  "idaHeat2D_kry_p\;1\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the C compiler to the MPICC script.
 # If not, then add the MPI include directory for MPI headers.
-
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${IDA_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-IF(PETSC_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_FOUND)
-
-# Add the build and install targets for each IDA example
 
+# Add the build and install targets for each example
 FOREACH(example_tuple ${IDA_examples})
+
   list(GET example_tuple 0 example)
   list(GET example_tuple 1 number_of_nodes)
   list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  list(GET example_tuple 3 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPICC)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${IDA_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -95,31 +94,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
-  FOREACH(example_tuple ${IDA_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${IDA_examples})
-  
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+
+  EXAMPLES2STRING(IDA_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/ida/parallel/README b/examples/ida/parallel/README
index 08e1230..3b3c3fb 100644
--- a/examples/ida/parallel/README
+++ b/examples/ida/parallel/README
@@ -10,7 +10,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -21,7 +20,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -35,7 +37,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/ida/parallel/idaFoodWeb_kry_bbd_p.c b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.c
index 9daab3d..c66e1fd 100644
--- a/examples/ida/parallel/idaFoodWeb_kry_bbd_p.c
+++ b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.c
@@ -1,19 +1,15 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *         Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDA: Food web, parallel, GMRES, IDABBD
  * preconditioner.
  *
- * This example program for IDA uses IDASPGMR as the linear solver.
+ * This example program for IDA uses SUNSPGMR as the linear solver.
  * It is written for a parallel computer system and uses the
  * IDABBDPRE band-block-diagonal preconditioner module for the
- * IDASPGMR package. It was originally run on a Sun SPARC cluster
- * and used MPICH.
+ * SUNSPGMR package. 
  *
  * The mathematical problem solved in this example is a DAE system
  * that arises from a system of partial differential equations after
@@ -72,7 +68,7 @@
  * submeshes, processor by processor, with an MXSUB by MYSUB mesh
  * on each of NPEX * NPEY processors.
  *
- * The DAE system is solved by IDA using the IDASPGMR linear solver,
+ * The DAE system is solved by IDA using the SUNSPGMR linear solver,
  * in conjunction with the preconditioner module IDABBDPRE. The
  * preconditioner uses a 5-diagonal band-block-diagonal
  * approximation (half-bandwidths = 2). Output is printed at
@@ -101,11 +97,12 @@
 #include <math.h>
 
 #include <ida/ida.h>
-#include <ida/ida_spgmr.h>
+#include <ida/ida_spils.h>
 #include <ida/ida_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
-#include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
+#include <sundials/sundials_dense.h>
 #include <sundials/sundials_math.h>
 
 #include <mpi.h>
@@ -165,20 +162,19 @@ typedef struct {
     rhs[NUM_SPECIES], cext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
   MPI_Comm comm;
   N_Vector rates;
-  long int n_local;
+  sunindextype n_local;
 } *UserData;
 
 /* Prototypes for functions called by the IDA Solver. */
 
-static int resweb(realtype tt, 
-                  N_Vector cc, N_Vector cp, N_Vector rr, 
-                  void *user_data);
+static int resweb(realtype tt, N_Vector cc, N_Vector cp,
+                  N_Vector rr, void *user_data);
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector cc, N_Vector cp, N_Vector res, 
                     void *user_data);
 
-static int rescomm(long int Nlocal, realtype tt,
+static int rescomm(sunindextype Nlocal, realtype tt,
                    N_Vector cc, N_Vector cp, 
                    void *user_data);
 
@@ -208,15 +204,15 @@ static void InitUserData(UserData webdata, int thispe, int npes,
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                N_Vector scrtch, UserData webdata);
 
-static void PrintHeader(long int SystemSize, int maxl, 
-                        long int mudq, long int mldq, 
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol);
 
-static void PrintOutput(void *mem, N_Vector cc, realtype time,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype time,
                         UserData webdata, MPI_Comm comm);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -229,16 +225,18 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData webdata;
-  long int SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, tout, tret;
   N_Vector cc, cp, res, id;
   int thispe, npes, maxl, iout, retval;
 
   cc = cp = res = id = NULL;
   webdata = NULL;
-  mem = NULL;
+  LS = NULL;
+  ida_mem = NULL;
 
   /* Set communicator, and get processor number and total number of PE's. */
 
@@ -296,26 +294,28 @@ int main(int argc, char *argv[])
   
   /* Call IDACreate and IDAMalloc to initialize solution */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetUserData(mem, webdata);
+  retval = IDASetUserData(ida_mem, webdata);
   if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetId(mem, id);
+  retval = IDASetId(ida_mem, id);
   if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDAInit(mem, resweb, t0, cc, cp);
+  retval = IDAInit(ida_mem, resweb, t0, cc, cp);
   if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  retval = IDASStolerances(mem, rtol, atol);
+  retval = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the IDA linear solver IDASPGMR */
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the linear solver */
 
   maxl = 16;
-  retval = IDASpgmr(mem, maxl);
-  if(check_flag(&retval, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  LS = SUNSPGMR(cc, PREC_LEFT, maxl);
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+  retval = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&retval, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDABBDPrecInit to initialize the band-block-diagonal preconditioner.
      The half-bandwidths for the difference quotient evaluation are exact
@@ -323,14 +323,14 @@ int main(int argc, char *argv[])
   
   mudq = mldq = NSMXSUB;
   mukeep = mlkeep = 2;
-  retval = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  retval = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                           ZERO, reslocal, NULL);
   if(check_flag(&retval, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
   
   /* Call IDACalcIC (with default options) to correct the initial values. */
   
   tout = RCONST(0.001);
-  retval = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  retval = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&retval, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
   
   /* On PE 0, print heading, basic parameters, initial values. */
@@ -338,16 +338,16 @@ int main(int argc, char *argv[])
   if (thispe == 0) PrintHeader(SystemSize, maxl, 
                                mudq, mldq, mukeep, mlkeep,
                                rtol, atol);
-  PrintOutput(mem, cc, t0, webdata, comm);
+  PrintOutput(ida_mem, cc, t0, webdata, comm);
 
   /* Call IDA in tout loop, normal mode, and print selected output. */
   
   for (iout = 1; iout <= NOUT; iout++) {
     
-    retval = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    retval = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
     
-    PrintOutput(mem, cc, tret, webdata, comm);
+    PrintOutput(ida_mem, cc, tret, webdata, comm);
     
     if (iout < 3) tout *= TMULT; 
     else          tout += TADD;
@@ -356,7 +356,7 @@ int main(int argc, char *argv[])
   
   /* On PE 0, print final set of statistics. */
   
-  if (thispe == 0)  PrintFinalStats(mem);
+  if (thispe == 0)  PrintFinalStats(ida_mem);
 
   /* Free memory. */
 
@@ -364,7 +364,8 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(cp);
   N_VDestroy_Parallel(id);
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   destroyMat(webdata->acoef);
   N_VDestroy_Parallel(webdata->rates);
@@ -506,15 +507,15 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * and table headerr
  */
 
-static void PrintHeader(long int SystemSize, int maxl, 
-                        long int mudq, long int mldq, 
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol)
 {
   printf("\nidaFoodWeb_kry_bbd_p: Predator-prey DAE parallel example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d", MX, MY);
-  printf("     Total system size: %ld\n",SystemSize);
+  printf("     Total system size: %ld\n",(long int) SystemSize);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("     Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -524,10 +525,10 @@ static void PrintHeader(long int SystemSize, int maxl,
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASPGMR     Max. Krylov dimension maxl: %d\n", maxl);
+  printf("Linear solver: SUNSPGMR     Max. Krylov dimension maxl: %d\n", maxl);
   printf("Preconditioner: band-block-diagonal (IDABBDPRE), with parameters\n");
   printf("     mudq = %ld,  mldq = %ld,  mukeep = %ld,  mlkeep = %ld\n",
-         mudq, mldq, mukeep, mlkeep);
+         (long int) mudq, (long int) mldq, (long int) mukeep, (long int) mlkeep);
   printf("CalcIC called to correct initial predator concentrations \n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -542,7 +543,7 @@ static void PrintHeader(long int SystemSize, int maxl,
  * are printed for the bottom left and top right grid points only.
  */
 
-static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype tt,
                         UserData webdata, MPI_Comm comm)
 {
   MPI_Status status;
@@ -570,11 +571,11 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
     if (npelast != 0)
       MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
     
-    flag = IDAGetLastOrder(mem, &kused);
+    flag = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&flag, "IDAGetLastOrder", 1, thispe);
-    flag = IDAGetNumSteps(mem, &nst);
+    flag = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&flag, "IDAGetNumSteps", 1, thispe);
-    flag = IDAGetLastStep(mem, &hused);
+    flag = IDAGetLastStep(ida_mem, &hused);
     check_flag(&flag, "IDAGetLastStep", 1, thispe);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -603,34 +604,34 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1, 0);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1, 0);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
 
-  flag = IDASpilsGetNumConvFails(mem, &ncfl);
+  flag = IDASpilsGetNumConvFails(ida_mem, &ncfl);
   check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
-  flag = IDASpilsGetNumLinIters(mem, &nli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &nli);
   check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
-  flag = IDASpilsGetNumPrecEvals(mem, &npe);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npe);
   check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
-  flag = IDASpilsGetNumResEvals(mem, &nreLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
 
-  flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+  flag = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
   check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
 
   printf("-----------------------------------------------------------\n");
@@ -710,7 +711,7 @@ static int resweb(realtype tt,
 {
   int retval;
   UserData webdata;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   webdata = (UserData) user_data;
   
@@ -735,7 +736,7 @@ static int resweb(realtype tt,
  * and receive-waiting, in routines BRecvPost, BSend, BRecvWait.         
  */
 
-static int rescomm(long int Nlocal, realtype tt, 
+static int rescomm(sunindextype Nlocal, realtype tt, 
                    N_Vector cc, N_Vector cp,
                    void *user_data)
 {
@@ -958,7 +959,7 @@ static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
  * for use by the preconditioner setup routine.                          
  */
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector cc, N_Vector cp, N_Vector rr,
                     void *user_data)
 {
diff --git a/examples/ida/parallel/idaFoodWeb_kry_bbd_p.out b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.out
index 16b0f3c..5d07930 100644
--- a/examples/ida/parallel/idaFoodWeb_kry_bbd_p.out
+++ b/examples/ida/parallel/idaFoodWeb_kry_bbd_p.out
@@ -1,18 +1,12 @@
 
-idaFoodWeb_kry_bbd_p: Predator-prey DAE parallel example problem
-
-Number of species ns: 2
-Mesh dimensions:      20 x 20
-Total system size:    800
-Subgrid dimensions:   10 x 10
-Processor array:      2 x 2
-Tolerance parameters:
- relative tolerance = 1e-05
- absolute tolerance = 1e-05
-Linear solver: scaled preconditioned GMRES (IDASPGMR)
- max. Krylov dimension: maxl = 16
-Preconditioner: band-block-diagonal (IDABBDPRE)
- mudq = 20,  mldq = 20,  mukeep = 2,  mlkeep = 2
+idaFoodWeb_kry_bbd_p: Predator-prey DAE parallel example problem for IDA 
+
+Number of species ns: 2     Mesh dimensions: 20 x 20     Total system size: 800
+Subgrid dimensions: 10 x 10     Processor array: 2 x 2
+Tolerance parameters:  rtol = 1e-05   atol = 1e-05
+Linear solver: SUNSPGMR     Max. Krylov dimension maxl: 16
+Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
+     mudq = 20,  mldq = 20,  mukeep = 2,  mlkeep = 2
 CalcIC called to correct initial predator concentrations 
 
 -----------------------------------------------------------
@@ -25,34 +19,34 @@ CalcIC called to correct initial predator concentrations
 1.00e-03   1.0318e+01   1.0827e+01   |  33  4   9.7404e-05
            1.0319e+05   1.0822e+05   |
 
-1.00e-02   1.6189e+02   1.9735e+02   | 123  3   1.9481e-04
+1.00e-02   1.6189e+02   1.9735e+02   | 119  4   1.7533e-04
            1.6189e+06   1.9735e+06   |
 
-1.00e-01   2.4019e+02   2.7072e+02   | 197  1   4.0396e-02
+1.00e-01   2.4019e+02   2.7072e+02   | 190  1   3.8524e-02
            2.4019e+06   2.7072e+06   |
 
-4.00e-01   2.4019e+02   2.7072e+02   | 200  1   3.2316e-01
+4.00e-01   2.4019e+02   2.7072e+02   | 193  1   3.0819e-01
            2.4019e+06   2.7072e+06   |
 
-7.00e-01   2.4019e+02   2.7072e+02   | 200  1   3.2316e-01
+7.00e-01   2.4019e+02   2.7072e+02   | 194  1   6.1639e-01
            2.4019e+06   2.7072e+06   |
 
-1.00e+00   2.4019e+02   2.7072e+02   | 201  1   6.4633e-01
+1.00e+00   2.4019e+02   2.7072e+02   | 194  1   6.1639e-01
            2.4019e+06   2.7072e+06   |
 
 -----------------------------------------------------------
 
 Final statistics: 
 
-Number of steps                    = 201
-Number of residual evaluations     = 1110
-Number of nonlinear iterations     = 245
+Number of steps                    = 194
+Number of residual evaluations     = 1057
+Number of nonlinear iterations     = 239
 Number of error test failures      = 0
 Number of nonlinear conv. failures = 0
 
-Number of linear iterations        = 863
+Number of linear iterations        = 816
 Number of linear conv. failures    = 0
 
-Number of preconditioner setups    = 26
-Number of preconditioner solves    = 1110
-Number of local residual evals.    = 1092
+Number of preconditioner setups    = 25
+Number of preconditioner solves    = 1057
+Number of local residual evals.    = 1050
diff --git a/examples/ida/parallel/idaFoodWeb_kry_p.c b/examples/ida/parallel/idaFoodWeb_kry_p.c
index 64a56f8..a1280c8 100644
--- a/examples/ida/parallel/idaFoodWeb_kry_p.c
+++ b/examples/ida/parallel/idaFoodWeb_kry_p.c
@@ -1,19 +1,15 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *         Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDA: Food web, parallel, GMRES, user
  * preconditioner.
  *
- * This example program for IDA uses IDASPGMR as the linear solver.
+ * This example program for IDA uses SUNSPGMR as the linear solver.
  * It is written for a parallel computer system and uses a
  * block-diagonal preconditioner (setup and solve routines) for the
- * IDASPGMR package. It was originally run on a Sun SPARC cluster
- * and used MPICH.
+ * SUNSPGMR package. 
  *
  * The mathematical problem solved in this example is a DAE system
  * that arises from a system of partial differential equations after
@@ -72,9 +68,9 @@
  * submeshes, processor by processor, with an MXSUB by MYSUB mesh
  * on each of NPEX * NPEY processors.
  *
- * The DAE system is solved by IDA using the IDASPGMR linear
+ * The DAE system is solved by IDA using the SUNSPGMR linear
  * solver, which uses the preconditioned GMRES iterative method to
- * solve linear systems. The precondtioner supplied to IDASPGMR is
+ * solve linear systems. The precondtioner supplied to SUNSPGMR is
  * the block-diagonal part of the Jacobian with ns by ns blocks
  * arising from the reaction terms only. Output is printed at
  * t = 0, .001, .01, .1, .4, .7, 1.
@@ -102,7 +98,8 @@
 #include <math.h>
 
 #include <ida/ida.h>
-#include <ida/ida_spgmr.h>
+#include <ida/ida_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
@@ -157,7 +154,7 @@
 /* Type: UserData.  Contains problem constants, preconditioner data, etc. */
 
 typedef struct {
-  long int ns;
+  sunindextype ns;
   int np, thispe, npes, ixsub, jysub, npex, npey;
   int mxsub, mysub, nsmxsub, nsmxsub2;
   realtype dx, dy, **acoef;
@@ -166,7 +163,7 @@ typedef struct {
   MPI_Comm comm;
   N_Vector rates;
   realtype **PP[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
   N_Vector ewt;
   void *ida_mem;
 } *UserData;
@@ -178,16 +175,12 @@ static int resweb(realtype time,
                   N_Vector cc, N_Vector cp, N_Vector resval, 
                   void *user_data);
 
-static int Precondbd(realtype tt, 
-                     N_Vector cc, N_Vector cp, N_Vector rr, 
-                     realtype cj, void *user_data,
-                     N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
+static int Precondbd(realtype tt, N_Vector cc, N_Vector cp,
+                     N_Vector rr, realtype cj, void *user_data);
 
-static int PSolvebd(realtype tt, 
-                    N_Vector cc, N_Vector cp, N_Vector rr, 
-                    N_Vector rvec, N_Vector zvec,
-                    realtype cj, realtype delta, void *user_data, 
-                    N_Vector tempv);
+static int PSolvebd(realtype tt, N_Vector cc, N_Vector cp, 
+                    N_Vector rr, N_Vector rvec, N_Vector zvec,
+                    realtype cj, realtype delta, void *user_data);
 
 static int rescomm(N_Vector cc, N_Vector cp, void *user_data);
 
@@ -212,8 +205,8 @@ static realtype dotprod(int size, realtype *x1, realtype *x2);
 
 /* Prototypes for private Helper Functions. */
 
-static UserData AllocUserData(MPI_Comm comm, long int local_N, 
-                              long int SystemSize);
+static UserData AllocUserData(MPI_Comm comm, sunindextype local_N, 
+                              sunindextype SystemSize);
 
 static void InitUserData(UserData webdata, int thispe, int npes, 
                          MPI_Comm comm);
@@ -223,13 +216,13 @@ static void FreeUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                N_Vector scrtch, UserData webdata);
 
-static void PrintHeader(long int SystemSize, int maxl, 
+static void PrintHeader(sunindextype SystemSize, int maxl, 
                         realtype rtol, realtype atol);
 
-static void PrintOutput(void *mem, N_Vector cc, realtype time,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype time,
                         UserData webdata, MPI_Comm comm);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -242,16 +235,18 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData webdata;
-  long int SystemSize, local_N;
+  sunindextype SystemSize, local_N;
   realtype rtol, atol, t0, tout, tret;
   N_Vector cc, cp, res, id;
   int thispe, npes, maxl, iout, flag;
 
   cc = cp = res = id = NULL;
   webdata = NULL;
-  mem = NULL;
+  LS = NULL;
+  ida_mem = NULL;
 
   /* Set communicator, and get processor number and total number of PE's. */
 
@@ -309,56 +304,62 @@ int main(int argc, char *argv[])
   /* Call IDACreate and IDAMalloc to initialize IDA.
      A pointer to IDA problem memory is returned and stored in idamem. */
 
-  mem = IDACreate();
-  if (check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if (check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDASetUserData(mem, webdata);
+  flag = IDASetUserData(ida_mem, webdata);
   if (check_flag(&flag, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDASetId(mem, id);
+  flag = IDASetId(ida_mem, id);
   if (check_flag(&flag, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDAInit(mem, resweb, t0, cc, cp);
+  flag = IDAInit(ida_mem, resweb, t0, cc, cp);
   if (check_flag(&flag, "IDAinit", 1, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDASStolerances(mem, rtol, atol);
+  flag = IDASStolerances(ida_mem, rtol, atol);
   if (check_flag(&flag, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  webdata->ida_mem = mem;
+  webdata->ida_mem = ida_mem;
 
-  /* Call IDASpgmr to specify the IDA linear solver IDASPGMR and specify
-     the preconditioner routines supplied (Precondbd and PSolvebd).
-     maxl (max. Krylov subspace dim.) is set to 16. */
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the linear solver 
+     to IDA, and specify the supplied [left] preconditioner routines 
+     (Precondbd & PSolvebd).  maxl (Krylov subspace dim.) is set to 16. */
 
   maxl = 16;
-  flag = IDASpgmr(mem, maxl);
-  if (check_flag(&flag, "IDASpgmr", 1, thispe)) 
+  LS = SUNSPGMR(cc, PREC_LEFT, maxl);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  flag = SUNSPGMRSetMaxRestarts(LS, 5);  /* IDA recommends allowing up to 5 restarts */
+  if(check_flag(&flag, "SUNSPGMRSetMaxRestarts", 1, thispe)) MPI_Abort(comm, 1);
+
+  flag = IDASpilsSetLinearSolver(ida_mem, LS);
+  if (check_flag(&flag, "IDASpilsSetLinearSolver", 1, thispe)) 
     MPI_Abort(comm, 1);
 
-  flag = IDASpilsSetPreconditioner(mem, Precondbd, PSolvebd);
+  flag = IDASpilsSetPreconditioner(ida_mem, Precondbd, PSolvebd);
   if (check_flag(&flag, "IDASpilsSetPreconditioner", 1, thispe)) 
     MPI_Abort(comm, 1);
   
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
   tout = RCONST(0.001);
-  flag = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  flag = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if (check_flag(&flag, "IDACalcIC", 1, thispe)) 
     MPI_Abort(comm, 1);
 
   /* On PE 0, print heading, basic parameters, initial values. */
 
   if (thispe == 0) PrintHeader(SystemSize, maxl, rtol, atol);
-  PrintOutput(mem, cc, t0, webdata, comm);
+  PrintOutput(ida_mem, cc, t0, webdata, comm);
   
   /* Loop over iout, call IDASolve (normal mode), print selected output. */
 
   for (iout = 1; iout <= NOUT; iout++) {
     
-    flag = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    flag = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if (check_flag(&flag, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(mem, cc, tret, webdata, comm);
+    PrintOutput(ida_mem, cc, tret, webdata, comm);
     
     if (iout < 3) tout *= TMULT; 
     else          tout += TADD;
@@ -366,7 +367,7 @@ int main(int argc, char *argv[])
   }
   
   /* On PE 0, print final set of statistics. */
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
 
   /* Free memory. */
 
@@ -374,8 +375,9 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(cp);
   N_VDestroy_Parallel(id);
 
-  IDAFree(&mem);
-
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
+  
   FreeUserData(webdata);
 
   MPI_Finalize();
@@ -394,7 +396,7 @@ int main(int argc, char *argv[])
  * AllocUserData: Allocate memory for data structure of type UserData.   
  */
 
-static UserData AllocUserData(MPI_Comm comm, long int local_N, long int SystemSize)
+static UserData AllocUserData(MPI_Comm comm, sunindextype local_N, sunindextype SystemSize)
 {
   int ix, jy;
   UserData webdata;
@@ -406,7 +408,7 @@ static UserData AllocUserData(MPI_Comm comm, long int local_N, long int SystemSi
   for (ix = 0; ix < MXSUB; ix++) {
     for (jy = 0; jy < MYSUB; jy++) {
       (webdata->PP)[ix][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (webdata->pivot)[ix][jy] = newLintArray(NUM_SPECIES);
+      (webdata->pivot)[ix][jy] = newIndexArray(NUM_SPECIES);
     }
   }
   
@@ -557,13 +559,13 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int SystemSize, int maxl, 
+static void PrintHeader(sunindextype SystemSize, int maxl, 
                         realtype rtol, realtype atol)
 {
   printf("\nidaFoodWeb_kry_p: Predator-prey DAE parallel example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d", MX, MY);
-  printf("     Total system size: %ld\n",SystemSize);
+  printf("     Total system size: %ld\n", (long int) SystemSize);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("     Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -573,7 +575,7 @@ static void PrintHeader(long int SystemSize, int maxl,
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASPGMR     Max. Krylov dimension maxl: %d\n", maxl);
+  printf("Linear solver: SUNSPGMR     Max. Krylov dimension maxl: %d\n", maxl);
   printf("Preconditioner: block diagonal, block size ns,"); 
   printf(" via difference quotients\n");
   printf("CalcIC called to correct initial predator concentrations \n\n");
@@ -591,7 +593,7 @@ static void PrintHeader(long int SystemSize, int maxl,
  * (NOTE: This routine is specific to the case NUM_SPECIES = 2.)         
  */
 
-static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype tt,
                         UserData webdata, MPI_Comm comm)
 {
   MPI_Status status;
@@ -619,11 +621,11 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
     if (npelast != 0)
       MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
     
-    flag = IDAGetLastOrder(mem, &kused);
+    flag = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&flag, "IDAGetLastOrder", 1, thispe);
-    flag = IDAGetNumSteps(mem, &nst);
+    flag = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&flag, "IDAGetNumSteps", 1, thispe);
-    flag = IDAGetLastStep(mem, &hused);
+    flag = IDAGetLastStep(ida_mem, &hused);
     check_flag(&flag, "IDAGetLastStep", 1, thispe);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -651,31 +653,31 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1, 0);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1, 0);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
 
-  flag = IDASpilsGetNumConvFails(mem, &ncfl);
+  flag = IDASpilsGetNumConvFails(ida_mem, &ncfl);
   check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
-  flag = IDASpilsGetNumLinIters(mem, &nli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &nli);
   check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
-  flag = IDASpilsGetNumPrecEvals(mem, &npe);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npe);
   check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
-  flag = IDASpilsGetNumResEvals(mem, &nreLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
 
   printf("-----------------------------------------------------------\n");
@@ -1122,10 +1124,8 @@ static realtype dotprod(int size, realtype *x1, realtype *x2)
  * Each block is LU-factored, for later solution of the linear systems.  
  */
 
-static int Precondbd(realtype tt, N_Vector cc,
-                     N_Vector cp, N_Vector rr, 
-                     realtype cj, void *user_data,
-                     N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+static int Precondbd(realtype tt, N_Vector cc, N_Vector cp, 
+                     N_Vector rr, realtype cj, void *user_data)
 {
   int flag, thispe;
   realtype uround;
@@ -1133,7 +1133,7 @@ static int Precondbd(realtype tt, N_Vector cc,
   realtype inc, sqru, fac, perturb_rates[NUM_SPECIES];
   int is, js, ix, jy, ret;
   UserData webdata;
-  void *mem;
+  void *ida_mem;
   N_Vector ewt;
   realtype hh;
 
@@ -1142,11 +1142,11 @@ static int Precondbd(realtype tt, N_Vector cc,
   sqru = SUNRsqrt(uround);
   thispe = webdata->thispe;
 
-  mem = webdata->ida_mem;
+  ida_mem = webdata->ida_mem;
   ewt = webdata->ewt;
-  flag = IDAGetErrWeights(mem, ewt);
+  flag = IDAGetErrWeights(ida_mem, ewt);
   check_flag(&flag, "IDAGetErrWeights", 1, thispe);
-  flag = IDAGetCurrentStep(mem, &hh);
+  flag = IDAGetCurrentStep(ida_mem, &hh);
   check_flag(&flag, "IDAGetCurrentStep", 1, thispe);
 
   for (jy = 0; jy < mysub; jy++) {
@@ -1197,14 +1197,12 @@ static int Precondbd(realtype tt, N_Vector cc,
  * preconditioner PP, to compute the solution of PP * zvec = rvec.       
  */
 
-static int PSolvebd(realtype tt, N_Vector cc,
-                 N_Vector cp, N_Vector rr, 
-                 N_Vector rvec, N_Vector zvec,
-                 realtype cj, realtype delta,
-                 void *user_data, N_Vector tempv)
+static int PSolvebd(realtype tt, N_Vector cc, N_Vector cp,
+                    N_Vector rr, N_Vector rvec, N_Vector zvec,
+                    realtype cj, realtype delta, void *user_data)
 {
   realtype **Pxy, *zxy;
-  long int *pivot, ix, jy;
+  sunindextype *pivot, ix, jy;
   UserData webdata;
 
   webdata = (UserData)user_data;
diff --git a/examples/ida/parallel/idaFoodWeb_kry_p.out b/examples/ida/parallel/idaFoodWeb_kry_p.out
index ee07f6f..5b9f9da 100644
--- a/examples/ida/parallel/idaFoodWeb_kry_p.out
+++ b/examples/ida/parallel/idaFoodWeb_kry_p.out
@@ -4,7 +4,7 @@ idaFoodWeb_kry_p: Predator-prey DAE parallel example problem for IDA
 Number of species ns: 2     Mesh dimensions: 20 x 20     Total system size: 800
 Subgrid dimensions: 10 x 10     Processor array: 2 x 2
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDASPGMR     Max. Krylov dimension maxl: 16
+Linear solver: SUNSPGMR     Max. Krylov dimension maxl: 16
 Preconditioner: block diagonal, block size ns, via difference quotients
 CalcIC called to correct initial predator concentrations 
 
@@ -21,30 +21,30 @@ CalcIC called to correct initial predator concentrations
 1.00e-02   1.6189e+02   1.9735e+02   |  86  4   1.7533e-04
            1.6189e+06   1.9735e+06   |
 
-1.00e-01   2.4019e+02   2.7072e+02   | 162  1   4.0396e-02
+1.00e-01   2.4019e+02   2.7072e+02   | 163  1   4.0396e-02
            2.4019e+06   2.7072e+06   |
 
-4.00e-01   2.4019e+02   2.7072e+02   | 165  1   3.2316e-01
+4.00e-01   2.4019e+02   2.7072e+02   | 166  1   3.2316e-01
            2.4019e+06   2.7072e+06   |
 
-7.00e-01   2.4019e+02   2.7072e+02   | 166  1   6.4633e-01
+7.00e-01   2.4019e+02   2.7072e+02   | 167  1   6.4633e-01
            2.4019e+06   2.7072e+06   |
 
-1.00e+00   2.4019e+02   2.7072e+02   | 166  1   6.4633e-01
+1.00e+00   2.4019e+02   2.7072e+02   | 167  1   6.4633e-01
            2.4019e+06   2.7072e+06   |
 
 -----------------------------------------------------------
 
 Final statistics: 
 
-Number of steps                    = 166
-Number of residual evaluations     = 1257
+Number of steps                    = 167
+Number of residual evaluations     = 1247
 Number of nonlinear iterations     = 206
 Number of error test failures      = 0
 Number of nonlinear conv. failures = 0
 
-Number of linear iterations        = 1049
+Number of linear iterations        = 1039
 Number of linear conv. failures    = 0
 
 Number of preconditioner setups    = 25
-Number of preconditioner solves    = 1257
+Number of preconditioner solves    = 1247
diff --git a/examples/ida/parallel/idaHeat2D_kry_bbd_p.c b/examples/ida/parallel/idaHeat2D_kry_bbd_p.c
index 36402f3..80d1a36 100644
--- a/examples/ida/parallel/idaHeat2D_kry_bbd_p.c
+++ b/examples/ida/parallel/idaHeat2D_kry_bbd_p.c
@@ -1,16 +1,13 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *         Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, parallel, GMRES,
  * IDABBDPRE.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the Krylov solver IDASpgmr and BBD
+ * This version uses the Krylov solver SUNSPGMR and BBD
  * preconditioning.
  *
  * The DAE system solved is a spatial discretization of the PDE
@@ -27,7 +24,7 @@
  * processors.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR in conjunction with the preconditioner module IDABBDPRE.
+ * SUNSPGMR in conjunction with the preconditioner module IDABBDPRE.
  * The preconditioner uses a tridiagonal approximation
  * (half-bandwidths = 1). The constraints u >= 0 are posed for all
  * components. Local error testing on the boundary values is
@@ -40,8 +37,9 @@
 #include <math.h>
 
 #include <ida/ida.h>
-#include <ida/ida_spgmr.h>
+#include <ida/ida_spils.h>
 #include <ida/ida_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
@@ -66,7 +64,7 @@
 
 typedef struct {  
   int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
-  long int n_local;
+  sunindextype n_local;
   realtype dx, dy, coeffx, coeffy, coeffxy;
   realtype uext[(MXSUB+2)*(MYSUB+2)];
   MPI_Comm comm;
@@ -74,15 +72,13 @@ typedef struct {
 
 /* Prototypes of user-supplied and supporting functions */
 
-static int heatres(realtype tres, 
-                   N_Vector uu, N_Vector up, N_Vector res, 
-                   void *user_data);
+static int heatres(realtype tres, N_Vector uu, N_Vector up,
+                   N_Vector res, void *user_data);
 
-static int rescomm(long int Nlocal, realtype tt, 
-                   N_Vector uu, N_Vector up, 
-                   void *user_data);
+static int rescomm(sunindextype Nlocal, realtype tt, 
+                   N_Vector uu, N_Vector up, void *user_data);
 
-static int reslocal(long int Nlocal, realtype tres, 
+static int reslocal(sunindextype Nlocal, realtype tres, 
                     N_Vector uu, N_Vector up, N_Vector res,  
                     void *user_data);
 
@@ -105,13 +101,13 @@ static int InitUserData(int thispe, MPI_Comm comm, UserData data);
 static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
                              N_Vector res, UserData data);
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol);
 
 static void PrintCase(int case_number, int mudq, int mukeep);
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -124,14 +120,16 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
   int thispe, iout, ier, npes;
-  long int Neq, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype Neq, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, t1, tout, tret;
   N_Vector uu, up, constraints, id, res;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
 
@@ -194,26 +192,26 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize solution */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetUserData(mem, data);
+  ier = IDASetUserData(ida_mem, data);
   if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetSuppressAlg(mem, TRUE);
+  ier = IDASetSuppressAlg(ida_mem, SUNTRUE);
   if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetId(mem, id);
+  ier = IDASetId(ida_mem, id);
   if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetConstraints(mem, constraints);
+  ier = IDASetConstraints(ida_mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
   N_VDestroy_Parallel(constraints);
 
-  ier = IDAInit(mem, heatres, t0, uu, up);
+  ier = IDAInit(ida_mem, heatres, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASStolerances(mem, rtol, atol);
+  ier = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
   mudq = MXSUB;
@@ -231,12 +229,19 @@ int main(int argc, char *argv[])
    * ----------------------------- 
    */
 
-  /* Call IDASpgmr to specify the linear solver. */
-  ier = IDASpgmr(mem, 0);
-  if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the linear solver. */
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);  /* IDA recommends left-preconditioning only;
+                                       0 indicates to use default maxl value */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  ier = SUNSPGMRSetMaxRestarts(LS, 5);  /* IDA recommends allowing up to 5 restarts */
+  if(check_flag(&ier, "SUNSPGMRSetMaxRestarts", 1, thispe)) MPI_Abort(comm, 1);
+
+  ier = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
   
   /* Call IDABBDPrecInit to initialize BBD preconditioner. */
-  ier = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  ier = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                        ZERO, reslocal, NULL);
   if(check_flag(&ier, "IDABBDPrecAlloc", 1, thispe)) MPI_Abort(comm, 1);
 
@@ -246,15 +251,15 @@ int main(int argc, char *argv[])
   /* Loop over tout, call IDASolve, print output. */
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) { 
     
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(thispe, mem, tret, uu);
+    PrintOutput(thispe, ida_mem, tret, uu);
     
   }
 
   /* Print final statistics */
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
   
   /*
    * ----------------------------- 
@@ -269,11 +274,11 @@ int main(int argc, char *argv[])
   SetInitialProfile(uu, up, id, res, data);
 
   /* Call IDAReInit to re-initialize IDA. */
-  ier = IDAReInit(mem, t0, uu, up);
+  ier = IDAReInit(ida_mem, t0, uu, up);
   if(check_flag(&ier, "IDAReInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDABBDPrecReInit to re-initialize BBD preconditioner. */
-  ier = IDABBDPrecReInit(mem, mudq, mldq, ZERO);
+  ier = IDABBDPrecReInit(ida_mem, mudq, mldq, ZERO);
   if(check_flag(&ier, "IDABBDPrecReInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Print output heading (on processor 0 only). */
@@ -282,18 +287,19 @@ int main(int argc, char *argv[])
   /* Loop over tout, call IDASolve, print output. */
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) { 
     
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(thispe, mem, tret, uu);
+    PrintOutput(thispe, ida_mem, tret, uu);
     
   }
   
   /* Print final statistics */
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
 
   /* Free Memory */
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
   free(data);
   N_VDestroy_Parallel(id);
   N_VDestroy_Parallel(res);
@@ -332,7 +338,7 @@ static int heatres(realtype tres, N_Vector uu, N_Vector up,
 {
   int retval;
   UserData data;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   data = (UserData) user_data;
   
@@ -353,7 +359,7 @@ static int heatres(realtype tres, N_Vector uu, N_Vector up,
  * communication of data in u needed to calculate G.                 
  */
 
-static int rescomm(long int Nlocal, realtype tt, 
+static int rescomm(sunindextype Nlocal, realtype tt, 
                    N_Vector uu, N_Vector up, void *user_data)
 {
   UserData data;
@@ -390,7 +396,7 @@ static int rescomm(long int Nlocal, realtype tt,
  *  has already been done, and that this data is in the work array uext.  
  */
 
-static int reslocal(long int Nlocal, realtype tres, 
+static int reslocal(sunindextype Nlocal, realtype tres, 
                     N_Vector uu, N_Vector up, N_Vector res,  
                     void *user_data)
 {
@@ -697,14 +703,14 @@ static int SetInitialProfile(N_Vector uu, N_Vector up,  N_Vector id,
  * and table heading
  */
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol)
 {
     printf("\nidaHeat2D_kry_bbd_p: Heat equation, parallel example problem for IDA\n");
     printf("                Discretized heat equation on 2D unit square.\n");
     printf("                Zero boundary conditions,");
     printf(" polynomial initial conditions.\n");
     printf("                Mesh dimensions: %d x %d", MX, MY);
-    printf("        Total system size: %ld\n\n", Neq);
+    printf("        Total system size: %ld\n\n", (long int) Neq);
 
     printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
     printf("         Processor array: %d x %d\n", NPEX, NPEY);
@@ -716,9 +722,9 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
     printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
     printf("Constraints set to force all solution components >= 0. \n");
-    printf("SUPPRESSALG = TRUE to suppress local error testing on");
+    printf("SUPPRESSALG = SUNTRUE to suppress local error testing on");
     printf(" all boundary components. \n");
-    printf("Linear solver: IDASPGMR.    ");
+    printf("Linear solver: SUNSPGMR.    ");
     printf("Preconditioner: IDABBDPRE - Banded-block-diagonal.\n"); 
 
 }
@@ -743,7 +749,7 @@ static void PrintCase(int case_number, int mudq, int mukeep)
  * Print integrator statistics and max-norm of solution
  */
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu)
 {
   realtype umax, hused;
   int kused, ier;
@@ -753,25 +759,25 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
   
   if (id == 0) {
 
-    ier = IDAGetLastOrder(mem, &kused);
+    ier = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&ier, "IDAGetLastOrder", 1, id);
-    ier = IDAGetNumSteps(mem, &nst);
+    ier = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&ier, "IDAGetNumSteps", 1, id);
-    ier = IDAGetNumNonlinSolvIters(mem, &nni);
+    ier = IDAGetNumNonlinSolvIters(ida_mem, &nni);
     check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
-    ier = IDAGetNumResEvals(mem, &nre);
+    ier = IDAGetNumResEvals(ida_mem, &nre);
     check_flag(&ier, "IDAGetNumResEvals", 1, id);
-    ier = IDAGetLastStep(mem, &hused);
+    ier = IDAGetLastStep(ida_mem, &hused);
     check_flag(&ier, "IDAGetLastStep", 1, id);
-    ier = IDASpilsGetNumLinIters(mem, &nli);
+    ier = IDASpilsGetNumLinIters(ida_mem, &nli);
     check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
-    ier = IDASpilsGetNumResEvals(mem, &nreLS);
+    ier = IDASpilsGetNumResEvals(ida_mem, &nreLS);
     check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
-    ier = IDABBDPrecGetNumGfnEvals(mem, &nge);
+    ier = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
     check_flag(&ier, "IDABBDPrecGetNumGfnEvals", 1, id);
-    ier = IDASpilsGetNumPrecEvals(mem, &npe);
+    ier = IDASpilsGetNumPrecEvals(ida_mem, &npe);
     check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
-    ier = IDASpilsGetNumPrecSolves(mem, &nps);
+    ier = IDASpilsGetNumPrecSolves(ida_mem, &nps);
     check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -792,13 +798,13 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
  * Print some final integrator statistics
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int netf, ncfn, ncfl;
 
-  IDAGetNumErrTestFails(mem, &netf);
-  IDAGetNumNonlinSolvConvFails(mem, &ncfn);
-  IDASpilsGetNumConvFails(mem, &ncfl);
+  IDAGetNumErrTestFails(ida_mem, &netf);
+  IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
+  IDASpilsGetNumConvFails(ida_mem, &ncfl);
 
   printf("\nError test failures            = %ld\n", netf);
   printf("Nonlinear convergence failures = %ld\n", ncfn);
diff --git a/examples/ida/parallel/idaHeat2D_kry_bbd_p.out b/examples/ida/parallel/idaHeat2D_kry_bbd_p.out
index 388faeb..c0cdb5c 100644
--- a/examples/ida/parallel/idaHeat2D_kry_bbd_p.out
+++ b/examples/ida/parallel/idaHeat2D_kry_bbd_p.out
@@ -1,3 +1,4 @@
+
 idaHeat2D_kry_bbd_p: Heat equation, parallel example problem for IDA
                 Discretized heat equation on 2D unit square.
                 Zero boundary conditions, polynomial initial conditions.
@@ -6,8 +7,8 @@ idaHeat2D_kry_bbd_p: Heat equation, parallel example problem for IDA
 Subgrid dimensions: 5 x 5         Processor array: 2 x 2
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-SUPPRESSALG = TRUE to suppress local error testing on all boundary components. 
-Linear solver: IDASPGMR.    Preconditioner: IDABBDPRE - Banded-block-diagonal.
+SUPPRESSALG = SUNTRUE to suppress local error testing on all boundary components. 
+Linear solver: SUNSPGMR.    Preconditioner: IDABBDPRE - Banded-block-diagonal.
 
 
 Case 1. 
@@ -15,19 +16,19 @@ Case 1.
 
    Output Summary (umax = max-norm of solution) 
 
-  time     umax       k  nst  nni  nli   nre nreLS nge   h      npe nps
+  time     umax       k  nst  nni  nli   nre nreLS nge     h      npe nps
  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
   0.01   8.24107e-01  2   12   14    7    14    7   96  2.56e-03    8  21
   0.02   6.88124e-01  3   15   18   12    18   12   96  5.12e-03    8  30
   0.04   4.70754e-01  3   18   24   22    24   22  108  6.58e-03    9  46
   0.08   2.16600e-01  3   22   29   30    29   30  108  1.32e-02    9  59
   0.16   4.56595e-02  4   28   37   43    37   43  120  2.63e-02   10  80
-  0.32   2.10959e-03  4   35   45   59    45   59  120  2.37e-02   10 104
-  0.64   5.53681e-05  1   40   54   71    54   71  156  1.90e-01   13 125
-  1.28   1.55972e-19  1   42   56   71    56   71  180  7.58e-01   15 127
-  2.56   3.38647e-21  1   43   57   71    57   71  192  1.52e+00   16 128
-  5.12   8.60743e-21  1   44   58   71    58   71  204  3.03e+00   17 129
- 10.24   1.66301e-20  1   45   59   71    59   71  216  6.06e+00   18 130
+  0.32   2.10967e-03  4   35   45   59    45   59  120  2.37e-02   10 104
+  0.64   3.16252e-05  1   40   54   73    54   73  156  1.90e-01   13 127
+  1.28   4.37189e-19  1   42   56   73    56   73  180  7.58e-01   15 129
+  2.56   9.47890e-21  1   43   57   73    57   73  192  1.52e+00   16 130
+  5.12   1.69074e-20  1   44   58   73    58   73  204  3.03e+00   17 131
+ 10.24   2.64109e-20  1   45   59   73    59   73  216  6.06e+00   18 132
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
@@ -39,7 +40,7 @@ Case 2.
 
    Output Summary (umax = max-norm of solution) 
 
-  time     umax       k  nst  nni  nli   nre nreLS nge   h      npe nps
+  time     umax       k  nst  nni  nli   nre nreLS nge     h      npe nps
  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
   0.01   8.24111e-01  2   12   14    7    14    7   32  2.56e-03    8  21
   0.02   6.88118e-01  3   15   18   12    18   12   32  5.12e-03    8  30
@@ -47,11 +48,11 @@ Case 2.
   0.08   2.16547e-01  3   23   27   32    27   32   36  1.02e-02    9  59
   0.16   4.52248e-02  4   27   33   44    33   44   40  2.05e-02   10  77
   0.32   2.18677e-03  3   34   41   67    41   67   44  4.10e-02   11 108
-  0.64   4.88467e-19  1   39   49   86    49   86   52  1.64e-01   13 135
-  1.28   5.39822e-19  1   41   51   86    51   86   60  6.55e-01   15 137
-  2.56   7.41945e-18  1   42   52   86    52   86   64  1.31e+00   16 138
-  5.12   6.10808e-17  1   43   53   86    53   86   68  2.62e+00   17 139
- 10.24   4.05358e-16  1   44   54   86    54   86   72  5.24e+00   18 140
+  0.64   3.25106e-19  1   39   49   86    49   86   52  1.64e-01   13 135
+  1.28   1.66623e-19  1   41   51   86    51   86   60  6.55e-01   15 137
+  2.56   1.06302e-18  1   42   52   86    52   86   64  1.31e+00   16 138
+  5.12   8.93778e-18  1   43   53   86    53   86   68  2.62e+00   17 139
+ 10.24   6.99660e-17  1   44   54   86    54   86   72  5.24e+00   18 140
 
 Error test failures            = 0
 Nonlinear convergence failures = 0
diff --git a/examples/ida/parallel/idaHeat2D_kry_p.c b/examples/ida/parallel/idaHeat2D_kry_p.c
index ab1394e..e070571 100644
--- a/examples/ida/parallel/idaHeat2D_kry_p.c
+++ b/examples/ida/parallel/idaHeat2D_kry_p.c
@@ -1,15 +1,12 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *         Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, parallel, GMRES.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the Krylov solver IDASpgmr.
+ * This version uses the Krylov solver SUNSPGMR.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -25,9 +22,9 @@
  * processors.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR. The preconditioner uses the diagonal elements of the
+ * SUNSPGMR. The preconditioner uses the diagonal elements of the
  * Jacobian only. Routines for preconditioning, required by
- * IDASPGMR, are supplied here. The constraints u >= 0 are posed
+ * SUNSPGMR, are supplied here. The constraints u >= 0 are posed
  * for all components. Local error testing on the boundary values
  * is suppressed. Output is taken at t = 0, .01, .02, .04,
  * ..., 10.24.
@@ -39,7 +36,8 @@
 #include <math.h>
 
 #include <ida/ida.h>
-#include <ida/ida_spgmr.h>
+#include <ida/ida_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
@@ -63,7 +61,8 @@
                                     /* Spatial mesh is MX by MY */
 
 typedef struct {  
-  long int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
+  int thispe, npex, npey, ixsub, jysub;
+  sunindextype mx, my, mxsub, mysub;
   realtype    dx, dy, coeffx, coeffy, coeffxy;
   realtype    uext[(MXSUB+2)*(MYSUB+2)];
   N_Vector    pp;    /* vector of diagonal preconditioner elements */
@@ -72,38 +71,32 @@ typedef struct {
 
 /* User-supplied residual function and supporting routines */
 
-int resHeat(realtype tt, 
-            N_Vector uu, N_Vector up, N_Vector rr, 
-            void *user_data);
+int resHeat(realtype tt, N_Vector uu, N_Vector up,
+            N_Vector rr, void *user_data);
 
 static int rescomm(N_Vector uu, N_Vector up, void *user_data);
 
 static int reslocal(realtype tt, N_Vector uu, N_Vector up, 
                     N_Vector res,  void *user_data);
 
-static int BSend(MPI_Comm comm, long int thispe, long int ixsub, long int jysub,
-                 long int dsizex, long int dsizey, realtype uarray[]);
+static int BSend(MPI_Comm comm, int thispe, int ixsub, int jysub,
+                 sunindextype dsizex, sunindextype dsizey, realtype uarray[]);
 
-static int BRecvPost(MPI_Comm comm, MPI_Request request[], long int thispe,
-                     long int ixsub, long int jysub,
-                     long int dsizex, long int dsizey,
-                     realtype uext[], realtype buffer[]);
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+                     int ixsub, int jysub, sunindextype dsizex,
+                     sunindextype dsizey, realtype uext[], realtype buffer[]);
 
-static int BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
-                     long int dsizex, realtype uext[], realtype buffer[]);
+static int BRecvWait(MPI_Request request[], int ixsub, int jysub,
+                     sunindextype dsizex, realtype uext[], realtype buffer[]);
 
 /* User-supplied preconditioner routines */
 
-int PsolveHeat(realtype tt, 
-               N_Vector uu, N_Vector up, N_Vector rr, 
-               N_Vector rvec, N_Vector zvec,
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp);
+int PsolveHeat(realtype tt, N_Vector uu, N_Vector up, N_Vector rr, 
+               N_Vector rvec, N_Vector zvec, realtype c_j,
+               realtype delta, void *user_data);
 
-int PsetupHeat(realtype tt, 
-               N_Vector yy, N_Vector yp, N_Vector rr, 
-               realtype c_j, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+int PsetupHeat(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, 
+               realtype c_j, void *user_data);
 
 /* Private function to check function return values */
 
@@ -112,11 +105,11 @@ static int InitUserData(int thispe, MPI_Comm comm, UserData data);
 static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
                              N_Vector res, UserData data);
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol);
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -129,14 +122,16 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
   int iout, thispe, ier, npes;
-  long int Neq, local_N;
+  sunindextype Neq, local_N;
   realtype rtol, atol, t0, t1, tout, tret;
   N_Vector uu, up, constraints, id, res;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
 
@@ -212,59 +207,63 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize solution. */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetUserData(mem, data);
+  ier = IDASetUserData(ida_mem, data);
   if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetSuppressAlg(mem, TRUE);
+  ier = IDASetSuppressAlg(ida_mem, SUNTRUE);
   if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetId(mem, id);
+  ier = IDASetId(ida_mem, id);
   if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetConstraints(mem, constraints);
+  ier = IDASetConstraints(ida_mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
   N_VDestroy_Parallel(constraints);  
 
-  ier = IDAInit(mem, resHeat, t0, uu, up);
+  ier = IDAInit(ida_mem, resHeat, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  ier = IDASStolerances(mem, rtol, atol);
+  ier = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the linear solver. */
+  /* Call SUNSPGMR and IDASetLinearSolver to specify the linear solver. */
+
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);  /* use default maxl */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASpgmr(mem, 0);
-  if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  ier = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
+  ier = IDASpilsSetPreconditioner(ida_mem, PsetupHeat, PsolveHeat);
   if(check_flag(&ier, "IDASpilsSetPreconditioner", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Print output heading (on processor 0 only) and intial solution  */
   
   if (thispe == 0) PrintHeader(Neq, rtol, atol);
-  PrintOutput(thispe, mem, t0, uu); 
+  PrintOutput(thispe, ida_mem, t0, uu); 
   
   /* Loop over tout, call IDASolve, print output. */
 
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) {
 
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(thispe, mem, tret, uu);
+    PrintOutput(thispe, ida_mem, tret, uu);
 
   }
   
   /* Print remaining counters. */
 
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
 
   /* Free memory */
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   N_VDestroy_Parallel(id);
   N_VDestroy_Parallel(res);
@@ -302,8 +301,7 @@ int main(int argc, char *argv[])
  * of uu required to calculate the residual. 
  */
 
-int resHeat(realtype tt, 
-            N_Vector uu, N_Vector up, N_Vector rr, 
+int resHeat(realtype tt, N_Vector uu, N_Vector up, N_Vector rr, 
             void *user_data)
 {
   int retval;
@@ -336,14 +334,12 @@ int resHeat(realtype tt,
  *
  */
 
-int PsetupHeat(realtype tt, 
-               N_Vector yy, N_Vector yp, N_Vector rr, 
-               realtype c_j, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+int PsetupHeat(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, 
+               realtype c_j, void *user_data)
 {
   realtype *ppv, pelinv;
-  long int lx, ly, ixbegin, ixend, jybegin, jyend, locu, mxsub, mysub;
-  long int ixsub, jysub, npex, npey;
+  sunindextype lx, ly, ixbegin, ixend, jybegin, jyend, locu, mxsub, mysub;
+  int ixsub, jysub, npex, npey;
   UserData data;
 
   data = (UserData) user_data;
@@ -389,11 +385,9 @@ int PsetupHeat(realtype tt,
  * computed in PsetupHeat), returning the result in zvec.      
  */
 
-int PsolveHeat(realtype tt, 
-               N_Vector uu, N_Vector up, N_Vector rr, 
-               N_Vector rvec, N_Vector zvec,
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp)
+int PsolveHeat(realtype tt, N_Vector uu, N_Vector up,
+               N_Vector rr, N_Vector rvec, N_Vector zvec,
+               realtype c_j, realtype delta, void *user_data)
 {
   UserData data;
 
@@ -422,7 +416,8 @@ static int rescomm(N_Vector uu, N_Vector up, void *user_data)
   UserData data;
   realtype *uarray, *uext, buffer[2*MYSUB];
   MPI_Comm comm;
-  long int thispe, ixsub, jysub, mxsub, mysub;
+  int thispe, ixsub, jysub;
+  sunindextype mxsub, mysub;
   MPI_Request request[4];
   
   data = (UserData) user_data;
@@ -453,15 +448,15 @@ static int rescomm(N_Vector uu, N_Vector up, void *user_data)
  * has already been done, and that this data is in the work array uext.  
  */
 
-static int reslocal(realtype tt, 
-                    N_Vector uu, N_Vector up, N_Vector rr,
+static int reslocal(realtype tt, N_Vector uu, N_Vector up, N_Vector rr,
                     void *user_data)
 {
   realtype *uext, *uuv, *upv, *resv;
   realtype termx, termy, termctr;
-  long int lx, ly, offsetu, offsetue, locu, locue;
-  long int ixsub, jysub, mxsub, mxsub2, mysub, npex, npey;
-  long int ixbegin, ixend, jybegin, jyend;
+  sunindextype lx, ly, offsetu, offsetue, locu, locue;
+  int ixsub, jysub, npex, npey;
+  sunindextype mxsub, mxsub2, mysub;
+  sunindextype ixbegin, ixend, jybegin, jyend;
   UserData data;
   
   /* Get subgrid indices, array sizes, extended work array uext. */
@@ -520,10 +515,10 @@ static int reslocal(realtype tt,
  * Routine to send boundary data to neighboring PEs.                     
  */
 
-static int BSend(MPI_Comm comm, long int thispe, long int ixsub, long int jysub,
-                 long int dsizex, long int dsizey, realtype uarray[])
+static int BSend(MPI_Comm comm, int thispe, int ixsub, int jysub,
+                 sunindextype dsizex, sunindextype dsizey, realtype uarray[])
 {
-  long int ly, offsetu;
+  sunindextype ly, offsetu;
   realtype bufleft[MYSUB], bufright[MYSUB];
 
   /* If jysub > 0, send data from bottom x-line of u. */
@@ -573,12 +568,11 @@ static int BSend(MPI_Comm comm, long int thispe, long int ixsub, long int jysub,
  *      both calls also. 
  */
 
-static int BRecvPost(MPI_Comm comm, MPI_Request request[], long int thispe,
-                     long int ixsub, long int jysub,
-                     long int dsizex, long int dsizey,
-                     realtype uext[], realtype buffer[])
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+                     int ixsub, int jysub, sunindextype dsizex,
+                     sunindextype dsizey, realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer. */
   realtype *bufleft = buffer, *bufright = buffer+MYSUB;
   
@@ -620,10 +614,10 @@ static int BRecvPost(MPI_Comm comm, MPI_Request request[], long int thispe,
  *      calls also. 
  */
 
-static int BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
-                     long int dsizex, realtype uext[], realtype buffer[])
+static int BRecvWait(MPI_Request request[], int ixsub, int jysub,
+                     sunindextype dsizex, realtype uext[], realtype buffer[])
 {
-  long int ly, dsizex2, offsetue;
+  sunindextype ly, dsizex2, offsetue;
   realtype *bufleft = buffer, *bufright = buffer+MYSUB;
   MPI_Status status;
   
@@ -701,8 +695,9 @@ static int InitUserData(int thispe, MPI_Comm comm, UserData data)
 static int SetInitialProfile(N_Vector uu, N_Vector up,  N_Vector id, 
                              N_Vector res, UserData data)
 {
-  long int i, iloc, j, jloc, offset, loc, ixsub, jysub;
-  long int ixbegin, ixend, jybegin, jyend;
+  int ixsub, jysub;
+  sunindextype i, iloc, j, jloc, offset, loc;
+  sunindextype ixbegin, ixend, jybegin, jyend;
   realtype xfact, yfact, *udata, *iddata, dx, dy;
   
   /* Initialize uu. */ 
@@ -756,14 +751,14 @@ static int SetInitialProfile(N_Vector uu, N_Vector up,  N_Vector id,
  * Print first lines of output and table heading
  */
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol)
 { 
   printf("\nidaHeat2D_kry_p: Heat equation, parallel example problem for IDA\n");
   printf("            Discretized heat equation on 2D unit square.\n");
   printf("            Zero boundary conditions,");
   printf(" polynomial initial conditions.\n");
   printf("            Mesh dimensions: %d x %d", MX, MY);
-  printf("        Total system size: %ld\n\n", Neq);
+  printf("        Total system size: %ld\n\n", (long int) Neq);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("        Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -774,9 +769,9 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("SUPPRESSALG = TRUE to suppress local error testing on ");
+  printf("SUPPRESSALG = SUNTRUE to suppress local error testing on ");
   printf("all boundary components. \n");
-  printf("Linear solver: IDASPGMR  ");
+  printf("Linear solver: SUNSPGMR  ");
   printf("Preconditioner: diagonal elements only.\n"); 
   
   /* Print output table heading and initial line of table. */
@@ -789,7 +784,7 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
  * PrintOutput: print max norm of solution and current solver statistics
  */
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu)
 {
   realtype hused, umax;
   long int nst, nni, nje, nre, nreLS, nli, npe, nps;
@@ -799,25 +794,25 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
 
   if (id == 0) {
 
-    ier = IDAGetLastOrder(mem, &kused);
+    ier = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&ier, "IDAGetLastOrder", 1, id);
-    ier = IDAGetNumSteps(mem, &nst);
+    ier = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&ier, "IDAGetNumSteps", 1, id);
-    ier = IDAGetNumNonlinSolvIters(mem, &nni);
+    ier = IDAGetNumNonlinSolvIters(ida_mem, &nni);
     check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
-    ier = IDAGetNumResEvals(mem, &nre);
+    ier = IDAGetNumResEvals(ida_mem, &nre);
     check_flag(&ier, "IDAGetNumResEvals", 1, id);
-    ier = IDAGetLastStep(mem, &hused);
+    ier = IDAGetLastStep(ida_mem, &hused);
     check_flag(&ier, "IDAGetLastStep", 1, id);
-    ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+    ier = IDASpilsGetNumJtimesEvals(ida_mem, &nje);
     check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1, id);
-    ier = IDASpilsGetNumLinIters(mem, &nli);
+    ier = IDASpilsGetNumLinIters(ida_mem, &nli);
     check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
-    ier = IDASpilsGetNumResEvals(mem, &nreLS);
+    ier = IDASpilsGetNumResEvals(ida_mem, &nreLS);
     check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
-    ier = IDASpilsGetNumPrecEvals(mem, &npe);
+    ier = IDASpilsGetNumPrecEvals(ida_mem, &npe);
     check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
-    ier = IDASpilsGetNumPrecSolves(mem, &nps);
+    ier = IDASpilsGetNumPrecSolves(ida_mem, &nps);
     check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)  
@@ -838,13 +833,13 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
  * Print some final integrator statistics
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int netf, ncfn, ncfl;
 
-  IDAGetNumErrTestFails(mem, &netf);
-  IDAGetNumNonlinSolvConvFails(mem, &ncfn);
-  IDASpilsGetNumConvFails(mem, &ncfl);
+  IDAGetNumErrTestFails(ida_mem, &netf);
+  IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
+  IDASpilsGetNumConvFails(ida_mem, &ncfl);
 
   printf("\nError test failures            = %ld\n", netf);
   printf("Nonlinear convergence failures = %ld\n", ncfn);
diff --git a/examples/ida/parallel/idaHeat2D_kry_p.out b/examples/ida/parallel/idaHeat2D_kry_p.out
index 12e1b95..187962e 100644
--- a/examples/ida/parallel/idaHeat2D_kry_p.out
+++ b/examples/ida/parallel/idaHeat2D_kry_p.out
@@ -7,8 +7,8 @@ idaHeat2D_kry_p: Heat equation, parallel example problem for IDA
 Subgrid dimensions: 5 x 5        Processor array: 2 x 2
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-SUPPRESSALG = TRUE to suppress local error testing on all boundary components. 
-Linear solver: IDASPGMR  Preconditioner: diagonal elements only.
+SUPPRESSALG = SUNTRUE to suppress local error testing on all boundary components. 
+Linear solver: SUNSPGMR  Preconditioner: diagonal elements only.
 
    Output Summary (umax = max-norm of solution) 
 
@@ -23,9 +23,9 @@ Linear solver: IDASPGMR  Preconditioner: diagonal elements only.
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
   0.64   5.54028e-21  1   39   51   77    51    77   1.05e-01   12 128
   1.28   3.85107e-20  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   5.00523e-20  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   1.50906e-19  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   4.63224e-19  1   45   57   77    57    77   6.74e+00   18 134
+  2.56   5.56136e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   1.92667e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   5.91880e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
diff --git a/examples/ida/petsc/CMakeLists.txt b/examples/ida/petsc/CMakeLists.txt
index 52e3a84..77ee193 100644
--- a/examples/ida/petsc/CMakeLists.txt
+++ b/examples/ida/petsc/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4137 $
-# $Date: 2014-06-15 12:26:15 -0700 (Sun, 15 Jun 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Slaven Peles, Eddy Banks @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,72 +12,78 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for IDA PETSc examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable IDA_examples with the names of the PETSc IDA examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(IDA_examples
   #"idaHeat2D_jac_petsc\;1\;4"  # Not to be released in 2.7.0
-  "idaHeat2D_kry_petsc\;1\;4"
+  "idaHeat2D_kry_petsc\;1\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the C compiler to the MPICC script.
 # If not, then add the MPI include directory for MPI headers.
-
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECP_LIB sundials_nvecpetsc_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECP_LIB sundials_nvecpetsc_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${IDA_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
 
-SET(SUNDIALS_LIBS ${IDA_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS} ${PETSC_LIBRARIES})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-# Add the build and install targets for each IDA example
 
+# Add the build and install targets for each example
 FOREACH(example_tuple ${IDA_examples})
+
   list(GET example_tuple 0 example)
   list(GET example_tuple 1 number_of_nodes)
   list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  list(GET example_tuple 3 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${PETSC_LIBRARIES})
+
   IF(NOT MPI_MPICC)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  ENDIF()
+
+  # install example
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/petsc)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/petsc)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${IDA_examples})
 
+
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -89,31 +92,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
-  FOREACH(example_tuple ${IDA_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${IDA_examples})
-  
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+
+  EXAMPLES2STRING(IDA_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_petsc_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/petsc/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_petsc_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/petsc/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/petsc/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/petsc 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/petsc
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/ida/petsc/README b/examples/ida/petsc/README
index a57edc0..e0a1bfb 100644
--- a/examples/ida/petsc/README
+++ b/examples/ida/petsc/README
@@ -1,14 +1,13 @@
 List of PETSc IDA examples
 
-  idaHeat2D_kry_petsc  : 2-D heat equation, diagonal preconditioner
-  idaHeat2D_kry_bbd_petsc : Not supposed to work with PETSc vector
+  idaHeat2D_kry_petsc  : 2D heat equation with SPGMR and PETSc vector
+  idaHeat2D_jac_petsc  : 2D heat equation with default PETSc Krylov solver
 
 
 The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/ida/petsc/idaHeat2D_kry_petsc.c b/examples/ida/petsc/idaHeat2D_kry_petsc.c
index f681a0f..94263eb 100644
--- a/examples/ida/petsc/idaHeat2D_kry_petsc.c
+++ b/examples/ida/petsc/idaHeat2D_kry_petsc.c
@@ -1,9 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4882 $
- * $Date: 2016-09-01 16:05:08 -0700 (Thu, 01 Sep 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Slaven Peles @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Slaven Peles @ LLNL
  * -----------------------------------------------------------------
  * Based on PETSc TS example 15 and a SUNDIALS example by 
  * Allan Taylor, Alan Hindmarsh and Radu Serban
@@ -11,7 +9,7 @@
  * Example problem for IDA: 2D heat equation, PETSc vector, GMRES.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the Krylov solver IDASpgmr.
+ * This version uses the Krylov solver SUNSPGMR.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -27,9 +25,9 @@
  * processors.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR. The preconditioner uses the diagonal elements of the
+ * SUNSPGMR. The preconditioner uses the diagonal elements of the
  * Jacobian only. Routines for preconditioning, required by
- * IDASPGMR, are supplied here. The constraints u >= 0 are posed
+ * SUNSPGMR, are supplied here. The constraints u >= 0 are posed
  * for all components. Local error testing on the boundary values
  * is suppressed. Output is taken at t = 0, .01, .02, .04,
  * ..., 10.24.
@@ -44,7 +42,8 @@
 #include <math.h>
 
 #include <ida/ida.h>
-#include <ida/ida_spgmr.h>
+#include <ida/ida_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_petsc.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
@@ -80,27 +79,23 @@ int resHeat(realtype tt, N_Vector uu, N_Vector up, N_Vector rr, void *user_data)
 
 /* User-supplied preconditioner routines */
 
-int PsetupHeat(realtype tt, 
-               N_Vector yy, N_Vector yp, N_Vector rr, 
-               realtype c_j, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+int PsetupHeat(realtype tt, N_Vector yy, N_Vector yp,
+               N_Vector rr, realtype c_j, void *user_data);
 
-int PsolveHeat(realtype tt, 
-               N_Vector uu, N_Vector up, N_Vector rr, 
-               N_Vector rvec, N_Vector zvec,
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp);
+int PsolveHeat(realtype tt, N_Vector uu, N_Vector up,
+               N_Vector rr, N_Vector rvec, N_Vector zvec,
+               realtype c_j, realtype delta, void *user_data);
 
 /* Private function to check function return values */
 
 static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
                              N_Vector res, void *user_data);
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol);
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -113,16 +108,18 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
   int iout, thispe, ier, npes;
-  long int Neq;
+  sunindextype Neq;
   realtype rtol, atol, t0, t1, tout, tret;
   N_Vector uu, up, constraints, id, res;
   PetscErrorCode ierr;                  /* PETSc error code  */
   Vec uvec;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
 
@@ -219,59 +216,63 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize solution. */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetUserData(mem, data);
+  ier = IDASetUserData(ida_mem, data);
   if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetSuppressAlg(mem, TRUE);
+  ier = IDASetSuppressAlg(ida_mem, SUNTRUE);
   if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetId(mem, id);
+  ier = IDASetId(ida_mem, id);
   if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetConstraints(mem, constraints);
+  ier = IDASetConstraints(ida_mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
   N_VDestroy_Petsc(constraints);  
 
-  ier = IDAInit(mem, resHeat, t0, uu, up);
+  ier = IDAInit(ida_mem, resHeat, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  ier = IDASStolerances(mem, rtol, atol);
+  ier = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the linear solver. */
+  /* Call SUNSPGMR and IDASetLinearSolver to specify the linear solver. */
+
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);  /* use default maxl */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASpgmr(mem, 0);
-  if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  ier = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
+  ier = IDASpilsSetPreconditioner(ida_mem, PsetupHeat, PsolveHeat);
   if(check_flag(&ier, "IDASpilsSetPreconditioner", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Print output heading (on processor 0 only) and intial solution  */
   
   if (thispe == 0) PrintHeader(Neq, rtol, atol);
-  PrintOutput(thispe, mem, t0, uu); 
+  PrintOutput(thispe, ida_mem, t0, uu); 
   
   /* Loop over tout, call IDASolve, print output. */
 
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) {
 
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(thispe, mem, tret, uu);
+    PrintOutput(thispe, ida_mem, tret, uu);
 
   }
   
   /* Print remaining counters. */
 
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
 
   /* Free memory */
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   N_VDestroy_Petsc(id);
   N_VDestroy_Petsc(res);
@@ -311,8 +312,7 @@ int main(int argc, char *argv[])
  *                    
  */
 
-int resHeat(realtype tt, 
-            N_Vector uu, N_Vector up, N_Vector rr, 
+int resHeat(realtype tt, N_Vector uu, N_Vector up, N_Vector rr, 
             void *user_data)
 {
   PetscErrorCode ierr;
@@ -418,10 +418,8 @@ int resHeat(realtype tt,
  *
  */
 
-int PsetupHeat(realtype tt, 
-               N_Vector yy, N_Vector yp, N_Vector rr, 
-               realtype c_j, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+int PsetupHeat(realtype tt, N_Vector yy, N_Vector yp,
+               N_Vector rr, realtype c_j, void *user_data)
 {
   PetscErrorCode ierr;
   PetscInt    i, j, Mx, My, xs, ys, xm, ym;
@@ -482,11 +480,9 @@ int PsetupHeat(realtype tt,
  * computed in PsetupHeat), returning the result in zvec.      
  */
 
-int PsolveHeat(realtype tt, 
-               N_Vector uu, N_Vector up, N_Vector rr, 
-               N_Vector rvec, N_Vector zvec,
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp)
+int PsolveHeat(realtype tt, N_Vector uu, N_Vector up,
+               N_Vector rr, N_Vector rvec, N_Vector zvec,
+               realtype c_j, realtype delta, void *user_data)
 {
   UserData data;
 
@@ -593,14 +589,14 @@ static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
  * Print first lines of output and table heading
  */
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol)
 { 
   printf("\nidaHeat2D_kry_petsc: Heat equation, parallel example problem for IDA\n");
   printf("            Discretized heat equation on 2D unit square.\n");
   printf("            Zero boundary conditions,");
   printf(" polynomial initial conditions.\n");
   printf("            Mesh dimensions: %d x %d", MX, MY);
-  printf("        Total system size: %ld\n\n", Neq);
+  printf("        Total system size: %ld\n\n", (long int) Neq);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("        Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -611,9 +607,9 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("SUPPRESSALG = TRUE to suppress local error testing on ");
+  printf("SUPPRESSALG = SUNTRUE to suppress local error testing on ");
   printf("all boundary components. \n");
-  printf("Linear solver: IDASPGMR  ");
+  printf("Linear solver: SUNSPGMR  ");
   printf("Preconditioner: diagonal elements only.\n"); 
   printf("This example uses PETSc vector.\n");
   
@@ -627,7 +623,7 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
  * PrintOutput: print max norm of solution and current solver statistics
  */
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu)
 {
   realtype hused, umax;
   long int nst, nni, nje, nre, nreLS, nli, npe, nps;
@@ -637,25 +633,25 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
 
   if (id == 0) {
 
-    ier = IDAGetLastOrder(mem, &kused);
+    ier = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&ier, "IDAGetLastOrder", 1, id);
-    ier = IDAGetNumSteps(mem, &nst);
+    ier = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&ier, "IDAGetNumSteps", 1, id);
-    ier = IDAGetNumNonlinSolvIters(mem, &nni);
+    ier = IDAGetNumNonlinSolvIters(ida_mem, &nni);
     check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
-    ier = IDAGetNumResEvals(mem, &nre);
+    ier = IDAGetNumResEvals(ida_mem, &nre);
     check_flag(&ier, "IDAGetNumResEvals", 1, id);
-    ier = IDAGetLastStep(mem, &hused);
+    ier = IDAGetLastStep(ida_mem, &hused);
     check_flag(&ier, "IDAGetLastStep", 1, id);
-    ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+    ier = IDASpilsGetNumJtimesEvals(ida_mem, &nje);
     check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1, id);
-    ier = IDASpilsGetNumLinIters(mem, &nli);
+    ier = IDASpilsGetNumLinIters(ida_mem, &nli);
     check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
-    ier = IDASpilsGetNumResEvals(mem, &nreLS);
+    ier = IDASpilsGetNumResEvals(ida_mem, &nreLS);
     check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
-    ier = IDASpilsGetNumPrecEvals(mem, &npe);
+    ier = IDASpilsGetNumPrecEvals(ida_mem, &npe);
     check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
-    ier = IDASpilsGetNumPrecSolves(mem, &nps);
+    ier = IDASpilsGetNumPrecSolves(ida_mem, &nps);
     check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)  
@@ -676,13 +672,13 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
  * Print some final integrator statistics
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int netf, ncfn, ncfl;
 
-  IDAGetNumErrTestFails(mem, &netf);
-  IDAGetNumNonlinSolvConvFails(mem, &ncfn);
-  IDASpilsGetNumConvFails(mem, &ncfl);
+  IDAGetNumErrTestFails(ida_mem, &netf);
+  IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
+  IDASpilsGetNumConvFails(ida_mem, &ncfl);
 
   printf("\nError test failures            = %ld\n", netf);
   printf("Nonlinear convergence failures = %ld\n", ncfn);
diff --git a/examples/ida/petsc/idaHeat2D_kry_petsc.out b/examples/ida/petsc/idaHeat2D_kry_petsc.out
index 51bd511..a8c8d9d 100644
--- a/examples/ida/petsc/idaHeat2D_kry_petsc.out
+++ b/examples/ida/petsc/idaHeat2D_kry_petsc.out
@@ -7,8 +7,8 @@ idaHeat2D_kry_petsc: Heat equation, parallel example problem for IDA
 Subgrid dimensions: 5 x 5        Processor array: 2 x 2
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-SUPPRESSALG = TRUE to suppress local error testing on all boundary components. 
-Linear solver: IDASPGMR  Preconditioner: diagonal elements only.
+SUPPRESSALG = SUNTRUE to suppress local error testing on all boundary components. 
+Linear solver: SUNSPGMR  Preconditioner: diagonal elements only.
 This example uses PETSc vector.
 
    Output Summary (umax = max-norm of solution) 
@@ -22,11 +22,11 @@ This example uses PETSc vector.
   0.08   2.16509e-01  3   22   29   30    29    30   1.32e-02    9  59
   0.16   4.57687e-02  4   28   36   44    36    44   1.32e-02    9  80
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
-  0.64   5.54028e-21  1   39   51   77    51    77   1.05e-01   12 128
-  1.28   0.00000e+00  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   0.00000e+00  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   0.00000e+00  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   0.00000e+00  1   45   57   77    57    77   6.74e+00   18 134
+  0.64   2.15648e-20  1   39   51   77    51    77   1.05e-01   12 128
+  1.28   5.77813e-20  1   41   53   77    53    77   4.21e-01   14 130
+  2.56   7.49337e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   2.26172e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   6.91707e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
diff --git a/examples/ida/serial/CMakeLists.txt b/examples/ida/serial/CMakeLists.txt
index c0b73ad..4661b35 100644
--- a/examples/ida/serial/CMakeLists.txt
+++ b/examples/ida/serial/CMakeLists.txt
@@ -1,13 +1,11 @@
 # ---------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,124 +13,235 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for IDA serial examples
-#
-# CSW 4/19/2014
-#    Added SUPERLUMT logic.
-
+# ---------------------------------------------------------------
 
-# Add variable IDA_examples with the names of the serial IDA examples
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS linear solvers
 SET(IDA_examples
-  idaFoodWeb_bnd
-  idaHeat2D_bnd
-  idaHeat2D_kry
-  idaFoodWeb_kry
-  idaKrylovDemo_ls
-  idaRoberts_dns
-  idaSlCrank_dns
+  "idaFoodWeb_bnd\;develop"
+  "idaHeat2D_bnd\;develop"
+  "idaHeat2D_kry\;develop"
+  "idaFoodWeb_kry\;develop"
+  "idaKrylovDemo_ls\;develop"
+  "idaRoberts_dns\;"
+  "idaSlCrank_dns\;develop"
   )
 
-SET(IDA_examples_SUPERLUMT
-  idaRoberts_sps
-  #idaHeat2D_sps ... not ready yet ... incorrect answer.
+# Examples using LAPACK linear solvers
+SET(IDA_examples_BL
   )
 
+# Examples using KLU linear solver
 SET(IDA_examples_KLU
-  idaRoberts_klu
-  idaHeat2D_klu
+  "idaRoberts_klu\;develop"
+  "idaHeat2D_klu\;develop"
   )
 
-# Add variable IDA_examples_BL with the names of the serial IDA examples
-# that use Lapack
-
-SET(IDA_examples_BL
-  )
+# Examples using SuperLU_MT linear solver
+SET(IDA_examples_SUPERLUMT
+    "idaRoberts_sps\;develop"
+    #"idaHeat2D_sps\;develop" # not ready yet, incorrect answer.
+    )
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDA_LIB sundials_ida_static)
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDA_LIB sundials_ida_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${IDA_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(PETSC_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${IDA_examples})
 
-# Add the build and install targets for each IDA example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${IDA_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${IDA_examples})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${IDA_examples})
 
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
 
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${IDA_examples_BL})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${IDA_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${IDA_examples_BL})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${IDA_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If SUPERLUMT support is enabled, add the build and install targets for
-# the examples using SUPERLUMT
-IF(SUPERLUMT_FOUND)
-  FOREACH(example ${IDA_examples_SUPERLUMT})
+
+# Add the build and install targets for each KLU example (if needed)
+IF(KLU_FOUND)
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${IDA_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${IDA_examples_SUPERLUMT})
-ENDIF(SUPERLUMT_FOUND)
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
+    ENDIF()
 
-# If KLU support is enabled, add the build and install targets for
-# the examples using KLU
-IF(KLU_FOUND)
-  FOREACH(example ${IDA_examples_KLU})
+  ENDFOREACH(example_tuple ${IDA_examples_KLU})
+
+ENDIF(KLU_FOUND)
+
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
+IF(SUPERLUMT_FOUND)
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${IDA_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # Do not include SuperLUMT examples in testing when the indextype is int64_t.
+    # Answer files were generated with int32_t and minor differences in output
+    # occur causing a false positive when testing. These tests can be re-enabled
+    # when type specific answer files are added.
+    IF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+      # add example to regression tests
+      SUNDIALS_ADD_TEST(${example} ${example}
+        ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+        ANSWER_FILE ${example}.out
+        EXAMPLE_TYPE ${example_type})
+    ENDIF()
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${IDA_examples_KLU})
-ENDIF(KLU_FOUND)
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${IDA_examples_SUPERLUMT})
+
+ENDIF(SUPERLUMT_FOUND)
+
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -141,46 +250,48 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "IDA")
   SET(SOLVER_LIB "sundials_ida")
-  LIST2STRING(IDA_examples EXAMPLES)
+
+  EXAMPLES2STRING(IDA_examples EXAMPLES)
 
   IF(LAPACK_FOUND)
-    LIST2STRING(IDA_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(IDA_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
 
   IF(KLU_FOUND)
-    LIST2STRING(IDA_examples_KLU EXAMPLES)
-  ENDIF(KLU_FOUND)
+    EXAMPLES2STRING(IDA_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
 
   IF(SUPERLUMT_FOUND)
-    LIST2STRING(IDA_examples_SUPERLUMT EXAMPLES)
-  ENDIF(SUPERLUMT_FOUND)
+    EXAMPLES2STRING(IDA_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
 
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
-
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/ida/serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/ida/serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/ida/serial/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
-  
+
   IF(UNIX)
     # generate Makefile and place it in the binary dir
     CONFIGURE_FILE(
@@ -190,10 +301,14 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/ida/serial/Makefile_ex 
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial 
+      FILES ${PROJECT_BINARY_DIR}/examples/ida/serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/ida/serial
       RENAME Makefile
       )
   ENDIF(UNIX)
 
+  # add test_install target
+  SUNDIALS_ADD_TEST_INSTALL(ida idaRoberts_dns
+    EXAMPLE_DIR ${EXAMPLES_INSTALL_PATH}/ida/serial)
+
 ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/ida/serial/README b/examples/ida/serial/README
index 98bca6c..e79d7c5 100644
--- a/examples/ida/serial/README
+++ b/examples/ida/serial/README
@@ -4,6 +4,8 @@ List of serial IDA examples
   idaFoodWeb_kry   : 2-D food web system using Krylov solver
   idaHeat2D_bnd    : 2-D heat equation, banded Jacobian
   idaHeat2D_kry    : 2-D heat equation, diagonal preconditioner
+  idaHeat2D_klu    : heat equation with KLU sparse linear solver
+  idaHeat2D_sps    : heat equation with SuperLUMT sparse linear solver
   idaKrylovDemo_ls : demonstration program with 3 Krylov solvers
   idaRoberts_dns   : 3-species Robertson kinetics system
   idaRoberts_klu   : Robertson system with KLU sparse linear solver
@@ -15,7 +17,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -26,7 +27,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -40,7 +44,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/ida/serial/idaFoodWeb_bnd.c b/examples/ida/serial/idaFoodWeb_bnd.c
index 9c4c5aa..d54facd 100644
--- a/examples/ida/serial/idaFoodWeb_bnd.c
+++ b/examples/ida/serial/idaFoodWeb_bnd.c
@@ -1,14 +1,10 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4853 $
- * $Date: 2016-08-03 16:27:46 -0700 (Wed, 03 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDA: Food web problem.
  *
- * This example program (serial version) uses the IDABAND linear 
+ * This example program (serial version) uses the banded linear 
  * solver, and IDACalcIC for initial condition calculation.
  *
  * The mathematical problem solved in this example is a DAE system
@@ -62,7 +58,7 @@
  * The PDEs are discretized by central differencing on a MX by MY
  * mesh.
  *
- * The DAE system is solved by IDA using the IDABAND linear solver.
+ * The DAE system is solved by IDA using the banded linear solver.
  * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
  * -----------------------------------------------------------------
  * References:
@@ -80,18 +76,18 @@
  *     Consistent Initial Condition Calculation for Differential-
  *     Algebraic Systems, SIAM J. Sci. Comput., 19 (1998),
  *     pp. 1495-1512.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_band.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
+#include <ida/ida.h>                   /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <ida/ida_direct.h>            /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
 
 /* Problem Constants. */
 
@@ -136,7 +132,7 @@
 /* Type: UserData.  Contains problem constants, etc. */
 
 typedef struct {
-  long int Neq, ns, np, mx, my;
+  sunindextype Neq, ns, np, mx, my;
   realtype dx, dy, **acoef;
   realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
   N_Vector rates;
@@ -152,13 +148,13 @@ static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval,
 static void InitUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata);
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol);
 static void PrintOutput(void *mem, N_Vector c, realtype t);
 static void PrintFinalStats(void *mem);
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate, UserData webdata);
 static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                      UserData webdata);
-static realtype dotprod(long int size, realtype *x1, realtype *x2);
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /*
@@ -173,12 +169,16 @@ int main()
   UserData webdata;
   N_Vector cc, cp, id;
   int iout, retval;
-  long int mu, ml;
+  sunindextype mu, ml;
   realtype rtol, atol, t0, tout, tret;
+  SUNMatrix A;
+  SUNLinearSolver LS;
 
   mem = NULL;
   webdata = NULL;
   cc = cp = id = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate and initialize user data block webdata. */
 
@@ -224,11 +224,18 @@ int main()
   retval = IDASStolerances(mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1)) return(1);
 
-  /* Call IDABand to specify the IDA linear solver. */
-
+  /* Create banded SUNMatrix for use in linear solves */
   mu = ml = NSMX;
-  retval = IDABand(mem, NEQ, mu, ml);
-  if(check_flag(&retval, "IDABand", 1)) return(1);
+  A = SUNBandMatrix(NEQ, mu, ml, mu+ml);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver object */
+  LS = SUNBandLinearSolver(cc, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
@@ -261,14 +268,16 @@ int main()
   /* Free memory */
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
 
-  N_VDestroy_Serial(cc);
-  N_VDestroy_Serial(cp);
-  N_VDestroy_Serial(id);
+  N_VDestroy(cc);
+  N_VDestroy(cp);
+  N_VDestroy(id);
 
 
   destroyMat(webdata->acoef);
-  N_VDestroy_Serial(webdata->rates);
+  N_VDestroy(webdata->rates);
   free(webdata);
 
   return(0);
@@ -297,14 +306,14 @@ int main()
 static int resweb(realtype tt, N_Vector cc, N_Vector cp, 
                   N_Vector res,  void *user_data)
 {
-  long int jx, jy, is, yloc, loc, np;
+  sunindextype jx, jy, is, yloc, loc, np;
   realtype *resv, *cpv;
   UserData webdata;
   
   webdata = (UserData)user_data;
   
-  cpv = N_VGetArrayPointer_Serial(cp);
-  resv = N_VGetArrayPointer_Serial(res);
+  cpv = N_VGetArrayPointer(cp);
+  resv = N_VGetArrayPointer(res);
   np = webdata->np;
   
   /* Call Fweb to set res to vector of right-hand sides. */
@@ -393,13 +402,13 @@ static void InitUserData(UserData webdata)
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata)
 {
-  long int loc, yloc, is, jx, jy, np;
+  sunindextype loc, yloc, is, jx, jy, np;
   realtype xx, yy, xyfactor;
   realtype *ccv, *cpv, *idv;
   
-  ccv = N_VGetArrayPointer_Serial(cc);
-  cpv = N_VGetArrayPointer_Serial(cp);
-  idv = N_VGetArrayPointer_Serial(id);
+  ccv = N_VGetArrayPointer(cc);
+  cpv = N_VGetArrayPointer(cp);
+  idv = N_VGetArrayPointer(id);
   np = webdata->np;
   
   /* Loop over grid, load cc values and id values. */
@@ -444,7 +453,7 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol)
 {
   printf("\nidaFoodWeb_bnd: Predator-prey DAE serial example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
@@ -457,7 +466,7 @@ static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDABAND,  Band parameters mu = %ld, ml = %ld\n",mu,ml);
+  printf("Linear solver: BAND,  Band parameters mu = %ld, ml = %ld\n", (long int) mu, (long int) ml);
   printf("CalcIC called to correct initial predator concentrations.\n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -553,7 +562,7 @@ static void PrintFinalStats(void *mem)
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,  
                  UserData webdata)
 { 
-  long int jx, jy, is, idyu, idyl, idxu, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxu, idxl;
   realtype xx, yy, *cxy, *ratesxy, *cratexy, dcyli, dcyui, dcxli, dcxui;
   
   /* Loop over grid points, evaluate interaction vector (length ns),
@@ -621,9 +630,9 @@ static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
  * dotprod: dot product routine for realtype arrays, for use by WebRates.    
  */
 
-static realtype dotprod(long int size, realtype *x1, realtype *x2)
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
diff --git a/examples/ida/serial/idaFoodWeb_bnd.out b/examples/ida/serial/idaFoodWeb_bnd.out
index f188bd8..43b819f 100644
--- a/examples/ida/serial/idaFoodWeb_bnd.out
+++ b/examples/ida/serial/idaFoodWeb_bnd.out
@@ -3,7 +3,7 @@ idaFoodWeb_bnd: Predator-prey DAE serial example problem for IDA
 
 Number of species ns: 2     Mesh dimensions: 20 x 20     System size: 800
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDABAND,  Band parameters mu = 40, ml = 40
+Linear solver: BAND,  Band parameters mu = 40, ml = 40
 CalcIC called to correct initial predator concentrations.
 
 -----------------------------------------------------------
diff --git a/examples/ida/serial/idaFoodWeb_kry.c b/examples/ida/serial/idaFoodWeb_kry.c
index 11be4a6..b235c1f 100644
--- a/examples/ida/serial/idaFoodWeb_kry.c
+++ b/examples/ida/serial/idaFoodWeb_kry.c
@@ -1,14 +1,10 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
- * -----------------------------------------------------------------
+ * ----------------------------------------------------------------
  * Example program for IDA: Food web problem, OpenMP, GMRES, 
  * user-supplied preconditioner
  *
- * This example program uses the IDASPGMR as the linear 
+ * This example program uses the SPGMR as the linear 
  * solver, and IDACalcIC for initial condition calculation.
  *
  * The mathematical problem solved in this example is a DAE system
@@ -62,7 +58,7 @@
  * The PDEs are discretized by central differencing on a MX by MY
  * mesh.
  *
- * The DAE system is solved by IDA using the IDABAND linear solver.
+ * The DAE system is solved by IDA using the SPGMR linear solver.
  * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
  * -----------------------------------------------------------------
  * References:
@@ -80,19 +76,19 @@
  *     Consistent Initial Condition Calculation for Differential-
  *     Algebraic Systems, SIAM J. Sci. Comput., 19 (1998),
  *     pp. 1495-1512.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_spgmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <ida/ida.h>                   /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <ida/ida_spils.h>             /* access to IDASpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to spgmr SUNLinearSolver      */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
+#include <sundials/sundials_math.h>    /* macros SUNRabs, SUNRsqrt, etc.       */
 
 /* Problem Constants. */
 
@@ -137,11 +133,11 @@
 /* Type: UserData.  Contains problem constants, etc. */
 
 typedef struct {
-  long int Neq, ns, np, mx, my;
+  sunindextype Neq, ns, np, mx, my;
   realtype dx, dy, **acoef;
   realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
   realtype **PP[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   N_Vector rates;
   N_Vector ewt;
   void *ida_mem;
@@ -154,27 +150,25 @@ static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval,
 
 static int Precond(realtype tt,
 		   N_Vector cc, N_Vector cp, N_Vector rr, 
-		   realtype cj, void *user_data,
-		   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+		   realtype cj, void *user_data);
 
 static int PSolve(realtype tt, 
 		  N_Vector cc, N_Vector cp, N_Vector rr,
 		  N_Vector rvec, N_Vector zvec,
-		  realtype cj, realtype delta, void *user_data,
-		  N_Vector tmp);
+		  realtype cj, realtype delta, void *user_data);
 
 /* Prototypes for private Helper Functions. */
 
 static void InitUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata);
-static void PrintHeader(long int maxl, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype maxl, realtype rtol, realtype atol);
 static void PrintOutput(void *mem, N_Vector c, realtype t);
 static void PrintFinalStats(void *mem);
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate, UserData webdata);
 static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                      UserData webdata);
-static realtype dotprod(long int size, realtype *x1, realtype *x2);
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, char *funcname, int opt);
 
 /*
@@ -189,12 +183,14 @@ int main()
   UserData webdata;
   N_Vector cc, cp, id;
   int iout, jx, jy, flag;
-  long int maxl;
+  sunindextype maxl;
   realtype rtol, atol, t0, tout, tret;
+  SUNLinearSolver LS;
 
   mem = NULL;
   webdata = NULL;
   cc = cp = id = NULL;
+  LS = NULL;
 
   /* Allocate and initialize user data block webdata. */
 
@@ -204,7 +200,7 @@ int main()
   webdata->ewt = N_VNew_Serial(NEQ);
   for (jx = 0; jx < MX; jx++) {
     for (jy = 0; jy < MY; jy++) {
-      (webdata->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (webdata->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
       (webdata->PP)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
     }
   }
@@ -249,12 +245,21 @@ int main()
 
   webdata->ida_mem = mem;
 
-  /* Call IDASpgmr to specify the IDA linear solver. */
+  /* Create the linear solver SUNSPGMR with left preconditioning
+     and maximum Krylov dimension maxl */
+  maxl = 16;
+  LS = SUNSPGMR(cc, PREC_LEFT, maxl);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* IDA recommends allowing up to 5 restarts (default is 0) */
+  flag = SUNSPGMRSetMaxRestarts(LS, 5);
+  if(check_flag(&flag, "SUNSPGMRSetMaxRestarts", 1)) return(1);
 
-  maxl = 16;                    /* max dimension of the Krylov subspace */
-  flag = IDASpgmr(mem, maxl);
-  if(check_flag(&flag, "IDASpgmr", 1)) return(1);
+  /* Attach the linear sovler */
+  flag = IDASpilsSetLinearSolver(mem, LS);
+  if(check_flag(&flag, "IDASpilsSetLinearSolver", 1)) return(1);
 
+  /* Set the preconditioner solve and setup functions */
   flag = IDASpilsSetPreconditioner(mem, Precond, PSolve);
   if(check_flag(&flag, "IDASpilsSetPreconditioner", 1)) return(1);
 
@@ -289,15 +294,16 @@ int main()
   /* Free memory */
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
 
-  N_VDestroy_Serial(cc);
-  N_VDestroy_Serial(cp);
-  N_VDestroy_Serial(id);
+  N_VDestroy(cc);
+  N_VDestroy(cp);
+  N_VDestroy(id);
 
 
   destroyMat(webdata->acoef);
-  N_VDestroy_Serial(webdata->rates);
-  N_VDestroy_Serial(webdata->ewt);
+  N_VDestroy(webdata->rates);
+  N_VDestroy(webdata->ewt);
   for (jx = 0; jx < MX; jx++) {
     for (jy = 0; jy < MY; jy ++) {
       destroyArray((webdata->pivot)[jx][jy]);
@@ -332,14 +338,14 @@ int main()
 static int resweb(realtype tt, N_Vector cc, N_Vector cp, 
                   N_Vector res,  void *user_data)
 {
-  long int jx, jy, is, yloc, loc, np;
+  sunindextype jx, jy, is, yloc, loc, np;
   realtype *resv, *cpv;
   UserData webdata;
   
   webdata = (UserData)user_data;
   
-  cpv = NV_DATA_S(cp);
-  resv = NV_DATA_S(res);
+  cpv = N_VGetArrayPointer(cp);
+  resv = N_VGetArrayPointer(res);;
   np = webdata->np;
   
   /* Call Fweb to set res to vector of right-hand sides. */
@@ -368,8 +374,7 @@ static int resweb(realtype tt, N_Vector cc, N_Vector cp,
 
 static int Precond(realtype tt, 
 		   N_Vector cc, N_Vector cp, N_Vector rr, 
-		   realtype cj, void *user_data,
-		   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+		   realtype cj, void *user_data)
 {
   int flag;
   realtype uround, xx, yy, del_x, del_y;
@@ -439,10 +444,10 @@ static int PSolve(realtype tt,
 		  N_Vector cc, N_Vector cp, N_Vector rr, 
 		  N_Vector rvec, N_Vector zvec,
 		  realtype cj, realtype dalta, 
-		  void *user_data, N_Vector tmp) 
+		  void *user_data) 
 {
   realtype **Pxy, *zxy;
-  long int *pivot;
+  sunindextype *pivot;
   int jx, jy;
   UserData webdata;
   
@@ -528,13 +533,13 @@ static void InitUserData(UserData webdata)
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata)
 {
-  long int loc, yloc, is, jx, jy, np;
+  sunindextype loc, yloc, is, jx, jy, np;
   realtype xx, yy, xyfactor;
   realtype *ccv, *cpv, *idv;
   
-  ccv = NV_DATA_S(cc);
-  cpv = NV_DATA_S(cp);
-  idv = NV_DATA_S(id);
+  ccv = N_VGetArrayPointer(cc);
+  cpv = N_VGetArrayPointer(cp) ;
+  idv = N_VGetArrayPointer(id);
   np = webdata->np;
   
   /* Loop over grid, load cc values and id values. */
@@ -579,7 +584,7 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int maxl, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype maxl, realtype rtol, realtype atol)
 {
   printf("\nidaFoodWeb_kry: Predator-prey DAE serial example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
@@ -592,7 +597,7 @@ static void PrintHeader(long int maxl, realtype rtol, realtype atol)
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASpgmr,  Spgmr parameters maxl = %ld\n",maxl);
+  printf("Linear solver: SPGMR,  SPGMR parameters maxl = %ld\n",(long int) maxl);
   printf("CalcIC called to correct initial predator concentrations.\n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -688,7 +693,7 @@ static void PrintFinalStats(void *mem)
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,  
                  UserData webdata)
 { 
-  long int jx, jy, is, idyu, idyl, idxu, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxu, idxl;
   realtype xx, yy, *cxy, *ratesxy, *cratexy, dcyli, dcyui, dcxli, dcxui;
   
   /* Loop over grid points, evaluate interaction vector (length ns),
@@ -756,9 +761,9 @@ static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
  * dotprod: dot product routine for realtype arrays, for use by WebRates.    
  */
 
-static realtype dotprod(long int size, realtype *x1, realtype *x2)
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
diff --git a/examples/ida/serial/idaFoodWeb_kry.out b/examples/ida/serial/idaFoodWeb_kry.out
index 09763cd..6dcee94 100644
--- a/examples/ida/serial/idaFoodWeb_kry.out
+++ b/examples/ida/serial/idaFoodWeb_kry.out
@@ -3,7 +3,7 @@ idaFoodWeb_kry: Predator-prey DAE serial example problem for IDA
 
 Number of species ns: 2     Mesh dimensions: 20 x 20     System size: 800
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDASpgmr,  Spgmr parameters maxl = 16
+Linear solver: SPGMR,  SPGMR parameters maxl = 16
 CalcIC called to correct initial predator concentrations.
 
 -----------------------------------------------------------
diff --git a/examples/ida/serial/idaHeat2D_bnd.c b/examples/ida/serial/idaHeat2D_bnd.c
index 3828d2f..bfc1722 100644
--- a/examples/ida/serial/idaHeat2D_bnd.c
+++ b/examples/ida/serial/idaHeat2D_bnd.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, serial, banded.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the band solver IDABand, and IDACalcIC.
+ * This version uses the band solver and IDACalcIC.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -28,17 +24,18 @@
  * u >= 0 are posed for all components. Output is taken at
  * t = 0, .01, .02, .04, ..., 10.24. (Output at t = 0 is for
  * IDACalcIC cost statistics only.)
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_band.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
+#include <ida/ida.h>                   /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <ida/ida_direct.h>            /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
 
 /* Problem Constants */
 
@@ -53,7 +50,7 @@
 /* Type: UserData */
 
 typedef struct {
-  long int mm;
+  sunindextype mm;
   realtype dx;
   realtype coeff;
 } *UserData;
@@ -83,12 +80,17 @@ int main(void)
   UserData data;
   N_Vector uu, up, constraints, id, res;
   int ier, iout;
-  long int mu, ml, netf, ncfn;
+  long int netf, ncfn;
+  sunindextype mu, ml;
   realtype rtol, atol, t0, t1, tout, tret;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   
   mem = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Create vectors uu, up, res, constraints, id. */
   uu = N_VNew_Serial(NEQ);
@@ -128,12 +130,13 @@ int main(void)
   ier = IDASetUserData(mem, data);
   if(check_flag(&ier, "IDASetUserData", 1)) return(1);
 
+  /* Set which components are algebraic or differential */
   ier = IDASetId(mem, id);
   if(check_flag(&ier, "IDASetId", 1)) return(1);
 
   ier = IDASetConstraints(mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
-  N_VDestroy_Serial(constraints);
+  N_VDestroy(constraints);
 
   ier = IDAInit(mem, heatres, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1)) return(1);
@@ -141,13 +144,21 @@ int main(void)
   ier = IDASStolerances(mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1)) return(1);
 
-  /* Call IDABand to specify the linear solver. */
+  /* Create banded SUNMatrix for use in linear solves */
   mu = MGRID; ml = MGRID;
-  ier = IDABand(mem, NEQ, mu, ml);
-  if(check_flag(&ier, "IDABand", 1)) return(1);
- 
+  A = SUNBandMatrix(NEQ, mu, ml, mu+ml);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver object */
+  LS = SUNBandLinearSolver(uu, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  ier = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&ier, "IDADlsSetLinearSolver", 1)) return(1);
+
   /* Call IDACalcIC to correct the initial values. */
-  
+
   ier = IDACalcIC(mem, IDA_YA_YDP_INIT, t1);
   if(check_flag(&ier, "IDACalcIC", 1)) return(1);
 
@@ -176,10 +187,12 @@ int main(void)
   printf("\n netf = %ld,   ncfn = %ld \n", netf, ncfn);
 
   IDAFree(&mem);
-  N_VDestroy_Serial(uu);
-  N_VDestroy_Serial(up);
-  N_VDestroy_Serial(id);
-  N_VDestroy_Serial(res);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(uu);
+  N_VDestroy(up);
+  N_VDestroy(id);
+  N_VDestroy(res);
   free(data);
 
   return(0);
@@ -187,7 +200,7 @@ int main(void)
 
 /*
  *--------------------------------------------------------------------
- * FUNCTIONS CALLED BY KINSOL
+ * FUNCTIONS CALLED BY IDA
  *--------------------------------------------------------------------
  */
 
@@ -203,11 +216,11 @@ int main(void)
 int heatres(realtype tres, N_Vector uu, N_Vector up, N_Vector resval, 
             void *user_data)
 {
-  long int mm, i, j, offset, loc;
+  sunindextype mm, i, j, offset, loc;
   realtype *uv, *upv, *resv, coeff;
   UserData data;
   
-  uv = N_VGetArrayPointer_Serial(uu); upv = N_VGetArrayPointer_Serial(up); resv = N_VGetArrayPointer_Serial(resval);
+  uv = N_VGetArrayPointer(uu); upv = N_VGetArrayPointer(up); resv = N_VGetArrayPointer(resval);
 
   data = (UserData)user_data;
   mm = data->mm;
@@ -244,14 +257,14 @@ static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
                              N_Vector id, N_Vector res)
 {
   realtype xfact, yfact, *udata, *updata, *iddata;
-  long int mm, mm1, i, j, offset, loc;
+  sunindextype mm, mm1, i, j, offset, loc;
   
   mm = data->mm;
   mm1 = mm - 1;
   
-  udata = N_VGetArrayPointer_Serial(uu);
-  updata = N_VGetArrayPointer_Serial(up);
-  iddata = N_VGetArrayPointer_Serial(id);
+  udata = N_VGetArrayPointer(uu);
+  updata = N_VGetArrayPointer(up);
+  iddata = N_VGetArrayPointer(id);
 
   /* Initialize id to 1's. */
   N_VConst(ONE, id);
@@ -310,7 +323,7 @@ static void PrintHeader(realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("Linear solver: IDABAND, banded direct solver \n");
+  printf("Linear solver: BAND, banded direct solver \n");
   printf("       difference quotient Jacobian, half-bandwidths = %d \n",MGRID);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("IDACalcIC called with input boundary values = %Lg \n",BVAL);
diff --git a/examples/ida/serial/idaHeat2D_bnd.out b/examples/ida/serial/idaHeat2D_bnd.out
index 0d98fae..dbff755 100644
--- a/examples/ida/serial/idaHeat2D_bnd.out
+++ b/examples/ida/serial/idaHeat2D_bnd.out
@@ -6,7 +6,7 @@ idaHeat2D_bnd: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDABAND, banded direct solver 
+Linear solver: BAND, banded direct solver 
        difference quotient Jacobian, half-bandwidths = 10 
 IDACalcIC called with input boundary values = 0.1 
 
@@ -14,17 +14,17 @@ IDACalcIC called with input boundary values = 0.1
 
   time       umax     k  nst  nni  nje   nre   nreLS    h      
  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 
-  0.00   9.75461e-01  0    0    1    2     3    42   1.00e-05 
-  0.01   8.24113e-01  2   12   15   10    17   210   2.56e-03 
-  0.02   6.88124e-01  3   15   19   10    21   210   5.12e-03 
-  0.04   4.71054e-01  3   19   23   10    25   210   5.12e-03 
-  0.08   2.16451e-01  3   23   28   11    30   231   1.02e-02 
-  0.16   4.50382e-02  4   28   35   12    37   252   2.05e-02 
-  0.32   2.14520e-03  5   34   43   13    45   273   4.10e-02 
-  0.64   2.89374e-18  1   39   52   15    54   315   1.64e-01 
-  1.28   1.17136e-32  1   41   54   17    56   357   6.55e-01 
-  2.56   1.31711e-35  1   42   55   18    57   378   1.31e+00 
-  5.12   1.18294e-37  1   43   56   19    58   399   2.62e+00 
- 10.24   1.26706e-39  1   44   57   20    59   420   5.24e+00 
+  0.00   9.75461e-01  0    0    3    2     5    42   1.00e-05 
+  0.01   8.24602e-01  2   13   20    9    22   189   2.56e-03 
+  0.02   6.88908e-01  2   15   23   10    25   210   5.12e-03 
+  0.04   4.71178e-01  3   19   28   10    30   210   5.12e-03 
+  0.08   2.16305e-01  3   23   33   10    35   210   1.02e-02 
+  0.16   4.53754e-02  4   29   41   11    43   231   2.05e-02 
+  0.32   1.78933e-03  4   36   50   12    52   252   4.10e-02 
+  0.64   1.27055e-20  1   41   59   14    61   294   1.64e-01 
+  1.28   1.34319e-33  1   43   61   16    63   336   6.55e-01 
+  2.56   3.69260e-36  1   44   62   17    64   357   1.31e+00 
+  5.12   8.13278e-38  1   45   63   18    65   378   2.62e+00 
+ 10.24   9.53175e-40  1   46   64   19    66   399   5.24e+00 
 
  netf = 0,   ncfn = 0 
diff --git a/examples/ida/serial/idaHeat2D_klu.c b/examples/ida/serial/idaHeat2D_klu.c
index b63468b..392f768 100644
--- a/examples/ida/serial/idaHeat2D_klu.c
+++ b/examples/ida/serial/idaHeat2D_klu.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4853 $
- * $Date: 2016-08-03 16:27:46 -0700 (Wed, 03 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Chris Nguyen @ LLNL
+ *                based on idaHeat2D_bnd.c and idaRoberts_klu.c
  * -----------------------------------------------------------------
- * Example problem for IDA: 2D heat equation, serial, sparse. 
- * Based on idaHeat2D_bnd.c and idaRoberts_klu.c
+ * Example problem for IDA: 2D heat equation, serial, sparse.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the band solver IDABand, and IDACalcIC.
+ * This version uses the KLU solver and IDACalcIC.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -20,27 +16,30 @@
  * equations u = 0 at the boundaries are appended, to form a DAE
  * system of size N = MGRID^2. Here MGRID = 10.
  *
- * The system is solved with IDA using the banded linear system
- * solver and default difference-quotient Jacobian. 
+ * The system is solved with IDA using the sparse linear system
+ * solver and a user supplied Jacobian. 
  * For purposes of illustration,
  * IDACalcIC is called to compute correct values at the boundary,
  * given incorrect values as input initial guesses. The constraints
  * u >= 0 are posed for all components. Output is taken at
  * t = 0, .01, .02, .04, ..., 10.24. (Output at t = 0 is for
  * IDACalcIC cost statistics only.)
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_klu.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
+#include <ida/ida.h>                       /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>       /* access to KLU linear solver          */
+#include <ida/ida_direct.h>                /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
+
 #define NOUT  11
 #define MGRID 10
 #define NEQ   MGRID*MGRID
@@ -53,26 +52,25 @@
 /* Type: UserData */
 
 typedef struct {
-  long int mm;
+  sunindextype mm;
   realtype dx;
   realtype coeff;
 } *UserData;
 
 /* Prototypes of functions called by IDA */
 
-int heatres(realtype tres, N_Vector uu, N_Vector up, 
-	    N_Vector resval, void *user_data);
+int heatres(realtype tres, N_Vector uu, N_Vector up, N_Vector resval, void *user_data);
 
 int jacHeat(realtype tt,  realtype cj, 
 	    N_Vector yy, N_Vector yp, N_Vector resvec,
-	    SlsMat JacMat, void *user_data,
+	    SUNMatrix JJ, void *user_data,
 	    N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Exact same setup as jacHeat. Function needed for special case MGRID=3  */
 int jacHeat3(realtype tt,  realtype cj, 
-	    N_Vector yy, N_Vector yp, N_Vector resvec,
-	    SlsMat JacMat, void *user_data,
-	    N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
+             N_Vector yy, N_Vector yp, N_Vector resvec,
+             SUNMatrix JJ, void *user_data,
+             N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Prototypes of private functions */
 
@@ -93,12 +91,13 @@ int main(void)
 {
   void *mem;
   UserData data;
-  N_Vector uu, up, constraints, id, res;  /* uu is u, up is du/dt */
+  N_Vector uu, up, constraints, id, res;
   int ier, iout;
   long int netf, ncfn;
   realtype rtol, atol, t0, t1, tout, tret;
-
-  int nnz; /* number of non-zeroes  */
+  SUNMatrix A;
+  SUNLinearSolver LS;
+  sunindextype nnz;
   
   mem = NULL;
   data = NULL;
@@ -113,7 +112,7 @@ int main(void)
   if(check_flag((void *)res, "N_VNew_Serial", 0)) return(1);
   constraints = N_VNew_Serial(NEQ);
   if(check_flag((void *)constraints, "N_VNew_Serial", 0)) return(1);
-  id = N_VNew_Serial(NEQ); /* differentiate between algebraic and differential */
+  id = N_VNew_Serial(NEQ);
   if(check_flag((void *)id, "N_VNew_Serial", 0)) return(1);
 
   /* Create and load problem data block. */
@@ -142,13 +141,13 @@ int main(void)
   ier = IDASetUserData(mem, data);
   if(check_flag(&ier, "IDASetUserData", 1)) return(1);
 
-  /* Sets up which components are algebraic or differential */
-  ier = IDASetId(mem, id); 
+  /* Set which components are algebraic or differential */
+  ier = IDASetId(mem, id);
   if(check_flag(&ier, "IDASetId", 1)) return(1);
 
   ier = IDASetConstraints(mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
-  N_VDestroy_Serial(constraints);
+  N_VDestroy(constraints);
 
   ier = IDAInit(mem, heatres, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1)) return(1);
@@ -156,26 +155,33 @@ int main(void)
   ier = IDASStolerances(mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1)) return(1);
 
-  /* Call IDAKLU and set up the linear solver  */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ*NEQ;
-  ier = IDAKLU(mem, NEQ, nnz, CSC_MAT);
-  if(check_flag(&ier, "IDAKLU", 1)) return(1);
-  /* check size of Jacobian matrix  */
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void*)A, "SUNSparseMtarix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object */
+  LS = SUNKLU(uu, A);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  ier = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&ier, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
   if(MGRID >= 4){
-    ier = IDASlsSetSparseJacFn(mem, jacHeat);
-  }
-  /* special case MGRID=3  */
-  else if(MGRID==3){
-    ier = IDASlsSetSparseJacFn(mem, jacHeat3);
-  }
-  /* MGRID<=2 is pure boundary points, nothing to solve  */
-  else{
+    ier = IDADlsSetJacFn(mem, jacHeat);
+  } else if(MGRID == 3) {
+    ier = IDADlsSetJacFn(mem, jacHeat3);
+  } else {
+    /* MGRID<=2 is pure boundary points, nothing to solve */
     printf("MGRID size is too small to run.\n");
     return(1);
   }
-  if(check_flag(&ier, "IDASlsSetSparseJacFn", 1)) return(1);
+  if(check_flag(&ier, "IDADlsSetJacFn", 1)) return(1);
 
   /* Call IDACalcIC to correct the initial values. */
+
   ier = IDACalcIC(mem, IDA_YA_YDP_INIT, t1);
   if(check_flag(&ier, "IDACalcIC", 1)) return(1);
 
@@ -204,10 +210,12 @@ int main(void)
   printf("\n netf = %ld,   ncfn = %ld \n", netf, ncfn);
 
   IDAFree(&mem);
-  N_VDestroy_Serial(uu);
-  N_VDestroy_Serial(up);
-  N_VDestroy_Serial(id);
-  N_VDestroy_Serial(res);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(uu);
+  N_VDestroy(up);
+  N_VDestroy(id);
+  N_VDestroy(res);
   free(data);
 
   return(0);
@@ -231,11 +239,11 @@ int main(void)
 int heatres(realtype tres, N_Vector uu, N_Vector up, N_Vector resval, 
             void *user_data)
 {
-  long int mm, i, j, offset, loc;
+  sunindextype mm, i, j, offset, loc;
   realtype *uv, *upv, *resv, coeff;
   UserData data;
   
-  uv = N_VGetArrayPointer_Serial(uu); upv = N_VGetArrayPointer_Serial(up); resv = N_VGetArrayPointer_Serial(resval);
+  uv = N_VGetArrayPointer(uu); upv = N_VGetArrayPointer(up); resv = N_VGetArrayPointer(resval);
 
   data = (UserData)user_data;
   mm = data->mm;
@@ -260,18 +268,18 @@ int heatres(realtype tres, N_Vector uu, N_Vector up, N_Vector resval,
 
 /* Jacobian matrix setup for MGRID=3  */
 int jacHeat3(realtype tt,  realtype cj, 
-           N_Vector yy, N_Vector yp, N_Vector resvec,
-	   SlsMat JacMat, void *user_data,
-           N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+             N_Vector yy, N_Vector yp, N_Vector resvec,
+             SUNMatrix JJ, void *user_data,
+             N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype dx =  ONE/(MGRID - ONE);
   realtype beta = RCONST(4.0)/(dx*dx) + cj;
   
-  int *colptrs   = (*JacMat->colptrs);
-  int *rowvals   = (*JacMat->rowvals);
-  realtype *data = JacMat->data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
 
-  SparseSetMatToZero(JacMat); /* initialize Jacobian matrix */
+  SUNMatZero(JJ);
 
   /*
    * set up number of elements in each column 
@@ -323,22 +331,22 @@ int jacHeat3(realtype tt,  realtype cj,
 
 /* Jacobian matrix setup for MGRID>=4  */
 int jacHeat(realtype tt,  realtype cj, 
-           N_Vector yy, N_Vector yp, N_Vector resvec,
-	   SlsMat JacMat, void *user_data,
-           N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+            N_Vector yy, N_Vector yp, N_Vector resvec,
+            SUNMatrix JJ, void *user_data,
+            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
   realtype dx =  ONE/(MGRID - ONE);
   realtype beta = RCONST(4.0)/(dx*dx) + cj;
   int i,j, repeat=0;
 
-  int *colptrs   = (*JacMat->colptrs);
-  int *rowvals   = (*JacMat->rowvals);
-  realtype *data = JacMat->data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
 
-  yval = N_VGetArrayPointer_Serial(yy);
+  yval = N_VGetArrayPointer(yy);
 
-  SparseSetMatToZero(JacMat); /* initialize Jacobian matrix  */
+  SUNMatZero(JJ);
 
   /* 
    *-----------------------------------------------
@@ -565,8 +573,6 @@ int jacHeat(realtype tt,  realtype cj,
   for(i=0;i<(MGRID-2);i++) rowvals[TOTAL-2*(MGRID-2)  +2*i] = MGRID*MGRID-MGRID+1+i;  
   rowvals[TOTAL-1] = MGRID*MGRID-1;
 
-  /*SparsePrintMat(JacMat);*/
- 
   return(0);
 }
 
@@ -585,14 +591,14 @@ static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
                              N_Vector id, N_Vector res)
 {
   realtype xfact, yfact, *udata, *updata, *iddata;
-  long int mm, mm1, i, j, offset, loc;
+  sunindextype mm, mm1, i, j, offset, loc;
   
   mm = data->mm;
   mm1 = mm - 1;
   
-  udata = N_VGetArrayPointer_Serial(uu);
-  updata = N_VGetArrayPointer_Serial(up);
-  iddata = N_VGetArrayPointer_Serial(id);
+  udata = N_VGetArrayPointer(uu);
+  updata = N_VGetArrayPointer(up);
+  iddata = N_VGetArrayPointer(id);
 
   /* Initialize id to 1's. */
   N_VConst(ONE, id);
@@ -651,7 +657,7 @@ static void PrintHeader(realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("Linear solver: IDAKLU, sparse direct solver \n");
+  printf("Linear solver: KLU, sparse direct solver \n");
   printf("       difference quotient Jacobian\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("IDACalcIC called with input boundary values = %Lg \n",BVAL);
@@ -689,10 +695,9 @@ static void PrintOutput(void *mem, realtype t, N_Vector uu)
   check_flag(&ier, "IDAGetNumResEvals", 1);
   ier = IDAGetLastStep(mem, &hused);
   check_flag(&ier, "IDAGetLastStep", 1);
-  ier = IDASlsGetNumJacEvals(mem, &nje);
-  check_flag(&ier, "IDASlsGetNumJacEvals", 1);
+  ier = IDADlsGetNumJacEvals(mem, &nje);
+  check_flag(&ier, "IDADlsGetNumJacEvals", 1);
 
- 
 #if defined(SUNDIALS_EXTENDED_PRECISION) 
   printf(" %5.2Lf %13.5Le  %d  %3ld  %3ld  %3ld  %4ld  %9.2Le \n",
          t, umax, kused, nst, nni, nje, nre, hused);
diff --git a/examples/ida/serial/idaHeat2D_klu.out b/examples/ida/serial/idaHeat2D_klu.out
index ced958a..8ed0a3e 100644
--- a/examples/ida/serial/idaHeat2D_klu.out
+++ b/examples/ida/serial/idaHeat2D_klu.out
@@ -6,7 +6,7 @@ idaHeat2D_klu: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 1e-08
 Constraints set to force all solution components >= 0. 
-Linear solver: IDAKLU, sparse direct solver 
+Linear solver: KLU, sparse direct solver 
        difference quotient Jacobian
 IDACalcIC called with input boundary values = 0 
 
diff --git a/examples/ida/serial/idaHeat2D_kry.c b/examples/ida/serial/idaHeat2D_kry.c
index 2c765e7..269b908 100644
--- a/examples/ida/serial/idaHeat2D_kry.c
+++ b/examples/ida/serial/idaHeat2D_kry.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, serial, GMRES.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the Krylov solver IDASpgmr.
+ * This version uses the Krylov solver Spgmr.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -21,24 +17,24 @@
  * system of size N = M^2. Here M = 10.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR. The preconditioner uses the diagonal elements of the
+ * SPGMR. The preconditioner uses the diagonal elements of the
  * Jacobian only. Routines for preconditioning, required by
- * IDASPGMR, are supplied here. The constraints u >= 0 are posed
+ * SPGMR, are supplied here. The constraints u >= 0 are posed
  * for all components. Output is taken at t = 0, .01, .02, .04,
  * ..., 10.24. Two cases are run -- with the Gram-Schmidt type
  * being Modified in the first case, and Classical in the second.
- * The second run uses IDAReInit and IDAReInitSpgmr.
- * -----------------------------------------------------------------
- */
+ * The second run uses IDAReInit.
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_spgmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
+#include <ida/ida.h>                   /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <ida/ida_spils.h>             /* access to IDASpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to spgmr SUNLinearSolver      */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
 
 /* Problem Constants */
 
@@ -53,7 +49,7 @@
 /* User data type */
 
 typedef struct {  
-  long int mm;  /* number of grid points */
+  sunindextype mm;  /* number of grid points */
   realtype dx;
   realtype coeff;
   N_Vector pp;  /* vector of prec. diag. elements */
@@ -66,14 +62,12 @@ int resHeat(realtype tres, N_Vector uu, N_Vector up,
 
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *prec_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+               realtype c_j, void *prec_data);
 
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *prec_data, 
-               N_Vector tmp);
+               realtype c_j, realtype delta, void *prec_data);
 
 /* Prototypes for private functions */
 
@@ -97,10 +91,12 @@ int main()
   int ier, iout;
   realtype rtol, atol, t0, t1, tout, tret;
   long int netf, ncfn, ncfl;
+  SUNLinearSolver LS;
 
   mem = NULL;
   data = NULL;
   uu = up = constraints = res = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors and the user data structure. */
 
@@ -153,7 +149,7 @@ int main()
 
   ier = IDASetConstraints(mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
-  N_VDestroy_Serial(constraints);
+  N_VDestroy(constraints);
 
   ier = IDAInit(mem, resHeat, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1)) return(1);
@@ -161,11 +157,20 @@ int main()
   ier = IDASStolerances(mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1)) return(1);
 
-  /* Call IDASpgmr to specify the linear solver. */
+  /* Create the linear solver SUNSPGMR with left preconditioning
+     and the default Krylov dimension */
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* IDA recommends allowing up to 5 restarts (default is 0) */
+  ier = SUNSPGMRSetMaxRestarts(LS, 5);
+  if(check_flag(&ier, "SUNSPGMRSetMaxRestarts", 1)) return(1);
 
-  ier = IDASpgmr(mem, 0);
-  if(check_flag(&ier, "IDASpgmr", 1)) return(1);
+  /* Attach the linear sovler */
+  ier = IDASpilsSetLinearSolver(mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return(1);
 
+  /* Set the preconditioner solve and setup functions */
   ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
   if(check_flag(&ier, "IDASpilsSetPreconditioner", 1)) return(1);
 
@@ -218,13 +223,13 @@ int main()
 
   SetInitialProfile(data, uu, up, res);
   
-  /* Re-initialize IDA and IDASPGMR */
+  /* Re-initialize IDA and SPGMR */
 
   ier = IDAReInit(mem, t0, uu, up);
   if(check_flag(&ier, "IDAReInit", 1)) return(1);
   
-  ier = IDASpilsSetGSType(mem, CLASSICAL_GS);
-  if(check_flag(&ier, "IDASpilsSetGSType",1)) return(1); 
+  ier = SUNSPGMRSetGSType(LS, CLASSICAL_GS);
+  if(check_flag(&ier, "SUNSPGMRSetGSType",1)) return(1); 
   
   /* Print case number, output table heading, and initial line of table. */
 
@@ -259,12 +264,13 @@ int main()
   /* Free Memory */
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
 
-  N_VDestroy_Serial(uu);
-  N_VDestroy_Serial(up);
-  N_VDestroy_Serial(res);
+  N_VDestroy(uu);
+  N_VDestroy(up);
+  N_VDestroy(res);
 
-  N_VDestroy_Serial(data->pp);
+  N_VDestroy(data->pp);
   free(data);
 
   return(0);
@@ -289,13 +295,13 @@ int resHeat(realtype tt,
             N_Vector uu, N_Vector up, N_Vector rr, 
             void *user_data)
 {
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
   UserData data;
   
-  uu_data = N_VGetArrayPointer_Serial(uu); 
-  up_data = N_VGetArrayPointer_Serial(up); 
-  rr_data = N_VGetArrayPointer_Serial(rr);
+  uu_data = N_VGetArrayPointer(uu); 
+  up_data = N_VGetArrayPointer(up); 
+  rr_data = N_VGetArrayPointer(rr);
 
   data = (UserData) user_data;
   
@@ -338,16 +344,15 @@ int resHeat(realtype tt,
   
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *prec_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+               realtype c_j, void *prec_data)
 {
   
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *ppv, pelinv;
   UserData data;
   
   data = (UserData) prec_data;
-  ppv = N_VGetArrayPointer_Serial(data->pp);
+  ppv = N_VGetArrayPointer(data->pp);
   mm = data->mm;
 
   /* Initialize the entire vector to 1., then set the interior points to the
@@ -378,8 +383,7 @@ int PsetupHeat(realtype tt,
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *prec_data, 
-               N_Vector tmp)
+               realtype c_j, realtype delta, void *prec_data)
 {
   UserData data;
   data = (UserData) prec_data;
@@ -400,13 +404,13 @@ int PsolveHeat(realtype tt,
 static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up, 
                              N_Vector res)
 {
-  long int mm, mm1, i, j, offset, loc;
+  sunindextype mm, mm1, i, j, offset, loc;
   realtype xfact, yfact, *udata, *updata;
 
   mm = data->mm;
 
-  udata = N_VGetArrayPointer_Serial(uu);
-  updata = N_VGetArrayPointer_Serial(up);
+  udata = N_VGetArrayPointer(uu);
+  updata = N_VGetArrayPointer(up);
 
   /* Initialize uu on all grid points. */ 
   mm1 = mm - 1;
@@ -461,7 +465,7 @@ static void PrintHeader(realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("Linear solver: IDASPGMR, preconditioner using diagonal elements. \n");
+  printf("Linear solver: SPGMR, preconditioner using diagonal elements. \n");
 }
 
 /*
diff --git a/examples/ida/serial/idaHeat2D_kry.out b/examples/ida/serial/idaHeat2D_kry.out
index fe7bde0..d24695c 100644
--- a/examples/ida/serial/idaHeat2D_kry.out
+++ b/examples/ida/serial/idaHeat2D_kry.out
@@ -6,7 +6,7 @@ idaHeat2D_kry: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPGMR, preconditioner using diagonal elements. 
+Linear solver: SPGMR, preconditioner using diagonal elements. 
 
 
 Case 1: gsytpe = MODIFIED_GS
@@ -21,11 +21,11 @@ Case 1: gsytpe = MODIFIED_GS
   0.08   2.16509e-01  3   22   29   30    29    30   1.32e-02    9  59
   0.16   4.57687e-02  4   28   36   44    36    44   1.32e-02    9  80
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
-  0.64   0.00000e+00  1   39   51   77    51    77   1.05e-01   12 128
-  1.28   0.00000e+00  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   0.00000e+00  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   0.00000e+00  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   0.00000e+00  1   45   57   77    57    77   6.74e+00   18 134
+  0.64   5.54028e-21  1   39   51   77    51    77   1.05e-01   12 128
+  1.28   3.85107e-20  1   41   53   77    53    77   4.21e-01   14 130
+  2.56   5.00523e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   1.58940e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   5.12685e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
@@ -45,10 +45,10 @@ Case 2: gstype = CLASSICAL_GS
   0.16   4.57687e-02  4   28   36   44    36    44   1.32e-02    9  80
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
   0.64   2.15648e-20  1   39   51   77    51    77   1.05e-01   12 128
-  1.28   1.30250e-20  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   3.00951e-20  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   7.38674e-20  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   1.79685e-19  1   45   57   77    57    77   6.74e+00   18 134
+  1.28   5.77661e-20  1   41   53   77    53    77   4.21e-01   14 130
+  2.56   7.50780e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   2.26547e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   6.95460e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
diff --git a/examples/ida/serial/idaKrylovDemo_ls.c b/examples/ida/serial/idaKrylovDemo_ls.c
index b967969..a4e28fd 100644
--- a/examples/ida/serial/idaKrylovDemo_ls.c
+++ b/examples/ida/serial/idaKrylovDemo_ls.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -13,8 +9,8 @@
  * Example problem for IDA: 2D heat equation, serial, GMRES.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version loops through the Krylov solvers IDASpgmr, IDASpbcg
- * and IDASptfqmr.
+ * This version loops through the Krylov solvers Spgmr, Spbcg
+ * and Sptfqmr.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -26,24 +22,24 @@
  * system of size N = M^2. Here M = 10.
  *
  * The system is solved with IDA using the following Krylov
- * linear solvers: IDASPGMR, IDASPBCG and IDASPTFQMR. The
+ * linear solvers: SPGMR, SPBCG and SPTFQMR. The
  * preconditioner uses the diagonal elements of the Jacobian only.
- * Routines for preconditioning, required by IDASP*, are supplied
+ * Routines for preconditioning, required by SP*, are supplied
  * here. The constraints u >= 0 are posed for all components. Output
  * is taken at t = 0, .01, .02, .04,..., 10.24.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_spgmr.h>
-#include <ida/ida_spbcgs.h>
-#include <ida/ida_sptfqmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
+#include <ida/ida.h>                     /* main integrator header file       */
+#include <ida/ida_spils.h>               /* access to IDASpils interface      */
+#include <sunlinsol/sunlinsol_spgmr.h>   /* access to SPGMR SUNLinearSolver   */
+#include <sunlinsol/sunlinsol_spbcgs.h>  /* access to SPBCGS SUNLinearSolver  */
+#include <sunlinsol/sunlinsol_sptfqmr.h> /* access to SPTFQMR SUNLinearSolver */
+#include <nvector/nvector_serial.h>      /* serial N_Vector types, fct. and macros */
+#include <sundials/sundials_types.h>     /* definition of realtype */
 
 /* Problem Constants */
 
@@ -64,7 +60,7 @@
 /* User data type */
 
 typedef struct {  
-  long int mm;  /* number of grid points */
+  sunindextype mm;  /* number of grid points */
   realtype dx;
   realtype coeff;
   N_Vector pp;  /* vector of prec. diag. elements */
@@ -77,14 +73,12 @@ int resHeat(realtype tres, N_Vector uu, N_Vector up,
 
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+               realtype c_j, void *user_data);
 
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp);
+               realtype c_j, realtype delta, void *user_data);
 
 /* Prototypes for private functions */
 
@@ -108,10 +102,12 @@ int main(void)
   int ier, iout, linsolver;
   realtype rtol, atol, t0, t1, tout, tret;
   long int netf, ncfn, ncfl;
+  SUNLinearSolver LS;
 
   mem = NULL;
   data = NULL;
   uu = up = constraints = res = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors and the user data structure. */
 
@@ -164,7 +160,7 @@ int main(void)
 
   ier = IDASetConstraints(mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
-  N_VDestroy_Serial(constraints);
+  N_VDestroy(constraints);
 
   ier = IDAInit(mem, resHeat, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1)) return(1);
@@ -197,9 +193,14 @@ int main(void)
       printf(" \n| SPGMR |\n");
       printf(" -------\n");
 
-      /* Call IDASpgmr to specify the linear solver. */
-      ier = IDASpgmr(mem, 0);
-      if(check_flag(&ier, "IDASpgmr", 1)) return(1);
+      /* Call SUNSPGMR to specify the linear solver SPGMR with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPGMR(uu, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+      /* Attach the linear solver */
+      ier = IDASpilsSetLinearSolver(mem, LS);
+      if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -208,12 +209,17 @@ int main(void)
 
       /* Print header */
       printf(" -------");
-      printf(" \n| SPBCG |\n");
+      printf(" \n| SPBCGS |\n");
       printf(" -------\n");
 
-      /* Call IDASpbcg to specify the linear solver. */
-      ier = IDASpbcg(mem, 0);
-      if(check_flag(&ier, "IDASpbcg", 1)) return(1);
+      /* Call SUNSPBCGS to specify the linear solver SPBCGS with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPBCGS(uu, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPBCGS", 0)) return(1);
+
+      /* Attach the linear solver */
+      ier = IDASpilsSetLinearSolver(mem, LS);
+      if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -225,9 +231,14 @@ int main(void)
       printf(" \n| SPTFQMR |\n");
       printf(" ---------\n");
 
-      /* Call IDASptfqmr to specify the linear solver. */
-      ier = IDASptfqmr(mem, 0);
-      if(check_flag(&ier, "IDASptfqmr", 1)) return(1);
+      /* Call SUNSPTFQMR to specify the linear solver SPTFQMR with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPTFQMR(uu, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPTFQMR", 0)) return(1);
+
+      /* Attach the linear solver */
+      ier = IDASpilsSetLinearSolver(mem, LS);
+      if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -276,12 +287,13 @@ int main(void)
   /* Free Memory */
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
 
-  N_VDestroy_Serial(uu);
-  N_VDestroy_Serial(up);
-  N_VDestroy_Serial(res);
+  N_VDestroy(uu);
+  N_VDestroy(up);
+  N_VDestroy(res);
 
-  N_VDestroy_Serial(data->pp);
+  N_VDestroy(data->pp);
   free(data);
 
   return(0);
@@ -306,13 +318,13 @@ int resHeat(realtype tt,
             N_Vector uu, N_Vector up, N_Vector rr, 
             void *user_data)
 {
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
   UserData data;
   
-  uu_data = N_VGetArrayPointer_Serial(uu); 
-  up_data = N_VGetArrayPointer_Serial(up); 
-  rr_data = N_VGetArrayPointer_Serial(rr);
+  uu_data = N_VGetArrayPointer(uu); 
+  up_data = N_VGetArrayPointer(up); 
+  rr_data = N_VGetArrayPointer(rr);
 
   data = (UserData) user_data;
   
@@ -355,16 +367,15 @@ int resHeat(realtype tt,
   
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+               realtype c_j, void *user_data)
 {
   
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *ppv, pelinv;
   UserData data;
   
   data = (UserData) user_data;
-  ppv = N_VGetArrayPointer_Serial(data->pp);
+  ppv = N_VGetArrayPointer(data->pp);
   mm = data->mm;
 
   /* Initialize the entire vector to 1., then set the interior points to the
@@ -395,8 +406,7 @@ int PsetupHeat(realtype tt,
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp)
+               realtype c_j, realtype delta, void *user_data)
 {
   UserData data;
   data = (UserData) user_data;
@@ -417,13 +427,13 @@ int PsolveHeat(realtype tt,
 static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up, 
                              N_Vector res)
 {
-  long int mm, mm1, i, j, offset, loc;
+  sunindextype mm, mm1, i, j, offset, loc;
   realtype xfact, yfact, *udata, *updata;
 
   mm = data->mm;
 
-  udata = N_VGetArrayPointer_Serial(uu);
-  updata = N_VGetArrayPointer_Serial(up);
+  udata = N_VGetArrayPointer(uu);
+  updata = N_VGetArrayPointer(up);
 
   /* Initialize uu on all grid points. */ 
   mm1 = mm - 1;
@@ -482,15 +492,15 @@ static void PrintHeader(realtype rtol, realtype atol, int linsolver)
   switch(linsolver) {
 
   case(USE_SPGMR):
-    printf("Linear solver: IDASPGMR, preconditioner using diagonal elements. \n");
+    printf("Linear solver: SPGMR, preconditioner using diagonal elements. \n");
     break;
 
   case(USE_SPBCG):
-    printf("Linear solver: IDASPBCG, preconditioner using diagonal elements. \n");
+    printf("Linear solver: SPBCG, preconditioner using diagonal elements. \n");
     break;
 
   case(USE_SPTFQMR):
-    printf("Linear solver: IDASPTFQMR, preconditioner using diagonal elements. \n");
+    printf("Linear solver: SPTFQMR, preconditioner using diagonal elements. \n");
     break;
   }
 }
diff --git a/examples/ida/serial/idaKrylovDemo_ls.out b/examples/ida/serial/idaKrylovDemo_ls.out
index 01ad81a..c642437 100644
--- a/examples/ida/serial/idaKrylovDemo_ls.out
+++ b/examples/ida/serial/idaKrylovDemo_ls.out
@@ -9,7 +9,7 @@ idaKrylovDemo_ls: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPGMR, preconditioner using diagonal elements. 
+Linear solver: SPGMR, preconditioner using diagonal elements. 
 
    Output Summary (umax = max-norm of solution) 
 
@@ -21,11 +21,11 @@ Linear solver: IDASPGMR, preconditioner using diagonal elements.
   0.08   2.16509e-01  3   22   29   30    29    30   1.32e-02    9  59
   0.16   4.57687e-02  4   28   36   44    36    44   1.32e-02    9  80
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
-  0.64   0.00000e+00  1   39   51   77    51    77   1.05e-01   12 128
-  1.28   0.00000e+00  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   0.00000e+00  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   0.00000e+00  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   0.00000e+00  1   45   57   77    57    77   6.74e+00   18 134
+  0.64   5.54028e-21  1   39   51   77    51    77   1.05e-01   12 128
+  1.28   3.85107e-20  1   41   53   77    53    77   4.21e-01   14 130
+  2.56   5.00523e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   1.58940e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   5.12685e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
@@ -34,7 +34,7 @@ Linear convergence failures    = 0
 ======================================================================
 
  ------- 
-| SPBCG |
+| SPBCGS |
  -------
 
 idaKrylovDemo_ls: Heat equation, serial example problem for IDA
@@ -44,7 +44,7 @@ idaKrylovDemo_ls: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPBCG, preconditioner using diagonal elements. 
+Linear solver: SPBCG, preconditioner using diagonal elements. 
 
    Output Summary (umax = max-norm of solution) 
 
@@ -79,7 +79,7 @@ idaKrylovDemo_ls: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPTFQMR, preconditioner using diagonal elements. 
+Linear solver: SPTFQMR, preconditioner using diagonal elements. 
 
    Output Summary (umax = max-norm of solution) 
 
@@ -91,11 +91,11 @@ Linear solver: IDASPTFQMR, preconditioner using diagonal elements.
   0.08   2.16481e-01  3   23   27   57    27    57   1.02e-02    9  96
   0.16   4.51083e-02  4   27   33   84    33    84   2.05e-02   10 133
   0.32   1.78483e-03  4   34   42  139    42   139   4.10e-02   11 204
-  0.64   4.07887e-04  1   39   51  183    51   183   1.47e-01   13 262
-  1.28   4.59662e-04  1   41   54  199    54   199   5.90e-01   15 282
-  2.56   2.03940e-05  1   43   56  202    56   202   1.18e+00   16 288
-  5.12   9.56073e-21  1   45   58  202    58   202   2.36e+00   17 290
- 10.24   5.70363e-20  1   46   59  202    59   202   4.72e+00   18 291
+  0.64   3.99803e-04  1   39   51  182    51   182   1.47e-01   13 261
+  1.28   4.56475e-04  1   41   54  198    54   198   5.90e-01   15 281
+  2.56   7.30003e-05  1   43   56  200    56   200   1.18e+00   16 285
+  5.12   1.27643e-20  1   44   57  200    57   200   2.36e+00   17 286
+ 10.24   3.22610e-20  1   45   58  200    58   200   4.72e+00   18 287
 
 Error test failures            = 0
 Nonlinear convergence failures = 0
diff --git a/examples/ida/serial/idaRoberts_dns.c b/examples/ida/serial/idaRoberts_dns.c
index d657e5e..9205b71 100644
--- a/examples/ida/serial/idaRoberts_dns.c
+++ b/examples/ida/serial/idaRoberts_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -21,20 +17,21 @@
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01.
  *
- * The problem is solved with IDA using IDADENSE for the linear
+ * The problem is solved with IDA using the DENSE linear
  * solver, with a user-supplied Jacobian. Output is printed at
  * t = .4, 4, 40, ..., 4e10.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
-#include <sundials/sundials_types.h>
+#include <ida/ida.h>                   /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <ida/ida_direct.h>            /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
 
@@ -46,7 +43,7 @@
 
 /* Macro to define dense matrix elements, indexed from 1. */
 
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1)
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1)
 
 /* Prototypes of functions called by IDA */
 
@@ -56,9 +53,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp,
 static int grob(realtype t, N_Vector yy, N_Vector yp,
                 realtype *gout, void *user_data);
 
-int jacrob(long int Neq, realtype tt,  realtype cj, 
+int jacrob(realtype tt,  realtype cj, 
            N_Vector yy, N_Vector yp, N_Vector resvec,
-           DlsMat JJ, void *user_data,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Prototypes of private functions */
@@ -67,6 +64,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y);
 static void PrintRootInfo(int root_f1, int root_f2);
 static void PrintFinalStats(void *mem);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol);
 
 /*
  *--------------------------------------------------------------------
@@ -82,10 +80,14 @@ int main(void)
   realtype t0, tout1, tout, tret;
   int iout, retval, retvalr;
   int rootsfound[2];
+  SUNMatrix A;
+  SUNLinearSolver LS;
 
   mem = NULL;
   yy = yp = avtol = NULL;
   yval = ypval = atval = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors. */
   yy = N_VNew_Serial(NEQ);
@@ -96,19 +98,19 @@ int main(void)
   if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
 
   /* Create and initialize  y, y', and absolute tolerance vectors. */
-  yval  = N_VGetArrayPointer_Serial(yy);
+  yval  = N_VGetArrayPointer(yy);
   yval[0] = ONE;
   yval[1] = ZERO;
   yval[2] = ZERO;
 
-  ypval = N_VGetArrayPointer_Serial(yp);
+  ypval = N_VGetArrayPointer(yp);
   ypval[0]  = RCONST(-0.04);
   ypval[1]  = RCONST(0.04);
   ypval[2]  = ZERO;  
 
   rtol = RCONST(1.0e-4);
 
-  atval = N_VGetArrayPointer_Serial(avtol);
+  atval = N_VGetArrayPointer(avtol);
   atval[0] = RCONST(1.0e-8);
   atval[1] = RCONST(1.0e-14);
   atval[2] = RCONST(1.0e-6);
@@ -128,18 +130,25 @@ int main(void)
   retval = IDASVtolerances(mem, rtol, avtol);
   if(check_flag(&retval, "IDASVtolerances", 1)) return(1);
 
-  /* Free avtol */
-  N_VDestroy_Serial(avtol);
-
   /* Call IDARootInit to specify the root function grob with 2 components */
   retval = IDARootInit(mem, 2, grob);
   if (check_flag(&retval, "IDARootInit", 1)) return(1);
 
-  /* Call IDADense and set up the linear solver. */
-  retval = IDADense(mem, NEQ);
-  if(check_flag(&retval, "IDADense", 1)) return(1);
-  retval = IDADlsSetDenseJacFn(mem, jacrob);
-  if(check_flag(&retval, "IDADlsSetDenseJacFn", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  retval = IDADlsSetJacFn(mem, jacrob);
+  if(check_flag(&retval, "IDADlsSetJacFn", 1)) return(1);
 
   /* In loop, call IDASolve, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached. */
@@ -169,13 +178,18 @@ int main(void)
 
   PrintFinalStats(mem);
 
-  /* Free memory */
+  /* check the solution error */
+  retval = check_ans(yy, tret, rtol, avtol);
 
+  /* Free memory */
   IDAFree(&mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(avtol);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
 
-  return(0);
+  return(retval);
   
 }
 
@@ -193,9 +207,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data
 {
   realtype *yval, *ypval, *rval;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy); 
+  ypval = N_VGetArrayPointer(yp); 
+  rval = N_VGetArrayPointer(rr);
 
   rval[0]  = RCONST(-0.04)*yval[0] + RCONST(1.0e4)*yval[1]*yval[2];
   rval[1]  = -rval[0] - RCONST(3.0e7)*yval[1]*yval[1] - ypval[1];
@@ -214,7 +228,7 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 {
   realtype *yval, y1, y3;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
+  yval = N_VGetArrayPointer(yy); 
   y1 = yval[0]; y3 = yval[2];
   gout[0] = y1 - RCONST(0.0001);
   gout[1] = y3 - RCONST(0.01);
@@ -226,14 +240,14 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
  * Define the Jacobian function. 
  */
 
-int jacrob(long int Neq, realtype tt,  realtype cj, 
+int jacrob(realtype tt,  realtype cj, 
            N_Vector yy, N_Vector yp, N_Vector resvec,
-           DlsMat JJ, void *user_data,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
-  
-  yval = N_VGetArrayPointer_Serial(yy);
+
+  yval = N_VGetArrayPointer(yy);
 
   IJth(JJ,1,1) = RCONST(-0.04) - cj;
   IJth(JJ,2,1) = RCONST(0.04);
@@ -262,12 +276,12 @@ static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
 {
   realtype *atval, *yval;
 
-  atval  = N_VGetArrayPointer_Serial(avtol);
-  yval  = N_VGetArrayPointer_Serial(y);
+  atval  = N_VGetArrayPointer(avtol);
+  yval  = N_VGetArrayPointer(y);
 
   printf("\nidaRoberts_dns: Robertson kinetics DAE serial example problem for IDA\n");
   printf("         Three equation chemical kinetics problem.\n\n");
-  printf("Linear solver: IDADENSE, with user-supplied Jacobian.\n");
+  printf("Linear solver: DENSE, with user-supplied Jacobian.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg %Lg %Lg \n",
          rtol, atval[0],atval[1],atval[2]);
@@ -302,7 +316,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   retval = IDAGetLastOrder(mem, &kused);
   check_flag(&retval, "IDAGetLastOrder", 1);
@@ -402,3 +416,48 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
 
   return(0);
 }
+
+/* compare the solution at the final time 4e10s to a reference solution computed
+   using a relative tolerance of 1e-8 and absoltue tolerance of 1e-14 */
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol)
+{
+  int      passfail=0;        /* answer pass (0) or fail (1) flag */  
+  N_Vector ref;               /* reference solution vector        */
+  N_Vector ewt;               /* error weight vector              */
+  realtype err;               /* wrms error                       */
+
+  /* create reference solution and error weight vectors */
+  ref = N_VClone(y);
+  ewt = N_VClone(y);
+
+  /* set the reference solution data */
+  NV_Ith_S(ref,0) = RCONST(5.2083474251394888e-08);
+  NV_Ith_S(ref,1) = RCONST(2.0833390772616859e-13);
+  NV_Ith_S(ref,2) = RCONST(9.9999994791631752e-01);
+
+  /* compute the error weight vector, loosen atol */
+  N_VAbs(ref, ewt);
+  N_VLinearSum(rtol, ewt, RCONST(10.0), atol, ewt);
+  if (N_VMin(ewt) <= ZERO) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: check_ans failed - ewt <= 0\n\n");
+    return(-1);
+  }
+  N_VInv(ewt, ewt);   
+
+  /* compute the solution error */
+  N_VLinearSum(ONE, y, -ONE, ref, ref);
+  err = N_VWrmsNorm(ref, ewt);
+
+  /* is the solution within the tolerances? */
+  passfail = (err < ONE) ? 0 : 1; 
+
+  if (passfail) {
+    fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%g \n\n", err);
+  }
+
+  /* Free vectors */
+  N_VDestroy(ref);
+  N_VDestroy(ewt);
+
+  return(passfail);
+}
diff --git a/examples/ida/serial/idaRoberts_dns.out b/examples/ida/serial/idaRoberts_dns.out
index 04c1d91..22c8c78 100644
--- a/examples/ida/serial/idaRoberts_dns.out
+++ b/examples/ida/serial/idaRoberts_dns.out
@@ -2,7 +2,7 @@
 idaRoberts_dns: Robertson kinetics DAE serial example problem for IDA
          Three equation chemical kinetics problem.
 
-Linear solver: IDADENSE, with user-supplied Jacobian.
+Linear solver: DENSE, with user-supplied Jacobian.
 Tolerance parameters:  rtol = 0.0001   atol = 1e-08 1e-14 1e-06 
 Initial conditions y0 = (1 0 0)
 Constraints and id not used.
@@ -10,29 +10,29 @@ Constraints and id not used.
 -----------------------------------------------------------------------
   t             y1           y2           y3      | nst  k      h
 -----------------------------------------------------------------------
-2.6403e-01   9.8997e-01   3.4706e-05   1.0000e-02 |  85  2   6.4537e-02
+2.6404e-01   9.8997e-01   3.4706e-05   1.0000e-02 |  80  2   6.5324e-02
     rootsfound[] =   0   1
-4.0000e-01   9.8517e-01   3.3864e-05   1.4796e-02 |  88  2   6.4537e-02
-4.0000e+00   9.0550e-01   2.2403e-05   9.4473e-02 | 102  4   4.1426e-01
-4.0000e+01   7.1582e-01   9.1851e-06   2.8417e-01 | 136  2   1.3422e+00
-4.0000e+02   4.5049e-01   3.2226e-06   5.4950e-01 | 190  4   3.3557e+01
-4.0000e+03   1.8321e-01   8.9429e-07   8.1679e-01 | 239  4   3.4533e+02
-4.0000e+04   3.8984e-02   1.6218e-07   9.6102e-01 | 287  5   2.0140e+03
-4.0000e+05   4.9389e-03   1.9852e-08   9.9506e-01 | 339  3   1.6788e+04
-4.0000e+06   5.1683e-04   2.0684e-09   9.9948e-01 | 444  4   2.1755e+05
-2.0793e+07   1.0000e-04   4.0004e-10   9.9990e-01 | 495  4   1.0146e+06
+4.0000e-01   9.8517e-01   3.3864e-05   1.4795e-02 |  82  2   6.5324e-02
+4.0000e+00   9.0550e-01   2.2403e-05   9.4473e-02 |  97  4   4.1520e-01
+4.0000e+01   7.1584e-01   9.1861e-06   2.8415e-01 | 132  4   1.9421e+00
+4.0000e+02   4.5054e-01   3.2232e-06   5.4946e-01 | 177  4   3.2576e+01
+4.0000e+03   1.8320e-01   8.9421e-07   8.1680e-01 | 220  4   2.0527e+02
+4.0000e+04   3.8984e-02   1.6218e-07   9.6102e-01 | 266  3   1.2965e+03
+4.0000e+05   4.9390e-03   1.9853e-08   9.9506e-01 | 307  5   1.6802e+04
+4.0000e+06   5.1669e-04   2.0678e-09   9.9948e-01 | 364  3   1.8269e+05
+2.0798e+07   1.0000e-04   4.0004e-10   9.9990e-01 | 395  5   1.1839e+06
     rootsfound[] =  -1   0
-4.0000e+07   5.2036e-05   2.0816e-10   9.9995e-01 | 506  5   2.5503e+06
-4.0000e+08   5.2103e-06   2.0841e-11   9.9999e-01 | 541  4   2.3847e+07
-4.0000e+09   5.2125e-07   2.0850e-12   1.0000e-00 | 569  4   3.9351e+08
-4.0000e+10   5.1091e-08   2.0437e-13   1.0000e-00 | 589  2   6.0246e+09
+4.0000e+07   5.2043e-05   2.0818e-10   9.9995e-01 | 407  4   2.8429e+06
+4.0000e+08   5.2075e-06   2.0830e-11   9.9999e-01 | 451  5   3.3159e+07
+4.0000e+09   5.2291e-07   2.0916e-12   1.0000e+00 | 483  3   4.5703e+08
+4.0000e+10   5.1012e-08   2.0405e-13   1.0000e+00 | 503  2   6.5812e+09
 
 Final Run Statistics: 
 
-Number of steps                    = 589
-Number of residual evaluations     = 832
-Number of Jacobian evaluations     = 79
-Number of nonlinear iterations     = 832
-Number of error test failures      = 14
+Number of steps                    = 503
+Number of residual evaluations     = 707
+Number of Jacobian evaluations     = 76
+Number of nonlinear iterations     = 707
+Number of error test failures      = 13
 Number of nonlinear conv. failures = 0
-Number of root fn. evaluations     = 624
+Number of root fn. evaluations     = 532
diff --git a/examples/ida/serial/idaRoberts_klu.c b/examples/ida/serial/idaRoberts_klu.c
index 46c304c..4a1e56b 100644
--- a/examples/ida/serial/idaRoberts_klu.c
+++ b/examples/ida/serial/idaRoberts_klu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward @ LLNL  (based on idaRoberts_dns.c)
  * -----------------------------------------------------------------
  * This simple example problem for IDA, due to Robertson, 
@@ -20,19 +16,21 @@
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01.
  *
- * The problem is solved with IDA using IDAKLU for the linear
+ * The problem is solved with IDA using the KLU linear
  * solver, with a user-supplied Jacobian. Output is printed at
  * t = .4, 4, 40, ..., 4e10.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_klu.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <ida/ida.h>                       /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>       /* access to KLU linear solver          */
+#include <ida/ida_direct.h>                /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
 
@@ -50,14 +48,14 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp,
 static int grob(realtype t, N_Vector yy, N_Vector yp,
                 realtype *gout, void *user_data);
 
-int jacrobCSC(realtype tt,  realtype cj, 
-              N_Vector yy, N_Vector yp, N_Vector resvec, 
-              SlsMat JacMat, void *user_data,
+int jacrobCSC(realtype tt,  realtype cj,
+              N_Vector yy, N_Vector yp, N_Vector resvec,
+              SUNMatrix JJ, void *user_data,
               N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
-int jacrobCSR(realtype tt,  realtype cj, 
-              N_Vector yy, N_Vector yp, N_Vector resvec, 
-              SlsMat JacMat, void *user_data,
+int jacrobCSR(realtype tt,  realtype cj,
+              N_Vector yy, N_Vector yp, N_Vector resvec,
+              SUNMatrix JJ, void *user_data,
               N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Prototypes of private functions */
@@ -81,12 +79,15 @@ int main(void)
   realtype t0, tout1, tout, tret;
   int iout, retval, retvalr;
   int rootsfound[2];
-
-  int nnz;
+  SUNMatrix A;
+  SUNLinearSolver LS;
+  sunindextype nnz;
 
   mem = NULL;
   yy = yp = avtol = NULL;
   yval = ypval = atval = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors. */
   yy = N_VNew_Serial(NEQ);
@@ -97,19 +98,19 @@ int main(void)
   if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
 
   /* Create and initialize  y, y', and absolute tolerance vectors. */
-  yval  = N_VGetArrayPointer_Serial(yy);
+  yval  = N_VGetArrayPointer(yy);
   yval[0] = ONE;
   yval[1] = ZERO;
   yval[2] = ZERO;
 
-  ypval = N_VGetArrayPointer_Serial(yp);
+  ypval = N_VGetArrayPointer(yp);
   ypval[0]  = RCONST(-0.04);
   ypval[1]  = RCONST(0.04);
   ypval[2]  = ZERO;  
 
   rtol = RCONST(1.0e-4);
 
-  atval = N_VGetArrayPointer_Serial(avtol);
+  atval = N_VGetArrayPointer(avtol);
   atval[0] = RCONST(1.0e-8);
   atval[1] = RCONST(1.0e-6);
   atval[2] = RCONST(1.0e-6);
@@ -120,30 +121,42 @@ int main(void)
 
   PrintHeader(rtol, avtol, yy);
 
-  /* Call IDACreate and IDAMalloc to initialize IDA memory */
+  /* Call IDACreate and IDAInit to initialize IDA memory */
   mem = IDACreate();
   if(check_flag((void *)mem, "IDACreate", 0)) return(1);
   retval = IDAInit(mem, resrob, t0, yy, yp);
   if(check_flag(&retval, "IDAInit", 1)) return(1);
+  /* Call IDASVtolerances to set tolerances */
   retval = IDASVtolerances(mem, rtol, avtol);
   if(check_flag(&retval, "IDASVtolerances", 1)) return(1);
 
   /* Free avtol */
-  N_VDestroy_Serial(avtol);
+  N_VDestroy(avtol);
 
   /* Call IDARootInit to specify the root function grob with 2 components */
   retval = IDARootInit(mem, 2, grob);
   if (check_flag(&retval, "IDARootInit", 1)) return(1);
 
-  /* Call IDAKLU and set up the linear solver. */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  retval = IDAKLU(mem, NEQ, nnz, CSR_MAT);
-  if(check_flag(&retval, "IDAKLU", 1)) return(1);
-  retval = IDASlsSetSparseJacFn(mem, jacrobCSR);
-  if(check_flag(&retval, "IDASlsSetSparseJacFn", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSR_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object */
+  LS = SUNKLU(yy, A);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  retval = IDADlsSetJacFn(mem, jacrobCSR);
+  if(check_flag(&retval, "IDADlsSetJacFn", 1)) return(1);
 
   /* In loop, call IDASolve, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached. */
+
   iout = 0; tout = tout1;
   while(1) {
 
@@ -172,8 +185,10 @@ int main(void)
   /* Free memory */
 
   IDAFree(&mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
 
   return(0);
   
@@ -193,9 +208,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data
 {
   realtype *yval, *ypval, *rval;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy); 
+  ypval = N_VGetArrayPointer(yp); 
+  rval = N_VGetArrayPointer(rr);
 
   rval[0]  = RCONST(-0.04)*yval[0] + RCONST(1.0e4)*yval[1]*yval[2];
   rval[1]  = -rval[0] - RCONST(3.0e7)*yval[1]*yval[1] - ypval[1];
@@ -214,7 +229,7 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 {
   realtype *yval, y1, y3;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
+  yval = N_VGetArrayPointer(yy); 
   y1 = yval[0]; y3 = yval[2];
   gout[0] = y1 - RCONST(0.0001);
   gout[1] = y3 - RCONST(0.01);
@@ -228,21 +243,17 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 
 int jacrobCSC(realtype tt,  realtype cj, 
               N_Vector yy, N_Vector yp, N_Vector resvec,
-              SlsMat JacMat, void *user_data,
+              SUNMatrix JJ, void *user_data,
               N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
-  
-  yval = N_VGetArrayPointer_Serial(yy);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data    = JacMat->data;
-  
-  
-  SparseSetMatToZero(JacMat);
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
+  yval = N_VGetArrayPointer(yy);
+
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
@@ -281,21 +292,17 @@ int jacrobCSC(realtype tt,  realtype cj,
  */
 int jacrobCSR(realtype tt,  realtype cj, 
               N_Vector yy, N_Vector yp, N_Vector resvec,
-              SlsMat JacMat, void *user_data,
+              SUNMatrix JJ, void *user_data,
               N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
-  int* rowptrs;
-  int* colvals;
-  realtype* data;
+  sunindextype *rowptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *colvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
   
-  yval = N_VGetArrayPointer_Serial(yy);
-  rowptrs = (*JacMat->rowptrs);
-  colvals = (*JacMat->colvals);
-  data    = JacMat->data;
+  yval = N_VGetArrayPointer(yy);  
   
-  
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   rowptrs[0] = 0;
   rowptrs[1] = 3;
@@ -343,12 +350,12 @@ static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
 {
   realtype *atval, *yval;
 
-  atval  = N_VGetArrayPointer_Serial(avtol);
-  yval  = N_VGetArrayPointer_Serial(y);
+  atval  = N_VGetArrayPointer(avtol);
+  yval  = N_VGetArrayPointer(y);
 
   printf("\nidaRoberts_klu: Robertson kinetics DAE serial example problem for IDA.\n");
   printf("               Three equation chemical kinetics problem.\n\n");
-  printf("Linear solver: IDAKLU, with user-supplied Jacobian.\n");
+  printf("Linear solver: KLU, with user-supplied Jacobian.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg %Lg %Lg \n",
          rtol, atval[0],atval[1],atval[2]);
@@ -383,7 +390,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   retval = IDAGetLastOrder(mem, &kused);
   check_flag(&retval, "IDAGetLastOrder", 1);
@@ -395,7 +402,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   printf("%10.4Le %12.4Le %12.4Le %12.4Le | %3ld  %1d %12.4Le\n", 
          t, yval[0], yval[1], yval[2], nst, kused, hused);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-  printf("%10.4e %12.4e %12.4e %12.4e | %3ld  %d %12.4e\n", 
+  printf("%10.4e %12.4e %12.4e %12.4e | %3ld  %1d %12.4e\n", 
          t, yval[0], yval[1], yval[2], nst, kused, hused);
 #else
   printf("%10.4e %12.4e %12.4e %12.4e | %3ld  %1d %12.4e\n", 
@@ -416,31 +423,26 @@ static void PrintRootInfo(int root_f1, int root_f2)
 static void PrintFinalStats(void *mem)
 {
   int retval;
-  long int nst, nni, nje, nre, nreLS, netf, ncfn, nge;
+  long int nst, nni, nje, nre, netf, ncfn, nge;
 
   retval = IDAGetNumSteps(mem, &nst);
   check_flag(&retval, "IDAGetNumSteps", 1);
   retval = IDAGetNumResEvals(mem, &nre);
   check_flag(&retval, "IDAGetNumResEvals", 1);
-  retval = IDASlsGetNumJacEvals(mem, &nje);
-  check_flag(&retval, "IDASlsGetNumJacEvals", 1);
+  retval = IDADlsGetNumJacEvals(mem, &nje);
+  check_flag(&retval, "IDADlsGetNumJacEvals", 1);
   retval = IDAGetNumNonlinSolvIters(mem, &nni);
   check_flag(&retval, "IDAGetNumNonlinSolvIters", 1);
   retval = IDAGetNumErrTestFails(mem, &netf);
   check_flag(&retval, "IDAGetNumErrTestFails", 1);
   retval = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
   check_flag(&retval, "IDAGetNumNonlinSolvConvFails", 1);
-  /*  
-      retval = IDASlsGetNumResEvals(mem, &nreLS);
-      check_flag(&retval, "IDASlsGetNumResEvals", 1);
-  */
-  nreLS = 0;
   retval = IDAGetNumGEvals(mem, &nge);
   check_flag(&retval, "IDAGetNumGEvals", 1);
 
   printf("\nFinal Run Statistics: \n\n");
   printf("Number of steps                    = %ld\n", nst);
-  printf("Number of residual evaluations     = %ld\n", nre+nreLS);
+  printf("Number of residual evaluations     = %ld\n", nre);
   printf("Number of Jacobian evaluations     = %ld\n", nje);
   printf("Number of nonlinear iterations     = %ld\n", nni);
   printf("Number of error test failures      = %ld\n", netf);
diff --git a/examples/ida/serial/idaRoberts_klu.out b/examples/ida/serial/idaRoberts_klu.out
index 7d56d20..c0c345d 100644
--- a/examples/ida/serial/idaRoberts_klu.out
+++ b/examples/ida/serial/idaRoberts_klu.out
@@ -2,7 +2,7 @@
 idaRoberts_klu: Robertson kinetics DAE serial example problem for IDA.
                Three equation chemical kinetics problem.
 
-Linear solver: IDAKLU, with user-supplied Jacobian.
+Linear solver: KLU, with user-supplied Jacobian.
 Tolerance parameters:  rtol = 0.0001   atol = 1e-08 1e-06 1e-06 
 Initial conditions y0 = (1 0 0)
 Constraints and id not used.
diff --git a/examples/ida/serial/idaRoberts_sps.c b/examples/ida/serial/idaRoberts_sps.c
index fc4579c..45c2cc7 100644
--- a/examples/ida/serial/idaRoberts_sps.c
+++ b/examples/ida/serial/idaRoberts_sps.c
@@ -1,9 +1,5 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL  (based on idasRoberts_dns.c)
+/* -----------------------------------------------------------------
+ * Programmer(s): Carol Woodward @ LLNL  (based on idaRoberts_dns.c)
  * -----------------------------------------------------------------
  * This simple example problem for IDA, due to Robertson, 
  * is from chemical kinetics, and consists of the following three 
@@ -20,19 +16,21 @@
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01.
  *
- * The problem is solved with IDA using IDASUPERLUMT for the linear
+ * The problem is solved with IDA using the SUPERLUMT linear
  * solver, with a user-supplied Jacobian. Output is printed at
  * t = .4, 4, 40, ..., 4e10.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_superlumt.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <ida/ida.h>                       /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h> /* access to SuperLUMT linear solver    */
+#include <ida/ida_direct.h>                /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
 
@@ -50,9 +48,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp,
 static int grob(realtype t, N_Vector yy, N_Vector yp,
                 realtype *gout, void *user_data);
 
-int jacrob(realtype tt,  realtype cj, 
-           N_Vector yy, N_Vector yp, N_Vector resvec, 
-	   SlsMat JacMat, void *user_data,
+int jacrob(realtype tt,  realtype cj,
+           N_Vector yy, N_Vector yp, N_Vector resvec,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Prototypes of private functions */
@@ -76,12 +74,15 @@ int main(void)
   realtype t0, tout1, tout, tret;
   int iout, retval, retvalr;
   int rootsfound[2];
-
-  int nnz;
+  SUNMatrix A;
+  SUNLinearSolver LS;
+  sunindextype nnz;
 
   mem = NULL;
   yy = yp = avtol = NULL;
   yval = ypval = atval = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors. */
   yy = N_VNew_Serial(NEQ);
@@ -92,19 +93,19 @@ int main(void)
   if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
 
   /* Create and initialize  y, y', and absolute tolerance vectors. */
-  yval  = N_VGetArrayPointer_Serial(yy);
+  yval  = N_VGetArrayPointer(yy);
   yval[0] = ONE;
   yval[1] = ZERO;
   yval[2] = ZERO;
 
-  ypval = N_VGetArrayPointer_Serial(yp);
+  ypval = N_VGetArrayPointer(yp);
   ypval[0]  = RCONST(-0.04);
   ypval[1]  = RCONST(0.04);
   ypval[2]  = ZERO;  
 
   rtol = RCONST(1.0e-4);
 
-  atval = N_VGetArrayPointer_Serial(avtol);
+  atval = N_VGetArrayPointer(avtol);
   atval[0] = RCONST(1.0e-8);
   atval[1] = RCONST(1.0e-6);
   atval[2] = RCONST(1.0e-6);
@@ -115,27 +116,38 @@ int main(void)
 
   PrintHeader(rtol, avtol, yy);
 
-  /* Call IDACreate and IDAMalloc to initialize IDA memory */
+  /* Call IDACreate and IDAInit to initialize IDA memory */
   mem = IDACreate();
   if(check_flag((void *)mem, "IDACreate", 0)) return(1);
   retval = IDAInit(mem, resrob, t0, yy, yp);
   if(check_flag(&retval, "IDAInit", 1)) return(1);
+  /* Call IDASVtolerances to set tolerances */
   retval = IDASVtolerances(mem, rtol, avtol);
   if(check_flag(&retval, "IDASVtolerances", 1)) return(1);
 
   /* Free avtol */
-  N_VDestroy_Serial(avtol);
+  N_VDestroy(avtol);
 
   /* Call IDARootInit to specify the root function grob with 2 components */
   retval = IDARootInit(mem, 2, grob);
   if (check_flag(&retval, "IDARootInit", 1)) return(1);
 
-  /* Call IDASuperLUMT and set up the linear solver. */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  retval = IDASuperLUMT(mem, 1, NEQ, nnz);
-  if(check_flag(&retval, "IDASuperLUMT", 1)) return(1);
-  retval = IDASlsSetSparseJacFn(mem, jacrob);
-  if(check_flag(&retval, "IDASlsSetSparseJacFn", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT SUNLinearSolver object (one thread) */
+  LS = SUNSuperLUMT(yy, A, 1);
+  if(check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  retval = IDADlsSetJacFn(mem, jacrob);
+  if(check_flag(&retval, "IDADlsSetJacFn", 1)) return(1);
 
   /* In loop, call IDASolve, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached. */
@@ -168,8 +180,10 @@ int main(void)
   /* Free memory */
 
   IDAFree(&mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
 
   return(0);
   
@@ -189,9 +203,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data
 {
   realtype *yval, *ypval, *rval;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy); 
+  ypval = N_VGetArrayPointer(yp); 
+  rval = N_VGetArrayPointer(rr);
 
   rval[0]  = RCONST(-0.04)*yval[0] + RCONST(1.0e4)*yval[1]*yval[2];
   rval[1]  = -rval[0] - RCONST(3.0e7)*yval[1]*yval[1] - ypval[1];
@@ -210,7 +224,7 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 {
   realtype *yval, y1, y3;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
+  yval = N_VGetArrayPointer(yy); 
   y1 = yval[0]; y3 = yval[2];
   gout[0] = y1 - RCONST(0.0001);
   gout[1] = y3 - RCONST(0.01);
@@ -224,41 +238,45 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 
 int jacrob(realtype tt,  realtype cj, 
            N_Vector yy, N_Vector yp, N_Vector resvec,
-	   SlsMat JacMat, void *user_data,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
-  int *colptrs = *JacMat->colptrs;
-  int *rowvals = *JacMat->rowvals;
-  
-  yval = N_VGetArrayPointer_Serial(yy);
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
+  yval = N_VGetArrayPointer(yy);
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  JacMat->data[0] = RCONST(-0.04) - cj;
+  /* column 0 */
+  data[0] = RCONST(-0.04) - cj;
   rowvals[0] = 0;
-  JacMat->data[1] = RCONST(0.04);
+  data[1] = RCONST(0.04);
   rowvals[1] = 1;
-  JacMat->data[2] = ONE;
+  data[2] = ONE;
   rowvals[2] = 2;
 
-  JacMat->data[3] = RCONST(1.0e4)*yval[2];
+  /* column 1 */
+  data[3] = RCONST(1.0e4)*yval[2];
   rowvals[3] = 0;
-  JacMat->data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]) - cj;
+  data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]) - cj;
   rowvals[4] = 1;
-  JacMat->data[5] = ONE;
+  data[5] = ONE;
   rowvals[5] = 2;
 
-  JacMat->data[6] = RCONST(1.0e4)*yval[1];
+  /* column 2 */
+  data[6] = RCONST(1.0e4)*yval[1];
   rowvals[6] = 0;
-  JacMat->data[7] = RCONST(-1.0e4)*yval[1];
+  data[7] = RCONST(-1.0e4)*yval[1];
   rowvals[7] = 1;
-  JacMat->data[8] = ONE;
+  data[8] = ONE;
   rowvals[8] = 2;
 
   return(0);
@@ -278,12 +296,12 @@ static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
 {
   realtype *atval, *yval;
 
-  atval  = N_VGetArrayPointer_Serial(avtol);
-  yval  = N_VGetArrayPointer_Serial(y);
+  atval  = N_VGetArrayPointer(avtol);
+  yval  = N_VGetArrayPointer(y);
 
   printf("\nidaRoberts_sps: Robertson kinetics DAE serial example problem for IDA.\n");
   printf("               Three equation chemical kinetics problem.\n\n");
-  printf("Linear solver: IDASUPERLUMT, with user-supplied Jacobian.\n");
+  printf("Linear solver: SUPERLUMT, with user-supplied Jacobian.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg %Lg %Lg \n",
          rtol, atval[0],atval[1],atval[2]);
@@ -318,7 +336,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   retval = IDAGetLastOrder(mem, &kused);
   check_flag(&retval, "IDAGetLastOrder", 1);
@@ -351,29 +369,26 @@ static void PrintRootInfo(int root_f1, int root_f2)
 static void PrintFinalStats(void *mem)
 {
   int retval;
-  long int nst, nni, nje, nre, nreLS, netf, ncfn, nge;
+  long int nst, nni, nje, nre, netf, ncfn, nge;
 
   retval = IDAGetNumSteps(mem, &nst);
   check_flag(&retval, "IDAGetNumSteps", 1);
   retval = IDAGetNumResEvals(mem, &nre);
   check_flag(&retval, "IDAGetNumResEvals", 1);
-  retval = IDASlsGetNumJacEvals(mem, &nje);
-  check_flag(&retval, "IDASlsGetNumJacEvals", 1);
+  retval = IDADlsGetNumJacEvals(mem, &nje);
+  check_flag(&retval, "IDADlsGetNumJacEvals", 1);
   retval = IDAGetNumNonlinSolvIters(mem, &nni);
   check_flag(&retval, "IDAGetNumNonlinSolvIters", 1);
   retval = IDAGetNumErrTestFails(mem, &netf);
   check_flag(&retval, "IDAGetNumErrTestFails", 1);
   retval = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
   check_flag(&retval, "IDAGetNumNonlinSolvConvFails", 1);
-  /*  retval = IDASlsGetNumResEvals(mem, &nreLS); */
-  /*  check_flag(&retval, "IDASlsGetNumResEvals", 1); */
-  nreLS = 0;
   retval = IDAGetNumGEvals(mem, &nge);
   check_flag(&retval, "IDAGetNumGEvals", 1);
 
   printf("\nFinal Run Statistics: \n\n");
   printf("Number of steps                    = %ld\n", nst);
-  printf("Number of residual evaluations     = %ld\n", nre+nreLS);
+  printf("Number of residual evaluations     = %ld\n", nre);
   printf("Number of Jacobian evaluations     = %ld\n", nje);
   printf("Number of nonlinear iterations     = %ld\n", nni);
   printf("Number of error test failures      = %ld\n", netf);
diff --git a/examples/ida/serial/idaRoberts_sps.out b/examples/ida/serial/idaRoberts_sps.out
index 86a24d9..a40fb3d 100644
--- a/examples/ida/serial/idaRoberts_sps.out
+++ b/examples/ida/serial/idaRoberts_sps.out
@@ -2,7 +2,7 @@
 idaRoberts_sps: Robertson kinetics DAE serial example problem for IDA.
                Three equation chemical kinetics problem.
 
-Linear solver: IDASUPERLUMT, with user-supplied Jacobian.
+Linear solver: SUPERLUMT, with user-supplied Jacobian.
 Tolerance parameters:  rtol = 0.0001   atol = 1e-08 1e-06 1e-06 
 Initial conditions y0 = (1 0 0)
 Constraints and id not used.
@@ -19,20 +19,20 @@ Constraints and id not used.
 4.0000e+03   1.8320e-01   8.9444e-07   8.1680e-01 | 126  3   3.1458e+02
 4.0000e+04   3.8992e-02   1.6221e-07   9.6101e-01 | 161  5   2.5058e+03
 4.0000e+05   4.9369e-03   1.9842e-08   9.9506e-01 | 202  3   2.6371e+04
-4.0000e+06   5.1693e-04   2.0688e-09   9.9948e-01 | 252  5   2.5583e+05
-2.0801e+07   1.0000e-04   4.0004e-10   9.9990e-01 | 291  4   1.1781e+06
+4.0000e+06   5.1674e-04   2.0684e-09   9.9948e-01 | 250  3   1.7187e+05
+2.0788e+07   1.0000e-04   4.0004e-10   9.9990e-01 | 280  5   1.0513e+06
     rootsfound[] =  -1   0
-4.0000e+07   5.2043e-05   2.0818e-10   9.9995e-01 | 303  5   2.3562e+06
-4.0000e+08   5.2113e-06   2.0845e-11   9.9999e-01 | 336  4   3.7885e+07
-4.0000e+09   5.2515e-07   2.1006e-12   1.0000e+00 | 359  3   5.4083e+08
-4.0000e+10   5.1251e-08   2.0500e-13   1.0000e+00 | 375  3   8.6532e+09
+4.0000e+07   5.2009e-05   2.0805e-10   9.9995e-01 | 293  4   2.3655e+06
+4.0000e+08   5.2012e-06   2.0805e-11   9.9999e-01 | 325  4   2.6808e+07
+4.0000e+09   5.1850e-07   2.0740e-12   1.0000e+00 | 348  3   7.4305e+08
+4.0000e+10   4.8641e-08   1.9456e-13   1.0000e+00 | 362  2   7.5480e+09
 
 Final Run Statistics: 
 
-Number of steps                    = 375
-Number of residual evaluations     = 529
-Number of Jacobian evaluations     = 54
-Number of nonlinear iterations     = 529
-Number of error test failures      = 10
+Number of steps                    = 362
+Number of residual evaluations     = 537
+Number of Jacobian evaluations     = 60
+Number of nonlinear iterations     = 537
+Number of error test failures      = 15
 Number of nonlinear conv. failures = 0
-Number of root fn. evaluations     = 417
+Number of root fn. evaluations     = 404
diff --git a/examples/ida/serial/idaSlCrank_dns.c b/examples/ida/serial/idaSlCrank_dns.c
index af3ad59..8d2254a 100644
--- a/examples/ida/serial/idaSlCrank_dns.c
+++ b/examples/ida/serial/idaSlCrank_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4809 $
- * $Date: 2016-07-18 11:16:25 -0700 (Mon, 18 Jul 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer: Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Simulation of a slider-crank mechanism modelled with 3 generalized
@@ -13,18 +9,19 @@
  *
  * The equations of motion are formulated as a system of stabilized
  * index-2 DAEs (Gear-Gupta-Leimkuhler formulation).
- *
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <ida/ida.h>
-#include <ida/ida_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <ida/ida.h>                   /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <ida/ida_direct.h>            /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
 
@@ -53,9 +50,11 @@ int ressc(realtype tres, N_Vector yy, N_Vector yp,
 void setIC(N_Vector yy, N_Vector yp, UserData data);
 void force(N_Vector yy, realtype *Q, UserData data);
 
+/* Prototypes of private functions */
 static void PrintHeader(realtype rtol, realtype atol, N_Vector y);
 static void PrintOutput(void *mem, realtype t, N_Vector y);
 static void PrintFinalStats(void *mem);
+static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /*
  *--------------------------------------------------------------------
@@ -72,6 +71,11 @@ int main(void)
   realtype rtol, atol;
   realtype t0, tf, tout, dt, tret;
   int flag, iout;
+  SUNMatrix A;
+  SUNLinearSolver LS;
+
+  A = NULL;
+  LS = NULL;
 
   /* User data */
 
@@ -116,10 +120,19 @@ int main(void)
   flag = IDASStolerances(mem, rtol, atol);
   flag = IDASetUserData(mem, data);
   flag = IDASetId(mem, id);
-  flag = IDASetSuppressAlg(mem, TRUE);
+  flag = IDASetSuppressAlg(mem, SUNTRUE);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
 
-  /* Call IDADense and set up the linear solver. */
-  flag = IDADense(mem, NEQ);
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
   PrintHeader(rtol, atol, yy);
 
@@ -143,9 +156,11 @@ int main(void)
 
   free(data);
   IDAFree(&mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(id);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(id);
 
   return(0);
   
@@ -246,9 +261,9 @@ int ressc(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
   m2 = data->m2;
   J2 = data->J2;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy);
+  ypval = N_VGetArrayPointer(yp);
+  rval = N_VGetArrayPointer(rr);
 
   q = yval[0];
   x = yval[1];
@@ -290,8 +305,8 @@ int ressc(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
 
 static void PrintHeader(realtype rtol, realtype atol, N_Vector y)
 {
-  printf("\nidaSlCrank_dns: Slider-Crank DAE serial example problem for IDAS\n");
-  printf("Linear solver: IDADENSE, Jacobian is computed by IDAS.\n");
+  printf("\nidaSlCrank_dns: Slider-Crank DAE serial example problem for IDA\n");
+  printf("Linear solver: DENSE, Jacobian is computed by IDA.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg\n",
          rtol, atol);
@@ -315,14 +330,19 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   flag = IDAGetLastOrder(mem, &kused);
   flag = IDAGetNumSteps(mem, &nst);
   flag = IDAGetLastStep(mem, &hused);
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("%10.4Le %12.4Le %12.4Le %12.4Le %3ld  %1d %12.4Le\n", 
+         t, yval[0], yval[1], yval[2], nst, kused, hused);
+#else
   printf("%10.4e %12.4e %12.4e %12.4e %3ld  %1d %12.4e\n", 
          t, yval[0], yval[1], yval[2], nst, kused, hused);
+#endif
 }
 
 
@@ -348,3 +368,41 @@ static void PrintFinalStats(void *mem)
   printf("Number of nonlinear conv. failures = %ld\n", ncfn);
 }
 
+/*
+ * Check function return value...
+ *   opt == 0 means SUNDIALS function allocates memory so check if
+ *            returned NULL pointer
+ *   opt == 1 means SUNDIALS function returns a flag so check if
+ *            flag >= 0
+ *   opt == 2 means function allocates memory so check if returned
+ *            NULL pointer 
+ */
+
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+  /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+  if (opt == 0 && flagvalue == NULL) {
+    fprintf(stderr, 
+            "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n", 
+            funcname);
+    return(1);
+  } else if (opt == 1) {
+    /* Check if flag < 0 */
+    errflag = (int *) flagvalue;
+    if (*errflag < 0) {
+      fprintf(stderr, 
+              "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n", 
+              funcname, *errflag);
+      return(1); 
+    }
+  } else if (opt == 2 && flagvalue == NULL) {
+    /* Check if function returned NULL pointer - no memory allocated */
+    fprintf(stderr, 
+            "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n", 
+            funcname);
+    return(1);
+  }
+
+  return(0);
+}
diff --git a/examples/ida/serial/idaSlCrank_dns.out b/examples/ida/serial/idaSlCrank_dns.out
index b79ec57..2a44888 100644
--- a/examples/ida/serial/idaSlCrank_dns.out
+++ b/examples/ida/serial/idaSlCrank_dns.out
@@ -1,6 +1,6 @@
 
-idaSlCrank_dns: Slider-Crank DAE serial example problem for IDAS
-Linear solver: IDADENSE, Jacobian is computed by IDAS.
+idaSlCrank_dns: Slider-Crank DAE serial example problem for IDA
+Linear solver: DENSE, Jacobian is computed by IDA.
 Tolerance parameters:  rtol = 1e-06   atol = 1e-06
 -----------------------------------------------------------------------
   t            y1          y2           y3      | nst  k      h
diff --git a/examples/idas/C_openmp/CMakeLists.txt b/examples/idas/C_openmp/CMakeLists.txt
index 845504e..eccbffb 100644
--- a/examples/idas/C_openmp/CMakeLists.txt
+++ b/examples/idas/C_openmp/CMakeLists.txt
@@ -1,14 +1,14 @@
 # ---------------------------------------------------------------
-# Programmer:  Ting Yan @ SMU
+# Programmer: Ting Yan @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2015, Southern Methodist University and
 # Lawrence Livermore National Security
 #
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Southern Methodist University and Lawrence Livermore 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
 # National Laboratory under Contract DE-AC52-07NA27344.
-# Produced at Southern Methodist University and the Lawrence 
+# Produced at Southern Methodist University and the Lawrence
 # Livermore National Laboratory.
 #
 # All rights reserved.
@@ -19,96 +19,122 @@
 # For details, see the LICENSE file.
 # -----------------------------------------------------------------
 # CMakeLists.txt file for IDAS OpenMP examples
+# -----------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if OpenMP is enabled
 IF(OPENMP_FOUND)
-  # Add variable IDAS_examples_OMP with the names of the openmp IDAS examples
-  SET(IDAS_examples_OMP
-    idasFoodWeb_bnd_omp
-    idasFoodWeb_kry_omp
+
+  # Examples using SUNDIALS linear solvers
+  SET(IDAS_examples
+    "idasFoodWeb_bnd_omp\;4\;develop"
+    "idasFoodWeb_kry_omp\;4\;develop"
     )
+
 ENDIF(OPENMP_FOUND)
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDAS_LIB sundials_idas_static)
   SET(NVECOMP_LIB sundials_nvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDAS_LIB sundials_idas_shared)
   SET(NVECOMP_LIB sundials_nvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${IDAS_LIB} ${NVECOMP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # update the compilation flags to include OpenMP support
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 
-# Add the build and install targets for each IDAS example
-FOREACH(example ${IDAS_examples_OMP})
-  IF(NOT ${example} MATCHES "idasFoodWeb_kry_omp") # LEB NOTE: This goes away with TestRunner fix for OpenMP
+# Add the build and install targets for each example
+FOREACH(example_tuple ${IDAS_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
+    # folder to organize targets in an IDE
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example} TEST_ARGS 4)
+
+    # libraries to link against
     TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
   ENDIF()
+
+  # check if example args are provided and set the test name
+  # IF("${example_args}" STREQUAL "")
+  #   SET(test_name ${example})
+  # ELSE()
+  #   STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  # ENDIF()
+
+  # LEB NOTE: This goes away with TestRunner fix for OpenMP
+  IF(NOT ${example} MATCHES "idasFoodWeb_kry_omp") 
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+  ENDIF()
+
+  # install example source and .out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/C_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${IDAS_examples_OMP})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/C_openmp)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${IDAS_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
   INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/C_openmp)
 
   # Install the extra files
-  FOREACH(extrafile ${IDAS_extras_OMP})
+  FOREACH(extrafile ${IDAS_extras})
     INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/C_openmp)
-  ENDFOREACH(extrafile ${IDAS_extras_OMP})
+  ENDFOREACH()
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "IDAS")
   SET(SOLVER_LIB "sundials_idas")
-  LIST2STRING(IDAS_examples_OMP EXAMPLES)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
 
+  EXAMPLES2STRING(IDAS_examples EXAMPLES)
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/idas/C_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/idas/C_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/idas/C_openmp/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/C_openmp 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/C_openmp
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -120,7 +146,7 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/idas/C_openmp/Makefile_ex 
+      FILES ${PROJECT_BINARY_DIR}/examples/idas/C_openmp/Makefile_ex
       DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/C_openmp
       RENAME Makefile
       )
diff --git a/examples/idas/C_openmp/README b/examples/idas/C_openmp/README
index 5adf53f..1b708a3 100644
--- a/examples/idas/C_openmp/README
+++ b/examples/idas/C_openmp/README
@@ -8,7 +8,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/idas/C_openmp/idasFoodWeb_bnd_omp.c b/examples/idas/C_openmp/idasFoodWeb_bnd_omp.c
index dd9facc..031b6b4 100644
--- a/examples/idas/C_openmp/idasFoodWeb_bnd_omp.c
+++ b/examples/idas/C_openmp/idasFoodWeb_bnd_omp.c
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
- * Programmer(s): Ting Yan @ SMU
- *      Based on idasFoodWeb_bnd.c and parallelized with OpenMP
+ * Programmer(s): Daniel R. Reynolds and Ting Yan @ SMU
+ *      Based on idaFoodWeb_bnd.c and parallelized with OpenMP
  * -----------------------------------------------------------------
  * Example program for IDAS: Food web problem.
  *
- * This example program (OpenMP version) uses the IDABAND linear 
+ * This example program (OpenMP version) uses the SUNBAND linear 
  * solver, and IDACalcIC for initial condition calculation.
  *
  * The mathematical problem solved in this example is a DAE system
@@ -62,7 +59,7 @@
  * The PDEs are discretized by central differencing on a MX by MY
  * mesh.
  *
- * The DAE system is solved by IDAS using the IDABAND linear solver.
+ * The DAE system is solved by IDAS using the SUNBAND linear solver.
  * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
  *
  * Optionally, we can set the number of threads from environment 
@@ -72,12 +69,12 @@
  *
  * Execution:
  *
- * If the user want to use the default value or the number of threads 
- * from environment value:
+ * To use the default value for the number of threads from 
+ * the OMP_NUM_THREADS environment value:
  *      % ./idasFoodWeb_bnd_omp 
- * If the user want to specify the number of threads to use
+ * To specify the number of threads at the command line, use
  *      % ./idasFoodWeb_bnd_omp num_threads
- * where num_threads is the number of threads the user want to use 
+ * where num_threads is the desired number of threads. 
  *
  * -----------------------------------------------------------------
  * References:
@@ -103,9 +100,11 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_band.h>
+#include <idas/idas_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 #include <nvector/nvector_openmp.h>
-#include <sundials/sundials_dense.h>
+#include <sundials/sundials_direct.h>
 #include <sundials/sundials_types.h>
 
 #ifdef _OPENMP
@@ -155,7 +154,7 @@
 /* Type: UserData.  Contains problem constants, etc. */
 
 typedef struct {
-  long int Neq, ns, np, mx, my;
+  sunindextype Neq, ns, np, mx, my;
   realtype dx, dy, **acoef;
   realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
   N_Vector rates;
@@ -172,13 +171,13 @@ static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval,
 static void InitUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata);
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol);
-static void PrintOutput(void *mem, N_Vector c, realtype t);
-static void PrintFinalStats(void *mem);
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol);
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t);
+static void PrintFinalStats(void *ida_mem);
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate, UserData webdata);
 static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                      UserData webdata);
-static realtype dotprod(long int size, realtype *x1, realtype *x2);
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, char *funcname, int opt);
 
 /*
@@ -189,15 +188,19 @@ static int check_flag(void *flagvalue, char *funcname, int opt);
 
 int main(int argc, char *argv[])
 { 
-  void *mem;
+  void *ida_mem;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   UserData webdata;
   N_Vector cc, cp, id;
   int iout, retval;
-  long int mu, ml;
+  sunindextype mu, ml, smu;
   realtype rtol, atol, t0, tout, tret;
   int num_threads;
 
-  mem = NULL;
+  ida_mem = NULL;
+  A = NULL;
+  LS = NULL;
   webdata = NULL;
   cc = cp = id = NULL;
 
@@ -239,46 +242,51 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize IDA. */
   
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0)) return(1);
 
-  retval = IDASetUserData(mem, webdata);
+  retval = IDASetUserData(ida_mem, webdata);
   if(check_flag(&retval, "IDASetUserData", 1)) return(1);
 
-  retval = IDASetId(mem, id);
+  retval = IDASetId(ida_mem, id);
   if(check_flag(&retval, "IDASetId", 1)) return(1);
 
-  retval = IDAInit(mem, resweb, t0, cc, cp);
+  retval = IDAInit(ida_mem, resweb, t0, cc, cp);
   if(check_flag(&retval, "IDAInit", 1)) return(1);
 
-  retval = IDASStolerances(mem, rtol, atol);
+  retval = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1)) return(1);
 
-  /* Call IDABand to specify the IDA linear solver. */
+  /* Setup band matrix and linear solver, and attach to IDA. */
 
   mu = ml = NSMX;
-  retval = IDABand(mem, NEQ, mu, ml);
-  if(check_flag(&retval, "IDABand", 1)) return(1);
+  smu = mu+ml;
+  A = SUNBandMatrix(NEQ, mu, ml, smu);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+  LS = SUNBandLinearSolver(cc, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+  retval = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
   tout = RCONST(0.001);
-  retval = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  retval = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&retval, "IDACalcIC", 1)) return(1);
   
   /* Print heading, basic parameters, and initial values. */
 
   PrintHeader(mu, ml, rtol, atol);
-  PrintOutput(mem, cc, ZERO);
+  PrintOutput(ida_mem, cc, ZERO);
   
   /* Loop over iout, call IDASolve (normal mode), print selected output. */
   
   for (iout = 1; iout <= NOUT; iout++) {
     
-    retval = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    retval = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if(check_flag(&retval, "IDASolve", 1)) return(retval);
     
-    PrintOutput(mem, cc, tret);
+    PrintOutput(ida_mem, cc, tret);
     
     if (iout < 3) tout *= TMULT; else tout += TADD;
     
@@ -286,12 +294,14 @@ int main(int argc, char *argv[])
   
   /* Print final statistics and free memory. */  
   
-  PrintFinalStats(mem);
+  PrintFinalStats(ida_mem);
   printf("num_threads = %i\n\n", num_threads);
 
   /* Free memory */
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
 
   N_VDestroy_OpenMP(cc);
   N_VDestroy_OpenMP(cp);
@@ -328,7 +338,7 @@ int main(int argc, char *argv[])
 static int resweb(realtype tt, N_Vector cc, N_Vector cp, 
                   N_Vector res,  void *user_data)
 {
-  long int jx, jy, is, yloc, loc, np;
+  sunindextype jx, jy, is, yloc, loc, np;
   realtype *resv, *cpv;
   UserData webdata;
   
@@ -343,7 +353,7 @@ static int resweb(realtype tt, N_Vector cc, N_Vector cp,
   
   /* Loop over all grid points, setting residual values appropriately
      for differential or algebraic components.                        */
-#pragma omp parallel for default(shared) private(jy, yloc, jx, loc, is) schedule(static) 
+#pragma omp parallel for default(shared) private(jy, yloc, jx, loc, is) schedule(static) num_threads(webdata->nthreads)
   for (jy = 0; jy < MY; jy++) {
     yloc = NSMX * jy;
     for (jx = 0; jx < MX; jx++) {
@@ -424,7 +434,7 @@ static void InitUserData(UserData webdata)
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata)
 {
-  long int loc, yloc, is, jx, jy, np;
+  sunindextype loc, yloc, is, jx, jy, np;
   realtype xx, yy, xyfactor;
   realtype *ccv, *cpv, *idv;
   
@@ -475,7 +485,7 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol)
 {
   printf("\nidasFoodWeb_bnd_omp: Predator-prey DAE OpenMP example problem for IDAS \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
@@ -488,7 +498,8 @@ static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDABAND,  Band parameters mu = %ld, ml = %ld\n",mu,ml);
+  printf("Linear solver: SUNBAND,  Band parameters mu = %ld, ml = %ld\n",
+         (long int) mu, (long int) ml);
   printf("CalcIC called to correct initial predator concentrations.\n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -503,17 +514,17 @@ static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
  * are printed for the bottom left and top right grid points only.  
  */
 
-static void PrintOutput(void *mem, N_Vector c, realtype t)
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t)
 {
   int i, kused, flag;
   long int nst;
   realtype *c_bl, *c_tr, hused;
 
-  flag = IDAGetLastOrder(mem, &kused);
+  flag = IDAGetLastOrder(ida_mem, &kused);
   check_flag(&flag, "IDAGetLastOrder", 1);
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDAGetLastStep(mem, &hused);
+  flag = IDAGetLastStep(ida_mem, &hused);
   check_flag(&flag, "IDAGetLastStep", 1);
   
   c_bl = IJ_Vptr(c,0,0);
@@ -543,24 +554,24 @@ static void PrintOutput(void *mem, N_Vector c, realtype t)
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 { 
   long int nst, nre, nreLS, nni, nje, netf, ncfn;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1);
-  flag = IDADlsGetNumJacEvals(mem, &nje);
+  flag = IDADlsGetNumJacEvals(ida_mem, &nje);
   check_flag(&flag, "IDADlsGetNumJacEvals", 1);
-  flag = IDADlsGetNumResEvals(mem, &nreLS);
+  flag = IDADlsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDADlsGetNumResEvals", 1);
 
   printf("-----------------------------------------------------------\n");
@@ -584,7 +595,7 @@ static void PrintFinalStats(void *mem)
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,  
                  UserData webdata)
 { 
-  long int jx, jy, is, idyu, idyl, idxu, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxu, idxl;
   realtype xx, yy, *cxy, *ratesxy, *cratexy, dcyli, dcyui, dcxli, dcxui;
   
   /* Loop over grid points, evaluate interaction vector (length ns),
@@ -607,7 +618,7 @@ static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,
       WebRates(xx, yy, cxy, ratesxy, webdata);
       
       /* Loop over species, do differencing, load crate segment. */
-#pragma omp parallel for default(shared) private(is, dcyli, dcyui, dcxli, dcxui) schedule(static)
+#pragma omp parallel for default(shared) private(is, dcyli, dcyui, dcxli, dcxui) schedule(static) num_threads(webdata->nthreads)
       for (is = 0; is < NUM_SPECIES; is++) {
         
         /* Differencing in y. */
@@ -653,9 +664,9 @@ static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
  * dotprod: dot product routine for realtype arrays, for use by WebRates.    
  */
 
-static realtype dotprod(long int size, realtype *x1, realtype *x2)
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
diff --git a/examples/idas/C_openmp/idasFoodWeb_bnd_omp.out b/examples/idas/C_openmp/idasFoodWeb_bnd_omp.out
index 2fe8ab1..d5486f1 100644
--- a/examples/idas/C_openmp/idasFoodWeb_bnd_omp.out
+++ b/examples/idas/C_openmp/idasFoodWeb_bnd_omp.out
@@ -3,7 +3,7 @@ idasFoodWeb_bnd_omp: Predator-prey DAE OpenMP example problem for IDAS
 
 Number of species ns: 2     Mesh dimensions: 20 x 20     System size: 800
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDABAND,  Band parameters mu = 40, ml = 40
+Linear solver: SUNBAND,  Band parameters mu = 40, ml = 40
 CalcIC called to correct initial predator concentrations.
 
 -----------------------------------------------------------
diff --git a/examples/idas/C_openmp/idasFoodWeb_kry_omp.c b/examples/idas/C_openmp/idasFoodWeb_kry_omp.c
index 2365ca9..b600d5b 100644
--- a/examples/idas/C_openmp/idasFoodWeb_kry_omp.c
+++ b/examples/idas/C_openmp/idasFoodWeb_kry_omp.c
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
- * Programmer(s): Ting Yan @ SMU
+ * Programmer(s): Daniel R. Reynolds and Ting Yan @ SMU
  * -----------------------------------------------------------------
  * Example program for IDAS: Food web problem, OpenMP, GMRES, 
  * user-supplied preconditioner
  *
- * This example program uses the IDASPGMR as the linear 
+ * This example program uses SUNSPGMR as the linear 
  * solver, and IDACalcIC for initial condition calculation.
  *
  * The mathematical problem solved in this example is a DAE system
@@ -62,7 +59,7 @@
  * The PDEs are discretized by central differencing on a MX by MY
  * mesh.
  *
- * The DAE system is solved by IDAS using the IDABAND linear solver.
+ * The DAE system is solved by IDAS using the SUNSPGMR linear solver.
  * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
  *
  * Optionally, we can set the number of threads from environment 
@@ -72,12 +69,12 @@
  *
  * Execution:
  *
- * If the user want to use the default value or the number of threads 
- * from environment value:
+ * To use the default value for the number of threads from 
+ * the OMP_NUM_THREADS environment value:
  *      % ./idasFoodWeb_kry_omp 
- * If the user want to specify the number of threads to use
+ * To specify the number of threads at the command line, use
  *      % ./idasFoodWeb_kry_omp num_threads
- * where num_threads is the number of threads the user want to use 
+ * where num_threads is the desired number of threads. 
  *
  * -----------------------------------------------------------------
  * References:
@@ -103,7 +100,8 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_openmp.h>
 #include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
@@ -156,11 +154,11 @@
 /* Type: UserData.  Contains problem constants, etc. */
 
 typedef struct {
-  long int Neq, ns, np, mx, my;
+  sunindextype Neq, ns, np, mx, my;
   realtype dx, dy, **acoef;
   realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
   realtype **PP[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   N_Vector rates;
   N_Vector ewt;
   void *ida_mem;
@@ -172,29 +170,25 @@ typedef struct {
 static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval, 
                   void *user_data);
 
-static int Precond(realtype tt,
-		   N_Vector cc, N_Vector cp, N_Vector rr, 
-		   realtype cj, void *user_data,
-		   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+static int Precond(realtype tt, N_Vector cc, N_Vector cp,
+                   N_Vector rr, realtype cj, void *user_data);
 
-static int PSolve(realtype tt, 
-		  N_Vector cc, N_Vector cp, N_Vector rr,
-		  N_Vector rvec, N_Vector zvec,
-		  realtype cj, realtype delta, void *user_data,
-		  N_Vector tmp);
+static int PSolve(realtype tt, N_Vector cc, N_Vector cp,
+                  N_Vector rr, N_Vector rvec, N_Vector zvec,
+		  realtype cj, realtype delta, void *user_data);
 
 /* Prototypes for private Helper Functions. */
 
 static void InitUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata);
-static void PrintHeader(long int maxl, realtype rtol, realtype atol);
-static void PrintOutput(void *mem, N_Vector c, realtype t);
-static void PrintFinalStats(void *mem);
+static void PrintHeader(sunindextype maxl, realtype rtol, realtype atol);
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t);
+static void PrintFinalStats(void *ida_mem);
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate, UserData webdata);
 static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                      UserData webdata);
-static realtype dotprod(long int size, realtype *x1, realtype *x2);
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, char *funcname, int opt);
 
 /*
@@ -205,15 +199,17 @@ static int check_flag(void *flagvalue, char *funcname, int opt);
 
 int main(int argc, char *argv[])
 { 
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData webdata;
   N_Vector cc, cp, id;
   int iout, jx, jy, flag;
-  long int maxl;
+  sunindextype maxl;
   realtype rtol, atol, t0, tout, tret;
   int num_threads;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   webdata = NULL;
   cc = cp = id = NULL;
 
@@ -233,7 +229,7 @@ int main(int argc, char *argv[])
   webdata->ewt = N_VNew_OpenMP(NEQ, num_threads);
   for (jx = 0; jx < MX; jx++) {
     for (jy = 0; jy < MY; jy++) {
-      (webdata->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (webdata->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
       (webdata->PP)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
     }
   }
@@ -262,51 +258,55 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize IDA. */
   
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0)) return(1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0)) return(1);
 
-  flag = IDASetUserData(mem, webdata);
+  flag = IDASetUserData(ida_mem, webdata);
   if(check_flag(&flag, "IDASetUserData", 1)) return(1);
 
-  flag = IDASetId(mem, id);
+  flag = IDASetId(ida_mem, id);
   if(check_flag(&flag, "IDASetId", 1)) return(1);
 
-  flag = IDAInit(mem, resweb, t0, cc, cp);
+  flag = IDAInit(ida_mem, resweb, t0, cc, cp);
   if(check_flag(&flag, "IDAInit", 1)) return(1);
 
-  flag = IDASStolerances(mem, rtol, atol);
+  flag = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&flag, "IDASStolerances", 1)) return(1);
 
-  webdata->ida_mem = mem;
+  webdata->ida_mem = ida_mem;
 
-  /* Call IDASpgmr to specify the IDA linear solver. */
+  /* Create SUNSPGMR linear solver, attach to IDA, and set 
+     preconditioning routines. */
 
-  maxl = 16;                    /* max dimension of the Krylov subspace */
-  flag = IDASpgmr(mem, maxl);
-  if(check_flag(&flag, "IDASpgmr", 1)) return(1);
+  maxl = 16;                               /* max dimension of the Krylov subspace */
+  LS = SUNSPGMR(cc, PREC_LEFT, maxl);      /* IDA only allows left preconditioning */
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
 
-  flag = IDASpilsSetPreconditioner(mem, Precond, PSolve);
+  flag = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&flag, "IDASpilsSetLinearSolver", 1)) return(1);
+
+  flag = IDASpilsSetPreconditioner(ida_mem, Precond, PSolve);
   if(check_flag(&flag, "IDASpilsSetPreconditioner", 1)) return(1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
   tout = RCONST(0.001);
-  flag = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  flag = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&flag, "IDACalcIC", 1)) return(1);
   
   /* Print heading, basic parameters, and initial values. */
 
   PrintHeader(maxl, rtol, atol);
-  PrintOutput(mem, cc, ZERO);
+  PrintOutput(ida_mem, cc, ZERO);
   
   /* Loop over iout, call IDASolve (normal mode), print selected output. */
   
   for (iout = 1; iout <= NOUT; iout++) {
     
-    flag = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    flag = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if(check_flag(&flag, "IDASolve", 1)) return(flag);
     
-    PrintOutput(mem, cc, tret);
+    PrintOutput(ida_mem, cc, tret);
     
     if (iout < 3) tout *= TMULT; else tout += TADD;
     
@@ -314,12 +314,13 @@ int main(int argc, char *argv[])
   
   /* Print final statistics and free memory. */  
   
-  PrintFinalStats(mem);
+  PrintFinalStats(ida_mem);
   printf("num_threads = %i\n\n", num_threads);
 
   /* Free memory */
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   N_VDestroy_OpenMP(cc);
   N_VDestroy_OpenMP(cp);
@@ -363,7 +364,7 @@ int main(int argc, char *argv[])
 static int resweb(realtype tt, N_Vector cc, N_Vector cp, 
                   N_Vector res,  void *user_data)
 {
-  long int jx, jy, is, yloc, loc, np;
+  sunindextype jx, jy, is, yloc, loc, np;
   realtype *resv, *cpv;
   UserData webdata;
   
@@ -397,17 +398,15 @@ static int resweb(realtype tt, N_Vector cc, N_Vector cp,
 }
 
 
-static int Precond(realtype tt, 
-		   N_Vector cc, N_Vector cp, N_Vector rr, 
-		   realtype cj, void *user_data,
-		   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+static int Precond(realtype tt, N_Vector cc, N_Vector cp,
+                   N_Vector rr, realtype cj, void *user_data)
 {
   int flag;
   realtype uround, xx, yy, del_x, del_y;
   realtype **Pxy, *ratesxy, *Pxycol, *cxy, *cpxy, *ewtxy, cctmp;
   realtype inc, fac, sqru, perturb_rates[NUM_SPECIES];
   int is, js, jx, jy, ret;
-  void *mem;
+  void *ida_mem;
   N_Vector ewt;
   realtype hh;
   UserData webdata;
@@ -419,11 +418,11 @@ static int Precond(realtype tt,
   uround = UNIT_ROUNDOFF;
   sqru = SUNRsqrt(uround);
 
-  mem = webdata->ida_mem;
+  ida_mem = webdata->ida_mem;
   ewt = webdata->ewt;
-  flag = IDAGetErrWeights(mem, ewt);
+  flag = IDAGetErrWeights(ida_mem, ewt);
   if(check_flag(&flag, "IDAGetErrWeights", 1)) return(1);
-  flag = IDAGetCurrentStep(mem, &hh);
+  flag = IDAGetCurrentStep(ida_mem, &hh);
   if(check_flag(&flag, "IDAGetCurrentStep", 1)) return(1);
 
   for (jy = 0; jy < MY; jy++) {
@@ -466,14 +465,12 @@ static int Precond(realtype tt,
 }
 
 
-static int PSolve(realtype tt, 
-		  N_Vector cc, N_Vector cp, N_Vector rr, 
-		  N_Vector rvec, N_Vector zvec,
-		  realtype cj, realtype dalta, 
-		  void *user_data, N_Vector tmp) 
+static int PSolve(realtype tt, N_Vector cc, N_Vector cp,
+                  N_Vector rr, N_Vector rvec, N_Vector zvec,
+		  realtype cj, realtype dalta, void *user_data) 
 {
   realtype **Pxy, *zxy;
-  long int *pivot;
+  sunindextype *pivot;
   int jx, jy;
   UserData webdata;
   
@@ -560,7 +557,7 @@ static void InitUserData(UserData webdata)
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata)
 {
-  long int loc, yloc, is, jx, jy, np;
+  sunindextype loc, yloc, is, jx, jy, np;
   realtype xx, yy, xyfactor;
   realtype *ccv, *cpv, *idv;
   
@@ -611,9 +608,9 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int maxl, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype maxl, realtype rtol, realtype atol)
 {
-  printf("\nidasFoodWeb_kry_omp: Predator-prey DAE OpenMP example problem for IDAS \n\n");
+  printf("\nidasFoodWeb_kry_omp: Predator-prey DAE OpenMP example problem using Krylov solver for IDAS \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d", MX, MY);
   printf("     System size: %d\n", NEQ);
@@ -624,7 +621,7 @@ static void PrintHeader(long int maxl, realtype rtol, realtype atol)
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASpgmr,  Spgmr parameters maxl = %ld\n",maxl);
+  printf("Linear solver: SUNSPGMR, maxl = %ld\n",(long int) maxl);
   printf("CalcIC called to correct initial predator concentrations.\n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -639,17 +636,17 @@ static void PrintHeader(long int maxl, realtype rtol, realtype atol)
  * are printed for the bottom left and top right grid points only.  
  */
 
-static void PrintOutput(void *mem, N_Vector c, realtype t)
+static void PrintOutput(void *ida_mem, N_Vector c, realtype t)
 {
   int i, kused, flag;
   long int nst;
   realtype *c_bl, *c_tr, hused;
 
-  flag = IDAGetLastOrder(mem, &kused);
+  flag = IDAGetLastOrder(ida_mem, &kused);
   check_flag(&flag, "IDAGetLastOrder", 1);
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDAGetLastStep(mem, &hused);
+  flag = IDAGetLastStep(ida_mem, &hused);
   check_flag(&flag, "IDAGetLastStep", 1);
   
   c_bl = IJ_Vptr(c,0,0);
@@ -679,24 +676,24 @@ static void PrintOutput(void *mem, N_Vector c, realtype t)
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 { 
   long int nst, nre, sli, netf, nps, npevals, nrevalsLS;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
-  flag = IDASpilsGetNumLinIters(mem, &sli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &sli);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1);
-  flag = IDASpilsGetNumPrecEvals(mem, &npevals);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npevals);
   check_flag(&flag, "IDADlsGetNumJacEvals", 1);
-  flag = IDASpilsGetNumResEvals(mem, &nrevalsLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nrevalsLS);
   check_flag(&flag, "IDADlsGetNumResEvals", 1);
 
   printf("-----------------------------------------------------------\n");
@@ -720,7 +717,7 @@ static void PrintFinalStats(void *mem)
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,  
                  UserData webdata)
 { 
-  long int jx, jy, is, idyu, idyl, idxu, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxu, idxl;
   realtype xx, yy, *cxy, *ratesxy, *cratexy, dcyli, dcyui, dcxli, dcxui;
   
   /* Loop over grid points, evaluate interaction vector (length ns),
@@ -789,9 +786,9 @@ static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
  * dotprod: dot product routine for realtype arrays, for use by WebRates.    
  */
 
-static realtype dotprod(long int size, realtype *x1, realtype *x2)
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
diff --git a/examples/idas/parallel/CMakeLists.txt b/examples/idas/parallel/CMakeLists.txt
index 24978c8..4256ba6 100644
--- a/examples/idas/parallel/CMakeLists.txt
+++ b/examples/idas/parallel/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4137 $
-# $Date: 2014-06-15 12:26:15 -0700 (Sun, 15 Jun 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,20 +12,21 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for IDAS parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable IDAS_examples with the names of the parallel IDAS examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(IDAS_examples
-  "idasBruss_ASAp_kry_bbd_p\;1\;4"
-  "idasBruss_FSA_kry_bbd_p\;1\;4"
-  "idasBruss_kry_bbd_p\;1\;4"
-  "idasFoodWeb_kry_bbd_p\;1\;4"
-  "idasFoodWeb_kry_p\;1\;4"
-  "idasHeat2D_FSA_kry_bbd_p\;1\;4\;-sensi stg t"
-  "idasHeat2D_kry_bbd_p\;1\;4"
-  "idasHeat2D_kry_p\;1\;4"
-
+  "idasBruss_ASAp_kry_bbd_p\;\;1\;4\;develop"
+  "idasBruss_FSA_kry_bbd_p\;\;1\;4\;develop"
+  "idasBruss_kry_bbd_p\;\;1\;4\;develop"
+  "idasFoodWeb_kry_bbd_p\;\;1\;4\;develop"
+  "idasFoodWeb_kry_p\;\;1\;4\;develop"
+  "idasHeat2D_FSA_kry_bbd_p\;-sensi stg t\;1\;4\;develop"
+  "idasHeat2D_kry_bbd_p\;\;1\;4\;develop"
+  "idasHeat2D_kry_p\;\;1\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
@@ -38,73 +36,80 @@ SET(IDAS_examples
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDAS_LIB sundials_idas_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDAS_LIB sundials_idas_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${IDAS_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-# Add the build and install targets for each IDAS example
-
-SET(ADDED_EXECUTABLES "")
+# Add the build and install targets for each example
 FOREACH(example_tuple ${IDAS_examples})
-  # first item is example
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-
-  # Only need to add the executable once
-  LIST(FIND ADDED_EXECUTABLES ${example} index)
-  IF(index EQUAL -1)
-    LIST(APPEND ADDED_EXECUTABLES ${example})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
+    # folder to organize targets in an IDE
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  ENDIF(index EQUAL -1)
-
-  # Optional 4th element is test arguments
-  LIST(LENGTH example_tuple n)
-  IF(n EQUAL 4)
-    LIST(GET example_tuple 3 test_args)
-    STRING(REGEX REPLACE " " "_" test_name ${example}_${test_args})
-    SUNDIALS_ADD_TEST(${test_name} ${example} MPI_NPROCS ${number_of_tasks} TEST_ARGS ${test_args})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
   ELSE()
-    SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
   ENDIF()
 
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-  IF(NOT MPI_MPICC)
-    TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${test_name}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # find all .out files for this example
+  FILE(GLOB example_out ${example}.out*)
+
+  # install example source and .out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example_out}
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${IDAS_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -113,30 +118,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "IDAS")
   SET(SOLVER_LIB "sundials_idas")
-  FOREACH(example_tuple ${IDAS_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${IDAS_examples})
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(IDAS_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/idas/parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/idas/parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/idas/parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/idas/parallel/README b/examples/idas/parallel/README
index 661c144..3fd27b8 100644
--- a/examples/idas/parallel/README
+++ b/examples/idas/parallel/README
@@ -14,7 +14,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -25,7 +24,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -39,7 +41,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c
index fe570fe..90d7099 100644
--- a/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c
+++ b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.c
@@ -1,16 +1,14 @@
-/* * -----------------------------------------------------------------
- * $Revision:
- * $Date:
- * -----------------------------------------------------------------
- * Programmer(s): Cosmin Petra and Radu Serban @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Cosmin Petra and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDAS: Brusselator, parallel, GMRES, IDABBD
  * preconditioner, ASA
  *
- * This example program for IDAS uses IDASPGMR as the linear solver.
+ * This example program for IDAS uses SUNSPGMR as the linear solver.
  * It is written for a parallel computer system and uses the
  * IDABBDPRE band-block-diagonal preconditioner module for the
- * IDASPGMR package.
+ * IDASPILS interface.
  *
  * The mathematical problem solved in this example is a DAE system
  * that arises from a system of partial differential equations after
@@ -68,10 +66,10 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
 #include <idas/idas_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
-#include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
 
@@ -130,29 +128,26 @@ typedef struct {
   realtype rhs[NUM_SPECIES];
   MPI_Comm comm;
   realtype rates[2];
-  long int n_local;
+  sunindextype n_local;
 } *UserData;
 
 /* Prototypes for functions called by the IDA Solver. */
-static int res(realtype tt, 
-               N_Vector uv, N_Vector uvp, N_Vector rr, 
-               void *user_data);
+static int res(realtype tt, N_Vector uv, N_Vector uvp,
+               N_Vector rr, void *user_data);
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector uv, N_Vector uvp, N_Vector res, 
                     void *user_data);
 
-static int rescomm(long int Nlocal, realtype tt,
-                   N_Vector uv, N_Vector uvp, 
-                   void *user_data);
+static int rescomm(sunindextype Nlocal, realtype tt,
+                   N_Vector uv, N_Vector uvp, void *user_data);
 
 /* Prototypes for supporting functions */
 static void BSend(MPI_Comm comm, int thispe, int ixsub, int jysub,
                   int dsizex, int dsizey, realtype carray[]);
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
-                      int ixsub, int jysub,
-                      int dsizex, int dsizey,
+                      int ixsub, int jysub, int dsizex, int dsizey,
                       realtype cext[], realtype buffer[]);
 
 static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
@@ -163,12 +158,11 @@ static void ReactRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesx
 
 /*                  ADJOINT                        */
 
-static int resB(realtype tt, 
-                N_Vector yy, N_Vector yp,
+static int resB(realtype tt, N_Vector yy, N_Vector yp,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB,
                 void *user_dataB);
 
-static int resBlocal(long int Nlocal, realtype tt, 
+static int resBlocal(sunindextype Nlocal, realtype tt, 
                      N_Vector uv, N_Vector uvp, 
                      N_Vector yyB, N_Vector ypB, 
                      N_Vector res, void *user_dataB);
@@ -184,9 +178,9 @@ static void SetInitialProfilesB(N_Vector uv, N_Vector uvp,
                                N_Vector uvB, N_Vector uvpB,
                                 N_Vector residB, UserData data);
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        long int mudq, long int mldq, 
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol);
 
 static void PrintOutput(void *mem, N_Vector uv, realtype time,
@@ -210,9 +204,11 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
+  SUNLinearSolver LS_B;
   UserData data;
-  long int SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, tout, tret;
   N_Vector uv, uvp, resid, id, uvB, uvpB, residB, qB;
   int thispe, npes, maxl, retval;
@@ -221,7 +217,9 @@ int main(int argc, char *argv[])
 
   uv = uvp = resid = id = NULL;
   data = NULL;
-  mem = NULL;
+  LS = NULL;
+  LS_B = NULL;
+  ida_mem = NULL;
 
   /* Set communicator, and get processor number and total number of PE's. */
 
@@ -272,44 +270,47 @@ int main(int argc, char *argv[])
   atol = ATOL;
   
   /* Call IDACreate and IDAInit to initialize solution */
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetUserData(mem, data);
+  retval = IDASetUserData(ida_mem, data);
   if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetId(mem, id);
+  retval = IDASetId(ida_mem, id);
   if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDAInit(mem, res, t0, uv, uvp);
+  retval = IDAInit(ida_mem, res, t0, uv, uvp);
   if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  retval = IDASStolerances(mem, rtol, atol);
+  retval = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the IDAS LINEAR SOLVER IDASPGMR */
-  maxl = 16;
-  retval = IDASpgmr(mem, maxl);
-  if(check_flag(&retval, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the IDAS linear solver */
+  maxl = 16;                               /* max dimension of the Krylov subspace */
+  LS = SUNSPGMR(uv, PREC_LEFT, maxl);      /* IDA only allows left preconditioning */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
 
+  retval = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&retval, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
+  
 
   /* Call IDABBDPrecInit to initialize the band-block-diagonal preconditioner.
      The half-bandwidths for the difference quotient evaluation are exact
      for the system Jacobian, but only a 5-diagonal band matrix is retained. */
   mudq = mldq = NSMXSUB;
   mukeep = mlkeep = 2;
-  retval = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  retval = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                           ZERO, reslocal, NULL);
   if(check_flag(&retval, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Initialize adjoint module. */
-  retval = IDAAdjInit(mem, STEPS, IDA_POLYNOMIAL);
+  retval = IDAAdjInit(ida_mem, STEPS, IDA_POLYNOMIAL);
   if(check_flag(&retval, "IDAAdjInit", 1, thispe)) MPI_Abort(comm, 1);
 
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
   tout = RCONST(0.001);
-  retval = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  retval = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&retval, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
 
   if (thispe == 0) printf("\nStarting integration of the FORWARD problem\n\n");  
@@ -319,18 +320,18 @@ int main(int argc, char *argv[])
                                mudq, mldq, mukeep, mlkeep,
                                rtol, atol);
   /* Call IDAS in tout loop, normal mode, and print selected output. */
-  retval = IDASolveF(mem, TEND, &tret, uv, uvp, IDA_NORMAL, &nckpnt);
+  retval = IDASolveF(ida_mem, TEND, &tret, uv, uvp, IDA_NORMAL, &nckpnt);
   if(check_flag(&retval, "IDASolveF", 1, thispe)) MPI_Abort(comm, 1);
 
 
-  PrintOutput(mem, uv, tret, data, comm);
+  PrintOutput(ida_mem, uv, tret, data, comm);
 
   /* Print each PE's portion of the solution in a separate file. */
-  /* PrintSol(mem, uv, uvp, data, comm); */
+  /* PrintSol(ida_mem, uv, uvp, data, comm); */
 
   /* On PE 0, print final set of statistics. */  
   if (thispe == 0)  {
-    PrintFinalStats(mem);
+    PrintFinalStats(ida_mem);
   }
 
   /*******************************************************
@@ -344,37 +345,41 @@ int main(int argc, char *argv[])
   qB = N_VNew_Parallel(comm, local_N, SystemSize);
 
 
-  retval = IDACreateB(mem, &indexB);
+  retval = IDACreateB(ida_mem, &indexB);
 
   /*Get consistent IC */
   SetInitialProfilesB(uv, uvp, uvB, uvpB, residB, data);
 
-  retval = IDAInitB(mem, indexB, resB, TEND, uvB, uvpB);
+  retval = IDAInitB(ida_mem, indexB, resB, TEND, uvB, uvpB);
   if(check_flag(&retval, "IDAInitB", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetUserDataB(mem, indexB, data);
+  retval = IDASetUserDataB(ida_mem, indexB, data);
   if(check_flag(&retval, "IDASetUserDataB", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetIdB(mem, indexB, id);
+  retval = IDASetIdB(ida_mem, indexB, id);
   if(check_flag(&retval, "IDASetIdBIDAInitB", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASStolerancesB(mem, indexB, rtol, atol);
+  retval = IDASStolerancesB(ida_mem, indexB, rtol, atol);
   if(check_flag(&retval, "IDASStolerancesB", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the IDAS LINEAR SOLVER IDASPGMR */
+  /* Call SUNSPGMR and IDASpilsSetLinearSolverB to specify the IDAS linear solver */
   maxl = 16;
-  retval = IDASpgmrB(mem, indexB, maxl);
+  LS_B = SUNSPGMR(uv, PREC_LEFT, maxl);
+  if(check_flag((void *)LS_B, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  retval = IDASpilsSetLinearSolverB(ida_mem, indexB, LS_B);
+  if(check_flag(&retval, "IDASpilsSetLinearSolverB", 1, thispe)) MPI_Abort(comm, 1);
 
   mudq = mldq = NSMXSUB;
   mukeep = mlkeep = 2;
-  retval = IDABBDPrecInitB(mem, indexB, local_N, mudq, mldq, mukeep, mlkeep, 
+  retval = IDABBDPrecInitB(ida_mem, indexB, local_N, mudq, mldq, mukeep, mlkeep, 
                           ZERO, resBlocal, NULL);
   if(check_flag(&retval, "IDABBDPrecInitB", 1, thispe)) MPI_Abort(comm, 1);
   
-  retval = IDASolveB(mem, TBEGIN, IDA_NORMAL);
+  retval = IDASolveB(ida_mem, TBEGIN, IDA_NORMAL);
   if(check_flag(&retval, "IDASolveB", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDAGetB(mem, indexB, &tret, uvB, uvpB);
+  retval = IDAGetB(ida_mem, indexB, &tret, uvB, uvpB);
   if(check_flag(&retval, "IDAGetB", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Print each PE's portion of solution in a separate file. */
@@ -382,7 +387,7 @@ int main(int argc, char *argv[])
 
   /* On PE 0, print final set of statistics. */  
   if (thispe == 0)  {
-    PrintFinalStats(IDAGetAdjIDABmem(mem, indexB));
+    PrintFinalStats(IDAGetAdjIDABmem(ida_mem, indexB));
   }
 
 
@@ -395,7 +400,9 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(uvpB);
   N_VDestroy_Parallel(residB);
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
+  SUNLinSolFree(LS_B);
 
   free(data);
 
@@ -614,15 +621,15 @@ static void SetInitialProfilesB(N_Vector uv, N_Vector uvp,
  * and table headerr
  */
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        long int mudq, long int mldq, 
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol)
 {
   printf("\n BRUSSELATOR: chemically reacting system\n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d\n", MX, MY);
-  printf("Total system size: %d\n",SystemSize);
+  printf("Total system size: %ld\n",(long int) SystemSize);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("     Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -632,10 +639,10 @@ static void PrintHeader(int SystemSize, int maxl,
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASPGMR     Max. Krylov dimension maxl: %d\n", maxl);
+  printf("Linear solver: SUNSPGMR     Max. Krylov dimension maxl: %d\n", maxl);
   printf("Preconditioner: band-block-diagonal (IDABBDPRE), with parameters\n");
   printf("     mudq = %ld,  mldq = %ld,  mukeep = %ld,  mlkeep = %ld\n",
-         mudq, mldq, mukeep, mlkeep);
+         (long int) mudq, (long int) mldq, (long int) mukeep, (long int) mlkeep);
 
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -650,7 +657,7 @@ static void PrintHeader(int SystemSize, int maxl,
  * are printed for the bottom left and top right grid points only.
  */
 
-static void PrintOutput(void *mem, N_Vector uv, realtype tt,
+static void PrintOutput(void *ida_mem, N_Vector uv, realtype tt,
                         UserData data, MPI_Comm comm)
 {
   MPI_Status status;
@@ -678,11 +685,11 @@ static void PrintOutput(void *mem, N_Vector uv, realtype tt,
     if (npelast != 0)
       MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
     
-    flag = IDAGetLastOrder(mem, &kused);
+    flag = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&flag, "IDAGetLastOrder", 1, thispe);
-    flag = IDAGetNumSteps(mem, &nst);
+    flag = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&flag, "IDAGetNumSteps", 1, thispe);
-    flag = IDAGetLastStep(mem, &hused);
+    flag = IDAGetLastStep(ida_mem, &hused);
     check_flag(&flag, "IDAGetLastStep", 1, thispe);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -707,7 +714,7 @@ static void PrintOutput(void *mem, N_Vector uv, realtype tt,
 
 }
 
-static void PrintSol(void* mem, N_Vector uv, N_Vector uvp, 
+static void PrintSol(void* ida_mem, N_Vector uv, N_Vector uvp, 
                      UserData data, MPI_Comm comm)
 {
   FILE* fout;
@@ -750,7 +757,11 @@ static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
         
       uvxy  = IJ_Vptr(uv, ix, jy);
       /* uvxy = (&NV_Ith_P(uv, (i)*NUM_SPECIES + (j)*NSMXSUB*npex )); */
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      fprintf(fout, "%Lg\n%Lg\n", uvxy[0], uvxy[1]);
+#else
       fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+#endif      
     }
   }    
   fclose(fout);
@@ -788,7 +799,11 @@ static void PrintAdjSol(N_Vector uvB, N_Vector uvpB, UserData data)
     for (ix=0; ix<mxsub; ix++) {
 
       uvxy  = IJ_Vptr(uvB, ix, jy);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      fprintf(fout, "%Lg\n%Lg\n", uvxy[0], uvxy[1]);
+#else
       fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+#endif      
     }
   }    
   fclose(fout);
@@ -800,34 +815,34 @@ static void PrintAdjSol(N_Vector uvB, N_Vector uvpB, UserData data)
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1, 0);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1, 0);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
 
-  flag = IDASpilsGetNumConvFails(mem, &ncfl);
+  flag = IDASpilsGetNumConvFails(ida_mem, &ncfl);
   check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
-  flag = IDASpilsGetNumLinIters(mem, &nli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &nli);
   check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
-  flag = IDASpilsGetNumPrecEvals(mem, &npe);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npe);
   check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
-  flag = IDASpilsGetNumResEvals(mem, &nreLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
 
-  flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+  flag = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
   check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
 
   printf("-----------------------------------------------------------\n");
@@ -908,7 +923,7 @@ static int res(realtype tt,
 {
   int retval;
   UserData data;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   data = (UserData) user_data;
   
@@ -933,7 +948,7 @@ static int res(realtype tt,
  * and receive-waiting, in routines BRecvPost, BSend, BRecvWait.         
  */
 
-static int rescomm(long int Nlocal, realtype tt, 
+static int rescomm(sunindextype Nlocal, realtype tt, 
                    N_Vector uv, N_Vector uvp,
                    void *user_data)
 {
@@ -1149,7 +1164,7 @@ static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
  * for use by the preconditioner setup routine.                          
  */
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector uv, N_Vector uvp, N_Vector rr,
                     void *user_data)
 {
@@ -1316,7 +1331,7 @@ static int resB(realtype tt, N_Vector yy, N_Vector yp,
 {
   UserData data;
   int retval;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   data = (UserData) user_dataB;
 
@@ -1333,7 +1348,7 @@ static int resB(realtype tt, N_Vector yy, N_Vector yp,
 
 
 
-static int resBlocal(long int Nlocal, realtype tt, 
+static int resBlocal(sunindextype Nlocal, realtype tt, 
                      N_Vector uv, N_Vector uvp,
                      N_Vector uvB, N_Vector uvpB, N_Vector rrB,
                      void *user_dataB)
diff --git a/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.out b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.out
index 15a5385..41410cd 100644
--- a/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.out
+++ b/examples/idas/parallel/idasBruss_ASAp_kry_bbd_p.out
@@ -1,10 +1,14 @@
-BRUSSELATOR: chemically reacting system
+
+Starting integration of the FORWARD problem
+
+
+ BRUSSELATOR: chemically reacting system
 
 Number of species ns: 2     Mesh dimensions: 42 x 42
 Total system size: 3528
 Subgrid dimensions: 21 x 21     Processor array: 2 x 2
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDASPGMR     Max. Krylov dimension maxl: 16
+Linear solver: SUNSPGMR     Max. Krylov dimension maxl: 16
 Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
      mudq = 42,  mldq = 42,  mukeep = 2,  mlkeep = 2
 -----------------------------------------------------------
diff --git a/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c
index a52294b..c65f744 100644
--- a/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c
+++ b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.c
@@ -1,16 +1,14 @@
-/* * -----------------------------------------------------------------
- * $Revision:
- * $Date:
- * -----------------------------------------------------------------
- * Programmer(s): Cosmin Petra and Radu Serban @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Cosmin Petra and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDA: Brusselator, parallel, GMRES, IDABBD
  * preconditioner, FSA.
  *
- * This example program for IDAS uses IDASPGMR as the linear solver.
+ * This example program for IDAS uses SUNSPGMR as the linear solver.
  * It is written for a parallel computer system and uses the
  * IDABBDPRE band-block-diagonal preconditioner module for the
- * IDASPGMR package.
+ * IDASPILS interface.
  *
  * The mathematical problem solved in this example is a DAE system
  * that arises from a system of partial differential equations after
@@ -52,10 +50,10 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <idas/idas_bbdpre.h>
 #include <nvector/nvector_parallel.h>
-#include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
 
@@ -115,21 +113,19 @@ typedef struct {
   realtype rhs[NUM_SPECIES];
   MPI_Comm comm;
   realtype rates[2];
-  long int n_local;
+  sunindextype n_local;
 } *UserData;
 
 /* Prototypes for functions called by the IDA Solver. */
-static int res(realtype tt, 
-               N_Vector uv, N_Vector uvp, N_Vector rr, 
-               void *user_data);
+static int res(realtype tt, N_Vector uv, N_Vector uvp,
+               N_Vector rr, void *user_data);
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector uv, N_Vector uvp, N_Vector res, 
                     void *user_data);
 
-static int rescomm(long int Nlocal, realtype tt,
-                   N_Vector uv, N_Vector uvp, 
-                   void *user_data);
+static int rescomm(sunindextype Nlocal, realtype tt,
+                   N_Vector uv, N_Vector uvp, void *user_data);
 
 /* Integrate over spatial domain. */
 static int integr(MPI_Comm comm, N_Vector uv, void *user_data, realtype *intval);
@@ -155,9 +151,9 @@ static void InitUserData(UserData data, int thispe, int npes, MPI_Comm comm);
 static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
                                N_Vector resid, UserData data);
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        long int mudq, long int mldq,
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq,
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol);
 
 static void PrintOutput(void *mem, N_Vector uv, realtype time,
@@ -179,9 +175,10 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
-  long int SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, tout, tret;
   N_Vector uv, uvp, resid, id, *uvS, *uvpS;
   int thispe, npes, maxl, iout, retval;
@@ -192,7 +189,8 @@ int main(int argc, char *argv[])
   uv = uvp = resid = id = NULL;
   uvS = uvpS = NULL;
   data = NULL;
-  mem = NULL;
+  LS = NULL;
+  ida_mem = NULL;
 
   /* Set communicator, and get processor number and total number of PE's. */
   MPI_Init(&argc, &argv);
@@ -251,99 +249,110 @@ int main(int argc, char *argv[])
   atol = ATOL;
   
   /* Call IDACreate and IDAInit to initialize solution */
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetUserData(mem, data);
+  retval = IDASetUserData(ida_mem, data);
   if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetId(mem, id);
+  retval = IDASetId(ida_mem, id);
   if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDAInit(mem, res, t0, uv, uvp);
+  retval = IDAInit(ida_mem, res, t0, uv, uvp);
   if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  retval = IDASStolerances(mem, rtol, atol);
+  retval = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
 
   /* Enable forward sensitivity analysis. */
-  retval = IDASensInit(mem, NS, IDA_SIMULTANEOUS, NULL, uvS, uvpS);
+  retval = IDASensInit(ida_mem, NS, IDA_SIMULTANEOUS, NULL, uvS, uvpS);
   if(check_flag(&retval, "IDASensInit", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASensEEtolerances(mem);
+  retval = IDASensEEtolerances(ida_mem);
   if(check_flag(&retval, "IDASensEEtolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetSensErrCon(mem, TRUE);
+  retval = IDASetSensErrCon(ida_mem, SUNTRUE);
   if (check_flag(&retval, "IDASetSensErrCon", 1, thispe)) MPI_Abort(comm, 1);
 
   pbar[0] = data->eps[0];
   pbar[1] = data->eps[1];
-  retval = IDASetSensParams(mem, data->eps, pbar, NULL);
+  retval = IDASetSensParams(ida_mem, data->eps, pbar, NULL);
   if (check_flag(&retval, "IDASetSensParams", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the IDAS LINEAR SOLVER IDASPGMR */
-  maxl = 16;
-  retval = IDASpgmr(mem, maxl);
-  if(check_flag(&retval, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the IDAS linear solver */
+  maxl = 16;                               /* max dimension of the Krylov subspace */
+  LS = SUNSPGMR(uv, PREC_LEFT, maxl);      /* IDA only allows left preconditioning */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  retval = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&retval, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDABBDPrecInit to initialize the band-block-diagonal preconditioner.
      The half-bandwidths for the difference quotient evaluation are exact
      for the system Jacobian, but only a 5-diagonal band matrix is retained. */
   mudq = mldq = NSMXSUB;
   mukeep = mlkeep = 2;
-  retval = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  retval = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                           ZERO, reslocal, NULL);
   if(check_flag(&retval, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
   tout = RCONST(0.001);
-  retval = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  retval = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&retval, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
   
   /* On PE 0, print heading, basic parameters, initial values. */
   if (thispe == 0) PrintHeader(SystemSize, maxl, 
                                mudq, mldq, mukeep, mlkeep,
                                rtol, atol);
-  PrintOutput(mem, uv, t0, data, comm);
+  PrintOutput(ida_mem, uv, t0, data, comm);
 
 
   /* Call IDAS in tout loop, normal mode, and print selected output. */
   for (iout = 1; iout <= NOUT; iout++) {
     
-    retval = IDASolve(mem, tout, &tret, uv, uvp, IDA_NORMAL);
+    retval = IDASolve(ida_mem, tout, &tret, uv, uvp, IDA_NORMAL);
     if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(mem, uv, tret, data, comm);
+    PrintOutput(ida_mem, uv, tret, data, comm);
 
     if (iout < 3) tout *= TMULT;
     else          tout += TADD;
 
   }
   /* Print each PE's portion of the solution in a separate file. */
-  /* PrintSol(mem, uv, uvp, data, comm); */
+  /* PrintSol(ida_mem, uv, uvp, data, comm); */
 
 
   /* On PE 0, print final set of statistics. */  
   if (thispe == 0) {
-    PrintFinalStats(mem);
+    PrintFinalStats(ida_mem);
   }
 
   /* calculate integral of u over domain. */
   integr(comm, uv, data, &intval);
   if (thispe == 0) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    printf("\n\nThe average of u on the domain:\ng = %Lg\n", intval);
+#else
     printf("\n\nThe average of u on the domain:\ng = %g\n", intval);
+#endif    
   }
 
   /* integrate the sensitivities of u over domain. */
-  IDAGetSens(mem, &tret, uvS);
+  IDAGetSens(ida_mem, &tret, uvS);
   if (thispe == 0)
     printf("\nSensitivities of g:\n");
 
   for (is=0; is<NS; is++) {
     integr(comm, uvS[is], data, &intval);
     if (thispe == 0) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      printf("w.r.t. eps%d = %14.10Lf\n", is, intval);
+#else
       printf("w.r.t. eps%d = %14.10f\n", is, intval);
+#endif      
     }
   }
 
@@ -354,7 +363,8 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(resid);
   N_VDestroyVectorArray_Parallel(uvS, NS);
   N_VDestroyVectorArray_Parallel(uvpS, NS);
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   free(data);
 
@@ -499,15 +509,15 @@ static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
  * and table headerr
  */
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        long int mudq, long int mldq, 
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol)
 {
   printf("\n Brusselator PDE -  DAE parallel example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d\n", MX, MY);
-  printf("Total system size: %d\n",SystemSize);
+  printf("Total system size: %ld\n",(long int) SystemSize);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("     Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -517,10 +527,10 @@ static void PrintHeader(int SystemSize, int maxl,
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASPGMR     Max. Krylov dimension maxl: %d\n", maxl);
+  printf("Linear solver: SUNSPGMR     Max. Krylov dimension maxl: %d\n", maxl);
   printf("Preconditioner: band-block-diagonal (IDABBDPRE), with parameters\n");
   printf("     mudq = %ld,  mldq = %ld,  mukeep = %ld,  mlkeep = %ld\n",
-         mudq, mldq, mukeep, mlkeep);
+         (long int) mudq, (long int) mldq, (long int) mukeep, (long int) mlkeep);
   printf("CalcIC called to correct initial concentrations \n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -535,7 +545,7 @@ static void PrintHeader(int SystemSize, int maxl,
  * are printed for the bottom left and top right grid points only.
  */
 
-static void PrintOutput(void *mem, N_Vector uv, realtype tt,
+static void PrintOutput(void *ida_mem, N_Vector uv, realtype tt,
                         UserData data, MPI_Comm comm)
 {
   MPI_Status status;
@@ -562,11 +572,11 @@ static void PrintOutput(void *mem, N_Vector uv, realtype tt,
     if (npelast != 0)
       MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
     
-    flag = IDAGetLastOrder(mem, &kused);
+    flag = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&flag, "IDAGetLastOrder", 1, thispe);
-    flag = IDAGetNumSteps(mem, &nst);
+    flag = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&flag, "IDAGetNumSteps", 1, thispe);
-    flag = IDAGetLastStep(mem, &hused);
+    flag = IDAGetLastStep(ida_mem, &hused);
     check_flag(&flag, "IDAGetLastStep", 1, thispe);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -594,7 +604,7 @@ static void PrintOutput(void *mem, N_Vector uv, realtype tt,
 /* 
  * PrintSol the PE's portion of the solution to a file.
  */
-static void PrintSol(void* mem, N_Vector uv, N_Vector uvp, 
+static void PrintSol(void* ida_mem, N_Vector uv, N_Vector uvp, 
                      UserData data, MPI_Comm comm)
 {
   FILE* fout;
@@ -618,7 +628,11 @@ static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
     for (ix=0; ix<mxsub; ix++) {
     
       uvxy  = IJ_Vptr(uv, ix, jy);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      fprintf(fout, "%Lg\n%Lg\n", uvxy[0], uvxy[1]);
+#else
       fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+#endif      
     }
   }    
   fclose(fout);
@@ -630,34 +644,34 @@ static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1, 0);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1, 0);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
 
-  flag = IDASpilsGetNumConvFails(mem, &ncfl);
+  flag = IDASpilsGetNumConvFails(ida_mem, &ncfl);
   check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
-  flag = IDASpilsGetNumLinIters(mem, &nli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &nli);
   check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
-  flag = IDASpilsGetNumPrecEvals(mem, &npe);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npe);
   check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
-  flag = IDASpilsGetNumResEvals(mem, &nreLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
 
-  flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+  flag = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
   check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
 
   printf("-----------------------------------------------------------\n");
@@ -732,13 +746,12 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id)
  * reslocal, for computation of the residuals on this processor.      
  */
 
-static int res(realtype tt, 
-               N_Vector uv, N_Vector uvp, N_Vector rr, 
-               void *user_data)
+static int res(realtype tt, N_Vector uv, N_Vector uvp,
+               N_Vector rr, void *user_data)
 {
   int retval;
   UserData data;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   data = (UserData) user_data;
   
@@ -762,9 +775,8 @@ static int res(realtype tt,
  * The message-passing uses blocking sends, non-blocking receives,
  * and receive-waiting, in routines BRecvPost, BSend, BRecvWait.         
  */
-static int rescomm(long int Nlocal, realtype tt, 
-                   N_Vector uv, N_Vector uvp,
-                   void *user_data)
+static int rescomm(sunindextype Nlocal, realtype tt, 
+                   N_Vector uv, N_Vector uvp, void *user_data)
 {
 
   UserData data;
@@ -808,8 +820,7 @@ static int rescomm(long int Nlocal, realtype tt,
  */
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
-                      int ixsub, int jysub,
-                      int dsizex, int dsizey,
+                      int ixsub, int jysub, int dsizex, int dsizey,
                       realtype cext[], realtype buffer[])
 {
   int offsetce;
@@ -976,9 +987,8 @@ static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
  * for use by the preconditioner setup routine.                          
  */
 
-static int reslocal(long int Nlocal, realtype tt, 
-                    N_Vector uv, N_Vector uvp, N_Vector rr,
-                    void *user_data)
+static int reslocal(sunindextype Nlocal, realtype tt, N_Vector uv, 
+                    N_Vector uvp, N_Vector rr, void *user_data)
 {
   realtype *uvdata, *uvpxy, *resxy, xx, yy, dcyli, dcyui, dcxli, dcxui, dx2, dy2;
   realtype ixend, ixstart, jystart, jyend;
@@ -1121,8 +1131,8 @@ static int reslocal(long int Nlocal, realtype tt,
  * At a given (x,y), evaluate the array of ns reaction terms R.          
  */
 
-static void ReactRates(realtype xx, realtype yy, realtype *uvval, realtype *rates,
-                       UserData data)
+static void ReactRates(realtype xx, realtype yy, realtype *uvval, 
+                       realtype *rates, UserData data)
 {
   realtype A, B;
 
diff --git a/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out
index a3165f8..3618981 100644
--- a/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out
+++ b/examples/idas/parallel/idasBruss_FSA_kry_bbd_p.out
@@ -1,10 +1,11 @@
-Brusselator PDE -  DAE parallel example problem for IDA 
+
+ Brusselator PDE -  DAE parallel example problem for IDA 
 
 Number of species ns: 2     Mesh dimensions: 82 x 82
 Total system size: 13448
 Subgrid dimensions: 41 x 41     Processor array: 2 x 2
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDASPGMR     Max. Krylov dimension maxl: 16
+Linear solver: SUNSPGMR     Max. Krylov dimension maxl: 16
 Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
      mudq = 82,  mldq = 82,  mukeep = 2,  mlkeep = 2
 CalcIC called to correct initial concentrations 
@@ -56,5 +57,5 @@ The average of u on the domain:
 g = 1.62453
 
 Sensitivities of g:
-w.r.t. eps0 =  16.1571399307
-w.r.t. eps1 =  -3.7188337016
+w.r.t. eps0 =  16.1571399862
+w.r.t. eps1 =  -3.7188305042
diff --git a/examples/idas/parallel/idasBruss_kry_bbd_p.c b/examples/idas/parallel/idasBruss_kry_bbd_p.c
index 83ce142..cc42ee6 100644
--- a/examples/idas/parallel/idasBruss_kry_bbd_p.c
+++ b/examples/idas/parallel/idasBruss_kry_bbd_p.c
@@ -1,16 +1,14 @@
-/* * -----------------------------------------------------------------
- * $Revision:
- * $Date:
- * -----------------------------------------------------------------
- * Programmer(s): Cosmin Petra and Radu Serban @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Cosmin Petra and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDAS: Brusselator, parallel, GMRES, IDABBD
  * preconditioner.
  *
- * This example program for IDAS uses IDASPGMR as the linear solver.
+ * This example program for IDAS uses SUSNSPGMR as the linear solver.
  * It is written for a parallel computer system and uses the
  * IDABBDPRE band-block-diagonal preconditioner module for the
- * IDASPGMR package.
+ * IDASPILS interface.
  *
  * The mathematical problem solved in this example is a DAE system
  * that arises from a system of partial differential equations after
@@ -42,10 +40,10 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
 #include <idas/idas_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
-#include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
 
@@ -104,36 +102,33 @@ typedef struct {
   realtype rhs[NUM_SPECIES];
   MPI_Comm comm;
   realtype rates[2];
-  long int n_local;
+  sunindextype n_local;
 } *UserData;
 
 /* Prototypes for functions called by the IDA Solver. */
-static int res(realtype tt, 
-               N_Vector uv, N_Vector uvp, N_Vector rr, 
-               void *user_data);
+static int res(realtype tt, N_Vector uv, N_Vector uvp,
+               N_Vector rr, void *user_data);
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector uv, N_Vector uvp, N_Vector res, 
                     void *user_data);
 
-static int rescomm(long int Nlocal, realtype tt,
-                   N_Vector uv, N_Vector uvp, 
-                   void *user_data);
+static int rescomm(sunindextype Nlocal, realtype tt,
+                   N_Vector uv, N_Vector uvp, void *user_data);
 
 /* Prototypes for supporting functions */
 static void BSend(MPI_Comm comm, int thispe, int ixsub, int jysub,
                   int dsizex, int dsizey, realtype carray[]);
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
-                      int ixsub, int jysub,
-                      int dsizex, int dsizey,
+                      int ixsub, int jysub, int dsizex, int dsizey,
                       realtype cext[], realtype buffer[]);
 
 static void BRecvWait(MPI_Request request[], int ixsub, int jysub,
                       int dsizex, realtype cext[], realtype buffer[]);
 
-static void ReactRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
-                     UserData data);
+static void ReactRates(realtype xx, realtype yy, realtype *cxy,
+                       realtype *ratesxy, UserData data);
 
 /* Prototypes for private functions */
 static void InitUserData(UserData data, int thispe, int npes, 
@@ -142,18 +137,18 @@ static void InitUserData(UserData data, int thispe, int npes,
 static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
                                N_Vector resid, UserData data);
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        long int mudq, long int mldq, 
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol);
 
-static void PrintOutput(void *mem, N_Vector uv, realtype time,
+static void PrintOutput(void *ida_mem, N_Vector uv, realtype time,
                         UserData data, MPI_Comm comm);
 
-static void PrintSol(void* mem, N_Vector uv, N_Vector uvp, UserData data,
+static void PrintSol(void* ida_mem, N_Vector uv, N_Vector uvp, UserData data,
                      MPI_Comm comm);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -166,16 +161,18 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
-  long int SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, tout, tret;
   N_Vector uv, uvp, resid, id;
   int thispe, npes, maxl, iout, retval;
 
   uv = uvp = resid = id = NULL;
   data = NULL;
-  mem = NULL;
+  LS = NULL;
+  ida_mem = NULL;
 
   /* Set communicator, and get processor number and total number of PE's. */
   MPI_Init(&argc, &argv);
@@ -225,25 +222,28 @@ int main(int argc, char *argv[])
   
   /* Call IDACreate and IDAInit to initialize solution */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetUserData(mem, data);
+  retval = IDASetUserData(ida_mem, data);
   if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetId(mem, id);
+  retval = IDASetId(ida_mem, id);
   if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDAInit(mem, res, t0, uv, uvp);
+  retval = IDAInit(ida_mem, res, t0, uv, uvp);
   if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  retval = IDASStolerances(mem, rtol, atol);
+  retval = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the IDAS LINEAR SOLVER IDASPGMR */
-  maxl = 16;
-  retval = IDASpgmr(mem, maxl);
-  if(check_flag(&retval, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the IDAS linear solver */
+  maxl = 16;                               /* max dimension of the Krylov subspace */
+  LS = SUNSPGMR(uv, PREC_LEFT, maxl);      /* IDA only allows left preconditioning */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  retval = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&retval, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
 
 
   /* Call IDABBDPrecInit to initialize the band-block-diagonal preconditioner.
@@ -251,16 +251,16 @@ int main(int argc, char *argv[])
      for the system Jacobian, but only a 5-diagonal band matrix is retained. */
   mudq = mldq = NSMXSUB;
   mukeep = mlkeep = 2;
-  retval = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  retval = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                           ZERO, reslocal, NULL);
   if(check_flag(&retval, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
   tout = RCONST(0.001);
-  retval = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  retval = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&retval, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
   
-  retval = IDAGetConsistentIC(mem, uv, uvp);
+  retval = IDAGetConsistentIC(ida_mem, uv, uvp);
   if(check_flag(&retval, "IDAGetConsistentIC", 1, thispe)) MPI_Abort(comm, 1);
 
   /* On PE 0, print heading, basic parameters, initial values. */
@@ -268,28 +268,28 @@ int main(int argc, char *argv[])
                                mudq, mldq, mukeep, mlkeep,
                                rtol, atol);
 
-  PrintOutput(mem, uv, t0, data, comm);
+  PrintOutput(ida_mem, uv, t0, data, comm);
 
 
   /* Call IDAS in tout loop, normal mode, and print selected output. */
   for (iout = 1; iout <= NOUT; iout++) {
     
-    retval = IDASolve(mem, tout, &tret, uv, uvp, IDA_NORMAL);
+    retval = IDASolve(ida_mem, tout, &tret, uv, uvp, IDA_NORMAL);
     if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(mem, uv, tret, data, comm);
+    PrintOutput(ida_mem, uv, tret, data, comm);
 
     if (iout < 3) tout *= TMULT; 
     else          tout += TADD;
 
   }
   /* Print each PE's portion of the solution in a separate file. */
-  /* PrintSol(mem, uv, uvp, data, comm); */
+  /* PrintSol(ida_mem, uv, uvp, data, comm); */
 
 
   /* On PE 0, print final set of statistics. */  
   if (thispe == 0)  {
-    PrintFinalStats(mem);
+    PrintFinalStats(ida_mem);
   }
 
   /* Free memory. */
@@ -297,8 +297,9 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(uvp);
   N_VDestroy_Parallel(id);
   N_VDestroy_Parallel(resid);
-  IDAFree(&mem);
-
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
+  
   free(data);
 
   MPI_Finalize();
@@ -334,13 +335,10 @@ static void InitUserData(UserData data, int thispe, int npes,
   data->nsmxsub2 = (MXSUB+2)*NUM_SPECIES;
   data->comm = comm;
   data->n_local = MXSUB*MYSUB*NUM_SPECIES;
-
   data->A = ctA;
   data->B = ctB;
   data->L = ctL;
   data->eps[0] = data->eps[1] = ctEps;
-
-  
 }
 
 /*
@@ -436,7 +434,6 @@ static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
   res(ZERO, uv, uvp, resid, data);
   N_VScale(-ONE, resid, uvp);
 
-
 }
 
 /*
@@ -444,15 +441,15 @@ static void SetInitialProfiles(N_Vector uv, N_Vector uvp, N_Vector id,
  * and table headerr
  */
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        long int mudq, long int mldq, 
-                        long int mukeep, long int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol)
 {
   printf("\nidasBruss_kry_bbd_p: Brusselator DAE parallel example problem for IDAS \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d", MX, MY);
-  printf("     Total system size: %d\n",SystemSize);
+  printf("     Total system size: %ld\n",(long int) SystemSize);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("     Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -462,10 +459,10 @@ static void PrintHeader(int SystemSize, int maxl,
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASPGMR     Max. Krylov dimension maxl: %d\n", maxl);
+  printf("Linear solver: SUNSPGMR     Max. Krylov dimension maxl: %d\n", maxl);
   printf("Preconditioner: band-block-diagonal (IDABBDPRE), with parameters\n");
   printf("     mudq = %ld,  mldq = %ld,  mukeep = %ld,  mlkeep = %ld\n",
-         mudq, mldq, mukeep, mlkeep);
+         (long int) mudq, (long int) mldq, (long int) mukeep, (long int) mlkeep);
   printf("CalcIC called to correct initial guesses \n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -480,7 +477,7 @@ static void PrintHeader(int SystemSize, int maxl,
  * are printed for the bottom left and top right grid points only.
  */
 
-static void PrintOutput(void *mem, N_Vector uv, realtype tt,
+static void PrintOutput(void *ida_mem, N_Vector uv, realtype tt,
                         UserData data, MPI_Comm comm)
 {
   MPI_Status status;
@@ -507,11 +504,11 @@ static void PrintOutput(void *mem, N_Vector uv, realtype tt,
     if (npelast != 0)
       MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
     
-    flag = IDAGetLastOrder(mem, &kused);
+    flag = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&flag, "IDAGetLastOrder", 1, thispe);
-    flag = IDAGetNumSteps(mem, &nst);
+    flag = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&flag, "IDAGetNumSteps", 1, thispe);
-    flag = IDAGetLastStep(mem, &hused);
+    flag = IDAGetLastStep(ida_mem, &hused);
     check_flag(&flag, "IDAGetLastStep", 1, thispe);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -539,7 +536,7 @@ static void PrintOutput(void *mem, N_Vector uv, realtype tt,
 /* 
  * PrintSol the PE's portion of the solution to a file.
  */
-static void PrintSol(void* mem, N_Vector uv, N_Vector uvp, 
+static void PrintSol(void* ida_mem, N_Vector uv, N_Vector uvp, 
                      UserData data, MPI_Comm comm)
 {
   FILE* fout;
@@ -563,7 +560,11 @@ static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
     for (ix=0; ix<mxsub; ix++) {
     
       uvxy  = IJ_Vptr(uv, ix, jy);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      fprintf(fout, "%Lg\n%Lg\n", uvxy[0], uvxy[1]);
+#else
       fprintf(fout, "%g\n%g\n", uvxy[0], uvxy[1]);
+#endif      
     }
   }    
   fclose(fout);
@@ -575,34 +576,34 @@ static void PrintSol(void* mem, N_Vector uv, N_Vector uvp,
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1, 0);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1, 0);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
 
-  flag = IDASpilsGetNumConvFails(mem, &ncfl);
+  flag = IDASpilsGetNumConvFails(ida_mem, &ncfl);
   check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
-  flag = IDASpilsGetNumLinIters(mem, &nli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &nli);
   check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
-  flag = IDASpilsGetNumPrecEvals(mem, &npe);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npe);
   check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
-  flag = IDASpilsGetNumResEvals(mem, &nreLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
 
-  flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+  flag = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
   check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
 
   printf("-----------------------------------------------------------\n");
@@ -677,13 +678,12 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id)
  * reslocal, for computation of the residuals on this processor.      
  */
 
-static int res(realtype tt, 
-               N_Vector uv, N_Vector uvp, N_Vector rr, 
-               void *user_data)
+static int res(realtype tt, N_Vector uv, N_Vector uvp, 
+               N_Vector rr, void *user_data)
 {
   int retval;
   UserData data;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   data = (UserData) user_data;
   
@@ -707,9 +707,8 @@ static int res(realtype tt,
  * The message-passing uses blocking sends, non-blocking receives,
  * and receive-waiting, in routines BRecvPost, BSend, BRecvWait.         
  */
-static int rescomm(long int Nlocal, realtype tt, 
-                   N_Vector uv, N_Vector uvp,
-                   void *user_data)
+static int rescomm(sunindextype Nlocal, realtype tt, 
+                   N_Vector uv, N_Vector uvp, void *user_data)
 {
 
   UserData data;
@@ -753,8 +752,7 @@ static int rescomm(long int Nlocal, realtype tt,
  */
 
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
-                      int ixsub, int jysub,
-                      int dsizex, int dsizey,
+                      int ixsub, int jysub, int dsizex, int dsizey,
                       realtype cext[], realtype buffer[])
 {
   int offsetce;
@@ -921,9 +919,8 @@ static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
  * for use by the preconditioner setup routine.                          
  */
 
-static int reslocal(long int Nlocal, realtype tt, 
-                    N_Vector uv, N_Vector uvp, N_Vector rr,
-                    void *user_data)
+static int reslocal(sunindextype Nlocal, realtype tt, N_Vector uv, 
+                    N_Vector uvp, N_Vector rr, void *user_data)
 {
   realtype *uvdata, *uvpxy, *resxy, xx, yy, dcyli, dcyui, dcxli, dcxui, dx2, dy2;
   realtype ixend, ixstart, jystart, jyend;
@@ -1066,8 +1063,8 @@ static int reslocal(long int Nlocal, realtype tt,
  * At a given (x,y), evaluate the array of ns reaction terms R.          
  */
 
-static void ReactRates(realtype xx, realtype yy, realtype *uvval, realtype *rates,
-                       UserData data)
+static void ReactRates(realtype xx, realtype yy, realtype *uvval, 
+                       realtype *rates, UserData data)
 {
   realtype A, B;
 
diff --git a/examples/idas/parallel/idasBruss_kry_bbd_p.out b/examples/idas/parallel/idasBruss_kry_bbd_p.out
index 3afac54..329a0f2 100644
--- a/examples/idas/parallel/idasBruss_kry_bbd_p.out
+++ b/examples/idas/parallel/idasBruss_kry_bbd_p.out
@@ -1,9 +1,10 @@
+
 idasBruss_kry_bbd_p: Brusselator DAE parallel example problem for IDAS 
 
 Number of species ns: 2     Mesh dimensions: 42 x 42     Total system size: 3528
 Subgrid dimensions: 21 x 21     Processor array: 2 x 2
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDASPGMR     Max. Krylov dimension maxl: 16
+Linear solver: SUNSPGMR     Max. Krylov dimension maxl: 16
 Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
      mudq = 42,  mldq = 42,  mukeep = 2,  mlkeep = 2
 CalcIC called to correct initial guesses 
diff --git a/examples/idas/parallel/idasFoodWeb_kry_bbd_p.c b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.c
index 63473d4..95a44e1 100644
--- a/examples/idas/parallel/idasFoodWeb_kry_bbd_p.c
+++ b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.c
@@ -1,19 +1,15 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *         Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDA: Food web, parallel, GMRES, IDABBD
  * preconditioner.
  *
- * This example program for IDAS uses IDASPGMR as the linear solver.
+ * This example program for IDA uses SUNSPGMR as the linear solver.
  * It is written for a parallel computer system and uses the
  * IDABBDPRE band-block-diagonal preconditioner module for the
- * IDASPGMR package. It was originally run on a Sun SPARC cluster
- * and used MPICH.
+ * SUNSPGMR package. 
  *
  * The mathematical problem solved in this example is a DAE system
  * that arises from a system of partial differential equations after
@@ -72,7 +68,7 @@
  * submeshes, processor by processor, with an MXSUB by MYSUB mesh
  * on each of NPEX * NPEY processors.
  *
- * The DAE system is solved by IDAS using the IDASPGMR linear solver,
+ * The DAE system is solved by IDA using the SUNSPGMR linear solver,
  * in conjunction with the preconditioner module IDABBDPRE. The
  * preconditioner uses a 5-diagonal band-block-diagonal
  * approximation (half-bandwidths = 2). Output is printed at
@@ -101,11 +97,12 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
 #include <idas/idas_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
-#include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
+#include <sundials/sundials_dense.h>
 #include <sundials/sundials_math.h>
 
 #include <mpi.h>
@@ -165,20 +162,19 @@ typedef struct {
     rhs[NUM_SPECIES], cext[(MXSUB+2)*(MYSUB+2)*NUM_SPECIES];
   MPI_Comm comm;
   N_Vector rates;
-  long int n_local;
+  sunindextype n_local;
 } *UserData;
 
 /* Prototypes for functions called by the IDA Solver. */
 
-static int resweb(realtype tt, 
-                  N_Vector cc, N_Vector cp, N_Vector rr, 
-                  void *user_data);
+static int resweb(realtype tt, N_Vector cc, N_Vector cp,
+                  N_Vector rr, void *user_data);
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector cc, N_Vector cp, N_Vector res, 
                     void *user_data);
 
-static int rescomm(long int Nlocal, realtype tt,
+static int rescomm(sunindextype Nlocal, realtype tt,
                    N_Vector cc, N_Vector cp, 
                    void *user_data);
 
@@ -208,15 +204,15 @@ static void InitUserData(UserData webdata, int thispe, int npes,
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                N_Vector scrtch, UserData webdata);
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        int mudq, int mldq, 
-                        int mukeep, int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol);
 
-static void PrintOutput(void *mem, N_Vector cc, realtype time,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype time,
                         UserData webdata, MPI_Comm comm);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -229,16 +225,18 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData webdata;
-  long int SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype SystemSize, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, tout, tret;
   N_Vector cc, cp, res, id;
   int thispe, npes, maxl, iout, retval;
 
   cc = cp = res = id = NULL;
   webdata = NULL;
-  mem = NULL;
+  LS = NULL;
+  ida_mem = NULL;
 
   /* Set communicator, and get processor number and total number of PE's. */
 
@@ -296,26 +294,28 @@ int main(int argc, char *argv[])
   
   /* Call IDACreate and IDAMalloc to initialize solution */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetUserData(mem, webdata);
+  retval = IDASetUserData(ida_mem, webdata);
   if(check_flag(&retval, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDASetId(mem, id);
+  retval = IDASetId(ida_mem, id);
   if(check_flag(&retval, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  retval = IDAInit(mem, resweb, t0, cc, cp);
+  retval = IDAInit(ida_mem, resweb, t0, cc, cp);
   if(check_flag(&retval, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  retval = IDASStolerances(mem, rtol, atol);
+  retval = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the IDA linear solver IDASPGMR */
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the linear solver */
 
   maxl = 16;
-  retval = IDASpgmr(mem, maxl);
-  if(check_flag(&retval, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  LS = SUNSPGMR(cc, PREC_LEFT, maxl);
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+  retval = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&retval, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDABBDPrecInit to initialize the band-block-diagonal preconditioner.
      The half-bandwidths for the difference quotient evaluation are exact
@@ -323,14 +323,14 @@ int main(int argc, char *argv[])
   
   mudq = mldq = NSMXSUB;
   mukeep = mlkeep = 2;
-  retval = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  retval = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                           ZERO, reslocal, NULL);
   if(check_flag(&retval, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
   
   tout = RCONST(0.001);
-  retval = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  retval = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if(check_flag(&retval, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
   
   /* On PE 0, print heading, basic parameters, initial values. */
@@ -338,16 +338,16 @@ int main(int argc, char *argv[])
   if (thispe == 0) PrintHeader(SystemSize, maxl, 
                                mudq, mldq, mukeep, mlkeep,
                                rtol, atol);
-  PrintOutput(mem, cc, t0, webdata, comm);
+  PrintOutput(ida_mem, cc, t0, webdata, comm);
 
   /* Call IDA in tout loop, normal mode, and print selected output. */
   
   for (iout = 1; iout <= NOUT; iout++) {
     
-    retval = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    retval = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if(check_flag(&retval, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
     
-    PrintOutput(mem, cc, tret, webdata, comm);
+    PrintOutput(ida_mem, cc, tret, webdata, comm);
     
     if (iout < 3) tout *= TMULT; 
     else          tout += TADD;
@@ -356,7 +356,7 @@ int main(int argc, char *argv[])
   
   /* On PE 0, print final set of statistics. */
   
-  if (thispe == 0)  PrintFinalStats(mem);
+  if (thispe == 0)  PrintFinalStats(ida_mem);
 
   /* Free memory. */
 
@@ -364,7 +364,8 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(cp);
   N_VDestroy_Parallel(id);
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   destroyMat(webdata->acoef);
   N_VDestroy_Parallel(webdata->rates);
@@ -478,7 +479,8 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
       cxy = IJ_Vptr(cc,ix,jy); 
       idxy = IJ_Vptr(id,ix,jy); 
       for (is = 0; is < NUM_SPECIES; is++) {
-	if (is < np) { cxy[is] = RCONST(10.0) + (realtype)(is+1)*xyfactor; idxy[is] = ONE; }
+	if (is < np)
+          { cxy[is] = RCONST(10.0) + (realtype)(is+1)*xyfactor; idxy[is] = ONE; }
         else { cxy[is] = 1.0e5; idxy[is] = ZERO; }
       }
     }
@@ -505,15 +507,15 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * and table headerr
  */
 
-static void PrintHeader(int SystemSize, int maxl, 
-                        int mudq, int mldq, 
-                        int mukeep, int mlkeep,
+static void PrintHeader(sunindextype SystemSize, int maxl, 
+                        sunindextype mudq, sunindextype mldq, 
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype rtol, realtype atol)
 {
   printf("\nidasFoodWeb_kry_bbd_p: Predator-prey DAE parallel example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d", MX, MY);
-  printf("     Total system size: %d\n",SystemSize);
+  printf("     Total system size: %ld\n",(long int) SystemSize);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("     Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -523,10 +525,10 @@ static void PrintHeader(int SystemSize, int maxl,
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASPGMR     Max. Krylov dimension maxl: %d\n", maxl);
+  printf("Linear solver: SUNSPGMR     Max. Krylov dimension maxl: %d\n", maxl);
   printf("Preconditioner: band-block-diagonal (IDABBDPRE), with parameters\n");
-  printf("     mudq = %d,  mldq = %d,  mukeep = %d,  mlkeep = %d\n",
-         mudq, mldq, mukeep, mlkeep);
+  printf("     mudq = %ld,  mldq = %ld,  mukeep = %ld,  mlkeep = %ld\n",
+         (long int) mudq, (long int) mldq, (long int) mukeep, (long int) mlkeep);
   printf("CalcIC called to correct initial predator concentrations \n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -541,7 +543,7 @@ static void PrintHeader(int SystemSize, int maxl,
  * are printed for the bottom left and top right grid points only.
  */
 
-static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype tt,
                         UserData webdata, MPI_Comm comm)
 {
   MPI_Status status;
@@ -569,11 +571,11 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
     if (npelast != 0)
       MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
     
-    flag = IDAGetLastOrder(mem, &kused);
+    flag = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&flag, "IDAGetLastOrder", 1, thispe);
-    flag = IDAGetNumSteps(mem, &nst);
+    flag = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&flag, "IDAGetNumSteps", 1, thispe);
-    flag = IDAGetLastStep(mem, &hused);
+    flag = IDAGetLastStep(ida_mem, &hused);
     check_flag(&flag, "IDAGetLastStep", 1, thispe);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -602,34 +604,34 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps, nge;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1, 0);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1, 0);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
 
-  flag = IDASpilsGetNumConvFails(mem, &ncfl);
+  flag = IDASpilsGetNumConvFails(ida_mem, &ncfl);
   check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
-  flag = IDASpilsGetNumLinIters(mem, &nli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &nli);
   check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
-  flag = IDASpilsGetNumPrecEvals(mem, &npe);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npe);
   check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
-  flag = IDASpilsGetNumResEvals(mem, &nreLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
 
-  flag = IDABBDPrecGetNumGfnEvals(mem, &nge);
+  flag = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
   check_flag(&flag, "IDABBDPrecGetNumGfnEvals", 1, 0);
 
   printf("-----------------------------------------------------------\n");
@@ -709,7 +711,7 @@ static int resweb(realtype tt,
 {
   int retval;
   UserData webdata;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   webdata = (UserData) user_data;
   
@@ -734,7 +736,7 @@ static int resweb(realtype tt,
  * and receive-waiting, in routines BRecvPost, BSend, BRecvWait.         
  */
 
-static int rescomm(long int Nlocal, realtype tt, 
+static int rescomm(sunindextype Nlocal, realtype tt, 
                    N_Vector cc, N_Vector cp,
                    void *user_data)
 {
@@ -957,7 +959,7 @@ static void BSend(MPI_Comm comm, int my_pe, int ixsub, int jysub,
  * for use by the preconditioner setup routine.                          
  */
 
-static int reslocal(long int Nlocal, realtype tt, 
+static int reslocal(sunindextype Nlocal, realtype tt, 
                     N_Vector cc, N_Vector cp, N_Vector rr,
                     void *user_data)
 {
diff --git a/examples/idas/parallel/idasFoodWeb_kry_bbd_p.out b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.out
index da6066b..c7beeb0 100644
--- a/examples/idas/parallel/idasFoodWeb_kry_bbd_p.out
+++ b/examples/idas/parallel/idasFoodWeb_kry_bbd_p.out
@@ -1,9 +1,10 @@
+
 idasFoodWeb_kry_bbd_p: Predator-prey DAE parallel example problem for IDA 
 
 Number of species ns: 2     Mesh dimensions: 20 x 20     Total system size: 800
 Subgrid dimensions: 10 x 10     Processor array: 2 x 2
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDASPGMR     Max. Krylov dimension maxl: 16
+Linear solver: SUNSPGMR     Max. Krylov dimension maxl: 16
 Preconditioner: band-block-diagonal (IDABBDPRE), with parameters
      mudq = 20,  mldq = 20,  mukeep = 2,  mlkeep = 2
 CalcIC called to correct initial predator concentrations 
@@ -18,34 +19,34 @@ CalcIC called to correct initial predator concentrations
 1.00e-03   1.0318e+01   1.0827e+01   |  33  4   9.7404e-05
            1.0319e+05   1.0822e+05   |
 
-1.00e-02   1.6189e+02   1.9735e+02   | 123  3   1.9481e-04
+1.00e-02   1.6189e+02   1.9735e+02   | 119  4   1.7533e-04
            1.6189e+06   1.9735e+06   |
 
-1.00e-01   2.4019e+02   2.7072e+02   | 197  1   4.0396e-02
+1.00e-01   2.4019e+02   2.7072e+02   | 190  1   3.8524e-02
            2.4019e+06   2.7072e+06   |
 
-4.00e-01   2.4019e+02   2.7072e+02   | 200  1   3.2316e-01
+4.00e-01   2.4019e+02   2.7072e+02   | 193  1   3.0819e-01
            2.4019e+06   2.7072e+06   |
 
-7.00e-01   2.4019e+02   2.7072e+02   | 200  1   3.2316e-01
+7.00e-01   2.4019e+02   2.7072e+02   | 194  1   6.1639e-01
            2.4019e+06   2.7072e+06   |
 
-1.00e+00   2.4019e+02   2.7072e+02   | 201  1   6.4633e-01
+1.00e+00   2.4019e+02   2.7072e+02   | 194  1   6.1639e-01
            2.4019e+06   2.7072e+06   |
 
 -----------------------------------------------------------
 
 Final statistics: 
 
-Number of steps                    = 201
-Number of residual evaluations     = 1110
-Number of nonlinear iterations     = 245
+Number of steps                    = 194
+Number of residual evaluations     = 1057
+Number of nonlinear iterations     = 239
 Number of error test failures      = 0
 Number of nonlinear conv. failures = 0
 
-Number of linear iterations        = 863
+Number of linear iterations        = 816
 Number of linear conv. failures    = 0
 
-Number of preconditioner setups    = 26
-Number of preconditioner solves    = 1110
-Number of local residual evals.    = 1092
+Number of preconditioner setups    = 25
+Number of preconditioner solves    = 1057
+Number of local residual evals.    = 1050
diff --git a/examples/idas/parallel/idasFoodWeb_kry_p.c b/examples/idas/parallel/idasFoodWeb_kry_p.c
index b8a962e..fa9efc4 100644
--- a/examples/idas/parallel/idasFoodWeb_kry_p.c
+++ b/examples/idas/parallel/idasFoodWeb_kry_p.c
@@ -1,19 +1,14 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *      Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDA: Food web, parallel, GMRES, user
  * preconditioner.
  *
- * This example program for IDAS uses IDASPGMR as the linear solver.
+ * This example program for IDAS uses SUNSPGMR as the linear solver.
  * It is written for a parallel computer system and uses a
  * block-diagonal preconditioner (setup and solve routines) for the
- * IDASPGMR package. It was originally run on a Sun SPARC cluster
- * and used MPICH.
+ * IDASPILS interface.
  *
  * The mathematical problem solved in this example is a DAE system
  * that arises from a system of partial differential equations after
@@ -72,9 +67,9 @@
  * submeshes, processor by processor, with an MXSUB by MYSUB mesh
  * on each of NPEX * NPEY processors.
  *
- * The DAE system is solved by IDAS using the IDASPGMR linear
+ * The DAE system is solved by IDAS using the SUNSPGMR linear
  * solver, which uses the preconditioned GMRES iterative method to
- * solve linear systems. The precondtioner supplied to IDASPGMR is
+ * solve linear systems. The precondtioner supplied to SUNSPGMR is
  * the block-diagonal part of the Jacobian with ns by ns blocks
  * arising from the reaction terms only. Output is printed at
  * t = 0, .001, .01, .1, .4, .7, 1.
@@ -102,7 +97,8 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_dense.h>
 #include <sundials/sundials_types.h>
@@ -157,7 +153,7 @@
 /* Type: UserData.  Contains problem constants, preconditioner data, etc. */
 
 typedef struct {
-  long int ns;
+  sunindextype ns;
   int np, thispe, npes, ixsub, jysub, npex, npey;
   int mxsub, mysub, nsmxsub, nsmxsub2;
   realtype dx, dy, **acoef;
@@ -166,7 +162,7 @@ typedef struct {
   MPI_Comm comm;
   N_Vector rates;
   realtype **PP[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
   N_Vector ewt;
   void *ida_mem;
 } *UserData;
@@ -178,16 +174,12 @@ static int resweb(realtype time,
                   N_Vector cc, N_Vector cp, N_Vector resval, 
                   void *user_data);
 
-static int Precondbd(realtype tt, 
-                     N_Vector cc, N_Vector cp, N_Vector rr, 
-                     realtype cj, void *user_data,
-                     N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
+static int Precondbd(realtype tt, N_Vector cc, N_Vector cp, N_Vector rr, 
+                     realtype cj, void *user_data);
 
-static int PSolvebd(realtype tt, 
-                    N_Vector cc, N_Vector cp, N_Vector rr, 
-                    N_Vector rvec, N_Vector zvec,
-                    realtype cj, realtype delta, void *user_data, 
-                    N_Vector tempv);
+static int PSolvebd(realtype tt, N_Vector cc, N_Vector cp, 
+                    N_Vector rr, N_Vector rvec, N_Vector zvec,
+                    realtype cj, realtype delta, void *user_data);
 
 static int rescomm(N_Vector cc, N_Vector cp, void *user_data);
 
@@ -212,8 +204,8 @@ static realtype dotprod(int size, realtype *x1, realtype *x2);
 
 /* Prototypes for private Helper Functions. */
 
-static UserData AllocUserData(MPI_Comm comm, long int local_N, 
-                              long int SystemSize);
+static UserData AllocUserData(MPI_Comm comm, sunindextype local_N, 
+                              sunindextype SystemSize);
 
 static void InitUserData(UserData webdata, int thispe, int npes, 
                          MPI_Comm comm);
@@ -223,13 +215,13 @@ static void FreeUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                N_Vector scrtch, UserData webdata);
 
-static void PrintHeader(long int SystemSize, int maxl, 
+static void PrintHeader(sunindextype SystemSize, int maxl, 
                         realtype rtol, realtype atol);
 
-static void PrintOutput(void *mem, N_Vector cc, realtype time,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype time,
                         UserData webdata, MPI_Comm comm);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -242,16 +234,18 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData webdata;
-  long int SystemSize, local_N;
+  sunindextype SystemSize, local_N;
   realtype rtol, atol, t0, tout, tret;
   N_Vector cc, cp, res, id;
   int thispe, npes, maxl, iout, flag;
 
   cc = cp = res = id = NULL;
   webdata = NULL;
-  mem = NULL;
+  LS = NULL;
+  ida_mem = NULL;
 
   /* Set communicator, and get processor number and total number of PE's. */
 
@@ -309,56 +303,62 @@ int main(int argc, char *argv[])
   /* Call IDACreate and IDAMalloc to initialize IDA.
      A pointer to IDA problem memory is returned and stored in idamem. */
 
-  mem = IDACreate();
-  if (check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if (check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDASetUserData(mem, webdata);
+  flag = IDASetUserData(ida_mem, webdata);
   if (check_flag(&flag, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDASetId(mem, id);
+  flag = IDASetId(ida_mem, id);
   if (check_flag(&flag, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDAInit(mem, resweb, t0, cc, cp);
+  flag = IDAInit(ida_mem, resweb, t0, cc, cp);
   if (check_flag(&flag, "IDAinit", 1, thispe)) MPI_Abort(comm, 1);
 
-  flag = IDASStolerances(mem, rtol, atol);
+  flag = IDASStolerances(ida_mem, rtol, atol);
   if (check_flag(&flag, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  webdata->ida_mem = mem;
+  webdata->ida_mem = ida_mem;
 
-  /* Call IDASpgmr to specify the IDA linear solver IDASPGMR and specify
-     the preconditioner routines supplied (Precondbd and PSolvebd).
-     maxl (max. Krylov subspace dim.) is set to 16. */
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the linear solver 
+     to IDA, and specify the supplied [left] preconditioner routines 
+     (Precondbd & PSolvebd).  maxl (Krylov subspace dim.) is set to 16. */
 
   maxl = 16;
-  flag = IDASpgmr(mem, maxl);
-  if (check_flag(&flag, "IDASpgmr", 1, thispe)) 
+  LS = SUNSPGMR(cc, PREC_LEFT, maxl);
+  if (check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  flag = SUNSPGMRSetMaxRestarts(LS, 5);  /* IDA recommends allowing up to 5 restarts */
+  if(check_flag(&flag, "SUNSPGMRSetMaxRestarts", 1, thispe)) MPI_Abort(comm, 1);
+
+  flag = IDASpilsSetLinearSolver(ida_mem, LS);
+  if (check_flag(&flag, "IDASpilsSetLinearSolver", 1, thispe)) 
     MPI_Abort(comm, 1);
 
-  flag = IDASpilsSetPreconditioner(mem, Precondbd, PSolvebd);
+  flag = IDASpilsSetPreconditioner(ida_mem, Precondbd, PSolvebd);
   if (check_flag(&flag, "IDASpilsSetPreconditioner", 1, thispe)) 
     MPI_Abort(comm, 1);
   
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
   tout = RCONST(0.001);
-  flag = IDACalcIC(mem, IDA_YA_YDP_INIT, tout);
+  flag = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, tout);
   if (check_flag(&flag, "IDACalcIC", 1, thispe)) 
     MPI_Abort(comm, 1);
 
   /* On PE 0, print heading, basic parameters, initial values. */
 
   if (thispe == 0) PrintHeader(SystemSize, maxl, rtol, atol);
-  PrintOutput(mem, cc, t0, webdata, comm);
+  PrintOutput(ida_mem, cc, t0, webdata, comm);
   
   /* Loop over iout, call IDASolve (normal mode), print selected output. */
 
   for (iout = 1; iout <= NOUT; iout++) {
     
-    flag = IDASolve(mem, tout, &tret, cc, cp, IDA_NORMAL);
+    flag = IDASolve(ida_mem, tout, &tret, cc, cp, IDA_NORMAL);
     if (check_flag(&flag, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(mem, cc, tret, webdata, comm);
+    PrintOutput(ida_mem, cc, tret, webdata, comm);
     
     if (iout < 3) tout *= TMULT; 
     else          tout += TADD;
@@ -366,7 +366,7 @@ int main(int argc, char *argv[])
   }
   
   /* On PE 0, print final set of statistics. */
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
 
   /* Free memory. */
 
@@ -374,7 +374,8 @@ int main(int argc, char *argv[])
   N_VDestroy_Parallel(cp);
   N_VDestroy_Parallel(id);
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   FreeUserData(webdata);
 
@@ -394,7 +395,7 @@ int main(int argc, char *argv[])
  * AllocUserData: Allocate memory for data structure of type UserData.   
  */
 
-static UserData AllocUserData(MPI_Comm comm, long int local_N, long int SystemSize)
+static UserData AllocUserData(MPI_Comm comm, sunindextype local_N, sunindextype SystemSize)
 {
   int ix, jy;
   UserData webdata;
@@ -406,7 +407,7 @@ static UserData AllocUserData(MPI_Comm comm, long int local_N, long int SystemSi
   for (ix = 0; ix < MXSUB; ix++) {
     for (jy = 0; jy < MYSUB; jy++) {
       (webdata->PP)[ix][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (webdata->pivot)[ix][jy] = newLintArray(NUM_SPECIES);
+      (webdata->pivot)[ix][jy] = newIndexArray(NUM_SPECIES);
     }
   }
   
@@ -557,13 +558,13 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int SystemSize, int maxl, 
+static void PrintHeader(sunindextype SystemSize, int maxl, 
                         realtype rtol, realtype atol)
 {
   printf("\nidasFoodWeb_kry_p: Predator-prey DAE parallel example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
   printf("     Mesh dimensions: %d x %d", MX, MY);
-  printf("     Total system size: %ld\n",SystemSize);
+  printf("     Total system size: %ld\n", (long int) SystemSize);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("     Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -573,7 +574,7 @@ static void PrintHeader(long int SystemSize, int maxl,
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDASPGMR     Max. Krylov dimension maxl: %d\n", maxl);
+  printf("Linear solver: SUNSPGMR     Max. Krylov dimension maxl: %d\n", maxl);
   printf("Preconditioner: block diagonal, block size ns,"); 
   printf(" via difference quotients\n");
   printf("CalcIC called to correct initial predator concentrations \n\n");
@@ -591,7 +592,7 @@ static void PrintHeader(long int SystemSize, int maxl,
  * (NOTE: This routine is specific to the case NUM_SPECIES = 2.)         
  */
 
-static void PrintOutput(void *mem, N_Vector cc, realtype tt,
+static void PrintOutput(void *ida_mem, N_Vector cc, realtype tt,
                         UserData webdata, MPI_Comm comm)
 {
   MPI_Status status;
@@ -619,11 +620,11 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
     if (npelast != 0)
       MPI_Recv(&clast[0], 2, PVEC_REAL_MPI_TYPE, npelast, 0, comm, &status);
     
-    flag = IDAGetLastOrder(mem, &kused);
+    flag = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&flag, "IDAGetLastOrder", 1, thispe);
-    flag = IDAGetNumSteps(mem, &nst);
+    flag = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&flag, "IDAGetNumSteps", 1, thispe);
-    flag = IDAGetLastStep(mem, &hused);
+    flag = IDAGetLastStep(ida_mem, &hused);
     check_flag(&flag, "IDAGetLastStep", 1, thispe);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -651,31 +652,31 @@ static void PrintOutput(void *mem, N_Vector cc, realtype tt,
  * PrintFinalStats: Print final run data contained in iopt.              
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int nst, nre, nreLS, netf, ncfn, nni, ncfl, nli, npe, nps;
   int flag;
 
-  flag = IDAGetNumSteps(mem, &nst);
+  flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1, 0);
-  flag = IDAGetNumResEvals(mem, &nre);
+  flag = IDAGetNumResEvals(ida_mem, &nre);
   check_flag(&flag, "IDAGetNumResEvals", 1, 0);
-  flag = IDAGetNumErrTestFails(mem, &netf);
+  flag = IDAGetNumErrTestFails(ida_mem, &netf);
   check_flag(&flag, "IDAGetNumErrTestFails", 1, 0);
-  flag = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
+  flag = IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
   check_flag(&flag, "IDAGetNumNonlinSolvConvFails", 1, 0);
-  flag = IDAGetNumNonlinSolvIters(mem, &nni);
+  flag = IDAGetNumNonlinSolvIters(ida_mem, &nni);
   check_flag(&flag, "IDAGetNumNonlinSolvIters", 1, 0);
 
-  flag = IDASpilsGetNumConvFails(mem, &ncfl);
+  flag = IDASpilsGetNumConvFails(ida_mem, &ncfl);
   check_flag(&flag, "IDASpilsGetNumConvFails", 1, 0);
-  flag = IDASpilsGetNumLinIters(mem, &nli);
+  flag = IDASpilsGetNumLinIters(ida_mem, &nli);
   check_flag(&flag, "IDASpilsGetNumLinIters", 1, 0);
-  flag = IDASpilsGetNumPrecEvals(mem, &npe);
+  flag = IDASpilsGetNumPrecEvals(ida_mem, &npe);
   check_flag(&flag, "IDASpilsGetNumPrecEvals", 1, 0);
-  flag = IDASpilsGetNumPrecSolves(mem, &nps);
+  flag = IDASpilsGetNumPrecSolves(ida_mem, &nps);
   check_flag(&flag, "IDASpilsGetNumPrecSolves", 1, 0);
-  flag = IDASpilsGetNumResEvals(mem, &nreLS);
+  flag = IDASpilsGetNumResEvals(ida_mem, &nreLS);
   check_flag(&flag, "IDASpilsGetNumResEvals", 1, 0);
 
   printf("-----------------------------------------------------------\n");
@@ -1122,10 +1123,8 @@ static realtype dotprod(int size, realtype *x1, realtype *x2)
  * Each block is LU-factored, for later solution of the linear systems.  
  */
 
-static int Precondbd(realtype tt, N_Vector cc,
-                     N_Vector cp, N_Vector rr, 
-                     realtype cj, void *user_data,
-                     N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+static int Precondbd(realtype tt, N_Vector cc, N_Vector cp, 
+                     N_Vector rr, realtype cj, void *user_data)
 {
   int flag, thispe;
   realtype uround;
@@ -1133,7 +1132,7 @@ static int Precondbd(realtype tt, N_Vector cc,
   realtype inc, sqru, fac, perturb_rates[NUM_SPECIES];
   int is, js, ix, jy, ret;
   UserData webdata;
-  void *mem;
+  void *ida_mem;
   N_Vector ewt;
   realtype hh;
 
@@ -1142,11 +1141,11 @@ static int Precondbd(realtype tt, N_Vector cc,
   sqru = SUNRsqrt(uround);
   thispe = webdata->thispe;
 
-  mem = webdata->ida_mem;
+  ida_mem = webdata->ida_mem;
   ewt = webdata->ewt;
-  flag = IDAGetErrWeights(mem, ewt);
+  flag = IDAGetErrWeights(ida_mem, ewt);
   check_flag(&flag, "IDAGetErrWeights", 1, thispe);
-  flag = IDAGetCurrentStep(mem, &hh);
+  flag = IDAGetCurrentStep(ida_mem, &hh);
   check_flag(&flag, "IDAGetCurrentStep", 1, thispe);
 
   for (jy = 0; jy < mysub; jy++) {
@@ -1197,14 +1196,12 @@ static int Precondbd(realtype tt, N_Vector cc,
  * preconditioner PP, to compute the solution of PP * zvec = rvec.       
  */
 
-static int PSolvebd(realtype tt, N_Vector cc,
-                 N_Vector cp, N_Vector rr, 
-                 N_Vector rvec, N_Vector zvec,
-                 realtype cj, realtype delta,
-                 void *user_data, N_Vector tempv)
+static int PSolvebd(realtype tt, N_Vector cc, N_Vector cp, 
+                    N_Vector rr, N_Vector rvec, N_Vector zvec,
+                    realtype cj, realtype delta, void *user_data)
 {
   realtype **Pxy, *zxy;
-  long int *pivot, ix, jy;
+  sunindextype *pivot, ix, jy;
   UserData webdata;
 
   webdata = (UserData)user_data;
diff --git a/examples/idas/parallel/idasFoodWeb_kry_p.out b/examples/idas/parallel/idasFoodWeb_kry_p.out
index 85cfd22..42ffbb0 100644
--- a/examples/idas/parallel/idasFoodWeb_kry_p.out
+++ b/examples/idas/parallel/idasFoodWeb_kry_p.out
@@ -1,9 +1,10 @@
+
 idasFoodWeb_kry_p: Predator-prey DAE parallel example problem for IDA 
 
 Number of species ns: 2     Mesh dimensions: 20 x 20     Total system size: 800
 Subgrid dimensions: 10 x 10     Processor array: 2 x 2
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDASPGMR     Max. Krylov dimension maxl: 16
+Linear solver: SUNSPGMR     Max. Krylov dimension maxl: 16
 Preconditioner: block diagonal, block size ns, via difference quotients
 CalcIC called to correct initial predator concentrations 
 
@@ -20,30 +21,30 @@ CalcIC called to correct initial predator concentrations
 1.00e-02   1.6189e+02   1.9735e+02   |  86  4   1.7533e-04
            1.6189e+06   1.9735e+06   |
 
-1.00e-01   2.4019e+02   2.7072e+02   | 162  1   4.0396e-02
+1.00e-01   2.4019e+02   2.7072e+02   | 163  1   4.0396e-02
            2.4019e+06   2.7072e+06   |
 
-4.00e-01   2.4019e+02   2.7072e+02   | 165  1   3.2316e-01
+4.00e-01   2.4019e+02   2.7072e+02   | 166  1   3.2316e-01
            2.4019e+06   2.7072e+06   |
 
-7.00e-01   2.4019e+02   2.7072e+02   | 166  1   6.4633e-01
+7.00e-01   2.4019e+02   2.7072e+02   | 167  1   6.4633e-01
            2.4019e+06   2.7072e+06   |
 
-1.00e+00   2.4019e+02   2.7072e+02   | 166  1   6.4633e-01
+1.00e+00   2.4019e+02   2.7072e+02   | 167  1   6.4633e-01
            2.4019e+06   2.7072e+06   |
 
 -----------------------------------------------------------
 
 Final statistics: 
 
-Number of steps                    = 166
-Number of residual evaluations     = 1257
+Number of steps                    = 167
+Number of residual evaluations     = 1247
 Number of nonlinear iterations     = 206
 Number of error test failures      = 0
 Number of nonlinear conv. failures = 0
 
-Number of linear iterations        = 1049
+Number of linear iterations        = 1039
 Number of linear conv. failures    = 0
 
 Number of preconditioner setups    = 25
-Number of preconditioner solves    = 1257
+Number of preconditioner solves    = 1247
diff --git a/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c
index 0ee8188..1716258 100644
--- a/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c
+++ b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.c
@@ -1,9 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDAS: FSA for 2D heat equation, parallel,
  * GMRES, IDABBDPRE.
@@ -11,7 +9,7 @@
  * This example solves a discretized 2D heat equation problem and
  * performs forward sensitivity analysis with respect to the 
  * diffusion coefficients. This version uses the Krylov solver
- * IDASpgmr and BBD preconditioning.
+ * SUNSPGMR and BBD preconditioning.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = p1 * d^2u/dx^2 + p2 * d^2u/dy^2
@@ -28,7 +26,7 @@
  * processors.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR in conjunction with the preconditioner module IDABBDPRE.
+ * SUNSPGMR in conjunction with the preconditioner module IDABBDPRE.
  * The preconditioner uses a tridiagonal approximation
  * (half-bandwidths = 1). The constraints u >= 0 are posed for all
  * components. Local error testing on the boundary values is
@@ -42,8 +40,9 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
 #include <idas/idas_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_math.h>
 
@@ -70,7 +69,7 @@
 typedef struct {  
   realtype p[2];
   int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
-  long int n_local;
+  sunindextype n_local;
   realtype dx, dy, coeffx, coeffy, coeffxy;
   realtype uext[(MXSUB+2)*(MYSUB+2)];
   MPI_Comm comm;
@@ -78,13 +77,11 @@ typedef struct {
 
 /* Prototypes of user-supplied and supporting functions */
 
-static int heatres(realtype tres, 
-                   N_Vector uu, N_Vector up, N_Vector res, 
-                   void *user_data);
-static int rescomm(long int Nlocal, realtype tt, 
-                   N_Vector uu, N_Vector up, 
-                   void *user_data);
-static int reslocal(long int Nlocal, realtype tres, 
+static int heatres(realtype tres, N_Vector uu, N_Vector up,
+                   N_Vector res, void *user_data);
+static int rescomm(sunindextype Nlocal, realtype tt, 
+                   N_Vector uu, N_Vector up, void *user_data);
+static int reslocal(sunindextype Nlocal, realtype tres, 
                     N_Vector uu, N_Vector up, N_Vector res,  
                     void *user_data);
 static int BSend(MPI_Comm comm, int thispe, int ixsub,
@@ -103,15 +100,16 @@ static int InitUserData(int thispe, MPI_Comm comm, UserData data);
 static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
                              N_Vector res, UserData data);
 
-static void PrintHeader(int Neq, realtype rtol, realtype atol,
-                        int mudq, int mukeep,
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol,
+                        sunindextype mudq, sunindextype mukeep,
                         booleantype sensi, int sensi_meth, int err_con);
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu, 
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu, 
                         booleantype sensi, N_Vector *uuS);
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static void ProcessArgs(int argc, char *argv[], int my_pe,
-                        booleantype *sensi, int *sensi_meth, booleantype *err_con);
+                        booleantype *sensi, int *sensi_meth,
+                        booleantype *err_con);
 static void WrongArgs(int my_pe, char *name);
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -124,10 +122,11 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
   int thispe, iout, ier, npes;
-  long int Neq, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype Neq, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, t1, tout, tret;
   N_Vector uu, up, constraints, id, res;
 
@@ -137,7 +136,8 @@ int main(int argc, char *argv[])
   booleantype sensi, err_con;
   int sensi_meth;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
   uuS = upS = NULL;
@@ -209,34 +209,40 @@ int main(int argc, char *argv[])
      - exclude algebraic variables from error test
      - specify additional constraints on solution components */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetUserData(mem, data);
+  ier = IDASetUserData(ida_mem, data);
   if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetSuppressAlg(mem, TRUE);
+  ier = IDASetSuppressAlg(ida_mem, SUNTRUE);
   if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetId(mem, id);
+  ier = IDASetId(ida_mem, id);
   if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetConstraints(mem, constraints);
+  ier = IDASetConstraints(ida_mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
   N_VDestroy_Parallel(constraints);
 
-  ier = IDAInit(mem, heatres, t0, uu, up);
+  ier = IDAInit(ida_mem, heatres, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Specify state tolerances (scalar relative and absolute tolerances) */
 
-  ier = IDASStolerances(mem, rtol, atol);
+  ier = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the linear solver. */
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the linear solver. */
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);  /* IDA recommends left-preconditioning only;
+                                       0 indicates to use default maxl value */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  ier = SUNSPGMRSetMaxRestarts(LS, 5);  /* IDA recommends allowing up to 5 restarts */
+  if(check_flag(&ier, "SUNSPGMRSetMaxRestarts", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASpgmr(mem, 12);
-  if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  ier = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
   
   /* Call IDABBDPrecInit to initialize BBD preconditioner. */
 
@@ -244,7 +250,7 @@ int main(int argc, char *argv[])
   mldq = MXSUB;
   mukeep = 1;
   mlkeep = 1;
-  ier = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  ier = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                        ZERO, reslocal, NULL);
   if(check_flag(&ier, "IDABBDPrecInit", 1, thispe)) MPI_Abort(comm, 1);
 
@@ -278,34 +284,34 @@ int main(int argc, char *argv[])
     /* Initialize FSA using the default internal sensitivity residual function
        (Note that this requires specifying the problem parameters -- see below) */
 
-    ier = IDASensInit(mem, NS, sensi_meth, NULL, uuS, upS);
+    ier = IDASensInit(ida_mem, NS, sensi_meth, NULL, uuS, upS);
     if(check_flag(&ier, "IDASensInit", 1, thispe)) MPI_Abort(comm, 1);
 
     /* Indicate the use of internally estimated tolerances for the sensitivity
        variables (based on the tolerances provided for the states and the 
        pbar values) */
 
-    ier = IDASensEEtolerances(mem);
+    ier = IDASensEEtolerances(ida_mem);
     if(check_flag(&ier, "IDASensEEtolerances", 1, thispe)) MPI_Abort(comm, 1);
 
     /* Specify whether the sensitivity variables are included in the error
        test or not */
 
-    ier = IDASetSensErrCon(mem, err_con);
+    ier = IDASetSensErrCon(ida_mem, err_con);
     if(check_flag(&ier, "IDASetSensErrCon", 1, thispe)) MPI_Abort(comm, 1);
 
     /* Specify the problem parameters and their order of magnitude
        (Note that we do not specify the index array plist and therefore
        IDAS will compute sensitivities w.r.t. the first NS parameters) */
 
-    ier = IDASetSensParams(mem, data->p, pbar, NULL);
+    ier = IDASetSensParams(ida_mem, data->p, pbar, NULL);
     if(check_flag(&ier, "IDASetSensParams", 1, thispe)) MPI_Abort(comm, 1);
 
     /* Compute consistent initial conditions (Note that this is required
        only if performing SA since uu and up already contain consistent 
        initial conditions for the states) */
   
-    ier = IDACalcIC(mem, IDA_YA_YDP_INIT, t1);
+    ier = IDACalcIC(ida_mem, IDA_YA_YDP_INIT, t1);
     if(check_flag(&ier, "IDACalcIC", 1, thispe)) MPI_Abort(comm, 1);
 
   }
@@ -318,24 +324,25 @@ int main(int argc, char *argv[])
   /* Loop over tout, call IDASolve, print output. */
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) { 
     
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
     if (sensi) {
-      ier = IDAGetSens(mem, &tret, uuS);
+      ier = IDAGetSens(ida_mem, &tret, uuS);
       if(check_flag(&ier, "IDAGetSens", 1, thispe)) MPI_Abort(comm, 1);
     }
 
-    PrintOutput(thispe, mem, tret, uu, sensi, uuS);
+    PrintOutput(thispe, ida_mem, tret, uu, sensi, uuS);
     
   }
 
   /* Print final statistics */
 
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
   
   /* Free Memory */
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
   free(data);
   N_VDestroy_Parallel(id);
   N_VDestroy_Parallel(res);
@@ -374,7 +381,7 @@ static int heatres(realtype tres, N_Vector uu, N_Vector up,
 {
   int retval;
   UserData data;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   data = (UserData) user_data;
   
@@ -395,7 +402,7 @@ static int heatres(realtype tres, N_Vector uu, N_Vector up,
  * communication of data in u needed to calculate G.                 
  */
 
-static int rescomm(long int Nlocal, realtype tt, 
+static int rescomm(sunindextype Nlocal, realtype tt, 
                    N_Vector uu, N_Vector up, void *user_data)
 {
   UserData data;
@@ -432,7 +439,7 @@ static int rescomm(long int Nlocal, realtype tt,
  *  has already been done, and that this data is in the work array uext.  
  */
 
-static int reslocal(long int Nlocal, realtype tres, 
+static int reslocal(sunindextype Nlocal, realtype tres, 
                     N_Vector uu, N_Vector up, N_Vector res,  
                     void *user_data)
 {
@@ -747,15 +754,15 @@ static int SetInitialProfile(N_Vector uu, N_Vector up,  N_Vector id,
  * and table heading
  */
 
-static void PrintHeader(int Neq, realtype rtol, realtype atol,
-                        int mudq, int mukeep,
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol,
+                        sunindextype mudq, sunindextype mukeep,
                         booleantype sensi, int sensi_meth, int err_con)
 {
     printf("\nidasHeat2D_FSA_kry_bbd_p: Heat equation, parallel example problem for IDA\n");
     printf("                     Discretized heat equation on 2D unit square.\n");
     printf("                     Zero boundary conditions, polynomial initial conditions.\n");
     printf("                     Mesh dimensions: %d x %d ; ", MX, MY);
-    printf("    Total system size: %d\n\n", Neq);
+    printf("    Total system size: %ld\n\n", (long int) Neq);
 
     printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
     printf("         Processor array: %d x %d\n", NPEX, NPEY);
@@ -767,12 +774,12 @@ static void PrintHeader(int Neq, realtype rtol, realtype atol,
     printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
     printf("Constraints set to force all solution components >= 0. \n");
-    printf("SUPPRESSALG = TRUE to suppress local error testing on");
+    printf("SUPPRESSALG = SUNTRUE to suppress local error testing on");
     printf(" all boundary components. \n");
-    printf("Linear solver: IDASPGMR.    ");
+    printf("Linear solver: SUNSPGMR.    ");
     printf("Preconditioner: IDABBDPRE - Banded-block-diagonal.\n"); 
-    printf("Difference quotient half-bandwidths = %d",mudq);
-    printf("Retained matrix half-bandwidths = %d \n\n",mukeep);
+    printf("Difference quotient half-bandwidths = %ld",(long int) mudq);
+    printf("Retained matrix half-bandwidths = %ld \n\n",(long int) mukeep);
 
     if (sensi) {
       printf("Sensitivity: YES ");
@@ -801,7 +808,7 @@ static void PrintHeader(int Neq, realtype rtol, realtype atol,
 /*
  * Print integrator statistics and max-norm of solution
  */
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu, 
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu, 
                         booleantype sensi, N_Vector *uuS)
 {
   realtype umax, hused;
@@ -812,25 +819,25 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu,
 
   if (id == 0) {
 
-    ier = IDAGetLastOrder(mem, &kused);
+    ier = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&ier, "IDAGetLastOrder", 1, id);
-    ier = IDAGetNumSteps(mem, &nst);
+    ier = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&ier, "IDAGetNumSteps", 1, id);
-    ier = IDAGetNumNonlinSolvIters(mem, &nni);
+    ier = IDAGetNumNonlinSolvIters(ida_mem, &nni);
     check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
-    ier = IDAGetNumResEvals(mem, &nre);
+    ier = IDAGetNumResEvals(ida_mem, &nre);
     check_flag(&ier, "IDAGetNumResEvals", 1, id);
-    ier = IDAGetLastStep(mem, &hused);
+    ier = IDAGetLastStep(ida_mem, &hused);
     check_flag(&ier, "IDAGetLastStep", 1, id);
-    ier = IDASpilsGetNumLinIters(mem, &nli);
+    ier = IDASpilsGetNumLinIters(ida_mem, &nli);
     check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
-    ier = IDASpilsGetNumResEvals(mem, &nreLS);
+    ier = IDASpilsGetNumResEvals(ida_mem, &nreLS);
     check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
-    ier = IDABBDPrecGetNumGfnEvals(mem, &nge);
+    ier = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
     check_flag(&ier, "IDABBDPrecGetNumGfnEvals", 1, id);
-    ier = IDASpilsGetNumPrecEvals(mem, &npe);
+    ier = IDASpilsGetNumPrecEvals(ida_mem, &npe);
     check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
-    ier = IDASpilsGetNumPrecSolves(mem, &nps);
+    ier = IDASpilsGetNumPrecSolves(ida_mem, &nps);
     check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -868,13 +875,13 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu,
  * Print some final integrator statistics
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int netf, ncfn, ncfl;
 
-  IDAGetNumErrTestFails(mem, &netf);
-  IDAGetNumNonlinSolvConvFails(mem, &ncfn);
-  IDASpilsGetNumConvFails(mem, &ncfl);
+  IDAGetNumErrTestFails(ida_mem, &netf);
+  IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
+  IDASpilsGetNumConvFails(ida_mem, &ncfl);
 
   printf("\nError test failures            = %ld\n", netf);
   printf("Nonlinear convergence failures = %ld\n", ncfn);
@@ -888,16 +895,16 @@ static void PrintFinalStats(void *mem)
 static void ProcessArgs(int argc, char *argv[], int my_pe,
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(my_pe, argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(my_pe, argv[0]);
   
@@ -914,9 +921,9 @@ static void ProcessArgs(int argc, char *argv[], int my_pe,
       WrongArgs(my_pe, argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(my_pe, argv[0]);
   }
diff --git a/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.out b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.out
deleted file mode 100644
index d2038ae..0000000
--- a/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p.out
+++ /dev/null
@@ -1,57 +0,0 @@
-idasHeat2D_FSA_kry_bbd_p: Heat equation, parallel example problem for IDA
-                     Discretized heat equation on 2D unit square.
-                     Zero boundary conditions, polynomial initial conditions.
-                     Mesh dimensions: 10 x 10 ;     Total system size: 100
- 
-Subgrid dimensions: 5 x 5         Processor array: 2 x 2
-Tolerance parameters:  rtol = 0   atol = 0.001
-Constraints set to force all solution components >= 0.
-SUPPRESSALG = TRUE to suppress local error testing on all boundary components.
-Linear solver: IDASPGMR.    Preconditioner: IDABBDPRE - Banded-block-diagonal.
-Difference quotient half-bandwidths = 5Retained matrix half-bandwidths = 1
- 
-Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
- 
-Output Summary: umax = max-norm of solution
-                       max-norm of sensitivity 1
-                       max-norm of sensitivity 2
- 
-  time     umax       k  nst  nni  nli   nre nreLS nge     h      npe nps
- .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
-  0.01   8.24107e-01  2   12   17   30    19   30  144  2.56e-03   12  87
-         7.20970e-02
-         7.20841e-02
-  0.02   6.88132e-01  3   15   22   43    24   43  144  5.12e-03   12 115
-         1.27103e-01
-         1.27071e-01
-  0.04   4.70895e-01  3   19   26   60    28   60  144  5.12e-03   12 144
-         1.81692e-01
-         1.81794e-01
-  0.08   2.16325e-01  3   23   31   95    33   95  156  1.02e-02   13 194
-         1.68436e-01
-         1.68462e-01
-  0.16   4.58960e-02  3   29   39  140    41  140  168  1.84e-02   14 263
-         7.02125e-02
-         7.03265e-02
-  0.32   2.29034e-03  3   36   47  200    49  200  180  3.69e-02   15 347
-         6.22596e-03
-         6.33303e-03
-  0.64   2.32389e-05  1   41   55  255    57  255  204  1.47e-01   17 426
-         7.82118e-05
-         8.20707e-05
-  1.28   5.39438e-19  1   43   59  269    61  269  228  5.90e-01   19 452
-         3.23841e-04
-         1.68342e-04
-  2.56   1.44292e-20  1   44   61  272    63  272  240  1.18e+00   20 461
-         7.70031e-05
-         1.35511e-04
-  5.12   3.10555e-20  1   46   64  277    66  277  264  4.72e+00   22 475
-         3.35209e-04
-         6.48901e-05
- 10.24   4.32423e-20  1   47   66  279    68  279  276  9.44e+00   23 483
-         7.13723e-05
-         5.93381e-05
- 
-Error test failures            = 0
-Nonlinear convergence failures = 2
-Linear convergence failures    = 0
diff --git a/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p_-sensi_stg_t.out b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p_-sensi_stg_t.out
new file mode 100644
index 0000000..3cad282
--- /dev/null
+++ b/examples/idas/parallel/idasHeat2D_FSA_kry_bbd_p_-sensi_stg_t.out
@@ -0,0 +1,58 @@
+
+idasHeat2D_FSA_kry_bbd_p: Heat equation, parallel example problem for IDA
+                     Discretized heat equation on 2D unit square.
+                     Zero boundary conditions, polynomial initial conditions.
+                     Mesh dimensions: 10 x 10 ;     Total system size: 100
+
+Subgrid dimensions: 5 x 5         Processor array: 2 x 2
+Tolerance parameters:  rtol = 0   atol = 0.001
+Constraints set to force all solution components >= 0. 
+SUPPRESSALG = SUNTRUE to suppress local error testing on all boundary components. 
+Linear solver: SUNSPGMR.    Preconditioner: IDABBDPRE - Banded-block-diagonal.
+Difference quotient half-bandwidths = 5Retained matrix half-bandwidths = 1 
+
+Sensitivity: YES ( STAGGERED + FULL ERROR CONTROL )
+
+Output Summary: umax = max-norm of solution
+                       max-norm of sensitivity 1
+                       max-norm of sensitivity 2
+
+  time     umax       k  nst  nni  nli   nre nreLS nge     h      npe nps
+ .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
+  0.01   8.24104e-01  2   13   15   23    18   23  120  2.56e-03   10  76
+         7.20931e-02
+         7.20846e-02
+  0.02   6.88120e-01  3   16   19   37    22   37  120  5.12e-03   10 102
+         1.27152e-01
+         1.27115e-01
+  0.04   4.70886e-01  3   20   23   53    26   53  120  5.12e-03   10 130
+         1.81624e-01
+         1.81694e-01
+  0.08   2.16374e-01  3   24   28   79    31   79  132  1.02e-02   11 171
+         1.68510e-01
+         1.68537e-01
+  0.16   4.51906e-02  4   30   37  119    40  119  144  1.84e-02   12 238
+         7.11926e-02
+         7.11497e-02
+  0.32   2.16763e-03  3   37   45  164    48  164  156  3.69e-02   13 307
+         6.21650e-03
+         6.23955e-03
+  0.64   2.97427e-19  1   43   54  207    57  207  168  7.37e-02   14 377
+         2.35214e-04
+         2.19576e-04
+  1.28   2.42843e-21  1   46   57  215    60  215  204  5.90e-01   17 398
+         1.44071e-04
+         2.18901e-04
+  2.56   9.80850e-21  1   47   58  218    61  218  216  1.18e+00   18 406
+         1.01140e-04
+         1.03448e-04
+  5.12   2.68730e-20  1   48   59  220    62  220  228  2.36e+00   19 413
+         2.74385e-04
+         1.21440e-04
+ 10.24   6.66396e-20  1   50   61  226    64  226  252  9.44e+00   21 427
+         2.38027e-04
+         1.89053e-04
+
+Error test failures            = 0
+Nonlinear convergence failures = 0
+Linear convergence failures    = 0
diff --git a/examples/idas/parallel/idasHeat2D_kry_bbd_p.c b/examples/idas/parallel/idasHeat2D_kry_bbd_p.c
index 66cdb60..a3e3389 100644
--- a/examples/idas/parallel/idasHeat2D_kry_bbd_p.c
+++ b/examples/idas/parallel/idasHeat2D_kry_bbd_p.c
@@ -1,16 +1,13 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *      Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, parallel, GMRES,
  * IDABBDPRE.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the Krylov solver IDASpgmr and BBD
+ * This version uses the Krylov solver SUNSPGMR and BBD
  * preconditioning.
  *
  * The DAE system solved is a spatial discretization of the PDE
@@ -27,7 +24,7 @@
  * processors.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR in conjunction with the preconditioner module IDABBDPRE.
+ * SUNSPGMR in conjunction with the preconditioner module IDABBDPRE.
  * The preconditioner uses a tridiagonal approximation
  * (half-bandwidths = 1). The constraints u >= 0 are posed for all
  * components. Local error testing on the boundary values is
@@ -40,8 +37,9 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
 #include <idas/idas_bbdpre.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
@@ -74,15 +72,13 @@ typedef struct {
 
 /* Prototypes of user-supplied and supporting functions */
 
-static int heatres(realtype tres, 
-                   N_Vector uu, N_Vector up, N_Vector res, 
-                   void *user_data);
+static int heatres(realtype tres, N_Vector uu, N_Vector up,
+                   N_Vector res, void *user_data);
 
-static int rescomm(long int Nlocal, realtype tt, 
-                   N_Vector uu, N_Vector up, 
-                   void *user_data);
+static int rescomm(sunindextype Nlocal, realtype tt, 
+                   N_Vector uu, N_Vector up, void *user_data);
 
-static int reslocal(long int Nlocal, realtype tres, 
+static int reslocal(sunindextype Nlocal, realtype tres, 
                     N_Vector uu, N_Vector up, N_Vector res,  
                     void *user_data);
 
@@ -105,13 +101,13 @@ static int InitUserData(int thispe, MPI_Comm comm, UserData data);
 static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
                              N_Vector res, UserData data);
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol);
 
 static void PrintCase(int case_number, int mudq, int mukeep);
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -124,14 +120,16 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
   int thispe, iout, ier, npes;
-  long int Neq, local_N, mudq, mldq, mukeep, mlkeep;
+  sunindextype Neq, local_N, mudq, mldq, mukeep, mlkeep;
   realtype rtol, atol, t0, t1, tout, tret;
   N_Vector uu, up, constraints, id, res;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
 
@@ -194,26 +192,26 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize solution */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetUserData(mem, data);
+  ier = IDASetUserData(ida_mem, data);
   if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetSuppressAlg(mem, TRUE);
+  ier = IDASetSuppressAlg(ida_mem, SUNTRUE);
   if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetId(mem, id);
+  ier = IDASetId(ida_mem, id);
   if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetConstraints(mem, constraints);
+  ier = IDASetConstraints(ida_mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
   N_VDestroy_Parallel(constraints);
 
-  ier = IDAInit(mem, heatres, t0, uu, up);
+  ier = IDAInit(ida_mem, heatres, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASStolerances(mem, rtol, atol);
+  ier = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
   mudq = MXSUB;
@@ -231,12 +229,19 @@ int main(int argc, char *argv[])
    * ----------------------------- 
    */
 
-  /* Call IDASpgmr to specify the linear solver. */
-  ier = IDASpgmr(mem, 0);
-  if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  /* Call SUNSPGMR and IDASpilsSetLinearSolver to specify the linear solver. */
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);  /* IDA recommends left-preconditioning only;
+                                       0 indicates to use default maxl value */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
+
+  ier = SUNSPGMRSetMaxRestarts(LS, 5);  /* IDA recommends allowing up to 5 restarts */
+  if(check_flag(&ier, "SUNSPGMRSetMaxRestarts", 1, thispe)) MPI_Abort(comm, 1);
+
+  ier = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
   
   /* Call IDABBDPrecInit to initialize BBD preconditioner. */
-  ier = IDABBDPrecInit(mem, local_N, mudq, mldq, mukeep, mlkeep, 
+  ier = IDABBDPrecInit(ida_mem, local_N, mudq, mldq, mukeep, mlkeep, 
                        ZERO, reslocal, NULL);
   if(check_flag(&ier, "IDABBDPrecAlloc", 1, thispe)) MPI_Abort(comm, 1);
 
@@ -246,15 +251,15 @@ int main(int argc, char *argv[])
   /* Loop over tout, call IDASolve, print output. */
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) { 
     
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(thispe, mem, tret, uu);
+    PrintOutput(thispe, ida_mem, tret, uu);
     
   }
 
   /* Print final statistics */
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
   
   /*
    * ----------------------------- 
@@ -269,11 +274,11 @@ int main(int argc, char *argv[])
   SetInitialProfile(uu, up, id, res, data);
 
   /* Call IDAReInit to re-initialize IDA. */
-  ier = IDAReInit(mem, t0, uu, up);
+  ier = IDAReInit(ida_mem, t0, uu, up);
   if(check_flag(&ier, "IDAReInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Call IDABBDPrecReInit to re-initialize BBD preconditioner. */
-  ier = IDABBDPrecReInit(mem, mudq, mldq, ZERO);
+  ier = IDABBDPrecReInit(ida_mem, mudq, mldq, ZERO);
   if(check_flag(&ier, "IDABBDPrecReInit", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Print output heading (on processor 0 only). */
@@ -282,18 +287,19 @@ int main(int argc, char *argv[])
   /* Loop over tout, call IDASolve, print output. */
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) { 
     
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(thispe, mem, tret, uu);
+    PrintOutput(thispe, ida_mem, tret, uu);
     
   }
   
   /* Print final statistics */
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
 
   /* Free Memory */
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
   free(data);
   N_VDestroy_Parallel(id);
   N_VDestroy_Parallel(res);
@@ -332,7 +338,7 @@ static int heatres(realtype tres, N_Vector uu, N_Vector up,
 {
   int retval;
   UserData data;
-  long int Nlocal;
+  sunindextype Nlocal;
   
   data = (UserData) user_data;
   
@@ -353,7 +359,7 @@ static int heatres(realtype tres, N_Vector uu, N_Vector up,
  * communication of data in u needed to calculate G.                 
  */
 
-static int rescomm(long int Nlocal, realtype tt, 
+static int rescomm(sunindextype Nlocal, realtype tt, 
                    N_Vector uu, N_Vector up, void *user_data)
 {
   UserData data;
@@ -390,7 +396,7 @@ static int rescomm(long int Nlocal, realtype tt,
  *  has already been done, and that this data is in the work array uext.  
  */
 
-static int reslocal(long int Nlocal, realtype tres, 
+static int reslocal(sunindextype Nlocal, realtype tres, 
                     N_Vector uu, N_Vector up, N_Vector res,  
                     void *user_data)
 {
@@ -697,14 +703,14 @@ static int SetInitialProfile(N_Vector uu, N_Vector up,  N_Vector id,
  * and table heading
  */
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol)
 {
     printf("idasHeat2D_kry_bbd_p: Heat equation, parallel example problem for IDA\n");
     printf("                  Discretized heat equation on 2D unit square.\n");
     printf("                  Zero boundary conditions,");
     printf(" polynomial initial conditions.\n");
     printf("                Mesh dimensions: %d x %d", MX, MY);
-    printf("        Total system size: %ld\n\n", Neq);
+    printf("        Total system size: %ld\n\n", (long int) Neq);
 
     printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
     printf("         Processor array: %d x %d\n", NPEX, NPEY);
@@ -716,9 +722,9 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
     printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
     printf("Constraints set to force all solution components >= 0. \n");
-    printf("SUPPRESSALG = TRUE to suppress local error testing on");
+    printf("SUPPRESSALG = SUNTRUE to suppress local error testing on");
     printf(" all boundary components. \n");
-    printf("Linear solver: IDASPGMR.    ");
+    printf("Linear solver: SUNSPGMR.    ");
     printf("Preconditioner: IDABBDPRE - Banded-block-diagonal.\n"); 
 
 }
@@ -743,7 +749,7 @@ static void PrintCase(int case_number, int mudq, int mukeep)
  * Print integrator statistics and max-norm of solution
  */
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu)
 {
   realtype umax, hused;
   int kused, ier;
@@ -753,25 +759,25 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
   
   if (id == 0) {
 
-    ier = IDAGetLastOrder(mem, &kused);
+    ier = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&ier, "IDAGetLastOrder", 1, id);
-    ier = IDAGetNumSteps(mem, &nst);
+    ier = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&ier, "IDAGetNumSteps", 1, id);
-    ier = IDAGetNumNonlinSolvIters(mem, &nni);
+    ier = IDAGetNumNonlinSolvIters(ida_mem, &nni);
     check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
-    ier = IDAGetNumResEvals(mem, &nre);
+    ier = IDAGetNumResEvals(ida_mem, &nre);
     check_flag(&ier, "IDAGetNumResEvals", 1, id);
-    ier = IDAGetLastStep(mem, &hused);
+    ier = IDAGetLastStep(ida_mem, &hused);
     check_flag(&ier, "IDAGetLastStep", 1, id);
-    ier = IDASpilsGetNumLinIters(mem, &nli);
+    ier = IDASpilsGetNumLinIters(ida_mem, &nli);
     check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
-    ier = IDASpilsGetNumResEvals(mem, &nreLS);
+    ier = IDASpilsGetNumResEvals(ida_mem, &nreLS);
     check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
-    ier = IDABBDPrecGetNumGfnEvals(mem, &nge);
+    ier = IDABBDPrecGetNumGfnEvals(ida_mem, &nge);
     check_flag(&ier, "IDABBDPrecGetNumGfnEvals", 1, id);
-    ier = IDASpilsGetNumPrecEvals(mem, &npe);
+    ier = IDASpilsGetNumPrecEvals(ida_mem, &npe);
     check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
-    ier = IDASpilsGetNumPrecSolves(mem, &nps);
+    ier = IDASpilsGetNumPrecSolves(ida_mem, &nps);
     check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -792,13 +798,13 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
  * Print some final integrator statistics
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int netf, ncfn, ncfl;
 
-  IDAGetNumErrTestFails(mem, &netf);
-  IDAGetNumNonlinSolvConvFails(mem, &ncfn);
-  IDASpilsGetNumConvFails(mem, &ncfl);
+  IDAGetNumErrTestFails(ida_mem, &netf);
+  IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
+  IDASpilsGetNumConvFails(ida_mem, &ncfl);
 
   printf("\nError test failures            = %ld\n", netf);
   printf("Nonlinear convergence failures = %ld\n", ncfn);
diff --git a/examples/idas/parallel/idasHeat2D_kry_bbd_p.out b/examples/idas/parallel/idasHeat2D_kry_bbd_p.out
index 8315b95..d45e2f2 100644
--- a/examples/idas/parallel/idasHeat2D_kry_bbd_p.out
+++ b/examples/idas/parallel/idasHeat2D_kry_bbd_p.out
@@ -1,13 +1,13 @@
 idasHeat2D_kry_bbd_p: Heat equation, parallel example problem for IDA
                   Discretized heat equation on 2D unit square.
                   Zero boundary conditions, polynomial initial conditions.
-                  Mesh dimensions: 10 x 10        Total system size: 100
+                Mesh dimensions: 10 x 10        Total system size: 100
 
 Subgrid dimensions: 5 x 5         Processor array: 2 x 2
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-SUPPRESSALG = TRUE to suppress local error testing on all boundary components. 
-Linear solver: IDASPGMR.    Preconditioner: IDABBDPRE - Banded-block-diagonal.
+SUPPRESSALG = SUNTRUE to suppress local error testing on all boundary components. 
+Linear solver: SUNSPGMR.    Preconditioner: IDABBDPRE - Banded-block-diagonal.
 
 
 Case 1. 
@@ -15,19 +15,19 @@ Case 1.
 
    Output Summary (umax = max-norm of solution) 
 
-  time     umax       k  nst  nni  nli   nre nreLS nge   h      npe nps
+  time     umax       k  nst  nni  nli   nre nreLS nge     h      npe nps
  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
   0.01   8.24107e-01  2   12   14    7    14    7   96  2.56e-03    8  21
   0.02   6.88124e-01  3   15   18   12    18   12   96  5.12e-03    8  30
   0.04   4.70754e-01  3   18   24   22    24   22  108  6.58e-03    9  46
   0.08   2.16600e-01  3   22   29   30    29   30  108  1.32e-02    9  59
   0.16   4.56595e-02  4   28   37   43    37   43  120  2.63e-02   10  80
-  0.32   2.10959e-03  4   35   45   59    45   59  120  2.37e-02   10 104
-  0.64   5.53681e-05  1   40   54   71    54   71  156  1.90e-01   13 125
-  1.28   1.55972e-19  1   42   56   71    56   71  180  7.58e-01   15 127
-  2.56   3.38647e-21  1   43   57   71    57   71  192  1.52e+00   16 128
-  5.12   8.60743e-21  1   44   58   71    58   71  204  3.03e+00   17 129
- 10.24   1.66301e-20  1   45   59   71    59   71  216  6.06e+00   18 130
+  0.32   2.10967e-03  4   35   45   59    45   59  120  2.37e-02   10 104
+  0.64   3.16252e-05  1   40   54   73    54   73  156  1.90e-01   13 127
+  1.28   4.37189e-19  1   42   56   73    56   73  180  7.58e-01   15 129
+  2.56   9.47890e-21  1   43   57   73    57   73  192  1.52e+00   16 130
+  5.12   1.69074e-20  1   44   58   73    58   73  204  3.03e+00   17 131
+ 10.24   2.64109e-20  1   45   59   73    59   73  216  6.06e+00   18 132
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
@@ -39,7 +39,7 @@ Case 2.
 
    Output Summary (umax = max-norm of solution) 
 
-  time     umax       k  nst  nni  nli   nre nreLS nge   h      npe nps
+  time     umax       k  nst  nni  nli   nre nreLS nge     h      npe nps
  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
   0.01   8.24111e-01  2   12   14    7    14    7   32  2.56e-03    8  21
   0.02   6.88118e-01  3   15   18   12    18   12   32  5.12e-03    8  30
@@ -47,11 +47,11 @@ Case 2.
   0.08   2.16547e-01  3   23   27   32    27   32   36  1.02e-02    9  59
   0.16   4.52248e-02  4   27   33   44    33   44   40  2.05e-02   10  77
   0.32   2.18677e-03  3   34   41   67    41   67   44  4.10e-02   11 108
-  0.64   4.88467e-19  1   39   49   86    49   86   52  1.64e-01   13 135
-  1.28   5.39822e-19  1   41   51   86    51   86   60  6.55e-01   15 137
-  2.56   7.41945e-18  1   42   52   86    52   86   64  1.31e+00   16 138
-  5.12   6.10808e-17  1   43   53   86    53   86   68  2.62e+00   17 139
- 10.24   4.05358e-16  1   44   54   86    54   86   72  5.24e+00   18 140
+  0.64   3.25106e-19  1   39   49   86    49   86   52  1.64e-01   13 135
+  1.28   1.66623e-19  1   41   51   86    51   86   60  6.55e-01   15 137
+  2.56   1.06302e-18  1   42   52   86    52   86   64  1.31e+00   16 138
+  5.12   8.93778e-18  1   43   53   86    53   86   68  2.62e+00   17 139
+ 10.24   6.99660e-17  1   44   54   86    54   86   72  5.24e+00   18 140
 
 Error test failures            = 0
 Nonlinear convergence failures = 0
diff --git a/examples/idas/parallel/idasHeat2D_kry_p.c b/examples/idas/parallel/idasHeat2D_kry_p.c
index 68c9b3c..d2f6ea9 100644
--- a/examples/idas/parallel/idasHeat2D_kry_p.c
+++ b/examples/idas/parallel/idasHeat2D_kry_p.c
@@ -1,15 +1,12 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *         Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, parallel, GMRES.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the Krylov solver IDASpgmr.
+ * This version uses the Krylov solver SUNSPGMR.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -25,9 +22,9 @@
  * processors.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR. The preconditioner uses the diagonal elements of the
+ * SUNSPGMR. The preconditioner uses the diagonal elements of the
  * Jacobian only. Routines for preconditioning, required by
- * IDASPGMR, are supplied here. The constraints u >= 0 are posed
+ * SUNSPGMR, are supplied here. The constraints u >= 0 are posed
  * for all components. Local error testing on the boundary values
  * is suppressed. Output is taken at t = 0, .01, .02, .04,
  * ..., 10.24.
@@ -39,7 +36,8 @@
 #include <math.h>
 
 #include <idas/idas.h>
-#include <idas/idas_spgmr.h>
+#include <idas/idas_spils.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
 #include <nvector/nvector_parallel.h>
 #include <sundials/sundials_types.h>
 #include <sundials/sundials_math.h>
@@ -63,7 +61,8 @@
                                     /* Spatial mesh is MX by MY */
 
 typedef struct {  
-  long int thispe, mx, my, ixsub, jysub, npex, npey, mxsub, mysub;
+  int thispe, npex, npey, ixsub, jysub;
+  sunindextype mx, my, mxsub, mysub;
   realtype    dx, dy, coeffx, coeffy, coeffxy;
   realtype    uext[(MXSUB+2)*(MYSUB+2)];
   N_Vector    pp;    /* vector of diagonal preconditioner elements */
@@ -72,38 +71,32 @@ typedef struct {
 
 /* User-supplied residual function and supporting routines */
 
-int resHeat(realtype tt, 
-            N_Vector uu, N_Vector up, N_Vector rr, 
-            void *user_data);
+int resHeat(realtype tt, N_Vector uu, N_Vector up,
+            N_Vector rr, void *user_data);
 
 static int rescomm(N_Vector uu, N_Vector up, void *user_data);
 
 static int reslocal(realtype tt, N_Vector uu, N_Vector up, 
                     N_Vector res,  void *user_data);
 
-static int BSend(MPI_Comm comm, long int thispe, long int ixsub, long int jysub,
-                 long int dsizex, long int dsizey, realtype uarray[]);
+static int BSend(MPI_Comm comm, int thispe, int ixsub, int jysub,
+                 sunindextype dsizex, sunindextype dsizey, realtype uarray[]);
 
-static int BRecvPost(MPI_Comm comm, MPI_Request request[], long int thispe,
-                     long int ixsub, long int jysub,
-                     long int dsizex, long int dsizey,
-                     realtype uext[], realtype buffer[]);
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+                     int ixsub, int jysub, sunindextype dsizex,
+                     sunindextype dsizey, realtype uext[], realtype buffer[]);
 
-static int BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
-                     long int dsizex, realtype uext[], realtype buffer[]);
+static int BRecvWait(MPI_Request request[], int ixsub, int jysub,
+                     sunindextype dsizex, realtype uext[], realtype buffer[]);
 
 /* User-supplied preconditioner routines */
 
-int PsolveHeat(realtype tt, 
-               N_Vector uu, N_Vector up, N_Vector rr, 
-               N_Vector rvec, N_Vector zvec,
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp);
+int PsolveHeat(realtype tt, N_Vector uu, N_Vector up, N_Vector rr, 
+               N_Vector rvec, N_Vector zvec, realtype c_j,
+               realtype delta, void *user_data);
 
-int PsetupHeat(realtype tt, 
-               N_Vector yy, N_Vector yp, N_Vector rr, 
-               realtype c_j, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+int PsetupHeat(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, 
+               realtype c_j, void *user_data);
 
 /* Private function to check function return values */
 
@@ -112,11 +105,11 @@ static int InitUserData(int thispe, MPI_Comm comm, UserData data);
 static int SetInitialProfile(N_Vector uu, N_Vector up, N_Vector id,
                              N_Vector res, UserData data);
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol);
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu);
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu);
 
-static void PrintFinalStats(void *mem);
+static void PrintFinalStats(void *ida_mem);
 
 static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
@@ -129,14 +122,16 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 int main(int argc, char *argv[])
 {
   MPI_Comm comm;
-  void *mem;
+  void *ida_mem;
+  SUNLinearSolver LS;
   UserData data;
   int iout, thispe, ier, npes;
-  long int Neq, local_N;
+  sunindextype Neq, local_N;
   realtype rtol, atol, t0, t1, tout, tret;
   N_Vector uu, up, constraints, id, res;
 
-  mem = NULL;
+  ida_mem = NULL;
+  LS = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
 
@@ -212,59 +207,63 @@ int main(int argc, char *argv[])
 
   /* Call IDACreate and IDAMalloc to initialize solution. */
 
-  mem = IDACreate();
-  if(check_flag((void *)mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
+  ida_mem = IDACreate();
+  if(check_flag((void *)ida_mem, "IDACreate", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetUserData(mem, data);
+  ier = IDASetUserData(ida_mem, data);
   if(check_flag(&ier, "IDASetUserData", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetSuppressAlg(mem, TRUE);
+  ier = IDASetSuppressAlg(ida_mem, SUNTRUE);
   if(check_flag(&ier, "IDASetSuppressAlg", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetId(mem, id);
+  ier = IDASetId(ida_mem, id);
   if(check_flag(&ier, "IDASetId", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASetConstraints(mem, constraints);
+  ier = IDASetConstraints(ida_mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1, thispe)) MPI_Abort(comm, 1);
   N_VDestroy_Parallel(constraints);  
 
-  ier = IDAInit(mem, resHeat, t0, uu, up);
+  ier = IDAInit(ida_mem, resHeat, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1, thispe)) MPI_Abort(comm, 1);
   
-  ier = IDASStolerances(mem, rtol, atol);
+  ier = IDASStolerances(ida_mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1, thispe)) MPI_Abort(comm, 1);
 
-  /* Call IDASpgmr to specify the linear solver. */
+  /* Call SUNSPGMR and IDASetLinearSolver to specify the linear solver. */
+
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);  /* use default maxl */
+  if(check_flag((void *)LS, "SUNSPGMR", 0, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASpgmr(mem, 0);
-  if(check_flag(&ier, "IDASpgmr", 1, thispe)) MPI_Abort(comm, 1);
+  ier = IDASpilsSetLinearSolver(ida_mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1, thispe)) MPI_Abort(comm, 1);
 
-  ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
+  ier = IDASpilsSetPreconditioner(ida_mem, PsetupHeat, PsolveHeat);
   if(check_flag(&ier, "IDASpilsSetPreconditioner", 1, thispe)) MPI_Abort(comm, 1);
 
   /* Print output heading (on processor 0 only) and intial solution  */
   
   if (thispe == 0) PrintHeader(Neq, rtol, atol);
-  PrintOutput(thispe, mem, t0, uu); 
+  PrintOutput(thispe, ida_mem, t0, uu); 
   
   /* Loop over tout, call IDASolve, print output. */
 
   for (tout = t1, iout = 1; iout <= NOUT; iout++, tout *= TWO) {
 
-    ier = IDASolve(mem, tout, &tret, uu, up, IDA_NORMAL);
+    ier = IDASolve(ida_mem, tout, &tret, uu, up, IDA_NORMAL);
     if(check_flag(&ier, "IDASolve", 1, thispe)) MPI_Abort(comm, 1);
 
-    PrintOutput(thispe, mem, tret, uu);
+    PrintOutput(thispe, ida_mem, tret, uu);
 
   }
   
   /* Print remaining counters. */
 
-  if (thispe == 0) PrintFinalStats(mem);
+  if (thispe == 0) PrintFinalStats(ida_mem);
 
   /* Free memory */
 
-  IDAFree(&mem);
+  IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
 
   N_VDestroy_Parallel(id);
   N_VDestroy_Parallel(res);
@@ -302,8 +301,7 @@ int main(int argc, char *argv[])
  * of uu required to calculate the residual. 
  */
 
-int resHeat(realtype tt, 
-            N_Vector uu, N_Vector up, N_Vector rr, 
+int resHeat(realtype tt, N_Vector uu, N_Vector up, N_Vector rr, 
             void *user_data)
 {
   int retval;
@@ -336,14 +334,12 @@ int resHeat(realtype tt,
  *
  */
 
-int PsetupHeat(realtype tt, 
-               N_Vector yy, N_Vector yp, N_Vector rr, 
-               realtype c_j, void *user_data,
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+int PsetupHeat(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, 
+               realtype c_j, void *user_data)
 {
   realtype *ppv, pelinv;
-  long int lx, ly, ixbegin, ixend, jybegin, jyend, locu, mxsub, mysub;
-  long int ixsub, jysub, npex, npey;
+  sunindextype lx, ly, ixbegin, ixend, jybegin, jyend, locu, mxsub, mysub;
+  int ixsub, jysub, npex, npey;
   UserData data;
 
   data = (UserData) user_data;
@@ -389,11 +385,9 @@ int PsetupHeat(realtype tt,
  * computed in PsetupHeat), returning the result in zvec.      
  */
 
-int PsolveHeat(realtype tt, 
-               N_Vector uu, N_Vector up, N_Vector rr, 
-               N_Vector rvec, N_Vector zvec,
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp)
+int PsolveHeat(realtype tt, N_Vector uu, N_Vector up,
+               N_Vector rr, N_Vector rvec, N_Vector zvec,
+               realtype c_j, realtype delta, void *user_data)
 {
   UserData data;
 
@@ -422,7 +416,8 @@ static int rescomm(N_Vector uu, N_Vector up, void *user_data)
   UserData data;
   realtype *uarray, *uext, buffer[2*MYSUB];
   MPI_Comm comm;
-  long int thispe, ixsub, jysub, mxsub, mysub;
+  int thispe, ixsub, jysub;
+  sunindextype mxsub, mysub;
   MPI_Request request[4];
   
   data = (UserData) user_data;
@@ -453,15 +448,15 @@ static int rescomm(N_Vector uu, N_Vector up, void *user_data)
  * has already been done, and that this data is in the work array uext.  
  */
 
-static int reslocal(realtype tt, 
-                    N_Vector uu, N_Vector up, N_Vector rr,
+static int reslocal(realtype tt, N_Vector uu, N_Vector up, N_Vector rr,
                     void *user_data)
 {
   realtype *uext, *uuv, *upv, *resv;
   realtype termx, termy, termctr;
-  long int lx, ly, offsetu, offsetue, locu, locue;
-  long int ixsub, jysub, mxsub, mxsub2, mysub, npex, npey;
-  long int ixbegin, ixend, jybegin, jyend;
+  sunindextype lx, ly, offsetu, offsetue, locu, locue;
+  int ixsub, jysub, npex, npey;
+  sunindextype mxsub, mxsub2, mysub;
+  sunindextype ixbegin, ixend, jybegin, jyend;
   UserData data;
   
   /* Get subgrid indices, array sizes, extended work array uext. */
@@ -520,10 +515,10 @@ static int reslocal(realtype tt,
  * Routine to send boundary data to neighboring PEs.                     
  */
 
-static int BSend(MPI_Comm comm, long int thispe, long int ixsub, long int jysub,
-                 long int dsizex, long int dsizey, realtype uarray[])
+static int BSend(MPI_Comm comm, int thispe, int ixsub, int jysub,
+                 sunindextype dsizex, sunindextype dsizey, realtype uarray[])
 {
-  long int ly, offsetu;
+  sunindextype ly, offsetu;
   realtype bufleft[MYSUB], bufright[MYSUB];
 
   /* If jysub > 0, send data from bottom x-line of u. */
@@ -573,12 +568,11 @@ static int BSend(MPI_Comm comm, long int thispe, long int ixsub, long int jysub,
  *      both calls also. 
  */
 
-static int BRecvPost(MPI_Comm comm, MPI_Request request[], long int thispe,
-                     long int ixsub, long int jysub,
-                     long int dsizex, long int dsizey,
-                     realtype uext[], realtype buffer[])
+static int BRecvPost(MPI_Comm comm, MPI_Request request[], int thispe,
+                     int ixsub, int jysub, sunindextype dsizex,
+                     sunindextype dsizey, realtype uext[], realtype buffer[])
 {
-  long int offsetue;
+  sunindextype offsetue;
   /* Have bufleft and bufright use the same buffer. */
   realtype *bufleft = buffer, *bufright = buffer+MYSUB;
   
@@ -620,10 +614,10 @@ static int BRecvPost(MPI_Comm comm, MPI_Request request[], long int thispe,
  *      calls also. 
  */
 
-static int BRecvWait(MPI_Request request[], long int ixsub, long int jysub,
-                     long int dsizex, realtype uext[], realtype buffer[])
+static int BRecvWait(MPI_Request request[], int ixsub, int jysub,
+                     sunindextype dsizex, realtype uext[], realtype buffer[])
 {
-  long int ly, dsizex2, offsetue;
+  sunindextype ly, dsizex2, offsetue;
   realtype *bufleft = buffer, *bufright = buffer+MYSUB;
   MPI_Status status;
   
@@ -701,8 +695,9 @@ static int InitUserData(int thispe, MPI_Comm comm, UserData data)
 static int SetInitialProfile(N_Vector uu, N_Vector up,  N_Vector id, 
                              N_Vector res, UserData data)
 {
-  long int i, iloc, j, jloc, offset, loc, ixsub, jysub;
-  long int ixbegin, ixend, jybegin, jyend;
+  int ixsub, jysub;
+  sunindextype i, iloc, j, jloc, offset, loc;
+  sunindextype ixbegin, ixend, jybegin, jyend;
   realtype xfact, yfact, *udata, *iddata, dx, dy;
   
   /* Initialize uu. */ 
@@ -756,14 +751,14 @@ static int SetInitialProfile(N_Vector uu, N_Vector up,  N_Vector id,
  * Print first lines of output and table heading
  */
 
-static void PrintHeader(long int Neq, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype Neq, realtype rtol, realtype atol)
 { 
   printf("\nidasHeat2D_p: Heat equation, parallel example problem for IDA\n");
   printf("                Discretized heat equation on 2D unit square.\n");
   printf("                Zero boundary conditions,");
   printf(" polynomial initial conditions.\n");
   printf("                Mesh dimensions: %d x %d", MX, MY);
-  printf("        Total system size: %ld\n\n", Neq);
+  printf("        Total system size: %ld\n\n", (long int) Neq);
   printf("Subgrid dimensions: %d x %d", MXSUB, MYSUB);
   printf("        Processor array: %d x %d\n", NPEX, NPEY);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -774,9 +769,9 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("SUPPRESSALG = TRUE to suppress local error testing on ");
+  printf("SUPPRESSALG = SUNTRUE to suppress local error testing on ");
   printf("all boundary components. \n");
-  printf("Linear solver: IDASPGMR  ");
+  printf("Linear solver: SUNSPGMR  ");
   printf("Preconditioner: diagonal elements only.\n"); 
   
   /* Print output table heading and initial line of table. */
@@ -789,7 +784,7 @@ static void PrintHeader(long int Neq, realtype rtol, realtype atol)
  * PrintOutput: print max norm of solution and current solver statistics
  */
 
-static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
+static void PrintOutput(int id, void *ida_mem, realtype t, N_Vector uu)
 {
   realtype hused, umax;
   long int nst, nni, nje, nre, nreLS, nli, npe, nps;
@@ -799,25 +794,25 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
 
   if (id == 0) {
 
-    ier = IDAGetLastOrder(mem, &kused);
+    ier = IDAGetLastOrder(ida_mem, &kused);
     check_flag(&ier, "IDAGetLastOrder", 1, id);
-    ier = IDAGetNumSteps(mem, &nst);
+    ier = IDAGetNumSteps(ida_mem, &nst);
     check_flag(&ier, "IDAGetNumSteps", 1, id);
-    ier = IDAGetNumNonlinSolvIters(mem, &nni);
+    ier = IDAGetNumNonlinSolvIters(ida_mem, &nni);
     check_flag(&ier, "IDAGetNumNonlinSolvIters", 1, id);
-    ier = IDAGetNumResEvals(mem, &nre);
+    ier = IDAGetNumResEvals(ida_mem, &nre);
     check_flag(&ier, "IDAGetNumResEvals", 1, id);
-    ier = IDAGetLastStep(mem, &hused);
+    ier = IDAGetLastStep(ida_mem, &hused);
     check_flag(&ier, "IDAGetLastStep", 1, id);
-    ier = IDASpilsGetNumJtimesEvals(mem, &nje);
+    ier = IDASpilsGetNumJtimesEvals(ida_mem, &nje);
     check_flag(&ier, "IDASpilsGetNumJtimesEvals", 1, id);
-    ier = IDASpilsGetNumLinIters(mem, &nli);
+    ier = IDASpilsGetNumLinIters(ida_mem, &nli);
     check_flag(&ier, "IDASpilsGetNumLinIters", 1, id);
-    ier = IDASpilsGetNumResEvals(mem, &nreLS);
+    ier = IDASpilsGetNumResEvals(ida_mem, &nreLS);
     check_flag(&ier, "IDASpilsGetNumResEvals", 1, id);
-    ier = IDASpilsGetNumPrecEvals(mem, &npe);
+    ier = IDASpilsGetNumPrecEvals(ida_mem, &npe);
     check_flag(&ier, "IDASpilsGetPrecEvals", 1, id);
-    ier = IDASpilsGetNumPrecSolves(mem, &nps);
+    ier = IDASpilsGetNumPrecSolves(ida_mem, &nps);
     check_flag(&ier, "IDASpilsGetNumPrecSolves", 1, id);
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)  
@@ -838,13 +833,13 @@ static void PrintOutput(int id, void *mem, realtype t, N_Vector uu)
  * Print some final integrator statistics
  */
 
-static void PrintFinalStats(void *mem)
+static void PrintFinalStats(void *ida_mem)
 {
   long int netf, ncfn, ncfl;
 
-  IDAGetNumErrTestFails(mem, &netf);
-  IDAGetNumNonlinSolvConvFails(mem, &ncfn);
-  IDASpilsGetNumConvFails(mem, &ncfl);
+  IDAGetNumErrTestFails(ida_mem, &netf);
+  IDAGetNumNonlinSolvConvFails(ida_mem, &ncfn);
+  IDASpilsGetNumConvFails(ida_mem, &ncfl);
 
   printf("\nError test failures            = %ld\n", netf);
   printf("Nonlinear convergence failures = %ld\n", ncfn);
diff --git a/examples/idas/parallel/idasHeat2D_kry_p.out b/examples/idas/parallel/idasHeat2D_kry_p.out
index b513617..57ce02a 100644
--- a/examples/idas/parallel/idasHeat2D_kry_p.out
+++ b/examples/idas/parallel/idasHeat2D_kry_p.out
@@ -1,14 +1,14 @@
 
-idasHeat2D_kry_p: Heat equation, parallel example problem for IDA
-              Discretized heat equation on 2D unit square.
-              Zero boundary conditions, polynomial initial conditions.
-              Mesh dimensions: 10 x 10        Total system size: 100
+idasHeat2D_p: Heat equation, parallel example problem for IDA
+                Discretized heat equation on 2D unit square.
+                Zero boundary conditions, polynomial initial conditions.
+                Mesh dimensions: 10 x 10        Total system size: 100
 
 Subgrid dimensions: 5 x 5        Processor array: 2 x 2
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-SUPPRESSALG = TRUE to suppress local error testing on all boundary components. 
-Linear solver: IDASPGMR  Preconditioner: diagonal elements only.
+SUPPRESSALG = SUNTRUE to suppress local error testing on all boundary components. 
+Linear solver: SUNSPGMR  Preconditioner: diagonal elements only.
 
    Output Summary (umax = max-norm of solution) 
 
@@ -23,9 +23,9 @@ Linear solver: IDASPGMR  Preconditioner: diagonal elements only.
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
   0.64   5.54028e-21  1   39   51   77    51    77   1.05e-01   12 128
   1.28   3.85107e-20  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   5.00523e-20  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   1.50906e-19  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   4.63224e-19  1   45   57   77    57    77   6.74e+00   18 134
+  2.56   5.56136e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   1.92667e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   5.91880e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
diff --git a/examples/idas/serial/CMakeLists.txt b/examples/idas/serial/CMakeLists.txt
index 267bfd7..b9d0300 100644
--- a/examples/idas/serial/CMakeLists.txt
+++ b/examples/idas/serial/CMakeLists.txt
@@ -1,13 +1,11 @@
 # ---------------------------------------------------------------
-# $Revision: 4866 $
-# $Date: 2016-08-18 16:07:58 -0700 (Thu, 18 Aug 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,147 +13,311 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for IDAS serial examples
-#
-# LEBanks 3/25/2013
-#    Added SUPERLUMT logic.
-
+# ---------------------------------------------------------------
 
-# Add variable IDAS_examples with the names of the serial IDAS examples
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS linear solvers
 SET(IDAS_examples
-  idasAkzoNob_ASAi_dns
-  idasAkzoNob_dns
-  idasFoodWeb_bnd
-  idasHeat2D_bnd
-  idasHeat2D_kry
-  idasHessian_ASA_FSA
-  idasKrylovDemo_ls
-  idasRoberts_ASAi_dns
-  idasRoberts_dns
-  "idasRoberts_FSA_dns\;-sensi stg t"
-  idasSlCrank_dns
-  idasSlCrank_FSA_dns
+  "idasAkzoNob_ASAi_dns\;\;develop"
+  "idasAkzoNob_dns\;\;develop"
+  "idasFoodWeb_bnd\;\;develop"
+  "idasHeat2D_bnd\;\;develop"
+  "idasHeat2D_kry\;\;develop"
+  "idasHessian_ASA_FSA\;\;develop"
+  "idasKrylovDemo_ls\;\;develop"
+  "idasRoberts_ASAi_dns\;\;develop"
+  "idasRoberts_dns\;\;"
+  "idasRoberts_FSA_dns\;-sensi stg t\;develop"
+  "idasSlCrank_dns\;\;develop"
+  "idasSlCrank_FSA_dns\;\;develop"
   )
 
-# Add variable IDAS_examples_BL with the names of the serial IDAS examples
-# that use Lapack
-
+# Examples using LAPACK linear solvers
 SET(IDAS_examples_BL
   )
-  
-SET(IDAS_examples_SUPERLUMT
-  idasRoberts_sps
-  idasRoberts_ASAi_sps
-  "idasRoberts_FSA_sps\;-sensi stg t"
-  )
 
+# Example using KLU linear solver
 SET(IDAS_examples_KLU
-  idasRoberts_klu
-  idasRoberts_ASAi_klu
-  "idasRoberts_FSA_klu\;-sensi stg t"
+  "idasRoberts_klu\;\;develop"
+  "idasRoberts_ASAi_klu\;\;develop"
+  "idasRoberts_FSA_klu\;-sensi stg t\;develop"
   )
 
-# Specify libraries to link against (through the target that was used to 
-# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+# Examples using SuperLU_MT linear solver
+SET(IDAS_examples_SUPERLUMT
+  "idasRoberts_sps\;\;develop"
+  "idasRoberts_ASAi_sps\;\;develop"
+  "idasRoberts_FSA_sps\;-sensi stg t\;develop"
+  )
 
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(IDAS_LIB sundials_idas_static)
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(IDAS_LIB sundials_idas_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${IDAS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  # quote list to retain integrity
-  LIST(APPEND IDAS_examples "${IDAS_examples_SUPERLUMT}")
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND IDAS_examples "${IDAS_examples_KLU}")
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-# Add the build and install targets for each IDAS example
 
-# SGS is there a way to query CMAKE variable to get added executables 
-# rather than keeping our own list?
-SET(ADDED_EXECUTABLES "")
+# Add the build and install targets for each example
 FOREACH(example_tuple ${IDAS_examples})
+
+  # first item is example
   LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
 
-  # Only need to add the executable once
-  LIST(FIND ADDED_EXECUTABLES ${example} index)
-  IF(index EQUAL -1)
-    LIST(APPEND ADDED_EXECUTABLES ${example})
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
+
+    # folder to organize targets in an IDE
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  ENDIF(index EQUAL -1)
 
-  LIST(LENGTH example_tuple n)
-  IF(n EQUAL 2)
-    LIST(GET example_tuple 1 test_args)
-    STRING(REGEX REPLACE " " "_" test_name ${example}_${test_args})
-    SUNDIALS_ADD_TEST(${test_name} ${example} TEST_ARGS ${test_args})
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
   ELSE()
-    SUNDIALS_ADD_TEST(${example} ${example})
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
   ENDIF()
 
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${test_name}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # find all .out files for this example
+  FILE(GLOB example_out ${example}.out*)
+
+  # install example source and .out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example_out}
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${IDAS_examples})
 
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
+
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${IDAS_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.c)
-    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${IDAS_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_args)
+    LIST(GET example_tuple 2 example_type)
+
+    # check if this example has already been added, only need to add
+    # example source files once for testing with different inputs
+    IF(NOT TARGET ${example})
+      # example source files
+      ADD_EXECUTABLE(${example} ${example}.c)
+
+      # folder to organize targets in an IDE
+      SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+      # libraries to link against
+      TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+    ENDIF()
+
+    # check if example args are provided and set the test name
+    # IF("${example_args}" STREQUAL "")
+    #   SET(test_name ${example})
+    # ELSE()
+    #   STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+    # ENDIF()
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # find all .out files for this example
+    FILE(GLOB example_out ${example}.out*)
+
+    # install example source and .out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${IDAS_examples_BL})
+      INSTALL(FILES ${example}.c ${example_out}
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${IDAS_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If SUPERLUMT support is enabled, add the build and install targets for
-# the examples using SUPERLUMT
-#IF(SUPERLUMT_FOUND)
-#  FOREACH(example ${IDAS_examples_SUPERLUMT})
-#    ADD_EXECUTABLE(${example} ${example}.c)
-#    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-#    SUNDIALS_ADD_TEST(${example} ${example})
-#    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-#    IF(EXAMPLES_INSTALL)
-#      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
-#    ENDIF(EXAMPLES_INSTALL)
-#  ENDFOREACH(example ${IDAS_examples_SUPERLUMT})
-#ENDIF(SUPERLUMT_FOUND)
-
-# If KLU support is enabled, add the build and install targets for
-# the examples using KLU
-#IF(KLU_FOUND)
-#  FOREACH(example ${IDAS_examples_KLU})
-#    ADD_EXECUTABLE(${example} ${example}.c)
-#    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-#    SUNDIALS_ADD_TEST(${example} ${example})
-#    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-#    IF(EXAMPLES_INSTALL)
-#      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
-#    ENDIF(EXAMPLES_INSTALL)
-#  ENDFOREACH(example ${IDAS_examples_KLU})
-#ENDIF(KLU_FOUND)
+
+# Add the build and install targets for each KLU example (if needed)
+IF(KLU_FOUND)
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${IDAS_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_args)
+    LIST(GET example_tuple 2 example_type)
+
+    # check if this example has already been added, only need to add
+    # example source files once for testing with different inputs
+    IF(NOT TARGET ${example})
+      # example source files
+      ADD_EXECUTABLE(${example} ${example}.c)
+      
+      # folder to organize targets in an IDE
+      SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+      
+      # libraries to link against
+      TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+    ENDIF()
+
+    # check if example args are provided and set the test name
+    IF("${example_args}" STREQUAL "")
+      SET(test_name ${example})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+    ENDIF()
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${test_name} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${test_name}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # find all .out files for this example
+    FILE(GLOB example_out ${example}.out*)
+
+    # install example source and .out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.c ${example_out}
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${IDAS_examples_KLU})
+
+ENDIF(KLU_FOUND)
+
+
+# Add the build and install targets for each SuperLU_MT example (if needed)
+IF(SUPERLUMT_FOUND)
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${IDAS_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_args)
+    LIST(GET example_tuple 2 example_type)
+
+    # check if this example has already been added, only need to add
+    # example source files once for testing with different inputs
+    IF(NOT TARGET ${example})
+      # example source files
+      ADD_EXECUTABLE(${example} ${example}.c)
+      
+      # folder to organize targets in an IDE
+      SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+      
+      # libraries to link against
+      TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+    ENDIF()
+
+    # check if example args are provided and set the test name
+    IF("${example_args}" STREQUAL "")
+      SET(test_name ${example})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+    ENDIF()
+
+    # Do not include SuperLUMT examples in testing when the indextype is int64_t.
+    # Answer files were generated with int32_t and minor differences in output
+    # occur causing a false positive when testing. These tests can be re-enabled
+    # when type specific answer files are added.
+    IF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+      # add example to regression tests
+      SUNDIALS_ADD_TEST(${test_name} ${example}
+        TEST_ARGS ${example_args}
+        ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+        ANSWER_FILE ${test_name}.out
+        EXAMPLE_TYPE ${example_type})
+
+    ENDIF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+    # find all .out files for this example
+    FILE(GLOB example_out ${example}.out*)
+
+    # install example source and .out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.c ${example_out}
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${IDAS_examples_SUPERLUMT})
+
+ENDIF(SUPERLUMT_FOUND)
+
+
 
 IF(EXAMPLES_INSTALL)
 
@@ -165,47 +327,46 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "IDAS")
   SET(SOLVER_LIB "sundials_idas")
-  FOREACH(example_tuple ${IDAS_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${IDAS_examples})
+
+  EXAMPLES2STRING(IDAS_examples EXAMPLES)
 
   IF(LAPACK_FOUND)
-    LIST2STRING(IDAS_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
+    EXAMPLES2STRING(IDAS_examples_BL EXAMPLES_BL)
+  ELSE()
     SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+  ENDIF()
 
   IF(KLU_FOUND)
-    #LIST2STRING(IDAS_examples_KLU EXAMPLES)
-  ENDIF(KLU_FOUND)
+    EXAMPLES2STRING(IDAS_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
+  ENDIF()
 
   IF(SUPERLUMT_FOUND)
-    #LIST2STRING(IDAS_examples_SUPERLUMT EXAMPLES)
-  ENDIF(SUPERLUMT_FOUND)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
+    EXAMPLES2STRING(IDAS_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMTU "")
+  ENDIF()
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/idas/serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/idas/serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/idas/serial/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
@@ -217,10 +378,14 @@ IF(EXAMPLES_INSTALL)
       )
     # install the configured Makefile_ex as Makefile
     INSTALL(
-      FILES ${PROJECT_BINARY_DIR}/examples/idas/serial/Makefile_ex 
-      DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial 
+      FILES ${PROJECT_BINARY_DIR}/examples/idas/serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/idas/serial
       RENAME Makefile
       )
   ENDIF(UNIX)
 
+  # add test_install target
+  SUNDIALS_ADD_TEST_INSTALL(idas idasRoberts_dns
+    EXAMPLE_DIR ${EXAMPLES_INSTALL_PATH}/idas/serial)
+
 ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/idas/serial/README b/examples/idas/serial/README
index b4a3169..5174d7e 100644
--- a/examples/idas/serial/README
+++ b/examples/idas/serial/README
@@ -7,11 +7,15 @@ List of serial IDAS examples
   idasHeat2D_kry        : 2-D heat equation, diagonal preconditioner
   idasHessian_ASA_FSA   : computation of Hessian for Robertson kinetics system
   idasKrylovDemo_ls     : demonstration program with 3 Krylov solvers
-  idasRoberts_ASAi_dns  : adjoint sensitivity for Robertson kinetics system
   idasRoberts_dns       : 3-species Robertson kinetics system with user Jacobian
   idasRoberts_klu       : Robertson system with KLU sparse linear solver
   idasRoberts_sps       : Robertson system with SuperLUMT sparse linear solver
   idasRoberts_FSA_dns   : forward sensitivity for Robertson kinetics system
+  idasRoberts_FSA_klu   : FSA for Robertson system with KLU sparse linear solver
+  idasRoberts_FSA_sps   : FSA for Robertson system with SuperLUMT sparse solver
+  idasRoberts_ASAi_dns  : adjoint sensitivity for Robertson kinetics system
+  idasRoberts_ASAi_klu  : ASA for Robertson system with KLU sparse linear solver
+  idasRoberts_ASAi_sps  : ASA for Robertson system with SuperLUMT sparse solver
   idasSlCrank_dns       : slider-crank simulation
   idasSlCrank_FSA_dns   : forward sensitivity for slider-crank
 
@@ -21,7 +25,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -32,7 +35,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -46,7 +52,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/idas/serial/idasAkzoNob_ASAi_dns.c b/examples/idas/serial/idasAkzoNob_ASAi_dns.c
index c05d1d6..f398f66 100644
--- a/examples/idas/serial/idasAkzoNob_ASAi_dns.c
+++ b/examples/idas/serial/idasAkzoNob_ASAi_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -27,25 +23,28 @@
  * conditions of the following quantity:
  *   G = int_t0^t1 y1 dt
  * The sensitivity of G is the solution of the adjoint system at t0. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
  
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
  
-#include <idas/idas.h>
-#include <idas/idas_dense.h>
-#include <sundials/sundials_math.h>
-#include <nvector/nvector_serial.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component */
 
 /* Problem Constants */
 #define NEQ 6
-#define T0 RCONST(0.0)
-#define TF RCONST(180.0)
+#define T0  RCONST(0.0)
+
+#define TF  RCONST(180.0) /* Final time. */
 
 #define RTOL  RCONST(1.0e-08)
 #define ATOL  RCONST(1.0e-10)
@@ -54,7 +53,6 @@
 #define RTOLQ RCONST(1.0e-10)
 #define ATOLQ RCONST(1.0e-12)
 
-
 #define ZERO  RCONST(0.0)
 #define HALF  RCONST(0.5)
 #define ONE   RCONST(1.0)
@@ -80,7 +78,6 @@ static int rhsQ(realtype t, N_Vector yy, N_Vector yp,
 static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector ypB);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
-
 /* Main program */
 int main()
 {
@@ -92,10 +89,20 @@ int main()
   realtype time;
   long int nst, nstB;
   int indexB;
-    
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
+
+  /* Consistent IC for  y, y'. */
+  const realtype y01 = RCONST(0.444);
+  const realtype y02 = RCONST(0.00123);
+  const realtype y03 = RCONST(0.0);
+  const realtype y04 = RCONST(0.007);
+  const realtype y05 = RCONST(0.0);
 
   mem = NULL;
   yy = yp = NULL;
+  A = AB = NULL;
+  LS = LSB = NULL;
 
   printf("\nAdjoint Sensitivity Example for Akzo-Nobel Chemical Kinetics\n");
   printf("-------------------------------------------------------------\n");
@@ -121,18 +128,13 @@ int main()
   yp = N_VNew_Serial(NEQ);
   if (check_flag((void *)yp, "N_VNew_Serial", 0)) return(1);
 
-  /* Consistent IC for  y, y'. */
-#define y01 0.444
-#define y02 0.00123
-#define y03 0.00
-#define y04 0.007
-#define y05 0.0
-  Ith(yy,1) = RCONST(y01);
-  Ith(yy,2) = RCONST(y02);
-  Ith(yy,3) = RCONST(y03);
-  Ith(yy,4) = RCONST(y04);
-  Ith(yy,5) = RCONST(y05);
-  Ith(yy,6) = data->Ks * RCONST(y01) * RCONST(y04);
+  /* Set IC */
+  Ith(yy,1) = y01;
+  Ith(yy,2) = y02;
+  Ith(yy,3) = y03;
+  Ith(yy,4) = y04;
+  Ith(yy,5) = y05;
+  Ith(yy,6) = data->Ks * y01 * y04;
 
   /* Get y' = - res(t0, y, 0) */
   N_VConst(ZERO, yp);
@@ -140,7 +142,7 @@ int main()
   rr = N_VNew_Serial(NEQ);
   res(T0, yy, yp, rr, data);
   N_VScale(-ONE, rr, yp);
-  N_VDestroy_Serial(rr);
+  N_VDestroy(rr);
   
  /* Create and initialize q0 for quadratures. */
   q = N_VNew_Serial(1);
@@ -161,10 +163,19 @@ int main()
 
   /* Attach user data. */
   flag = IDASetUserData(mem, data);
-  if(check_flag(&flag, "IDASetUser", 1)) return(1);
-  
-  /* Attach linear solver. */
-  flag = IDADense(mem, NEQ);
+  if(check_flag(&flag, "IDASetUserData", 1)) return(1);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
   /* Initialize QUADRATURE(S). */
   flag = IDAQuadInit(mem, rhsQ, q);
@@ -174,7 +185,7 @@ int main()
   flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
   if (check_flag(&flag, "IDAQuadSStolerances", 1)) return(1);
 
-  flag = IDASetQuadErrCon(mem, TRUE);
+  flag = IDASetQuadErrCon(mem, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
  
   /* Prepare ADJOINT. */
@@ -194,7 +205,11 @@ int main()
   flag = IDAGetQuad(mem, &time, q);
   if (check_flag(&flag, "IDAGetQuad", 1)) return(1);
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("G:          %24.16Lf \n",Ith(q,1));
+#else
   printf("G:          %24.16f \n",Ith(q,1));
+#endif  
   printf("--------------------------------------------------------\n\n");
 
 
@@ -224,8 +239,17 @@ int main()
 
   flag = IDASetMaxNumStepsB(mem, indexB, 1000);
 
-  flag = IDADenseB(mem, indexB, NEQ);
-  if (check_flag(&flag, "IDADenseB", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  AB = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)AB, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LSB = SUNDenseLinearSolver(yB, AB);
+  if(check_flag((void *)LSB, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolverB(mem, indexB, LSB, AB);
+  if(check_flag(&flag, "IDADlsSetLinearSolverB", 1)) return(1);
 
   printf("Backward integration ... ");
 
@@ -241,12 +265,15 @@ int main()
   PrintOutput(time, yB, ypB);
 
   IDAFree(&mem);
-
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(yB);
-  N_VDestroy_Serial(ypB);
-  N_VDestroy_Serial(q);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB);
+  SUNMatDestroy(AB);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(yB);
+  N_VDestroy(ypB);
+  N_VDestroy(q);
 
   return(0);
 }
@@ -403,7 +430,11 @@ static int resB(realtype tt,
  */
 static void PrintOutput(realtype tfinal, N_Vector yB, N_Vector ypB)
 {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("dG/dy0: \t%12.4Le\n\t\t%12.4Le\n\t\t%12.4Le\n\t\t%12.4Le\n\t\t%12.4Le\n\t\t%12.4Le\n",
+#else
   printf("dG/dy0: \t%12.4e\n\t\t%12.4e\n\t\t%12.4e\n\t\t%12.4e\n\t\t%12.4e\n\t\t%12.4e\n",
+#endif         
          Ith(yB,1), Ith(yB,2), Ith(yB,3), Ith(yB,4), Ith(yB,5), Ith(yB,6));
   printf("--------------------------------------------------------\n\n");
 }
diff --git a/examples/idas/serial/idasAkzoNob_dns.c b/examples/idas/serial/idasAkzoNob_dns.c
index f3cd5ac..1c84ae9 100644
--- a/examples/idas/serial/idasAkzoNob_dns.c
+++ b/examples/idas/serial/idasAkzoNob_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -22,31 +18,30 @@
  * The Netherlands, and describes a chemical process in which 2 
  * species are mixed, while carbon dioxide is continuously added.
  * See http://pitagora.dm.uniba.it/~testset/report/chemakzo.pdf  
- * 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
  
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
  
-#include <idas/idas.h>
-#include <idas/idas_dense.h>
-#include <sundials/sundials_math.h>
-#include <nvector/nvector_serial.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component */
 
 /* Problem Constants */
-#define NEQ  6
+#define NEQ 6
+#define T0  RCONST(0.0)
+#define T1  RCONST(1e-8)  /* first time for output */
 
-#define T0      RCONST(0.0)
-
-#define T1      RCONST(1e-8)  /* first time for output */
-
-#define TF      RCONST(180.0) /* Final time. */
-#define NF      25            /* Total number of outputs. */ 
+#define TF  RCONST(180.0) /* Final time. */
+#define NF  25            /* Total number of outputs. */ 
 
 #define RTOL  RCONST(1.0e-08)
 #define ATOL  RCONST(1.0e-10)
@@ -83,9 +78,20 @@ int main()
   int flag;
   realtype time, tout, incr;
   int nout;
+  SUNMatrix A;
+  SUNLinearSolver LS;
+
+  /* Consistent IC for  y, y'. */
+  const realtype y01 = RCONST(0.444);
+  const realtype y02 = RCONST(0.00123);
+  const realtype y03 = RCONST(0.0);
+  const realtype y04 = RCONST(0.007);
+  const realtype y05 = RCONST(0.0);
 
   mem = NULL;
   yy = yp = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate user data. */
   data = (UserData) malloc(sizeof(*data));
@@ -107,18 +113,13 @@ int main()
   yp = N_VNew_Serial(NEQ);
   if (check_flag((void *)yp, "N_VNew_Serial", 0)) return(1);
 
-  /* Consistent IC for  y, y'. */
-#define y01 0.444
-#define y02 0.00123
-#define y03 0.00
-#define y04 0.007
-#define y05 0.0
-  Ith(yy,1) = RCONST(y01);
-  Ith(yy,2) = RCONST(y02);
-  Ith(yy,3) = RCONST(y03);
-  Ith(yy,4) = RCONST(y04);
-  Ith(yy,5) = RCONST(y05);
-  Ith(yy,6) = data->Ks * RCONST(y01) * RCONST(y04);
+  /* Set IC */
+  Ith(yy,1) = y01;
+  Ith(yy,2) = y02;
+  Ith(yy,3) = y03;
+  Ith(yy,4) = y04;
+  Ith(yy,5) = y05;
+  Ith(yy,6) = data->Ks * y01 * y04;
 
   /* Get y' = - res(t0, y, 0) */
   N_VConst(ZERO, yp);
@@ -126,7 +127,7 @@ int main()
   rr = N_VNew_Serial(NEQ);
   res(T0, yy, yp, rr, data);
   N_VScale(-ONE, rr, yp);
-  N_VDestroy_Serial(rr);
+  N_VDestroy(rr);
   
  /* Create and initialize q0 for quadratures. */
   q = N_VNew_Serial(1);
@@ -148,9 +149,18 @@ int main()
   /* Attach user data. */
   flag = IDASetUserData(mem, data);
   if(check_flag(&flag, "IDASetUserData", 1)) return(1);
-  
-  /* Attach linear solver. */
-  flag = IDADense(mem, NEQ);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
   /* Initialize QUADRATURE(S). */
   flag = IDAQuadInit(mem, rhsQ, q);
@@ -160,7 +170,7 @@ int main()
   flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
   if (check_flag(&flag, "IDAQuadSStolerances", 1)) return(1);
 
-  flag = IDASetQuadErrCon(mem, TRUE);
+  flag = IDASetQuadErrCon(mem, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
 
   PrintHeader(RTOL, ATOL, yy);
@@ -188,16 +198,21 @@ int main()
   if (check_flag(&flag, "IDAGetQuad", 1)) return(1);
 
   printf("\n--------------------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("G:          %24.16Lf \n",Ith(q,1));
+#else
   printf("G:          %24.16f \n",Ith(q,1));
+#endif  
   printf("--------------------------------------------------------\n\n");
 
   PrintFinalStats(mem);
 
   IDAFree(&mem);
-
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(q);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(q);
 
   return(0);
 }
@@ -269,7 +284,7 @@ static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_
 static void PrintHeader(realtype rtol, realtype avtol, N_Vector y)
 {
   printf("\nidasAkzoNob_dns: Akzo Nobel chemical kinetics DAE serial example problem for IDAS\n");
-  printf("Linear solver: IDADENSE, Jacobian is computed by IDAS.\n");
+  printf("Linear solver: DENSE, Jacobian is computed by IDAS.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg\n",
          rtol, avtol);
@@ -294,7 +309,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   retval = IDAGetLastOrder(mem, &kused);
   check_flag(&retval, "IDAGetLastOrder", 1);
diff --git a/examples/idas/serial/idasAkzoNob_dns.out b/examples/idas/serial/idasAkzoNob_dns.out
index f965973..ea36ac7 100644
--- a/examples/idas/serial/idasAkzoNob_dns.out
+++ b/examples/idas/serial/idasAkzoNob_dns.out
@@ -1,6 +1,6 @@
 
 idasAkzoNob_dns: Akzo Nobel chemical kinetics DAE serial example problem for IDAS
-Linear solver: IDADENSE, Jacobian is computed by IDAS.
+Linear solver: DENSE, Jacobian is computed by IDAS.
 Tolerance parameters:  rtol = 1e-08   atol = 1e-10
 ---------------------------------------------------------------------------------
    t        y1        y2       y3       y4       y5      y6    | nst  k      h
@@ -34,7 +34,7 @@ Tolerance parameters:  rtol = 1e-08   atol = 1e-10
 1.80e+02 1.15e-01 1.20e-03 1.61e-01 3.66e-04 1.71e-02 4.87e-03 | 500  4 1.03e+00
 
 --------------------------------------------------------
-G:               31.2642162723035995 
+G:               31.2642162723034609 
 --------------------------------------------------------
 
 
diff --git a/examples/idas/serial/idasFoodWeb_bnd.c b/examples/idas/serial/idasFoodWeb_bnd.c
index 329238c..e82615f 100644
--- a/examples/idas/serial/idasFoodWeb_bnd.c
+++ b/examples/idas/serial/idasFoodWeb_bnd.c
@@ -1,14 +1,10 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example program for IDA: Food web problem.
  *
- * This example program (serial version) uses the IDABAND linear 
+ * This example program (serial version) uses the banded linear 
  * solver, and IDACalcIC for initial condition calculation.
  *
  * The mathematical problem solved in this example is a DAE system
@@ -62,7 +58,7 @@
  * The PDEs are discretized by central differencing on a MX by MY
  * mesh.
  *
- * The DAE system is solved by IDA using the IDABAND linear solver.
+ * The DAE system is solved by IDA using the banded linear solver.
  * Output is printed at t = 0, .001, .01, .1, .4, .7, 1.
  * -----------------------------------------------------------------
  * References:
@@ -80,18 +76,18 @@
  *     Consistent Initial Condition Calculation for Differential-
  *     Algebraic Systems, SIAM J. Sci. Comput., 19 (1998),
  *     pp. 1495-1512.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_band.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
 
 /* Problem Constants. */
 
@@ -136,7 +132,7 @@
 /* Type: UserData.  Contains problem constants, etc. */
 
 typedef struct {
-  long int Neq, ns, np, mx, my;
+  sunindextype Neq, ns, np, mx, my;
   realtype dx, dy, **acoef;
   realtype cox[NUM_SPECIES], coy[NUM_SPECIES], bcoef[NUM_SPECIES];
   N_Vector rates;
@@ -152,13 +148,13 @@ static int resweb(realtype time, N_Vector cc, N_Vector cp, N_Vector resval,
 static void InitUserData(UserData webdata);
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata);
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol);
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol);
 static void PrintOutput(void *mem, N_Vector c, realtype t);
 static void PrintFinalStats(void *mem);
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate, UserData webdata);
 static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                      UserData webdata);
-static realtype dotprod(long int size, realtype *x1, realtype *x2);
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /*
@@ -173,12 +169,16 @@ int main()
   UserData webdata;
   N_Vector cc, cp, id;
   int iout, retval;
-  long int mu, ml;
+  sunindextype mu, ml;
   realtype rtol, atol, t0, tout, tret;
+  SUNMatrix A;
+  SUNLinearSolver LS;
 
   mem = NULL;
   webdata = NULL;
   cc = cp = id = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate and initialize user data block webdata. */
 
@@ -224,11 +224,18 @@ int main()
   retval = IDASStolerances(mem, rtol, atol);
   if(check_flag(&retval, "IDASStolerances", 1)) return(1);
 
-  /* Call IDABand to specify the IDA linear solver. */
-
+  /* Create banded SUNMatrix for use in linear solves */
   mu = ml = NSMX;
-  retval = IDABand(mem, NEQ, mu, ml);
-  if(check_flag(&retval, "IDABand", 1)) return(1);
+  A = SUNBandMatrix(NEQ, mu, ml, mu+ml);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver object */
+  LS = SUNBandLinearSolver(cc, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
 
   /* Call IDACalcIC (with default options) to correct the initial values. */
 
@@ -261,14 +268,16 @@ int main()
   /* Free memory */
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
 
-  N_VDestroy_Serial(cc);
-  N_VDestroy_Serial(cp);
-  N_VDestroy_Serial(id);
+  N_VDestroy(cc);
+  N_VDestroy(cp);
+  N_VDestroy(id);
 
 
   destroyMat(webdata->acoef);
-  N_VDestroy_Serial(webdata->rates);
+  N_VDestroy(webdata->rates);
   free(webdata);
 
   return(0);
@@ -297,14 +306,14 @@ int main()
 static int resweb(realtype tt, N_Vector cc, N_Vector cp, 
                   N_Vector res,  void *user_data)
 {
-  long int jx, jy, is, yloc, loc, np;
+  sunindextype jx, jy, is, yloc, loc, np;
   realtype *resv, *cpv;
   UserData webdata;
   
   webdata = (UserData)user_data;
   
-  cpv = N_VGetArrayPointer_Serial(cp);
-  resv = N_VGetArrayPointer_Serial(res);
+  cpv = N_VGetArrayPointer(cp);
+  resv = N_VGetArrayPointer(res);
   np = webdata->np;
   
   /* Call Fweb to set res to vector of right-hand sides. */
@@ -393,13 +402,13 @@ static void InitUserData(UserData webdata)
 static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
                                UserData webdata)
 {
-  long int loc, yloc, is, jx, jy, np;
+  sunindextype loc, yloc, is, jx, jy, np;
   realtype xx, yy, xyfactor, fac;
   realtype *ccv, *cpv, *idv;
   
-  ccv = N_VGetArrayPointer_Serial(cc);
-  cpv = N_VGetArrayPointer_Serial(cp);
-  idv = N_VGetArrayPointer_Serial(id);
+  ccv = N_VGetArrayPointer(cc);
+  cpv = N_VGetArrayPointer(cp);
+  idv = N_VGetArrayPointer(id);
   np = webdata->np;
   
   /* Loop over grid, load cc values and id values. */
@@ -412,10 +421,10 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
       xyfactor *= xyfactor;
       loc = yloc + NUM_SPECIES*jx;
       fac = ONE + ALPHA * xx * yy + BETA * sin(FOURPI*xx) * sin(FOURPI*yy);
-      
+
       for (is = 0; is < NUM_SPECIES; is++) {
         if (is < np) {
-	    ccv[loc+is] = RCONST(10.0) + (realtype)(is+1) * xyfactor;
+          ccv[loc+is] = RCONST(10.0) + (realtype)(is+1) * xyfactor;
           idv[loc+is] = ONE;
         }
         else {
@@ -445,7 +454,7 @@ static void SetInitialProfiles(N_Vector cc, N_Vector cp, N_Vector id,
  * Print first lines of output (problem description)
  */
 
-static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
+static void PrintHeader(sunindextype mu, sunindextype ml, realtype rtol, realtype atol)
 {
   printf("\nidasFoodWeb_bnd: Predator-prey DAE serial example problem for IDA \n\n");
   printf("Number of species ns: %d", NUM_SPECIES);
@@ -458,7 +467,7 @@ static void PrintHeader(long int mu, long int ml, realtype rtol, realtype atol)
 #else
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
-  printf("Linear solver: IDABAND,  Band parameters mu = %ld, ml = %ld\n",mu,ml);
+  printf("Linear solver: BAND,  Band parameters mu = %ld, ml = %ld\n", (long int) mu, (long int) ml);
   printf("CalcIC called to correct initial predator concentrations.\n\n");
   printf("-----------------------------------------------------------\n");
   printf("  t        bottom-left  top-right");
@@ -554,7 +563,7 @@ static void PrintFinalStats(void *mem)
 static void Fweb(realtype tcalc, N_Vector cc, N_Vector crate,  
                  UserData webdata)
 { 
-  long int jx, jy, is, idyu, idyl, idxu, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxu, idxl;
   realtype xx, yy, *cxy, *ratesxy, *cratexy, dcyli, dcyui, dcxli, dcxui;
   
   /* Loop over grid points, evaluate interaction vector (length ns),
@@ -622,9 +631,9 @@ static void WebRates(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
  * dotprod: dot product routine for realtype arrays, for use by WebRates.    
  */
 
-static realtype dotprod(long int size, realtype *x1, realtype *x2)
+static realtype dotprod(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
diff --git a/examples/idas/serial/idasFoodWeb_bnd.out b/examples/idas/serial/idasFoodWeb_bnd.out
index b88210e..4e81a7f 100644
--- a/examples/idas/serial/idasFoodWeb_bnd.out
+++ b/examples/idas/serial/idasFoodWeb_bnd.out
@@ -3,7 +3,7 @@ idasFoodWeb_bnd: Predator-prey DAE serial example problem for IDA
 
 Number of species ns: 2     Mesh dimensions: 20 x 20     System size: 800
 Tolerance parameters:  rtol = 1e-05   atol = 1e-05
-Linear solver: IDABAND,  Band parameters mu = 40, ml = 40
+Linear solver: BAND,  Band parameters mu = 40, ml = 40
 CalcIC called to correct initial predator concentrations.
 
 -----------------------------------------------------------
diff --git a/examples/idas/serial/idasHeat2D_bnd.c b/examples/idas/serial/idasHeat2D_bnd.c
index 1373319..b6b2e6b 100644
--- a/examples/idas/serial/idasHeat2D_bnd.c
+++ b/examples/idas/serial/idasHeat2D_bnd.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, serial, banded.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the band solver IDABand, and IDACalcIC.
+ * This version uses the band solver and IDACalcIC.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -28,17 +24,18 @@
  * u >= 0 are posed for all components. Output is taken at
  * t = 0, .01, .02, .04, ..., 10.24. (Output at t = 0 is for
  * IDACalcIC cost statistics only.)
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_band.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix             */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver       */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
 
 /* Problem Constants */
 
@@ -53,7 +50,7 @@
 /* Type: UserData */
 
 typedef struct {
-  long int mm;
+  sunindextype mm;
   realtype dx;
   realtype coeff;
 } *UserData;
@@ -83,12 +80,17 @@ int main(void)
   UserData data;
   N_Vector uu, up, constraints, id, res;
   int ier, iout;
-  long int mu, ml, netf, ncfn;
+  long int netf, ncfn;
+  sunindextype mu, ml;
   realtype rtol, atol, t0, t1, tout, tret;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   
   mem = NULL;
   data = NULL;
   uu = up = constraints = id = res = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Create vectors uu, up, res, constraints, id. */
   uu = N_VNew_Serial(NEQ);
@@ -128,12 +130,13 @@ int main(void)
   ier = IDASetUserData(mem, data);
   if(check_flag(&ier, "IDASetUserData", 1)) return(1);
 
+  /* Set which components are algebraic or differential */
   ier = IDASetId(mem, id);
   if(check_flag(&ier, "IDASetId", 1)) return(1);
 
   ier = IDASetConstraints(mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
-  N_VDestroy_Serial(constraints);
+  N_VDestroy(constraints);
 
   ier = IDAInit(mem, heatres, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1)) return(1);
@@ -141,13 +144,21 @@ int main(void)
   ier = IDASStolerances(mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1)) return(1);
 
-  /* Call IDABand to specify the linear solver. */
+  /* Create banded SUNMatrix for use in linear solves */
   mu = MGRID; ml = MGRID;
-  ier = IDABand(mem, NEQ, mu, ml);
-  if(check_flag(&ier, "IDABand", 1)) return(1);
- 
+  A = SUNBandMatrix(NEQ, mu, ml, mu+ml);
+  if(check_flag((void *)A, "SUNBandMatrix", 0)) return(1);
+
+  /* Create banded SUNLinearSolver object */
+  LS = SUNBandLinearSolver(uu, A);
+  if(check_flag((void *)LS, "SUNBandLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  ier = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&ier, "IDADlsSetLinearSolver", 1)) return(1);
+
   /* Call IDACalcIC to correct the initial values. */
-  
+
   ier = IDACalcIC(mem, IDA_YA_YDP_INIT, t1);
   if(check_flag(&ier, "IDACalcIC", 1)) return(1);
 
@@ -176,10 +187,12 @@ int main(void)
   printf("\n netf = %ld,   ncfn = %ld \n", netf, ncfn);
 
   IDAFree(&mem);
-  N_VDestroy_Serial(uu);
-  N_VDestroy_Serial(up);
-  N_VDestroy_Serial(id);
-  N_VDestroy_Serial(res);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(uu);
+  N_VDestroy(up);
+  N_VDestroy(id);
+  N_VDestroy(res);
   free(data);
 
   return(0);
@@ -187,7 +200,7 @@ int main(void)
 
 /*
  *--------------------------------------------------------------------
- * FUNCTIONS CALLED BY KINSOL
+ * FUNCTIONS CALLED BY IDA
  *--------------------------------------------------------------------
  */
 
@@ -203,11 +216,11 @@ int main(void)
 int heatres(realtype tres, N_Vector uu, N_Vector up, N_Vector resval, 
             void *user_data)
 {
-  long int mm, i, j, offset, loc;
+  sunindextype mm, i, j, offset, loc;
   realtype *uv, *upv, *resv, coeff;
   UserData data;
   
-  uv = N_VGetArrayPointer_Serial(uu); upv = N_VGetArrayPointer_Serial(up); resv = N_VGetArrayPointer_Serial(resval);
+  uv = N_VGetArrayPointer(uu); upv = N_VGetArrayPointer(up); resv = N_VGetArrayPointer(resval);
 
   data = (UserData)user_data;
   mm = data->mm;
@@ -244,14 +257,14 @@ static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up,
                              N_Vector id, N_Vector res)
 {
   realtype xfact, yfact, *udata, *updata, *iddata;
-  long int mm, mm1, i, j, offset, loc;
+  sunindextype mm, mm1, i, j, offset, loc;
   
   mm = data->mm;
   mm1 = mm - 1;
   
-  udata = N_VGetArrayPointer_Serial(uu);
-  updata = N_VGetArrayPointer_Serial(up);
-  iddata = N_VGetArrayPointer_Serial(id);
+  udata = N_VGetArrayPointer(uu);
+  updata = N_VGetArrayPointer(up);
+  iddata = N_VGetArrayPointer(id);
 
   /* Initialize id to 1's. */
   N_VConst(ONE, id);
@@ -310,7 +323,7 @@ static void PrintHeader(realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("Linear solver: IDABAND, banded direct solver \n");
+  printf("Linear solver: BAND, banded direct solver \n");
   printf("       difference quotient Jacobian, half-bandwidths = %d \n",MGRID);
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("IDACalcIC called with input boundary values = %Lg \n",BVAL);
diff --git a/examples/idas/serial/idasHeat2D_bnd.out b/examples/idas/serial/idasHeat2D_bnd.out
index 368673a..0b5b5fc 100644
--- a/examples/idas/serial/idasHeat2D_bnd.out
+++ b/examples/idas/serial/idasHeat2D_bnd.out
@@ -6,7 +6,7 @@ idasHeat2D_bnd: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDABAND, banded direct solver 
+Linear solver: BAND, banded direct solver 
        difference quotient Jacobian, half-bandwidths = 10 
 IDACalcIC called with input boundary values = 0.1 
 
@@ -14,17 +14,17 @@ IDACalcIC called with input boundary values = 0.1
 
   time       umax     k  nst  nni  nje   nre   nreLS    h      
  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 
-  0.00   9.75461e-01  0    0    1    2     3    42   1.00e-05 
-  0.01   8.24113e-01  2   12   15   10    17   210   2.56e-03 
-  0.02   6.88124e-01  3   15   19   10    21   210   5.12e-03 
-  0.04   4.71054e-01  3   19   23   10    25   210   5.12e-03 
-  0.08   2.16451e-01  3   23   28   11    30   231   1.02e-02 
-  0.16   4.50382e-02  4   28   35   12    37   252   2.05e-02 
-  0.32   2.14520e-03  5   34   43   13    45   273   4.10e-02 
-  0.64   2.89374e-18  1   39   52   15    54   315   1.64e-01 
-  1.28   1.17136e-32  1   41   54   17    56   357   6.55e-01 
-  2.56   1.31711e-35  1   42   55   18    57   378   1.31e+00 
-  5.12   1.18294e-37  1   43   56   19    58   399   2.62e+00 
- 10.24   1.26706e-39  1   44   57   20    59   420   5.24e+00 
+  0.00   9.75461e-01  0    0    3    2     5    42   1.00e-05 
+  0.01   8.24602e-01  2   13   20    9    22   189   2.56e-03 
+  0.02   6.88908e-01  2   15   23   10    25   210   5.12e-03 
+  0.04   4.71178e-01  3   19   28   10    30   210   5.12e-03 
+  0.08   2.16305e-01  3   23   33   10    35   210   1.02e-02 
+  0.16   4.53754e-02  4   29   41   11    43   231   2.05e-02 
+  0.32   1.78933e-03  4   36   50   12    52   252   4.10e-02 
+  0.64   1.27055e-20  1   41   59   14    61   294   1.64e-01 
+  1.28   1.34319e-33  1   43   61   16    63   336   6.55e-01 
+  2.56   3.69260e-36  1   44   62   17    64   357   1.31e+00 
+  5.12   8.13278e-38  1   45   63   18    65   378   2.62e+00 
+ 10.24   9.53175e-40  1   46   64   19    66   399   5.24e+00 
 
  netf = 0,   ncfn = 0 
diff --git a/examples/idas/serial/idasHeat2D_kry.c b/examples/idas/serial/idasHeat2D_kry.c
index 5e0af54..e92626e 100644
--- a/examples/idas/serial/idasHeat2D_kry.c
+++ b/examples/idas/serial/idasHeat2D_kry.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem for IDA: 2D heat equation, serial, GMRES.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version uses the Krylov solver IDASpgmr.
+ * This version uses the Krylov solver Spgmr.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -21,24 +17,24 @@
  * system of size N = M^2. Here M = 10.
  *
  * The system is solved with IDA using the Krylov linear solver
- * IDASPGMR. The preconditioner uses the diagonal elements of the
+ * SPGMR. The preconditioner uses the diagonal elements of the
  * Jacobian only. Routines for preconditioning, required by
- * IDASPGMR, are supplied here. The constraints u >= 0 are posed
+ * SPGMR, are supplied here. The constraints u >= 0 are posed
  * for all components. Output is taken at t = 0, .01, .02, .04,
  * ..., 10.24. Two cases are run -- with the Gram-Schmidt type
  * being Modified in the first case, and Classical in the second.
- * The second run uses IDAReInit and IDAReInitSpgmr.
- * -----------------------------------------------------------------
- */
+ * The second run uses IDAReInit.
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_spgmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <idas/idas_spils.h>           /* access to IDASpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to spgmr SUNLinearSolver      */
+#include <sundials/sundials_types.h>   /* definition of type realtype          */
 
 /* Problem Constants */
 
@@ -53,7 +49,7 @@
 /* User data type */
 
 typedef struct {  
-  long int mm;  /* number of grid points */
+  sunindextype mm;  /* number of grid points */
   realtype dx;
   realtype coeff;
   N_Vector pp;  /* vector of prec. diag. elements */
@@ -66,14 +62,12 @@ int resHeat(realtype tres, N_Vector uu, N_Vector up,
 
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+               realtype c_j, void *prec_data);
 
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp);
+               realtype c_j, realtype delta, void *prec_data);
 
 /* Prototypes for private functions */
 
@@ -97,10 +91,12 @@ int main()
   int ier, iout;
   realtype rtol, atol, t0, t1, tout, tret;
   long int netf, ncfn, ncfl;
+  SUNLinearSolver LS;
 
   mem = NULL;
   data = NULL;
   uu = up = constraints = res = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors and the user data structure. */
 
@@ -153,7 +149,7 @@ int main()
 
   ier = IDASetConstraints(mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
-  N_VDestroy_Serial(constraints);
+  N_VDestroy(constraints);
 
   ier = IDAInit(mem, resHeat, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1)) return(1);
@@ -161,11 +157,20 @@ int main()
   ier = IDASStolerances(mem, rtol, atol);
   if(check_flag(&ier, "IDASStolerances", 1)) return(1);
 
-  /* Call IDASpgmr to specify the linear solver. */
+  /* Create the linear solver SUNSPGMR with left preconditioning
+     and the default Krylov dimension */
+  LS = SUNSPGMR(uu, PREC_LEFT, 0);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* IDA recommends allowing up to 5 restarts (default is 0) */
+  ier = SUNSPGMRSetMaxRestarts(LS, 5);
+  if(check_flag(&ier, "SUNSPGMRSetMaxRestarts", 1)) return(1);
 
-  ier = IDASpgmr(mem, 0);
-  if(check_flag(&ier, "IDASpgmr", 1)) return(1);
+  /* Attach the linear sovler */
+  ier = IDASpilsSetLinearSolver(mem, LS);
+  if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return(1);
 
+  /* Set the preconditioner solve and setup functions */
   ier = IDASpilsSetPreconditioner(mem, PsetupHeat, PsolveHeat);
   if(check_flag(&ier, "IDASpilsSetPreconditioner", 1)) return(1);
 
@@ -218,13 +223,13 @@ int main()
 
   SetInitialProfile(data, uu, up, res);
   
-  /* Re-initialize IDA and IDASPGMR */
+  /* Re-initialize IDA and SPGMR */
 
   ier = IDAReInit(mem, t0, uu, up);
   if(check_flag(&ier, "IDAReInit", 1)) return(1);
   
-  ier = IDASpilsSetGSType(mem, CLASSICAL_GS);
-  if(check_flag(&ier, "IDASpilsSetGSType",1)) return(1); 
+  ier = SUNSPGMRSetGSType(LS, CLASSICAL_GS);
+  if(check_flag(&ier, "SUNSPGMRSetGSType",1)) return(1); 
   
   /* Print case number, output table heading, and initial line of table. */
 
@@ -259,12 +264,13 @@ int main()
   /* Free Memory */
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
 
-  N_VDestroy_Serial(uu);
-  N_VDestroy_Serial(up);
-  N_VDestroy_Serial(res);
+  N_VDestroy(uu);
+  N_VDestroy(up);
+  N_VDestroy(res);
 
-  N_VDestroy_Serial(data->pp);
+  N_VDestroy(data->pp);
   free(data);
 
   return(0);
@@ -289,13 +295,13 @@ int resHeat(realtype tt,
             N_Vector uu, N_Vector up, N_Vector rr, 
             void *user_data)
 {
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
   UserData data;
   
-  uu_data = N_VGetArrayPointer_Serial(uu); 
-  up_data = N_VGetArrayPointer_Serial(up); 
-  rr_data = N_VGetArrayPointer_Serial(rr);
+  uu_data = N_VGetArrayPointer(uu); 
+  up_data = N_VGetArrayPointer(up); 
+  rr_data = N_VGetArrayPointer(rr);
 
   data = (UserData) user_data;
   
@@ -338,16 +344,15 @@ int resHeat(realtype tt,
   
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+               realtype c_j, void *prec_data)
 {
   
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *ppv, pelinv;
   UserData data;
   
-  data = (UserData) user_data;
-  ppv = N_VGetArrayPointer_Serial(data->pp);
+  data = (UserData) prec_data;
+  ppv = N_VGetArrayPointer(data->pp);
   mm = data->mm;
 
   /* Initialize the entire vector to 1., then set the interior points to the
@@ -378,11 +383,10 @@ int PsetupHeat(realtype tt,
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp)
+               realtype c_j, realtype delta, void *prec_data)
 {
   UserData data;
-  data = (UserData) user_data;
+  data = (UserData) prec_data;
   N_VProd(data->pp, rvec, zvec);
   return(0);
 }
@@ -400,13 +404,13 @@ int PsolveHeat(realtype tt,
 static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up, 
                              N_Vector res)
 {
-  long int mm, mm1, i, j, offset, loc;
+  sunindextype mm, mm1, i, j, offset, loc;
   realtype xfact, yfact, *udata, *updata;
 
   mm = data->mm;
 
-  udata = N_VGetArrayPointer_Serial(uu);
-  updata = N_VGetArrayPointer_Serial(up);
+  udata = N_VGetArrayPointer(uu);
+  updata = N_VGetArrayPointer(up);
 
   /* Initialize uu on all grid points. */ 
   mm1 = mm - 1;
@@ -461,7 +465,7 @@ static void PrintHeader(realtype rtol, realtype atol)
   printf("Tolerance parameters:  rtol = %g   atol = %g\n", rtol, atol);
 #endif
   printf("Constraints set to force all solution components >= 0. \n");
-  printf("Linear solver: IDASPGMR, preconditioner using diagonal elements. \n");
+  printf("Linear solver: SPGMR, preconditioner using diagonal elements. \n");
 }
 
 /*
diff --git a/examples/idas/serial/idasHeat2D_kry.out b/examples/idas/serial/idasHeat2D_kry.out
index 74602d7..b8ce37b 100644
--- a/examples/idas/serial/idasHeat2D_kry.out
+++ b/examples/idas/serial/idasHeat2D_kry.out
@@ -6,7 +6,7 @@ idasHeat2D_kry: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPGMR, preconditioner using diagonal elements. 
+Linear solver: SPGMR, preconditioner using diagonal elements. 
 
 
 Case 1: gsytpe = MODIFIED_GS
@@ -21,11 +21,11 @@ Case 1: gsytpe = MODIFIED_GS
   0.08   2.16509e-01  3   22   29   30    29    30   1.32e-02    9  59
   0.16   4.57687e-02  4   28   36   44    36    44   1.32e-02    9  80
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
-  0.64   0.00000e+00  1   39   51   77    51    77   1.05e-01   12 128
-  1.28   0.00000e+00  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   0.00000e+00  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   0.00000e+00  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   0.00000e+00  1   45   57   77    57    77   6.74e+00   18 134
+  0.64   5.54028e-21  1   39   51   77    51    77   1.05e-01   12 128
+  1.28   3.85107e-20  1   41   53   77    53    77   4.21e-01   14 130
+  2.56   5.00523e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   1.58940e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   5.12685e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
@@ -45,10 +45,10 @@ Case 2: gstype = CLASSICAL_GS
   0.16   4.57687e-02  4   28   36   44    36    44   1.32e-02    9  80
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
   0.64   2.15648e-20  1   39   51   77    51    77   1.05e-01   12 128
-  1.28   1.30250e-20  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   3.00951e-20  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   7.38674e-20  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   1.79685e-19  1   45   57   77    57    77   6.74e+00   18 134
+  1.28   5.77661e-20  1   41   53   77    53    77   4.21e-01   14 130
+  2.56   7.50780e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   2.26547e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   6.95460e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
diff --git a/examples/idas/serial/idasHessian_ASA_FSA.c b/examples/idas/serial/idasHessian_ASA_FSA.c
index 40d9591..8116ad3 100644
--- a/examples/idas/serial/idasHessian_ASA_FSA.c
+++ b/examples/idas/serial/idasHessian_ASA_FSA.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4809 $
- * $Date: 2016-07-18 11:16:25 -0700 (Mon, 18 Jul 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -41,21 +37,23 @@
  * Reference: D.B. Ozyurt and P.I. Barton, SISC 26(5) 1725-1743, 2005.
  *
  * Error handling was suppressed for code readibility reasons.
-*/
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 #include <stdlib.h>
 
-#include <idas/idas.h>
-#include <idas/idas_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i= 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* (i,j)-th matrix component i,j = 1..NEQ */
 
 /* Problem Constants */
 #define NEQ      3             /* number of equations                  */
@@ -117,6 +115,8 @@ static int rhsQBS2(realtype tt, N_Vector yy, N_Vector yp,
                    N_Vector *yyS, N_Vector *ypS, N_Vector yyB, N_Vector ypB,
                    N_Vector rhsBQS, void *user_dataB);
 
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+
 
 int main(int argc, char *argv[])
 {
@@ -128,7 +128,8 @@ int main(int argc, char *argv[])
   int flag, nckp, indexB1, indexB2;
   realtype G, Gm, Gp, dp1, dp2, grdG_fwd[2], grdG_bck[2], grdG_cntr[2], H11, H22;
   realtype rtolFD, atolFD;
-
+  SUNMatrix A, AB1, AB2;
+  SUNLinearSolver LS, LSB1, LSB2;
 
   /* Print problem description */
   printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n");
@@ -153,12 +154,12 @@ int main(int argc, char *argv[])
   q = N_VNew_Serial(1);
   N_VConst(ZERO, q);
 
-  yyS = N_VCloneVectorArray_Serial(NP, yy);
-  ypS = N_VCloneVectorArray_Serial(NP, yp);
+  yyS = N_VCloneVectorArray(NP, yy);
+  ypS = N_VCloneVectorArray(NP, yp);
   N_VConst(ZERO, yyS[0]); N_VConst(ZERO, yyS[1]);
   N_VConst(ZERO, ypS[0]); N_VConst(ZERO, ypS[1]);
 
-  qS = N_VCloneVectorArray_Serial(NP, q);
+  qS = N_VCloneVectorArray(NP, q);
   N_VConst(ZERO, qS[0]);
 
   ida_mem = IDACreate();
@@ -168,24 +169,36 @@ int main(int argc, char *argv[])
 
   /* Forward problem's setup. */
   flag = IDASStolerances(ida_mem, RTOL, ATOL);
-  flag = IDADense(ida_mem, NEQ);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
+
   flag = IDASetUserData(ida_mem, data);
   flag = IDASetMaxNumSteps(ida_mem, 1500);
 
   /* Quadrature's setup. */
   flag = IDAQuadInit(ida_mem, rhsQ, q);
   flag = IDAQuadSStolerances(ida_mem, RTOL, ATOL);
-  flag = IDASetQuadErrCon(ida_mem, TRUE);
+  flag = IDASetQuadErrCon(ida_mem, SUNTRUE);
 
   /* Sensitivity's setup. */
   flag = IDASensInit(ida_mem, NP, IDA_SIMULTANEOUS, resS, yyS, ypS);
   flag = IDASensEEtolerances(ida_mem);
-  flag = IDASetSensErrCon(ida_mem, TRUE);
+  flag = IDASetSensErrCon(ida_mem, SUNTRUE);
 
   /* Setup of quadrature's sensitivities */
   flag = IDAQuadSensInit(ida_mem, rhsQS, qS);
   flag = IDAQuadSensEEtolerances(ida_mem);
-  flag = IDASetQuadSensErrCon(ida_mem, TRUE); 
+  flag = IDASetQuadSensErrCon(ida_mem, SUNTRUE); 
   
   /* Initialize ASA. */
   flag = IDAAdjInit(ida_mem, 100, IDA_HERMITE);
@@ -199,14 +212,22 @@ int main(int argc, char *argv[])
 
   IDAGetQuad(ida_mem, &time, q);
   G = Ith(q,1);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("     G:    %12.4Le\n", G);
+#else
   printf("     G:    %12.4e\n", G);
+#endif  
 
   /* Sensitivities are needed for IC of backward problems. */
   IDAGetSensDky(ida_mem, tf, 0, yyS);
   IDAGetSensDky(ida_mem, tf, 1, ypS);
 
   IDAGetQuadSens(ida_mem, &time, qS);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le\n", Ith(qS[0],1), Ith(qS[1],1));
+#else
   printf("   dG/dp:  %12.4e %12.4e\n", Ith(qS[0],1), Ith(qS[1],1));
+#endif  
   printf("\n");
   /******************************
   * BACKWARD PROBLEM #1
@@ -234,7 +255,19 @@ int main(int argc, char *argv[])
   flag = IDASStolerancesB(ida_mem, indexB1, RTOLA, ATOLA);   
   flag = IDASetUserDataB(ida_mem, indexB1, data);
   flag = IDASetMaxNumStepsB(ida_mem, indexB1, 5000);
-  flag = IDADenseB(ida_mem, indexB1, 2*NEQ);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  AB1 = SUNDenseMatrix(2*NEQ, 2*NEQ);
+  if(check_flag((void *)AB1, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LSB1 = SUNDenseLinearSolver(yyB1, AB1);
+  if(check_flag((void *)LSB1, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolverB(ida_mem, indexB1, LSB1, AB1);
+  if(check_flag(&flag, "IDADlsSetLinearSolverB", 1)) return(1);
+
   flag = IDAQuadInitBS(ida_mem, indexB1, rhsQBS1, qB1);
 
   /******************************
@@ -263,7 +296,19 @@ int main(int argc, char *argv[])
   flag = IDASStolerancesB(ida_mem, indexB2, RTOLA, ATOLA);   
   flag = IDASetUserDataB(ida_mem, indexB2, data);
   flag = IDASetMaxNumStepsB(ida_mem, indexB2, 2500);
-  flag = IDADenseB(ida_mem, indexB2, 2*NEQ);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  AB2 = SUNDenseMatrix(2*NEQ, 2*NEQ);
+  if(check_flag((void *)AB2, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LSB2 = SUNDenseLinearSolver(yyB2, AB2);
+  if(check_flag((void *)LSB2, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolverB(ida_mem, indexB2, LSB2, AB2);
+  if(check_flag(&flag, "IDADlsSetLinearSolverB", 1)) return(1);
+
   flag = IDAQuadInitBS(ida_mem, indexB2, rhsQBS2, qB2);
 
   /* Integrate backward problems. */
@@ -283,16 +328,33 @@ int main(int argc, char *argv[])
 
   flag = IDAGetQuadB(ida_mem, indexB1, &time, qB1);
   flag = IDAGetQuadB(ida_mem, indexB2, &time, qB2);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le   (from backward pb. 1)\n", Ith(qB1,1), Ith(qB1,2));
+  printf("   dG/dp:  %12.4Le %12.4Le   (from backward pb. 2)\n", Ith(qB2,1), Ith(qB2,2));
+#else
   printf("   dG/dp:  %12.4e %12.4e   (from backward pb. 1)\n", Ith(qB1,1), Ith(qB1,2));
   printf("   dG/dp:  %12.4e %12.4e   (from backward pb. 2)\n", Ith(qB2,1), Ith(qB2,2));
+#endif  
 
   printf("\n");
   printf("   H = d2G/dp2:\n");
   printf("        (1)            (2)\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("  %12.4Le  %12.4Le\n", Ith(qB1,3), Ith(qB2,3));
+  printf("  %12.4Le  %12.4Le\n", Ith(qB1,4), Ith(qB2,4));
+#else
   printf("  %12.4e  %12.4e\n", Ith(qB1,3), Ith(qB2,3));
   printf("  %12.4e  %12.4e\n", Ith(qB1,4), Ith(qB2,4));
+#endif  
 
   IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB1);
+  SUNMatDestroy(AB1);
+  SUNLinSolFree(LSB2);
+  SUNMatDestroy(AB2);
+
 
   /*********************************
   * Use Finite Differences to verify
@@ -304,7 +366,11 @@ int main(int argc, char *argv[])
 
   printf("\n");
   printf("---------------------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("Finite Differences ( dp1=%6.1Le and dp2 = %6.1Le )\n", dp1, dp2);
+#else
   printf("Finite Differences ( dp1=%6.1e and dp2 = %6.1e )\n", dp1, dp2);
+#endif  
   printf("---------------------------------------------------------\n\n");
 
   ida_mem = IDACreate();
@@ -326,13 +392,25 @@ int main(int argc, char *argv[])
   atolFD = RCONST(1.0e-14);
 
   flag = IDASStolerances(ida_mem, rtolFD, atolFD);
-  flag = IDADense(ida_mem, NEQ);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
+
   flag = IDASetUserData(ida_mem, data);
   flag = IDASetMaxNumSteps(ida_mem, 10000);
 
   flag = IDAQuadInit(ida_mem, rhsQ, q);
   flag = IDAQuadSStolerances(ida_mem, rtolFD, atolFD);
-  flag = IDASetQuadErrCon(ida_mem, TRUE);
+  flag = IDASetQuadErrCon(ida_mem, SUNTRUE);
 
   flag = IDASolve(ida_mem, tf, &time, yy, yp, IDA_NORMAL);
   flag = IDAGetQuad(ida_mem, &time, q);
@@ -402,30 +480,40 @@ int main(int argc, char *argv[])
 
 
   printf("\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le  %12.4Le   (fwd FD)\n",  grdG_fwd[0],  grdG_fwd[1]);
+  printf("           %12.4Le  %12.4Le   (bck FD)\n",  grdG_bck[0],  grdG_bck[1]);
+  printf("           %12.4Le  %12.4Le   (cntr FD)\n", grdG_cntr[0], grdG_cntr[1]);
+  printf("\n");
+  printf("  H(1,1):  %12.4Le\n", H11);
+  printf("  H(2,2):  %12.4Le\n", H22);
+#else
   printf("   dG/dp:  %12.4e  %12.4e   (fwd FD)\n",  grdG_fwd[0],  grdG_fwd[1]);
   printf("           %12.4e  %12.4e   (bck FD)\n",  grdG_bck[0],  grdG_bck[1]);
   printf("           %12.4e  %12.4e   (cntr FD)\n", grdG_cntr[0], grdG_cntr[1]);
   printf("\n");
   printf("  H(1,1):  %12.4e\n", H11);
   printf("  H(2,2):  %12.4e\n", H22);
+#endif  
 
   IDAFree(&ida_mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
 
-  N_VDestroy_Serial(yyB1);
-  N_VDestroy_Serial(ypB1);
-  N_VDestroy_Serial(qB1);
+  N_VDestroy(yyB1);
+  N_VDestroy(ypB1);
+  N_VDestroy(qB1);
 
-  N_VDestroy_Serial(yyB2);
-  N_VDestroy_Serial(ypB2);
-  N_VDestroy_Serial(qB2);
+  N_VDestroy(yyB2);
+  N_VDestroy(ypB2);
+  N_VDestroy(qB2);
 
-
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(q);
-  N_VDestroyVectorArray_Serial(yyS, NP);
-  N_VDestroyVectorArray_Serial(ypS, NP);
-  N_VDestroyVectorArray_Serial(qS, NP);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(q);
+  N_VDestroyVectorArray(yyS, NP);
+  N_VDestroyVectorArray(ypS, NP);
+  N_VDestroyVectorArray(qS, NP);
 
   free(data);
   return 0;
@@ -441,7 +529,7 @@ static int res(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_
 
   y1  = Ith(yy,1); y2  = Ith(yy,2); y3  = Ith(yy,3); 
   yp1 = Ith(yp,1); yp2 = Ith(yp,2); yp3 = Ith(yp,3);
-  rval = N_VGetArrayPointer_Serial(rr);
+  rval = N_VGetArrayPointer(rr);
 
   data = (UserData) user_data;
   p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
@@ -739,3 +827,41 @@ static int rhsQBS2(realtype tt,
 
   return(0);
 }
+
+/* 
+ * Check function return value.
+ *    opt == 0 means SUNDIALS function allocates memory so check if
+ *             returned NULL pointer
+ *    opt == 1 means SUNDIALS function returns a flag so check if
+ *             flag >= 0
+ *    opt == 2 means function allocates memory so check if returned
+ *             NULL pointer 
+ */
+
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
+  if (opt == 0 && flagvalue == NULL) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return(1); }
+
+  /* Check if flag < 0 */
+  else if (opt == 1) {
+    errflag = (int *) flagvalue;
+    if (*errflag < 0) {
+      fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return(1); }}
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  else if (opt == 2 && flagvalue == NULL) {
+    fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return(1); }
+
+  return(0);
+}
+
diff --git a/examples/idas/serial/idasKrylovDemo_ls.c b/examples/idas/serial/idasKrylovDemo_ls.c
index 42e819e..845dcad 100644
--- a/examples/idas/serial/idasKrylovDemo_ls.c
+++ b/examples/idas/serial/idasKrylovDemo_ls.c
@@ -1,9 +1,6 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh and Radu Serban @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): Allan Taylor, Alan Hindmarsh and
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  *
  * This example loops through the available iterative linear solvers:
@@ -12,8 +9,8 @@
  * Example problem for IDA: 2D heat equation, serial, GMRES.
  *
  * This example solves a discretized 2D heat equation problem.
- * This version loops through the Krylov solvers IDASpgmr, IDASpbcg
- * and IDASptfqmr.
+ * This version loops through the Krylov solvers Spgmr, Spbcg
+ * and Sptfqmr.
  *
  * The DAE system solved is a spatial discretization of the PDE
  *          du/dt = d^2u/dx^2 + d^2u/dy^2
@@ -25,24 +22,24 @@
  * system of size N = M^2. Here M = 10.
  *
  * The system is solved with IDA using the following Krylov
- * linear solvers: IDASPGMR, IDASPBCG and IDASPTFQMR. The
+ * linear solvers: SPGMR, SPBCG and SPTFQMR. The
  * preconditioner uses the diagonal elements of the Jacobian only.
- * Routines for preconditioning, required by IDASP*, are supplied
+ * Routines for preconditioning, required by SP*, are supplied
  * here. The constraints u >= 0 are posed for all components. Output
  * is taken at t = 0, .01, .02, .04,..., 10.24.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_spgmr.h>
-#include <idas/idas_spbcgs.h>
-#include <idas/idas_sptfqmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
+#include <idas/idas.h>                   /* main integrator header file       */
+#include <idas/idas_spils.h>             /* access to IDASpils interface      */
+#include <sunlinsol/sunlinsol_spgmr.h>   /* access to SPGMR SUNLinearSolver   */
+#include <sunlinsol/sunlinsol_spbcgs.h>  /* access to SPBCGS SUNLinearSolver  */
+#include <sunlinsol/sunlinsol_sptfqmr.h> /* access to SPTFQMR SUNLinearSolver */
+#include <nvector/nvector_serial.h>      /* serial N_Vector types, fct. and macros */
+#include <sundials/sundials_types.h>     /* definition of realtype */
 
 /* Problem Constants */
 
@@ -63,7 +60,7 @@
 /* User data type */
 
 typedef struct {  
-  long int mm;  /* number of grid points */
+  sunindextype mm;  /* number of grid points */
   realtype dx;
   realtype coeff;
   N_Vector pp;  /* vector of prec. diag. elements */
@@ -76,14 +73,12 @@ int resHeat(realtype tres, N_Vector uu, N_Vector up,
 
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+               realtype c_j, void *user_data);
 
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp);
+               realtype c_j, realtype delta, void *user_data);
 
 /* Prototypes for private functions */
 
@@ -107,10 +102,12 @@ int main(void)
   int ier, iout, linsolver;
   realtype rtol, atol, t0, t1, tout, tret;
   long int netf, ncfn, ncfl;
+  SUNLinearSolver LS;
 
   mem = NULL;
   data = NULL;
   uu = up = constraints = res = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors and the user data structure. */
 
@@ -163,7 +160,7 @@ int main(void)
 
   ier = IDASetConstraints(mem, constraints);
   if(check_flag(&ier, "IDASetConstraints", 1)) return(1);
-  N_VDestroy_Serial(constraints);
+  N_VDestroy(constraints);
 
   ier = IDAInit(mem, resHeat, t0, uu, up);
   if(check_flag(&ier, "IDAInit", 1)) return(1);
@@ -196,9 +193,14 @@ int main(void)
       printf(" \n| SPGMR |\n");
       printf(" -------\n");
 
-      /* Call IDASpgmr to specify the linear solver. */
-      ier = IDASpgmr(mem, 0);
-      if(check_flag(&ier, "IDASpgmr", 1)) return(1);
+      /* Call SUNSPGMR to specify the linear solver SPGMR with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPGMR(uu, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+      /* Attach the linear solver */
+      ier = IDASpilsSetLinearSolver(mem, LS);
+      if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -207,12 +209,17 @@ int main(void)
 
       /* Print header */
       printf(" -------");
-      printf(" \n| SPBCG |\n");
+      printf(" \n| SPBCGS |\n");
       printf(" -------\n");
 
-      /* Call IDASpbcg to specify the linear solver. */
-      ier = IDASpbcg(mem, 0);
-      if(check_flag(&ier, "IDASpbcg", 1)) return(1);
+      /* Call SUNSPBCGS to specify the linear solver SPBCGS with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPBCGS(uu, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPBCGS", 0)) return(1);
+
+      /* Attach the linear solver */
+      ier = IDASpilsSetLinearSolver(mem, LS);
+      if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -224,9 +231,14 @@ int main(void)
       printf(" \n| SPTFQMR |\n");
       printf(" ---------\n");
 
-      /* Call IDASptfqmr to specify the linear solver. */
-      ier = IDASptfqmr(mem, 0);
-      if(check_flag(&ier, "IDASptfqmr", 1)) return(1);
+      /* Call SUNSPTFQMR to specify the linear solver SPTFQMR with
+         left preconditioning and the default maximum Krylov dimension */
+      LS = SUNSPTFQMR(uu, PREC_LEFT, 0);
+      if(check_flag((void *)LS, "SUNSPTFQMR", 0)) return(1);
+
+      /* Attach the linear solver */
+      ier = IDASpilsSetLinearSolver(mem, LS);
+      if(check_flag(&ier, "IDASpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -275,12 +287,13 @@ int main(void)
   /* Free Memory */
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
 
-  N_VDestroy_Serial(uu);
-  N_VDestroy_Serial(up);
-  N_VDestroy_Serial(res);
+  N_VDestroy(uu);
+  N_VDestroy(up);
+  N_VDestroy(res);
 
-  N_VDestroy_Serial(data->pp);
+  N_VDestroy(data->pp);
   free(data);
 
   return(0);
@@ -305,13 +318,13 @@ int resHeat(realtype tt,
             N_Vector uu, N_Vector up, N_Vector rr, 
             void *user_data)
 {
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *uu_data, *up_data, *rr_data, coeff, dif1, dif2;
   UserData data;
   
-  uu_data = N_VGetArrayPointer_Serial(uu); 
-  up_data = N_VGetArrayPointer_Serial(up); 
-  rr_data = N_VGetArrayPointer_Serial(rr);
+  uu_data = N_VGetArrayPointer(uu); 
+  up_data = N_VGetArrayPointer(up); 
+  rr_data = N_VGetArrayPointer(rr);
 
   data = (UserData) user_data;
   
@@ -354,16 +367,15 @@ int resHeat(realtype tt,
   
 int PsetupHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
-               realtype c_j, void *user_data, 
-               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+               realtype c_j, void *user_data)
 {
   
-  long int i, j, offset, loc, mm;
+  sunindextype i, j, offset, loc, mm;
   realtype *ppv, pelinv;
   UserData data;
   
   data = (UserData) user_data;
-  ppv = N_VGetArrayPointer_Serial(data->pp);
+  ppv = N_VGetArrayPointer(data->pp);
   mm = data->mm;
 
   /* Initialize the entire vector to 1., then set the interior points to the
@@ -394,8 +406,7 @@ int PsetupHeat(realtype tt,
 int PsolveHeat(realtype tt, 
                N_Vector uu, N_Vector up, N_Vector rr, 
                N_Vector rvec, N_Vector zvec, 
-               realtype c_j, realtype delta, void *user_data, 
-               N_Vector tmp)
+               realtype c_j, realtype delta, void *user_data)
 {
   UserData data;
   data = (UserData) user_data;
@@ -416,13 +427,13 @@ int PsolveHeat(realtype tt,
 static int SetInitialProfile(UserData data, N_Vector uu, N_Vector up, 
                              N_Vector res)
 {
-  long int mm, mm1, i, j, offset, loc;
+  sunindextype mm, mm1, i, j, offset, loc;
   realtype xfact, yfact, *udata, *updata;
 
   mm = data->mm;
 
-  udata = N_VGetArrayPointer_Serial(uu);
-  updata = N_VGetArrayPointer_Serial(up);
+  udata = N_VGetArrayPointer(uu);
+  updata = N_VGetArrayPointer(up);
 
   /* Initialize uu on all grid points. */ 
   mm1 = mm - 1;
@@ -481,15 +492,15 @@ static void PrintHeader(realtype rtol, realtype atol, int linsolver)
   switch(linsolver) {
 
   case(USE_SPGMR):
-    printf("Linear solver: IDASPGMR, preconditioner using diagonal elements. \n");
+    printf("Linear solver: SPGMR, preconditioner using diagonal elements. \n");
     break;
 
   case(USE_SPBCG):
-    printf("Linear solver: IDASPBCG, preconditioner using diagonal elements. \n");
+    printf("Linear solver: SPBCG, preconditioner using diagonal elements. \n");
     break;
 
   case(USE_SPTFQMR):
-    printf("Linear solver: IDASPTFQMR, preconditioner using diagonal elements. \n");
+    printf("Linear solver: SPTFQMR, preconditioner using diagonal elements. \n");
     break;
   }
 }
diff --git a/examples/idas/serial/idasKrylovDemo_ls.out b/examples/idas/serial/idasKrylovDemo_ls.out
index ecdb3b8..460d154 100644
--- a/examples/idas/serial/idasKrylovDemo_ls.out
+++ b/examples/idas/serial/idasKrylovDemo_ls.out
@@ -9,7 +9,7 @@ idasKrylovDemo_ls: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPGMR, preconditioner using diagonal elements. 
+Linear solver: SPGMR, preconditioner using diagonal elements. 
 
    Output Summary (umax = max-norm of solution) 
 
@@ -21,11 +21,11 @@ Linear solver: IDASPGMR, preconditioner using diagonal elements.
   0.08   2.16509e-01  3   22   29   30    29    30   1.32e-02    9  59
   0.16   4.57687e-02  4   28   36   44    36    44   1.32e-02    9  80
   0.32   2.09938e-03  4   35   44   67    44    67   2.63e-02   10 111
-  0.64   0.00000e+00  1   39   51   77    51    77   1.05e-01   12 128
-  1.28   0.00000e+00  1   41   53   77    53    77   4.21e-01   14 130
-  2.56   0.00000e+00  1   43   55   77    55    77   1.69e+00   16 132
-  5.12   0.00000e+00  1   44   56   77    56    77   3.37e+00   17 133
- 10.24   0.00000e+00  1   45   57   77    57    77   6.74e+00   18 134
+  0.64   5.54028e-21  1   39   51   77    51    77   1.05e-01   12 128
+  1.28   3.85107e-20  1   41   53   77    53    77   4.21e-01   14 130
+  2.56   5.00523e-20  1   43   55   77    55    77   1.69e+00   16 132
+  5.12   1.58940e-19  1   44   56   77    56    77   3.37e+00   17 133
+ 10.24   5.12685e-19  1   45   57   77    57    77   6.74e+00   18 134
 
 Error test failures            = 1
 Nonlinear convergence failures = 0
@@ -34,7 +34,7 @@ Linear convergence failures    = 0
 ======================================================================
 
  ------- 
-| SPBCG |
+| SPBCGS |
  -------
 
 idasKrylovDemo_ls: Heat equation, serial example problem for IDA
@@ -44,7 +44,7 @@ idasKrylovDemo_ls: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPBCG, preconditioner using diagonal elements. 
+Linear solver: SPBCG, preconditioner using diagonal elements. 
 
    Output Summary (umax = max-norm of solution) 
 
@@ -79,7 +79,7 @@ idasKrylovDemo_ls: Heat equation, serial example problem for IDA
 
 Tolerance parameters:  rtol = 0   atol = 0.001
 Constraints set to force all solution components >= 0. 
-Linear solver: IDASPTFQMR, preconditioner using diagonal elements. 
+Linear solver: SPTFQMR, preconditioner using diagonal elements. 
 
    Output Summary (umax = max-norm of solution) 
 
@@ -91,11 +91,11 @@ Linear solver: IDASPTFQMR, preconditioner using diagonal elements.
   0.08   2.16481e-01  3   23   27   57    27    57   1.02e-02    9  96
   0.16   4.51083e-02  4   27   33   84    33    84   2.05e-02   10 133
   0.32   1.78483e-03  4   34   42  139    42   139   4.10e-02   11 204
-  0.64   4.07887e-04  1   39   51  183    51   183   1.47e-01   13 262
-  1.28   4.59662e-04  1   41   54  199    54   199   5.90e-01   15 282
-  2.56   2.03940e-05  1   43   56  202    56   202   1.18e+00   16 288
-  5.12   9.56073e-21  1   45   58  202    58   202   2.36e+00   17 290
- 10.24   5.70363e-20  1   46   59  202    59   202   4.72e+00   18 291
+  0.64   3.99803e-04  1   39   51  182    51   182   1.47e-01   13 261
+  1.28   4.56475e-04  1   41   54  198    54   198   5.90e-01   15 281
+  2.56   7.30003e-05  1   43   56  200    56   200   1.18e+00   16 285
+  5.12   1.27643e-20  1   44   57  200    57   200   2.36e+00   17 286
+ 10.24   3.22610e-20  1   45   58  200    58   200   4.72e+00   18 287
 
 Error test failures            = 0
 Nonlinear convergence failures = 0
diff --git a/examples/idas/serial/idasRoberts_ASAi_dns.c b/examples/idas/serial/idasRoberts_ASAi_dns.c
index ad3dacd..b74a99c 100644
--- a/examples/idas/serial/idasRoberts_ASAi_dns.c
+++ b/examples/idas/serial/idasRoberts_ASAi_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -50,22 +46,23 @@
  * where
  *   d(phi)/dt = g(t,y,p)
  *   phi(t1) = 0
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <idas/idas.h>
-#include <idas/idas_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
-#define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i= 1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* (i,j)-th matrix component i,j = 1..NEQ */
+#define Ith(v,i)    NV_Ith_S(v,i-1)         /* i-th vector component i= 1..NEQ */
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* (i,j)-th matrix component i,j = 1..NEQ */
 
 /* Problem Constants */
 
@@ -106,9 +103,9 @@ typedef struct {
 
 static int res(realtype t, N_Vector yy, N_Vector yp, 
                N_Vector resval, void *user_data);
-static int Jac(long int Neq, realtype t, realtype cj, 
+static int Jac(realtype t, realtype cj, 
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               DlsMat J, void *user_data, 
+               SUNMatrix J, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data);
@@ -119,10 +116,10 @@ static int resB(realtype tt,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB,
                 void *user_dataB);
 
-static int JacB(long int NeqB, realtype tt, realtype cjB,
+static int JacB(realtype tt, realtype cjB,
                 N_Vector yy, N_Vector yp,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                DlsMat JB, void *user_data,
+                SUNMatrix JB, void *user_data,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
 
 
@@ -146,6 +143,8 @@ int main(int argc, char *argv[])
   UserData data;
 
   void *ida_mem;
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
 
   realtype reltolQ, abstolQ;
   N_Vector yy, yp, q;
@@ -168,6 +167,8 @@ int main(int argc, char *argv[])
   data = NULL;
   ckpnt = NULL;
   ida_mem = NULL;
+  A = AB = NULL;
+  LS = LSB = NULL;
   yy = yp = yB = qB = NULL;
 
   /* Print problem description */
@@ -225,11 +226,21 @@ int main(int argc, char *argv[])
   flag = IDASetUserData(ida_mem, data);
   if (check_flag(&flag, "IDASetUserData", 1)) return(1);
 
-  flag = IDADense(ida_mem, NEQ);
-  if (check_flag(&flag, "IDADense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
 
-  flag = IDADlsSetDenseJacFn(ida_mem, Jac);
-  if (check_flag(&flag, "IDADlsSetDenseJacFn", 1)) return(1);
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFn(ida_mem, Jac);
+  if(check_flag(&flag, "IDADlsSetJacFn", 1)) return(1);
 
   flag = IDAQuadInit(ida_mem, rhsQ, q);
   if (check_flag(&flag, "IDAQuadInit", 1)) return(1);
@@ -237,7 +248,7 @@ int main(int argc, char *argv[])
   flag = IDAQuadSStolerances(ida_mem, reltolQ, abstolQ);
   if (check_flag(&flag, "IDAQuadSStolerances", 1)) return(1);
 
-  flag = IDASetQuadErrCon(ida_mem, TRUE);
+  flag = IDASetQuadErrCon(ida_mem, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
 
   /* Allocate global memory */
@@ -354,12 +365,21 @@ int main(int argc, char *argv[])
 
   flag = IDASetMaxNumStepsB(ida_mem, indexB, 1000);
 
-  flag = IDADenseB(ida_mem, indexB, NEQ);
-  if (check_flag(&flag, "IDADenseB", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  AB = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)AB, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LSB = SUNDenseLinearSolver(yB, AB);
+  if(check_flag((void *)LSB, "SUNDenseLinearSolver", 0)) return(1);
 
-  flag = IDADlsSetDenseJacFnB(ida_mem, indexB, JacB);
-  if (check_flag(&flag, "IDASetDenseJacB", 1)) return(1);
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolverB(ida_mem, indexB, LSB, AB);
+  if(check_flag(&flag, "IDADlsSetLinearSolverB", 1)) return(1);
 
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFnB(ida_mem, indexB, JacB);
+  if(check_flag(&flag, "IDADlsSetJacFnB", 1)) return(1);
 
   /* Quadrature for backward problem. */
  
@@ -377,7 +397,7 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "IDAQuadSStolerancesB", 1)) return(1);
 
   /* Include quadratures in error control. */
-  flag = IDASetQuadErrConB(ida_mem, indexB, TRUE);
+  flag = IDASetQuadErrConB(ida_mem, indexB, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrConB", 1)) return(1);
 
 
@@ -464,15 +484,19 @@ int main(int argc, char *argv[])
   printf("Free memory\n\n");
 
   IDAFree(&ida_mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(q);
-  N_VDestroy_Serial(yB);
-  N_VDestroy_Serial(ypB);
-  N_VDestroy_Serial(qB);
-  N_VDestroy_Serial(id);
-  N_VDestroy_Serial(yyTB1);
-  N_VDestroy_Serial(ypTB1);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB);
+  SUNMatDestroy(AB);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(q);
+  N_VDestroy(yB);
+  N_VDestroy(ypB);
+  N_VDestroy(qB);
+  N_VDestroy(id);
+  N_VDestroy(yyTB1);
+  N_VDestroy(ypTB1);
 
   if (ckpnt != NULL) free(ckpnt);
   free(data);
@@ -499,7 +523,7 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
 
   y1  = Ith(yy,1); y2  = Ith(yy,2); y3  = Ith(yy,3); 
   yp1 = Ith(yp,1); yp2 = Ith(yp,2);
-  rval = N_VGetArrayPointer_Serial(resval);
+  rval = N_VGetArrayPointer(resval);
 
   data = (UserData) user_data;
   p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
@@ -516,9 +540,9 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
  * Jacobian routine. Compute J(t,y). 
 */
 
-static int Jac(long int Neq, realtype t, realtype cj,
+static int Jac(realtype t, realtype cj,
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               DlsMat J, void *user_data, 
+               SUNMatrix J, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype y2, y3;
@@ -622,10 +646,10 @@ static int resB(realtype tt,
 }
 
 /*Jacobian for backward problem. */
-static int JacB(long int NeqB, realtype tt, realtype cj,
+static int JacB(realtype tt, realtype cj,
                 N_Vector yy, N_Vector yp,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                DlsMat JB, void *user_data,
+                SUNMatrix JB, void *user_data,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   realtype y2, y3;
diff --git a/examples/idas/serial/idasRoberts_ASAi_dns.out b/examples/idas/serial/idasRoberts_ASAi_dns.out
index 3e2a801..43edb4e 100644
--- a/examples/idas/serial/idasRoberts_ASAi_dns.out
+++ b/examples/idas/serial/idasRoberts_ASAi_dns.out
@@ -12,21 +12,21 @@ Find dG/dp for
 
 
 Create and allocate IDAS memory for forward runs
-Forward integration ... done ( nst = 816 )
+Forward integration ... done ( nst = 774 )
 --------------------------------------------------------
-G:            4.0000e+10 
+G:            4.0000e+10
 --------------------------------------------------------
 
 Create and allocate IDAS memory for backward run
-Backward integration ... done ( nst = 1272 )
+Backward integration ... done ( nst = 1303 )
 --------------------------------------------------------
 tB0:          4.0000e+10
-dG/dp:        1.4879e+06  -5.9470e+00   9.9117e-04
+dG/dp:        1.4878e+06  -5.9467e+00   9.9112e-04
 lambda(t0):  -2.4998e+01   1.6442e-03   1.0000e+00
 --------------------------------------------------------
 
 Re-initialize IDAS memory for backward run
-Backward integration ... done ( nst = 399 )
+Backward integration ... done ( nst = 416 )
 --------------------------------------------------------
 tB0:          5.0000e+01
 dG/dp:        1.7341e+02  -5.0592e-04   8.4323e-08
@@ -34,4 +34,3 @@ lambda(t0):  -7.6780e+00  -1.2758e-04   1.0000e+00
 --------------------------------------------------------
 
 Free memory
-
diff --git a/examples/idas/serial/idasRoberts_ASAi_klu.c b/examples/idas/serial/idasRoberts_ASAi_klu.c
index d845164..40d8ecf 100644
--- a/examples/idas/serial/idasRoberts_ASAi_klu.c
+++ b/examples/idas/serial/idasRoberts_ASAi_klu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Ting Yan @ SMU
  *      Based on idasRoberts_ASAi_dns.c and modified to use KLU
  * -----------------------------------------------------------------
@@ -41,18 +37,18 @@
  * where
  *   d(phi)/dt = g(t,y,p)
  *   phi(t1) = 0
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <idas/idas.h>
-#include <idas/idas_klu.h>
-#include <sundials/sundials_sparse.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <idas/idas.h>                     /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>       /* access to KLU linear solver          */
+#include <idas/idas_direct.h>              /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
@@ -99,7 +95,7 @@ static int res(realtype t, N_Vector yy, N_Vector yp,
                N_Vector resval, void *user_data);
 static int Jac(realtype t, realtype cj, 
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data);
@@ -113,7 +109,7 @@ static int resB(realtype tt,
 static int JacB(realtype tt, realtype cjB,
                 N_Vector yy, N_Vector yp,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                SlsMat JacMatB, void *user_data,
+                SUNMatrix JB, void *user_data,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
 
 
@@ -137,6 +133,8 @@ int main(int argc, char *argv[])
   UserData data;
 
   void *ida_mem;
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
 
   realtype reltolQ, abstolQ;
   N_Vector yy, yp, q;
@@ -160,6 +158,8 @@ int main(int argc, char *argv[])
   ckpnt = NULL;
   ida_mem = NULL;
   yy = yp = yB = qB = NULL;
+  A = AB = NULL;
+  LS = LSB = NULL;
 
   /* Print problem description */
   printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n");
@@ -216,20 +216,30 @@ int main(int argc, char *argv[])
   flag = IDASetUserData(ida_mem, data);
   if (check_flag(&flag, "IDASetUserData", 1)) return(1);
 
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = IDAKLU(ida_mem, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "IDAKLU", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
 
-  flag = IDASlsSetSparseJacFn(ida_mem, Jac);
-  if (check_flag(&flag, "IDASlsSetSparseJacFn", 1)) return(1);
+  /* Create KLU SUNLinearSolver object (one thread) */
+  LS = SUNKLU(yy, A);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
 
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFn(ida_mem, Jac);
+  if(check_flag(&flag, "IDADlsSetJacFn", 1)) return(1);
+  
   flag = IDAQuadInit(ida_mem, rhsQ, q);
   if (check_flag(&flag, "IDAQuadInit", 1)) return(1);
 
   flag = IDAQuadSStolerances(ida_mem, reltolQ, abstolQ);
   if (check_flag(&flag, "IDAQuadSStolerances", 1)) return(1);
 
-  flag = IDASetQuadErrCon(ida_mem, TRUE);
+  flag = IDASetQuadErrCon(ida_mem, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
 
   /* Allocate global memory */
@@ -346,12 +356,21 @@ int main(int argc, char *argv[])
 
   flag = IDASetMaxNumStepsB(ida_mem, indexB, 1000);
 
-  flag = IDAKLUB(ida_mem, indexB, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "IDAKLUB", 1)) return(1);
+  /* Create sparse SUNMatrix for use in linear solves */
+  AB = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)AB, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object (one thread) */
+  LSB = SUNKLU(yB, AB);
+  if(check_flag((void *)LSB, "SUNKLU", 0)) return(1);
 
-  flag = IDASlsSetSparseJacFnB(ida_mem, indexB, JacB);
-  if (check_flag(&flag, "IDASlsSetSparseJacB", 1)) return(1);
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolverB(ida_mem, indexB, LSB, AB);
+  if(check_flag(&flag, "IDADlsSetLinearSolverB", 1)) return(1);
 
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFnB(ida_mem, indexB, JacB);
+  if(check_flag(&flag, "IDADlsSetJacFnB", 1)) return(1);
 
   /* Quadrature for backward problem. */
  
@@ -369,7 +388,7 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "IDAQuadSStolerancesB", 1)) return(1);
 
   /* Include quadratures in error control. */
-  flag = IDASetQuadErrConB(ida_mem, indexB, TRUE);
+  flag = IDASetQuadErrConB(ida_mem, indexB, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrConB", 1)) return(1);
 
 
@@ -456,15 +475,19 @@ int main(int argc, char *argv[])
   printf("Free memory\n\n");
 
   IDAFree(&ida_mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(q);
-  N_VDestroy_Serial(yB);
-  N_VDestroy_Serial(ypB);
-  N_VDestroy_Serial(qB);
-  N_VDestroy_Serial(id);
-  N_VDestroy_Serial(yyTB1);
-  N_VDestroy_Serial(ypTB1);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB);
+  SUNMatDestroy(AB);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(q);
+  N_VDestroy(yB);
+  N_VDestroy(ypB);
+  N_VDestroy(qB);
+  N_VDestroy(id);
+  N_VDestroy(yyTB1);
+  N_VDestroy(ypTB1);
 
   if (ckpnt != NULL) free(ckpnt);
   free(data);
@@ -491,7 +514,7 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
 
   y1  = Ith(yy,1); y2  = Ith(yy,2); y3  = Ith(yy,3); 
   yp1 = Ith(yp,1); yp2 = Ith(yp,2);
-  rval = N_VGetArrayPointer_Serial(resval);
+  rval = N_VGetArrayPointer(resval);
 
   data = (UserData) user_data;
   p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
@@ -510,41 +533,52 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
 
 static int Jac(realtype t, realtype cj,
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int *colptrs;
-  int *rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(yy);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(yy);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = p1+cj;                        rowvals[0] = 0;
-  data[1] = -p1;                          rowvals[1] = 1;
-  data[2] = ONE;                          rowvals[2] = 2;
-
-  data[3] = -p2*yval[2];                  rowvals[3] = 0;
-  data[4] = p2*yval[2]+2*p3*yval[1]+cj;   rowvals[4] = 1;
-  data[5] = ONE;                          rowvals[5] = 2;
-
-  data[6] = -p2*yval[1];                  rowvals[6] = 0;
-  data[7] = p2*yval[1];                   rowvals[7] = 1;
-  data[8] = ONE;                          rowvals[8] = 2;
+  /* column 0 */
+  data[0] = p1+cj;
+  rowvals[0] = 0;
+  data[1] = -p1;
+  rowvals[1] = 1;
+  data[2] = ONE;
+  rowvals[2] = 2;
+
+  /* column 1 */
+  data[3] = -p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = p2*yval[2]+2*p3*yval[1]+cj;
+  rowvals[4] = 1;
+  data[5] = ONE;
+  rowvals[5] = 2;
+
+  /* column 2 */
+  data[6] = -p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ONE;
+  rowvals[8] = 2;
 
   return(0);
 }
@@ -629,42 +663,52 @@ static int resB(realtype tt,
 static int JacB(realtype tt, realtype cjB,
                 N_Vector yy, N_Vector yp,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                SlsMat JacMatB, void *user_data,
+                SUNMatrix JB, void *user_data,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   realtype *yvalB;
-  int* colptrsB;
-  int* rowvalsB;
-  realtype* dataB;
+  sunindextype *colptrsB = SUNSparseMatrix_IndexPointers(JB);
+  sunindextype *rowvalsB = SUNSparseMatrix_IndexValues(JB);
+  realtype *dataB = SUNSparseMatrix_Data(JB);
+
   UserData userdata;
   realtype p1, p2, p3;
  
-  yvalB = N_VGetArrayPointer_Serial(yy);
-  colptrsB = (*JacMatB->colptrs);
-  rowvalsB = (*JacMatB->rowvals);
-  dataB = JacMatB->data;
+  yvalB = N_VGetArrayPointer(yy);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMatB);
+  SUNMatZero(JB);
 
   colptrsB[0] = 0;
   colptrsB[1] = 3;
   colptrsB[2] = 6;
   colptrsB[3] = 9;
 
-  dataB[0] = -p1+cjB;                          rowvalsB[0] = 0;
-  dataB[1] = p2*yvalB[2];                      rowvalsB[1] = 1;
-  dataB[2] = p2*yvalB[1];                      rowvalsB[2] = 2;
-
-  dataB[3] = p1;;                              rowvalsB[3] = 0;
+  /* column 0 */
+  dataB[0] = -p1+cjB;
+  rowvalsB[0] = 0;
+  dataB[1] = p2*yvalB[2];
+  rowvalsB[1] = 1;
+  dataB[2] = p2*yvalB[1];
+  rowvalsB[2] = 2;
+
+  /* column 1 */
+  dataB[3] = p1;
+  rowvalsB[3] = 0;
   dataB[4] = -(p2*yvalB[2]+RCONST(2.0)*p3*yvalB[1])+cjB;
   rowvalsB[4] = 1;
-  dataB[5] = -p2*yvalB[1];                     rowvalsB[5] = 2;
-     
-  dataB[6] = -ONE;                             rowvalsB[6] = 0;
-  dataB[7] = -ONE;                             rowvalsB[7] = 1;
-  dataB[8] = -ONE;                             rowvalsB[8] = 2;
+  dataB[5] = -p2*yvalB[1];
+  rowvalsB[5] = 2;
+
+  /* column 2 */    
+  dataB[6] = -ONE;
+  rowvalsB[6] = 0;
+  dataB[7] = -ONE;
+  rowvalsB[7] = 1;
+  dataB[8] = -ONE;
+  rowvalsB[8] = 2;
 
   return(0);
 }
diff --git a/examples/idas/serial/idasRoberts_ASAi_sps.c b/examples/idas/serial/idasRoberts_ASAi_sps.c
index fb58b32..af01282 100644
--- a/examples/idas/serial/idasRoberts_ASAi_sps.c
+++ b/examples/idas/serial/idasRoberts_ASAi_sps.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Ting Yan @ SMU
  *      Based on idasRoberts_ASAi_dns.c and modified to use SuperLUMT
  * -----------------------------------------------------------------
@@ -41,18 +37,18 @@
  * where
  *   d(phi)/dt = g(t,y,p)
  *   phi(t1) = 0
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <idas/idas.h>
-#include <idas/idas_superlumt.h>
-#include <sundials/sundials_sparse.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <idas/idas.h>                     /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h> /* access to SuperLUMT linear solver    */
+#include <idas/idas_direct.h>              /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
@@ -99,7 +95,7 @@ static int res(realtype t, N_Vector yy, N_Vector yp,
                N_Vector resval, void *user_data);
 static int Jac(realtype t, realtype cj, 
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_data);
@@ -113,7 +109,7 @@ static int resB(realtype tt,
 static int JacB(realtype tt, realtype cjB,
                 N_Vector yy, N_Vector yp,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                SlsMat JacMatB, void *user_data,
+                SUNMatrix JB, void *user_data,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
 
 
@@ -137,6 +133,8 @@ int main(int argc, char *argv[])
   UserData data;
 
   void *ida_mem;
+  SUNMatrix A, AB;
+  SUNLinearSolver LS, LSB;
 
   realtype reltolQ, abstolQ;
   N_Vector yy, yp, q;
@@ -160,6 +158,8 @@ int main(int argc, char *argv[])
   ckpnt = NULL;
   ida_mem = NULL;
   yy = yp = yB = qB = NULL;
+  A = AB = NULL;
+  LS = LSB = NULL;
 
   /* Print problem description */
   printf("\nAdjoint Sensitivity Example for Chemical Kinetics\n");
@@ -216,21 +216,31 @@ int main(int argc, char *argv[])
   flag = IDASetUserData(ida_mem, data);
   if (check_flag(&flag, "IDASetUserData", 1)) return(1);
 
-  nthreads = 1;
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = IDASuperLUMT(ida_mem, nthreads, NEQ, nnz);
-  if (check_flag(&flag, "IDASuperLUMT", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT SUNLinearSolver object (one thread) */
+  nthreads = 1;
+  LS = SUNSuperLUMT(yy, A, nthreads);
+  if(check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
 
-  flag = IDASlsSetSparseJacFn(ida_mem, Jac);
-  if (check_flag(&flag, "IDASlsSetSparseJacFn", 1)) return(1);
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFn(ida_mem, Jac);
+  if(check_flag(&flag, "IDADlsSetJacFn", 1)) return(1);
+  
   flag = IDAQuadInit(ida_mem, rhsQ, q);
   if (check_flag(&flag, "IDAQuadInit", 1)) return(1);
 
   flag = IDAQuadSStolerances(ida_mem, reltolQ, abstolQ);
   if (check_flag(&flag, "IDAQuadSStolerances", 1)) return(1);
 
-  flag = IDASetQuadErrCon(ida_mem, TRUE);
+  flag = IDASetQuadErrCon(ida_mem, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrCon", 1)) return(1);
 
   /* Allocate global memory */
@@ -347,12 +357,21 @@ int main(int argc, char *argv[])
 
   flag = IDASetMaxNumStepsB(ida_mem, indexB, 1000);
 
-  flag = IDASuperLUMTB(ida_mem, indexB, nthreads, NEQ, nnz);
-  if (check_flag(&flag, "IDASuperLUMTB", 1)) return(1);
+  /* Create sparse SUNMatrix for use in linear solves */
+  AB = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)AB, "SUNSparseMatrix", 0)) return(1);
 
-  flag = IDASlsSetSparseJacFnB(ida_mem, indexB, JacB);
-  if (check_flag(&flag, "IDASlsSetSparseJacB", 1)) return(1);
+  /* Create SuperLUMT SUNLinearSolver object (one thread) */
+  LSB = SUNSuperLUMT(yB, AB, nthreads);
+  if(check_flag((void *)LSB, "SUNSuperLUMT", 0)) return(1);
 
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolverB(ida_mem, indexB, LSB, AB);
+  if(check_flag(&flag, "IDADlsSetLinearSolverB", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFnB(ida_mem, indexB, JacB);
+  if(check_flag(&flag, "IDADlsSetJacFnB", 1)) return(1);
 
   /* Quadrature for backward problem. */
  
@@ -370,7 +389,7 @@ int main(int argc, char *argv[])
   if (check_flag(&flag, "IDAQuadSStolerancesB", 1)) return(1);
 
   /* Include quadratures in error control. */
-  flag = IDASetQuadErrConB(ida_mem, indexB, TRUE);
+  flag = IDASetQuadErrConB(ida_mem, indexB, SUNTRUE);
   if (check_flag(&flag, "IDASetQuadErrConB", 1)) return(1);
 
 
@@ -457,15 +476,19 @@ int main(int argc, char *argv[])
   printf("Free memory\n\n");
 
   IDAFree(&ida_mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(q);
-  N_VDestroy_Serial(yB);
-  N_VDestroy_Serial(ypB);
-  N_VDestroy_Serial(qB);
-  N_VDestroy_Serial(id);
-  N_VDestroy_Serial(yyTB1);
-  N_VDestroy_Serial(ypTB1);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNLinSolFree(LSB);
+  SUNMatDestroy(AB);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(q);
+  N_VDestroy(yB);
+  N_VDestroy(ypB);
+  N_VDestroy(qB);
+  N_VDestroy(id);
+  N_VDestroy(yyTB1);
+  N_VDestroy(ypTB1);
 
   if (ckpnt != NULL) free(ckpnt);
   free(data);
@@ -492,7 +515,7 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
 
   y1  = Ith(yy,1); y2  = Ith(yy,2); y3  = Ith(yy,3); 
   yp1 = Ith(yp,1); yp2 = Ith(yp,2);
-  rval = N_VGetArrayPointer_Serial(resval);
+  rval = N_VGetArrayPointer(resval);
 
   data = (UserData) user_data;
   p1 = data->p[0]; p2 = data->p[1]; p3 = data->p[2];
@@ -511,41 +534,52 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
 
 static int Jac(realtype t, realtype cj,
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int *colptrs;
-  int *rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(yy);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(yy);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = p1+cj;                        rowvals[0] = 0;
-  data[1] = -p1;                          rowvals[1] = 1;
-  data[2] = ONE;                          rowvals[2] = 2;
-
-  data[3] = -p2*yval[2];                  rowvals[3] = 0;
-  data[4] = p2*yval[2]+2*p3*yval[1]+cj;   rowvals[4] = 1;
-  data[5] = ONE;                          rowvals[5] = 2;
-
-  data[6] = -p2*yval[1];                  rowvals[6] = 0;
-  data[7] = p2*yval[1];                   rowvals[7] = 1;
-  data[8] = ONE;                          rowvals[8] = 2;
+  /* column 0 */
+  data[0] = p1+cj;
+  rowvals[0] = 0;
+  data[1] = -p1;
+  rowvals[1] = 1;
+  data[2] = ONE;
+  rowvals[2] = 2;
+
+  /* column 1 */
+  data[3] = -p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = p2*yval[2]+2*p3*yval[1]+cj;
+  rowvals[4] = 1;
+  data[5] = ONE;
+  rowvals[5] = 2;
+
+  /* column 2 */
+  data[6] = -p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ONE;
+  rowvals[8] = 2;
 
   return(0);
 }
@@ -630,42 +664,52 @@ static int resB(realtype tt,
 static int JacB(realtype tt, realtype cjB,
                 N_Vector yy, N_Vector yp,
                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                SlsMat JacMatB, void *user_data,
+                SUNMatrix JB, void *user_data,
                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   realtype *yvalB;
-  int* colptrsB;
-  int* rowvalsB;
-  realtype* dataB;
+  sunindextype *colptrsB = SUNSparseMatrix_IndexPointers(JB);
+  sunindextype *rowvalsB = SUNSparseMatrix_IndexValues(JB);
+  realtype *dataB = SUNSparseMatrix_Data(JB);
+
   UserData userdata;
   realtype p1, p2, p3;
  
-  yvalB = N_VGetArrayPointer_Serial(yy);
-  colptrsB = (*JacMatB->colptrs);
-  rowvalsB = (*JacMatB->rowvals);
-  dataB = JacMatB->data;
+  yvalB = N_VGetArrayPointer(yy);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMatB);
+  SUNMatZero(JB);
 
   colptrsB[0] = 0;
   colptrsB[1] = 3;
   colptrsB[2] = 6;
   colptrsB[3] = 9;
 
-  dataB[0] = -p1+cjB;                          rowvalsB[0] = 0;
-  dataB[1] = p2*yvalB[2];                      rowvalsB[1] = 1;
-  dataB[2] = p2*yvalB[1];                      rowvalsB[2] = 2;
-
-  dataB[3] = p1;;                              rowvalsB[3] = 0;
+  /* column 0 */
+  dataB[0] = -p1+cjB;
+  rowvalsB[0] = 0;
+  dataB[1] = p2*yvalB[2];
+  rowvalsB[1] = 1;
+  dataB[2] = p2*yvalB[1];
+  rowvalsB[2] = 2;
+
+  /* column 1 */
+  dataB[3] = p1;
+  rowvalsB[3] = 0;
   dataB[4] = -(p2*yvalB[2]+RCONST(2.0)*p3*yvalB[1])+cjB;
   rowvalsB[4] = 1;
-  dataB[5] = -p2*yvalB[1];                     rowvalsB[5] = 2;
-     
-  dataB[6] = -ONE;                             rowvalsB[6] = 0;
-  dataB[7] = -ONE;                             rowvalsB[7] = 1;
-  dataB[8] = -ONE;                             rowvalsB[8] = 2;
+  dataB[5] = -p2*yvalB[1];
+  rowvalsB[5] = 2;
+
+  /* column 2 */    
+  dataB[6] = -ONE;
+  rowvalsB[6] = 0;
+  dataB[7] = -ONE;
+  rowvalsB[7] = 1;
+  dataB[8] = -ONE;
+  rowvalsB[8] = 2;
 
   return(0);
 }
diff --git a/examples/idas/serial/idasRoberts_FSA_dns.c b/examples/idas/serial/idasRoberts_FSA_dns.c
index 30afa2e..d7fcf5a 100644
--- a/examples/idas/serial/idasRoberts_FSA_dns.c
+++ b/examples/idas/serial/idasRoberts_FSA_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Cosmin Petra and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -25,7 +21,7 @@
  * user routine fS (of type SensRhs1Fn).
  * Any of two sensitivity methods (SIMULTANEOUS and STAGGERED can be
  * used and sensitivities may be included in the error test or not 
- *(error control set on TRUE or FALSE, respectively).
+ *(error control set on SUNTRUE or SUNFALSE, respectively).
  *
  * Execution:
  *
@@ -35,23 +31,23 @@
  *    % idasRoberts_FSA_dns -sensi sensi_meth err_con
  * where sensi_meth is one of {sim, stg} and err_con is one of
  * {t, f}.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <idas/idas.h>           /* prototypes for IDAS fcts. and consts. */
-#include <idas/idas_dense.h>
-#include <nvector/nvector_serial.h>  /* defs. of serial NVECTOR fcts. and macros  */
-#include <sundials/sundials_types.h> /* def. of type realtype */
-#include <sundials/sundials_math.h>  /* definition of ABS */
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i=1..NEQ */
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1) /* (i,j)-th matrix component i,j=1..NEQ */
 
 /* Problem Constants */
 
@@ -112,6 +108,8 @@ static int check_flag(void *flagvalue, const char *funcname, int opt);
 int main(int argc, char *argv[])
 {
   void *ida_mem;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   UserData data;
   realtype reltol, t, tout;
   N_Vector y, yp, abstol, id;
@@ -126,8 +124,10 @@ int main(int argc, char *argv[])
   N_Vector yQ, *yQS;
 
   ida_mem = NULL;
+  A       = NULL;
+  LS      = NULL;
   data    = NULL;
-  y       =  NULL;
+  y       = NULL;
   yS      = NULL;
   ypS     = NULL;
 
@@ -187,9 +187,17 @@ int main(int argc, char *argv[])
   flag = IDASetUserData(ida_mem, data);
   if (check_flag(&flag, "IDASetUserData", 1)) return(1);
 
-  /* Attach linear solver */
-  flag = IDADense(ida_mem, NEQ);
-  if (check_flag(&flag, "IDADense", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(y, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
   printf("\n3-species chemical kinetics problem\n");
 
@@ -200,12 +208,12 @@ int main(int argc, char *argv[])
     pbar[1] = data->p[1];
     pbar[2] = data->p[2];
 
-    yS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)yS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    yS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)yS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);
     
-    ypS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)ypS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    ypS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)ypS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, ypS[is]);
 
     /* 
@@ -252,7 +260,7 @@ int main(int argc, char *argv[])
 
   IDAQuadInit(ida_mem, rhsQ, yQ);
 
-  yQS = N_VCloneVectorArray_Serial(NS, yQ);
+  yQS = N_VCloneVectorArray(NS, yQ);
   for (is=0;is<NS;is++) N_VConst(ZERO, yQS[is]);  
 
   IDAQuadSensInit(ida_mem, NULL, yQS);
@@ -302,27 +310,40 @@ int main(int argc, char *argv[])
 
   printf("\nQuadrature:\n");
   IDAGetQuad(ida_mem, &t, yQ);
-  printf("G:      %10.4e\n", Ith(yQ,1)); 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("G:      %10.4Le\n", Ith(yQ,1)); 
+#else
+  printf("G:      %10.4e\n", Ith(yQ,1));
+#endif
 
   if(sensi) {
     IDAGetQuadSens(ida_mem, &t, yQS);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    printf("\nSensitivities at t=%Lg:\n",t);
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[0], 1));
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[1], 1));
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[2], 1));
+#else
     printf("\nSensitivities at t=%g:\n",t);
     printf("dG/dp1: %11.4e\n", Ith(yQS[0], 1));
     printf("dG/dp1: %11.4e\n", Ith(yQS[1], 1));
     printf("dG/dp1: %11.4e\n", Ith(yQS[2], 1));
+#endif
   }
 
   /* Print final statistics */
   PrintFinalStats(ida_mem, sensi);
 
   /* Free memory */
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
   if (sensi) {
-    N_VDestroyVectorArray_Serial(yS, NS);
+    N_VDestroyVectorArray(yS, NS);
   }
   free(data);
   IDAFree(&ida_mem);
-  N_VDestroy_Serial(yQ);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yQ);
 
   return(0);
 }
@@ -463,16 +484,16 @@ static int rhsQ(realtype t, N_Vector y, N_Vector yp,
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -489,9 +510,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -512,7 +533,7 @@ static void PrintIC(N_Vector y, N_Vector yp)
 {
   realtype* data;
 
-  data = N_VGetArrayPointer_Serial(y);
+  data = N_VGetArrayPointer(y);
   printf("\n\nConsistent IC:\n");
   printf("\ty = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -523,7 +544,7 @@ static void PrintIC(N_Vector y, N_Vector yp)
   printf("%12.4e %12.4e %12.4e \n", data[0], data[1], data[2]);
 #endif
 
-  data = N_VGetArrayPointer_Serial(yp);
+  data = N_VGetArrayPointer(yp);
   printf("\typ= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", data[0], data[1], data[2]);
@@ -538,7 +559,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(yS[0]);
+  sdata = N_VGetArrayPointer(yS[0]);
   printf("                  Sensitivity 1  ");
 
   printf("\n\ts1 = ");
@@ -549,7 +570,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[0]);
+  sdata = N_VGetArrayPointer(ypS[0]);
   printf("\ts1'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -561,7 +582,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 
 
   printf("                  Sensitivity 2  ");
-  sdata = N_VGetArrayPointer_Serial(yS[1]);
+  sdata = N_VGetArrayPointer(yS[1]);
   printf("\n\ts2 = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -570,7 +591,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[1]);
+  sdata = N_VGetArrayPointer(ypS[1]);
   printf("\ts2'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -582,7 +603,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 
 
   printf("                  Sensitivity 3  ");
-  sdata = N_VGetArrayPointer_Serial(yS[2]);
+  sdata = N_VGetArrayPointer(yS[2]);
   printf("\n\ts3 = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -591,7 +612,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[2]);
+  sdata = N_VGetArrayPointer(ypS[2]);
   printf("\ts3'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -614,7 +635,7 @@ static void PrintOutput(void *ida_mem, realtype t, N_Vector u)
   int qu, flag;
   realtype hu, *udata;
   
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
@@ -651,7 +672,7 @@ static void PrintSensOutput(N_Vector *uS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(uS[0]);
+  sdata = N_VGetArrayPointer(uS[0]);
   printf("                  Sensitivity 1  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -662,7 +683,7 @@ static void PrintSensOutput(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
   
-  sdata = N_VGetArrayPointer_Serial(uS[1]);
+  sdata = N_VGetArrayPointer(uS[1]);
   printf("                  Sensitivity 2  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -673,7 +694,7 @@ static void PrintSensOutput(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
 
-  sdata = N_VGetArrayPointer_Serial(uS[2]);
+  sdata = N_VGetArrayPointer(uS[2]);
   printf("                  Sensitivity 3  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
diff --git a/examples/idas/serial/idasRoberts_FSA_dns.out b/examples/idas/serial/idasRoberts_FSA_dns_-sensi_stg_t.out
similarity index 60%
rename from examples/idas/serial/idasRoberts_FSA_dns.out
rename to examples/idas/serial/idasRoberts_FSA_dns_-sensi_stg_t.out
index cb70bb8..6113e37 100644
--- a/examples/idas/serial/idasRoberts_FSA_dns.out
+++ b/examples/idas/serial/idasRoberts_FSA_dns_-sensi_stg_t.out
@@ -1,13 +1,13 @@
 
 3-species chemical kinetics problem
-Sensitivity: YES ( SIMULTANEOUS + FULL ERROR CONTROL )
+Sensitivity: YES ( STAGGERED + FULL ERROR CONTROL )
 
 Consistent IC:
-	y =   1.0000e+00   0.0000e+00  -7.7954e-16 
+	y =   1.0000e+00   0.0000e+00  -5.3101e-16 
 	yp=  -4.0000e-02   4.0000e-02   0.0000e+00 
                   Sensitivity 1  
-	s1 =   0.0000e+00   0.0000e+00  -1.9467e-14 
-	s1'=  -1.0000e-00   1.0000e-00   0.0000e+00 
+	s1 =   0.0000e+00   0.0000e+00  -5.1214e-14 
+	s1'=  -1.0000e+00   1.0000e+00   0.0000e+00 
                   Sensitivity 2  
 	s2 =   0.0000e+00   0.0000e+00   0.0000e+00 
 	s2'=   0.0000e+00   0.0000e+00   0.0000e+00 
@@ -19,97 +19,97 @@ Consistent IC:
 =======================================================================
      T     Q       H      NST           y1           y2           y3    
 =======================================================================
-4.000e-01  3  5.234e-02   410
-                  Solution         9.8517e-01   3.3864e-05   1.4792e-02 
-                  Sensitivity 1   -3.5590e-01   3.9026e-04   3.5551e-01 
-                  Sensitivity 2    9.5512e-08  -2.1306e-10  -9.5299e-08 
-                  Sensitivity 3   -1.5847e-11  -5.2901e-13   1.6376e-11 
+4.000e-01  5  3.779e-02   214
+                  Solution         9.8517e-01   3.3864e-05   1.4794e-02 
+                  Sensitivity 1   -3.5595e-01   3.9025e-04   3.5556e-01 
+                  Sensitivity 2    9.5423e-08  -2.1310e-10  -9.5210e-08 
+                  Sensitivity 3   -1.5832e-11  -5.2900e-13   1.6361e-11 
 -----------------------------------------------------------------------
-4.000e+00  4  1.544e-01   452
-                  Solution         9.0552e-01   2.2405e-05   9.4458e-02 
+4.000e+00  5  1.511e-01   250
+                  Solution         9.0552e-01   2.2405e-05   9.4459e-02 
                   Sensitivity 1   -1.8761e+00   1.7922e-04   1.8759e+00 
-                  Sensitivity 2    2.9614e-06  -5.8304e-10  -2.9608e-06 
-                  Sensitivity 3   -4.9335e-10  -2.7626e-13   4.9362e-10 
+                  Sensitivity 2    2.9614e-06  -5.8305e-10  -2.9608e-06 
+                  Sensitivity 3   -4.9334e-10  -2.7626e-13   4.9362e-10 
 -----------------------------------------------------------------------
-4.000e+01  4  1.280e+00   511
+4.000e+01  3  8.823e-01   352
                   Solution         7.1583e-01   9.1855e-06   2.8416e-01 
                   Sensitivity 1   -4.2476e+00   4.5912e-05   4.2475e+00 
                   Sensitivity 2    1.3731e-05  -2.3572e-10  -1.3731e-05 
                   Sensitivity 3   -2.2884e-09  -1.1381e-13   2.2885e-09 
 -----------------------------------------------------------------------
-4.000e+02  5  1.323e+01   581
+4.000e+02  4  1.008e+01   504
                   Solution         4.5052e-01   3.2229e-06   5.4948e-01 
                   Sensitivity 1   -5.9584e+00   3.5427e-06   5.9584e+00 
                   Sensitivity 2    2.2738e-05  -2.2601e-11  -2.2738e-05 
                   Sensitivity 3   -3.7897e-09  -4.9948e-14   3.7897e-09 
 -----------------------------------------------------------------------
-4.000e+03  4  9.361e+01   675
+4.000e+03  5  1.360e+02   676
                   Solution         1.8320e-01   8.9424e-07   8.1680e-01 
                   Sensitivity 1   -4.7501e+00  -5.9937e-06   4.7501e+00 
                   Sensitivity 2    1.8809e-05   2.3127e-11  -1.8809e-05 
                   Sensitivity 3   -3.1348e-09  -1.8758e-14   3.1348e-09 
 -----------------------------------------------------------------------
-4.000e+04  5  1.092e+03   763
+4.000e+04  5  6.919e+02   799
                   Solution         3.8983e-02   1.6218e-07   9.6102e-01 
                   Sensitivity 1   -1.5750e+00  -2.7620e-06   1.5750e+00 
                   Sensitivity 2    6.2875e-06   1.1002e-11  -6.2875e-06 
                   Sensitivity 3   -1.0479e-09  -4.5367e-15   1.0479e-09 
 -----------------------------------------------------------------------
-4.000e+05  5  1.116e+04   846
+4.000e+05  3  5.672e+03   926
                   Solution         4.9383e-03   1.9850e-08   9.9506e-01 
                   Sensitivity 1   -2.3633e-01  -4.5841e-07   2.3633e-01 
                   Sensitivity 2    9.4503e-07   1.8325e-12  -9.4503e-07 
                   Sensitivity 3   -1.5751e-10  -6.3625e-16   1.5751e-10 
 -----------------------------------------------------------------------
-4.000e+06  5  1.281e+05   919
-                  Solution         5.1682e-04   2.0683e-09   9.9948e-01 
+4.000e+06  3  6.729e+04  1049
+                  Solution         5.1681e-04   2.0683e-09   9.9948e-01 
                   Sensitivity 1   -2.5666e-02  -5.1061e-08   2.5666e-02 
-                  Sensitivity 2    1.0266e-07   2.0423e-13  -1.0266e-07 
-                  Sensitivity 3   -1.7110e-11  -6.8510e-17   1.7110e-11 
+                  Sensitivity 2    1.0266e-07   2.0422e-13  -1.0266e-07 
+                  Sensitivity 3   -1.7110e-11  -6.8509e-17   1.7110e-11 
 -----------------------------------------------------------------------
-4.000e+07  5  1.793e+06   974
+4.000e+07  4  1.946e+06  1123
                   Solution         5.2033e-05   2.0814e-10   9.9995e-01 
-                  Sensitivity 1   -2.5993e-03  -5.1947e-09   2.5993e-03 
+                  Sensitivity 1   -2.5992e-03  -5.1945e-09   2.5992e-03 
                   Sensitivity 2    1.0397e-08   2.0778e-14  -1.0397e-08 
                   Sensitivity 3   -1.7328e-12  -6.9320e-18   1.7328e-12 
 -----------------------------------------------------------------------
-4.000e+08  4  2.324e+07  1011
-                  Solution         5.2096e-06   2.0839e-11   9.9999e-01 
-                  Sensitivity 1   -2.6054e-04  -5.2100e-10   2.6054e-04 
-                  Sensitivity 2    1.0422e-09   2.0840e-15  -1.0422e-09 
-                  Sensitivity 3   -1.7363e-13  -6.9454e-19   1.7364e-13 
+4.000e+08  3  2.517e+07  1190
+                  Solution         5.2065e-06   2.0826e-11   9.9999e-01 
+                  Sensitivity 1   -2.6032e-04  -5.2068e-10   2.6033e-04 
+                  Sensitivity 2    1.0413e-09   2.0827e-15  -1.0413e-09 
+                  Sensitivity 3   -1.7355e-13  -6.9420e-19   1.7355e-13 
 -----------------------------------------------------------------------
-4.000e+09  3  3.664e+08  1042
-                  Solution         5.2268e-07   2.0907e-12   1.0000e-00 
-                  Sensitivity 1   -2.6168e-05  -5.2687e-11   2.6169e-05 
-                  Sensitivity 2    1.0467e-10   2.1075e-16  -1.0467e-10 
-                  Sensitivity 3   -1.7422e-14  -6.9690e-20   1.7423e-14 
+4.000e+09  3  3.215e+08  1221
+                  Solution         5.2279e-07   2.0912e-12   1.0000e+00 
+                  Sensitivity 1   -2.6139e-05  -5.2277e-11   2.6139e-05 
+                  Sensitivity 2    1.0456e-10   2.0911e-16  -1.0456e-10 
+                  Sensitivity 3   -1.7426e-14  -6.9702e-20   1.7426e-14 
 -----------------------------------------------------------------------
-4.000e+10  2  4.467e+09  1064
-                  Solution         5.1289e-08   2.0516e-13   1.0000e-00 
-                  Sensitivity 1   -2.5638e-06  -4.9912e-12   2.5638e-06 
-                  Sensitivity 2    1.0255e-11   1.9965e-17  -1.0255e-11 
-                  Sensitivity 3   -1.7096e-15  -6.8385e-21   1.7096e-15 
+4.000e+10  2  8.900e+09  1242
+                  Solution         5.2628e-08   2.1051e-13   1.0000e+00 
+                  Sensitivity 1   -2.6350e-06  -5.2772e-12   2.6350e-06 
+                  Sensitivity 2    1.0540e-11   2.1109e-17  -1.0540e-11 
+                  Sensitivity 3   -1.7544e-15  -7.0174e-21   1.7544e-15 
 -----------------------------------------------------------------------
 
 Quadrature:
 G:      4.0000e+10
 
 Sensitivities at t=4e+10:
-dG/dp1:  1.4895e+06
-dG/dp1: -5.9536e+00
-dG/dp1:  9.9196e-04
+dG/dp1:  1.4881e+06
+dG/dp1: -5.9477e+00
+dG/dp1:  9.9125e-04
 
 Final Statistics
 
-nst     =  1064
+nst     =  1242
 
-nfe     =  1702
-netf    =    19    nsetups  =   129
-nni     =  1700    ncfn     =    12
+nfe     =  1510
+netf    =     3    nsetups  =    88
+nni     =  1507    ncfn     =     0
 
-nfSe    =  1702    nfeS     =     0
-netfs   =     0    nsetupsS =     0
-nniS    =     0    ncfnS    =     0
+nfSe    =  1600    nfeS     =     0
+netfs   =     0    nsetupsS =     2
+nniS    =  1598    ncfnS    =     0
 
-nje    =   129    nfeLS     =   387
+nje    =    90    nfeLS     =   270
diff --git a/examples/idas/serial/idasRoberts_FSA_klu.c b/examples/idas/serial/idasRoberts_FSA_klu.c
index 264b41f..b2eee5d 100644
--- a/examples/idas/serial/idasRoberts_FSA_klu.c
+++ b/examples/idas/serial/idasRoberts_FSA_klu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date: $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
  *      Based on idasRoberts_FSA_dns.c and modified to use KLU
  * -----------------------------------------------------------------
@@ -26,7 +22,7 @@
  * user routine fS (of type SensRhs1Fn).
  * Any of two sensitivity methods (SIMULTANEOUS and STAGGERED can be
  * used and sensitivities may be included in the error test or not 
- *(error control set on TRUE or FALSE, respectively).
+ *(error control set on SUNTRUE or SUNFALSE, respectively).
  *
  * Execution:
  *
@@ -36,8 +32,7 @@
  *    % idasRoberts_FSA_klu -sensi sensi_meth err_con
  * where sensi_meth is one of {sim, stg} and err_con is one of
  * {t, f}.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -45,12 +40,13 @@
 
 /* Header files with a description of contents used */
 
-#include <idas/idas.h>                 /* prototypes for IDAS fcts. and consts. */
-#include <idas/idas_klu.h>             /* prototypes for IDAKLU fcts. and constants */
-#include <sundials/sundials_sparse.h>  /* defs. of SlsMat */
-#include <nvector/nvector_serial.h>    /* defs. of serial NVECTOR fcts. and macros  */
-#include <sundials/sundials_types.h>   /* def. of type realtype */
-#include <sundials/sundials_math.h>    /* definition of ABS */
+#include <idas/idas.h>                     /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>       /* access to KLU linear solver          */
+#include <idas/idas_direct.h>              /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
@@ -83,7 +79,7 @@ static int res(realtype t, N_Vector y, N_Vector yp, N_Vector resval, void *user_
 
 static int Jac(realtype t, realtype cj, 
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 static int resS(int Ns, realtype t, 
@@ -120,6 +116,8 @@ static int check_flag(void *flagvalue, char *funcname, int opt);
 int main(int argc, char *argv[])
 {
   void *ida_mem;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   UserData data;
   realtype reltol, t, tout;
   N_Vector y, yp, abstol, id;
@@ -135,9 +133,11 @@ int main(int argc, char *argv[])
 
   ida_mem = NULL;
   data    = NULL;
-  y       =  NULL;
+  y       = NULL;
   yS      = NULL;
   ypS     = NULL;
+  A       = NULL;
+  LS      = NULL;
 
   /* Process arguments */
   ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
@@ -195,13 +195,22 @@ int main(int argc, char *argv[])
   flag = IDASetUserData(ida_mem, data);
   if (check_flag(&flag, "IDASetUserData", 1)) return(1);
 
-  /* Attach linear solver */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = IDAKLU(ida_mem, NEQ, nnz, CSC_MAT);
-  if (check_flag(&flag, "IDAKLU", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object (one thread) */
+  LS = SUNKLU(y, A);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
 
-  flag = IDASlsSetSparseJacFn(ida_mem, Jac);
-  if (check_flag(&flag, "IDASlsSetSparseJacFn", 1)) return(1);
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFn(ida_mem, Jac);
+  if(check_flag(&flag, "IDADlsSetJacFn", 1)) return(1);
 
   printf("\n3-species chemical kinetics problem\n");
 
@@ -212,12 +221,12 @@ int main(int argc, char *argv[])
     pbar[1] = data->p[1];
     pbar[2] = data->p[2];
 
-    yS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)yS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    yS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)yS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);
     
-    ypS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)ypS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    ypS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)ypS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, ypS[is]);
 
     /* 
@@ -264,7 +273,7 @@ int main(int argc, char *argv[])
 
   IDAQuadInit(ida_mem, rhsQ, yQ);
 
-  yQS = N_VCloneVectorArray_Serial(NS, yQ);
+  yQS = N_VCloneVectorArray(NS, yQ);
   for (is=0;is<NS;is++) N_VConst(ZERO, yQS[is]);  
 
   IDAQuadSensInit(ida_mem, NULL, yQS);
@@ -314,27 +323,40 @@ int main(int argc, char *argv[])
 
   printf("\nQuadrature:\n");
   IDAGetQuad(ida_mem, &t, yQ);
-  printf("G:      %10.4e\n", Ith(yQ,1)); 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("G:      %10.4Le\n", Ith(yQ,1));
+#else
+  printf("G:      %10.4e\n", Ith(yQ,1));
+#endif  
 
   if(sensi) {
     IDAGetQuadSens(ida_mem, &t, yQS);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    printf("\nSensitivities at t=%Lg:\n",t);
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[0], 1));
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[1], 1));
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[2], 1));
+#else
     printf("\nSensitivities at t=%g:\n",t);
     printf("dG/dp1: %11.4e\n", Ith(yQS[0], 1));
     printf("dG/dp1: %11.4e\n", Ith(yQS[1], 1));
     printf("dG/dp1: %11.4e\n", Ith(yQS[2], 1));
+#endif    
   }
 
   /* Print final statistics */
   PrintFinalStats(ida_mem, sensi);
 
   /* Free memory */
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
   if (sensi) {
-    N_VDestroyVectorArray_Serial(yS, NS);
+    N_VDestroyVectorArray(yS, NS);
   }
   free(data);
   IDAFree(&ida_mem);
-  N_VDestroy_Serial(yQ);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yQ);
 
   return(0);
 }
@@ -381,41 +403,49 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
 
 static int Jac(realtype t, realtype cj,
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int *colptrs;
-  int *rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(yy);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(yy);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = p1+cj;                        rowvals[0] = 0;
-  data[1] = -p1;                          rowvals[1] = 1;
-  data[2] = ONE;                          rowvals[2] = 2;
-
-  data[3] = -p2*yval[2];                  rowvals[3] = 0;
-  data[4] = p2*yval[2]+2*p3*yval[1]+cj;   rowvals[4] = 1;
-  data[5] = ONE;                          rowvals[5] = 2;
-
-  data[6] = -p2*yval[1];                  rowvals[6] = 0;
-  data[7] = p2*yval[1];                   rowvals[7] = 1;
-  data[8] = ONE;                          rowvals[8] = 2;
+  data[0] = p1+cj;
+  rowvals[0] = 0;
+  data[1] = -p1;
+  rowvals[1] = 1;
+  data[2] = ONE;
+  rowvals[2] = 2;
+
+  data[3] = -p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = p2*yval[2]+2*p3*yval[1]+cj;
+  rowvals[4] = 1;
+  data[5] = ONE;
+  rowvals[5] = 2;
+
+  data[6] = -p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ONE;
+  rowvals[8] = 2;
 
   return(0);
 }
@@ -513,16 +543,16 @@ static int rhsQ(realtype t, N_Vector y, N_Vector yp,
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -539,9 +569,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -562,7 +592,7 @@ static void PrintIC(N_Vector y, N_Vector yp)
 {
   realtype* data;
 
-  data = N_VGetArrayPointer_Serial(y);
+  data = N_VGetArrayPointer(y);
   printf("\n\nConsistent IC:\n");
   printf("\ty = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -573,7 +603,7 @@ static void PrintIC(N_Vector y, N_Vector yp)
   printf("%12.4e %12.4e %12.4e \n", data[0], data[1], data[2]);
 #endif
 
-  data = N_VGetArrayPointer_Serial(yp);
+  data = N_VGetArrayPointer(yp);
   printf("\typ= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", data[0], data[1], data[2]);
@@ -588,7 +618,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(yS[0]);
+  sdata = N_VGetArrayPointer(yS[0]);
   printf("                  Sensitivity 1  ");
 
   printf("\n\ts1 = ");
@@ -599,7 +629,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[0]);
+  sdata = N_VGetArrayPointer(ypS[0]);
   printf("\ts1'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -611,7 +641,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 
 
   printf("                  Sensitivity 2  ");
-  sdata = N_VGetArrayPointer_Serial(yS[1]);
+  sdata = N_VGetArrayPointer(yS[1]);
   printf("\n\ts2 = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -620,7 +650,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[1]);
+  sdata = N_VGetArrayPointer(ypS[1]);
   printf("\ts2'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -632,7 +662,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 
 
   printf("                  Sensitivity 3  ");
-  sdata = N_VGetArrayPointer_Serial(yS[2]);
+  sdata = N_VGetArrayPointer(yS[2]);
   printf("\n\ts3 = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -641,7 +671,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[2]);
+  sdata = N_VGetArrayPointer(ypS[2]);
   printf("\ts3'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -664,7 +694,7 @@ static void PrintOutput(void *ida_mem, realtype t, N_Vector u)
   int qu, flag;
   realtype hu, *udata;
   
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
@@ -701,7 +731,7 @@ static void PrintSensOutput(N_Vector *uS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(uS[0]);
+  sdata = N_VGetArrayPointer(uS[0]);
   printf("                  Sensitivity 1  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -712,7 +742,7 @@ static void PrintSensOutput(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
   
-  sdata = N_VGetArrayPointer_Serial(uS[1]);
+  sdata = N_VGetArrayPointer(uS[1]);
   printf("                  Sensitivity 2  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -723,7 +753,7 @@ static void PrintSensOutput(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
 
-  sdata = N_VGetArrayPointer_Serial(uS[2]);
+  sdata = N_VGetArrayPointer(uS[2]);
   printf("                  Sensitivity 3  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
diff --git a/examples/idas/serial/idasRoberts_FSA_klu.out b/examples/idas/serial/idasRoberts_FSA_klu_-sensi_stg_t.out
similarity index 100%
rename from examples/idas/serial/idasRoberts_FSA_klu.out
rename to examples/idas/serial/idasRoberts_FSA_klu_-sensi_stg_t.out
diff --git a/examples/idas/serial/idasRoberts_FSA_sps.c b/examples/idas/serial/idasRoberts_FSA_sps.c
index edeafbf..fb9defe 100644
--- a/examples/idas/serial/idasRoberts_FSA_sps.c
+++ b/examples/idas/serial/idasRoberts_FSA_sps.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date: $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
  *      Based on idasRoberts_FSA_dns.c and modified to use SuperLUMT
  * -----------------------------------------------------------------
@@ -26,7 +22,7 @@
  * user routine fS (of type SensRhs1Fn).
  * Any of two sensitivity methods (SIMULTANEOUS and STAGGERED can be
  * used and sensitivities may be included in the error test or not 
- *(error control set on TRUE or FALSE, respectively).
+ *(error control set on SUNTRUE or SUNFALSE, respectively).
  *
  * Execution:
  *
@@ -36,8 +32,7 @@
  *    % idasRoberts_FSA_sps -sensi sensi_meth err_con
  * where sensi_meth is one of {sim, stg} and err_con is one of
  * {t, f}.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -45,12 +40,13 @@
 
 /* Header files with a description of contents used */
 
-#include <idas/idas.h>                 /* prototypes for IDAS fcts. and consts. */
-#include <idas/idas_superlumt.h>       /* prototypes for IDASuperLUMT fcts. and consts. */
-#include <sundials/sundials_sparse.h>  /* defs. of SlsMat */
-#include <nvector/nvector_serial.h>    /* defs. of serial NVECTOR fcts. and macros  */
-#include <sundials/sundials_types.h>   /* def. of type realtype */
-#include <sundials/sundials_math.h>    /* definition of ABS */
+#include <idas/idas.h>                     /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h> /* access to SuperLUMT linear solver    */
+#include <idas/idas_direct.h>              /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Accessor macros */
 
@@ -83,7 +79,7 @@ static int res(realtype t, N_Vector y, N_Vector yp, N_Vector resval, void *user_
 
 static int Jac(realtype t, realtype cj, 
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
 static int resS(int Ns, realtype t, 
@@ -120,6 +116,8 @@ static int check_flag(void *flagvalue, char *funcname, int opt);
 int main(int argc, char *argv[])
 {
   void *ida_mem;
+  SUNMatrix A;
+  SUNLinearSolver LS;
   UserData data;
   realtype reltol, t, tout;
   N_Vector y, yp, abstol, id;
@@ -135,9 +133,11 @@ int main(int argc, char *argv[])
 
   ida_mem = NULL;
   data    = NULL;
-  y       =  NULL;
+  y       = NULL;
   yS      = NULL;
   ypS     = NULL;
+  A       = NULL;
+  LS      = NULL;
 
   /* Process arguments */
   ProcessArgs(argc, argv, &sensi, &sensi_meth, &err_con);
@@ -195,14 +195,23 @@ int main(int argc, char *argv[])
   flag = IDASetUserData(ida_mem, data);
   if (check_flag(&flag, "IDASetUserData", 1)) return(1);
 
-  /* Attach linear solver */
-  nthreads = 1;
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  flag = IDASuperLUMT(ida_mem, nthreads, NEQ, nnz);
-  if (check_flag(&flag, "IDASuperLUMT", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT SUNLinearSolver object (one thread) */
+  nthreads = 1;
+  LS = SUNSuperLUMT(y, A, nthreads);
+  if(check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(ida_mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
-  flag = IDASlsSetSparseJacFn(ida_mem, Jac);
-  if (check_flag(&flag, "IDASlsSetSparseJacFn", 1)) return(1);
+  /* Set the user-supplied Jacobian routine */
+  flag = IDADlsSetJacFn(ida_mem, Jac);
+  if(check_flag(&flag, "IDADlsSetJacFn", 1)) return(1);
 
   printf("\n3-species chemical kinetics problem\n");
 
@@ -213,12 +222,12 @@ int main(int argc, char *argv[])
     pbar[1] = data->p[1];
     pbar[2] = data->p[2];
 
-    yS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)yS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    yS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)yS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, yS[is]);
     
-    ypS = N_VCloneVectorArray_Serial(NS, y);
-    if (check_flag((void *)ypS, "N_VCloneVectorArray_Serial", 0)) return(1);
+    ypS = N_VCloneVectorArray(NS, y);
+    if (check_flag((void *)ypS, "N_VCloneVectorArray", 0)) return(1);
     for (is=0;is<NS;is++) N_VConst(ZERO, ypS[is]);
 
     /* 
@@ -265,7 +274,7 @@ int main(int argc, char *argv[])
 
   IDAQuadInit(ida_mem, rhsQ, yQ);
 
-  yQS = N_VCloneVectorArray_Serial(NS, yQ);
+  yQS = N_VCloneVectorArray(NS, yQ);
   for (is=0;is<NS;is++) N_VConst(ZERO, yQS[is]);  
 
   IDAQuadSensInit(ida_mem, NULL, yQS);
@@ -315,27 +324,40 @@ int main(int argc, char *argv[])
 
   printf("\nQuadrature:\n");
   IDAGetQuad(ida_mem, &t, yQ);
-  printf("G:      %10.4e\n", Ith(yQ,1)); 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("G:      %10.4Le\n", Ith(yQ,1));
+#else
+  printf("G:      %10.4e\n", Ith(yQ,1));
+#endif  
 
   if(sensi) {
     IDAGetQuadSens(ida_mem, &t, yQS);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    printf("\nSensitivities at t=%Lg:\n",t);
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[0], 1));
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[1], 1));
+    printf("dG/dp1: %11.4Le\n", Ith(yQS[2], 1));
+#else
     printf("\nSensitivities at t=%g:\n",t);
     printf("dG/dp1: %11.4e\n", Ith(yQS[0], 1));
     printf("dG/dp1: %11.4e\n", Ith(yQS[1], 1));
     printf("dG/dp1: %11.4e\n", Ith(yQS[2], 1));
+#endif    
   }
 
   /* Print final statistics */
   PrintFinalStats(ida_mem, sensi);
 
   /* Free memory */
-  N_VDestroy_Serial(y);
+  N_VDestroy(y);
   if (sensi) {
-    N_VDestroyVectorArray_Serial(yS, NS);
+    N_VDestroyVectorArray(yS, NS);
   }
   free(data);
   IDAFree(&ida_mem);
-  N_VDestroy_Serial(yQ);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yQ);
 
   return(0);
 }
@@ -382,41 +404,49 @@ static int res(realtype t, N_Vector yy, N_Vector yp, N_Vector resval, void *user
 
 static int Jac(realtype t, realtype cj,
                N_Vector yy, N_Vector yp, N_Vector resvec, 
-               SlsMat JacMat, void *user_data, 
+               SUNMatrix JJ, void *user_data, 
                N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
   realtype *yval;
-  int *colptrs;
-  int *rowvals;
-  realtype* data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
   UserData userdata;
   realtype p1, p2, p3;
  
-  yval = N_VGetArrayPointer_Serial(yy);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data = JacMat->data;
+  yval = N_VGetArrayPointer(yy);
+
   userdata = (UserData) user_data;
   p1 = userdata->p[0]; p2 = userdata->p[1]; p3 = userdata->p[2];
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  data[0] = p1+cj;                        rowvals[0] = 0;
-  data[1] = -p1;                          rowvals[1] = 1;
-  data[2] = ONE;                          rowvals[2] = 2;
-
-  data[3] = -p2*yval[2];                  rowvals[3] = 0;
-  data[4] = p2*yval[2]+2*p3*yval[1]+cj;   rowvals[4] = 1;
-  data[5] = ONE;                          rowvals[5] = 2;
-
-  data[6] = -p2*yval[1];                  rowvals[6] = 0;
-  data[7] = p2*yval[1];                   rowvals[7] = 1;
-  data[8] = ONE;                          rowvals[8] = 2;
+  data[0] = p1+cj;
+  rowvals[0] = 0;
+  data[1] = -p1;
+  rowvals[1] = 1;
+  data[2] = ONE;
+  rowvals[2] = 2;
+
+  data[3] = -p2*yval[2];
+  rowvals[3] = 0;
+  data[4] = p2*yval[2]+2*p3*yval[1]+cj;
+  rowvals[4] = 1;
+  data[5] = ONE;
+  rowvals[5] = 2;
+
+  data[6] = -p2*yval[1];
+  rowvals[6] = 0;
+  data[7] = p2*yval[1];
+  rowvals[7] = 1;
+  data[8] = ONE;
+  rowvals[8] = 2;
 
   return(0);
 }
@@ -514,16 +544,16 @@ static int rhsQ(realtype t, N_Vector y, N_Vector yp,
 static void ProcessArgs(int argc, char *argv[], 
                         booleantype *sensi, int *sensi_meth, booleantype *err_con)
 {
-  *sensi = FALSE;
+  *sensi = SUNFALSE;
   *sensi_meth = -1;
-  *err_con = FALSE;
+  *err_con = SUNFALSE;
 
   if (argc < 2) WrongArgs(argv[0]);
 
   if (strcmp(argv[1],"-nosensi") == 0)
-    *sensi = FALSE;
+    *sensi = SUNFALSE;
   else if (strcmp(argv[1],"-sensi") == 0)
-    *sensi = TRUE;
+    *sensi = SUNTRUE;
   else
     WrongArgs(argv[0]);
   
@@ -540,9 +570,9 @@ static void ProcessArgs(int argc, char *argv[],
       WrongArgs(argv[0]);
 
     if (strcmp(argv[3],"t") == 0)
-      *err_con = TRUE;
+      *err_con = SUNTRUE;
     else if (strcmp(argv[3],"f") == 0)
-      *err_con = FALSE;
+      *err_con = SUNFALSE;
     else
       WrongArgs(argv[0]);
   }
@@ -563,7 +593,7 @@ static void PrintIC(N_Vector y, N_Vector yp)
 {
   realtype* data;
 
-  data = N_VGetArrayPointer_Serial(y);
+  data = N_VGetArrayPointer(y);
   printf("\n\nConsistent IC:\n");
   printf("\ty = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -574,7 +604,7 @@ static void PrintIC(N_Vector y, N_Vector yp)
   printf("%12.4e %12.4e %12.4e \n", data[0], data[1], data[2]);
 #endif
 
-  data = N_VGetArrayPointer_Serial(yp);
+  data = N_VGetArrayPointer(yp);
   printf("\typ= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", data[0], data[1], data[2]);
@@ -589,7 +619,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(yS[0]);
+  sdata = N_VGetArrayPointer(yS[0]);
   printf("                  Sensitivity 1  ");
 
   printf("\n\ts1 = ");
@@ -600,7 +630,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[0]);
+  sdata = N_VGetArrayPointer(ypS[0]);
   printf("\ts1'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -612,7 +642,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 
 
   printf("                  Sensitivity 2  ");
-  sdata = N_VGetArrayPointer_Serial(yS[1]);
+  sdata = N_VGetArrayPointer(yS[1]);
   printf("\n\ts2 = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -621,7 +651,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[1]);
+  sdata = N_VGetArrayPointer(ypS[1]);
   printf("\ts2'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -633,7 +663,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 
 
   printf("                  Sensitivity 3  ");
-  sdata = N_VGetArrayPointer_Serial(yS[2]);
+  sdata = N_VGetArrayPointer(yS[2]);
   printf("\n\ts3 = ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -642,7 +672,7 @@ static void PrintSensIC(N_Vector y, N_Vector yp, N_Vector* yS, N_Vector* ypS)
 #else
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
-  sdata = N_VGetArrayPointer_Serial(ypS[2]);
+  sdata = N_VGetArrayPointer(ypS[2]);
   printf("\ts3'= ");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("%12.4Le %12.4Le %12.4Le \n", sdata[0], sdata[1], sdata[2]);
@@ -665,7 +695,7 @@ static void PrintOutput(void *ida_mem, realtype t, N_Vector u)
   int qu, flag;
   realtype hu, *udata;
   
-  udata = N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer(u);
 
   flag = IDAGetNumSteps(ida_mem, &nst);
   check_flag(&flag, "IDAGetNumSteps", 1);
@@ -702,7 +732,7 @@ static void PrintSensOutput(N_Vector *uS)
 {
   realtype *sdata;
 
-  sdata = N_VGetArrayPointer_Serial(uS[0]);
+  sdata = N_VGetArrayPointer(uS[0]);
   printf("                  Sensitivity 1  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -713,7 +743,7 @@ static void PrintSensOutput(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
   
-  sdata = N_VGetArrayPointer_Serial(uS[1]);
+  sdata = N_VGetArrayPointer(uS[1]);
   printf("                  Sensitivity 2  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
@@ -724,7 +754,7 @@ static void PrintSensOutput(N_Vector *uS)
   printf("%12.4e %12.4e %12.4e \n", sdata[0], sdata[1], sdata[2]);
 #endif
 
-  sdata = N_VGetArrayPointer_Serial(uS[2]);
+  sdata = N_VGetArrayPointer(uS[2]);
   printf("                  Sensitivity 3  ");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
diff --git a/examples/idas/serial/idasRoberts_FSA_sps.out b/examples/idas/serial/idasRoberts_FSA_sps_-sensi_stg_t.out
similarity index 100%
rename from examples/idas/serial/idasRoberts_FSA_sps.out
rename to examples/idas/serial/idasRoberts_FSA_sps_-sensi_stg_t.out
diff --git a/examples/idas/serial/idasRoberts_dns.c b/examples/idas/serial/idasRoberts_dns.c
index 2dffb09..ead50a9 100644
--- a/examples/idas/serial/idasRoberts_dns.c
+++ b/examples/idas/serial/idasRoberts_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -21,19 +17,21 @@
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01.
  *
- * The problem is solved with IDA using IDADENSE for the linear
+ * The problem is solved with IDA using the DENSE linear
  * solver, with a user-supplied Jacobian. Output is printed at
  * t = .4, 4, 40, ..., 4e10.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
 
@@ -45,7 +43,7 @@
 
 /* Macro to define dense matrix elements, indexed from 1. */
 
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1)
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1)
 
 /* Prototypes of functions called by IDA */
 
@@ -55,9 +53,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp,
 static int grob(realtype t, N_Vector yy, N_Vector yp,
                 realtype *gout, void *user_data);
 
-int jacrob(long int Neq, realtype tt,  realtype cj, 
+int jacrob(realtype tt,  realtype cj, 
            N_Vector yy, N_Vector yp, N_Vector resvec,
-           DlsMat JJ, void *user_data,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Prototypes of private functions */
@@ -66,6 +64,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y);
 static void PrintRootInfo(int root_f1, int root_f2);
 static void PrintFinalStats(void *mem);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol);
 
 /*
  *--------------------------------------------------------------------
@@ -81,10 +80,14 @@ int main(void)
   realtype t0, tout1, tout, tret;
   int iout, retval, retvalr;
   int rootsfound[2];
+  SUNMatrix A;
+  SUNLinearSolver LS;
 
   mem = NULL;
   yy = yp = avtol = NULL;
   yval = ypval = atval = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors. */
   yy = N_VNew_Serial(NEQ);
@@ -95,19 +98,19 @@ int main(void)
   if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
 
   /* Create and initialize  y, y', and absolute tolerance vectors. */
-  yval  = N_VGetArrayPointer_Serial(yy);
+  yval  = N_VGetArrayPointer(yy);
   yval[0] = ONE;
   yval[1] = ZERO;
   yval[2] = ZERO;
 
-  ypval = N_VGetArrayPointer_Serial(yp);
+  ypval = N_VGetArrayPointer(yp);
   ypval[0]  = RCONST(-0.04);
   ypval[1]  = RCONST(0.04);
   ypval[2]  = ZERO;  
 
   rtol = RCONST(1.0e-4);
 
-  atval = N_VGetArrayPointer_Serial(avtol);
+  atval = N_VGetArrayPointer(avtol);
   atval[0] = RCONST(1.0e-8);
   atval[1] = RCONST(1.0e-6);
   atval[2] = RCONST(1.0e-6);
@@ -118,26 +121,34 @@ int main(void)
 
   PrintHeader(rtol, avtol, yy);
 
-  /* Call IDACreate and IDAMalloc to initialize IDA memory */
+  /* Call IDACreate and IDAInit to initialize IDA memory */
   mem = IDACreate();
   if(check_flag((void *)mem, "IDACreate", 0)) return(1);
   retval = IDAInit(mem, resrob, t0, yy, yp);
   if(check_flag(&retval, "IDAInit", 1)) return(1);
+  /* Call IDASVtolerances to set tolerances */
   retval = IDASVtolerances(mem, rtol, avtol);
   if(check_flag(&retval, "IDASVtolerances", 1)) return(1);
 
-  /* Free avtol */
-  N_VDestroy_Serial(avtol);
-
   /* Call IDARootInit to specify the root function grob with 2 components */
   retval = IDARootInit(mem, 2, grob);
   if (check_flag(&retval, "IDARootInit", 1)) return(1);
 
-  /* Call IDADense and set up the linear solver. */
-  retval = IDADense(mem, NEQ);
-  if(check_flag(&retval, "IDADense", 1)) return(1);
-  retval = IDADlsSetDenseJacFn(mem, jacrob);
-  if(check_flag(&retval, "IDADlsSetDenseJacFn", 1)) return(1);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  retval = IDADlsSetJacFn(mem, jacrob);
+  if(check_flag(&retval, "IDADlsSetJacFn", 1)) return(1);
 
   /* In loop, call IDASolve, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached. */
@@ -167,13 +178,18 @@ int main(void)
 
   PrintFinalStats(mem);
 
-  /* Free memory */
+  /* check the solution error */
+  retval = check_ans(yy, tret, rtol, avtol);
 
+  /* Free memory */
   IDAFree(&mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(avtol);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
 
-  return(0);
+  return(retval);
   
 }
 
@@ -191,9 +207,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data
 {
   realtype *yval, *ypval, *rval;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy); 
+  ypval = N_VGetArrayPointer(yp); 
+  rval = N_VGetArrayPointer(rr);
 
   rval[0]  = RCONST(-0.04)*yval[0] + RCONST(1.0e4)*yval[1]*yval[2];
   rval[1]  = -rval[0] - RCONST(3.0e7)*yval[1]*yval[1] - ypval[1];
@@ -212,7 +228,7 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 {
   realtype *yval, y1, y3;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
+  yval = N_VGetArrayPointer(yy); 
   y1 = yval[0]; y3 = yval[2];
   gout[0] = y1 - RCONST(0.0001);
   gout[1] = y3 - RCONST(0.01);
@@ -224,14 +240,14 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
  * Define the Jacobian function. 
  */
 
-int jacrob(long int Neq, realtype tt,  realtype cj, 
+int jacrob(realtype tt,  realtype cj, 
            N_Vector yy, N_Vector yp, N_Vector resvec,
-           DlsMat JJ, void *user_data,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
-  
-  yval = N_VGetArrayPointer_Serial(yy);
+
+  yval = N_VGetArrayPointer(yy);
 
   IJth(JJ,1,1) = RCONST(-0.04) - cj;
   IJth(JJ,2,1) = RCONST(0.04);
@@ -260,12 +276,12 @@ static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
 {
   realtype *atval, *yval;
 
-  atval  = N_VGetArrayPointer_Serial(avtol);
-  yval  = N_VGetArrayPointer_Serial(y);
+  atval  = N_VGetArrayPointer(avtol);
+  yval  = N_VGetArrayPointer(y);
 
   printf("\nidasRoberts_dns: Robertson kinetics DAE serial example problem for IDA.\n");
   printf("               Three equation chemical kinetics problem.\n\n");
-  printf("Linear solver: IDADENSE, with user-supplied Jacobian.\n");
+  printf("Linear solver: DENSE, with user-supplied Jacobian.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg %Lg %Lg \n",
          rtol, atval[0],atval[1],atval[2]);
@@ -300,7 +316,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   retval = IDAGetLastOrder(mem, &kused);
   check_flag(&retval, "IDAGetLastOrder", 1);
@@ -400,3 +416,48 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
 
   return(0);
 }
+
+/* compare the solution at the final time 4e10s to a reference solution computed
+   using a relative tolerance of 1e-8 and absoltue tolerance of 1e-14 */
+static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol)
+{
+  int      passfail=0;        /* answer pass (0) or fail (1) flag */  
+  N_Vector ref;               /* reference solution vector        */
+  N_Vector ewt;               /* error weight vector              */
+  realtype err;               /* wrms error                       */
+
+  /* create reference solution and error weight vectors */
+  ref = N_VClone(y);
+  ewt = N_VClone(y);
+
+  /* set the reference solution data */
+  NV_Ith_S(ref,0) = RCONST(5.2083474251394888e-08);
+  NV_Ith_S(ref,1) = RCONST(2.0833390772616859e-13);
+  NV_Ith_S(ref,2) = RCONST(9.9999994791631752e-01);
+
+  /* compute the error weight vector, loosen atol */
+  N_VAbs(ref, ewt);
+  N_VLinearSum(rtol, ewt, RCONST(10.0), atol, ewt);
+  if (N_VMin(ewt) <= ZERO) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: check_ans failed - ewt <= 0\n\n");
+    return(-1);
+  }
+  N_VInv(ewt, ewt);   
+
+  /* compute the solution error */
+  N_VLinearSum(ONE, y, -ONE, ref, ref);
+  err = N_VWrmsNorm(ref, ewt);
+
+  /* is the solution within the tolerances? */
+  passfail = (err < ONE) ? 0 : 1; 
+
+  if (passfail) {
+    fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%g \n\n", err);
+  }
+
+  /* Free vectors */
+  N_VDestroy(ref);
+  N_VDestroy(ewt);
+
+  return(passfail);
+}
diff --git a/examples/idas/serial/idasRoberts_dns.out b/examples/idas/serial/idasRoberts_dns.out
index c2e4d03..ba2b697 100644
--- a/examples/idas/serial/idasRoberts_dns.out
+++ b/examples/idas/serial/idasRoberts_dns.out
@@ -2,7 +2,7 @@
 idasRoberts_dns: Robertson kinetics DAE serial example problem for IDA.
                Three equation chemical kinetics problem.
 
-Linear solver: IDADENSE, with user-supplied Jacobian.
+Linear solver: DENSE, with user-supplied Jacobian.
 Tolerance parameters:  rtol = 0.0001   atol = 1e-08 1e-06 1e-06 
 Initial conditions y0 = (1 0 0)
 Constraints and id not used.
@@ -18,14 +18,14 @@ Constraints and id not used.
 4.0000e+02   4.5044e-01   3.2218e-06   5.4956e-01 |  95  4   3.3201e+01
 4.0000e+03   1.8320e-01   8.9444e-07   8.1680e-01 | 126  3   3.1458e+02
 4.0000e+04   3.8992e-02   1.6221e-07   9.6101e-01 | 161  5   2.5058e+03
-4.0000e+05   4.9369e-03   1.9842e-08   9.9506e-01 | 202  3   2.6370e+04
-4.0000e+06   5.1674e-04   2.0684e-09   9.9948e-01 | 250  3   1.7186e+05
+4.0000e+05   4.9369e-03   1.9842e-08   9.9506e-01 | 202  3   2.6371e+04
+4.0000e+06   5.1674e-04   2.0684e-09   9.9948e-01 | 250  3   1.7187e+05
 2.0788e+07   1.0000e-04   4.0004e-10   9.9990e-01 | 280  5   1.0513e+06
     rootsfound[] =  -1   0
 4.0000e+07   5.2009e-05   2.0805e-10   9.9995e-01 | 293  4   2.3655e+06
-4.0000e+08   5.2012e-06   2.0805e-11   9.9999e-01 | 325  4   2.6809e+07
-4.0000e+09   5.1850e-07   2.0740e-12   1.0000e-00 | 348  3   7.4307e+08
-4.0000e+10   4.8641e-08   1.9456e-13   1.0000e-00 | 362  2   7.5482e+09
+4.0000e+08   5.2012e-06   2.0805e-11   9.9999e-01 | 325  4   2.6808e+07
+4.0000e+09   5.1850e-07   2.0740e-12   1.0000e+00 | 348  3   7.4305e+08
+4.0000e+10   4.8641e-08   1.9456e-13   1.0000e+00 | 362  2   7.5480e+09
 
 Final Run Statistics: 
 
diff --git a/examples/idas/serial/idasRoberts_klu.c b/examples/idas/serial/idasRoberts_klu.c
index be8d65d..495497a 100644
--- a/examples/idas/serial/idasRoberts_klu.c
+++ b/examples/idas/serial/idasRoberts_klu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward @ LLNL  (based on idasRoberts_dns.c)
  * -----------------------------------------------------------------
  * This simple example problem for IDA, due to Robertson, 
@@ -20,19 +16,21 @@
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01.
  *
- * The problem is solved with IDA using IDAKLU for the linear
+ * The problem is solved with IDA using the KLU linear
  * solver, with a user-supplied Jacobian. Output is printed at
  * t = .4, 4, 40, ..., 4e10.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_klu.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <idas/idas.h>                     /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_klu.h>       /* access to KLU linear solver          */
+#include <idas/idas_direct.h>              /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
 
@@ -50,9 +48,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp,
 static int grob(realtype t, N_Vector yy, N_Vector yp,
                 realtype *gout, void *user_data);
 
-int jacrob(realtype tt,  realtype cj, 
-           N_Vector yy, N_Vector yp, N_Vector resvec, 
-	   SlsMat JacMat, void *user_data,
+int jacrob(realtype tt,  realtype cj,
+           N_Vector yy, N_Vector yp, N_Vector resvec,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Prototypes of private functions */
@@ -76,12 +74,15 @@ int main(void)
   realtype t0, tout1, tout, tret;
   int iout, retval, retvalr;
   int rootsfound[2];
-
-  int nnz;
+  SUNMatrix A;
+  SUNLinearSolver LS;
+  sunindextype nnz;
 
   mem = NULL;
   yy = yp = avtol = NULL;
   yval = ypval = atval = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors. */
   yy = N_VNew_Serial(NEQ);
@@ -92,19 +93,19 @@ int main(void)
   if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
 
   /* Create and initialize  y, y', and absolute tolerance vectors. */
-  yval  = N_VGetArrayPointer_Serial(yy);
+  yval  = N_VGetArrayPointer(yy);
   yval[0] = ONE;
   yval[1] = ZERO;
   yval[2] = ZERO;
 
-  ypval = N_VGetArrayPointer_Serial(yp);
+  ypval = N_VGetArrayPointer(yp);
   ypval[0]  = RCONST(-0.04);
   ypval[1]  = RCONST(0.04);
   ypval[2]  = ZERO;  
 
   rtol = RCONST(1.0e-4);
 
-  atval = N_VGetArrayPointer_Serial(avtol);
+  atval = N_VGetArrayPointer(avtol);
   atval[0] = RCONST(1.0e-8);
   atval[1] = RCONST(1.0e-6);
   atval[2] = RCONST(1.0e-6);
@@ -115,27 +116,38 @@ int main(void)
 
   PrintHeader(rtol, avtol, yy);
 
-  /* Call IDACreate and IDAMalloc to initialize IDA memory */
+  /* Call IDACreate and IDAInit to initialize IDA memory */
   mem = IDACreate();
   if(check_flag((void *)mem, "IDACreate", 0)) return(1);
   retval = IDAInit(mem, resrob, t0, yy, yp);
   if(check_flag(&retval, "IDAInit", 1)) return(1);
+  /* Call IDASVtolerances to set tolerances */
   retval = IDASVtolerances(mem, rtol, avtol);
   if(check_flag(&retval, "IDASVtolerances", 1)) return(1);
 
   /* Free avtol */
-  N_VDestroy_Serial(avtol);
+  N_VDestroy(avtol);
 
   /* Call IDARootInit to specify the root function grob with 2 components */
   retval = IDARootInit(mem, 2, grob);
   if (check_flag(&retval, "IDARootInit", 1)) return(1);
 
-  /* Call IDAKLU and set up the linear solver. */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  retval = IDAKLU(mem, NEQ, nnz, CSC_MAT);
-  if(check_flag(&retval, "IDAKLU", 1)) return(1);
-  retval = IDASlsSetSparseJacFn(mem, jacrob);
-  if(check_flag(&retval, "IDASlsSetSparseJacFn", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU SUNLinearSolver object */
+  LS = SUNKLU(yy, A);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  retval = IDADlsSetJacFn(mem, jacrob);
+  if(check_flag(&retval, "IDADlsSetJacFn", 1)) return(1);
 
   /* In loop, call IDASolve, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached. */
@@ -168,8 +180,10 @@ int main(void)
   /* Free memory */
 
   IDAFree(&mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
 
   return(0);
   
@@ -189,9 +203,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data
 {
   realtype *yval, *ypval, *rval;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy); 
+  ypval = N_VGetArrayPointer(yp); 
+  rval = N_VGetArrayPointer(rr);
 
   rval[0]  = RCONST(-0.04)*yval[0] + RCONST(1.0e4)*yval[1]*yval[2];
   rval[1]  = -rval[0] - RCONST(3.0e7)*yval[1]*yval[1] - ypval[1];
@@ -210,7 +224,7 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 {
   realtype *yval, y1, y3;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
+  yval = N_VGetArrayPointer(yy); 
   y1 = yval[0]; y3 = yval[2];
   gout[0] = y1 - RCONST(0.0001);
   gout[1] = y3 - RCONST(0.01);
@@ -224,26 +238,24 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 
 int jacrob(realtype tt,  realtype cj, 
            N_Vector yy, N_Vector yp, N_Vector resvec,
-	   SlsMat JacMat, void *user_data,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
-  int* colptrs;
-  int* rowvals;
-  realtype* data;
-  
-  yval = N_VGetArrayPointer_Serial(yy);
-  colptrs = (*JacMat->colptrs);
-  rowvals = (*JacMat->rowvals);
-  data    = JacMat->data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
+  yval = N_VGetArrayPointer(yy);
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
+  /* column 0 */
   data[0] = RCONST(-0.04) - cj;
   rowvals[0] = 0;
   data[1] = RCONST(0.04);
@@ -251,6 +263,7 @@ int jacrob(realtype tt,  realtype cj,
   data[2] = ONE;
   rowvals[2] = 2;
 
+  /* column 1 */
   data[3] = RCONST(1.0e4)*yval[2];
   rowvals[3] = 0;
   data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]) - cj;
@@ -258,6 +271,7 @@ int jacrob(realtype tt,  realtype cj,
   data[5] = ONE;
   rowvals[5] = 2;
 
+  /* column 2 */
   data[6] = RCONST(1.0e4)*yval[1];
   rowvals[6] = 0;
   data[7] = RCONST(-1.0e4)*yval[1];
@@ -282,12 +296,12 @@ static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
 {
   realtype *atval, *yval;
 
-  atval  = N_VGetArrayPointer_Serial(avtol);
-  yval  = N_VGetArrayPointer_Serial(y);
+  atval  = N_VGetArrayPointer(avtol);
+  yval  = N_VGetArrayPointer(y);
 
   printf("\nidasRoberts_klu: Robertson kinetics DAE serial example problem for IDA.\n");
   printf("               Three equation chemical kinetics problem.\n\n");
-  printf("Linear solver: IDAKLU, with user-supplied Jacobian.\n");
+  printf("Linear solver: KLU, with user-supplied Jacobian.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg %Lg %Lg \n",
          rtol, atval[0],atval[1],atval[2]);
@@ -322,7 +336,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   retval = IDAGetLastOrder(mem, &kused);
   check_flag(&retval, "IDAGetLastOrder", 1);
@@ -334,7 +348,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   printf("%10.4Le %12.4Le %12.4Le %12.4Le | %3ld  %1d %12.4Le\n", 
          t, yval[0], yval[1], yval[2], nst, kused, hused);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-  printf("%10.4e %12.4e %12.4e %12.4e | %3ld  %d %12.4e\n", 
+  printf("%10.4e %12.4e %12.4e %12.4e | %3ld  %1d %12.4e\n", 
          t, yval[0], yval[1], yval[2], nst, kused, hused);
 #else
   printf("%10.4e %12.4e %12.4e %12.4e | %3ld  %1d %12.4e\n", 
@@ -355,31 +369,26 @@ static void PrintRootInfo(int root_f1, int root_f2)
 static void PrintFinalStats(void *mem)
 {
   int retval;
-  long int nst, nni, nje, nre, nreLS, netf, ncfn, nge;
+  long int nst, nni, nje, nre, netf, ncfn, nge;
 
   retval = IDAGetNumSteps(mem, &nst);
   check_flag(&retval, "IDAGetNumSteps", 1);
   retval = IDAGetNumResEvals(mem, &nre);
   check_flag(&retval, "IDAGetNumResEvals", 1);
-  retval = IDASlsGetNumJacEvals(mem, &nje);
-  check_flag(&retval, "IDASlsGetNumJacEvals", 1);
+  retval = IDADlsGetNumJacEvals(mem, &nje);
+  check_flag(&retval, "IDADlsGetNumJacEvals", 1);
   retval = IDAGetNumNonlinSolvIters(mem, &nni);
   check_flag(&retval, "IDAGetNumNonlinSolvIters", 1);
   retval = IDAGetNumErrTestFails(mem, &netf);
   check_flag(&retval, "IDAGetNumErrTestFails", 1);
   retval = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
   check_flag(&retval, "IDAGetNumNonlinSolvConvFails", 1);
-  /*  
-      retval = IDASlsGetNumResEvals(mem, &nreLS);
-      check_flag(&retval, "IDASlsGetNumResEvals", 1);
-  */
-  nreLS = 0;
   retval = IDAGetNumGEvals(mem, &nge);
   check_flag(&retval, "IDAGetNumGEvals", 1);
 
   printf("\nFinal Run Statistics: \n\n");
   printf("Number of steps                    = %ld\n", nst);
-  printf("Number of residual evaluations     = %ld\n", nre+nreLS);
+  printf("Number of residual evaluations     = %ld\n", nre);
   printf("Number of Jacobian evaluations     = %ld\n", nje);
   printf("Number of nonlinear iterations     = %ld\n", nni);
   printf("Number of error test failures      = %ld\n", netf);
diff --git a/examples/idas/serial/idasRoberts_klu.out b/examples/idas/serial/idasRoberts_klu.out
index d986b7f..36a3d8d 100644
--- a/examples/idas/serial/idasRoberts_klu.out
+++ b/examples/idas/serial/idasRoberts_klu.out
@@ -2,7 +2,7 @@
 idasRoberts_klu: Robertson kinetics DAE serial example problem for IDA.
                Three equation chemical kinetics problem.
 
-Linear solver: IDAKLU, with user-supplied Jacobian.
+Linear solver: KLU, with user-supplied Jacobian.
 Tolerance parameters:  rtol = 0.0001   atol = 1e-08 1e-06 1e-06 
 Initial conditions y0 = (1 0 0)
 Constraints and id not used.
diff --git a/examples/idas/serial/idasRoberts_sps.c b/examples/idas/serial/idasRoberts_sps.c
index e4c67ca..49c61de 100644
--- a/examples/idas/serial/idasRoberts_sps.c
+++ b/examples/idas/serial/idasRoberts_sps.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward @ LLNL  (based on idasRoberts_dns.c)
  * -----------------------------------------------------------------
  * This simple example problem for IDA, due to Robertson, 
@@ -20,19 +16,21 @@
  * feature to find the points at which y1 = 1e-4 or at which
  * y3 = 0.01.
  *
- * The problem is solved with IDA using IDASUPERLUMT for the linear
+ * The problem is solved with IDA using the SUPERLUMT linear
  * solver, with a user-supplied Jacobian. Output is printed at
  * t = .4, 4, 40, ..., 4e10.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_superlumt.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
+#include <idas/idas.h>                     /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix           */
+#include <sunlinsol/sunlinsol_superlumt.h> /* access to SuperLUMT linear solver    */
+#include <idas/idas_direct.h>              /* access to IDADls interface           */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>        /* defs. of SUNRabs, SUNRexp, etc.      */
 
 /* Problem Constants */
 
@@ -50,9 +48,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp,
 static int grob(realtype t, N_Vector yy, N_Vector yp,
                 realtype *gout, void *user_data);
 
-int jacrob(realtype tt,  realtype cj, 
-           N_Vector yy, N_Vector yp, N_Vector resvec, 
-	   SlsMat JacMat, void *user_data,
+int jacrob(realtype tt,  realtype cj,
+           N_Vector yy, N_Vector yp, N_Vector resvec,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);
 
 /* Prototypes of private functions */
@@ -76,12 +74,15 @@ int main(void)
   realtype t0, tout1, tout, tret;
   int iout, retval, retvalr;
   int rootsfound[2];
-
-  int nnz;
+  SUNMatrix A;
+  SUNLinearSolver LS;
+  sunindextype nnz;
 
   mem = NULL;
   yy = yp = avtol = NULL;
   yval = ypval = atval = NULL;
+  A = NULL;
+  LS = NULL;
 
   /* Allocate N-vectors. */
   yy = N_VNew_Serial(NEQ);
@@ -92,19 +93,19 @@ int main(void)
   if(check_flag((void *)avtol, "N_VNew_Serial", 0)) return(1);
 
   /* Create and initialize  y, y', and absolute tolerance vectors. */
-  yval  = N_VGetArrayPointer_Serial(yy);
+  yval  = N_VGetArrayPointer(yy);
   yval[0] = ONE;
   yval[1] = ZERO;
   yval[2] = ZERO;
 
-  ypval = N_VGetArrayPointer_Serial(yp);
+  ypval = N_VGetArrayPointer(yp);
   ypval[0]  = RCONST(-0.04);
   ypval[1]  = RCONST(0.04);
   ypval[2]  = ZERO;  
 
   rtol = RCONST(1.0e-4);
 
-  atval = N_VGetArrayPointer_Serial(avtol);
+  atval = N_VGetArrayPointer(avtol);
   atval[0] = RCONST(1.0e-8);
   atval[1] = RCONST(1.0e-6);
   atval[2] = RCONST(1.0e-6);
@@ -115,27 +116,38 @@ int main(void)
 
   PrintHeader(rtol, avtol, yy);
 
-  /* Call IDACreate and IDAMalloc to initialize IDA memory */
+  /* Call IDACreate and IDAInit to initialize IDA memory */
   mem = IDACreate();
   if(check_flag((void *)mem, "IDACreate", 0)) return(1);
   retval = IDAInit(mem, resrob, t0, yy, yp);
   if(check_flag(&retval, "IDAInit", 1)) return(1);
+  /* Call IDASVtolerances to set tolerances */
   retval = IDASVtolerances(mem, rtol, avtol);
   if(check_flag(&retval, "IDASVtolerances", 1)) return(1);
 
   /* Free avtol */
-  N_VDestroy_Serial(avtol);
+  N_VDestroy(avtol);
 
   /* Call IDARootInit to specify the root function grob with 2 components */
   retval = IDARootInit(mem, 2, grob);
   if (check_flag(&retval, "IDARootInit", 1)) return(1);
 
-  /* Call IDASuperLUMT and set up the linear solver. */
+  /* Create sparse SUNMatrix for use in linear solves */
   nnz = NEQ * NEQ;
-  retval = IDASuperLUMT(mem, 1, NEQ, nnz);
-  if(check_flag(&retval, "IDASuperLUMT", 1)) return(1);
-  retval = IDASlsSetSparseJacFn(mem, jacrob);
-  if(check_flag(&retval, "IDASlsSetSparseJacFn", 1)) return(1);
+  A = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)A, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT SUNLinearSolver object (one thread) */
+  LS = SUNSuperLUMT(yy, A, 1);
+  if(check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  retval = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&retval, "IDADlsSetLinearSolver", 1)) return(1);
+
+  /* Set the user-supplied Jacobian routine */
+  retval = IDADlsSetJacFn(mem, jacrob);
+  if(check_flag(&retval, "IDADlsSetJacFn", 1)) return(1);
 
   /* In loop, call IDASolve, print results, and test for error.
      Break out of loop when NOUT preset output times have been reached. */
@@ -168,8 +180,10 @@ int main(void)
   /* Free memory */
 
   IDAFree(&mem);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
 
   return(0);
   
@@ -189,9 +203,9 @@ int resrob(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data
 {
   realtype *yval, *ypval, *rval;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy); 
+  ypval = N_VGetArrayPointer(yp); 
+  rval = N_VGetArrayPointer(rr);
 
   rval[0]  = RCONST(-0.04)*yval[0] + RCONST(1.0e4)*yval[1]*yval[2];
   rval[1]  = -rval[0] - RCONST(3.0e7)*yval[1]*yval[1] - ypval[1];
@@ -210,7 +224,7 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 {
   realtype *yval, y1, y3;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
+  yval = N_VGetArrayPointer(yy); 
   y1 = yval[0]; y3 = yval[2];
   gout[0] = y1 - RCONST(0.0001);
   gout[1] = y3 - RCONST(0.01);
@@ -224,41 +238,45 @@ static int grob(realtype t, N_Vector yy, N_Vector yp, realtype *gout,
 
 int jacrob(realtype tt,  realtype cj, 
            N_Vector yy, N_Vector yp, N_Vector resvec,
-	   SlsMat JacMat, void *user_data,
+           SUNMatrix JJ, void *user_data,
            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
 {
   realtype *yval;
-  int *colptrs = *JacMat->colptrs;
-  int *rowvals = *JacMat->rowvals;
-  
-  yval = N_VGetArrayPointer_Serial(yy);
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(JJ);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(JJ);
+  realtype *data = SUNSparseMatrix_Data(JJ);
+
+  yval = N_VGetArrayPointer(yy);
 
-  SparseSetMatToZero(JacMat);
+  SUNMatZero(JJ);
 
   colptrs[0] = 0;
   colptrs[1] = 3;
   colptrs[2] = 6;
   colptrs[3] = 9;
 
-  JacMat->data[0] = RCONST(-0.04) - cj;
+  /* column 0 */
+  data[0] = RCONST(-0.04) - cj;
   rowvals[0] = 0;
-  JacMat->data[1] = RCONST(0.04);
+  data[1] = RCONST(0.04);
   rowvals[1] = 1;
-  JacMat->data[2] = ONE;
+  data[2] = ONE;
   rowvals[2] = 2;
 
-  JacMat->data[3] = RCONST(1.0e4)*yval[2];
+  /* column 1 */
+  data[3] = RCONST(1.0e4)*yval[2];
   rowvals[3] = 0;
-  JacMat->data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]) - cj;
+  data[4] = (RCONST(-1.0e4)*yval[2]) - (RCONST(6.0e7)*yval[1]) - cj;
   rowvals[4] = 1;
-  JacMat->data[5] = ONE;
+  data[5] = ONE;
   rowvals[5] = 2;
 
-  JacMat->data[6] = RCONST(1.0e4)*yval[1];
+  /* column 2 */
+  data[6] = RCONST(1.0e4)*yval[1];
   rowvals[6] = 0;
-  JacMat->data[7] = RCONST(-1.0e4)*yval[1];
+  data[7] = RCONST(-1.0e4)*yval[1];
   rowvals[7] = 1;
-  JacMat->data[8] = ONE;
+  data[8] = ONE;
   rowvals[8] = 2;
 
   return(0);
@@ -278,12 +296,12 @@ static void PrintHeader(realtype rtol, N_Vector avtol, N_Vector y)
 {
   realtype *atval, *yval;
 
-  atval  = N_VGetArrayPointer_Serial(avtol);
-  yval  = N_VGetArrayPointer_Serial(y);
+  atval  = N_VGetArrayPointer(avtol);
+  yval  = N_VGetArrayPointer(y);
 
   printf("\nidasRoberts_sps: Robertson kinetics DAE serial example problem for IDA.\n");
   printf("               Three equation chemical kinetics problem.\n\n");
-  printf("Linear solver: IDASUPERLUMT, with user-supplied Jacobian.\n");
+  printf("Linear solver: SUPERLUMT, with user-supplied Jacobian.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg %Lg %Lg \n",
          rtol, atval[0],atval[1],atval[2]);
@@ -318,7 +336,7 @@ static void PrintOutput(void *mem, realtype t, N_Vector y)
   long int nst;
   realtype hused;
 
-  yval  = N_VGetArrayPointer_Serial(y);
+  yval  = N_VGetArrayPointer(y);
 
   retval = IDAGetLastOrder(mem, &kused);
   check_flag(&retval, "IDAGetLastOrder", 1);
@@ -351,29 +369,26 @@ static void PrintRootInfo(int root_f1, int root_f2)
 static void PrintFinalStats(void *mem)
 {
   int retval;
-  long int nst, nni, nje, nre, nreLS, netf, ncfn, nge;
+  long int nst, nni, nje, nre, netf, ncfn, nge;
 
   retval = IDAGetNumSteps(mem, &nst);
   check_flag(&retval, "IDAGetNumSteps", 1);
   retval = IDAGetNumResEvals(mem, &nre);
   check_flag(&retval, "IDAGetNumResEvals", 1);
-  retval = IDASlsGetNumJacEvals(mem, &nje);
-  check_flag(&retval, "IDASlsGetNumJacEvals", 1);
+  retval = IDADlsGetNumJacEvals(mem, &nje);
+  check_flag(&retval, "IDADlsGetNumJacEvals", 1);
   retval = IDAGetNumNonlinSolvIters(mem, &nni);
   check_flag(&retval, "IDAGetNumNonlinSolvIters", 1);
   retval = IDAGetNumErrTestFails(mem, &netf);
   check_flag(&retval, "IDAGetNumErrTestFails", 1);
   retval = IDAGetNumNonlinSolvConvFails(mem, &ncfn);
   check_flag(&retval, "IDAGetNumNonlinSolvConvFails", 1);
-  /*  retval = IDASlsGetNumResEvals(mem, &nreLS); */
-  /*  check_flag(&retval, "IDASlsGetNumResEvals", 1); */
-  nreLS = 0;
   retval = IDAGetNumGEvals(mem, &nge);
   check_flag(&retval, "IDAGetNumGEvals", 1);
 
   printf("\nFinal Run Statistics: \n\n");
   printf("Number of steps                    = %ld\n", nst);
-  printf("Number of residual evaluations     = %ld\n", nre+nreLS);
+  printf("Number of residual evaluations     = %ld\n", nre);
   printf("Number of Jacobian evaluations     = %ld\n", nje);
   printf("Number of nonlinear iterations     = %ld\n", nni);
   printf("Number of error test failures      = %ld\n", netf);
diff --git a/examples/idas/serial/idasRoberts_sps.out b/examples/idas/serial/idasRoberts_sps.out
index d0739a6..c1a76c0 100644
--- a/examples/idas/serial/idasRoberts_sps.out
+++ b/examples/idas/serial/idasRoberts_sps.out
@@ -2,7 +2,7 @@
 idasRoberts_sps: Robertson kinetics DAE serial example problem for IDA.
                Three equation chemical kinetics problem.
 
-Linear solver: IDASUPERLUMT, with user-supplied Jacobian.
+Linear solver: SUPERLUMT, with user-supplied Jacobian.
 Tolerance parameters:  rtol = 0.0001   atol = 1e-08 1e-06 1e-06 
 Initial conditions y0 = (1 0 0)
 Constraints and id not used.
@@ -19,20 +19,20 @@ Constraints and id not used.
 4.0000e+03   1.8320e-01   8.9444e-07   8.1680e-01 | 126  3   3.1458e+02
 4.0000e+04   3.8992e-02   1.6221e-07   9.6101e-01 | 161  5   2.5058e+03
 4.0000e+05   4.9369e-03   1.9842e-08   9.9506e-01 | 202  3   2.6371e+04
-4.0000e+06   5.1693e-04   2.0688e-09   9.9948e-01 | 252  5   2.5583e+05
-2.0801e+07   1.0000e-04   4.0004e-10   9.9990e-01 | 291  4   1.1781e+06
+4.0000e+06   5.1674e-04   2.0684e-09   9.9948e-01 | 250  3   1.7187e+05
+2.0788e+07   1.0000e-04   4.0004e-10   9.9990e-01 | 280  5   1.0513e+06
     rootsfound[] =  -1   0
-4.0000e+07   5.2043e-05   2.0818e-10   9.9995e-01 | 303  5   2.3562e+06
-4.0000e+08   5.2113e-06   2.0845e-11   9.9999e-01 | 336  4   3.7885e+07
-4.0000e+09   5.2515e-07   2.1006e-12   1.0000e+00 | 359  3   5.4083e+08
-4.0000e+10   5.1251e-08   2.0500e-13   1.0000e+00 | 375  3   8.6532e+09
+4.0000e+07   5.2009e-05   2.0805e-10   9.9995e-01 | 293  4   2.3655e+06
+4.0000e+08   5.2012e-06   2.0805e-11   9.9999e-01 | 325  4   2.6808e+07
+4.0000e+09   5.1850e-07   2.0740e-12   1.0000e+00 | 348  3   7.4305e+08
+4.0000e+10   4.8641e-08   1.9456e-13   1.0000e+00 | 362  2   7.5480e+09
 
 Final Run Statistics: 
 
-Number of steps                    = 375
-Number of residual evaluations     = 529
-Number of Jacobian evaluations     = 54
-Number of nonlinear iterations     = 529
-Number of error test failures      = 10
+Number of steps                    = 362
+Number of residual evaluations     = 537
+Number of Jacobian evaluations     = 60
+Number of nonlinear iterations     = 537
+Number of error test failures      = 15
 Number of nonlinear conv. failures = 0
-Number of root fn. evaluations     = 417
+Number of root fn. evaluations     = 404
diff --git a/examples/idas/serial/idasSlCrank_FSA_dns.c b/examples/idas/serial/idasSlCrank_FSA_dns.c
index 790b238..f8b0c0d 100644
--- a/examples/idas/serial/idasSlCrank_FSA_dns.c
+++ b/examples/idas/serial/idasSlCrank_FSA_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer: Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
  * Simulation of a slider-crank mechanism modelled with 3 generalized
@@ -21,18 +17,19 @@
  * where
  *   g(t,y,p) = 0.5*J1*v1^2 + 0.5*J2*v3^2 + 0.5*m2*v2^2
  *              
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <math.h>
 #include <stdlib.h>
 
-#include <idas/idas.h>
-#include <idas/idas_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
-
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i= 1..NEQ */
 
@@ -100,6 +97,11 @@ int main(void)
   realtype dp, G, Gm[2], Gp[2];
   int flag, is;
   realtype atolS[NP];
+  SUNMatrix A;
+  SUNLinearSolver LS;
+
+  A  = NULL;
+  LS = NULL;
 
   id = N_VNew_Serial(NEQ);
   yy = N_VNew_Serial(NEQ);
@@ -108,7 +110,7 @@ int main(void)
 
   yyS= N_VCloneVectorArray(NP,yy);
   ypS= N_VCloneVectorArray(NP,yp);
-  qS = N_VCloneVectorArray_Serial(NP, q);
+  qS = N_VCloneVectorArray(NP, q);
 
   data = (UserData) malloc(sizeof *data);
 
@@ -144,28 +146,37 @@ int main(void)
   flag = IDASStolerances(mem, RTOLF, ATOLF);
   flag = IDASetUserData(mem, data);
   flag = IDASetId(mem, id);
-  flag = IDASetSuppressAlg(mem, TRUE);
+  flag = IDASetSuppressAlg(mem, SUNTRUE);
   flag = IDASetMaxNumSteps(mem, 20000);
 
-  /* Call IDADense and set up the linear solver. */
-  flag = IDADense(mem, NEQ);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
   flag = IDASensInit(mem, NP, IDA_SIMULTANEOUS, NULL, yyS, ypS);
   pbar[0] = data->params[0];pbar[1] = data->params[1];
   flag = IDASetSensParams(mem, data->params, pbar, NULL);
   flag = IDASensEEtolerances(mem);
-  IDASetSensErrCon(mem, TRUE);
+  IDASetSensErrCon(mem, SUNTRUE);
   
   N_VConst(ZERO, q);
   flag = IDAQuadInit(mem, rhsQ, q);
   flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
-  flag = IDASetQuadErrCon(mem, TRUE);
+  flag = IDASetQuadErrCon(mem, SUNTRUE);
   
   N_VConst(ZERO, qS[0]);
   flag = IDAQuadSensInit(mem, rhsQS, qS);
   atolS[0] = atolS[1] = ATOLQ;
   flag = IDAQuadSensSStolerances(mem, RTOLQ, atolS);
-  flag = IDASetQuadSensErrCon(mem, TRUE);  
+  flag = IDASetQuadSensErrCon(mem, SUNTRUE);  
   
 
   /* Perform forward run */
@@ -180,16 +191,25 @@ int main(void)
 
   IDAGetQuad(mem, &tret, q);
   printf("--------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("  G = %24.16Lf\n", Ith(q,1));
+#else
   printf("  G = %24.16f\n", Ith(q,1));
+#endif  
   printf("--------------------------------------------\n\n");
   
   IDAGetQuadSens(mem, &tret, qS);
   printf("-------------F O R W A R D------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le\n", Ith(qS[0],1), Ith(qS[1],1));
+#else
   printf("   dG/dp:  %12.4e %12.4e\n", Ith(qS[0],1), Ith(qS[1],1));
+#endif  
   printf("--------------------------------------------\n\n");
 
   IDAFree(&mem);
-
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
 
 
   /* Finite differences for dG/dp */
@@ -204,14 +224,24 @@ int main(void)
   flag = IDASStolerances(mem, RTOLFD, ATOLFD);
   flag = IDASetUserData(mem, data);
   flag = IDASetId(mem, id);
-  flag = IDASetSuppressAlg(mem, TRUE);
-  /* Call IDADense and set up the linear solver. */
-  flag = IDADense(mem, NEQ);
+  flag = IDASetSuppressAlg(mem, SUNTRUE);
+
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
   N_VConst(ZERO, q);
   IDAQuadInit(mem, rhsQ, q);
   IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
-  IDASetQuadErrCon(mem, TRUE);
+  IDASetQuadErrCon(mem, SUNTRUE);
 
   IDASolve(mem, TEND, &tret, yy, yp, IDA_NORMAL);
 
@@ -277,19 +307,33 @@ int main(void)
   Gp[1] = Ith(q,1);
 
   IDAFree(&mem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
 
   printf("\n\n   Checking using Finite Differences \n\n");
 
   printf("---------------BACKWARD------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le\n", (G-Gm[0])/dp, (G-Gm[1])/dp);
+#else
   printf("   dG/dp:  %12.4e %12.4e\n", (G-Gm[0])/dp, (G-Gm[1])/dp);
+#endif  
   printf("-----------------------------------------\n\n");
 
   printf("---------------FORWARD-------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le\n", (Gp[0]-G)/dp, (Gp[1]-G)/dp);
+#else
   printf("   dG/dp:  %12.4e %12.4e\n", (Gp[0]-G)/dp, (Gp[1]-G)/dp);
+#endif  
   printf("-----------------------------------------\n\n");
 
   printf("--------------CENTERED-------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("   dG/dp:  %12.4Le %12.4Le\n", (Gp[0]-Gm[0])/(TWO*dp) ,(Gp[1]-Gm[1])/(TWO*dp));
+#else
   printf("   dG/dp:  %12.4e %12.4e\n", (Gp[0]-Gm[0])/(TWO*dp) ,(Gp[1]-Gm[1])/(TWO*dp));
+#endif  
   printf("-----------------------------------------\n\n");
 
 
@@ -297,9 +341,9 @@ int main(void)
   free(data);
 
   N_VDestroy(id);
-  N_VDestroy_Serial(yy);
-  N_VDestroy_Serial(yp);
-  N_VDestroy_Serial(q);
+  N_VDestroy(yy);
+  N_VDestroy(yp);
+  N_VDestroy(q);
   return(0);
   
 }
@@ -399,9 +443,9 @@ static int ressc(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *use
   m2 = data->m2;
   J2 = data->J2;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy); 
+  ypval = N_VGetArrayPointer(yp); 
+  rval = N_VGetArrayPointer(rr);
 
   q = yval[0];
   x = yval[1];
diff --git a/examples/idas/serial/idasSlCrank_FSA_dns.out b/examples/idas/serial/idasSlCrank_FSA_dns.out
index 103893c..689ca61 100644
--- a/examples/idas/serial/idasSlCrank_FSA_dns.out
+++ b/examples/idas/serial/idasSlCrank_FSA_dns.out
@@ -5,14 +5,14 @@ Forward integration ... done!
 
 Final Run Statistics: 
 
-Number of steps                    = 234
-Number of residual evaluations     = 1194
-Number of Jacobian evaluations     = 48
-Number of nonlinear iterations     = 714
+Number of steps                    = 232
+Number of residual evaluations     = 1170
+Number of Jacobian evaluations     = 45
+Number of nonlinear iterations     = 720
 Number of error test failures      = 0
-Number of nonlinear conv. failures = 1
+Number of nonlinear conv. failures = 0
 --------------------------------------------
-  G =       3.3366156512592133
+  G =       3.3366157233164491
 --------------------------------------------
 
 -------------F O R W A R D------------------
@@ -28,7 +28,7 @@ Number of nonlinear conv. failures = 1
 -----------------------------------------
 
 ---------------FORWARD-------------------
-   dG/dp:    3.3345e-01  -3.6375e-01
+   dG/dp:    3.3345e-01  -3.6374e-01
 -----------------------------------------
 
 --------------CENTERED-------------------
diff --git a/examples/idas/serial/idasSlCrank_dns.c b/examples/idas/serial/idasSlCrank_dns.c
index fb1d782..bec0444 100644
--- a/examples/idas/serial/idasSlCrank_dns.c
+++ b/examples/idas/serial/idasSlCrank_dns.c
@@ -1,15 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer: Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
  * Simulation of a slider-crank mechanism modelled with 3 generalized
  * coordinates: crank angle, connecting bar angle, and slider location.
- * The mechanism moves under the action of a constant horizontal 
- * force applied to the connecting rod and a spring-damper connecting 
- * the crank and connecting rod.
+ * The mechanism moves under the action of a constant horizontal force
+ * applied to the connecting rod and a spring-damper connecting the crank
+ * and connecting rod.
  *
  * The equations of motion are formulated as a system of stabilized
  * index-2 DAEs (Gear-Gupta-Leimkuhler formulation).
@@ -23,14 +19,16 @@
  */
 
 #include <stdio.h>
-#include <math.h>
 #include <stdlib.h>
+#include <math.h>
 
-#include <idas/idas.h>
-#include <idas/idas_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_math.h>
-
+#include <idas/idas.h>                 /* prototypes for IDA fcts., consts.    */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix            */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver      */
+#include <idas/idas_direct.h>          /* access to IDADls interface           */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* defs. of SUNRabs, SUNRexp, etc.      */
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)       /* i-th vector component i= 1..NEQ */
 
@@ -71,10 +69,12 @@ static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_
 static void setIC(N_Vector yy, N_Vector yp, UserData data);
 static void force(N_Vector yy, realtype *Q, UserData data);
 
+/* Prototypes of private functions */
 static void PrintHeader(realtype rtol, realtype avtol, N_Vector y);
 static void PrintOutput(void *mem, realtype t, N_Vector y);
 static void PrintFinalStats(void *mem);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
+
 /*
  *--------------------------------------------------------------------
  * Main Program
@@ -89,6 +89,11 @@ int main(void)
   N_Vector yy, yp, id, q;
   realtype tret, tout;
   int flag;
+  SUNMatrix A;
+  SUNLinearSolver LS;
+
+  A = NULL;
+  LS = NULL;
 
   id = N_VNew_Serial(NEQ);
   yy = N_VNew_Serial(NEQ);
@@ -122,16 +127,25 @@ int main(void)
   flag = IDASStolerances(mem, RTOLF, ATOLF);
   flag = IDASetUserData(mem, data);
   flag = IDASetId(mem, id);
-  flag = IDASetSuppressAlg(mem, TRUE);
+  flag = IDASetSuppressAlg(mem, SUNTRUE);
   flag = IDASetMaxNumSteps(mem, 20000);
 
-  /* Call IDADense and set up the linear solver. */
-  flag = IDADense(mem, NEQ);
+  /* Create dense SUNMatrix for use in linear solves */
+  A = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)A, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(yy, A);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* Attach the matrix and linear solver */
+  flag = IDADlsSetLinearSolver(mem, LS, A);
+  if(check_flag(&flag, "IDADlsSetLinearSolver", 1)) return(1);
 
   N_VConst(ZERO, q);
   flag = IDAQuadInit(mem, rhsQ, q);
   flag = IDAQuadSStolerances(mem, RTOLQ, ATOLQ);
-  flag = IDASetQuadErrCon(mem, TRUE);
+  flag = IDASetQuadErrCon(mem, SUNTRUE);
 
   PrintHeader(RTOLF, ATOLF, yy);
 
@@ -152,12 +166,16 @@ int main(void)
     
     if (tret > TEND) break;
   }
-  
+
   PrintFinalStats(mem);
 
   IDAGetQuad(mem, &tret, q);
   printf("--------------------------------------------\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("  G = %24.16Lf\n", Ith(q,1));
+#else
   printf("  G = %24.16f\n", Ith(q,1));
+#endif  
   printf("--------------------------------------------\n\n");
   
   IDAFree(&mem);
@@ -165,6 +183,8 @@ int main(void)
   /* Free memory */
 
   free(data);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
   N_VDestroy(id);
   N_VDestroy_Serial(yy);
   N_VDestroy_Serial(yp);
@@ -268,9 +288,9 @@ static int ressc(realtype tres, N_Vector yy, N_Vector yp, N_Vector rr, void *use
   m2 = data->m2;
   J2 = data->J2;
 
-  yval = N_VGetArrayPointer_Serial(yy); 
-  ypval = N_VGetArrayPointer_Serial(yp); 
-  rval = N_VGetArrayPointer_Serial(rr);
+  yval = N_VGetArrayPointer(yy);
+  ypval = N_VGetArrayPointer(yp);
+  rval = N_VGetArrayPointer(rr);
 
   q = yval[0];
   x = yval[1];
@@ -335,7 +355,7 @@ static int rhsQ(realtype t, N_Vector yy, N_Vector yp, N_Vector qdot, void *user_
 static void PrintHeader(realtype rtol, realtype avtol, N_Vector y)
 {
   printf("\nidasSlCrank_dns: Slider-Crank DAE serial example problem for IDAS\n");
-  printf("Linear solver: IDADENSE, Jacobian is computed by IDAS.\n");
+  printf("Linear solver: DENSE, Jacobian is computed by IDAS.\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION)
   printf("Tolerance parameters:  rtol = %Lg   atol = %Lg\n",
          rtol, avtol);
@@ -352,7 +372,6 @@ static void PrintHeader(realtype rtol, realtype avtol, N_Vector y)
   printf("-----------------------------------------------------------------------\n");
 }
 
-
 static void PrintOutput(void *mem, realtype t, N_Vector y)
 {
   realtype *yval;
@@ -403,31 +422,41 @@ static void PrintFinalStats(void *mem)
   printf("Number of nonlinear conv. failures = %ld\n", ncfn);
 }
 
+/*
+ * Check function return value...
+ *   opt == 0 means SUNDIALS function allocates memory so check if
+ *            returned NULL pointer
+ *   opt == 1 means SUNDIALS function returns a flag so check if
+ *            flag >= 0
+ *   opt == 2 means function allocates memory so check if returned
+ *            NULL pointer 
+ */
+
 static int check_flag(void *flagvalue, const char *funcname, int opt)
 {
   int *errflag;
-
   /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
   if (opt == 0 && flagvalue == NULL) {
-    fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
-	    funcname);
-    return(1); }
-
-  /* Check if flag < 0 */
-  else if (opt == 1) {
+    fprintf(stderr, 
+            "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n", 
+            funcname);
+    return(1);
+  } else if (opt == 1) {
+    /* Check if flag < 0 */
     errflag = (int *) flagvalue;
     if (*errflag < 0) {
-      fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
-	      funcname, *errflag);
-      return(1); }}
-
-  /* Check if function returned NULL pointer - no memory allocated */
-  else if (opt == 2 && flagvalue == NULL) {
-    fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n",
-	    funcname);
-    return(1); }
+      fprintf(stderr, 
+              "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n", 
+              funcname, *errflag);
+      return(1); 
+    }
+  } else if (opt == 2 && flagvalue == NULL) {
+    /* Check if function returned NULL pointer - no memory allocated */
+    fprintf(stderr, 
+            "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n", 
+            funcname);
+    return(1);
+  }
 
   return(0);
 }
-
-
diff --git a/examples/idas/serial/idasSlCrank_dns.out b/examples/idas/serial/idasSlCrank_dns.out
index 0bfcbf2..075f901 100644
--- a/examples/idas/serial/idasSlCrank_dns.out
+++ b/examples/idas/serial/idasSlCrank_dns.out
@@ -1,6 +1,6 @@
 
 idasSlCrank_dns: Slider-Crank DAE serial example problem for IDAS
-Linear solver: IDADENSE, Jacobian is computed by IDAS.
+Linear solver: DENSE, Jacobian is computed by IDAS.
 Tolerance parameters:  rtol = 1e-06   atol = 1e-07
 -----------------------------------------------------------------------
   t         y1          y2           y3      | nst  k      h
@@ -41,6 +41,6 @@ Number of nonlinear iterations     = 676
 Number of error test failures      = 1
 Number of nonlinear conv. failures = 0
 --------------------------------------------
-  G =       3.3366160663212514
+  G =       3.3366160663047912
 --------------------------------------------
 
diff --git a/examples/kinsol/C_openmp/CMakeLists.txt b/examples/kinsol/C_openmp/CMakeLists.txt
index 06c937f..274fa03 100644
--- a/examples/kinsol/C_openmp/CMakeLists.txt
+++ b/examples/kinsol/C_openmp/CMakeLists.txt
@@ -19,75 +19,83 @@
 # For details, see the LICENSE file.
 # -----------------------------------------------------------------
 # CMakeLists.txt file for KINSOL OpenMP examples
+# -----------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
 # Only include tests if OpenMP is enabled
 IF(OPENMP_FOUND)
 
-# Add variable KINSOL_examples_OMP with the names of the openmp KINSOL examples
-SET(KINSOL_examples_OMP
-  kinFoodWeb_kry_omp
-  )
+  # Examples using SUNDIALS linear solvers
+  SET(KINSOL_examples
+    "kinFoodWeb_kry_omp\;4\;develop"
+    )
 
 ENDIF(OPENMP_FOUND)
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(KINSOL_LIB sundials_kinsol_static)
   SET(NVECOMP_LIB sundials_nvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(KINSOL_LIB sundials_kinsol_shared)
   SET(NVECOMP_LIB sundials_nvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${KINSOL_LIB} ${NVECOMP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
 # update the compilation flags to include OpenMP support
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 
-# Add the build and install targets for each KINSOL example
-FOREACH(example ${KINSOL_examples_OMP})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${KINSOL_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  #SUNDIALS_ADD_TEST(${example} ${example} TEST_ARGS 4) # No test until TestRunner modified for OpenMP
+
+  IF (NOT ${example} MATCHES "kinFoodWeb_kry_omp") # No test until TestRunner modified for OpenMP
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      TEST_ARGS ${example_args}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+  ENDIF()
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/C_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${KINSOL_examples_OMP})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/C_openmp)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${KINSOL_examples_OMP})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
   INSTALL(FILES README DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/C_openmp)
 
-  # Install the extra files
-  FOREACH(extrafile ${KINSOL_extras_OMP})
-    INSTALL(FILES ${extrafile} DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/C_openmp)
-  ENDFOREACH(extrafile ${KINSOL_extras_OMP})
-
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "KINSOL")
   SET(SOLVER_LIB "sundials_kinsol")
-  LIST2STRING(KINSOL_examples_OMP EXAMPLES)
-
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
 
+  EXAMPLES2STRING(KINSOL_examples EXAMPLES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -95,10 +103,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/kinsol/C_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/kinsol/C_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/kinsol/C_openmp/README b/examples/kinsol/C_openmp/README
index 56fb7dd..7d3dbe2 100644
--- a/examples/kinsol/C_openmp/README
+++ b/examples/kinsol/C_openmp/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/kinsol/C_openmp/kinFoodWeb_kry_omp.c b/examples/kinsol/C_openmp/kinFoodWeb_kry_omp.c
index c50b8c9..ecdd76d 100644
--- a/examples/kinsol/C_openmp/kinFoodWeb_kry_omp.c
+++ b/examples/kinsol/C_openmp/kinFoodWeb_kry_omp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:  $
- * $Date:  $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Ting Yan @ SMU
  *      Based on kinFoodWeb_kry.c and parallelized with OpenMP
  * -----------------------------------------------------------------
@@ -13,10 +9,10 @@
  * population model, with predator-prey interaction and diffusion
  * on the unit square in two dimensions. The dependent variable
  * vector is the following:
- * 
+ *
  *       1   2         ns
  * c = (c , c ,  ..., c  )     (denoted by the variable cc)
- * 
+ *
  * and the PDE's are as follows:
  *
  *                    i       i
@@ -51,9 +47,9 @@
  *
  * The PDEs are discretized by central differencing on an MX by
  * MY mesh.
- * 
+ *
  * The nonlinear system is solved by KINSOL using the method
- * specified in local variable globalstrat.
+ * specified in the local variable globalstrat.
  *
  * The preconditioner matrix is a block-diagonal matrix based on
  * the partial derivatives of the interaction terms f only.
@@ -61,19 +57,19 @@
  * Constraints are imposed to make all components of the solution
  * positive.
  *
- * Optionally, we can set the number of threads from environment 
- * variable or command line. To check the current value for number
- * of threads from environment:
+ * Optionally, we can set the number of threads with an environment
+ * variable or from the command line. To check the current value
+ * for number of threads set by the environment variable:
  *      % echo $OMP_NUM_THREADS
  *
  * Execution:
  *
- * If the user want to use the default value or the number of threads 
- * from environment value:
+ * If the user wants to use the default value or the number of
+ * threads set by the environment variable use
  *      % ./kinFoodWeb_kry_omp 
- * If the user want to specify the number of threads to use
+ * If the user wants to specify the number of threads to use
  *      % ./kinFoodWeb_kry_omp num_threads
- * where num_threads is the number of threads the user want to use 
+ * where num_threads is the number of threads the user wants to use
  *
  * -----------------------------------------------------------------
  * References:
@@ -96,12 +92,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_spgmr.h>
-#include <nvector/nvector_openmp.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts.      */
+#include <nvector/nvector_openmp.h>    /* access to OpenMP N_Vector            */
+#include <kinsol/kinsol_spils.h>       /* access to KINSpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* access to SUNMAX, SUNRabs, SUNRsqrt  */
 
 #ifdef _OPENMP
 #include <omp.h>
@@ -130,7 +127,7 @@
 #define FTOL        RCONST(1.e-7)  /* ftol tolerance */
 #define STOL        RCONST(1.e-13) /* stol tolerance */
 #define THOUSAND    RCONST(1000.0) /* one thousand */
-#define ZERO        RCONST(0.)     /* 0. */
+#define ZERO        RCONST(0.0)    /* 0. */
 #define ONE         RCONST(1.0)    /* 1. */
 #define TWO         RCONST(2.0)    /* 2. */
 #define PREYIN      RCONST(1.0)    /* initial guess for prey concentrations. */
@@ -150,13 +147,13 @@
 
 typedef struct {
   realtype **P[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   realtype **acoef, *bcoef;
   N_Vector rates;
   realtype *cox, *coy;
   realtype ax, ay, dx, dy;
   realtype uround, sqruround;
-  long int mx, my, ns, np;
+  sunindextype mx, my, ns, np;
   int nthreads;
 } *UserData;
 
@@ -166,13 +163,11 @@ static int func(N_Vector cc, N_Vector fval, void *user_data);
 
 static int PrecSetupBD(N_Vector cc, N_Vector cscale,
                        N_Vector fval, N_Vector fscale,
-                       void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2);
+                       void *user_data);
 
 static int PrecSolveBD(N_Vector cc, N_Vector cscale, 
                        N_Vector fval, N_Vector fscale, 
-                       N_Vector vv, void *user_data,
-                       N_Vector ftem);
+                       N_Vector vv, void *user_data);
 
 /* Private Helper Functions */
 
@@ -186,8 +181,8 @@ static void PrintOutput(N_Vector cc);
 static void PrintFinalStats(void *kmem);
 static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                     void *user_data);
-static realtype DotProd(long int size, realtype *x1, realtype *x2);
-static int check_flag(void *flagvalue, char *funcname, int opt);
+static realtype DotProd(sunindextype size, realtype *x1, realtype *x2);
+static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /*
  *--------------------------------------------------------------------
@@ -203,10 +198,12 @@ int main(int argc, char *argv[])
   UserData data;
   int flag, maxl, maxlrst;
   void *kmem;
+  SUNLinearSolver LS;
   int num_threads;
 
   cc = sc = constraints = NULL;
   kmem = NULL;
+  LS = NULL;
   data = NULL;
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
@@ -263,15 +260,23 @@ int main(int argc, char *argv[])
      creates a private copy for KINSOL to use. */
   N_VDestroy_OpenMP(constraints);
 
-  /* Call KINSpgmr to specify the linear solver KINSPGMR with preconditioner
-     routines PrecSetupBD and PrecSolveBD. */
+
+  /* Create SUNSPGMR object with right preconditioning and the 
+     maximum Krylov dimension maxl */
   maxl = 15; 
+  LS = SUNSPGMR(cc, PREC_RIGHT, maxl);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Attach the linear solver to KINSOL */
+  flag = KINSpilsSetLinearSolver(kmem, LS);
+  if (check_flag(&flag, "KINSpilsSetLinearSolver", 1)) return 1;
+
+  /* Set the maximum number of restarts */
   maxlrst = 2;
-  flag = KINSpgmr(kmem, maxl);
-  if (check_flag(&flag, "KINSpgmr", 1)) return(1);
+  flag = SUNSPGMRSetMaxRestarts(LS, maxlrst);
+  if (check_flag(&flag, "SUNSPGMRSpilsSetMaxRestarts", 1)) return(1);
 
-  flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
-  if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1)) return(1);
+  /* Specify the preconditioner setup and solve routines */
   flag = KINSpilsSetPreconditioner(kmem,
 				   PrecSetupBD,
 				   PrecSolveBD);
@@ -284,7 +289,7 @@ int main(int argc, char *argv[])
   flag = KINSol(kmem,           /* KINSol memory block */
                 cc,             /* initial guess on input; solution vector */
                 globalstrategy, /* global strategy choice */
-                sc,             /* scaling vector, for the variable cc */
+                sc,             /* scaling vector for the variable cc */
                 sc);            /* scaling vector for function values fval */
   if (check_flag(&flag, "KINSol", 1)) return(1);
 
@@ -298,6 +303,7 @@ int main(int argc, char *argv[])
   N_VDestroy_OpenMP(cc);
   N_VDestroy_OpenMP(sc);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
   FreeUserData(data);
 
   return(0);
@@ -323,7 +329,7 @@ int main(int argc, char *argv[])
 static int func(N_Vector cc, N_Vector fval, void *user_data)
 {
   realtype xx, yy, delx, dely, *cxy, *rxy, *fxy, dcyli, dcyui, dcxli, dcxri;
-  long int jx, jy, is, idyu, idyl, idxr, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxr, idxl;
   UserData data;
   
   data = (UserData)user_data;
@@ -383,12 +389,11 @@ static int func(N_Vector cc, N_Vector fval, void *user_data)
 
 static int PrecSetupBD(N_Vector cc, N_Vector cscale,
                        N_Vector fval, N_Vector fscale,
-                       void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2)
+                       void *user_data)
 {
   realtype r, r0, uround, sqruround, xx, yy, delx, dely, csave, fac;
   realtype *cxy, *scxy, **Pxy, *ratesxy, *Pxycol, perturb_rates[NUM_SPECIES];
-  long int i, j, jx, jy, ret;
+  sunindextype i, j, jx, jy, ret;
   UserData data;
   
   data = (UserData) user_data;
@@ -411,7 +416,7 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
       cxy = IJ_Vptr(cc,jx,jy);
       scxy= IJ_Vptr(cscale,jx,jy);
       ratesxy = IJ_Vptr((data->rates),jx,jy);
-      
+
       /* Compute difference quotients of interaction rate fn. */
       for (j = 0; j < NUM_SPECIES; j++) {
         
@@ -432,7 +437,6 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
         for (i = 0; i < NUM_SPECIES; i++)
           Pxycol[i] = (perturb_rates[i] - ratesxy[i]) * fac;
         
-        
       } /* end of j loop */
       
       /* Do LU decomposition of size NUM_SPECIES preconditioner block */
@@ -443,7 +447,7 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
     
   } /* end of jy loop */
   
-  return(0);  
+  return(0);
 }
 
 /*
@@ -452,11 +456,10 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
 
 static int PrecSolveBD(N_Vector cc, N_Vector cscale, 
                        N_Vector fval, N_Vector fscale, 
-                       N_Vector vv, void *user_data,
-                       N_Vector ftem)
+                       N_Vector vv, void *user_data)
 {
   realtype **Pxy, *vxy;
-  long int *piv, jx, jy;
+  sunindextype *piv, jx, jy;
   UserData data;
   
   data = (UserData)user_data;
@@ -489,7 +492,7 @@ static int PrecSolveBD(N_Vector cc, N_Vector cscale,
 static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                     void *user_data)
 {
-  long int i;
+  sunindextype i;
   realtype fac;
   UserData data;
   
@@ -502,22 +505,22 @@ static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
   
 #pragma omp parallel for default(shared) private(i) 
   for (i = 0; i < NUM_SPECIES; i++)
-    ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );  
+    ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );
 }
 
 /*
  * Dot product routine for realtype arrays 
  */
 
-static realtype DotProd(long int size, realtype *x1, realtype *x2)
+static realtype DotProd(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
   for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
 
-  return(temp);  
+  return(temp);
 }
 
 /*
@@ -540,9 +543,10 @@ static UserData AllocUserData(void)
   for (jx=0; jx < MX; jx++) {
     for (jy=0; jy < MY; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
+
   acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
   bcoef = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
   cox   = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
@@ -551,13 +555,13 @@ static UserData AllocUserData(void)
   return(data);
 }
 
-/* 
+/*
  * Load problem constants in data 
  */
 
 static void InitUserData(UserData data)
 {
-  long int i, j, np;
+  sunindextype i, j, np;
   realtype *a1,*a2, *a3, *a4, dx2, dy2;
 
   data->mx = MX;
@@ -602,24 +606,24 @@ static void InitUserData(UserData data)
 
     coy[i]=DPREY/dy2;
     coy[i+np]=DPRED/dy2;
-  }  
+  }
 }
 
-/* 
+/*
  * Free data memory 
  */
 
 static void FreeUserData(UserData data)
 {
   int jx, jy;
-  
+
   for (jx=0; jx < MX; jx++) {
     for (jy=0; jy < MY; jy++) {
       destroyMat((data->P)[jx][jy]);
       destroyArray((data->pivot)[jx][jy]);
     }
   }
-  
+
   destroyMat(acoef);
   free(bcoef);
   free(cox);
@@ -628,7 +632,7 @@ static void FreeUserData(UserData data)
   free(data);
 }
 
-/* 
+/*
  * Set initial conditions in cc 
  */
 
@@ -705,7 +709,7 @@ static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
 #endif
 }
 
-/* 
+/*
  * Print sampled values of current cc 
  */
 
@@ -748,7 +752,7 @@ static void PrintOutput(N_Vector cc)
   printf("\n\n");
 }
 
-/* 
+/*
  * Print final statistics contained in iopt 
  */
 
@@ -756,7 +760,7 @@ static void PrintFinalStats(void *kmem)
 {
   long int nni, nfe, nli, npe, nps, ncfl, nfeSG;
   int flag;
-  
+
   flag = KINGetNumNonlinSolvIters(kmem, &nni);
   check_flag(&flag, "KINGetNumNonlinSolvIters", 1);
   flag = KINGetNumFuncEvals(kmem, &nfe);
@@ -776,7 +780,7 @@ static void PrintFinalStats(void *kmem)
   printf("nni    = %5ld    nli   = %5ld\n", nni, nli);
   printf("nfe    = %5ld    nfeSG = %5ld\n", nfe, nfeSG);
   printf("nps    = %5ld    npe   = %5ld     ncfl  = %5ld\n", nps, npe, ncfl);
-  
+
 }
 
 /*
@@ -789,7 +793,7 @@ static void PrintFinalStats(void *kmem)
  *             NULL pointer 
  */
 
-static int check_flag(void *flagvalue, char *funcname, int opt)
+static int check_flag(void *flagvalue, const char *funcname, int opt)
 {
   int *errflag;
 
@@ -808,7 +812,7 @@ static int check_flag(void *flagvalue, char *funcname, int opt)
       fprintf(stderr,
               "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
 	      funcname, *errflag);
-      return(1); 
+      return(1);
     }
   }
 
diff --git a/examples/kinsol/fcmix_parallel/CMakeLists.txt b/examples/kinsol/fcmix_parallel/CMakeLists.txt
index d3f5d60..7c352d6 100644
--- a/examples/kinsol/fcmix_parallel/CMakeLists.txt
+++ b/examples/kinsol/fcmix_parallel/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4096 $
-# $Date: 2014-05-02 14:49:50 -0700 (Fri, 02 May 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -15,77 +12,84 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the FKINSOL parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable kinsol_examples with the names of the parallel KINSOL examples
-
+# Examples using SUNDIALS linear solvers
 SET(FKINSOL_examples
-  "fkinDiagon_kry_p\;1\;4"
+  "fkinDiagon_kry_p\;1\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the Fortran compiler to the MPIF77 script.
 # If not, then add the MPI include directory for MPI headers.
-
-IF(MPI_MPIF77 )
+IF(MPI_MPIF77)
   # use MPI_MPIF77 as the compiler
   SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
-ELSE(MPI_MPIF77)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPIF77)
+ENDIF()
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(KINSOL_LIB sundials_kinsol_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
   SET(FNVECP_LIB sundials_fnvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(KINSOL_LIB sundials_kinsol_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
   SET(FNVECP_LIB sundials_fnvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FKINSOL_LIB sundials_fkinsol_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FKINSOL_LIB} ${KINSOL_LIB} ${FNVECP_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FKINSOL_examples})
 
-# Add the build and install targets for each KINSOL example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
 
-FOREACH(example_tuple ${FKINSOL_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+  
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPIF77)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPIF77)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${FKINSOL_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -95,10 +99,8 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "KINSOL")
   SET(SOLVER_LIB "sundials_kinsol")
   SET(SOLVER_FLIB "sundials_fkinsol")
-  FOREACH(example_tuple ${FKINSOL_examples})
-    list(GET example_tuple 0 example)
-    LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${FKINSOL_examples})
+
+  EXAMPLES2STRING(FKINSOL_examples EXAMPLES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -106,10 +108,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
@@ -137,4 +139,3 @@ IF(EXAMPLES_INSTALL)
   ENDIF(UNIX)
 
 ENDIF(EXAMPLES_INSTALL)
-
diff --git a/examples/kinsol/fcmix_parallel/README b/examples/kinsol/fcmix_parallel/README
index 1c00d9e..4b77b95 100644
--- a/examples/kinsol/fcmix_parallel/README
+++ b/examples/kinsol/fcmix_parallel/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f b/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f
index bebff32..50899c9 100644
--- a/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f
+++ b/examples/kinsol/fcmix_parallel/fkinDiagon_kry_p.f
@@ -1,22 +1,18 @@
       program fkinDiagon_kry_p
 c     ----------------------------------------------------------------
-c     $Revision: 4881 $
-c     $Date: 2016-09-01 15:31:14 -0700 (Thu, 01 Sep 2016) $
-c     ----------------------------------------------------------------
 c     Programmer(s): Allan G. Taylor, Alan C. Hindmarsh and
 c                    Radu Serban @ LLNL
 c     ----------------------------------------------------------------
-c     Simple diagonal test with Fortran interface, using
-c     user-supplied preconditioner setup and solve routines (supplied
-c     in Fortran, below).
+c     Simple diagonal test with Fortran interface, using user-supplied
+c     preconditioner setup and solve routines (supplied in Fortran).
 c
 c     This example does a basic test of the solver by solving the
 c     system:
 c               f(u) = 0  for
 c               f(u) = u(i)^2 - i^2
 c
-c      No scaling is done.
-c      An approximate diagonal preconditioner is used.
+c     No scaling is done.
+c     An approximate diagonal preconditioner is used.
 c
 c      Execution command: mpirun -np 4 fkinDiagon_kry_p
 c     ----------------------------------------------------------------
@@ -28,13 +24,12 @@ c
       integer localsize
       parameter(localsize=32)
       integer baseadd, i, ii
-      integer ier, size, globalstrat, rank, mype, npes
-      integer maxl, maxlrst
+      integer size, rank, mype, npes
 c The following declaration specification should match C type long int.
       integer*8 neq, nlocal, iout(15), msbpre
-      double precision rout(2)
+      integer ier, globalstrat, prectype, maxl, maxlrst
       double precision pp, fnormtol, scsteptol
-      double precision uu(localsize), scale(localsize)
+      double precision rout(2), uu(localsize), scale(localsize)
       double precision constr(localsize)
 
       common /pcom/ pp(localsize), nlocal, mype, npes, baseadd
@@ -44,6 +39,7 @@ c The following declaration specification should match C type long int.
       globalstrat = 0
       fnormtol = 1.0d-5
       scsteptol = 1.0d-4
+      prectype = 2
       maxl = 10
       maxlrst = 2
       msbpre  = 5
@@ -79,8 +75,8 @@ c     number of this process.
       endif
       
       if (size .ne. 4) then
-         write(6,1230)
- 1230    format('MPI_ERROR: must use 4 processes')
+         write(6,1223)
+ 1223    format('MPI_ERROR: must use 4 processes')
          call mpi_finalize(ier)
          stop
       endif
@@ -95,7 +91,7 @@ c     number of this process.
       endif
 
       mype = rank
-      baseadd = mype * nlocal 
+      baseadd = mype * nlocal
 
       do 20 ii = 1, nlocal
          i = ii + baseadd
@@ -106,28 +102,106 @@ c     number of this process.
       
       call fkincreate(ier)
       if (ier .ne. 0) then
-         write(6,1231)ier
- 1231    format('SUNDIALS_ERROR: FKINCREATE returned IER = ', i4)
+         write(6,1230) ier
+ 1230    format('SUNDIALS_ERROR: FKINCREATE returned IER = ', i4)
          call mpi_abort(mpi_comm_world, 1, ier)
          stop
       endif
-      
+
       call fkinsetiin('MAX_SETUPS', msbpre, ier)
+      if (ier .ne. 0) then
+         write(6,1231) ier
+ 1231    format('SUNDIALS_ERROR: FKINSETIIN returned IER = ', i4)
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+
       call fkinsetrin('FNORM_TOL', fnormtol, ier)
+      if (ier .ne. 0) then
+         write(6,1232) ier
+ 1232    format('SUNDIALS_ERROR: FKINSETRIN returned IER = ', i4)
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+
       call fkinsetrin('SSTEP_TOL', scsteptol, ier)
-      call fkinsetvin('CONSTR_VEC', constr, ier)
+      if (ier .ne. 0) then
+         write(6,1232) ier
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
 
+      call fkinsetvin('CONSTR_VEC', constr, ier)
+      if (ier .ne. 0) then
+         write(6,1233) ier
+ 1233    format('SUNDIALS_ERROR: FKINSETVIN returned IER = ', i4)
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+c
+c Initialize KINSOL
+c
       call fkininit(iout, rout, ier)
       if (ier .ne. 0) then
-         write(6,1232)ier
- 1232    format('SUNDIALS_ERROR: FKININIT returned IER = ', i4)
+         write(6,1234) ier
+ 1234    format('SUNDIALS_ERROR: FKININIT returned IER = ', i4)
+         call fkinfree
          call mpi_abort(mpi_comm_world, 1, ier)
          stop
       endif
-
-      call fkinspgmr(maxl, maxlrst, ier)
+c
+c Initialize SPGMR linear solver module with right preconditioning
+c and maximum Krylov dimension maxl
+c
+      call fsunspgmrinit(3, prectype, maxl, ier)
+      if (ier .ne. 0) then
+         write(6,1235) ier
+ 1235    format('SUNDIALS_ERROR: FSUNSPGMRLINSOLINIT returned IER = ',
+     1          i4)
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+c
+c Attach SPGMR linear solver module to KINSOL
+c
+      call fkinspilsinit(ier)
+      if (ier .ne. 0) then
+         write(6,1236) ier
+ 1236    format('SUNDIALS_ERROR: FKINSPILSINIT returned IER = ', i4)
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+c
+c Set the maximum number of SPGMR restarts to maxlrst
+c
+      call fsunspgmrsetmaxrs(3, maxlrst, ier)
+      if (ier .ne. 0) then
+         write(6,1237) ier
+ 1237    format('SUNDIALS_ERROR: FSUNSPGRM_SETMATRS returned IER = ',
+     1          i4)
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+c
+c Set preconditioner routines
+c
       call fkinspilssetprec(1, ier)
-      
+      if (ier .ne. 0) then
+         write(6,1238) ier
+ 1238    format('SUNDIALS_ERROR: FKINSPILSSETPREC returned IER = ',
+     1          i4)
+         call fkinfree
+         call mpi_abort(mpi_comm_world, 1, ier)
+         stop
+      endif
+
       if (mype .eq. 0) write(6,1240)
  1240 format('Example program fkinDiagon_kry_p:'//
      1       ' This FKINSOL example',
@@ -140,6 +214,7 @@ c     number of this process.
          write(6,1242) ier, iout(9)
  1242    format('SUNDIALS_ERROR: FKINSOL returned IER = ', i4, /,
      1          '                Linear Solver returned IER = ', i4)
+         call fkinfree
          call mpi_abort(mpi_comm_world, 1, ier)
          stop
       endif
@@ -149,7 +224,7 @@ c     number of this process.
 
       if (mype .eq. 0) write(6,1246)
  1246 format(/' The resultant values of uu (process 0) are:'/)
-      
+
       do 30 i = 1, nlocal, 4
          if(mype .eq. 0) write(6,1256) i + baseadd, uu(i), uu(i+1),
      1                                 uu(i+2), uu(i+3)
@@ -164,26 +239,27 @@ c     number of this process.
      3     '  nps = ', i3, ',  ncfl = ', i3)
 
       call fkinfree
-      
-c     An explicit call to mpi_finalize (Fortran binding) is required by 
-c     the constructs used in fkinsol. 
+
+c     An explicit call to mpi_finalize (Fortran binding) is required by
+c     the constructs used in fkinsol.
       call mpi_finalize(ier)
-      
+
       stop
       end
       
 
 c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 c     The function defining the system f(u) = 0 must be defined by a Fortran
-c     function with the following name and form. 
+c     function with the following name and form.
       
       subroutine fkfun(uu, fval, ier)
 
       implicit none
 
+      integer ier, i
 c The following declaration specification should match C type long int.
       integer*8 nlocal
-      integer ier, mype, npes, baseadd, i
+      integer mype, npes, baseadd
       integer localsize
       parameter(localsize=32)
       double precision pp
@@ -193,9 +269,9 @@ c The following declaration specification should match C type long int.
 
       do 10 i = 1, nlocal
  10      fval(i) = uu(i) * uu(i) - (i + baseadd) * (i + baseadd)
-      
+
       ier = 0
-      
+
       return
       end
       
@@ -205,24 +281,23 @@ c     The routine kpreco is the preconditioner setup routine. It must have
 c     that specific name be used in order that the c code can find and link
 c     to it.  The argument list must also be as illustrated below:
       
-      subroutine fkpset(udata, uscale, fdata, fscale, 
-     1                  vtemp1, vtemp2, ier)
+      subroutine fkpset(udata, uscale, fdata, fscale, ier)
 
       implicit none
 
+      integer ier, i
 c The following declaration specification should match C type long int.
       integer*8 nlocal
-      integer ier, mype, npes, baseadd, i
+      integer mype, npes, baseadd
       integer localsize
       parameter(localsize=32)
       double precision pp
       double precision udata(*), uscale(*), fdata(*), fscale(*)
-      double precision vtemp1(*), vtemp2(*)
 
       common /pcom/ pp(localsize), nlocal, mype, npes, baseadd
 
       do 10 i = 1, nlocal
- 10      pp(i) = 0.5d0 / (udata(i)+ 5.0d0)
+ 10      pp(i) = 0.5d0 / (udata(i) + 5.0d0)
 
       ier = 0
 
@@ -235,19 +310,18 @@ c     The routine kpsol is the preconditioner solve routine. It must have
 c     that specific name be used in order that the c code can find and link
 c     to it.  The argument list must also be as illustrated below:
       
-      subroutine fkpsol(udata, uscale, fdata, fscale, 
-     1                  vv, ftem, ier)
+      subroutine fkpsol(udata, uscale, fdata, fscale, vv, ier)
 
       implicit none
 
+      integer ier, i
 c The following declaration specification should match C type long int.
       integer*8 nlocal
-      integer ier, mype, npes, baseadd, i
+      integer mype, npes, baseadd
       integer localsize
       parameter(localsize=32)
-      double precision udata(*), uscale(*), fdata(*), fscale(*)
-      double precision vv(*), ftem(*)
       double precision pp
+      double precision udata(*), uscale(*), fdata(*), fscale(*), vv(*)
 
       common /pcom/ pp(localsize), nlocal, mype, npes, baseadd
 
diff --git a/examples/kinsol/fcmix_serial/CMakeLists.txt b/examples/kinsol/fcmix_serial/CMakeLists.txt
index d739119..9b9afc2 100644
--- a/examples/kinsol/fcmix_serial/CMakeLists.txt
+++ b/examples/kinsol/fcmix_serial/CMakeLists.txt
@@ -1,8 +1,5 @@
 # ---------------------------------------------------------------
-# $Revision: 4096 $
-# $Date: 2014-05-02 14:49:50 -0700 (Fri, 02 May 2014) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer: Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
@@ -15,80 +12,66 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the FKINSOL serial examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
-# Add variable kinsol_examples with the names of the serial FKINSOL examples
-
+# Examples using SUNDIALS linear solvers
 SET(FKINSOL_examples
-  fkinDiagon_kry
-  )
-
-# Add variable FKINSOL_examples_BL with the names of the serial FKINSOL examples
-# that use Lapack
-
-SET(FKINSOL_examples_BL
+  "fkinDiagon_kry\;develop"
   )
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(KINSOL_LIB sundials_kinsol_static)
   SET(NVECS_LIB sundials_nvecserial_static)
   SET(FNVECS_LIB sundials_fnvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(KINSOL_LIB sundials_kinsol_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
   SET(FNVECS_LIB sundials_fnvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Only static FCMIX libraries are available
-
 SET(FKINSOL_LIB sundials_fkinsol_static)
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${FKINSOL_LIB} ${KINSOL_LIB} ${FNVECS_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${FKINSOL_examples})
 
-# Add the build and install targets for each FKINSOL example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${FKINSOL_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+   # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${FKINSOL_examples})
-
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
-
-IF(LAPACK_FOUND)
-  FOREACH(example ${FKINSOL_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.f)
-    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-    IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.f ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${FKINSOL_examples_BL})
-ENDIF(LAPACK_FOUND)
+    INSTALL(FILES ${example}.f ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/fcmix_serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${FKINSOL_examples})
 
 
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -98,12 +81,8 @@ IF(EXAMPLES_INSTALL)
   SET(SOLVER "KINSOL")
   SET(SOLVER_LIB "sundials_kinsol")
   SET(SOLVER_FLIB "sundials_fkinsol")
-  LIST2STRING(FKINSOL_examples EXAMPLES)
-  IF(LAPACK_FOUND)
-    LIST2STRING(FKINSOL_examples_BL EXAMPLES_BL)
-  ELSE(LAPACK_FOUND)
-    SET(EXAMPLES_BL "")
-  ENDIF(LAPACK_FOUND)
+
+  EXAMPLES2STRING(FKINSOL_examples EXAMPLES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -111,10 +90,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
-      ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_F77_ex.in
+    ${PROJECT_BINARY_DIR}/examples/kinsol/fcmix_serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/kinsol/fcmix_serial/README b/examples/kinsol/fcmix_serial/README
index d23c56f..887fae9 100644
--- a/examples/kinsol/fcmix_serial/README
+++ b/examples/kinsol/fcmix_serial/README
@@ -7,7 +7,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -18,7 +17,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -32,7 +34,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/kinsol/fcmix_serial/fkinDiagon_kry.f b/examples/kinsol/fcmix_serial/fkinDiagon_kry.f
index 87f1553..9e0edc8 100644
--- a/examples/kinsol/fcmix_serial/fkinDiagon_kry.f
+++ b/examples/kinsol/fcmix_serial/fkinDiagon_kry.f
@@ -1,10 +1,7 @@
       program fkinDiagon_kry
 c     ----------------------------------------------------------------
-c     $Revision: 4881 $
-c     $Date: 2016-09-01 15:31:14 -0700 (Thu, 01 Sep 2016) $
-c     ----------------------------------------------------------------
-c     Programmer(s): Allan Taylor, Alan Hindmarsh and
-c                    Radu Serban @ LLNL  
+c     Programmer(s): Allan G. Taylor, Alan C. Hindmarsh and
+c                    Radu Serban @ LLNL
 c     ----------------------------------------------------------------
 c     Simple diagonal test with Fortran interface, using user-supplied
 c     preconditioner setup and solve routines (supplied in Fortran).
@@ -25,7 +22,7 @@ c
       parameter(PROBSIZE=128)
 c The following declaration specification should match C type long int.
       integer*8 neq, iout(15), msbpre
-      integer ier, globalstrat, maxl, maxlrst, i
+      integer ier, globalstrat, prectype, maxl, maxlrst, i
       double precision pp, fnormtol, scsteptol
       double precision rout(2), uu(PROBSIZE), scale(PROBSIZE)
       double precision constr(PROBSIZE)
@@ -37,6 +34,7 @@ c The following declaration specification should match C type long int.
       globalstrat = 0
       fnormtol = 1.0d-5
       scsteptol = 1.0d-4
+      prectype = 2
       maxl = 10
       maxlrst = 2
       msbpre  = 5
@@ -93,23 +91,60 @@ c * * * * * * * * * * * * * * * * * * * * * *
          call fkinfree
          stop
       endif
-
+c
+c Initialize KINSOL
+c
       call fkininit(iout, rout, ier)
       if (ier .ne. 0) then
          write(6,1234) ier
  1234    format('SUNDIALS_ERROR: FKININIT returned IER = ', i4)
+         call fkinfree
          stop
       endif
-
-      call fkinspgmr(maxl, maxlrst, ier)
+c
+c Initialize SPGMR linear solver module with right preconditioning
+c and maximum Krylov dimension maxl
+c
+      call fsunspgmrinit(3, prectype, maxl, ier)
       if (ier .ne. 0) then
          write(6,1235) ier
- 1235    format('SUNDIALS_ERROR: FKINSPGMR returned IER = ', i4)
+ 1235    format('SUNDIALS_ERROR: FSUNSPGMRLINSOLINIT returned IER = ',
+     1          i4)
          call fkinfree
          stop
       endif
-
+c
+c Attach SPGMR linear solver module to KINSOL
+c
+      call fkinspilsinit(ier)
+      if (ier .ne. 0) then
+         write(6,1236) ier
+ 1236    format('SUNDIALS_ERROR: FKINSPILSINIT returned IER = ', i4)
+         call fkinfree
+         stop
+      endif
+c
+c Set the maximum number of SPGMR restarts to maxlrst
+c
+      call fsunspgmrsetmaxrs(3, maxlrst, ier)
+      if (ier .ne. 0) then
+         write(6,1237) ier
+ 1237    format('SUNDIALS_ERROR: FSUNSPGRM_SETMATRS returned IER = ',
+     1          i4)
+         call fkinfree
+         stop
+      endif
+c
+c Set preconditioner routines
+c
       call fkinspilssetprec(1, ier)
+      if (ier .ne. 0) then
+         write(6,1238) ier
+ 1238    format('SUNDIALS_ERROR: FKINSPILSSETPREC returned IER = ',
+     1          i4)
+         call fkinfree
+         stop
+      endif
 
       write(6,1240)
  1240 format('Example program fkinDiagon_kry:'//' This FKINSOL example',
@@ -152,7 +187,7 @@ c * * * * * * * * * * * * * * * * * * * * * *
       
 c * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 c     The function defining the system f(u) = 0 must be defined by a Fortran
-c     function of the following form.
+c     function with the following name and form.
       
       subroutine fkfun(uu, fval, ier)
 
@@ -166,8 +201,7 @@ c The following declaration specification should match C type long int.
       common /psize/ neq
 
       do 10 i = 1, neq
-         fval(i) = uu(i) * uu(i) - i * i
- 10   continue
+ 10      fval(i) = uu(i) * uu(i) - i * i
 
       ier = 0
 
@@ -180,8 +214,7 @@ c     The routine kpreco is the preconditioner setup routine. It must have
 c     that specific name be used in order that the c code can find and link
 c     to it.  The argument list must also be as illustrated below:
       
-      subroutine fkpset(udata, uscale, fdata, fscale, vtemp1, vtemp2,
-     1                  ier)
+      subroutine fkpset(udata, uscale, fdata, fscale, ier)
 
       implicit none
 
@@ -190,16 +223,15 @@ c The following declaration specification should match C type long int.
       integer*8 neq
       double precision pp
       double precision udata(*), uscale(*), fdata(*), fscale(*)
-      double precision vtemp1(*), vtemp2(*)
 
       common /pcom/ pp(128)
       common /psize/ neq
 
       do 10 i = 1, neq
-         pp(i) = 0.5d0 / (udata(i) + 5.0d0)
- 10   continue
+ 10      pp(i) = 0.5d0 / (udata(i) + 5.0d0)
+
       ier = 0
-      
+
       return
       end
       
@@ -209,7 +241,7 @@ c     The routine kpsol is the preconditioner solve routine. It must have
 c     that specific name be used in order that the c code can find and link
 c     to it.  The argument list must also be as illustrated below:
       
-      subroutine fkpsol(udata, uscale, fdata, fscale, vv, ftem, ier)
+      subroutine fkpsol(udata, uscale, fdata, fscale, vv, ier)
 
       implicit none
 
@@ -217,16 +249,15 @@ c     to it.  The argument list must also be as illustrated below:
 c The following declaration specification should match C type long int.
       integer*8 neq
       double precision pp
-      double precision udata(*), uscale(*), fdata(*), fscale(*)
-      double precision vv(*), ftem(*)
+      double precision udata(*), uscale(*), fdata(*), fscale(*), vv(*)
 
       common /pcom/ pp(128)
       common /psize/ neq
 
       do 10 i = 1, neq
-         vv(i) = vv(i) * pp(i)
- 10   continue
+ 10      vv(i) = vv(i) * pp(i)
+
       ier = 0
-      
+
       return
       end
diff --git a/examples/kinsol/parallel/CMakeLists.txt b/examples/kinsol/parallel/CMakeLists.txt
index 4a08d8f..4d53df3 100644
--- a/examples/kinsol/parallel/CMakeLists.txt
+++ b/examples/kinsol/parallel/CMakeLists.txt
@@ -1,13 +1,10 @@
 # ---------------------------------------------------------------
-# $Revision: 4137 $
-# $Date: 2014-06-15 12:26:15 -0700 (Sun, 15 Jun 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,72 +12,79 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for KINSOL parallel examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
-# Add variable KINSOL_examples with the names of the parallel KINSOL examples
-# "name\;nodes\;tasks"
+# Examples using SUNDIALS linear solvers
 SET(KINSOL_examples
-  "kinFoodWeb_kry_bbd_p\;1\;4"
-  "kinFoodWeb_kry_p\;1\;4"
+  "kinFoodWeb_kry_bbd_p\;1\;4\;develop"
+  "kinFoodWeb_kry_p\;1\;4\;develop"
   )
 
 # Check whether we use MPI compiler scripts.
 # If yes, then change the C compiler to the MPICC script.
 # If not, then add the MPI include directory for MPI headers.
-
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
+ELSE()
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
+ENDIF()
 
-# Specify libraries to link against (through the target that was used to 
+# Specify libraries to link against (through the target that was used to
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(KINSOL_LIB sundials_kinsol_static)
   SET(NVECP_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(KINSOL_LIB sundials_kinsol_shared)
   SET(NVECP_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${KINSOL_LIB} ${NVECP_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${KINSOL_examples})
 
-# Add the build and install targets for each KINSOL example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 number_of_nodes)
+  LIST(GET example_tuple 2 number_of_tasks)
+  LIST(GET example_tuple 3 example_type)
 
-FOREACH(example_tuple ${KINSOL_examples})
-  list(GET example_tuple 0 example)
-  list(GET example_tuple 1 number_of_nodes)
-  list(GET example_tuple 2 number_of_tasks)
-  # first item is example
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example} MPI_NPROCS ${number_of_tasks})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    MPI_NPROCS ${number_of_tasks}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
   IF(NOT MPI_MPICC)
     TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARIES})
-  ENDIF(NOT MPI_MPICC)
+  ENDIF()
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/parallel)
-  ENDIF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/parallel)
+  ENDIF()
+
 ENDFOREACH(example_tuple ${KINSOL_examples})
 
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -89,30 +93,28 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "KINSOL")
   SET(SOLVER_LIB "sundials_kinsol")
-  FOREACH(example_tuple ${KINSOL_examples})
-  	list(GET example_tuple 0 example)
-  	LIST2STRING(example EXAMPLES)
-  ENDFOREACH(example_tuple ${KINSOL_examples})
 
-  # Regardless of the platform we're on, we will generate and install 
-  # CMakeLists.txt file for building the examples. This file  can then 
+  EXAMPLES2STRING(KINSOL_examples EXAMPLES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
   # be used as a template for the user's own programs.
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/kinsol/parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/kinsol/parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
     FILES ${PROJECT_BINARY_DIR}/examples/kinsol/parallel/CMakeLists.txt
-    DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/parallel 
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/parallel
     )
 
-  # On UNIX-type platforms, we also  generate and install a makefile for 
-  # building the examples. This makefile can then be used as a template 
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
   # for the user's own programs.
 
   IF(UNIX)
diff --git a/examples/kinsol/parallel/README b/examples/kinsol/parallel/README
index f2d9bf4..ecf9adf 100644
--- a/examples/kinsol/parallel/README
+++ b/examples/kinsol/parallel/README
@@ -8,7 +8,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -19,7 +18,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -33,7 +35,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c b/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c
index 0543096..369ea82 100644
--- a/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c
+++ b/examples/kinsol/parallel/kinFoodWeb_kry_bbd_p.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -14,7 +10,7 @@
  * population model, with predator-prey interaction and diffusion on
  * the unit square in two dimensions. The dependent variable vector
  * is the following:
- * 
+ *
  *       1   2         ns
  * c = (c , c ,  ..., c  )     (denoted by the variable cc)
  *
@@ -47,10 +43,10 @@
  * routine InitUserData.
  *
  * The boundary conditions are: normal derivative = 0, and the
- * initial guess is constant in x and y, although the final
- * solution is not.
+ * initial guess is constant in x and y, but the final solution
+ * is not.
  *
- * The PDEs are discretized by central differencing on a MX by
+ * The PDEs are discretized by central differencing on an MX by
  * MY mesh.
  *
  * The nonlinear system is solved by KINSOL using the method
@@ -74,8 +70,8 @@
  *    Lawrence Livermore National Laboratory Report  UCRL-95088,
  *    Rev. 1, June 1987, and  Journal of Applied Mathematics and
  *    Computation, Vol. 31 (May 1989), pp. 40-91. (Presents a
- *    description of the time-dependent version of this
- *    test problem.)
+ *    description of the time-dependent version of this test
+ *    problem.)
  * --------------------------------------------------------------------------
  *  Run command line: mpirun -np N -machinefile machines kinFoodWeb_kry_bbd_p
  *  where N = NPEX * NPEY is the number of processors.
@@ -86,33 +82,33 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_spgmr.h>
-#include <kinsol/kinsol_bbdpre.h>
-#include <nvector/nvector_parallel.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_math.h>
-#include <sundials/sundials_types.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts.      */
+#include <nvector/nvector_parallel.h>  /* access to MPI parallel N_Vector      */
+#include <kinsol/kinsol_spils.h>       /* access to KINSpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <kinsol/kinsol_bbdpre.h>      /* access to BBD preconditioner         */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* access to SUNMAX, SUNRabs, SUNRsqrt  */
 
 #include <mpi.h>
 
-
 /* Problem Constants */
 
-#define NUM_SPECIES     6  /*  must equal 2*(number of prey or predators)
-                               number of prey =  number of predators      */
+#define NUM_SPECIES     6  /* must equal 2*(number of prey or predators)
+                              number of prey = number of predators       */ 
 
 #define PI       RCONST(3.1415926535898)   /* pi */ 
 
-#define NPEX        2            /* number of processors in the x-direction */
-#define NPEY        2            /* number of processors in the y-direction */
-#define MXSUB       10           /* number of x mesh points per subgrid     */
-#define MYSUB       10           /* number of y mesh points per subgrid     */
-#define MX          (NPEX*MXSUB) /* number of grid points in x-direction    */
-#define MY          (NPEY*MYSUB) /* number of grid points in y-direction    */
+#define NPEX        2            /* number of processors in the x-direction  */
+#define NPEY        2            /* number of processors in the y-direction  */
+#define MXSUB       10           /* number of x mesh points per subgrid      */
+#define MYSUB       10           /* number of y mesh points per subgrid      */
+#define MX          (NPEX*MXSUB) /* number of mesh points in the x-direction */
+#define MY          (NPEY*MYSUB) /* number of mesh points in the y-direction */
 #define NSMXSUB     (NUM_SPECIES * MXSUB)
 #define NSMXSUB2    (NUM_SPECIES * (MXSUB+2))
-#define NEQ         (NUM_SPECIES*MX*MY)  /* number of equations in system   */ 
+#define NEQ         (NUM_SPECIES*MX*MY)  /* number of equations in the system */
 #define AA          RCONST(1.0)    /* value of coefficient AA in above eqns */
 #define EE          RCONST(10000.) /* value of coefficient EE in above eqns */
 #define GG          RCONST(0.5e-6) /* value of coefficient GG in above eqns */
@@ -122,8 +118,8 @@
 #define ALPHA       RCONST(1.0)    /* value of coefficient alpha above */
 #define AX          RCONST(1.0)    /* total range of x variable */
 #define AY          RCONST(1.0)    /* total range of y variable */
-#define FTOL        RCONST(1.e-7)  /*  ftol tolerance */
-#define STOL        RCONST(1.e-13) /*  stol tolerance */
+#define FTOL        RCONST(1.e-7)  /* ftol tolerance */
+#define STOL        RCONST(1.e-13) /* stol tolerance */
 #define THOUSAND    RCONST(1000.0) /* one thousand */
 #define ZERO        RCONST(0.0)    /* 0. */
 #define ONE         RCONST(1.0)    /* 1. */
@@ -147,30 +143,30 @@ typedef struct {
   N_Vector rates;
   realtype *cox, *coy;
   realtype ax, ay, dx, dy;
-  long int Nlocal;
+  sunindextype Nlocal;
   int mx, my, ns, np;
   realtype cext[NUM_SPECIES * (MXSUB+2)*(MYSUB+2)];
   int my_pe, isubx, isuby, nsmxsub, nsmxsub2;
   MPI_Comm comm;
 } *UserData;
 
-/* Function called by the KINSol Solver */
+/* Functions called by the KINSOL Solver */
 
 static int func(N_Vector cc, N_Vector fval, void *user_data);
 
-static int ccomm(long int Nlocal, N_Vector cc, void *data);
+static int ccomm(sunindextype Nlocal, N_Vector cc, void *data);
 
-static int func_local(long int Nlocal, N_Vector cc, N_Vector fval, void *user_data);
+static int func_local(sunindextype Nlocal, N_Vector cc, N_Vector fval, void *user_data);
 
 /* Private Helper Functions */
 
 static UserData AllocUserData(void);
-static void InitUserData(int my_pe, long int Nlocal, MPI_Comm comm, UserData data);
+static void InitUserData(int my_pe, sunindextype Nlocal, MPI_Comm comm, UserData data);
 static void FreeUserData(UserData data);
 static void SetInitialProfiles(N_Vector cc, N_Vector sc);
 static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
-                        long int mudq, long int mldq,
-			long int mukeep, long int mlkeep,
+                        sunindextype mudq, sunindextype mldq,
+                        sunindextype mukeep, sunindextype mlkeep,
                         realtype fnormtol, realtype scsteptol);
 static void PrintOutput(int my_pe, MPI_Comm comm, N_Vector cc);
 static void PrintFinalStats(void *kmem);
@@ -197,20 +193,22 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id);
 
 int main(int argc, char *argv[])
 {
-  MPI_Comm comm;
-  void *kmem;
-  UserData data;
-  N_Vector cc, sc, constraints;
   int globalstrategy;
-  long int Nlocal;
+  sunindextype Nlocal;
   realtype fnormtol, scsteptol, dq_rel_uu;
+  N_Vector cc, sc, constraints;
+  UserData data;
   int flag, maxl, maxlrst;
-  long int mudq, mldq, mukeep, mlkeep;
   int my_pe, npes, npelast = NPEX*NPEY-1;
+  void *kmem;
+  SUNLinearSolver LS;
+  sunindextype mudq, mldq, mukeep, mlkeep;
+  MPI_Comm comm;
 
-  data = NULL;
-  kmem = NULL;
   cc = sc = constraints = NULL;
+  kmem = NULL;
+  LS = NULL;
+  data = NULL;
 
   /* Get processor number and total number of pe's */
   MPI_Init(&argc, &argv);
@@ -220,14 +218,15 @@ int main(int argc, char *argv[])
 
   if (npes != NPEX*NPEY) {
     if (my_pe == 0)
-      printf("\nMPI_ERROR(0): npes=%d is not equal to NPEX*NPEY=%d\n", npes,
-             NPEX*NPEY);
+      fprintf(stderr, "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n",
+	          npes,NPEX*NPEY);
+    MPI_Finalize();
     return(1);
   }
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
 
-  /* Set local length */
+  /* Set local vector length */
   Nlocal = NUM_SPECIES*MXSUB*MYSUB;
 
   /* Allocate and initialize user data block */
@@ -235,7 +234,7 @@ int main(int argc, char *argv[])
   if (check_flag((void *)data, "AllocUserData", 2, my_pe)) MPI_Abort(comm, 1);
   InitUserData(my_pe, Nlocal, comm, data);
 
-  /* Choose global strategy */
+  /* Set global strategy flag */
   globalstrategy = KIN_NONE;
 
   /* Allocate and initialize vectors */
@@ -244,18 +243,16 @@ int main(int argc, char *argv[])
   sc = N_VNew_Parallel(comm, Nlocal, NEQ);
   if (check_flag((void *)sc, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
   data->rates = N_VNew_Parallel(comm, Nlocal, NEQ);
-  if (check_flag((void *)data->rates, "N_VNew_Parallel", 0, my_pe))
-      MPI_Abort(comm, 1);
+  if (check_flag((void *)data->rates, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
   constraints = N_VNew_Parallel(comm, Nlocal, NEQ);
-  if (check_flag((void *)constraints, "N_VNew_Parallel", 0, my_pe))
-      MPI_Abort(comm, 1);
+  if (check_flag((void *)constraints, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
   N_VConst(ZERO, constraints);
-  
+
   SetInitialProfiles(cc, sc);
 
   fnormtol = FTOL; scsteptol = STOL;
 
-  /* Call KINCreate/KINInit to initialize KINSOL: 
+  /* Call KINCreate/KINInit to initialize KINSOL:
      nvSpec  points to machine environment data
      A pointer to KINSOL problem memory is returned and stored in kmem. */
   kmem = KINCreate();
@@ -264,22 +261,33 @@ int main(int argc, char *argv[])
   /* Vector cc passed as template vector. */
   flag = KINInit(kmem, func, cc);
   if (check_flag(&flag, "KINInit", 1, my_pe)) MPI_Abort(comm, 1);
-
   flag = KINSetUserData(kmem, data);
   if (check_flag(&flag, "KINSetUserData", 1, my_pe)) MPI_Abort(comm, 1);
-
   flag = KINSetConstraints(kmem, constraints);
   if (check_flag(&flag, "KINSetConstraints", 1, my_pe)) MPI_Abort(comm, 1);
+  flag = KINSetFuncNormTol(kmem, fnormtol);
+  if (check_flag(&flag, "KINSetFuncNormTol", 1, my_pe)) MPI_Abort(comm, 1);
+  flag = KINSetScaledStepTol(kmem, scsteptol);
+  if (check_flag(&flag, "KINSetScaledStepTol", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* We no longer need the constraints vector since KINSetConstraints
      creates a private copy for KINSOL to use. */
   N_VDestroy_Parallel(constraints);
 
-  flag = KINSetFuncNormTol(kmem, fnormtol);
-  if (check_flag(&flag, "KINSetFuncNormTol", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Create SUNSPGMR object with right preconditioning and the 
+     maximum Krylov dimension maxl */
+  maxl = 20; 
+  LS = SUNSPGMR(cc, PREC_RIGHT, maxl);
+  if(check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
 
-  flag = KINSetScaledStepTol(kmem, scsteptol);
-  if (check_flag(&flag, "KINSetScaledStepTol", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Attach the linear solver to KINSOL */
+  flag = KINSpilsSetLinearSolver(kmem, LS);
+  if (check_flag(&flag, "KINSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
+
+  /* Set the maximum number of restarts */
+  maxlrst = 2;
+  flag = SUNSPGMRSetMaxRestarts(LS, maxlrst);
+  if (check_flag(&flag, "SUNSPGMRSpilsSetMaxRestarts", 1, my_pe)) MPI_Abort(comm, 1);
   
   /* Call KINBBDPrecInit to initialize and allocate memory for the
      band-block-diagonal preconditioner, and specify the local and
@@ -289,45 +297,34 @@ int main(int argc, char *argv[])
   mudq = mldq = 2*NUM_SPECIES - 1;
   mukeep = mlkeep = NUM_SPECIES;
 
-  /* Call KINBBDSpgmr to specify the linear solver KINSPGMR */
-  maxl = 20; maxlrst = 2;
-  flag = KINSpgmr(kmem, maxl);
-  if (check_flag(&flag, "KINSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
-
   /* Initialize BBD preconditioner */
   flag = KINBBDPrecInit(kmem, Nlocal, mudq, mldq, mukeep, mlkeep,
                         dq_rel_uu, func_local, NULL);
   if (check_flag(&flag, "KINBBDPrecInit", 1, my_pe)) MPI_Abort(comm, 1);
 
-
-  flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
-  if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1, my_pe)) 
-    MPI_Abort(comm, 1);
-
   /* Print out the problem size, solution parameters, initial guess. */
   if (my_pe == 0)
     PrintHeader(globalstrategy, maxl, maxlrst, mudq, mldq, mukeep,
 		mlkeep, fnormtol, scsteptol);
 
-  /* call KINSol and print output concentration profile */
+  /* Call KINSol and print output concentration profile */
   flag = KINSol(kmem,           /* KINSol memory block */
-                cc,             /* initial guesss on input; solution vector */
-                globalstrategy, /* global stragegy choice */
-                sc,             /* scaling vector, for the variable cc */
+                cc,             /* initial guess on input; solution vector */
+                globalstrategy, /* global strategy choice */
+                sc,             /* scaling vector for the variable cc */
                 sc);            /* scaling vector for function values fval */
   if (check_flag(&flag, "KINSol", 1, my_pe)) MPI_Abort(comm, 1);
 
   if (my_pe == 0) printf("\n\nComputed equilibrium species concentrations:\n");
-  if (my_pe == 0 || my_pe==npelast) PrintOutput(my_pe, comm, cc);
-  
+  if (my_pe == 0 || my_pe == npelast) PrintOutput(my_pe, comm, cc);
+
   /* Print final statistics and free memory */
-  if (my_pe == 0) 
-    PrintFinalStats(kmem);
+  if (my_pe == 0) PrintFinalStats(kmem);
 
   N_VDestroy_Parallel(cc);
   N_VDestroy_Parallel(sc);
-
   KINFree(&kmem);
+  SUNLinSolFree(LS);
   FreeUserData(data);
 
   MPI_Finalize();
@@ -353,7 +350,7 @@ int main(int argc, char *argv[])
  * between processors of data needed to calculate f. 
  */
 
-static int ccomm(long int Nlocal, N_Vector cc, void *userdata)
+static int ccomm(sunindextype Nlocal, N_Vector cc, void *userdata)
 {
 
   realtype *cdata, *cext, buffer[2*NUM_SPECIES*MYSUB];
@@ -388,7 +385,7 @@ static int ccomm(long int Nlocal, N_Vector cc, void *userdata)
  * System function for predator-prey system - calculation part 
  */
 
-static int func_local(long int Nlocal, N_Vector cc, N_Vector fval, void *user_data)
+static int func_local(sunindextype Nlocal, N_Vector cc, N_Vector fval, void *user_data)
 {
   realtype xx, yy, *cxy, *rxy, *fxy, dcydi, dcyui, dcxli, dcxri;
   realtype *cext, dely, delx, *cdata;
@@ -580,7 +577,7 @@ static UserData AllocUserData(void)
  * Load problem constants in data 
  */
 
-static void InitUserData(int my_pe, long int Nlocal, MPI_Comm comm, UserData data)
+static void InitUserData(int my_pe, sunindextype Nlocal, MPI_Comm comm, UserData data)
 {
   int i, j, np;
   realtype *a1,*a2, *a3, *a4, dx2, dy2;
@@ -690,8 +687,8 @@ static void SetInitialProfiles(N_Vector cc, N_Vector sc)
  */
 
 static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
-                        long int mudq, long int mldq,
-			long int mukeep, long int mlkeep,
+                        sunindextype mudq, sunindextype mldq,
+			sunindextype mukeep, sunindextype mlkeep,
                         realtype fnormtol, realtype scsteptol)
 {
     printf("\nPredator-prey test problem--  KINSol (parallel-BBD version)\n\n");
@@ -706,9 +703,9 @@ static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
            maxl, maxlrst);
     printf("Preconditioning uses band-block-diagonal matrix from KINBBDPRE\n");
     printf("  Difference quotient half-bandwidths: mudq = %ld, mldq = %ld\n",
-	   mudq, mldq);
+	   (long int) mudq, (long int) mldq);
     printf("  Retained band block half-bandwidths: mukeep = %ld, mlkeep = %ld\n",
-	   mukeep, mlkeep);
+	   (long int) mukeep, (long int) mlkeep);
 #if defined(SUNDIALS_EXTENDED_PRECISION) 
     printf("Tolerance parameters:  fnormtol = %Lg   scsteptol = %Lg\n",
            fnormtol, scsteptol);
@@ -993,13 +990,13 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id)
       fprintf(stderr,
               "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
 	      id, funcname, *errflag);
-      return(1); 
+      return(1);
     }
   }
 
   /* Check if function returned NULL pointer - no memory allocated */
   else if (opt == 2 && flagvalue == NULL) {
-    fprintf(stderr, 
+    fprintf(stderr,
             "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
 	    id, funcname);
     return(1);
diff --git a/examples/kinsol/parallel/kinFoodWeb_kry_p.c b/examples/kinsol/parallel/kinFoodWeb_kry_p.c
index 0cbe6fe..d6ddd23 100644
--- a/examples/kinsol/parallel/kinFoodWeb_kry_p.c
+++ b/examples/kinsol/parallel/kinFoodWeb_kry_p.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -46,10 +42,10 @@
  * routine InitUserData.
  *
  * The boundary conditions are: normal derivative = 0, and the
- * initial guess is constant in x and y, although the final
- * solution is not.
+ * initial guess is constant in x and y, but the final solution
+ * is not.
  *
- * The PDEs are discretized by central differencing on a MX by
+ * The PDEs are discretized by central differencing on an MX by
  * MY mesh.
  *
  * The nonlinear system is solved by KINSOL using the method
@@ -81,16 +77,16 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_spgmr.h>
-#include <nvector/nvector_parallel.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts.      */
+#include <nvector/nvector_parallel.h>  /* access to MPI parallel N_Vector      */
+#include <kinsol/kinsol_spils.h>       /* access to KINSpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* access to SUNMAX, SUNRabs, SUNRsqrt  */
 
 #include <mpi.h>
 
-
 /* Problem Constants */
 
 #define NUM_SPECIES     6  /* must equal 2*(number of prey or predators)
@@ -116,8 +112,8 @@
 #define ALPHA       RCONST(1.0)    /* value of coefficient alpha above */
 #define AX          RCONST(1.0)    /* total range of x variable */
 #define AY          RCONST(1.0)    /* total range of y variable */
-#define FTOL        RCONST(1.e-7)  /*  ftol tolerance */
-#define STOL        RCONST(1.e-13) /*  stol tolerance */
+#define FTOL        RCONST(1.e-7)  /* ftol tolerance */
+#define STOL        RCONST(1.e-13) /* stol tolerance */
 #define THOUSAND    RCONST(1000.0) /* one thousand */
 #define ZERO        RCONST(0.0)    /* 0. */
 #define ONE         RCONST(1.0)    /* 1. */
@@ -138,7 +134,7 @@
 
 typedef struct {
   realtype **P[MXSUB][MYSUB];
-  long int *pivot[MXSUB][MYSUB];
+  sunindextype *pivot[MXSUB][MYSUB];
   realtype **acoef, *bcoef;
   N_Vector rates;
   realtype *cox, *coy;
@@ -150,19 +146,17 @@ typedef struct {
   MPI_Comm comm;
 } *UserData;
 
-/* Functions Called by the KINSol Solver */
+/* Functions called by the KINSOL Solver */
 
 static int funcprpr(N_Vector cc, N_Vector fval, void *user_data);
 
 static int Precondbd(N_Vector cc, N_Vector cscale,
                      N_Vector fval, N_Vector fscale,
-                     void *user_data,
-                     N_Vector vtemp1, N_Vector vtemp2);
+                     void *user_data);
 
 static int PSolvebd(N_Vector cc, N_Vector cscale, 
                     N_Vector fval, N_Vector fscale, 
-                    N_Vector vv, void *user_data,
-                    N_Vector vtemp);
+                    N_Vector vv, void *user_data);
 
 /* Private Helper Functions */
 
@@ -170,14 +164,14 @@ static UserData AllocUserData(void);
 static void InitUserData(int my_pe, MPI_Comm comm, UserData data);
 static void FreeUserData(UserData data);
 static void SetInitialProfiles(N_Vector cc, N_Vector sc);
-static void PrintHeader(int globalstrategy, int maxl, int maxlrst, 
+static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
                         realtype fnormtol, realtype scsteptol);
 static void PrintOutput(int my_pe, MPI_Comm comm, N_Vector cc);
 static void PrintFinalStats(void *kmem);
-static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
+static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
                     void *user_data);
 static realtype DotProd(int size, realtype *x1, realtype *x2);
-static void BSend(MPI_Comm comm, int my_pe, int isubx, 
+static void BSend(MPI_Comm comm, int my_pe, int isubx,
                   int isuby, int dsizex, 
                   int dsizey, realtype *cdata);
 static void BRecvPost(MPI_Comm comm, MPI_Request request[], int my_pe,
@@ -201,18 +195,20 @@ int main(int argc, char *argv[])
 
 {
   int globalstrategy;
-  long int local_N;
+  sunindextype local_N;
   realtype fnormtol, scsteptol;
   N_Vector cc, sc, constraints;
   UserData data;
   int flag, maxl, maxlrst;
   int my_pe, npes, npelast = NPEX*NPEY-1;
   void *kmem;
+  SUNLinearSolver LS;
   MPI_Comm comm;
 
   cc = sc = constraints = NULL;
-  data = NULL;
   kmem = NULL;
+  LS = NULL;
+  data = NULL;
 
   /* Get processor number and total number of pe's */
   MPI_Init(&argc, &argv);
@@ -222,8 +218,8 @@ int main(int argc, char *argv[])
 
   if (npes != NPEX*NPEY) {
     if (my_pe == 0)
-      fprintf(stderr, "\nMPI_ERROR(0); npes = %d is not equal to NPEX*NPEY = %d\n",
-	      npes,NPEX*NPEY);
+      fprintf(stderr, "\nMPI_ERROR(0): npes = %d is not equal to NPEX*NPEY = %d\n",
+	          npes,NPEX*NPEY);
     MPI_Finalize();
     return(1);
   }
@@ -240,7 +236,7 @@ int main(int argc, char *argv[])
 
   /* Set global strategy flag */
   globalstrategy = KIN_NONE;
-  
+
   /* Allocate and initialize vectors */
   cc = N_VNew_Parallel(comm, local_N, NEQ);
   if (check_flag((void *)cc, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
@@ -251,20 +247,20 @@ int main(int argc, char *argv[])
   constraints = N_VNew_Parallel(comm, local_N, NEQ);
   if (check_flag((void *)constraints, "N_VNew_Parallel", 0, my_pe)) MPI_Abort(comm, 1);
   N_VConst(ZERO, constraints);
-  
+
   SetInitialProfiles(cc, sc);
 
-  fnormtol=FTOL; scsteptol=STOL;
+  fnormtol = FTOL; scsteptol = STOL;
 
- /* Call KINCreate/KINInit to initialize KINSOL: 
+  /* Call KINCreate/KINInit to initialize KINSOL:
      nvSpec is the nvSpec pointer used in the parallel version
      A pointer to KINSOL problem memory is returned and stored in kmem. */
   kmem = KINCreate();
   if (check_flag((void *)kmem, "KINCreate", 0, my_pe)) MPI_Abort(comm, 1);
+
   /* Vector cc passed as template vector. */
   flag = KINInit(kmem, funcprpr, cc);
   if (check_flag(&flag, "KINInit", 1, my_pe)) MPI_Abort(comm, 1);
-
   flag = KINSetNumMaxIters(kmem, 250);
   if (check_flag(&flag, "KINSetNumMaxIters", 1, my_pe)) MPI_Abort(comm, 1);
   flag = KINSetUserData(kmem, data);
@@ -274,49 +270,55 @@ int main(int argc, char *argv[])
   flag = KINSetFuncNormTol(kmem, fnormtol);
   if (check_flag(&flag, "KINSetFuncNormTol", 1, my_pe)) MPI_Abort(comm, 1);
   flag = KINSetScaledStepTol(kmem, scsteptol);
-  if (check_flag(&flag, "KINSetScaledStepTop", 1, my_pe)) MPI_Abort(comm, 1);
+  if (check_flag(&flag, "KINSetScaledStepTol", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* We no longer need the constraints vector since KINSetConstraints
      creates a private copy for KINSOL to use. */
   N_VDestroy_Parallel(constraints);
 
-  /* Call KINSpgmr to specify the linear solver KINSPGMR with preconditioner
-     routines Precondbd and PSolvebd, and the pointer to the user data block. */
-  maxl = 20; maxlrst = 2;
-  flag = KINSpgmr(kmem, maxl);
-  if (check_flag(&flag, "KINSpgmr", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Create SUNSPGMR object with right preconditioning and the 
+     maximum Krylov dimension maxl */
+  maxl = 20; 
+  LS = SUNSPGMR(cc, PREC_RIGHT, maxl);
+  if(check_flag((void *)LS, "SUNSPGMR", 0, my_pe)) MPI_Abort(comm, 1);
+
+  /* Attach the linear solver to KINSOL */
+  flag = KINSpilsSetLinearSolver(kmem, LS);
+  if (check_flag(&flag, "KINSpilsSetLinearSolver", 1, my_pe)) MPI_Abort(comm, 1);
+
+  /* Set the maximum number of restarts */
+  maxlrst = 2;
+  flag = SUNSPGMRSetMaxRestarts(LS, maxlrst);
+  if (check_flag(&flag, "SUNSPGMRSpilsSetMaxRestarts", 1, my_pe)) MPI_Abort(comm, 1);
 
-  flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
-  if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1, my_pe)) MPI_Abort(comm, 1);
+  /* Specify the preconditioner setup and solve routines */
   flag = KINSpilsSetPreconditioner(kmem,
 				   Precondbd,
 				   PSolvebd);
   if (check_flag(&flag, "KINSpilsSetPreconditioner", 1, my_pe)) MPI_Abort(comm, 1);
 
   /* Print out the problem size, solution parameters, initial guess. */
-  if (my_pe == 0) 
+  if (my_pe == 0)
     PrintHeader(globalstrategy, maxl, maxlrst, fnormtol, scsteptol);
 
   /* Call KINSol and print output concentration profile */
   flag = KINSol(kmem,           /* KINSol memory block */
                 cc,             /* initial guess on input; solution vector */
-                globalstrategy, /* global stragegy choice */
+                globalstrategy, /* global strategy choice */
                 sc,             /* scaling vector for the variable cc */
                 sc);            /* scaling vector for function values fval */
   if (check_flag(&flag, "KINSol", 1, my_pe)) MPI_Abort(comm, 1);
 
-  if (my_pe == 0) 
-     printf("\n\nComputed equilibrium species concentrations:\n");
-  if (my_pe == 0 || my_pe == npelast) 
-     PrintOutput(my_pe, comm, cc);
+  if (my_pe == 0) printf("\n\nComputed equilibrium species concentrations:\n");
+  if (my_pe == 0 || my_pe == npelast) PrintOutput(my_pe, comm, cc);
 
-  /* Print final statistics and free memory */  
-  if (my_pe == 0) 
-     PrintFinalStats(kmem);
+  /* Print final statistics and free memory */
+  if (my_pe == 0) PrintFinalStats(kmem);
 
   N_VDestroy_Parallel(cc);
   N_VDestroy_Parallel(sc);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
   FreeUserData(data);
 
   MPI_Finalize();
@@ -367,15 +369,14 @@ static int funcprpr(N_Vector cc, N_Vector fval, void *user_data)
 
 static int Precondbd(N_Vector cc, N_Vector cscale,
                      N_Vector fval, N_Vector fscale,
-                     void *user_data,
-                     N_Vector vtemp1, N_Vector vtemp2)
+                     void *user_data)
 {
   realtype r, r0, uround, sqruround, xx, yy, delx, dely, csave, fac;
   realtype *cxy, *scxy, **Pxy, *ratesxy, *Pxycol, perturb_rates[NUM_SPECIES];
   int i, j, jx, jy, ret;
   UserData data;
   
-  data = (UserData)user_data;
+  data = (UserData) user_data;
   delx = data->dx;
   dely = data->dy;
   
@@ -421,6 +422,7 @@ static int Precondbd(N_Vector cc, N_Vector cscale,
       if (ret != 0) return(1);
       
     } /* end of jx loop */
+    
   } /* end of jy loop */
   
   return(0);
@@ -432,14 +434,13 @@ static int Precondbd(N_Vector cc, N_Vector cscale,
 
 static int PSolvebd(N_Vector cc, N_Vector cscale, 
                     N_Vector fval, N_Vector fscale, 
-                    N_Vector vv, void *user_data,
-                    N_Vector vtemp)
+                    N_Vector vv, void *user_data)
 {
   realtype **Pxy, *vxy;
-  long int *piv, jx, jy;
+  sunindextype *piv, jx, jy;
   UserData data;
   
-  data = (UserData)user_data;
+  data = (UserData) user_data;
   
   for (jx = 0; jx < MXSUB; jx++) {
     
@@ -458,7 +459,7 @@ static int PSolvebd(N_Vector cc, N_Vector cscale,
     
   } /* end of jx loop */
   
-  return(0); 
+  return(0);
 }
 
 /*
@@ -472,7 +473,7 @@ static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
   realtype fac;
   UserData data;
   
-  data = (UserData)user_data;
+  data = (UserData) user_data;
   
   for (i = 0; i<NUM_SPECIES; i++)
     ratesxy[i] = DotProd(NUM_SPECIES, cxy, acoef[i]);
@@ -481,7 +482,6 @@ static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
   
   for (i = 0; i < NUM_SPECIES; i++)
     ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );
-  
 }
 
 /*
@@ -495,8 +495,8 @@ static realtype DotProd(int size, realtype *x1, realtype *x2)
   
   xx1 = x1; xx2 = x2;
   for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
-  return(temp);
 
+  return(temp);
 }
 
 /*
@@ -519,7 +519,7 @@ static UserData AllocUserData(void)
   for (jx = 0; jx < MXSUB; jx++) {
     for (jy = 0; jy < MYSUB; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
 
@@ -529,7 +529,6 @@ static UserData AllocUserData(void)
   coy   = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
   
   return(data);
-  
 }
 
 /*
@@ -540,7 +539,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
 {
   int i, j, np;
   realtype *a1,*a2, *a3, *a4, dx2, dy2;
-  
+
   data->mx = MX;
   data->my = MY;
   data->ns = NUM_SPECIES;
@@ -557,7 +556,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
   data->isubx = my_pe - data->isuby*NPEX;
   data->nsmxsub = NUM_SPECIES * MXSUB;
   data->nsmxsub2 = NUM_SPECIES * (MXSUB+2);
-  
+
   /* Set up the coefficients a and b plus others found in the equations */
   np = data->np;
 
@@ -576,7 +575,7 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
       *a3++ = ZERO;
       *a4++ = ZERO;
     }
-    
+
     /* and then change the diagonal elements of acoef to -AA */
     acoef[i][i]=-AA;
     acoef[i+np][i+np] = -AA;
@@ -590,7 +589,6 @@ static void InitUserData(int my_pe, MPI_Comm comm, UserData data)
     coy[i]=DPREY/dy2;
     coy[i+np]=DPRED/dy2;
   }
-  
 }
 
 /*
@@ -610,10 +608,10 @@ static void FreeUserData(UserData data)
 
   destroyMat(acoef);
   free(bcoef);
-  free(cox); 
+  free(cox);
   free(coy);
   N_VDestroy_Parallel(data->rates);
-  free(data);  
+  free(data);
 }
 
 /*
@@ -635,7 +633,7 @@ static void SetInitialProfiles(N_Vector cc, N_Vector sc)
     ctemp[i] = PREDIN;
     stemp[i] = RCONST(0.00001);
   }
-  
+
   /* Load initial profiles into cc and sc vector from ctemp and stemp. */
   for (jy = 0; jy < MYSUB; jy++) {
     for (jx = 0; jx < MXSUB; jx++) {
@@ -656,18 +654,18 @@ static void SetInitialProfiles(N_Vector cc, N_Vector sc)
 static void PrintHeader(int globalstrategy, int maxl, int maxlrst, 
                         realtype fnormtol, realtype scsteptol)
 {
-    printf("\nPredator-prey test problem --  KINSol (parallel version)\n\n");
-    
-    printf("Mesh dimensions = %d X %d\n", MX, MY);
-    printf("Number of species = %d\n", NUM_SPECIES);
-    printf("Total system size = %d\n\n", NEQ);
-    printf("Subgrid dimensions = %d X %d\n", MXSUB, MYSUB);
-    printf("Processor array is %d X %d\n\n", NPEX, NPEY);
-    printf("Flag globalstrategy = %d (0 = None, 1 = Linesearch)\n",
-           globalstrategy);
-    printf("Linear solver is SPGMR with maxl = %d, maxlrst = %d\n",
-           maxl, maxlrst);
-    printf("Preconditioning uses interaction-only block-diagonal matrix\n");
+  printf("\nPredator-prey test problem --  KINSol (parallel version)\n\n");
+
+  printf("Mesh dimensions = %d X %d\n", MX, MY);
+  printf("Number of species = %d\n", NUM_SPECIES);
+  printf("Total system size = %d\n\n", NEQ);
+  printf("Subgrid dimensions = %d X %d\n", MXSUB, MYSUB);
+  printf("Processor array is %d X %d\n\n", NPEX, NPEY);
+  printf("Flag globalstrategy = %d (0 = None, 1 = Linesearch)\n",
+         globalstrategy);
+  printf("Linear solver is SPGMR with maxl = %d, maxlrst = %d\n",
+         maxl, maxlrst);
+  printf("Preconditioning uses interaction-only block-diagonal matrix\n");
 
 #if defined(SUNDIALS_EXTENDED_PRECISION) 
   printf("Tolerance parameters:  fnormtol = %Lg   scsteptol = %Lg\n",
@@ -683,27 +681,27 @@ static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
   printf("\nInitial profile of concentration\n");
 #if defined(SUNDIALS_EXTENDED_PRECISION) 
   printf("At all mesh points:  %Lg %Lg %Lg   %Lg %Lg %Lg\n", 
-         PREYIN,PREYIN,PREYIN,
-         PREDIN,PREDIN,PREDIN);
+         PREYIN, PREYIN, PREYIN,
+         PREDIN, PREDIN, PREDIN);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
   printf("At all mesh points:  %g %g %g   %g %g %g\n", 
-         PREYIN,PREYIN,PREYIN,
-         PREDIN,PREDIN,PREDIN);
+         PREYIN, PREYIN, PREYIN,
+         PREDIN, PREDIN, PREDIN);
 #else
   printf("At all mesh points:  %g %g %g   %g %g %g\n", 
-         PREYIN,PREYIN,PREYIN,
-         PREDIN,PREDIN,PREDIN);
+         PREYIN, PREYIN, PREYIN,
+         PREDIN, PREDIN, PREDIN);
 #endif
 }
 
 /*
- * Print sample of current cc values 
+ * Print sampled values of current cc 
  */
 
 static void PrintOutput(int my_pe, MPI_Comm comm, N_Vector cc)
 {
   int is, i0, npelast;
-  realtype  *ct, tempc[NUM_SPECIES];
+  realtype *ct, tempc[NUM_SPECIES];
   MPI_Status status;
 
   npelast = NPEX*NPEY - 1;
@@ -729,27 +727,27 @@ static void PrintOutput(int my_pe, MPI_Comm comm, N_Vector cc)
     printf("\nAt bottom left:");
     for (is = 0; is < NUM_SPECIES; is++) {
       if ((is%6)*6 == is) printf("\n");
-#if defined(SUNDIALS_EXTENDED_PRECISION) 
-      printf(" %Lg",ct[is]);
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    printf(" %Lg",ct[is]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-      printf(" %g",ct[is]);
+    printf(" %g",ct[is]);
 #else
-      printf(" %g",ct[is]);
+    printf(" %g",ct[is]);
 #endif
     }
-    
-    printf("\n\nAt top right:");
-    for (is = 0; is < NUM_SPECIES; is++) {
-      if ((is%6)*6 == is) printf("\n");
-#if defined(SUNDIALS_EXTENDED_PRECISION) 
-      printf(" %Lg",tempc[is]);
+
+  printf("\n\nAt top right:");
+  for (is = 0; is < NUM_SPECIES; is++) {
+    if ((is%6)*6 == is) printf("\n");
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    printf(" %Lg",tempc[is]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-      printf(" %g",tempc[is]);
+    printf(" %g",tempc[is]);
 #else
-      printf(" %g",tempc[is]);
+    printf(" %g",tempc[is]);
 #endif
-    }
-    printf("\n\n");
+  }
+  printf("\n\n");
   } 
 }
 
@@ -766,7 +764,6 @@ static void PrintFinalStats(void *kmem)
   check_flag(&flag, "KINGetNumNonlinSolvIters", 1, 0);
   flag = KINGetNumFuncEvals(kmem, &nfe);
   check_flag(&flag, "KINGetNumFuncEvals", 1, 0);
-
   flag = KINSpilsGetNumLinIters(kmem, &nli);
   check_flag(&flag, "KINSpilsGetNumLinIters", 1, 0);
   flag = KINSpilsGetNumPrecEvals(kmem, &npe);
@@ -1093,7 +1090,7 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id)
   else if (opt == 1) {
     errflag = (int *) flagvalue;
     if (*errflag < 0) {
-      fprintf(stderr, 
+      fprintf(stderr,
               "\nSUNDIALS_ERROR(%d): %s() failed with flag = %d\n\n",
 	      id, funcname, *errflag);
       return(1);
@@ -1102,10 +1099,10 @@ static int check_flag(void *flagvalue, const char *funcname, int opt, int id)
 
   /* Check if function returned NULL pointer - no memory allocated */
   else if (opt == 2 && flagvalue == NULL) {
-    fprintf(stderr, 
+    fprintf(stderr,
             "\nMEMORY_ERROR(%d): %s() failed - returned NULL pointer\n\n",
 	    id, funcname);
-    return(1); 
+    return(1);
   }
 
   return(0);
diff --git a/examples/kinsol/serial/CMakeLists.txt b/examples/kinsol/serial/CMakeLists.txt
index 1c0a39e..3235609 100644
--- a/examples/kinsol/serial/CMakeLists.txt
+++ b/examples/kinsol/serial/CMakeLists.txt
@@ -1,13 +1,11 @@
 # ---------------------------------------------------------------
-# $Revision: 4901 $
-# $Date: 2016-09-14 07:45:54 -0700 (Wed, 14 Sep 2016) $
-# ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
 # Copyright (c) 2014, Lawrence Livermore National Security
-# This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
 # Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
@@ -15,114 +13,227 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for KINSOL serial examples
+# ---------------------------------------------------------------
 
+# Example lists are tuples "name\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
-# Add variable KINSOL_examples with the names of the serial KINSOL examples
-
+# Examples using SUNDIALS linear solvers
 SET(KINSOL_examples
-  kinFerTron_dns
-  kinFoodWeb_kry
-  kinKrylovDemo_ls
-  kinLaplace_bnd
-  kinLaplace_picard_bnd
-  kinRoberts_fp
-  kinRoboKin_dns
+  "kinFerTron_dns\;develop"
+  "kinFoodWeb_kry\;develop"
+  "kinKrylovDemo_ls\;develop"
+  "kinLaplace_bnd\;develop"
+  "kinLaplace_picard_bnd\;develop"
+  "kinRoberts_fp\;"
+  "kinRoboKin_dns\;develop"
   )
 
-# Add variable KINSOL_examples_BL with the names of the serial KINSOL examples
-# that use Lapack
-
+# Examples using LAPACK linear solvers
 SET(KINSOL_examples_BL
   )
 
-SET(KINSOL_examples_SUPERLUMT
-  kinRoboKin_slu
+# Examples using KLU linear solver
+SET(KINSOL_examples_KLU
+  "kinFerTron_klu\;develop"
   )
 
-SET(KINSOL_examples_KLU
-  kinFerTron_klu
+# Examples using SuperLU_MT linear solver
+SET(KINSOL_examples_SUPERLUMT
+  "kinRoboKin_slu\;develop"
   )
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(KINSOL_LIB sundials_kinsol_static)
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(KINSOL_LIB sundials_kinsol_shared)
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${KINSOL_LIB} ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-IF(LAPACK_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_FOUND)
 
-IF(SUPERLUMT_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_FOUND)
 
-IF(KLU_FOUND)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_FOUND)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${KINSOL_examples})
 
-# Add the build and install targets for each KINSOL example
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_type)
 
-FOREACH(example ${KINSOL_examples})
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c)
+
   SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-  SUNDIALS_ADD_TEST(${example} ${example})
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${example} ${example}
+    ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+    ANSWER_FILE ${example}.out
+    EXAMPLE_TYPE ${example_type})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # install example source and out files
   IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${KINSOL_examples})
+    INSTALL(FILES ${example}.c ${example}.out
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
+  ENDIF()
 
-# If Lapack support is enabled, add the build and install targets for
-# the examples using Lapack
+ENDFOREACH(example_tuple ${KINSOL_examples})
 
+
+# Add the build and install targets for each LAPACK example (if needed)
 IF(LAPACK_FOUND)
-  FOREACH(example ${KINSOL_examples_BL})
-    ADD_EXECUTABLE(${example} ${example}.c)    
+
+  # Sundials LAPACK linear solver modules
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_static
+      sundials_sunlinsollapackdense_static)
+  ELSE()
+    SET(SUNLINSOLLAPACK_LIBS
+      sundials_sunlinsollapackband_shared
+      sundials_sunlinsollapackdense_shared)
+  ENDIF()
+
+  # LAPACK libraries
+  LIST(APPEND SUNLINSOLLAPACK_LIBS ${LAPACK_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLLAPACK_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${KINSOL_examples_BL})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c)
+
     SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLLAPACK_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${KINSOL_examples_BL})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${KINSOL_examples_BL})
+
 ENDIF(LAPACK_FOUND)
 
-# If SUPERLUMT support is enabled, add the build and install targets for
-# the examples using SUPERLUMT
-IF(SUPERLUMT_FOUND)
-  FOREACH(example ${KINSOL_examples_SUPERLUMT})
-    ADD_EXECUTABLE(${example} ${example}.c)
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-    IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${KINSOL_examples_SUPERLUMT})
-ENDIF(SUPERLUMT_FOUND)
 
-# If KLU support is enabled, add the build and install targets for
-# the examples using KLU
+# Add the build and install targets for each KLU example (if needed)
 IF(KLU_FOUND)
-  FOREACH(example ${KINSOL_examples_KLU})
+
+  # Sundials KLU linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_static)
+  ELSE()
+    SET(SUNLINSOLKLU_LIBS sundials_sunlinsolklu_shared)
+  ENDIF()
+
+  # KLU libraries
+  LIST(APPEND SUNLINSOLKLU_LIBS ${KLU_LIBRARIES})
+
+  FOREACH(example_tuple ${KINSOL_examples_KLU})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
     ADD_EXECUTABLE(${example} ${example}.c)
-    SUNDIALS_ADD_TEST(${example} ${example})
-    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLKLU_LIBS})
+
+    # install example source and out files
     IF(EXAMPLES_INSTALL)
-      INSTALL(FILES ${example}.c ${example}.out DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
-    ENDIF(EXAMPLES_INSTALL)
-  ENDFOREACH(example ${KINSOL_examples_KLU})
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${KINSOL_examples_KLU})
+
 ENDIF(KLU_FOUND)
 
 
+# Add the build and install targets for each SuperLU_MT example (if needed)
+IF(SUPERLUMT_FOUND)
+
+  # Sundials SuperLU_MT linear solver module
+  IF(LINK_LIBRARY_TYPE MATCHES "static")
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_static)
+  ELSE()
+    SET(SUNLINSOLSLUMT_LIBS sundials_sunlinsolsuperlumt_shared)
+  ENDIF()
+
+  # SuperLU_MT libraries
+  LIST(APPEND SUNLINSOLSLUMT_LIBS ${SUPERLUMT_LIBRARIES})
+
+  # BLAS libraries
+  IF(BLAS_FOUND)
+    LIST(APPEND SUNLINSOLSLUMT_LIBS ${BLAS_LIBRARIES})
+  ENDIF(BLAS_FOUND)
+
+  FOREACH(example_tuple ${KINSOL_examples_SUPERLUMT})
+
+    # parse the example tuple
+    LIST(GET example_tuple 0 example)
+    LIST(GET example_tuple 1 example_type)
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c)
+
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # add example to regression tests
+    SUNDIALS_ADD_TEST(${example} ${example}
+      ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+      ANSWER_FILE ${example}.out
+      EXAMPLE_TYPE ${example_type})
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${SUNLINSOLSLUMT_LIBS})
+
+    # install example source and out files
+    IF(EXAMPLES_INSTALL)
+      INSTALL(FILES ${example}.c ${example}.out
+        DESTINATION ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
+    ENDIF()
+
+  ENDFOREACH(example_tuple ${KINSOL_examples_SUPERLUMT})
+
+ENDIF(SUPERLUMT_FOUND)
+
+
+# create Makfile and CMakeLists.txt for examples
 IF(EXAMPLES_INSTALL)
 
   # Install the README file
@@ -131,23 +242,26 @@ IF(EXAMPLES_INSTALL)
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER "KINSOL")
   SET(SOLVER_LIB "sundials_kinsol")
-  LIST2STRING(KINSOL_examples EXAMPLES)
+
+  EXAMPLES2STRING(KINSOL_examples EXAMPLES)
+
   IF(LAPACK_FOUND)
-    LIST2STRING(KINSOL_examples_BL EXAMPLES_BL)
+    EXAMPLES2STRING(KINSOL_examples_BL EXAMPLES_BL)
   ELSE()
     SET(EXAMPLES_BL "")
   ENDIF()
 
-  IF(SUPERLUMT_FOUND)
-    LIST2STRING(KINSOL_examples_SUPERLUMT EXAMPLES)
-  ENDIF()
-
   IF(KLU_FOUND)
-    LIST2STRING(KINSOL_examples_KLU EXAMPLES)
+    EXAMPLES2STRING(KINSOL_examples_KLU EXAMPLES_KLU)
+  ELSE()
+    SET(EXAMPLES_KLU "")
   ENDIF()
 
-  STRING (REPLACE ";" " " TMP_STR ${EXAMPLES})
-  SET(EXAMPLES ${TMP_STR})
+  IF(SUPERLUMT_FOUND)
+    EXAMPLES2STRING(KINSOL_examples_SUPERLUMT EXAMPLES_SLUMT)
+  ELSE()
+    SET(EXAMPLES_SLUMT "")
+  ENDIF()
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -155,10 +269,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/kinsol/serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/kinsol/serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
@@ -176,7 +290,7 @@ IF(EXAMPLES_INSTALL)
       ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
       ${PROJECT_BINARY_DIR}/examples/kinsol/serial/Makefile_ex
       @ONLY
-      )    
+      )
     # install the configured Makefile_ex as Makefile
     INSTALL(
       FILES ${PROJECT_BINARY_DIR}/examples/kinsol/serial/Makefile_ex 
@@ -185,5 +299,8 @@ IF(EXAMPLES_INSTALL)
       )
   ENDIF(UNIX)
 
+  # add test_install target
+  SUNDIALS_ADD_TEST_INSTALL(kinsol kinRoberts_fp
+    EXAMPLE_DIR ${EXAMPLES_INSTALL_PATH}/kinsol/serial)
 
 ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/kinsol/serial/README b/examples/kinsol/serial/README
index ae1b396..bcf3503 100644
--- a/examples/kinsol/serial/README
+++ b/examples/kinsol/serial/README
@@ -1,6 +1,7 @@
 List of serial KINSOL examples
 
   kinFerTron_dns:          Ferraris-Tronconi example (DENSE)
+  kinFerTron_klu:          Ferraris-Tronconi example with KLU sparse linear solver
   kinFoodWeb_kry:          2-D food web system, block-diagonal preconditioner
   kinKrylovDemo_ls:        demonstration program with 3 Krylov solvers
   kinLaplace_bnd:          2-D elliptic PDE (BAND)
@@ -14,7 +15,6 @@ The following CMake command was used to configure SUNDIALS:
 
  cmake \
 -DCMAKE_BUILD_TYPE=DEBUG \
--DCXX_ENABLE=ON \
 -DBUILD_ARKODE=ON \
 -DBUILD_CVODE=ON \
 -DBUILD_CVODES=ON \
@@ -25,7 +25,10 @@ The following CMake command was used to configure SUNDIALS:
 -DEXAMPLES_INSTALL_PATH=/home/user1/sundials/build/install/examples \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_STATIC_LIBS=ON \
--DEXAMPLES_ENABLE=ON \
+-DEXAMPLES_ENABLE_C=ON \
+-DEXAMPLES_ENABLE_CXX=ON \
+-DEXAMPLES_ENABLE_F77=ON \
+-DEXAMPLES_ENABLE_F90=ON \
 -DEXAMPLES_INSTALL=ON \
 -DMPI_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
@@ -39,7 +42,6 @@ The following CMake command was used to configure SUNDIALS:
 -DOPENMP_ENABLE=ON \
 -DPTHREAD_ENABLE=ON \
 -DFCMIX_ENABLE=ON \
--DF90_ENABLE=ON \
 -DSUPERLUMT_ENABLE=ON \
 -DSUPERLUMT_INCLUDE_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/SRC \
 -DSUPERLUMT_LIBRARY_DIR=/usr/casc/sundials/apps/rh6/superlu_mt/SuperLU_MT_3.1/lib \
diff --git a/examples/kinsol/serial/kinFerTron_dns.c b/examples/kinsol/serial/kinFerTron_dns.c
index 1a3c3c3..5c92b9c 100644
--- a/examples/kinsol/serial/kinFerTron_dns.c
+++ b/examples/kinsol/serial/kinFerTron_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example (serial):
@@ -13,32 +9,31 @@
  *             C.A. Floudas, P.M. Pardalos et al.
  *             Kluwer Academic Publishers, 1999.
  * Test problem 4 from Section 14.1, Chapter 14: Ferraris and Tronconi
- * 
+ *
  * This problem involves a blend of trigonometric and exponential terms.
  *    0.5 sin(x1 x2) - 0.25 x2/pi - 0.5 x1 = 0
  *    (1-0.25/pi) ( exp(2 x1)-e ) + e x2 / pi - 2 e x1 = 0
  * such that
  *    0.25 <= x1 <=1.0
  *    1.5 <= x2 <= 2 pi
- * 
+ *
  * The treatment of the bound constraints on x1 and x2 is done using
  * the additional variables
  *    l1 = x1 - x1_min >= 0
  *    L1 = x1 - x1_max <= 0
  *    l2 = x2 - x2_min >= 0
  *    L2 = x2 - x2_max >= 0
- * 
+ *
  * and using the constraint feature in KINSOL to impose
  *    l1 >= 0    l2 >= 0
  *    L1 <= 0    L2 <= 0
- * 
+ *
  * The Ferraris-Tronconi test problem has two known solutions.
- * The nonlinear system is solved by KINSOL using different 
- * combinations of globalization and Jacobian update strategies 
+ * The nonlinear system is solved by KINSOL using different
+ * combinations of globalization and Jacobian update strategies
  * and with different initial guesses (leading to one or the other
  * of the known solutions).
  *
- *
  * Constraints are imposed to make all components of the solution
  * positive.
  * -----------------------------------------------------------------
@@ -48,19 +43,21 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts. */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector       */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix       */
+#include <kinsol/kinsol_direct.h>      /* access to KINDls interface      */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype */
+#include <sundials/sundials_math.h>    /* access to SUNRexp               */
 
 /* Problem Constants */
 
 #define NVAR   2
 #define NEQ    3*NVAR
 
-#define FTOL   RCONST(1.e-5)  /* function tolerance */
-#define STOL   RCONST(1.e-5) /* step tolerance */
+#define FTOL   RCONST(1.e-5) /* function tolerance */
+#define STOL   RCONST(1.e-5) /* step tolerance     */
 
 #define ZERO   RCONST(0.0)
 #define PT25   RCONST(0.25)
@@ -105,10 +102,14 @@ int main()
   N_Vector u1, u2, u, s, c;
   int glstr, mset, flag;
   void *kmem;
+  SUNMatrix J;
+  SUNLinearSolver LS;
 
   u1 = u2 = u = NULL;
   s = c = NULL;
   kmem = NULL;
+  J = NULL;
+  LS = NULL;
   data = NULL;
 
   /* User data */
@@ -163,10 +164,17 @@ int main()
   flag = KINInit(kmem, func, u);
   if (check_flag(&flag, "KINInit", 1)) return(1);
 
-  /* Call KINDense to specify the linear solver */
+  /* Create dense SUNMatrix */
+  J = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)J, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(u, J);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
 
-  flag = KINDense(kmem, NEQ);
-  if (check_flag(&flag, "KINDense", 1)) return(1);
+  /* Attach the matrix and linear solver to KINSOL */
+  flag = KINDlsSetLinearSolver(kmem, LS, J);
+  if(check_flag(&flag, "KINDlsSetLinearSolver", 1)) return(1);
 
   /* Print out the problem size, solution parameters, initial guess. */
   PrintHeader(fnormtol, scsteptol);
@@ -248,6 +256,8 @@ int main()
   N_VDestroy_Serial(s);
   N_VDestroy_Serial(c);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(J);
   free(data);
 
   return(0);
diff --git a/examples/kinsol/serial/kinFerTron_klu.c b/examples/kinsol/serial/kinFerTron_klu.c
index 2d8bc06..4044d84 100644
--- a/examples/kinsol/serial/kinFerTron_klu.c
+++ b/examples/kinsol/serial/kinFerTron_klu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4552 $
- * $Date: 2015-07-29 10:12:20 -0700 (Wed, 29 Jul 2015) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Example (serial):
@@ -38,7 +34,6 @@
  * and with different initial guesses (leading to one or the other
  * of the known solutions).
  *
- *
  * Constraints are imposed to make all components of the solution
  * positive.
  * -----------------------------------------------------------------
@@ -48,12 +43,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_klu.h>
-#include <kinsol/kinsol_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>              /* access to KINSOL func., consts. */
+#include <nvector/nvector_serial.h>     /* access to serial N_Vector       */
+#include <sunmatrix/sunmatrix_sparse.h> /* access to sparse SUNMatrix      */
+#include <kinsol/kinsol_direct.h>       /* access to KINDls interface      */
+#include <sunlinsol/sunlinsol_klu.h>    /* access to KLU SUNLinearSolver   */
+#include <sundials/sundials_types.h>    /* defs. of realtype, sunindextype */
+#include <sundials/sundials_math.h>     /* access to SUNRexp               */
 
 /* Problem Constants */
 
@@ -81,12 +77,8 @@ typedef struct {
 
 /* Functions Called by the KINSOL Solver */
 static int func(N_Vector u, N_Vector f, void *user_data);
-static int jac(N_Vector y, N_Vector f, SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2);
-static int jacDense(long int N,
-                    N_Vector y, N_Vector f,
-                    DlsMat J, void *user_data,
-                    N_Vector tmp1, N_Vector tmp2);
+static int jac(N_Vector y, N_Vector f, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2);
 
 /* Private Helper Functions */
 static void SetInitialGuess1(N_Vector u, UserData data);
@@ -110,10 +102,14 @@ int main()
   N_Vector u1, u2, u, s, c;
   int glstr, mset, flag;
   void *kmem;
+  SUNMatrix J;
+  SUNLinearSolver LS;
 
   u1 = u2 = u = NULL;
   s = c = NULL;
   kmem = NULL;
+  J = NULL;
+  LS = NULL;
   data = NULL;
 
   /* User data */
@@ -169,20 +165,21 @@ int main()
   flag = KINInit(kmem, func, u);
   if (check_flag(&flag, "KINInit", 1)) return(1);
 
-  /* Call KINDense to specify the linear solver */
-/*   
- * flag = KINDense(kmem, NEQ); // <-- Replace with KINKLU
- * if (check_flag(&flag, "KINDense", 1)) return(1);
- * flag = KINDlsSetDenseJacFn(kmem, jacDense);
- * if (check_flag(&flag, "KINDlsSetDenseJacFn", 1)) return(1);
- */
+  /* Create sparse SUNMatrix */
+  J = SUNSparseMatrix(NEQ, NEQ, data->nnz, CSR_MAT);
+  if(check_flag((void *)J, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create KLU solver object */
+  LS = SUNKLU(u, J);
+  if(check_flag((void *)LS, "SUNKLU", 0)) return(1);
 
-  /* Attach KLU linear solver, which uses CSR matrix */
-  flag = KINKLU(kmem, NEQ, data->nnz, CSR_MAT);
-  if (check_flag(&flag, "KINKLU", 1)) return(1);
+  /* Attach KLU linear solver */
+  flag = KINDlsSetLinearSolver(kmem, LS, J);
+  if(check_flag(&flag, "KINDlsSetLinearSolver", 1)) return(1);
 
-  flag = KINSlsSetSparseJacFn(kmem, jac);
-  if (check_flag(&flag, "KINSlsSetSparseJacFn", 1)) return(1);
+  /* Set the Jacobian function */
+  flag = KINDlsSetJacFn(kmem, jac);
+  if (check_flag(&flag, "KINDlsSetJacFn", 1)) return(1);
 
   /* Print out the problem size, solution parameters, initial guess. */
   PrintHeader(fnormtol, scsteptol);
@@ -266,6 +263,8 @@ int main()
   N_VDestroy_Serial(s);
   N_VDestroy_Serial(c);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(J);
   free(data);
 
   return(0);
@@ -350,21 +349,17 @@ static int func(N_Vector u, N_Vector f, void *user_data)
  * System Jacobian
  */
 
-static int jac(N_Vector y, N_Vector f,
-               SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2)
+static int jac(N_Vector y, N_Vector f, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2)
 {
   realtype *yd;
-  int *rowptrs;
-  int *colvals;
-  realtype *data;
+  sunindextype *rowptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *colvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
   
   yd = N_VGetArrayPointer_Serial(y);
-  rowptrs = (*J->rowptrs);
-  colvals = (*J->colvals);
-  data    = J->data;
   
-  SparseSetMatToZero(J);
+  SUNMatZero(J);
 
   rowptrs[0] =  0;
   rowptrs[1] =  2;
@@ -374,37 +369,37 @@ static int jac(N_Vector y, N_Vector f,
   rowptrs[5] = 10;
   rowptrs[6] = 12;
 
-  /* row 0 */
+  /* row 0: J(0,0) and J(0,1) */
   data[0] = PT5 * cos(yd[0]*yd[1]) * yd[1] - PT5;
   colvals[0] = 0;
   data[1] = PT5 * cos(yd[0]*yd[1]) * yd[0] - PT25/PI;
   colvals[1] = 1;
 
-  /* row 1 */
+  /* row 1: J(1,0) and J(1,1) */
   data[2] = TWO * (ONE - PT25/PI) * (SUNRexp(TWO*yd[0]) - E);
   colvals[2] = 0;
   data[3] = E/PI;
   colvals[3] = 1;
   
-  /* row 2 */
+  /* row 2: J(2,0) and J(2,2) */
   data[4] = -ONE;
   colvals[4] = 0;
   data[5] =  ONE;
   colvals[5] = 2;
   
-  /* row 3 */
+  /* row 3: J(3,0) and J(3,3) */
   data[6] = -ONE;
   colvals[6] = 0;
   data[7] =  ONE;
   colvals[7] = 3;
   
-  /* row 4 */
+  /* row 4: J(4,1) and J(4,4) */
   data[8] = -ONE;
   colvals[8] = 1;
   data[9] =  ONE;
   colvals[9] = 4;
   
-  /* row 5 */
+  /* row 5: J(5,1) and J(5,5) */
   data[10] = -ONE;
   colvals[10] = 1;
   data[11] =  ONE;
@@ -416,48 +411,6 @@ static int jac(N_Vector y, N_Vector f,
 
 
 /*
- * System dense Jacobian
- */
-
-static int jacDense(long int N,
-                    N_Vector y, N_Vector f,
-                    DlsMat J, void *user_data,
-                    N_Vector tmp1, N_Vector tmp2)
-{
-  realtype *yd;
-
-  yd = N_VGetArrayPointer_Serial(y);
-
-  /* row 0 */
-  DENSE_ELEM(J,0,0) = PT5 * cos(yd[0]*yd[1]) * yd[1] - PT5;
-  DENSE_ELEM(J,0,1) = PT5 * cos(yd[0]*yd[1]) * yd[0] - PT25/PI;
-
-  /* row 1 */
-  DENSE_ELEM(J,1,0) = TWO * (ONE - PT25/PI) * (SUNRexp(TWO*yd[0]) - E);
-  DENSE_ELEM(J,1,1) = E/PI;
-  
-  /* row 2 */
-  DENSE_ELEM(J,2,0) = -ONE;
-  DENSE_ELEM(J,2,2) =  ONE;
-  
-  /* row 3 */
-  DENSE_ELEM(J,3,0) = -ONE;
-  DENSE_ELEM(J,3,3) =  ONE;
-  
-  /* row 4 */
-  DENSE_ELEM(J,4,1) = -ONE;
-  DENSE_ELEM(J,4,4) =  ONE;
-  
-  /* row 5 */
-  DENSE_ELEM(J,5,1) = -ONE;
-  DENSE_ELEM(J,5,5) =  ONE;
-  
-
-  return(0);
-}
-
-
-/*
  *--------------------------------------------------------------------
  * PRIVATE FUNCTIONS
  *--------------------------------------------------------------------
@@ -558,20 +511,15 @@ static void PrintOutput(N_Vector u)
 
 static void PrintFinalStats(void *kmem)
 {
-  long int nni, nfe, nje, nfeD;
+  long int nni, nfe, nje;
   int flag;
   
   flag = KINGetNumNonlinSolvIters(kmem, &nni);
   check_flag(&flag, "KINGetNumNonlinSolvIters", 1);
   flag = KINGetNumFuncEvals(kmem, &nfe);
   check_flag(&flag, "KINGetNumFuncEvals", 1);
-
-/*   flag = KINDlsGetNumJacEvals(kmem, &nje);
- *   check_flag(&flag, "KINDlsGetNumJacEvals", 1);
- */
-
-  flag = KINSlsGetNumJacEvals(kmem, &nje);
-  check_flag(&flag, "KINSlsGetNumJacEvals", 1);
+  flag = KINDlsGetNumJacEvals(kmem, &nje);
+  check_flag(&flag, "KINDlsGetNumJacEvals", 1);
   
   printf("Final Statistics:\n");
   printf("  nni = %5ld    nfe  = %5ld \n", nni, nfe);
diff --git a/examples/kinsol/serial/kinFoodWeb_kry.c b/examples/kinsol/serial/kinFoodWeb_kry.c
index b6151ea..bd8d86f 100644
--- a/examples/kinsol/serial/kinFoodWeb_kry.c
+++ b/examples/kinsol/serial/kinFoodWeb_kry.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -13,10 +9,10 @@
  * population model, with predator-prey interaction and diffusion
  * on the unit square in two dimensions. The dependent variable
  * vector is the following:
- * 
+ *
  *       1   2         ns
  * c = (c , c ,  ..., c  )     (denoted by the variable cc)
- * 
+ *
  * and the PDE's are as follows:
  *
  *                    i       i
@@ -51,9 +47,9 @@
  *
  * The PDEs are discretized by central differencing on an MX by
  * MY mesh.
- * 
+ *
  * The nonlinear system is solved by KINSOL using the method
- * specified in local variable globalstrat.
+ * specified in the local variable globalstrat.
  *
  * The preconditioner matrix is a block-diagonal matrix based on
  * the partial derivatives of the interaction terms f only.
@@ -81,12 +77,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_spgmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts.      */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector            */
+#include <kinsol/kinsol_spils.h>       /* access to KINSpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h> /* access to SPGMR SUNLinearSolver      */
+#include <sundials/sundials_dense.h>   /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>    /* access to SUNMAX, SUNRabs, SUNRsqrt  */
 
 /* Problem Constants */
 
@@ -111,7 +108,7 @@
 #define FTOL        RCONST(1.e-7)  /* ftol tolerance */
 #define STOL        RCONST(1.e-13) /* stol tolerance */
 #define THOUSAND    RCONST(1000.0) /* one thousand */
-#define ZERO        RCONST(0.)     /* 0. */
+#define ZERO        RCONST(0.0)    /* 0. */
 #define ONE         RCONST(1.0)    /* 1. */
 #define TWO         RCONST(2.0)    /* 2. */
 #define PREYIN      RCONST(1.0)    /* initial guess for prey concentrations. */
@@ -131,13 +128,13 @@
 
 typedef struct {
   realtype **P[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   realtype **acoef, *bcoef;
   N_Vector rates;
   realtype *cox, *coy;
   realtype ax, ay, dx, dy;
   realtype uround, sqruround;
-  long int mx, my, ns, np;
+  sunindextype mx, my, ns, np;
 } *UserData;
 
 /* Functions Called by the KINSOL Solver */
@@ -146,13 +143,11 @@ static int func(N_Vector cc, N_Vector fval, void *user_data);
 
 static int PrecSetupBD(N_Vector cc, N_Vector cscale,
                        N_Vector fval, N_Vector fscale,
-                       void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2);
+                       void *user_data);
 
 static int PrecSolveBD(N_Vector cc, N_Vector cscale, 
                        N_Vector fval, N_Vector fscale, 
-                       N_Vector vv, void *user_data,
-                       N_Vector ftem);
+                       N_Vector vv, void *user_data);
 
 /* Private Helper Functions */
 
@@ -166,7 +161,7 @@ static void PrintOutput(N_Vector cc);
 static void PrintFinalStats(void *kmem);
 static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                     void *user_data);
-static realtype DotProd(long int size, realtype *x1, realtype *x2);
+static realtype DotProd(sunindextype size, realtype *x1, realtype *x2);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
 
 /*
@@ -183,9 +178,11 @@ int main(void)
   UserData data;
   int flag, maxl, maxlrst;
   void *kmem;
+  SUNLinearSolver LS;
 
   cc = sc = constraints = NULL;
   kmem = NULL;
+  LS = NULL;
   data = NULL;
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
@@ -233,15 +230,23 @@ int main(void)
      creates a private copy for KINSOL to use. */
   N_VDestroy_Serial(constraints);
 
-  /* Call KINSpgmr to specify the linear solver KINSPGMR with preconditioner
-     routines PrecSetupBD and PrecSolveBD. */
+
+  /* Create SUNSPGMR object with right preconditioning and the 
+     maximum Krylov dimension maxl */
   maxl = 15; 
+  LS = SUNSPGMR(cc, PREC_RIGHT, maxl);
+  if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
+
+  /* Attach the linear solver to KINSOL */
+  flag = KINSpilsSetLinearSolver(kmem, LS);
+  if (check_flag(&flag, "KINSpilsSetLinearSolver", 1)) return 1;
+
+  /* Set the maximum number of restarts */
   maxlrst = 2;
-  flag = KINSpgmr(kmem, maxl);
-  if (check_flag(&flag, "KINSpgmr", 1)) return(1);
+  flag = SUNSPGMRSetMaxRestarts(LS, maxlrst);
+  if (check_flag(&flag, "SUNSPGMRSpilsSetMaxRestarts", 1)) return(1);
 
-  flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
-  if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1)) return(1);
+  /* Specify the preconditioner setup and solve routines */
   flag = KINSpilsSetPreconditioner(kmem,
 				   PrecSetupBD,
 				   PrecSolveBD);
@@ -254,7 +259,7 @@ int main(void)
   flag = KINSol(kmem,           /* KINSol memory block */
                 cc,             /* initial guess on input; solution vector */
                 globalstrategy, /* global strategy choice */
-                sc,             /* scaling vector, for the variable cc */
+                sc,             /* scaling vector for the variable cc */
                 sc);            /* scaling vector for function values fval */
   if (check_flag(&flag, "KINSol", 1)) return(1);
 
@@ -267,6 +272,7 @@ int main(void)
   N_VDestroy_Serial(cc);
   N_VDestroy_Serial(sc);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
   FreeUserData(data);
 
   return(0);
@@ -292,7 +298,7 @@ int main(void)
 static int func(N_Vector cc, N_Vector fval, void *user_data)
 {
   realtype xx, yy, delx, dely, *cxy, *rxy, *fxy, dcyli, dcyui, dcxli, dcxri;
-  long int jx, jy, is, idyu, idyl, idxr, idxl;
+  sunindextype jx, jy, is, idyu, idyl, idxr, idxl;
   UserData data;
   
   data = (UserData)user_data;
@@ -352,12 +358,11 @@ static int func(N_Vector cc, N_Vector fval, void *user_data)
 
 static int PrecSetupBD(N_Vector cc, N_Vector cscale,
                        N_Vector fval, N_Vector fscale,
-                       void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2)
+                       void *user_data)
 {
   realtype r, r0, uround, sqruround, xx, yy, delx, dely, csave, fac;
   realtype *cxy, *scxy, **Pxy, *ratesxy, *Pxycol, perturb_rates[NUM_SPECIES];
-  long int i, j, jx, jy, ret;
+  sunindextype i, j, jx, jy, ret;
   UserData data;
   
   data = (UserData) user_data;
@@ -380,7 +385,7 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
       cxy = IJ_Vptr(cc,jx,jy);
       scxy= IJ_Vptr(cscale,jx,jy);
       ratesxy = IJ_Vptr((data->rates),jx,jy);
-      
+
       /* Compute difference quotients of interaction rate fn. */
       for (j = 0; j < NUM_SPECIES; j++) {
         
@@ -399,7 +404,6 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
         for (i = 0; i < NUM_SPECIES; i++)
           Pxycol[i] = (perturb_rates[i] - ratesxy[i]) * fac;
         
-        
       } /* end of j loop */
       
       /* Do LU decomposition of size NUM_SPECIES preconditioner block */
@@ -410,7 +414,7 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
     
   } /* end of jy loop */
   
-  return(0);  
+  return(0);
 }
 
 /*
@@ -419,11 +423,10 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
 
 static int PrecSolveBD(N_Vector cc, N_Vector cscale, 
                        N_Vector fval, N_Vector fscale, 
-                       N_Vector vv, void *user_data,
-                       N_Vector ftem)
+                       N_Vector vv, void *user_data)
 {
   realtype **Pxy, *vxy;
-  long int *piv, jx, jy;
+  sunindextype *piv, jx, jy;
   UserData data;
   
   data = (UserData)user_data;
@@ -455,7 +458,7 @@ static int PrecSolveBD(N_Vector cc, N_Vector cscale,
 static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy, 
                     void *user_data)
 {
-  long int i;
+  sunindextype i;
   realtype fac;
   UserData data;
   
@@ -467,22 +470,22 @@ static void WebRate(realtype xx, realtype yy, realtype *cxy, realtype *ratesxy,
   fac = ONE + ALPHA * xx * yy;
   
   for (i = 0; i < NUM_SPECIES; i++)
-    ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );  
+    ratesxy[i] = cxy[i] * ( bcoef[i] * fac + ratesxy[i] );
 }
 
 /*
  * Dot product routine for realtype arrays 
  */
 
-static realtype DotProd(long int size, realtype *x1, realtype *x2)
+static realtype DotProd(sunindextype size, realtype *x1, realtype *x2)
 {
-  long int i;
+  sunindextype i;
   realtype *xx1, *xx2, temp = ZERO;
   
   xx1 = x1; xx2 = x2;
   for (i = 0; i < size; i++) temp += (*xx1++) * (*xx2++);
 
-  return(temp);  
+  return(temp);
 }
 
 /*
@@ -505,9 +508,10 @@ static UserData AllocUserData(void)
   for (jx=0; jx < MX; jx++) {
     for (jy=0; jy < MY; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
+
   acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
   bcoef = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
   cox   = (realtype *)malloc(NUM_SPECIES * sizeof(realtype));
@@ -516,13 +520,13 @@ static UserData AllocUserData(void)
   return(data);
 }
 
-/* 
+/*
  * Load problem constants in data 
  */
 
 static void InitUserData(UserData data)
 {
-  long int i, j, np;
+  sunindextype i, j, np;
   realtype *a1,*a2, *a3, *a4, dx2, dy2;
 
   data->mx = MX;
@@ -567,24 +571,24 @@ static void InitUserData(UserData data)
 
     coy[i]=DPREY/dy2;
     coy[i+np]=DPRED/dy2;
-  }  
+  }
 }
 
-/* 
+/*
  * Free data memory 
  */
 
 static void FreeUserData(UserData data)
 {
   int jx, jy;
-  
+
   for (jx=0; jx < MX; jx++) {
     for (jy=0; jy < MY; jy++) {
       destroyMat((data->P)[jx][jy]);
       destroyArray((data->pivot)[jx][jy]);
     }
   }
-  
+
   destroyMat(acoef);
   free(bcoef);
   free(cox);
@@ -593,7 +597,7 @@ static void FreeUserData(UserData data)
   free(data);
 }
 
-/* 
+/*
  * Set initial conditions in cc 
  */
 
@@ -670,7 +674,7 @@ static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
 #endif
 }
 
-/* 
+/*
  * Print sampled values of current cc 
  */
 
@@ -713,7 +717,7 @@ static void PrintOutput(N_Vector cc)
   printf("\n\n");
 }
 
-/* 
+/*
  * Print final statistics contained in iopt 
  */
 
@@ -721,7 +725,7 @@ static void PrintFinalStats(void *kmem)
 {
   long int nni, nfe, nli, npe, nps, ncfl, nfeSG;
   int flag;
-  
+
   flag = KINGetNumNonlinSolvIters(kmem, &nni);
   check_flag(&flag, "KINGetNumNonlinSolvIters", 1);
   flag = KINGetNumFuncEvals(kmem, &nfe);
@@ -741,7 +745,7 @@ static void PrintFinalStats(void *kmem)
   printf("nni    = %5ld    nli   = %5ld\n", nni, nli);
   printf("nfe    = %5ld    nfeSG = %5ld\n", nfe, nfeSG);
   printf("nps    = %5ld    npe   = %5ld     ncfl  = %5ld\n", nps, npe, ncfl);
-  
+
 }
 
 /*
@@ -773,7 +777,7 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
       fprintf(stderr,
               "\nSUNDIALS_ERROR: %s() failed with flag = %d\n\n",
 	      funcname, *errflag);
-      return(1); 
+      return(1);
     }
   }
 
diff --git a/examples/kinsol/serial/kinFoodWeb_kry.out b/examples/kinsol/serial/kinFoodWeb_kry.out
index 61a7dc0..6d6b810 100644
--- a/examples/kinsol/serial/kinFoodWeb_kry.out
+++ b/examples/kinsol/serial/kinFoodWeb_kry.out
@@ -24,6 +24,6 @@ At top right:
  1.25797 1.25797 1.25797 37736.7 37736.7 37736.7
 
 Final Statistics.. 
-nni    =    10    nli   =   378
-nfe    =    11    nfeSG =   388
-nps    =   388    npe   =     1     ncfl  =     7
+nni    =     9    nli   =   329
+nfe    =    10    nfeSG =   338
+nps    =   338    npe   =     1     ncfl  =     6
diff --git a/examples/kinsol/serial/kinKrylovDemo_ls.c b/examples/kinsol/serial/kinKrylovDemo_ls.c
index d446e05..05f90a0 100644
--- a/examples/kinsol/serial/kinKrylovDemo_ls.c
+++ b/examples/kinsol/serial/kinKrylovDemo_ls.c
@@ -1,14 +1,10 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4840 $
- * $Date: 2016-08-03 13:07:16 -0700 (Wed, 03 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  *
  * This example loops through the available iterative linear solvers:
- * SPGMR, SPBCG, SPTFQMR, and SPFGMR.
+ * SPGMR, SPBCGS, SPTFQMR, and SPFGMR.
  *
  * Example (serial):
  *
@@ -85,15 +81,16 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_spgmr.h>
-#include <kinsol/kinsol_spbcgs.h>
-#include <kinsol/kinsol_sptfqmr.h>
-#include <kinsol/kinsol_spfgmr.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_dense.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>               /* access to KINSOL func., consts.      */
+#include <nvector/nvector_serial.h>      /* access to serial N_Vector            */
+#include <kinsol/kinsol_spils.h>         /* access to KINSpils interface         */
+#include <sunlinsol/sunlinsol_spgmr.h>   /* access to SPGMR SUNLinearSolver      */
+#include <sunlinsol/sunlinsol_spbcgs.h>  /* access to SPBCGS SUNLinearSolver     */ 
+#include <sunlinsol/sunlinsol_sptfqmr.h> /* access to SPTFQMR SUNLinearSolver    */
+#include <sunlinsol/sunlinsol_spfgmr.h>  /* access to SPFGMR SUNLinearSolver     */ 
+#include <sundials/sundials_dense.h>     /* use generic dense solver in precond. */
+#include <sundials/sundials_types.h>     /* defs. of realtype, sunindextype      */
+#include <sundials/sundials_math.h>      /* access to SUNMAX, SUNRabs, SUNRsqrt  */
 
 /* Problem Constants */
 
@@ -127,7 +124,7 @@
 /* Linear Solver Loop Constants */
 
 #define USE_SPGMR   0
-#define USE_SPBCG   1
+#define USE_SPBCGS  1
 #define USE_SPTFQMR 2
 #define USE_SPFGMR  3
 
@@ -145,7 +142,7 @@
 
 typedef struct {
   realtype **P[MX][MY];
-  long int *pivot[MX][MY];
+  sunindextype *pivot[MX][MY];
   realtype **acoef, *bcoef;
   N_Vector rates;
   realtype *cox, *coy;
@@ -160,13 +157,11 @@ static int func(N_Vector cc, N_Vector fval, void *user_data);
 
 static int PrecSetupBD(N_Vector cc, N_Vector cscale,
                        N_Vector fval, N_Vector fscale,
-                       void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2);
+                       void *user_data);
 
 static int PrecSolveBD(N_Vector cc, N_Vector cscale, 
                        N_Vector fval, N_Vector fscale, 
-                       N_Vector vv, void *user_data,
-                       N_Vector ftem);
+                       N_Vector vv, void *user_data);
 
 /* Private Helper Functions */
 
@@ -198,9 +193,11 @@ int main(void)
   UserData data;
   int flag, maxl, maxlrst;
   void *kmem;
+  SUNLinearSolver LS;
 
   cc = sc = constraints = NULL;
   kmem = NULL;
+  LS = NULL;
   data = NULL;
 
   /* Allocate memory, and set problem data, initial values, tolerances */ 
@@ -224,7 +221,7 @@ int main(void)
 
   fnormtol=FTOL; scsteptol=STOL;
 
-  /* START: Loop through SPGMR, SPBCG, SPTFQMR and SPFGMR linear solver modules */
+  /* START: Loop through SPGMR, SPBCGS, SPTFQMR and SPFGMR linear solver modules */
   for (linsolver = 0; linsolver < 4; ++linsolver) {
 
     /* (Re-)Initialize user data */
@@ -259,31 +256,40 @@ int main(void)
       printf(" \n| SPGMR |\n");
       printf(" -------\n");
 
-      /* Call KINSpgmr to specify the linear solver KINSPGMR with preconditioner
-	 routines PrecSetupBD and PrecSolveBD, and the pointer to the user block data. */
+      /* Create SUNSPGMR object with right preconditioning and the 
+         maximum Krylov dimension maxl */
       maxl = 15; 
-      maxlrst = 2;
-      flag = KINSpgmr(kmem, maxl);
-      if (check_flag(&flag, "KINSpgmr", 1)) return(1);
+      LS = SUNSPGMR(cc, PREC_RIGHT, maxl);
+      if(check_flag((void *)LS, "SUNSPGMR", 0)) return(1);
 
-      flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
-      if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1)) return(1);
+      /* Attach the linear solver to KINSOL */
+      flag = KINSpilsSetLinearSolver(kmem, LS);
+      if (check_flag(&flag, "KINSpilsSetLinearSolver", 1)) return 1;
+
+      /* Set the maximum number of restarts */
+      maxlrst = 2;
+      flag = SUNSPGMRSetMaxRestarts(LS, maxlrst);
+      if (check_flag(&flag, "SUNSPGMRSpilsSetMaxRestarts", 1)) return(1);
 
       break;
 
-    /* (b) SPBCG */
-    case(USE_SPBCG):
+    /* (b) SPBCGS */
+    case(USE_SPBCGS):
 
       /* Print header */
-      printf(" -------");
-      printf(" \n| SPBCG |\n");
-      printf(" -------\n");
+      printf(" --------");
+      printf(" \n| SPBCGS |\n");
+      printf(" --------\n");
 
-      /* Call KINSpbcg to specify the linear solver KINSPBCG with preconditioner
-	 routines PrecSetupBD and PrecSolveBD, and the pointer to the user block data. */
+      /* Create SUNSPBCGS object with right preconditioning and the 
+         maximum Krylov dimension maxl */
       maxl = 15; 
-      flag = KINSpbcg(kmem, maxl);
-      if (check_flag(&flag, "KINSpbcg", 1)) return(1);
+      LS = SUNSPBCGS(cc, PREC_RIGHT, maxl);
+      if(check_flag((void *)LS, "SUNSPBCGS", 0)) return(1);
+
+      /* Attach the linear solver to KINSOL */
+      flag = KINSpilsSetLinearSolver(kmem, LS);
+      if (check_flag(&flag, "KINSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -295,11 +301,15 @@ int main(void)
       printf(" \n| SPTFQMR |\n");
       printf(" ---------\n");
 
-      /* Call KINSptfqmr to specify the linear solver KINSPTFQMR with preconditioner
-	 routines PrecSetupBD and PrecSolveBD, and the pointer to the user block data. */
+      /* Create SUNSPTFQMR object with right preconditioning and the 
+         maximum Krylov dimension maxl */
       maxl = 25; 
-      flag = KINSptfqmr(kmem, maxl);
-      if (check_flag(&flag, "KINSptfqmr", 1)) return(1);
+      LS = SUNSPTFQMR(cc, PREC_RIGHT, maxl);
+      if(check_flag((void *)LS, "SUNSPTFQMR", 0)) return(1);
+
+      /* Attach the linear solver to KINSOL */
+      flag = KINSpilsSetLinearSolver(kmem, LS);
+      if (check_flag(&flag, "KINSpilsSetLinearSolver", 1)) return 1;
 
       break;
 
@@ -311,15 +321,20 @@ int main(void)
       printf(" \n| SPFGMR |\n");
       printf(" -------\n");
 
-      /* Call KINSpfgmr to specify the linear solver KINSPFGMR with preconditioner
-	 routines PrecSetupBD and PrecSolveBD, and the pointer to the user block data. */
+      /* Create SUNSPFGMR object with right preconditioning and the 
+         maximum Krylov dimension maxl */
       maxl = 15; 
-      maxlrst = 2;
-      flag = KINSpfgmr(kmem, maxl);
-      if (check_flag(&flag, "KINSpfgmr", 1)) return(1);
+      LS = SUNSPFGMR(cc, PREC_RIGHT, maxl);
+      if(check_flag((void *)LS, "SUNSPFGMR", 0)) return(1);
+
+      /* Attach the linear solver to KINSOL */
+      flag = KINSpilsSetLinearSolver(kmem, LS);
+      if (check_flag(&flag, "KINSpilsSetLinearSolver", 1)) return 1;
 
-      flag = KINSpilsSetMaxRestarts(kmem, maxlrst);
-      if (check_flag(&flag, "KINSpilsSetMaxRestarts", 1)) return(1);
+      /* Set the maximum number of restarts */
+      maxlrst = 2;
+      flag = SUNSPGMRSetMaxRestarts(LS, maxlrst);
+      if (check_flag(&flag, "SUNSPGMRSpilsSetMaxRestarts", 1)) return(1);
 
       break;
 
@@ -347,8 +362,9 @@ int main(void)
     PrintFinalStats(kmem, linsolver);
 
     KINFree(&kmem);
+    SUNLinSolFree(LS);
 
-  }  /* END: Loop through SPGMR, SPBCG, SPTFQMR, and SPFGMR linear solver modules */
+  }  /* END: Loop through SPGMR, SPBCGS, SPTFQMR, and SPFGMR linear solver modules */
 
   N_VDestroy_Serial(constraints);
   N_VDestroy_Serial(cc);
@@ -438,8 +454,7 @@ static int func(N_Vector cc, N_Vector fval, void *user_data)
 
 static int PrecSetupBD(N_Vector cc, N_Vector cscale,
                        N_Vector fval, N_Vector fscale,
-                       void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2)
+                       void *user_data)
 {
   realtype r, r0, uround, sqruround, xx, yy, delx, dely, csave, fac;
   realtype *cxy, *scxy, **Pxy, *ratesxy, *Pxycol, perturb_rates[NUM_SPECIES];
@@ -505,11 +520,10 @@ static int PrecSetupBD(N_Vector cc, N_Vector cscale,
 
 static int PrecSolveBD(N_Vector cc, N_Vector cscale, 
                        N_Vector fval, N_Vector fscale, 
-                       N_Vector vv, void *user_data,
-                       N_Vector ftem)
+                       N_Vector vv, void *user_data)
 {
   realtype **Pxy, *vxy;
-  long int *piv, jx, jy;
+  sunindextype *piv, jx, jy;
   UserData data;
   
   data = (UserData)user_data;
@@ -591,7 +605,7 @@ static UserData AllocUserData(void)
   for (jx=0; jx < MX; jx++) {
     for (jy=0; jy < MY; jy++) {
       (data->P)[jx][jy] = newDenseMat(NUM_SPECIES, NUM_SPECIES);
-      (data->pivot)[jx][jy] = newLintArray(NUM_SPECIES);
+      (data->pivot)[jx][jy] = newIndexArray(NUM_SPECIES);
     }
   }
   acoef = newDenseMat(NUM_SPECIES, NUM_SPECIES);
@@ -734,8 +748,8 @@ static void PrintHeader(int globalstrategy, int maxl, int maxlrst,
 	   maxl, maxlrst);
     break;
 
-  case(USE_SPBCG):
-    printf("Linear solver is SPBCG with maxl = %d\n", maxl);
+  case(USE_SPBCGS):
+    printf("Linear solver is SPBCGS with maxl = %d\n", maxl);
     break;
 
   case(USE_SPTFQMR):
diff --git a/examples/kinsol/serial/kinKrylovDemo_ls.out b/examples/kinsol/serial/kinKrylovDemo_ls.out
index 577c261..b4936c9 100644
--- a/examples/kinsol/serial/kinKrylovDemo_ls.out
+++ b/examples/kinsol/serial/kinKrylovDemo_ls.out
@@ -33,9 +33,9 @@ nps    =   120    npe   =     1     ncfl  =     2
 
 =========================================================
 
- ------- 
-| SPBCG |
- -------
+ -------- 
+| SPBCGS |
+ --------
 
 Predator-prey test problem --  KINSol (serial version)
 
@@ -44,7 +44,7 @@ Number of species = 6
 Total system size = 150
 
 Flag globalstrategy = 0 (0 = None, 1 = Linesearch)
-Linear solver is SPBCG with maxl = 15
+Linear solver is SPBCGS with maxl = 15
 Preconditioning uses interaction-only block-diagonal matrix
 Positivity constraints imposed on all components 
 Tolerance parameters:  fnormtol = 1e-07   scsteptol = 1e-13
diff --git a/examples/kinsol/serial/kinLaplace_bnd.c b/examples/kinsol/serial/kinLaplace_bnd.c
index cade735..19a0999 100644
--- a/examples/kinsol/serial/kinLaplace_bnd.c
+++ b/examples/kinsol/serial/kinLaplace_bnd.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * This example solves a 2D elliptic PDE
@@ -12,8 +8,8 @@
  * subject to homogeneous Dirichelt boundary conditions.
  * The PDE is discretized on a uniform NX+2 by NY+2 grid with
  * central differencing, and with boundary values eliminated,
- * leaving an system of size NEQ = NX*NY.
- * The nonlinear system is solved by KINSOL using the BAND linear
+ * leaving a system of size NEQ = NX*NY.
+ * The nonlinear system is solved by KINSOL using the SUNBAND linear
  * solver.
  * -----------------------------------------------------------------
  */
@@ -22,11 +18,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_band.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts. */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector       */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix        */
+#include <kinsol/kinsol_direct.h>      /* access to KINDls interface      */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver  */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype */
+#include <sundials/sundials_math.h>    /* access to SUNRexp               */
 
 /* Problem Constants */
 
@@ -47,7 +45,7 @@
    to the underlying 1-dimensional storage. 
    IJth(vdata,i,j) references the element in the vdata array for
    u at mesh point (i,j), where 1 <= i <= NX, 1 <= j <= NY.
-   The vdata array is obtained via the macro call vdata = N_VGetArrayPointer_Serial(v),
+   The vdata array is obtained via the call vdata = N_VGetArrayPointer_Serial(v),
    where v is an N_Vector. 
    The variables are ordered by the y index j, then by the x index i. */
 
@@ -72,9 +70,13 @@ int main()
   N_Vector y, scale;
   int mset, msubset, flag;
   void *kmem;
+  SUNMatrix J;
+  SUNLinearSolver LS;
 
   y = scale = NULL;
   kmem = NULL;
+  J = NULL;
+  LS = NULL;
 
   /* -------------------------
    * Print problem description
@@ -119,11 +121,25 @@ int main()
   if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);
 
   /* -------------------------
+   * Create band SUNMatrix
+   * ------------------------- */
+
+  J = SUNBandMatrix(NEQ, NX, NX, 2*NX);
+  if(check_flag((void *)J, "SUNBandMatrix", 0)) return(1);
+
+  /* ---------------------------
+   * Create band SUNLinearSolver
+   * --------------------------- */
+
+  LS = SUNBandLinearSolver(y, J);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* -------------------------
    * Attach band linear solver 
    * ------------------------- */
 
-  flag = KINBand(kmem, NEQ, NX, NX);
-  if (check_flag(&flag, "KINBand", 1)) return(1);
+  flag = KINDlsSetLinearSolver(kmem, LS, J);
+  if(check_flag(&flag, "KINDlsSetLinearSolver", 1)) return(1);
 
   /* ------------------------------
    * Parameters for Modified Newton
@@ -171,7 +187,11 @@ int main()
   flag = KINGetFuncNorm(kmem, &fnorm);
   if (check_flag(&flag, "KINGetfuncNorm", 1)) return(1);
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("\nComputed solution (||F|| = %Lg):\n\n",fnorm);
+#else
   printf("\nComputed solution (||F|| = %g):\n\n",fnorm);
+#endif  
   PrintOutput(y);
 
   PrintFinalStats(kmem);
@@ -183,6 +203,8 @@ int main()
   N_VDestroy_Serial(y);
   N_VDestroy_Serial(scale);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(J);
 
   return(0);
 }
diff --git a/examples/kinsol/serial/kinLaplace_bnd.out b/examples/kinsol/serial/kinLaplace_bnd.out
index 5f43154..c0589a0 100644
--- a/examples/kinsol/serial/kinLaplace_bnd.out
+++ b/examples/kinsol/serial/kinLaplace_bnd.out
@@ -6,7 +6,7 @@
 Solution method: Modified Newton with band linear solver
 Problem size: 31 x 31 =  961
 
-Computed solution (||F|| = 1.37621e-12):
+Computed solution (||F|| = 1.3498e-12):
 
             0.03125  0.12500  0.21875  0.31250  0.40625  0.50000  0.59375  0.68750  0.78125  0.87500  0.96875  
 
@@ -29,4 +29,4 @@ nbcfails =      0    nbacktr =      0
 nje      =      1    nfeB    =     63 
 
 lenrw    =   4822    leniw   =     27 
-lenrwB   = 150877    leniwB  =    961 
+lenrwB   =      0    leniwB  =    966 
diff --git a/examples/kinsol/serial/kinLaplace_picard_bnd.c b/examples/kinsol/serial/kinLaplace_picard_bnd.c
index b93a710..802d898 100644
--- a/examples/kinsol/serial/kinLaplace_picard_bnd.c
+++ b/examples/kinsol/serial/kinLaplace_picard_bnd.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward @ LLNL
  * -----------------------------------------------------------------
  * This example solves a 2D elliptic PDE
@@ -14,7 +10,7 @@
  * central differencing, and with boundary values eliminated,
  * leaving a system of size NEQ = NX*NY.
  * The nonlinear system is solved by KINSOL using the Picard
- * iteration and the BAND linear solver.
+ * iteration and the SUNBAND linear solver.
  *
  * This file is strongly based on the kinLaplace_bnd.c file 
  * developed by Radu Serban.
@@ -25,18 +21,18 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_band.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts. */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector       */
+#include <sunmatrix/sunmatrix_band.h>  /* access to band SUNMatrix        */
+#include <kinsol/kinsol_direct.h>      /* access to KINDls interface      */
+#include <sunlinsol/sunlinsol_band.h>  /* access to band SUNLinearSolver  */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype */
+#include <sundials/sundials_math.h>    /* access to SUNRexp               */
 
 /* Problem Constants */
 
 #define NX   31             /* no. of points in x direction */
 #define NY   31             /* no. of points in y direction */
-/* #define NX   3 */             /* no. of points in x direction */
-/* #define NY   3 */            /* no. of points in y direction */
 #define NEQ  NX*NY          /* problem dimension */
 
 #define SKIP 3              /* no. of points skipped for printing */
@@ -52,7 +48,7 @@
    to the underlying 1-dimensional storage. 
    IJth(vdata,i,j) references the element in the vdata array for
    u at mesh point (i,j), where 1 <= i <= NX, 1 <= j <= NY.
-   The vdata array is obtained via the macro call vdata = N_VGetArrayPointer_Serial(v),
+   The vdata array is obtained via the call vdata = N_VGetArrayPointer_Serial(v),
    where v is an N_Vector. 
    The variables are ordered by the y index j, then by the x index i. */
 
@@ -61,9 +57,8 @@
 /* Private functions */
 
 static int func(N_Vector u, N_Vector f, void *user_data);
-static int jac(long int N, long int mu, long int ml, 
-	       N_Vector u, N_Vector f, DlsMat J, void *user_data,
-	       N_Vector tmp1, N_Vector tmp2);
+static int jac(N_Vector u, N_Vector f, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2);
 static void PrintOutput(N_Vector u);
 static void PrintFinalStats(void *kmem);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -80,9 +75,13 @@ int main()
   N_Vector y, scale;
   int flag;
   void *kmem;
+  SUNMatrix J;
+  SUNLinearSolver LS;
 
   y = scale = NULL;
   kmem = NULL;
+  J = NULL;
+  LS = NULL;
 
   /* -------------------------
    * Print problem description
@@ -92,8 +91,7 @@ int main()
   printf("   d^2 u / dx^2 + d^2 u / dy^2 = u^3 - u + 2.0\n");
   printf(" + homogeneous Dirichlet boundary conditions\n\n");
   printf("Solution method: Anderson accelerated Picard iteration with band linear solver.\n");
-  printf("Problem size: %2ld x %2ld = %4ld\n", 
-	 (long int) NX, (long int) NY, (long int) NEQ);
+  printf("Problem size: %2ld x %2ld = %4ld\n", (long int) NX, (long int) NY, (long int) NEQ);
 
   /* --------------------------------------
    * Create vectors for solution and scales
@@ -132,13 +130,32 @@ int main()
   if (check_flag(&flag, "KINSetFuncNormTol", 1)) return(1);
 
   /* -------------------------
+   * Create band SUNMatrix
+   * ------------------------- */
+
+  J = SUNBandMatrix(NEQ, NX, NX, 2*NX);
+  if(check_flag((void *)J, "SUNBandMatrix", 0)) return(1);
+
+  /* ---------------------------
+   * Create band SUNLinearSolver
+   * --------------------------- */
+
+  LS = SUNBandLinearSolver(y, J);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
+
+  /* -------------------------
    * Attach band linear solver 
    * ------------------------- */
 
-  flag = KINBand(kmem, NEQ, NX, NX);
-  if (check_flag(&flag, "KINBand", 1)) return(1);
-  flag = KINDlsSetBandJacFn(kmem, jac);
-  if (check_flag(&flag, "KINDlsBandJacFn", 1)) return(1);
+  flag = KINDlsSetLinearSolver(kmem, LS, J);
+  if(check_flag(&flag, "KINDlsSetLinearSolver", 1)) return(1);
+
+  /* -------------------------
+   * Set Jacobian function
+   * ------------------------- */
+
+  flag = KINDlsSetJacFn(kmem, jac);
+  if (check_flag(&flag, "KINDlsSetJacFn", 1)) return(1);
 
   /* -------------
    * Initial guess 
@@ -172,7 +189,11 @@ int main()
   flag = KINGetFuncNorm(kmem, &fnorm);
   if (check_flag(&flag, "KINGetfuncNorm", 1)) return(1);
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("\nComputed solution (||F|| = %Lg):\n\n",fnorm);
+#else
   printf("\nComputed solution (||F|| = %g):\n\n",fnorm);
+#endif  
   PrintOutput(y);
 
   PrintFinalStats(kmem);
@@ -184,6 +205,8 @@ int main()
   N_VDestroy_Serial(y);
   N_VDestroy_Serial(scale);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(J);
 
   return(0);
 }
@@ -252,10 +275,8 @@ static int func(N_Vector u, N_Vector f, void *user_data)
  * Jacobian function 
  */
 
-static int jac(long int N, long int mu, long int ml, 
-	       N_Vector u, N_Vector f, 
-	       DlsMat J, void *user_data,
-	       N_Vector tmp1, N_Vector tmp2)
+static int jac(N_Vector u, N_Vector f, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2)
 {
   realtype dx, dy;
   realtype hdc, vdc;
@@ -263,8 +284,8 @@ static int jac(long int N, long int mu, long int ml,
 
   int i, j, k;
 
-  dx = ONE/(NX+1);  
-  dy = ONE/(NY+1);
+  dx  = ONE/(NX+1);  
+  dy  = ONE/(NY+1);
   hdc = ONE/(dx*dx);
   vdc = ONE/(dy*dy);
 
@@ -279,7 +300,6 @@ static int jac(long int N, long int mu, long int ml,
      f_{i+1,j} = hdc*(u_{i,j}    -2u_{i+1,j}+u_{i+2,j})   + vdc*(u_{i+1,j-1}-2u_{i+1,j}+u_{i+1,j+1})
      f_{i,j-1} = hdc*(u_{i-1,j-1}-2u_{i,j-1}+u_{i+1,j-1}) + vdc*(u_{i,j-2}  -2u_{i,j-1}+u_{i,j})
      f_{i,j+1} = hdc*(u_{i-1,j+1}-2u_{i,j+1}+u_{i+1,j+1}) + vdc*(u_{i,j}    -2u_{i,j+1}+u_{i,j+2})
-
   */
 
   for (j=0; j <= NY-1; j++) {
@@ -288,12 +308,12 @@ static int jac(long int N, long int mu, long int ml,
       /* Evaluate diffusion coefficients */
 
       k = i + j*NX;
-      kthCol = BAND_COL(J, k);
-      BAND_COL_ELEM(kthCol,k,k) = -2.0*hdc - 2.0*vdc;
-      if ( i != (NX-1) ) BAND_COL_ELEM(kthCol,k+1,k) = hdc;
-      if ( i != 0 )      BAND_COL_ELEM(kthCol,k-1,k) = hdc;
-      if ( j != (NY-1) ) BAND_COL_ELEM(kthCol,k+NX,k) = vdc;
-      if ( j != 0 )      BAND_COL_ELEM(kthCol,k-NX,k) = vdc;
+      kthCol = SUNBandMatrix_Column(J, k);
+      SM_COLUMN_ELEMENT_B(kthCol,k,k) = -2.0*hdc - 2.0*vdc;
+      if ( i != (NX-1) ) SM_COLUMN_ELEMENT_B(kthCol,k+1,k)  = hdc;
+      if ( i != 0 )      SM_COLUMN_ELEMENT_B(kthCol,k-1,k)  = hdc;
+      if ( j != (NY-1) ) SM_COLUMN_ELEMENT_B(kthCol,k+NX,k) = vdc;
+      if ( j != 0 )      SM_COLUMN_ELEMENT_B(kthCol,k-NX,k) = vdc;
     }
   }
 
@@ -313,7 +333,7 @@ static void PrintOutput(N_Vector u)
   dx = ONE/(NX+1);
   dy = ONE/(NY+1);
 
-  udata =  N_VGetArrayPointer_Serial(u);
+  udata = N_VGetArrayPointer_Serial(u);
 
   printf("            ");
   for (i=1; i<=NX; i+= SKIP) {
diff --git a/examples/kinsol/serial/kinLaplace_picard_bnd.out b/examples/kinsol/serial/kinLaplace_picard_bnd.out
index 6ef27cc..00e63f9 100644
--- a/examples/kinsol/serial/kinLaplace_picard_bnd.out
+++ b/examples/kinsol/serial/kinLaplace_picard_bnd.out
@@ -27,4 +27,4 @@ Final Statistics..
 nni      =      6    nfe     =      7 
 nje      =      6    nfeB    =      0 
 
-lenrwB   = 150877    leniwB  =    961 
+lenrwB   =      0    leniwB  =    966 
diff --git a/examples/kinsol/serial/kinRoberts_fp.c b/examples/kinsol/serial/kinRoberts_fp.c
index 82edd67..2cb22d5 100644
--- a/examples/kinsol/serial/kinRoberts_fp.c
+++ b/examples/kinsol/serial/kinRoberts_fp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward @ LLNL
  * -----------------------------------------------------------------
  * Example problem:
@@ -26,12 +22,9 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
-
-/* Problem Constants */
+#include <kinsol/kinsol.h>           /* access to KINSOL func., consts. */
+#include <nvector/nvector_serial.h>  /* access to serial N_Vector       */
+#include <sundials/sundials_types.h> /* defs. of realtype, sunindextype */
 
 /* Problem Constants */
 
@@ -67,6 +60,7 @@ static int funcRoberts(N_Vector u, N_Vector f, void *user_data);
 static void PrintOutput(N_Vector u);
 static void PrintFinalStats(void *kmem);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
+static int check_ans(N_Vector u, realtype rtol, realtype atol);
 
 /*
  *--------------------------------------------------------------------
@@ -166,11 +160,18 @@ int main()
   flag = KINGetFuncNorm(kmem, &fnorm);
   if (check_flag(&flag, "KINGetfuncNorm", 1)) return(1);
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+  printf("\nComputed solution (||F|| = %Lg):\n\n",fnorm);
+#else
   printf("\nComputed solution (||F|| = %g):\n\n",fnorm);
+#endif  
   PrintOutput(y);
 
   PrintFinalStats(kmem);
 
+  /* check the solution error */
+  flag = check_ans(y, RCONST(1e-4), RCONST(1e-6));
+
   /* -----------
    * Free memory 
    * ----------- */
@@ -179,7 +180,7 @@ int main()
   N_VDestroy_Serial(scale);
   KINFree(&kmem);
 
-  return(0);
+  return(flag);
 }
 
 /*
@@ -297,3 +298,49 @@ static int check_flag(void *flagvalue, const char *funcname, int opt)
 
   return(0);
 }
+
+/* compare the solution to a reference solution computed with a
+   tolerance of 1e-14 */
+static int check_ans(N_Vector u, realtype rtol, realtype atol)
+{
+  int      passfail=0;        /* answer pass (0) or fail (1) flag */  
+  N_Vector ref;               /* reference solution vector        */
+  N_Vector ewt;               /* error weight vector              */
+  realtype err;               /* wrms error                       */
+
+  /* create reference solution and error weight vectors */
+  ref = N_VClone(u);
+  ewt = N_VClone(u);
+
+  /* set the reference solution data */
+  NV_Ith_S(ref,0) = RCONST(9.9678538655358029e-01);
+  NV_Ith_S(ref,1) = RCONST(2.9530060962800345e-03);
+  NV_Ith_S(ref,2) = RCONST(2.6160735013975683e-04);
+
+  /* compute the error weight vector */
+  N_VAbs(ref, ewt);
+  N_VScale(rtol, ewt, ewt);
+  N_VAddConst(ewt, atol, ewt);
+  if (N_VMin(ewt) <= ZERO) {
+    fprintf(stderr, "\nSUNDIALS_ERROR: check_ans failed - ewt <= 0\n\n");
+    return(-1);
+  }
+  N_VInv(ewt, ewt);   
+
+  /* compute the solution error */
+  N_VLinearSum(ONE, u, -ONE, ref, ref);
+  err = N_VWrmsNorm(ref, ewt);
+
+  /* is the solution within the tolerances? */
+  passfail = (err < ONE) ? 0 : 1; 
+
+  if (passfail) {
+    fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%g \n\n", err);
+  }
+
+  /* Free vectors */
+  N_VDestroy(ref);
+  N_VDestroy(ewt);
+
+  return(passfail);
+}
diff --git a/examples/kinsol/serial/kinRoboKin_dns.c b/examples/kinsol/serial/kinRoboKin_dns.c
index baaf4bf..32103af 100644
--- a/examples/kinsol/serial/kinRoboKin_dns.c
+++ b/examples/kinsol/serial/kinRoboKin_dns.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * This example solves a nonlinear system from robot kinematics.
@@ -24,11 +20,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_dense.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>             /* access to KINSOL func., consts. */
+#include <nvector/nvector_serial.h>    /* access to serial N_Vector       */
+#include <sunmatrix/sunmatrix_dense.h> /* access to dense SUNMatrix       */
+#include <kinsol/kinsol_direct.h>      /* access to KINDls interface      */
+#include <sunlinsol/sunlinsol_dense.h> /* access to dense SUNLinearSolver */
+#include <sundials/sundials_types.h>   /* defs. of realtype, sunindextype */
+#include <sundials/sundials_math.h>    /* access to SUNRsqrt              */
 
 /* Problem Constants */
 
@@ -43,13 +41,11 @@
 #define TWO   RCONST(2.0)
 
 #define Ith(v,i)    NV_Ith_S(v,i-1)
-#define IJth(A,i,j) DENSE_ELEM(A,i-1,j-1)
+#define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1)
 
 static int func(N_Vector y, N_Vector f, void *user_data);
-static int jac(long int N,
-               N_Vector y, N_Vector f,
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2);
+static int jac(N_Vector y, N_Vector f, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2);
 static void PrintOutput(N_Vector y);
 static void PrintFinalStats(void *kmem);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -66,9 +62,13 @@ int main()
   N_Vector y, scale, constraints;
   int mset, flag, i;
   void *kmem;
+  SUNMatrix J;
+  SUNLinearSolver LS;
 
   y = scale = constraints = NULL;
   kmem = NULL;
+  J = NULL;
+  LS = NULL;
 
   printf("\nRobot Kinematics Example\n");
   printf("8 variables; -1 <= x_i <= 1\n");
@@ -109,13 +109,21 @@ int main()
   flag = KINSetScaledStepTol(kmem, scsteptol);
   if (check_flag(&flag, "KINSetScaledStepTol", 1)) return(1);
 
-  /* Attach dense linear solver */
+  /* Create dense SUNMatrix */
+  J = SUNDenseMatrix(NEQ, NEQ);
+  if(check_flag((void *)J, "SUNDenseMatrix", 0)) return(1);
+
+  /* Create dense SUNLinearSolver object */
+  LS = SUNDenseLinearSolver(y, J);
+  if(check_flag((void *)LS, "SUNDenseLinearSolver", 0)) return(1);
 
-  flag = KINDense(kmem, NEQ);
-  if (check_flag(&flag, "KINDense", 1)) return(1);
+  /* Attach the matrix and linear solver to KINSOL */
+  flag = KINDlsSetLinearSolver(kmem, LS, J);
+  if(check_flag(&flag, "KINDlsSetLinearSolver", 1)) return(1);
 
-  flag = KINDlsSetDenseJacFn(kmem, jac);
-  if (check_flag(&flag, "KINDlsSetDenseJacFn", 1)) return(1);
+  /* Set the Jacobian function */
+  flag = KINDlsSetJacFn(kmem, jac);
+  if (check_flag(&flag, "KINDlsSetJacFn", 1)) return(1);
 
   /* Indicate exact Newton */
 
@@ -152,6 +160,8 @@ int main()
   N_VDestroy_Serial(scale);
   N_VDestroy_Serial(constraints);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(J);
 
   return(0);
 }
@@ -235,10 +245,8 @@ static int func(N_Vector y, N_Vector f, void *user_data)
  * System Jacobian
  */
 
-static int jac(long int N,
-               N_Vector y, N_Vector f,
-               DlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2)
+static int jac(N_Vector y, N_Vector f,SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2)
 {
   int i;
   realtype *yd;
diff --git a/examples/kinsol/serial/kinRoboKin_slu.c b/examples/kinsol/serial/kinRoboKin_slu.c
index 4e3a8b1..1442d69 100644
--- a/examples/kinsol/serial/kinRoboKin_slu.c
+++ b/examples/kinsol/serial/kinRoboKin_slu.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4834 $
- * $Date: 2016-08-01 16:59:05 -0700 (Mon, 01 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol S. Woodward @ LLNL.  Adapted from the file
  *    kinRoboKin_dns.c by Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -25,11 +21,13 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include <kinsol/kinsol.h>
-#include <kinsol/kinsol_superlumt.h>
-#include <nvector/nvector_serial.h>
-#include <sundials/sundials_types.h>
-#include <sundials/sundials_math.h>
+#include <kinsol/kinsol.h>                 /* access to KINSOL func., consts.   */
+#include <nvector/nvector_serial.h>        /* access to serial N_Vector         */
+#include <sunmatrix/sunmatrix_sparse.h>    /* access to sparse SUNMatrix        */
+#include <kinsol/kinsol_direct.h>          /* access to KINDls interface        */
+#include <sunlinsol/sunlinsol_superlumt.h> /* access to SuperLUMT linear solver */
+#include <sundials/sundials_types.h>       /* defs. of realtype, sunindextype   */
+#include <sundials/sundials_math.h>        /* access to SUNRsqrt                */
 
 /* Problem Constants */
 
@@ -46,9 +44,8 @@
 #define Ith(v,i)    NV_Ith_S(v,i-1)
 
 static int func(N_Vector y, N_Vector f, void *user_data);
-static int jac(N_Vector y, N_Vector f,
-               SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2);
+static int jac(N_Vector y, N_Vector f, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2);
 static void PrintOutput(N_Vector y);
 static void PrintFinalStats(void *kmem);
 static int check_flag(void *flagvalue, const char *funcname, int opt);
@@ -65,11 +62,15 @@ int main()
   N_Vector y, scale, constraints;
   int mset, flag, i;
   void *kmem;
+  SUNMatrix J;
+  SUNLinearSolver LS;
 
   int nnz, num_threads;
 
   y = scale = constraints = NULL;
   kmem = NULL;
+  J = NULL;
+  LS = NULL;
 
   printf("\nRobot Kinematics Example\n");
   printf("8 variables; -1 <= x_i <= 1\n");
@@ -109,17 +110,24 @@ int main()
   scsteptol = STOL;
   flag = KINSetScaledStepTol(kmem, scsteptol);
   if (check_flag(&flag, "KINSetScaledStepTol", 1)) return(1);
+  
+  /* Create sparse SUNMatrix */
+  nnz = 56; /* number of nonzeros in the Jacobian */
+  J = SUNSparseMatrix(NEQ, NEQ, nnz, CSC_MAT);
+  if(check_flag((void *)J, "SUNSparseMatrix", 0)) return(1);
+
+  /* Create SuperLUMT solver object */
+  num_threads = 2; /* number fo threads to use */
+  LS = SUNSuperLUMT(y, J, num_threads);
+  if(check_flag((void *)LS, "SUNSuperLUMT", 0)) return(1);
 
-  /* Attach SuperLU_MT linear solver */
-  /* Set the number of nonzeros in the Jacobian */
-  nnz = 56;
-  /* Set the number fo threads to use */
-  num_threads = 2;
-  flag = KINSuperLUMT(kmem, num_threads, NEQ, nnz);
-  if (check_flag(&flag, "KINSuperLUMT", 1)) return(1);
+  /* Attach the SuperLU_MT linear solver */
+  flag = KINDlsSetLinearSolver(kmem, LS, J);
+  if(check_flag(&flag, "KINDlsSetLinearSolver", 1)) return(1);
 
-  flag = KINSlsSetSparseJacFn(kmem, jac);
-  if (check_flag(&flag, "KINSlsSetSparseJacFn", 1)) return(1);
+  /* Set the Jacobian function */
+  flag = KINDlsSetJacFn(kmem, jac);
+  if (check_flag(&flag, "KINDlsSetJacFn", 1)) return(1);
 
   /* Indicate exact Newton */
 
@@ -156,6 +164,8 @@ int main()
   N_VDestroy_Serial(scale);
   N_VDestroy_Serial(constraints);
   KINFree(&kmem);
+  SUNLinSolFree(LS);
+  SUNMatDestroy(J);
 
   return(0);
 }
@@ -239,15 +249,14 @@ static int func(N_Vector y, N_Vector f, void *user_data)
  * System Jacobian
  */
 
-static int jac(N_Vector y, N_Vector f,
-               SlsMat J, void *user_data,
-               N_Vector tmp1, N_Vector tmp2)
+static int jac(N_Vector y, N_Vector f, SUNMatrix J,
+               void *user_data, N_Vector tmp1, N_Vector tmp2)
 {
   realtype *yd;
   realtype x1, x2, x3, x4, x5, x6, x7, x8;
-  int *colptrs = *J->colptrs;
-  int *rowvals = *J->rowvals;
-  realtype *data = J->data;
+  sunindextype *colptrs = SUNSparseMatrix_IndexPointers(J);
+  sunindextype *rowvals = SUNSparseMatrix_IndexValues(J);
+  realtype *data = SUNSparseMatrix_Data(J);
 
   yd = N_VGetArrayPointer_Serial(y);
 
@@ -260,7 +269,7 @@ static int jac(N_Vector y, N_Vector f,
   x7 = yd[6];
   x8 = yd[7];
 
-  SparseSetMatToZero(J);
+  SUNMatZero(J);
   
   colptrs[0] = 0;
   colptrs[1] = 7;
@@ -302,15 +311,15 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,1,7) = 1.0;
   */
 
-  J->data[0] = - 0.1238 + 0.004731*x3;
+  data[0] = - 0.1238 + 0.004731*x3;
   rowvals[0] = 0;
-  J->data[7] = - 0.001637 - 0.3578*x3;
+  data[7] = - 0.001637 - 0.3578*x3;
   rowvals[7] = 0;
-  J->data[14] = 0.004731*x1 - 0.3578*x2;
+  data[14] = 0.004731*x1 - 0.3578*x2;
   rowvals[14] = 0;
-  J->data[19] = - 0.9338;
+  data[19] = - 0.9338;
   rowvals[19] = 0;
-  J->data[31] = 1.0;
+  data[31] = 1.0;
   rowvals[31] = 0;
 
   /*
@@ -325,15 +334,15 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,2,7) = -1.0;
   */
 
-  J->data[1] = 0.2638 + 0.2238*x3;
+  data[1] = 0.2638 + 0.2238*x3;
   rowvals[1] = 1;
-  J->data[8] = - 0.07745 + 0.7623*x3;
+  data[8] = - 0.07745 + 0.7623*x3;
   rowvals[8] = 1;
-  J->data[15] = 0.2238*x1 + 0.7623*x2;
+  data[15] = 0.2238*x1 + 0.7623*x2;
   rowvals[15] = 1;
-  J->data[20] = - 0.6734;
+  data[20] = - 0.6734;
   rowvals[20] = 1;
-  J->data[32] = -1.0;
+  data[32] = -1.0;
   rowvals[32] = 1;
 
 
@@ -347,13 +356,13 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,3,8) = x6;
   */
 
-  J->data[2] = 0.3578;
+  data[2] = 0.3578;
   rowvals[2] = 2;
-  J->data[9] = 0.004731;
+  data[9] = 0.004731;
   rowvals[9] = 2;
-  J->data[27] = x8;
+  data[27] = x8;
   rowvals[27] = 2;
-  J->data[36] = x6;
+  data[36] = x6;
   rowvals[36] = 2;
 
 
@@ -365,9 +374,9 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,4,2) = 0.2238;
   */
 
-  J->data[3] = - 0.7623;
+  data[3] = - 0.7623;
   rowvals[3] = 3;
-  J->data[10] = 0.2238;
+  data[10] = 0.2238;
   rowvals[10] = 3;
 
   /*
@@ -378,9 +387,9 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,5,2) = 2.0*x2;
   */
 
-  J->data[4] = 2.0*x1;
+  data[4] = 2.0*x1;
   rowvals[4] = 4;
-  J->data[11] = 2.0*x2;
+  data[11] = 2.0*x2;
   rowvals[11] = 4;
 
   /*
@@ -391,9 +400,9 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,6,4) = 2.0*x4;
   */
 
-  J->data[16] = 2.0*x3;
+  data[16] = 2.0*x3;
   rowvals[16] = 5;
-  J->data[21] = 2.0*x4;
+  data[21] = 2.0*x4;
   rowvals[21] = 5;
 
   /*
@@ -404,9 +413,9 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,7,6) = 2.0*x6;
   */
 
-  J->data[24] = 2.0*x5;
+  data[24] = 2.0*x5;
   rowvals[24] = 6;
-  J->data[28] = 2.0*x6;
+  data[28] = 2.0*x6;
   rowvals[28] = 6;
 
   /*
@@ -416,9 +425,9 @@ static int jac(N_Vector y, N_Vector f,
   IJth(J,8,7) = 2.0*x7;
   IJth(J,8,8) = 2.0*x8;
   */
-  J->data[33] = 2.0*x7;
+  data[33] = 2.0*x7;
   rowvals[33] = 7;
-  J->data[37] = 2.0*x8;
+  data[37] = 2.0*x8;
   rowvals[37] = 7;
 
   
@@ -435,38 +444,38 @@ static int jac(N_Vector y, N_Vector f,
   } 
   */
 
-  J->data[5] = -1.0;
+  data[5] = -1.0;
   rowvals[5] = 8;
-  J->data[12] = -1.0;
+  data[12] = -1.0;
   rowvals[12] = 9;
-  J->data[17] = -1.0;
+  data[17] = -1.0;
   rowvals[17] = 10;
-  J->data[22] = -1.0;
+  data[22] = -1.0;
   rowvals[22] = 11;
-  J->data[25] = -1.0;
+  data[25] = -1.0;
   rowvals[25] = 12;
-  J->data[29] = -1.0;
+  data[29] = -1.0;
   rowvals[29] = 13;
-  J->data[34] = -1.0;
+  data[34] = -1.0;
   rowvals[34] = 14;
-  J->data[38] = -1.0;
+  data[38] = -1.0;
   rowvals[38] = 15;
 
-  J->data[40] = 1.0;
+  data[40] = 1.0;
   rowvals[40] = 8;
-  J->data[41] = 1.0;
+  data[41] = 1.0;
   rowvals[41] = 9;
-  J->data[42] = 1.0;
+  data[42] = 1.0;
   rowvals[42] = 10;
-  J->data[43] = 1.0;
+  data[43] = 1.0;
   rowvals[43] = 11;
-  J->data[44] = 1.0;
+  data[44] = 1.0;
   rowvals[44] = 12;
-  J->data[45] = 1.0;
+  data[45] = 1.0;
   rowvals[45] = 13;
-  J->data[46] = 1.0;
+  data[46] = 1.0;
   rowvals[46] = 14;
-  J->data[47] = 1.0;
+  data[47] = 1.0;
   rowvals[47] = 15;
 
 
@@ -481,38 +490,38 @@ static int jac(N_Vector y, N_Vector f,
   }
   */
 
-  J->data[6] = 1.0;
+  data[6] = 1.0;
   rowvals[6] = 16;
-  J->data[13] = 1.0;
+  data[13] = 1.0;
   rowvals[13] = 17;
-  J->data[18] = 1.0;
+  data[18] = 1.0;
   rowvals[18] = 18;
-  J->data[23] = 1.0;
+  data[23] = 1.0;
   rowvals[23] = 19;
-  J->data[26] = 1.0;
+  data[26] = 1.0;
   rowvals[26] = 20;
-  J->data[30] = 1.0;
+  data[30] = 1.0;
   rowvals[30] = 21;
-  J->data[35] = 1.0;
+  data[35] = 1.0;
   rowvals[35] = 22;
-  J->data[39] = 1.0;
+  data[39] = 1.0;
   rowvals[39] = 23;
 
-  J->data[48] = 1.0;
+  data[48] = 1.0;
   rowvals[48] = 16;
-  J->data[49] = 1.0;
+  data[49] = 1.0;
   rowvals[49] = 17;
-  J->data[50] = 1.0;
+  data[50] = 1.0;
   rowvals[50] = 18;
-  J->data[51] = 1.0;
+  data[51] = 1.0;
   rowvals[51] = 19;
-  J->data[52] = 1.0;
+  data[52] = 1.0;
   rowvals[52] = 20;
-  J->data[53] = 1.0;
+  data[53] = 1.0;
   rowvals[53] = 21;
-  J->data[54] = 1.0;
+  data[54] = 1.0;
   rowvals[54] = 22;
-  J->data[55] = 1.0;
+  data[55] = 1.0;
   rowvals[55] = 23;
 
   return(0);
@@ -561,8 +570,8 @@ static void PrintFinalStats(void *kmem)
   flag = KINGetNumFuncEvals(kmem, &nfe);
   check_flag(&flag, "KINGetNumFuncEvals", 1);
 
-  flag = KINSlsGetNumJacEvals(kmem, &nje);
-  check_flag(&flag, "KINSlsGetNumJacEvals", 1);
+  flag = KINDlsGetNumJacEvals(kmem, &nje);
+  check_flag(&flag, "KINDlsGetNumJacEvals", 1);
 
   printf("\nFinal Statistics.. \n");
   printf("nni    = %5ld    nfe   = %5ld \n", nni, nfe);
diff --git a/examples/nvector/C_openmp/CMakeLists.txt b/examples/nvector/C_openmp/CMakeLists.txt
index 9fca937..3799f88 100644
--- a/examples/nvector/C_openmp/CMakeLists.txt
+++ b/examples/nvector/C_openmp/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4945 $
-# $Date: 2016-09-21 22:15:14 -0700 (Wed, 21 Sep 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -14,33 +11,40 @@
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for nvector examples
+# CMakeLists.txt file for OpenMP nvector examples
+# ---------------------------------------------------------------
 
-# Add variable nvector_openmp_examples with the names of the nvector examples
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS OpenMP nvector
 SET(nvector_openmp_examples
-  test_nvector_openmp
-)
-
+  "test_nvector_openmp\;1000 1 0\;"
+  "test_nvector_openmp\;1000 2 0\;"
+  "test_nvector_openmp\;1000 4 0\;"
+  "test_nvector_openmp\;10000 1 0\;"
+  "test_nvector_openmp\;10000 2 0\;"
+  "test_nvector_openmp\;10000 4 0\;"
+  )
+
+# Dependencies for nvector examples
 SET(nvector_examples_dependencies
   test_nvector
   sundials_nvector
-)
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(. ..)
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(NVECS_LIB sundials_nvecopenmp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(NVECS_LIB sundials_nvecopenmp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS})
 
 IF(OPENMP_FOUND)
@@ -50,26 +54,53 @@ IF(OPENMP_FOUND)
   SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}")
 ENDIF(OPENMP_FOUND)
 
-# Add the build and install targets for each nvector example
-
-FOREACH(example ${nvector_openmp_examples})
-  ADD_EXECUTABLE(${example} ${example}.c ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
-  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-
-  SUNDIALS_ADD_TEST(${example}_1000_1_0 ${example} TEST_ARGS 1000 1 0)
-  SUNDIALS_ADD_TEST(${example}_1000_2_0 ${example} TEST_ARGS 1000 2 0)
-  SUNDIALS_ADD_TEST(${example}_1000_4_0 ${example} TEST_ARGS 1000 4 0)
 
-  SUNDIALS_ADD_TEST(${example}_10000_1_0 ${example} TEST_ARGS 10000 1 0)
-  SUNDIALS_ADD_TEST(${example}_10000_2_0 ${example} TEST_ARGS 10000 2 0)
-  SUNDIALS_ADD_TEST(${example}_10000_4_0 ${example} TEST_ARGS 10000 4 0)
+# Add the build and install targets for each example
+FOREACH(example_tuple ${nvector_openmp_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+    
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/C_openmp)
+  ENDIF()
 
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ENDFOREACH(example_tuple ${nvector_openmp_examples})
 
-  IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ../test_nvector.c ../test_nvector.h ../../../src/sundials/sundials_nvector.c DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/C_openmp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${nvector_openmp_examples})
 
 IF(EXAMPLES_INSTALL)
 
@@ -78,8 +109,9 @@ IF(EXAMPLES_INSTALL)
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER_LIB "sundials_nvecopenmp")
-  LIST2STRING(nvector_openmp_examples EXAMPLES)
-  LIST2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  EXAMPLES2STRING(nvector_openmp_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -87,10 +119,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/nvector/C_openmp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_openmp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/C_openmp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/nvector/C_openmp/test_nvector_openmp.c b/examples/nvector/C_openmp/test_nvector_openmp.c
index 5319bcb..aafeaf7 100644
--- a/examples/nvector/C_openmp/test_nvector_openmp.c
+++ b/examples/nvector/C_openmp/test_nvector_openmp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4790 $
- * $Date: 2016-06-29 14:47:05 -0700 (Wed, 29 Jun 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -15,10 +11,9 @@
  * For details, see the LICENSE file.
  * LLNS Copyright End
  * -----------------------------------------------------------------
- * This is the testing routine to check the open MP NVECTOR module
+ * This is the testing routine to check the OpenMP NVECTOR module
  * implementation. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,11 +29,11 @@
  * --------------------------------------------------------------------*/
 int main(int argc, char *argv[]) 
 {
-  int      fails = 0;            /* counter for test failures */
-  long int veclen;               /* vector length             */
-  N_Vector W, X, Y, Z;           /* test vectors              */
-  int      num_threads;
-  int      print_timing;
+  int          fails = 0;     /* counter for test failures */
+  sunindextype veclen;        /* vector length             */
+  N_Vector     W, X, Y, Z;    /* test vectors              */
+  int          num_threads;
+  int          print_timing;
 
   /* check input and set vector length */
   if (argc < 4){
@@ -61,7 +56,7 @@ int main(int argc, char *argv[])
   print_timing = atoi(argv[3]);
   SetTiming(print_timing);
 
-  printf("\nRunning with vector length %ld \n \n", veclen);
+  printf("\nRunning with vector length %ld \n \n", (long int) veclen);
   printf("\nRunning with number of threads %d \n \n", num_threads);
 
   /* Create vectors */
@@ -114,16 +109,16 @@ int main(int argc, char *argv[])
     printf("SUCCESS: NVector module passed all tests \n \n");
   }
 
-  return(0);
+  return(fails);
 }
 
 /* ----------------------------------------------------------------------
  * Check vector
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int      failure = 0;
-  long int i;
+  sunindextype i;
   realtype *Xdata;
   
   Xdata = N_VGetArrayPointer(X);
@@ -143,17 +138,17 @@ booleantype has_data(N_Vector X)
 {
   realtype *Xdata = N_VGetArrayPointer(X);
   if (Xdata == NULL)
-    return FALSE;
+    return SUNFALSE;
   else
-    return TRUE;
+    return SUNTRUE;
 }
 
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
   NV_Ith_OMP(X,i) = val;
 }
  
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
   return NV_Ith_OMP(X,i);
 }
diff --git a/examples/nvector/cuda/CMakeLists.txt b/examples/nvector/cuda/CMakeLists.txt
new file mode 100644
index 0000000..c101766
--- /dev/null
+++ b/examples/nvector/cuda/CMakeLists.txt
@@ -0,0 +1,151 @@
+# ---------------------------------------------------------------
+# Programmer:  Slaven Peles @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for cuda nvector examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS cuda nvector
+SET(nvector_cuda_examples
+  "test_nvector_cuda\;10000 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(nvector_examples_dependencies
+  test_nvector
+  sundials_nvector
+  sundials_math
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. .. ${CUDA_TOOLKIT_ROOT_DIR}/samples/common/inc)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVECS_LIB sundials_nveccuda_static)
+ELSE()
+  SET(NVECS_LIB sundials_nveccuda_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${nvector_cuda_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    CUDA_ADD_EXECUTABLE(${example} ${example}.cu
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c
+      ../../../src/sundials/sundials_math.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${CUDA_LIBRARIES})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.cu
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      ../../../src/sundials/sundials_math.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/cuda)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${nvector_cuda_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/cuda)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_nveccuda")
+
+  EXAMPLES2STRING(nvector_cuda_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_cuda_CUDA_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/cuda/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/nvector/cuda/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/cuda
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_cuda_CUDA_ex.in
+      ${PROJECT_BINARY_DIR}/examples/nvector/cuda/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/nvector/cuda/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/cuda
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/nvector/serial/test_nvector_serial.c b/examples/nvector/cuda/test_nvector_cuda.cu
similarity index 58%
copy from examples/nvector/serial/test_nvector_serial.c
copy to examples/nvector/cuda/test_nvector_cuda.cu
index a2e1979..4d990cb 100644
--- a/examples/nvector/serial/test_nvector_serial.c
+++ b/examples/nvector/cuda/test_nvector_cuda.cu
@@ -1,9 +1,5 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4790 $
- * $Date: 2016-06-29 14:47:05 -0700 (Wed, 29 Jun 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): David J. Gardner @ LLNL
+/* ----------------------------------------------------------------- 
+ * Programmer(s): Slaven Peles @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -15,34 +11,35 @@
  * For details, see the LICENSE file.
  * LLNS Copyright End
  * -----------------------------------------------------------------
- * This is the testing routine to check the NVECTOR Serial module 
+ * This is the testing routine to check the NVECTOR CUDA module 
  * implementation. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <sundials/sundials_types.h>
-#include <nvector/nvector_serial.h>
+#include <nvector/nvector_cuda.h>
 #include <sundials/sundials_math.h>
 #include "test_nvector.h"
 
+#include <nvector/cuda/Vector.hpp>
 
 /* ----------------------------------------------------------------------
  * Main NVector Testing Routine
  * --------------------------------------------------------------------*/
 int main(int argc, char *argv[]) 
 {
-  int      fails = 0;  /* counter for test failures  */
-  long int veclen;     /* vector length              */
-  N_Vector W, X, Y, Z; /* test vectors               */
-  int      print_timing;
+  int          fails = 0;     /* counter for test failures  */
+  sunindextype veclen;        /* vector length              */
+  N_Vector     W, X, Y, Z;    /* test vectors               */
+  int          print_timing;
+  /* sunindextype lrw, liw; */
 
 
   /* check input and set vector length */
   if (argc < 3){
-    printf("ERROR: ONE (1) Input required: vector length, print timing \n");
+    printf("ERROR: TWO (2) Inputs required: vector length, print timing \n");
     return(-1);
   }
 
@@ -56,23 +53,32 @@ int main(int argc, char *argv[])
   SetTiming(print_timing);
 
 
-  printf("\nRunning with vector length %ld \n \n", veclen);
+  printf("\nRunning with vector length %ld \n\n", (long) veclen);
 
   /* Create vectors */
-  W = N_VNewEmpty_Serial(veclen);
-  X = N_VNew_Serial(veclen);
-  Y = N_VNew_Serial(veclen);
-  Z = N_VNew_Serial(veclen);
+  W = N_VNewEmpty_Cuda(veclen);
+  X = N_VNew_Cuda(veclen);
 
-  if(N_VGetVectorID(W) == SUNDIALS_NVEC_SERIAL) {
-    /*printf("Testing serial variant of N_Vector...\n");*/
-  }
-  
   /* NVector Tests */
-  fails += Test_N_VSetArrayPointer(W, veclen, 0);
-  fails += Test_N_VGetArrayPointer(X, veclen, 0);
-  fails += Test_N_VLinearSum(X, Y, Z, veclen, 0);
+  
+  /* CUDA specific tests */
+  
+  /* Memory allocation tests */
+  fails += Test_N_VCloneEmpty(X, 0);
+  fails += Test_N_VClone(X, veclen, 0);
+  fails += Test_N_VCloneEmptyVectorArray(5, X, 0);
+  fails += Test_N_VCloneVectorArray(5, X, veclen, 0);
+
+  Y = N_VClone_Cuda(X);
+  Z = N_VClone_Cuda(X);
+
+  /* Skipped tests */
+  /*   fails += Test_N_VSetArrayPointer(W, veclen, 0); */
+  /*   fails += Test_N_VGetArrayPointer(X, veclen, 0); */
+  
+  /* Vector operation tests */
   fails += Test_N_VConst(X, veclen, 0);
+  fails += Test_N_VLinearSum(X, Y, Z, veclen, 0);
   fails += Test_N_VProd(X, Y, Z, veclen, 0);
   fails += Test_N_VDiv(X, Y, Z, veclen, 0);
   fails += Test_N_VScale(X, Z, veclen, 0);
@@ -90,16 +96,15 @@ int main(int argc, char *argv[])
   fails += Test_N_VInvTest(X, Z, veclen, 0);
   fails += Test_N_VConstrMask(X, Y, Z, veclen, 0);
   fails += Test_N_VMinQuotient(X, Y, veclen, 0);
-  fails += Test_N_VCloneVectorArray(5, X, veclen, 0);
-  fails += Test_N_VCloneEmptyVectorArray(5, X, 0);
-  fails += Test_N_VCloneEmpty(X, 0);
-  fails += Test_N_VClone(X, veclen, 0);
 
+  /*   N_VSpace_Cuda(X, &lrw, &liw);               */
+  /*   printf("lrw = %ld, liw = %ld\n", lrw, liw); */
+  
   /* Free vectors */
-  N_VDestroy_Serial(W);
-  N_VDestroy_Serial(X);
-  N_VDestroy_Serial(Y);
-  N_VDestroy_Serial(Z);
+  N_VDestroy_Cuda(W);
+  N_VDestroy_Cuda(X);
+  N_VDestroy_Cuda(Y);
+  N_VDestroy_Cuda(Z);
 
   /* Print result */
   if (fails) {
@@ -108,46 +113,47 @@ int main(int argc, char *argv[])
     printf("SUCCESS: NVector module passed all tests \n \n");
   }
 
-  return(0);
+  return(fails);
 }
 
 /* ----------------------------------------------------------------------
  * Check vector
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int      failure = 0;
-  long int i;
-  realtype *Xdata;
+  sunindextype i;
+  suncudavec::Vector<realtype, sunindextype>* xv = suncudavec::extract<realtype, sunindextype>(X);
+  realtype *xdata;
   
-  Xdata = N_VGetArrayPointer(X);
-
+  xv->copyFromDev();
+  
+  xdata = xv->host();
   /* check vector data */
   for(i=0; i < local_length; i++){
-    failure += FNEQ(Xdata[i], ans);
+    failure += FNEQ(xdata[i], ans);
   }
-
-  if (failure > ZERO)
-    return(1);
-  else
-    return(0);
+  return (failure > ZERO) ? (1) : (0);
 }
 
 booleantype has_data(N_Vector X)
 {
-  realtype *Xdata = N_VGetArrayPointer(X);
-  if (Xdata == NULL)
-    return FALSE;
-  else
-    return TRUE;
+  suncudavec::Vector<realtype, sunindextype>* xv = suncudavec::extract<realtype, sunindextype>(X);
+
+  return (xv == NULL ? SUNFALSE : SUNTRUE);
 }
 
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
-  NV_Ith_S(X,i) = val;    
+  suncudavec::Vector<realtype, sunindextype>* xv = suncudavec::extract<realtype, sunindextype>(X);
+  xv->copyFromDev();
+  (xv->host())[i] = val;
+  xv->copyToDev();
 }
 
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
-  return NV_Ith_S(X,i);    
+  suncudavec::Vector<realtype, sunindextype>* xv = suncudavec::extract<realtype, sunindextype>(X);
+  xv->copyFromDev();
+  return (xv->host())[i];
 }
diff --git a/examples/nvector/parallel/CMakeLists.txt b/examples/nvector/parallel/CMakeLists.txt
index 4f37514..c37b8a2 100644
--- a/examples/nvector/parallel/CMakeLists.txt
+++ b/examples/nvector/parallel/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -14,33 +11,38 @@
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for nvector examples
+# CMakeLists.txt file for MPI nvector examples
+# ---------------------------------------------------------------
 
-# Add variable nvector_parallel_examples with the names of the nvector examples
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS MPI nvector
 SET(nvector_parallel_examples
-  test_nvector_mpi
-)
+  "test_nvector_mpi\;\;\;\;"          # run sequentially
+  "test_nvector_mpi\;1000 0\;\;\;"    # run sequentially with arguments
+  "test_nvector_mpi\;\;1\;4\;"        # run parallel on 4 procs
+  "test_nvector_mpi\;1000 0\;1\;4\;"  # run parallel on 4 procs with arguments
+  )
 
+# Dependencies for nvector examples
 SET(nvector_examples_dependencies
   test_nvector
   sundials_nvector
-)
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(. ..)
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(NVECS_LIB sundials_nvecparallel_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(NVECS_LIB sundials_nvecparallel_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS})
 
 IF(MPI_MPICC)
@@ -49,38 +51,70 @@ IF(MPI_MPICC)
 ELSE(MPI_MPICC)
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-  TARGET_LINK_LIBRARIES(${example} MPI_LIBRARIES)
 ENDIF(MPI_MPICC)
 
-# Add the build and install targets for each nvector example
-
-FOREACH(example ${nvector_parallel_examples})
-
-  ADD_EXECUTABLE(${example} ${example}.c ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
-  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-
-  # Run sequentially
-  SUNDIALS_ADD_TEST("${example}" ${example})
 
-  # Run sequentially with arguments
-  SUNDIALS_ADD_TEST("${example}_1000_0" ${example} TEST_ARGS 1000 0)
-
-  # Run in parallel on 4 procs
-  SUNDIALS_ADD_TEST("${example}_4" ${example} MPI_NPROCS 4)
-  
-  # Parallel with additional arguments and supplying an answer file
-  SUNDIALS_ADD_TEST("${example}_4_1000_0" ${example} MPI_NPROCS 4 TEST_ARGS 1000 0 ANSWER_FILE ${example})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${nvector_parallel_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    IF("${number_of_tasks}" STREQUAL "")
+      SET(test_name ${example})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${number_of_tasks})
+    ENDIF()
+  ELSE()
+    IF("${number_of_tasks}" STREQUAL "")
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${number_of_tasks}_${example_args})
+    ENDIF()
+  ENDIF()  
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/parallel)
+  ENDIF()
 
-  # Specify floating point precision and integer percentage for comparison
-  SUNDIALS_ADD_TEST("${example}_precision" ${example} MPI_NPROCS 4 TEST_ARGS 1000 0 ANSWER_FILE ${example}
-    FLOAT_PRECISION 5 INTEGER_PERCENTAGE 0)
-  
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ENDFOREACH(example_tuple ${nvector_parallel_examples})
 
-  IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ../test_nvector.c ../test_nvector.h ../../../src/sundials/sundials_nvector.c DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/parallel)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${nvector_parallel_examples})
 
 IF(EXAMPLES_INSTALL)
 
@@ -89,8 +123,9 @@ IF(EXAMPLES_INSTALL)
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER_LIB "sundials_nvecparallel")
-  LIST2STRING(nvector_parallel_examples EXAMPLES)
-  LIST2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  EXAMPLES2STRING(nvector_parallel_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -98,10 +133,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/nvector/parallel/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/parallel/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/nvector/parallel/test_nvector_mpi.c b/examples/nvector/parallel/test_nvector_mpi.c
index c6535f2..a17e20d 100644
--- a/examples/nvector/parallel/test_nvector_mpi.c
+++ b/examples/nvector/parallel/test_nvector_mpi.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4790 $
- * $Date: 2016-06-29 14:47:05 -0700 (Wed, 29 Jun 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -17,8 +13,7 @@
  * -----------------------------------------------------------------
  * This is the testing routine to check the NVECTOR Parallel module 
  * implementation. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -39,11 +34,13 @@
  * --------------------------------------------------------------------*/
 int main(int argc, char *argv[]) 
 {
-  int      fails = 0;                   /* counter for test failures */
-  long int local_length, global_length; /* vector lengths            */
-  N_Vector W, X, Y, Z;                  /* test vectors              */
-  MPI_Comm comm;                        /* MPI Communicator          */
-  int      nprocs, myid;                /* Number of procs, proc id  */
+  int          fails = 0;                   /* counter for test failures */
+  int          globfails = 0;               /* counter for test failures */
+  sunindextype local_length, global_length; /* vector lengths            */
+  N_Vector     W, X, Y, Z;                  /* test vectors              */
+  MPI_Comm     comm;                        /* MPI Communicator          */
+  int          nprocs, myid;                /* Number of procs, proc id  */
+  int          mpierr;                      /* mpi error flag            */
 
   /* Get processor number and total number of processes */
   MPI_Init(&argc, &argv);
@@ -106,18 +103,22 @@ int main(int argc, char *argv[])
 	printf("SUCCESS: NVector module passed all tests, Proc %d \n \n",myid);
      }
   }
+
+  /* check if any other process failed */
+  mpierr = MPI_Allreduce(&fails, &globfails, 1, MPI_INT, MPI_MAX, comm);
   
   MPI_Finalize();
-  return(0);
+
+  return(globfails);
 }
 
 /* ----------------------------------------------------------------------
  * Check vector
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int      failure = 0;
-  long int i;
+  sunindextype i;
   realtype *Xdata;
   
   Xdata = N_VGetArrayPointer(X);
@@ -137,17 +138,17 @@ booleantype has_data(N_Vector X)
 {
   realtype *Xdata = N_VGetArrayPointer(X);
   if (Xdata == NULL)
-    return FALSE;
+    return SUNFALSE;
   else
-    return TRUE;
+    return SUNTRUE;
 }
 
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
   NV_Ith_P(X,i) = val;    
 }
 
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
   return NV_Ith_P(X,i);    
 }
diff --git a/examples/nvector/parhyp/CMakeLists.txt b/examples/nvector/parhyp/CMakeLists.txt
index ad687bb..ce505a0 100644
--- a/examples/nvector/parhyp/CMakeLists.txt
+++ b/examples/nvector/parhyp/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -14,18 +11,25 @@
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for nvector examples
+# CMakeLists.txt file for hypre nvector examples
+# ---------------------------------------------------------------
 
-# Add variable nvector_parhyp_examples with the names of the nvector examples
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS parallel hypre nvector
 SET(nvector_parhyp_examples
-  test_nvector_parhyp
-)
+  "test_nvector_parhyp\;\;\;\;"          # run sequentially
+  "test_nvector_parhyp\;1000 0\;\;\;"    # run sequentially with arguments
+  "test_nvector_parhyp\;\;1\;4\;"        # run parallel on 4 procs
+  "test_nvector_parhyp\;10000 0\;1\;4\;" # run parallel on 4 procs with arguments
+  )
 
+# Dependencies for nvector examples
 SET(nvector_examples_dependencies
   test_nvector
   sundials_nvector
-)
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(. ..)
@@ -35,16 +39,16 @@ INCLUDE_DIRECTORIES(${HYPRE_LIB_DIR})
   
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(NVECS_LIB sundials_nvecparhyp_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(NVECS_LIB sundials_nvecparhyp_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
 SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS})
-SET(HYPRE_LIBS ${HYPRE_LIBRARIES})
+
+LIST(APPEND SUNDIALS_LIBS ${HYPRE_LIBRARIES})
 
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
@@ -52,40 +56,70 @@ IF(MPI_MPICC)
 ELSE(MPI_MPICC)
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-  TARGET_LINK_LIBRARIES(${example} MPI_LIBRARIES)
 ENDIF(MPI_MPICC)
 
-# Add the build and install targets for each nvector example
-
-FOREACH(example ${nvector_parhyp_examples})
 
-  ADD_EXECUTABLE(${example} ${example}.c ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
-  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-
-  # Run sequentially
-  SUNDIALS_ADD_TEST("${example}" ${example})
-
-  # Run sequentially with arguments
-  SUNDIALS_ADD_TEST("${example}_10000_0" ${example} TEST_ARGS 10000 0)
-
-  # Run in parhyp on 4 procs
-  SUNDIALS_ADD_TEST("${example}_4" ${example} MPI_NPROCS 4)
-  
-  # parhyp with additional arguments and supplying an answer file
-  SUNDIALS_ADD_TEST("${example}_4_10000_0" ${example} MPI_NPROCS 4 TEST_ARGS 10000 0 ANSWER_FILE ${example})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${nvector_parhyp_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    IF("${number_of_tasks}" STREQUAL "")
+      SET(test_name ${example})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${number_of_tasks})
+    ENDIF()
+  ELSE()
+    IF("${number_of_tasks}" STREQUAL "")
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${number_of_tasks}_${example_args})
+    ENDIF()
+  ENDIF()  
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF) 
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/parhyp)
+  ENDIF()
 
-  # Specify floating point precision and integer percentage for comparison
-  SUNDIALS_ADD_TEST("${example}_precision" ${example} MPI_NPROCS 4 TEST_ARGS 10000 0 ANSWER_FILE ${example}
-    FLOAT_PRECISION 5 INTEGER_PERCENTAGE 0)
+ENDFOREACH(example_tuple ${nvector_parhyp_examples})
 
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-  
-  TARGET_LINK_LIBRARIES(${example} ${HYPRE_LIBRARIES})
-  
-  IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ../test_nvector.c ../test_nvector.h ../../../src/sundials/sundials_nvector.c DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/parhyp)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${nvector_parhyp_examples})
 
 IF(EXAMPLES_INSTALL)
 
@@ -94,8 +128,9 @@ IF(EXAMPLES_INSTALL)
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER_LIB "sundials_nvecparhyp")
-  LIST2STRING(nvector_parhyp_examples EXAMPLES)
-  LIST2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  EXAMPLES2STRING(nvector_parhyp_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -103,10 +138,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parhyp_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/nvector/parhyp/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parhyp_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/parhyp/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/nvector/parhyp/test_nvector_parhyp.c b/examples/nvector/parhyp/test_nvector_parhyp.c
index adf9ee3..781eb2b 100644
--- a/examples/nvector/parhyp/test_nvector_parhyp.c
+++ b/examples/nvector/parhyp/test_nvector_parhyp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4137 $
- * $Date: 2014-06-15 12:26:15 -0700 (Sun, 15 Jun 2014) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Slaven Peles @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -17,8 +13,7 @@
  * -----------------------------------------------------------------
  * This is the testing routine to check the NVECTOR Parallel module 
  * implementation. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -29,7 +24,6 @@
 #include "test_nvector.h"
 
 #include <mpi.h>
-#include <omp.h>
 
 #if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
 #include <time.h>
@@ -48,16 +42,17 @@ static int Test_N_VGetVectorID(N_Vector W, int myid);
  * --------------------------------------------------------------------*/
 int main(int argc, char *argv[]) 
 {
-  int      fails = 0;                   /* counter for test failures */
-  long int local_length, global_length; /* vector lengths            */
-  N_Vector W;
-  N_Vector X, Y, Z;                     /* test vectors              */
-  MPI_Comm comm;                        /* MPI Communicator          */
-  int      nprocs, myid;                /* Number of procs, proc id  */
-  long int veclen;                      /* vector length             */
-  int      print_timing;
-  HYPRE_Int *partitioning;      /* Vector Partitioning */
-  HYPRE_ParVector Xhyp;         /* Instantiate hypre parallel vector */
+  int              fails = 0;                   /* counter for test failures */
+  int              globfails = 0;               /* counter for test failures */
+  sunindextype     local_length, global_length; /* vector lengths            */
+  N_Vector         W, X, Y, Z;                  /* test vectors              */
+  MPI_Comm         comm;                        /* MPI Communicator          */
+  int              nprocs, myid;                /* Number of procs, proc id  */
+  sunindextype     veclen;                      /* vector length             */
+  int              print_timing;
+  HYPRE_Int       *partitioning;                /* Vector Partitioning       */
+  HYPRE_ParVector  Xhyp;                        /* Instantiate hypre parallel vector */
+  int              mpierr;                      /* mpi error flag            */
 
   /* check input and set vector length */
   if (argc < 3) {
@@ -80,7 +75,7 @@ int main(int argc, char *argv[])
   /* printf("\nRunning with vector length %ld \n \n", veclen); */
   /* Get processor number and total number of processes */
   MPI_Init(&argc, &argv);
-  /* omp_set_num_threads(4); */
+
   comm = MPI_COMM_WORLD;
   MPI_Comm_size(comm, &nprocs);
   MPI_Comm_rank(comm, &myid);
@@ -167,11 +162,15 @@ int main(int argc, char *argv[])
      }
   }
 
+  /* check if any other process failed */
+  mpierr = MPI_Allreduce(&fails, &globfails, 1, MPI_INT, MPI_MAX, comm);
+
   /* Free hypre template vector */
   HYPRE_ParVectorDestroy(Xhyp);
   
   MPI_Finalize();
-  return(0);
+
+  return(globfails);
 }
 
 /* ----------------------------------------------------------------------
@@ -179,10 +178,10 @@ int main(int argc, char *argv[])
  * 
  * Checks if all elements of vector X are set to value ans. 
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int      failure = 0;
-  long int i;
+  sunindextype i;
   hypre_ParVector *Xvec = N_VGetVector_ParHyp(X);
   realtype *Xdata = Xvec == NULL ? NULL : hypre_VectorData(hypre_ParVectorLocalVector(Xvec));
   
@@ -208,9 +207,9 @@ booleantype has_data(N_Vector X)
   hypre_ParVector *Xvec = N_VGetVector_ParHyp(X);
   realtype *Xdata = Xvec == NULL ? NULL : hypre_VectorData(hypre_ParVectorLocalVector(Xvec));
   if (Xdata == NULL)
-    return FALSE;
+    return SUNFALSE;
   else
-    return TRUE;
+    return SUNTRUE;
 }
 
 
@@ -220,7 +219,7 @@ booleantype has_data(N_Vector X)
  * Sets single element in hypre vector by accessing its raw block. 
  * Probably not the most efficient way to set the entire vector.
  * --------------------------------------------------------------------*/
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
   hypre_ParVector *Xvec = N_VGetVector_ParHyp(X);
   realtype *Xdata = hypre_VectorData(hypre_ParVectorLocalVector(Xvec));
@@ -233,7 +232,7 @@ void set_element(N_Vector X, long int i, realtype val)
  * Reads single element from hypre vector by accessing its raw block. 
  * Probably not the most efficient way to get the vector values.
  * --------------------------------------------------------------------*/
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
   hypre_ParVector *Xvec = N_VGetVector_ParHyp(X);
   const realtype *Xdata = hypre_VectorData(hypre_ParVectorLocalVector(Xvec));
diff --git a/examples/nvector/petsc/CMakeLists.txt b/examples/nvector/petsc/CMakeLists.txt
index 2ced736..c289900 100644
--- a/examples/nvector/petsc/CMakeLists.txt
+++ b/examples/nvector/petsc/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -14,18 +11,25 @@
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for nvector examples
+# CMakeLists.txt file for PETSc nvector examples
+# ---------------------------------------------------------------
 
-# Add variable nvector_petsc_examples with the names of the nvector examples
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS PETSc nvector
 SET(nvector_petsc_examples
-  test_nvector_petsc
-)
+  "test_nvector_petsc\;\;\;\;"          # run sequentially
+  "test_nvector_petsc\;1000 0\;\;\;"    # run sequentially with arguments
+  "test_nvector_petsc\;\;1\;4\;"        # run parallel on 4 procs
+  "test_nvector_petsc\;1000 0\;1\;4\;"  # run parallel on 4 procs with arguments
+  )
 
+# Dependencies for nvector examples
 SET(nvector_examples_dependencies
   test_nvector
   sundials_nvector
-)
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(. ..)
@@ -33,56 +37,87 @@ INCLUDE_DIRECTORIES(${PETSC_INCLUDE_DIR})
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(NVECS_LIB sundials_nvecpetsc_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(NVECS_LIB sundials_nvecpetsc_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS})
 
+LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
+
 IF(MPI_MPICC)
   # use MPI_MPICC as the compiler
   SET(CMAKE_C_COMPILER ${MPI_MPICC})
 ELSE(MPI_MPICC)
   # add MPI_INCLUDE_PATH to include directories
   INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-  TARGET_LINK_LIBRARIES(${example} MPI_LIBRARIES)
 ENDIF(MPI_MPICC)
 
-# Add the build and install targets for each nvector example
-
-FOREACH(example ${nvector_petsc_examples})
-
-  ADD_EXECUTABLE(${example} ${example}.c ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
-  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-
-  # Run sequentially
-  SUNDIALS_ADD_TEST("${example}" ${example})
 
-  # Run sequentially with arguments
-  SUNDIALS_ADD_TEST("${example}_1000_0" ${example} TEST_ARGS 1000 0)
-
-  # Run in petsc on 4 procs
-  SUNDIALS_ADD_TEST("${example}_4" ${example} MPI_NPROCS 4)
-  
-  # Parallel with additional arguments and supplying an answer file
-  SUNDIALS_ADD_TEST("${example}_4_1000_0" ${example} MPI_NPROCS 4 TEST_ARGS 1000 0 ANSWER_FILE ${example})
+# Add the build and install targets for each nvector example
+FOREACH(example_tuple ${nvector_petsc_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    IF("${number_of_tasks}" STREQUAL "")
+      SET(test_name ${example})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${number_of_tasks})
+    ENDIF()
+  ELSE()
+    IF("${number_of_tasks}" STREQUAL "")
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+    ELSE()
+      STRING(REGEX REPLACE " " "_" test_name ${example}_${number_of_tasks}_${example_args})
+    ENDIF()
+  ENDIF()  
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/petsc)
+  ENDIF()
 
-  # Specify floating point precision and integer percentage for comparison
-  SUNDIALS_ADD_TEST("${example}_precision" ${example} MPI_NPROCS 4 TEST_ARGS 1000 0 ANSWER_FILE ${example}
-    FLOAT_PRECISION 5 INTEGER_PERCENTAGE 0)
-  
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-  TARGET_LINK_LIBRARIES(${example} ${PETSC_LIBRARIES})
+ENDFOREACH(example_tuple ${nvector_petsc_examples})
 
-  IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ../test_nvector.c ../test_nvector.h ../../../src/sundials/sundials_nvector.c DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/petsc)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${nvector_petsc_examples})
 
 IF(EXAMPLES_INSTALL)
 
@@ -91,8 +126,9 @@ IF(EXAMPLES_INSTALL)
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER_LIB "sundials_nvecpetsc")
-  LIST2STRING(nvector_petsc_examples EXAMPLES)
-  LIST2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  EXAMPLES2STRING(nvector_petsc_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -100,10 +136,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_petsc_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/nvector/petsc/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_petsc_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/petsc/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/nvector/petsc/test_nvector_petsc.c b/examples/nvector/petsc/test_nvector_petsc.c
index 513b522..55a5092 100644
--- a/examples/nvector/petsc/test_nvector_petsc.c
+++ b/examples/nvector/petsc/test_nvector_petsc.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4137 $
- * $Date: 2014-06-15 12:26:15 -0700 (Sun, 15 Jun 2014) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Slaven Peles @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -17,8 +13,7 @@
  * -----------------------------------------------------------------
  * This is the testing routine to check the NVECTOR Parallel module 
  * implementation. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,13 +37,15 @@ static int Test_N_VMake(Vec* W, int myid);
  * --------------------------------------------------------------------*/
 int main(int argc, char *argv[]) 
 {
-  int      fails = 0;                   /* counter for test failures */
-  long int local_length, global_length; /* vector lengths            */
-  N_Vector W, X, Y, Z;                  /* test vectors              */
-  MPI_Comm comm;                        /* MPI Communicator          */
-  int      nprocs, myid;                /* Number of procs, proc id  */
-  Vec xvec;                             /* PETSc vector              */
-  PetscErrorCode ierr;                  /* PETSc error code          */
+  int            fails = 0;                   /* counter for test failures */
+  int            globfails = 0;               /* counter for test failures */
+  sunindextype   local_length, global_length; /* vector lengths            */
+  N_Vector       W, X, Y, Z;                  /* test vectors              */
+  MPI_Comm       comm;                        /* MPI Communicator          */
+  int            nprocs, myid;                /* Number of procs, proc id  */
+  Vec            xvec;                        /* PETSc vector              */
+  PetscErrorCode ierr;                        /* PETSc error code          */
+  int            mpierr;                      /* mpi error flag            */
 
   /* Get processor number and total number of processes */
   MPI_Init(&argc, &argv);
@@ -130,19 +127,23 @@ int main(int argc, char *argv[])
      }
   }
   
+  /* check if any other process failed */
+  mpierr = MPI_Allreduce(&fails, &globfails, 1, MPI_INT, MPI_MAX, comm);
+
   ierr = PetscFinalize();
   CHKERRQ(ierr);
   MPI_Finalize();
-  return(0);
+
+  return(globfails);
 }
 
 /* ----------------------------------------------------------------------
  * Check vector
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int failure = 0;
-  long int i;
+  sunindextype i;
   Vec *xv = N_VGetVector_Petsc(X);
   PetscScalar *a;
 
@@ -163,12 +164,12 @@ int check_ans(realtype ans, N_Vector X, long int local_length)
 booleantype has_data(N_Vector X)
 {
   if(N_VGetVector_Petsc(X) == NULL)
-    return FALSE;
+    return SUNFALSE;
   else
-    return TRUE;
+    return SUNTRUE;
 }
 
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
   PetscScalar *a;
   Vec *xv = N_VGetVector_Petsc(X);
@@ -178,7 +179,7 @@ void set_element(N_Vector X, long int i, realtype val)
   VecRestoreArray(*xv, &a);
 }
 
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
   PetscScalar *a;
   Vec *xv = N_VGetVector_Petsc(X);
diff --git a/examples/nvector/pthreads/CMakeLists.txt b/examples/nvector/pthreads/CMakeLists.txt
index 946d0d3..5c49893 100644
--- a/examples/nvector/pthreads/CMakeLists.txt
+++ b/examples/nvector/pthreads/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -14,66 +11,97 @@
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for nvector examples
+# CMakeLists.txt file for PThread nvector examples
+# ---------------------------------------------------------------
 
-# Add variable nvector_pthreads_examples with the names of the nvector examples
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS pthread nvector
 SET(nvector_pthreads_examples
-  test_nvector_pthreads
-)
-
+  "test_nvector_pthreads\;1000 1 0\;"
+  "test_nvector_pthreads\;1000 2 0\;"
+  "test_nvector_pthreads\;1000 4 0\;"
+  "test_nvector_pthreads\;10000 1 0\;"
+  "test_nvector_pthreads\;10000 2 0\;"
+  "test_nvector_pthreads\;10000 4 0\;"
+  )
+
+# Dependencies for nvector examples
 SET(nvector_examples_dependencies
   test_nvector
   sundials_nvector
-)
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(. ..)
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(NVECS_LIB sundials_nvecpthreads_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(NVECS_LIB sundials_nvecpthreads_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS})
 
-# Add the build and install targets for each nvector example
 
-FOREACH(example ${nvector_pthreads_examples})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${nvector_pthreads_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
 
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
   IF(WIN32)
-    # This is used to get around DLL linkage issue since we are
-    # manually including sundials_nvector.c here, which is normally in
-    # a library that is included.  If this is not set build system
-    # thinks nvector is externally linked.
     ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
   ENDIF(WIN32)
 
-  ADD_EXECUTABLE(${example} ${example}.c ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
-  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-
-  SUNDIALS_ADD_TEST(${example}_1000_1_0 ${example} TEST_ARGS 1000 1 0)
-  SUNDIALS_ADD_TEST(${example}_1000_2_0 ${example} TEST_ARGS 1000 2 0)
-  SUNDIALS_ADD_TEST(${example}_1000_4_0 ${example} TEST_ARGS 1000 4 0)
-
-  SUNDIALS_ADD_TEST(${example}_10000_1_0 ${example} TEST_ARGS 10000 1 0)
-  SUNDIALS_ADD_TEST(${example}_10000_2_0 ${example} TEST_ARGS 10000 2 0)
-  SUNDIALS_ADD_TEST(${example}_10000_4_0 ${example} TEST_ARGS 10000 4 0)
-
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${CMAKE_THREAD_LIBS_INIT})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/pthreads)
+  ENDIF()
 
-  TARGET_LINK_LIBRARIES(${example} ${CMAKE_THREAD_LIBS_INIT})
+ENDFOREACH(example_tuple ${nvector_pthreads_examples})
 
-  IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ../test_nvector.c ../test_nvector.h ../../../src/sundials/sundials_nvector.c DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/pthreads)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${nvector_pthreads_examples})
 
 IF(EXAMPLES_INSTALL)
 
@@ -82,8 +110,9 @@ IF(EXAMPLES_INSTALL)
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER_LIB "sundials_nvecpthreads")
-  LIST2STRING(nvector_pthreads_examples EXAMPLES)
-  LIST2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  EXAMPLES2STRING(nvector_pthreads_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -91,10 +120,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_pthreads_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/nvector/pthreads/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_pthreads_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/pthreads/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/nvector/pthreads/test_nvector_pthreads.c b/examples/nvector/pthreads/test_nvector_pthreads.c
index e29402a..0ec4efc 100644
--- a/examples/nvector/pthreads/test_nvector_pthreads.c
+++ b/examples/nvector/pthreads/test_nvector_pthreads.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4790 $
- * $Date: 2016-06-29 14:47:05 -0700 (Wed, 29 Jun 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -18,8 +14,7 @@
  * This is the testing routine to check the POSIX Threads (Pthreads) 
  * NVECTOR module implementation which uses a LOCAL data struct to 
  * share data between threads. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,11 +30,11 @@
  * --------------------------------------------------------------------*/
 int main(int argc, char *argv[]) 
 {
-  int      fails = 0;  /* counter for test failures */
-  int      nthreads;   /* number of threads         */
-  long int veclen;     /* vector length             */
-  N_Vector W, X, Y, Z; /* test vectors              */
-  int      print_timing;
+  int          fails = 0;    /* counter for test failures */
+  int          nthreads;     /* number of threads         */
+  sunindextype veclen;       /* vector length             */
+  N_Vector     W, X, Y, Z;   /* test vectors              */
+  int          print_timing;
 
   /* check inputs, set vector length, and number of threads */
   if (argc < 4){
@@ -63,7 +58,8 @@ int main(int argc, char *argv[])
   SetTiming(print_timing);
 
 
-  printf("\nRunning with %d threads and vector length %ld \n \n", nthreads, veclen);
+  printf("\nRunning with %d threads and vector length %ld \n \n",
+         nthreads, (long int) veclen);
 
   /* Create vectors */
   W = N_VNewEmpty_Pthreads(veclen, nthreads);
@@ -115,16 +111,16 @@ int main(int argc, char *argv[])
     printf("SUCCESS: NVector module passed all tests \n \n");
   }
 
-  return(0);
+  return(fails);
 }
 
 /* ----------------------------------------------------------------------
  * Check vector
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int      failure = 0;
-  long int i;
+  sunindextype i;
   realtype *Xdata;
   
   Xdata = N_VGetArrayPointer(X);
@@ -144,17 +140,17 @@ booleantype has_data(N_Vector X)
 {
   realtype *Xdata = N_VGetArrayPointer(X);
   if (Xdata == NULL)
-    return FALSE;
+    return SUNFALSE;
   else
-    return TRUE;
+    return SUNTRUE;
 }
 
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
   NV_Ith_PT(X,i) = val;
 }
  
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
   return NV_Ith_PT(X,i);
 }
diff --git a/examples/nvector/raja/CMakeLists.txt b/examples/nvector/raja/CMakeLists.txt
new file mode 100644
index 0000000..f1edb72
--- /dev/null
+++ b/examples/nvector/raja/CMakeLists.txt
@@ -0,0 +1,149 @@
+# ---------------------------------------------------------------
+# Programmer:  Slaven Peles @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for raja nvector examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS raja nvector
+SET(nvector_raja_examples
+  "test_nvector_raja\;10000 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(nvector_examples_dependencies
+  test_nvector
+  sundials_nvector
+  sundials_math
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. .. ${CUDA_TOOLKIT_ROOT_DIR}/samples/common/inc)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVECS_LIB sundials_nvecraja_static)
+ELSE()
+  SET(NVECS_LIB sundials_nvecraja_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS} -L${RAJA_LIB_PATH} -lRAJA) 
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${nvector_raja_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    CUDA_ADD_EXECUTABLE(${example} ${example}.cu
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c
+      ../../../src/sundials/sundials_math.c)
+    
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${CUDA_LIBRARIES})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.cu
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      ../../../src/sundials/sundials_math.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/raja)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${nvector_raja_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/raja)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_nvecraja")
+
+  EXAMPLES2STRING(nvector_raja_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_raja_CUDA_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/raja/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/nvector/raja/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/raja
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_raja_CUDA_ex.in
+      ${PROJECT_BINARY_DIR}/examples/nvector/raja/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/nvector/raja/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/raja
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/nvector/serial/test_nvector_serial.c b/examples/nvector/raja/test_nvector_raja.cu
similarity index 58%
copy from examples/nvector/serial/test_nvector_serial.c
copy to examples/nvector/raja/test_nvector_raja.cu
index a2e1979..a9fa14c 100644
--- a/examples/nvector/serial/test_nvector_serial.c
+++ b/examples/nvector/raja/test_nvector_raja.cu
@@ -1,9 +1,5 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4790 $
- * $Date: 2016-06-29 14:47:05 -0700 (Wed, 29 Jun 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): David J. Gardner @ LLNL
+/* ----------------------------------------------------------------- 
+ * Programmer(s): Slaven Peles @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -15,34 +11,35 @@
  * For details, see the LICENSE file.
  * LLNS Copyright End
  * -----------------------------------------------------------------
- * This is the testing routine to check the NVECTOR Serial module 
+ * This is the testing routine to check the NVECTOR Raja module
  * implementation. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <sundials/sundials_types.h>
-#include <nvector/nvector_serial.h>
+#include <nvector/nvector_raja.h>
 #include <sundials/sundials_math.h>
 #include "test_nvector.h"
 
+#include <nvector/raja/Vector.hpp>
 
 /* ----------------------------------------------------------------------
  * Main NVector Testing Routine
  * --------------------------------------------------------------------*/
 int main(int argc, char *argv[]) 
 {
-  int      fails = 0;  /* counter for test failures  */
-  long int veclen;     /* vector length              */
-  N_Vector W, X, Y, Z; /* test vectors               */
-  int      print_timing;
+  int          fails = 0;   /* counter for test failures  */
+  sunindextype veclen;      /* vector length              */
+  N_Vector     W, X, Y, Z;  /* test vectors               */
+  int print_timing;
+  /*  sunindextype liw, lrw; */
 
 
   /* check input and set vector length */
   if (argc < 3){
-    printf("ERROR: ONE (1) Input required: vector length, print timing \n");
+    printf("ERROR: TWO (2) Inputs required: vector length, print timing \n");
     return(-1);
   }
 
@@ -56,23 +53,32 @@ int main(int argc, char *argv[])
   SetTiming(print_timing);
 
 
-  printf("\nRunning with vector length %ld \n \n", veclen);
+  printf("\nRunning with vector length %ld \n\n", (long) veclen);
 
   /* Create vectors */
-  W = N_VNewEmpty_Serial(veclen);
-  X = N_VNew_Serial(veclen);
-  Y = N_VNew_Serial(veclen);
-  Z = N_VNew_Serial(veclen);
+  W = N_VNewEmpty_Raja(veclen);
+  X = N_VNew_Raja(veclen);
 
-  if(N_VGetVectorID(W) == SUNDIALS_NVEC_SERIAL) {
-    /*printf("Testing serial variant of N_Vector...\n");*/
-  }
-  
   /* NVector Tests */
-  fails += Test_N_VSetArrayPointer(W, veclen, 0);
-  fails += Test_N_VGetArrayPointer(X, veclen, 0);
-  fails += Test_N_VLinearSum(X, Y, Z, veclen, 0);
+  
+  /* Raja specific tests */
+  
+  /* Memory allocation tests */
+  fails += Test_N_VCloneEmpty(X, 0);
+  fails += Test_N_VClone(X, veclen, 0);
+  fails += Test_N_VCloneEmptyVectorArray(5, X, 0);
+  fails += Test_N_VCloneVectorArray(5, X, veclen, 0);
+
+  Y = N_VClone_Raja(X);
+  Z = N_VClone_Raja(X);
+
+  /* Skipped tests */
+  /*   fails += Test_N_VSetArrayPointer(W, veclen, 0); */
+  /*   fails += Test_N_VGetArrayPointer(X, veclen, 0); */
+  
+  /* Vector operation tests */
   fails += Test_N_VConst(X, veclen, 0);
+  fails += Test_N_VLinearSum(X, Y, Z, veclen, 0);
   fails += Test_N_VProd(X, Y, Z, veclen, 0);
   fails += Test_N_VDiv(X, Y, Z, veclen, 0);
   fails += Test_N_VScale(X, Z, veclen, 0);
@@ -90,16 +96,15 @@ int main(int argc, char *argv[])
   fails += Test_N_VInvTest(X, Z, veclen, 0);
   fails += Test_N_VConstrMask(X, Y, Z, veclen, 0);
   fails += Test_N_VMinQuotient(X, Y, veclen, 0);
-  fails += Test_N_VCloneVectorArray(5, X, veclen, 0);
-  fails += Test_N_VCloneEmptyVectorArray(5, X, 0);
-  fails += Test_N_VCloneEmpty(X, 0);
-  fails += Test_N_VClone(X, veclen, 0);
 
+  /*  N_VSpace_Raja(X, &lrw, &liw);               */
+  /*  printf("lrw = %ld, liw = %ld\n", lrw, liw); */
+  
   /* Free vectors */
-  N_VDestroy_Serial(W);
-  N_VDestroy_Serial(X);
-  N_VDestroy_Serial(Y);
-  N_VDestroy_Serial(Z);
+  N_VDestroy_Raja(W);
+  N_VDestroy_Raja(X);
+  N_VDestroy_Raja(Y);
+  N_VDestroy_Raja(Z);
 
   /* Print result */
   if (fails) {
@@ -108,46 +113,48 @@ int main(int argc, char *argv[])
     printf("SUCCESS: NVector module passed all tests \n \n");
   }
 
-  return(0);
+  return(fails);
 }
 
 /* ----------------------------------------------------------------------
  * Check vector
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int      failure = 0;
-  long int i;
-  realtype *Xdata;
+  sunindextype i;
+  sunrajavec::Vector<double, sunindextype>* xv = sunrajavec::extract<realtype, sunindextype>(X);
+  realtype *xdata;
   
-  Xdata = N_VGetArrayPointer(X);
-
+  xv->copyFromDev();
+  
+  xdata = xv->host();
   /* check vector data */
   for(i=0; i < local_length; i++){
-    failure += FNEQ(Xdata[i], ans);
+    failure += FNEQ(xdata[i], ans);
+    //printf("%g ?= %g\n", xdata[i], ans);
   }
-
-  if (failure > ZERO)
-    return(1);
-  else
-    return(0);
+  return (failure > ZERO) ? (1) : (0);
 }
 
 booleantype has_data(N_Vector X)
 {
-  realtype *Xdata = N_VGetArrayPointer(X);
-  if (Xdata == NULL)
-    return FALSE;
-  else
-    return TRUE;
+  sunrajavec::Vector<double, sunindextype>* xv = sunrajavec::extract<realtype, sunindextype>(X);
+
+  return (xv == NULL ? SUNFALSE : SUNTRUE);
 }
 
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
-  NV_Ith_S(X,i) = val;    
+  sunrajavec::Vector<double, sunindextype>* xv = sunrajavec::extract<realtype, sunindextype>(X);
+  xv->copyFromDev();
+  (xv->host())[i] = val;
+  xv->copyToDev();
 }
 
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
-  return NV_Ith_S(X,i);    
+  sunrajavec::Vector<double, sunindextype>* xv = sunrajavec::extract<realtype, sunindextype>(X);
+  xv->copyFromDev();
+  return (xv->host())[i];
 }
diff --git a/examples/nvector/serial/CMakeLists.txt b/examples/nvector/serial/CMakeLists.txt
index 9c38a10..e36c9e4 100644
--- a/examples/nvector/serial/CMakeLists.txt
+++ b/examples/nvector/serial/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
-# ---------------------------------------------------------------
 # Programmer:  Steven Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -14,59 +11,93 @@
 # For details, see the LICENSE file.
 # LLNS Copyright End
 # ---------------------------------------------------------------
-# CMakeLists.txt file for nvector examples
+# CMakeLists.txt file for serial nvector examples
+# ---------------------------------------------------------------
 
-# Add variable nvector_serial_examples with the names of the nvector examples
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
 
+# Examples using SUNDIALS serial nvector
 SET(nvector_serial_examples
-  test_nvector_serial
-)
+  "test_nvector_serial\;1000 0\;"
+  "test_nvector_serial\;10000 0\;"
+  )
 
+# Dependencies for nvector examples
 SET(nvector_examples_dependencies
   test_nvector
   sundials_nvector
-)
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(. ..)
 
 # Specify libraries to link against (through the target that was used to 
 # generate them) based on the value of the variable LINK_LIBRARY_TYPE
-
 IF(LINK_LIBRARY_TYPE MATCHES "static")
   SET(NVECS_LIB sundials_nvecserial_static)
-ELSE(LINK_LIBRARY_TYPE MATCHES "static")
+ELSE()
   SET(NVECS_LIB sundials_nvecserial_shared)
-ENDIF(LINK_LIBRARY_TYPE MATCHES "static")
+ENDIF()
 
 # Set-up linker flags and link libraries
-
 SET(SUNDIALS_LIBS ${NVECS_LIB} ${EXTRA_LINK_LIBS})
 
-# Add the build and install targets for each nvector example
 
-FOREACH(example ${nvector_serial_examples})
+# Add the build and install targets for each example
+FOREACH(example_tuple ${nvector_serial_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
 
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
   IF(WIN32)
-    # This is used to get around DLL linkage issue since we are
-    # manually including sundials_nvector.c here, which is normally in
-    # a library that is included.  If this is not set build system
-    # thinks nvector is externally linked.
     ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
   ENDIF(WIN32)
 
-  ADD_EXECUTABLE(${example} ${example}.c ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
-  SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
-
-  SUNDIALS_ADD_TEST( ${example}_1000_0 ${example} TEST_ARGS 1000 0)
-  SUNDIALS_ADD_TEST( ${example}_10000_0 ${example} TEST_ARGS 10000 0)
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_nvector.c ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+    
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_nvector.c
+      ../test_nvector.h
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/serial)
+  ENDIF()
 
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+ENDFOREACH(example_tuple ${nvector_serial_examples})
 
-  IF(EXAMPLES_INSTALL)
-    INSTALL(FILES ${example}.c ../test_nvector.c ../test_nvector.h ../../../src/sundials/sundials_nvector.c DESTINATION ${EXAMPLES_INSTALL_PATH}/nvector/serial)
-  ENDIF(EXAMPLES_INSTALL)
-ENDFOREACH(example ${nvector_serial_examples})
 
 IF(EXAMPLES_INSTALL)
 
@@ -75,8 +106,9 @@ IF(EXAMPLES_INSTALL)
 
   # Prepare substitution variables for Makefile and/or CMakeLists templates
   SET(SOLVER_LIB "sundials_nvecserial")
-  LIST2STRING(nvector_serial_examples EXAMPLES)
-  LIST2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
+
+  EXAMPLES2STRING(nvector_serial_examples EXAMPLES)
+  EXAMPLES2STRING(nvector_examples_dependencies EXAMPLES_DEPENDENCIES)
 
   # Regardless of the platform we're on, we will generate and install 
   # CMakeLists.txt file for building the examples. This file  can then 
@@ -84,10 +116,10 @@ IF(EXAMPLES_INSTALL)
 
   # generate CMakelists.txt in the binary directory
   CONFIGURE_FILE(
-      ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
-      ${PROJECT_BINARY_DIR}/examples/nvector/serial/CMakeLists.txt
-      @ONLY
-      )
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/nvector/serial/CMakeLists.txt
+    @ONLY
+    )
 
   # install CMakelists.txt
   INSTALL(
diff --git a/examples/nvector/serial/test_nvector_serial.c b/examples/nvector/serial/test_nvector_serial.c
index a2e1979..55fa9d1 100644
--- a/examples/nvector/serial/test_nvector_serial.c
+++ b/examples/nvector/serial/test_nvector_serial.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4790 $
- * $Date: 2016-06-29 14:47:05 -0700 (Wed, 29 Jun 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -17,8 +13,7 @@
  * -----------------------------------------------------------------
  * This is the testing routine to check the NVECTOR Serial module 
  * implementation. 
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,14 +30,14 @@
 int main(int argc, char *argv[]) 
 {
   int      fails = 0;  /* counter for test failures  */
-  long int veclen;     /* vector length              */
+  sunindextype veclen;     /* vector length              */
   N_Vector W, X, Y, Z; /* test vectors               */
   int      print_timing;
 
 
   /* check input and set vector length */
   if (argc < 3){
-    printf("ERROR: ONE (1) Input required: vector length, print timing \n");
+    printf("ERROR: TWO (2) Inputs required: vector length, print timing \n");
     return(-1);
   }
 
@@ -56,7 +51,7 @@ int main(int argc, char *argv[])
   SetTiming(print_timing);
 
 
-  printf("\nRunning with vector length %ld \n \n", veclen);
+  printf("\nRunning with vector length %ld \n \n", (long int) veclen);
 
   /* Create vectors */
   W = N_VNewEmpty_Serial(veclen);
@@ -108,16 +103,16 @@ int main(int argc, char *argv[])
     printf("SUCCESS: NVector module passed all tests \n \n");
   }
 
-  return(0);
+  return(fails);
 }
 
 /* ----------------------------------------------------------------------
  * Check vector
  * --------------------------------------------------------------------*/
-int check_ans(realtype ans, N_Vector X, long int local_length)
+int check_ans(realtype ans, N_Vector X, sunindextype local_length)
 {
   int      failure = 0;
-  long int i;
+  sunindextype i;
   realtype *Xdata;
   
   Xdata = N_VGetArrayPointer(X);
@@ -137,17 +132,17 @@ booleantype has_data(N_Vector X)
 {
   realtype *Xdata = N_VGetArrayPointer(X);
   if (Xdata == NULL)
-    return FALSE;
+    return SUNFALSE;
   else
-    return TRUE;
+    return SUNTRUE;
 }
 
-void set_element(N_Vector X, long int i, realtype val)
+void set_element(N_Vector X, sunindextype i, realtype val)
 {
   NV_Ith_S(X,i) = val;    
 }
 
-realtype get_element(N_Vector X, long int i)
+realtype get_element(N_Vector X, sunindextype i)
 {
   return NV_Ith_S(X,i);    
 }
diff --git a/examples/nvector/test_nvector.c b/examples/nvector/test_nvector.c
index 4da2886..0549ef0 100644
--- a/examples/nvector/test_nvector.c
+++ b/examples/nvector/test_nvector.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4652 $
- * $Date: 2016-02-11 10:22:15 -0800 (Thu, 11 Feb 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner and Slaven Peles @ LLNL
  * -----------------------------------------------------------------
  * Acknowledgements: These testing routines are based on an
@@ -26,8 +22,7 @@
  *       to get a pointer to the data component of an N_Vector. This 
  *       assumes the internal data is stored in a contiguous 
  *       realtype array.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <sundials/sundials_nvector.h>
 #include <sundials/sundials_types.h>
@@ -57,7 +52,7 @@ int print_time = 0;
  *
  * NOTE: This routine depends on N_VConst to check vector data.
  * --------------------------------------------------------------------*/
-int Test_N_VCloneVectorArray(int count, N_Vector W, long int local_length, int myid)
+int Test_N_VCloneVectorArray(int count, N_Vector W, sunindextype local_length, int myid)
 {
   int      i, failure;
   double   start_time, stop_time;
@@ -197,7 +192,7 @@ int Test_N_VCloneEmpty(N_Vector W, int myid)
  *
  * NOTE: This routine depends on N_VConst to check vector data.
  * --------------------------------------------------------------------*/
-int Test_N_VClone(N_Vector W, long int local_length, int myid)
+int Test_N_VClone(N_Vector W, sunindextype local_length, int myid)
 {
   int      failure;
   double   start_time, stop_time;
@@ -211,7 +206,7 @@ int Test_N_VClone(N_Vector W, long int local_length, int myid)
   /* check cloned vector */
   if (X == NULL) {
     printf(">>> FAILED test -- N_VClone, Proc %d \n", myid);
-    printf("    After N_VCloneEmpty, X == NULL \n \n");
+    printf("    After N_VClone, X == NULL \n \n");
     return(1);
   } 
 
@@ -227,7 +222,7 @@ int Test_N_VClone(N_Vector W, long int local_length, int myid)
   failure = check_ans(ONE, X, local_length);
   if (failure) {
     printf(">>> FAILED test -- N_VClone, Proc %d \n", myid);
-    printf("    Failed N_VConst check \n \n");
+    printf("    Failed N_VClone check \n \n");
     N_VDestroy(X);
     return(1);
   }    
@@ -252,7 +247,7 @@ int Test_N_VClone(N_Vector W, long int local_length, int myid)
  *
  * NOTE: This routine depends on N_VConst to check vector data.
  * --------------------------------------------------------------------*/
-int Test_N_VGetArrayPointer(N_Vector W, long int local_length, int myid)
+int Test_N_VGetArrayPointer(N_Vector W, sunindextype local_length, int myid)
 {
   int      failure = 0;
   double   start_time, stop_time;
@@ -294,10 +289,10 @@ int Test_N_VGetArrayPointer(N_Vector W, long int local_length, int myid)
  *
  * NOTE: This routine depends on N_VConst to check vector data.
  * --------------------------------------------------------------------*/
-int Test_N_VSetArrayPointer(N_Vector W, long int local_length, int myid)
+int Test_N_VSetArrayPointer(N_Vector W, sunindextype local_length, int myid)
 {
   int      failure = 0;
-  long int i;  
+  sunindextype i;  
   double   start_time, stop_time;
   realtype *Wdata;
 
@@ -339,7 +334,7 @@ int Test_N_VSetArrayPointer(N_Vector W, long int local_length, int myid)
 /* ----------------------------------------------------------------------
  * N_VLinearSum Tests
  * --------------------------------------------------------------------*/
-int Test_N_VLinearSum(N_Vector X, N_Vector Y, N_Vector Z, long int local_length, int myid)
+int Test_N_VLinearSum(N_Vector X, N_Vector Y, N_Vector Z, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -806,13 +801,13 @@ int Test_N_VLinearSum(N_Vector X, N_Vector Y, N_Vector Z, long int local_length,
 /* ----------------------------------------------------------------------
  * N_VConst Test
  * --------------------------------------------------------------------*/
-int Test_N_VConst(N_Vector X, long int local_length, int myid)
+int Test_N_VConst(N_Vector X, sunindextype local_length, int myid)
 {
-  int      fails = 0, failure = 0;
+  int      i, fails = 0, failure = 0;
   double   start_time, stop_time;
-  long int i;
 
-  /* fill vector data */
+  /* fill vector data with zeros to prevent passing in the case where
+     the input vector is a vector of ones */
   for(i=0; i < local_length; i++){
     set_element(X, i, ZERO);
   }
@@ -841,7 +836,7 @@ int Test_N_VConst(N_Vector X, long int local_length, int myid)
 /* ----------------------------------------------------------------------
  * N_VProd Test
  * --------------------------------------------------------------------*/
-int Test_N_VProd(N_Vector X, N_Vector Y, N_Vector Z, long int local_length, int myid)
+int Test_N_VProd(N_Vector X, N_Vector Y, N_Vector Z, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -875,7 +870,7 @@ int Test_N_VProd(N_Vector X, N_Vector Y, N_Vector Z, long int local_length, int
 /* ----------------------------------------------------------------------
  * N_VDiv Test
  * --------------------------------------------------------------------*/
-int Test_N_VDiv(N_Vector X, N_Vector Y, N_Vector Z, long int local_length, int myid)
+int Test_N_VDiv(N_Vector X, N_Vector Y, N_Vector Z, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -909,7 +904,7 @@ int Test_N_VDiv(N_Vector X, N_Vector Y, N_Vector Z, long int local_length, int m
 /* ----------------------------------------------------------------------
  * N_VScale Tests
  * --------------------------------------------------------------------*/
-int Test_N_VScale(N_Vector X, N_Vector Z, long int local_length, int myid)
+int Test_N_VScale(N_Vector X, N_Vector Z, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1029,7 +1024,7 @@ int Test_N_VScale(N_Vector X, N_Vector Z, long int local_length, int myid)
 /* ----------------------------------------------------------------------
  * N_VAbs Test
  * --------------------------------------------------------------------*/
-int Test_N_VAbs(N_Vector X, N_Vector Z, long int local_length, int myid)
+int Test_N_VAbs(N_Vector X, N_Vector Z, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1062,7 +1057,7 @@ int Test_N_VAbs(N_Vector X, N_Vector Z, long int local_length, int myid)
 /* ----------------------------------------------------------------------
  * N_VInv Test
  * --------------------------------------------------------------------*/
-int Test_N_VInv(N_Vector X, N_Vector Z, long int local_length, int myid)
+int Test_N_VInv(N_Vector X, N_Vector Z, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1095,7 +1090,7 @@ int Test_N_VInv(N_Vector X, N_Vector Z, long int local_length, int myid)
 /* ----------------------------------------------------------------------
  * N_VAddConst Test
  * --------------------------------------------------------------------*/
-int Test_N_VAddConst(N_Vector X, N_Vector Z, long int local_length, int myid)
+int Test_N_VAddConst(N_Vector X, N_Vector Z, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1129,7 +1124,7 @@ int Test_N_VAddConst(N_Vector X, N_Vector Z, long int local_length, int myid)
  * N_VDotProd Test
  * --------------------------------------------------------------------*/
 int Test_N_VDotProd(N_Vector X, N_Vector Y, 
-                    long int local_length, long int global_length, int myid)
+                    sunindextype local_length, sunindextype global_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1163,7 +1158,7 @@ int Test_N_VDotProd(N_Vector X, N_Vector Y,
 /* ----------------------------------------------------------------------
  * N_VMaxNorm Test
  * --------------------------------------------------------------------*/
-int Test_N_VMaxNorm(N_Vector X, long int local_length, int myid)
+int Test_N_VMaxNorm(N_Vector X, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1197,7 +1192,7 @@ int Test_N_VMaxNorm(N_Vector X, long int local_length, int myid)
 /* ----------------------------------------------------------------------
  * N_VWrmsNorm Test
  * --------------------------------------------------------------------*/
-int Test_N_VWrmsNorm(N_Vector X, N_Vector W, long int local_length, int myid)
+int Test_N_VWrmsNorm(N_Vector X, N_Vector W, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1232,7 +1227,7 @@ int Test_N_VWrmsNorm(N_Vector X, N_Vector W, long int local_length, int myid)
  * N_VWrmsNormMask Test
  * --------------------------------------------------------------------*/
 int Test_N_VWrmsNormMask(N_Vector X, N_Vector W, N_Vector ID, 
-			 long int local_length, long int global_length, int myid)
+			 sunindextype local_length, sunindextype global_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1300,7 +1295,7 @@ int Test_N_VWrmsNormMask(N_Vector X, N_Vector W, N_Vector ID,
 /* ----------------------------------------------------------------------
  * N_VMin Test
  * --------------------------------------------------------------------*/
-int Test_N_VMin(N_Vector X, long int local_length, int myid)
+int Test_N_VMin(N_Vector X, sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1335,7 +1330,7 @@ int Test_N_VMin(N_Vector X, long int local_length, int myid)
  * N_VWL2Norm Test
  * --------------------------------------------------------------------*/
 int Test_N_VWL2Norm(N_Vector X, N_Vector W, 
-                    long int local_length, long int global_length, int myid)
+                    sunindextype local_length, sunindextype global_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1369,8 +1364,8 @@ int Test_N_VWL2Norm(N_Vector X, N_Vector W,
 /* ----------------------------------------------------------------------
  * N_VL1Norm Test
  * --------------------------------------------------------------------*/
-int Test_N_VL1Norm(N_Vector X, long int local_length, 
-                   long int global_length, int myid)
+int Test_N_VL1Norm(N_Vector X, sunindextype local_length, 
+                   sunindextype global_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
@@ -1403,14 +1398,15 @@ int Test_N_VL1Norm(N_Vector X, long int local_length,
 /* ----------------------------------------------------------------------
  * N_VCompare
  * --------------------------------------------------------------------*/
-int Test_N_VCompare(N_Vector X, N_Vector Z, long int local_length, int myid)
+int Test_N_VCompare(N_Vector X, N_Vector Z, sunindextype local_length, int myid)
 {
   int      mask, fails = 0, failure = 0;
   double   start_time, stop_time;
-  long int i;
+  sunindextype i;
 
   if (local_length < 3) {
-    printf("Error Test_N_VCompare: Local vector length is %ld, length must be >= 3", local_length);
+    printf("Error Test_N_VCompare: Local vector length is %ld, length must be >= 3",
+           (long int) local_length);
     return(-1);
   }
 
@@ -1485,15 +1481,16 @@ int Test_N_VCompare(N_Vector X, N_Vector Z, long int local_length, int myid)
 /* ----------------------------------------------------------------------
  * N_VInvTest
  * --------------------------------------------------------------------*/
-int Test_N_VInvTest(N_Vector X, N_Vector Z, long int local_length, int myid)
+int Test_N_VInvTest(N_Vector X, N_Vector Z, sunindextype local_length, int myid)
 {
   int         mask, fails = 0, failure = 0;
   double      start_time, stop_time;
-  long int    i;
+  sunindextype    i;
   booleantype test;
 
   if (local_length < 2) {
-    printf("Error Test_N_VCompare: Local vector length is %ld, length must be >= 2", local_length);
+    printf("Error Test_N_VCompare: Local vector length is %ld, length must be >= 2",
+           (long int) local_length);
     return(-1);
   }
 
@@ -1574,15 +1571,16 @@ int Test_N_VInvTest(N_Vector X, N_Vector Z, long int local_length, int myid)
  * N_VConstrMask
  * --------------------------------------------------------------------*/
 int Test_N_VConstrMask(N_Vector C, N_Vector X, N_Vector M, 
-                       long int local_length, int myid)
+                       sunindextype local_length, int myid)
 {
   int         mask, fails = 0, failure = 0;
   double      start_time, stop_time;
-  long int    i;
+  sunindextype    i;
   booleantype test;
 
   if (local_length < 7) {
-    printf("Error Test_N_VCompare: Local vector length is %ld, length must be >= 7", local_length);
+    printf("Error Test_N_VCompare: Local vector length is %ld, length must be >= 7",
+           (long int) local_length);
     return(-1);
   }
 
@@ -1737,7 +1735,7 @@ int Test_N_VConstrMask(N_Vector C, N_Vector X, N_Vector M,
  * N_VMinQuotient Test
  * --------------------------------------------------------------------*/
 int Test_N_VMinQuotient(N_Vector NUM, N_Vector DENOM, 
-                        long int local_length, int myid)
+                        sunindextype local_length, int myid)
 {
   int      fails = 0, failure = 0;
   double   start_time, stop_time;
diff --git a/examples/nvector/test_nvector.h b/examples/nvector/test_nvector.h
index 81852c9..4c7abe4 100644
--- a/examples/nvector/test_nvector.h
+++ b/examples/nvector/test_nvector.h
@@ -22,7 +22,7 @@
 
 #include <math.h>
 
-/* define constatnts */
+/* define constants */
 #define NEG_TWO  RCONST(-2.0)
 #define NEG_ONE  RCONST(-1.0)
 #define NEG_HALF RCONST(-0.5)
@@ -43,42 +43,42 @@
 extern "C" {
 #endif
   /* Forward declarations for implementation specific utility functions */
-  int check_ans(realtype ans, N_Vector X, long int local_length);
+  int check_ans(realtype ans, N_Vector X, sunindextype local_length);
   booleantype has_data(N_Vector X);
-  void set_element(N_Vector X, long int i, realtype val);
-  realtype get_element(N_Vector X, long int i);
+  void set_element(N_Vector X, sunindextype i, realtype val);
+  realtype get_element(N_Vector X, sunindextype i);
 
   /* Test function declarations */
-  int Test_N_VCloneVectorArray(int count, N_Vector W, long int local_length, int myid);
+  int Test_N_VCloneVectorArray(int count, N_Vector W, sunindextype local_length, int myid);
   int Test_N_VCloneEmptyVectorArray(int count, N_Vector W, int myid);
   int Test_N_VCloneEmpty(N_Vector W, int myid);
-  int Test_N_VClone(N_Vector W, long int local_length, int myid);
-  int Test_N_VGetArrayPointer(N_Vector W, long int local_length, int myid);
-  int Test_N_VSetArrayPointer(N_Vector W, long int local_length, int myid);
+  int Test_N_VClone(N_Vector W, sunindextype local_length, int myid);
+  int Test_N_VGetArrayPointer(N_Vector W, sunindextype local_length, int myid);
+  int Test_N_VSetArrayPointer(N_Vector W, sunindextype local_length, int myid);
   int Test_N_VLinearSum(N_Vector X, N_Vector Y, N_Vector Z, 
-                        long int local_length, int myid);
-  int Test_N_VConst(N_Vector X, long int local_length, int myid);
-  int Test_N_VProd(N_Vector X, N_Vector Y, N_Vector Z, long int local_length, int myid);
-  int Test_N_VDiv(N_Vector X, N_Vector Y, N_Vector Z, long int local_length, int myid);
-  int Test_N_VScale(N_Vector X, N_Vector Z, long int local_length, int myid);
-  int Test_N_VAbs(N_Vector X, N_Vector Z, long int local_length, int myid);
-  int Test_N_VInv(N_Vector X, N_Vector Z, long int local_length, int myid);
-  int Test_N_VAddConst(N_Vector X, N_Vector Z, long int local_length, int myid);
+                        sunindextype local_length, int myid);
+  int Test_N_VConst(N_Vector X, sunindextype local_length, int myid);
+  int Test_N_VProd(N_Vector X, N_Vector Y, N_Vector Z, sunindextype local_length, int myid);
+  int Test_N_VDiv(N_Vector X, N_Vector Y, N_Vector Z, sunindextype local_length, int myid);
+  int Test_N_VScale(N_Vector X, N_Vector Z, sunindextype local_length, int myid);
+  int Test_N_VAbs(N_Vector X, N_Vector Z, sunindextype local_length, int myid);
+  int Test_N_VInv(N_Vector X, N_Vector Z, sunindextype local_length, int myid);
+  int Test_N_VAddConst(N_Vector X, N_Vector Z, sunindextype local_length, int myid);
   int Test_N_VDotProd(N_Vector X, N_Vector Y, 
-                      long int local_length, long int global_length, int myid);
-  int Test_N_VMaxNorm(N_Vector X, long int local_length, int myid); 
-  int Test_N_VWrmsNorm(N_Vector X, N_Vector W, long int local_length, int myid);
+                      sunindextype local_length, sunindextype global_length, int myid);
+  int Test_N_VMaxNorm(N_Vector X, sunindextype local_length, int myid); 
+  int Test_N_VWrmsNorm(N_Vector X, N_Vector W, sunindextype local_length, int myid);
   int Test_N_VWrmsNormMask(N_Vector X, N_Vector W, N_Vector ID, 
-                           long int local_length, long int global_length, int myid);
-  int Test_N_VMin(N_Vector X, long int local_length, int myid); 
+                           sunindextype local_length, sunindextype global_length, int myid);
+  int Test_N_VMin(N_Vector X, sunindextype local_length, int myid); 
   int Test_N_VWL2Norm(N_Vector X, N_Vector W, 
-                      long int local_length, long int global_length, int myid);
-  int Test_N_VL1Norm(N_Vector X, long int local_length, long int global_length, int myid);
-  int Test_N_VCompare(N_Vector X, N_Vector Z, long int local_length, int myid);
-  int Test_N_VInvTest(N_Vector X, N_Vector Z, long int local_length, int myid);
+                      sunindextype local_length, sunindextype global_length, int myid);
+  int Test_N_VL1Norm(N_Vector X, sunindextype local_length, sunindextype global_length, int myid);
+  int Test_N_VCompare(N_Vector X, N_Vector Z, sunindextype local_length, int myid);
+  int Test_N_VInvTest(N_Vector X, N_Vector Z, sunindextype local_length, int myid);
   int Test_N_VConstrMask(N_Vector C, N_Vector X, N_Vector M, 
-                         long int local_length, int myid);
-  int Test_N_VMinQuotient(N_Vector NUM, N_Vector DENOM, long int local_length, int myid);
+                         sunindextype local_length, int myid);
+  int Test_N_VMinQuotient(N_Vector NUM, N_Vector DENOM, sunindextype local_length, int myid);
 
   void SetTiming(int onoff);
   
diff --git a/examples/sunlinsol/band/CMakeLists.txt b/examples/sunlinsol/band/CMakeLists.txt
new file mode 100644
index 0000000..336b6c0
--- /dev/null
+++ b/examples/sunlinsol/band/CMakeLists.txt
@@ -0,0 +1,171 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol band examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS band linear solver
+SET(sunlinsol_band_examples
+  "test_sunlinsol_band\;10 2 3 0\;"
+  "test_sunlinsol_band\;300 7 4 0\;"
+  "test_sunlinsol_band\;1000 8 8 0\;"
+  "test_sunlinsol_band\;5000 3 100 0\;"
+)
+
+# Dependencies for nvector examples
+SET(sunlinsol_band_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_matrix
+  sundials_linearsolver
+)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNMAT_LIB sundials_sunmatrixband_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolband_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNMAT_LIB sundials_sunmatrixband_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolband_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNMAT_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_band_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunlinsol.h
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/band)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_band_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/band)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolband")
+  SET(LIBS "${LIBS} -lsundials_sunmatrixband")
+
+  # Set the link directory for the band sunmatrix library 
+  # The generated CMakeLists.txt does not use find_library() locate it
+  SET(EXTRA_LIBS_DIR "${libdir}")
+
+  EXAMPLES2STRING(sunlinsol_band_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_band_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/band/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/band/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/band
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/band/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/band/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/band
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/band/test_sunlinsol_band.c b/examples/sunlinsol/band/test_sunlinsol_band.c
new file mode 100644
index 0000000..f5cb642
--- /dev/null
+++ b/examples/sunlinsol/band/test_sunlinsol_band.c
@@ -0,0 +1,184 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol Band module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_band.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+
+/* ----------------------------------------------------------------------
+ * SUNBandLinearSolver Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails = 0;          /* counter for test failures  */
+  sunindextype    cols, uband, lband; /* matrix columns, bandwidths */
+  SUNLinearSolver LS;                 /* solver object              */
+  SUNMatrix       A, B;               /* test matrices              */
+  N_Vector        x, y, b;            /* test vectors               */
+  int             print_timing;
+  sunindextype    j, k, kstart, kend;
+  realtype        *colj, *xdata;
+
+  /* check input and set matrix dimensions */
+  if (argc < 5){
+    printf("ERROR: FOUR (4) Inputs required: matrix cols, matrix uband, matrix lband, print timing \n");
+    return(-1);
+  }
+
+  cols = atol(argv[1]); 
+  if (cols <= 0) {
+    printf("ERROR: number of matrix columns must be a positive integer \n");
+    return(-1); 
+  }
+
+  uband = atol(argv[2]); 
+  if ((uband <= 0) || (uband >= cols)){
+    printf("ERROR: matrix upper bandwidth must be a positive integer, less than number of columns \n");
+    return(-1); 
+  }
+
+  lband = atol(argv[3]); 
+  if ((lband <= 0) || (lband >= cols)){
+    printf("ERROR: matrix lower bandwidth must be a positive integer, less than number of columns \n");
+    return(-1); 
+  }
+
+  print_timing = atoi(argv[4]);
+  SetTiming(print_timing);
+
+  printf("\nBand linear solver test: size %ld, bandwidths %ld %ld\n\n",
+         (long int) cols, (long int) uband, (long int) lband);
+
+  /* Create matrices and vectors */
+  A = SUNBandMatrix(cols, uband, lband, lband+uband);
+  B = SUNBandMatrix(cols, uband, lband, lband+uband);
+  x = N_VNew_Serial(cols);
+  y = N_VNew_Serial(cols);
+  b = N_VNew_Serial(cols);
+
+  /* Fill matrix and x vector with uniform random data in [0,1] */
+  xdata = N_VGetArrayPointer(x);
+  for (j=0; j<cols; j++) {
+    
+    /* A matrix column */
+    colj = SUNBandMatrix_Column(A, j);
+    kstart = (j<uband) ? -j : -uband;
+    kend = (j>cols-1-lband) ? cols-1-j: lband;
+    for (k=kstart; k<=kend; k++)
+      colj[k] = (realtype) rand() / (realtype) RAND_MAX;
+
+    /* x entry */
+    xdata[j] = (realtype) rand() / (realtype) RAND_MAX;
+    
+  }
+
+  /* Scale/shift matrix to ensure diagonal dominance */
+  fails += SUNMatScaleAddI( ONE/(uband+lband+1), A );
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatScaleAddI failure\n");
+    return(1);
+  }
+
+  /* copy A and x into B and y to print in case of solver failure */
+  SUNMatCopy(A, B);
+  N_VScale(ONE, x, y);
+
+  /* create right-hand side vector for linear solve */
+  fails = SUNMatMatvec(A, x, b);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatMatvec failure\n");
+    return(1);
+  }
+  
+  /* Create banded linear solver */
+  LS = SUNBandLinearSolver(x, A);
+  
+  /* Run Tests */
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSetup(LS, A, 0);
+  fails += Test_SUNLinSolSolve(LS, A, x, b, RCONST(1.0e-15), 0);
+ 
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_DIRECT, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNLinSol module failed %i tests \n \n", fails);
+    printf("\nA (original) =\n");
+    SUNBandMatrix_Print(B,stdout);
+    printf("\nA (factored) =\n");
+    SUNBandMatrix_Print(A,stdout);
+    printf("\nx (original) =\n");
+    N_VPrint_Serial(y);
+    printf("\nx (computed) =\n");
+    N_VPrint_Serial(x);
+  } else {
+    printf("SUCCESS: SUNLinSol module passed all tests \n \n");
+  }
+
+  /* Free solver, matrix and vectors */
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNMatDestroy(B);
+  N_VDestroy(x);
+  N_VDestroy(y);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, local_length;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  local_length = N_VGetLength_Serial(X);
+  
+  /* check vector data */
+  for(i=0; i < local_length; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], tol);
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_length; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, tol);
+    return(1);
+  }
+  else
+    return(0);
+}
diff --git a/examples/sunlinsol/dense/CMakeLists.txt b/examples/sunlinsol/dense/CMakeLists.txt
new file mode 100644
index 0000000..aeb3717
--- /dev/null
+++ b/examples/sunlinsol/dense/CMakeLists.txt
@@ -0,0 +1,170 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol dense examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS dense linear solver
+SET(sunlinsol_dense_examples
+  "test_sunlinsol_dense\;10 0\;"
+  "test_sunlinsol_dense\;100 0\;"
+  "test_sunlinsol_dense\;500 0\;"
+  "test_sunlinsol_dense\;1000 0\;"
+)
+
+# Dependencies for nvector examples
+SET(sunlinsol_dense_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_matrix
+  sundials_linearsolver
+)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNMAT_LIB sundials_sunmatrixdense_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsoldense_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNMAT_LIB sundials_sunmatrixdense_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsoldense_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNMAT_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_dense_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunlinsol.h
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/dense)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_dense_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/dense)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsoldense")
+  SET(LIBS "${LIBS} -lsundials_sunmatrixdense")
+
+  # Set the link directory for the dense sunmatrix library 
+  # The generated CMakeLists.txt does not use find_library() locate it
+  SET(EXTRA_LIBS_DIR "${libdir}")
+
+  EXAMPLES2STRING(sunlinsol_dense_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_dense_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/dense/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/dense/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/dense
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/dense/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/dense/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/dense
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/dense/test_sunlinsol_dense.c b/examples/sunlinsol/dense/test_sunlinsol_dense.c
new file mode 100644
index 0000000..6b53005
--- /dev/null
+++ b/examples/sunlinsol/dense/test_sunlinsol_dense.c
@@ -0,0 +1,181 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol Dense module
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_dense.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+
+/* ----------------------------------------------------------------------
+ * SUNDenseLinearSolver Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails = 0;          /* counter for test failures  */
+  sunindextype    cols, rows;         /* matrix columns, rows       */
+  SUNLinearSolver LS;                 /* solver object              */
+  SUNMatrix       A, B, I;            /* test matrices              */
+  N_Vector        x, y, b;            /* test vectors               */
+  int             print_timing;
+  sunindextype    j, k;
+  realtype        *colj, *xdata, *colIj;
+
+  /* check input and set matrix dimensions */
+  if (argc < 3){
+    printf("ERROR: TWO (2) Inputs required: matrix cols, print timing \n");
+    return(-1);
+  }
+
+  cols = atol(argv[1]); 
+  if (cols <= 0) {
+    printf("ERROR: number of matrix columns must be a positive integer \n");
+    return(-1); 
+  }
+
+  rows = cols;
+
+  print_timing = atoi(argv[2]);
+  SetTiming(print_timing);
+
+  printf("\nDense linear solver test: size %ld\n\n",
+         (long int) cols);
+
+  /* Create matrices and vectors */
+  A = SUNDenseMatrix(rows, cols);
+  B = SUNDenseMatrix(rows, cols);
+  I = SUNDenseMatrix(rows, cols);
+  x = N_VNew_Serial(cols);
+  y = N_VNew_Serial(cols);
+  b = N_VNew_Serial(cols);
+
+  /* Fill A matrix with uniform random data in [0,1/cols] */
+  for (j=0; j<cols; j++) {
+    colj = SUNDenseMatrix_Column(A, j);
+    for (k=0; k<rows; k++)
+      colj[k] = (realtype) rand() / (realtype) RAND_MAX / cols;    
+  }
+
+  /* Create anti-identity matrix */
+  j=cols-1;
+  for (k=0; k<rows; k++) {
+    colj = SUNDenseMatrix_Column(I,j);
+    colj[k] = 1;
+    j = j-1;
+  }    
+  
+  /* Add anti-identity to ensure the solver needs to do row-swapping */
+  for (k=0; k<rows; k++){
+    for(j=0; j<cols; j++){
+      colj = SUNDenseMatrix_Column(A,j);
+      colIj = SUNDenseMatrix_Column(I,j);
+      colj[k]  = colj[k] + colIj[k]; 
+   }
+  }
+
+  /* Fill x vector with uniform random data in [0,1] */
+  xdata = N_VGetArrayPointer(x);
+  for (j=0; j<cols; j++) {
+    xdata[j] = (realtype) rand() / (realtype) RAND_MAX;
+  } 
+
+  /* copy A and x into B and y to print in case of solver failure */
+  SUNMatCopy(A, B);
+  N_VScale(ONE, x, y);
+
+  /* create right-hand side vector for linear solve */
+  fails = SUNMatMatvec(A, x, b);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatMatvec failure\n");
+    return(1);
+  }
+
+  /* Create dense linear solver */
+  LS = SUNDenseLinearSolver(x, A);
+  
+  /* Run Tests */
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSetup(LS, A, 0);
+  fails += Test_SUNLinSolSolve(LS, A, x, b, RCONST(1.0e-15), 0);
+ 
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_DIRECT, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNLinSol module failed %i tests \n \n", fails);
+    printf("\nA (original) =\n");
+    SUNDenseMatrix_Print(B,stdout);
+    printf("\nA (factored) =\n");
+    SUNDenseMatrix_Print(A,stdout);
+    printf("\nx (original) =\n");
+    N_VPrint_Serial(y);
+    printf("\nx (computed) =\n");
+    N_VPrint_Serial(x);
+  } else {
+    printf("SUCCESS: SUNLinSol module passed all tests \n \n");
+  }
+
+  /* Free solver, matrix and vectors */
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNMatDestroy(B);
+  N_VDestroy(x);
+  N_VDestroy(y);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, local_length;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  local_length = N_VGetLength_Serial(X);
+  
+  /* check vector data */
+  for(i=0; i < local_length; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], tol);
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_length; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, tol);
+    return(1);
+  }
+  else
+    return(0);
+}
diff --git a/examples/sunlinsol/klu/CMakeLists.txt b/examples/sunlinsol/klu/CMakeLists.txt
new file mode 100644
index 0000000..2e2c9d6
--- /dev/null
+++ b/examples/sunlinsol/klu/CMakeLists.txt
@@ -0,0 +1,175 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol KLU examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using the KLU linear solver
+SET(sunlinsol_klu_examples
+  "test_sunlinsol_klu\;300 0 0\;"
+  "test_sunlinsol_klu\;300 1 0\;"
+  "test_sunlinsol_klu\;1000 0 0\;"
+  "test_sunlinsol_klu\;1000 1 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_klu_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_matrix
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNMAT_LIB sundials_sunmatrixdense_static)
+  LIST(APPEND SUNMAT_LIB sundials_sunmatrixsparse_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolklu_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNMAT_LIB sundials_sunmatrixdense_shared)
+  LIST(APPEND SUNMAT_LIB sundials_sunmatrixsparse_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolklu_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNMAT_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_klu_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against    
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunlinsol.h
+      ../test_sunlinsol.c 
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/klu)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_klu_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/klu)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolklu")
+  SET(LIBS "${LIBS} -lsundials_sunmatrixsparse -lsundials_sunmatrixdense")
+
+  # Set the link directory for the sparse and dense sunmatrix libraries
+  # The generated CMakeLists.txt does not use find_library() locate them
+  SET(EXTRA_LIBS_DIR "${libdir}")
+
+  EXAMPLES2STRING(sunlinsol_klu_examples EXAMPLES_KLU)
+  EXAMPLES2STRING(sunlinsol_klu_dependencies EXAMPLES_DEPENDENCIES_KLU)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/klu/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/klu/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/klu
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/klu/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/klu/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/klu
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/klu/test_sunlinsol_klu.c b/examples/sunlinsol/klu/test_sunlinsol_klu.c
new file mode 100644
index 0000000..1388131
--- /dev/null
+++ b/examples/sunlinsol/klu/test_sunlinsol_klu.c
@@ -0,0 +1,183 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol KLU module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_klu.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+
+/* ----------------------------------------------------------------------
+ * SUNKLU Linear Solver Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails = 0;          /* counter for test failures  */
+  sunindextype    N;                  /* matrix columns, rows       */
+  SUNLinearSolver LS;                 /* linear solver object       */
+  SUNMatrix       A, B;               /* test matrices              */
+  N_Vector        x, y, b;            /* test vectors               */
+  realtype        *matdata, *xdata;
+  int             mattype, print_timing;
+  sunindextype    i, j, k;
+
+  /* check input and set matrix dimensions */
+  if (argc < 4){
+    printf("ERROR: THREE (3) Inputs required: matrix size, matrix type (0/1), print timing \n");
+    return(-1);
+  }
+
+  N = atol(argv[1]); 
+  if (N <= 0) {
+    printf("ERROR: matrix size must be a positive integer \n");
+    return(-1); 
+  }
+
+  mattype = atoi(argv[2]);
+  if ((mattype != 0) && (mattype != 1)) {
+    printf("ERROR: matrix type must be 0 or 1 \n");
+    return(-1); 
+  }
+  mattype = (mattype == 0) ? CSC_MAT : CSR_MAT;
+  
+  print_timing = atoi(argv[3]);
+  SetTiming(print_timing);
+
+  printf("\nKLU linear solver test: size %ld, type %i\n\n",
+         (long int) N, mattype);
+
+  /* Create matrices and vectors */
+  B = SUNDenseMatrix(N, N);
+  x = N_VNew_Serial(N);
+  y = N_VNew_Serial(N);
+  b = N_VNew_Serial(N);
+
+  /* Fill matrix with uniform random data in [0,1/N] */
+  for (k=0; k<5*N; k++) {
+    i = rand() % N;
+    j = rand() % N;
+    matdata = SUNDenseMatrix_Column(B,j);
+    matdata[i] = (realtype) rand() / (realtype) RAND_MAX / N;
+  }
+
+  /* Add identity to matrix */
+  fails = SUNMatScaleAddI(ONE, B);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatScaleAddI failure\n");
+    return(1);
+  }
+
+  /* Fill x vector with uniform random data in [0,1] */
+  xdata = N_VGetArrayPointer(x);
+  for (i=0; i<N; i++)
+    xdata[i] = (realtype) rand() / (realtype) RAND_MAX;
+
+  /* Create sparse matrix from dense, and destroy B */
+  A = SUNSparseFromDenseMatrix(B, ZERO, mattype);
+  SUNMatDestroy(B);
+
+  /* copy x into y to print in case of solver failure */
+  N_VScale(ONE, x, y);
+
+  /* create right-hand side vector for linear solve */
+  fails = SUNMatMatvec(A, x, b);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatMatvec failure\n");
+    return(1);
+  }
+  
+  /* Create KLU linear solver */
+  LS = SUNKLU(x, A);
+  
+  /* Run Tests */
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSetup(LS, A, 0);
+  fails += Test_SUNLinSolSolve(LS, A, x, b, RCONST(1.0e-13), 0);
+ 
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_DIRECT, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNLinSol module failed %i tests \n \n", fails);
+    printf("\nA =\n");
+    SUNSparseMatrix_Print(A,stdout);
+    printf("\nx (original) =\n");
+    N_VPrint_Serial(y);
+    printf("\nb =\n");
+    N_VPrint_Serial(b);
+    printf("\nx (computed) =\n");
+    N_VPrint_Serial(x);
+  } else {
+    printf("SUCCESS: SUNLinSol module passed all tests \n \n");
+  }
+
+  /* Free solver, matrix and vectors */
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(x);
+  N_VDestroy(y);
+  N_VDestroy(b);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, local_length, maxloc;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  local_length = N_VGetLength_Serial(X);
+  
+  /* check vector data */
+  for(i=0; i < local_length; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], tol);
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    maxloc = -1;
+    for(i=0; i < local_length; i++) {
+      if (SUNRabs(Xdata[i]-Ydata[i]) >  maxerr) {
+        maxerr = SUNRabs(Xdata[i]-Ydata[i]);
+        maxloc = i;
+      }
+    }
+    printf("check err failure: maxerr = %g at loc %li (tol = %g)\n",
+	   maxerr, (long int) maxloc, tol);
+    return(1);
+  }
+  else
+    return(0);
+}
diff --git a/examples/sunlinsol/lapackband/CMakeLists.txt b/examples/sunlinsol/lapackband/CMakeLists.txt
new file mode 100644
index 0000000..823a984
--- /dev/null
+++ b/examples/sunlinsol/lapackband/CMakeLists.txt
@@ -0,0 +1,177 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol LAPACK band examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using the LAPACK band linear solver
+SET(sunlinsol_lapackband_examples
+  "test_sunlinsol_lapackband\;10 2 3 0\;"
+  "test_sunlinsol_lapackband\;300 7 4 0\;"
+  "test_sunlinsol_lapackband\;1000 8 8 0\;"
+  "test_sunlinsol_lapackband\;5000 3 100 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_lapackband_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_matrix
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNMAT_LIB sundials_sunmatrixband_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsollapackband_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNMAT_LIB sundials_sunmatrixband_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsollapackband_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNMAT_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
+
+IF(BLAS_FOUND)
+  LIST(APPEND SUNDIALS_LIBS ${BLAS_LIBRARIES})
+ENDIF(BLAS_FOUND)
+
+
+# Add the build and install targets for each sunlinsol example
+FOREACH(example_tuple ${sunlinsol_lapackband_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c)
+    
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunlinsol.h
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackband)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_lapackband_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackband)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsollapackband")
+  SET(LIBS "${LIBS} -lsundials_sunmatrixband -lsundials_sunmatrixdense")
+
+  # Set the link directory for the band and dense sunmatrix libraries
+  # The generated CMakeLists.txt does not use find_library() locate them
+  SET(EXTRA_LIBS_DIR "${libdir}")
+
+  EXAMPLES2STRING(sunlinsol_lapackband_examples EXAMPLES_BL)
+  EXAMPLES2STRING(sunlinsol_lapackband_dependencies EXAMPLES_DEPENDENCIES_BL)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackband/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackband/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackband
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackband/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackband/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackband
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/lapackband/test_sunlinsol_lapackband.c b/examples/sunlinsol/lapackband/test_sunlinsol_lapackband.c
new file mode 100644
index 0000000..66ac890
--- /dev/null
+++ b/examples/sunlinsol/lapackband/test_sunlinsol_lapackband.c
@@ -0,0 +1,184 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol LapackBand 
+ * module implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_lapackband.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+
+/* ----------------------------------------------------------------------
+ * SUNLapackBand Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails = 0;          /* counter for test failures  */
+  sunindextype    cols, uband, lband; /* matrix columns, bandwidths */
+  SUNLinearSolver LS;                 /* solver object              */
+  SUNMatrix       A, B;               /* test matrices              */
+  N_Vector        x, y, b;            /* test vectors               */
+  int             print_timing;
+  sunindextype    j, k, kstart, kend;
+  realtype        *colj, *xdata;
+
+  /* check input and set matrix dimensions */
+  if (argc < 5){
+    printf("ERROR: FOUR (4) Inputs required: matrix cols, matrix uband, matrix lband, print timing \n");
+    return(-1);
+  }
+
+  cols = atol(argv[1]); 
+  if (cols <= 0) {
+    printf("ERROR: number of matrix columns must be a positive integer \n");
+    return(-1); 
+  }
+
+  uband = atol(argv[2]); 
+  if ((uband <= 0) || (uband >= cols)){
+    printf("ERROR: matrix upper bandwidth must be a positive integer, less than number of columns \n");
+    return(-1); 
+  }
+
+  lband = atol(argv[3]); 
+  if ((lband <= 0) || (lband >= cols)){
+    printf("ERROR: matrix lower bandwidth must be a positive integer, less than number of columns \n");
+    return(-1); 
+  }
+
+  print_timing = atoi(argv[4]);
+  SetTiming(print_timing);
+
+  printf("\nLapackBand linear solver test: size %ld, bandwidths %ld %ld\n\n",
+         (long int) cols, (long int) uband, (long int) lband);
+
+  /* Create matrices and vectors */
+  A = SUNBandMatrix(cols, uband, lband, lband+uband);
+  B = SUNBandMatrix(cols, uband, lband, lband+uband);
+  x = N_VNew_Serial(cols);
+  y = N_VNew_Serial(cols);
+  b = N_VNew_Serial(cols);
+
+  /* Fill matrix and x vector with uniform random data in [0,1] */
+  xdata = N_VGetArrayPointer(x);
+  for (j=0; j<cols; j++) {
+    
+    /* A matrix column */
+    colj = SUNBandMatrix_Column(A, j);
+    kstart = (j<uband) ? -j : -uband;
+    kend = (j>cols-1-lband) ? cols-1-j: lband;
+    for (k=kstart; k<=kend; k++)
+      colj[k] = (realtype) rand() / (realtype) RAND_MAX;
+
+    /* x entry */
+    xdata[j] = (realtype) rand() / (realtype) RAND_MAX;
+    
+  }
+
+  /* Scale/shift matrix to ensure diagonal dominance */
+  fails = SUNMatScaleAddI( ONE/(uband+lband+1), A );
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatScaleAddI failure\n");
+    return(1);
+  }
+
+  /* copy A and x into B and y to print in case of solver failure */
+  SUNMatCopy(A, B);
+  N_VScale(ONE, x, y);
+
+  /* create right-hand side vector for linear solve */
+  fails = SUNMatMatvec(A, x, b);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatMatvec failure\n");
+    return(1);
+  }
+  
+  /* Create banded linear solver */
+  LS = SUNLapackBand(x, A);
+  
+  /* Run Tests */
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSetup(LS, A, 0);
+  fails += Test_SUNLinSolSolve(LS, A, x, b, RCONST(1.0e-15), 0);
+ 
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_DIRECT, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNLinSol module failed %i tests \n \n", fails);
+    printf("\nA (original) =\n");
+    SUNBandMatrix_Print(B,stdout);
+    printf("\nA (factored) =\n");
+    SUNBandMatrix_Print(A,stdout);
+    printf("\nx (original) =\n");
+    N_VPrint_Serial(y);
+    printf("\nx (computed) =\n");
+    N_VPrint_Serial(x);
+  } else {
+    printf("SUCCESS: SUNLinSol module passed all tests \n \n");
+  }
+
+  /* Free solver, matrix and vectors */
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNMatDestroy(B);
+  N_VDestroy(x);
+  N_VDestroy(y);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, local_length;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  local_length = N_VGetLength_Serial(X);
+  
+  /* check vector data */
+  for(i=0; i < local_length; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], tol);
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_length; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, tol);
+    return(1);
+  }
+  else
+    return(0);
+}
diff --git a/examples/sunlinsol/lapackdense/CMakeLists.txt b/examples/sunlinsol/lapackdense/CMakeLists.txt
new file mode 100644
index 0000000..12e73a5
--- /dev/null
+++ b/examples/sunlinsol/lapackdense/CMakeLists.txt
@@ -0,0 +1,177 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol LAPACK dense examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using the LAPACK dense linear solver
+SET(sunlinsol_lapackdense_examples
+  "test_sunlinsol_lapackdense\;10 0\;"
+  "test_sunlinsol_lapackdense\;100 0\;"
+  "test_sunlinsol_lapackdense\;500 0\;"
+  "test_sunlinsol_lapackdense\;1000 0\;"
+)
+
+# Dependencies for nvector examples
+SET(sunlinsol_lapackdense_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_matrix
+  sundials_linearsolver
+)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNMAT_LIB sundials_sunmatrixdense_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsollapackdense_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNMAT_LIB sundials_sunmatrixdense_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsollapackdense_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNMAT_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
+
+IF(BLAS_FOUND)
+  LIST(APPEND SUNDIALS_LIBS ${BLAS_LIBRARIES})
+ENDIF(BLAS_FOUND)
+
+
+# Add the build and install targets for each sunlinsol example
+FOREACH(example_tuple ${sunlinsol_lapackdense_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunlinsol.h
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackdense)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_lapackdense_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackdense)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsollapackdense")
+  SET(LIBS "${LIBS} -lsundials_sunmatrixdense -lsundials_sunmatrixband")
+
+  # Set the link directory for the dense and band sunmatrix libraries
+  # The generated CMakeLists.txt does not use find_library() locate them
+  SET(EXTRA_LIBS_DIR "${libdir}")
+
+  EXAMPLES2STRING(sunlinsol_lapackdense_examples EXAMPLES_BL)
+  EXAMPLES2STRING(sunlinsol_lapackdense_dependencies EXAMPLES_DEPENDENCIES_BL)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackdense/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackdense/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackdense
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackdense/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/lapackdense/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/lapackdense
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/lapackdense/test_sunlinsol_lapackdense.c b/examples/sunlinsol/lapackdense/test_sunlinsol_lapackdense.c
new file mode 100644
index 0000000..b6ee5fa
--- /dev/null
+++ b/examples/sunlinsol/lapackdense/test_sunlinsol_lapackdense.c
@@ -0,0 +1,181 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol LapackDense
+ * module implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_lapackdense.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+
+/* ----------------------------------------------------------------------
+ * SUNDenseLinearSolver Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails = 0;          /* counter for test failures  */
+  sunindextype    cols, rows;         /* matrix columns, rows       */
+  SUNLinearSolver LS;                 /* solver object              */
+  SUNMatrix       A, B, I;            /* test matrices              */
+  N_Vector        x, y, b;            /* test vectors               */
+  int             print_timing;
+  sunindextype    j, k;
+  realtype        *colj, *xdata, *colIj;
+
+  /* check input and set matrix dimensions */
+  if (argc < 3){
+    printf("ERROR: TWO (2) Inputs required: matrix cols, print timing \n");
+    return(-1);
+  }
+
+  cols = atol(argv[1]); 
+  if (cols <= 0) {
+    printf("ERROR: number of matrix columns must be a positive integer \n");
+    return(-1); 
+  }
+
+  rows = cols;
+
+  print_timing = atoi(argv[2]);
+  SetTiming(print_timing);
+
+  printf("\nLapackDense linear solver test: size %ld\n\n",
+         (long int) cols);
+
+  /* Create matrices and vectors */
+  A = SUNDenseMatrix(rows, cols);
+  B = SUNDenseMatrix(rows, cols);
+  I = SUNDenseMatrix(rows, cols);
+  x = N_VNew_Serial(cols);
+  y = N_VNew_Serial(cols);
+  b = N_VNew_Serial(cols);
+
+  /* Fill A matrix with uniform random data in [0,1/cols] */
+  for (j=0; j<cols; j++) {
+    colj = SUNDenseMatrix_Column(A, j);
+    for (k=0; k<rows; k++)
+      colj[k] = (realtype) rand() / (realtype) RAND_MAX / cols;    
+  }
+
+  /* Create anti-identity matrix */
+  j=cols-1;
+  for (k=0; k<rows; k++) {
+    colj = SUNDenseMatrix_Column(I,j);
+    colj[k] = 1;
+    j = j-1;
+  }    
+  
+  /* Add anti-identity to ensure the solver needs to do row-swapping */
+  for (k=0; k<rows; k++){
+    for(j=0; j<cols; j++){
+      colj = SUNDenseMatrix_Column(A,j);
+      colIj = SUNDenseMatrix_Column(I,j);
+      colj[k]  = colj[k] + colIj[k]; 
+   }
+  }
+
+  /* Fill x vector with uniform random data in [0,1] */
+  xdata = N_VGetArrayPointer(x);
+  for (j=0; j<cols; j++) {
+    xdata[j] = (realtype) rand() / (realtype) RAND_MAX;
+  } 
+
+  /* copy A and x into B and y to print in case of solver failure */
+  SUNMatCopy(A, B);
+  N_VScale(ONE, x, y);
+
+  /* create right-hand side vector for linear solve */
+  fails = SUNMatMatvec(A, x, b);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatMatvec failure\n");
+    return(1);
+  }
+
+  /* Create dense linear solver */
+  LS = SUNLapackDense(x, A);
+  
+  /* Run Tests */
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSetup(LS, A, 0);
+  fails += Test_SUNLinSolSolve(LS, A, x, b, RCONST(1.0e-15), 0);
+ 
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_DIRECT, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNLinSol module failed %i tests \n \n", fails);
+    printf("\nA (original) =\n");
+    SUNDenseMatrix_Print(B,stdout);
+    printf("\nA (factored) =\n");
+    SUNDenseMatrix_Print(A,stdout);
+    printf("\nx (original) =\n");
+    N_VPrint_Serial(y);
+    printf("\nx (computed) =\n");
+    N_VPrint_Serial(x);
+  } else {
+    printf("SUCCESS: SUNLinSol module passed all tests \n \n");
+  }
+
+  /* Free solver, matrix and vectors */
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  SUNMatDestroy(B);
+  N_VDestroy(x);
+  N_VDestroy(y);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, local_length;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  local_length = N_VGetLength_Serial(X);
+  
+  /* check vector data */
+  for(i=0; i < local_length; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], tol);
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_length; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, tol);
+    return(1);
+  }
+  else
+    return(0);
+}
diff --git a/examples/sunlinsol/pcg/serial/CMakeLists.txt b/examples/sunlinsol/pcg/serial/CMakeLists.txt
new file mode 100644
index 0000000..9801e9d
--- /dev/null
+++ b/examples/sunlinsol/pcg/serial/CMakeLists.txt
@@ -0,0 +1,158 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol PCG examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS PCG linear solver
+SET(sunlinsol_pcg_examples
+  "test_sunlinsol_pcg_serial\;100 200 1e-13 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_pcg_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolpcg_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolpcg_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_pcg_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/pcg/serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_pcg_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/pcg/serial)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolpcg")
+
+  EXAMPLES2STRING(sunlinsol_pcg_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_pcg_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/pcg/serial/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/pcg/serial/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/pcg/serial
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/pcg/serial/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/pcg/serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/pcg/serial
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/pcg/serial/test_sunlinsol_pcg_serial.c b/examples/sunlinsol/pcg/serial/test_sunlinsol_pcg_serial.c
new file mode 100644
index 0000000..98dbc8a
--- /dev/null
+++ b/examples/sunlinsol/pcg/serial/test_sunlinsol_pcg_serial.c
@@ -0,0 +1,444 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol PCG module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_pcg.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype N; /* problem size */
+  N_Vector d;     /* matrix diagonal */
+  N_Vector s;     /* scaling vector supplied to PCG */
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of the problem size (for check_vector routine) */
+sunindextype problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNOCG Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution 
+ *       xhat, and a corresponding rhs vector bhat = Ahat*xhat, such 
+ *       that each of these is unit-less.  To test scaling, we use 
+ *       the matrix 
+ *             A = (S-inverse) Ahat (S-inverse), 
+ *       solution vector 
+ *             x = S xhat; 
+ *       and construct b = A*x.  Hence the linear system has both rows 
+ *       and columns scaled by (S-inverse), where S is the diagonal 
+ *       matrix with entries from the vector s, the 'scaling' vector 
+ *       supplied to PCG having strictly positive entries.  
+ *
+ *       When this is combined with preconditioning, we construct 
+ *       P \approx (A-inverse) by taking a unit-less preconditioner 
+ *       Phat \approx (Ahat-inverse), and constructing the operator
+ *       P via
+ *             P = S Phat S \approx S (Ahat-inverse) S = A-inverse
+ *       We apply this via the steps:
+ *             z = Pr = S Phat S r
+ *       Since both S and Phat are diagonal matrices, this is 
+ *       equivalent to
+ *             z(i) = s(i)^2 Phat(i) r(i)
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 5) {
+    printf("ERROR: FOUR (4) Inputs required:\n");
+    printf("  Problem size should be >0\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.N = atol(argv[1]);
+  problem_size = ProbData.N;
+  if (ProbData.N <= 0) {
+    printf("ERROR: Problem size must be a positive integer\n");
+    return 1; 
+  }
+  maxl = atoi(argv[2]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[3]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[4]);
+  SetTiming(print_timing);
+
+  printf("\nPCG linear solver test:\n");
+  printf("  Problem size = %ld\n", (long int) ProbData.N);
+  printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+  printf("  Solver Tolerance = %"GSYM"\n", tol);
+  printf("  timing output flag = %i\n\n", print_timing);
+  
+  /* Create vectors */
+  x = N_VNew_Serial(ProbData.N);
+  if (check_flag(x, "N_VNew_Serial", 0)) return 1;
+  xhat = N_VNew_Serial(ProbData.N);
+  if (check_flag(xhat, "N_VNew_Serial", 0)) return 1;
+  b = N_VNew_Serial(ProbData.N);
+  if (check_flag(b, "N_VNew_Serial", 0)) return 1;
+  ProbData.d = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.d, "N_VNew_Serial", 0)) return 1;
+  ProbData.s = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s, "N_VNew_Serial", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.N; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create PCG linear solver */
+  LS = SUNPCG(x, PREC_RIGHT, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE, 0);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, 0);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup, PSolve, 0);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s, NULL, 0);
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+  if (fails) {
+    printf("FAIL: SUNPCG module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else {
+    printf("SUCCESS: SUNPCG module passed all initialization tests\n\n");
+  }
+
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vector */
+  N_VConst(ONE, ProbData.s);
+
+  /* Fill x vector with scaled version */
+  N_VProd(xhat, ProbData.s, x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run test with this setup */
+  fails += SUNPCGSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNPCG module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNPCG module, problem 1, passed all tests\n\n");
+  }
+
+  
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vector */
+  N_VConst(ONE, ProbData.s);
+
+  /* Fill x vector with scaled version */
+  N_VProd(xhat, ProbData.s, x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNPCGSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNPCG module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNPCG module, problem 2, passed all tests\n\n");
+  }
+
+  
+  /*** Test 3: Poisson-like solve w/ scaling (no preconditioning) ***/
+
+  /* set scaling vector */
+  vecdata = N_VGetArrayPointer(ProbData.s);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VProd(xhat, ProbData.s, x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNPCGSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNPCG module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNPCG module, problem 3, passed all tests\n\n");
+  }
+
+  
+  /*** Test 4: Poisson-like solve w/ scaling (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VProd(xhat, ProbData.s, x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNPCGSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) { 
+    printf("FAIL: SUNPCG module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNPCG module, problem 4, passed all tests\n\n");
+  }
+
+  
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s);
+
+  return(passfail);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s;
+  sunindextype i, N;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s = N_VGetArrayPointer(ProbData->s);
+  if (check_flag(s, "N_VGetArrayPointer", 0)) return 1;
+  N = ProbData->N;  
+
+  /* perform product at left boundary (note: v is zero at the boundary)*/
+  z[0] = (FIVE*v[0]/s[0] - v[1]/s[1])/s[0];
+
+  /* iterate through interior of domain, performing product */
+  for (i=1; i<N-1; i++) 
+    z[i] = (-v[i-1]/s[i-1] + FIVE*v[i]/s[i] - v[i+1]/s[i+1])/s[i];
+
+  /* perform product at right boundary (note: v is zero at the boundary)*/  
+  z[N-1] = (-v[N-2]/s[N-2] + FIVE*v[N-1]/s[N-1])/s[N-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d, *s;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  s = N_VGetArrayPointer(ProbData->s);
+  if (check_flag(s, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->N; i++) 
+    z[i] = s[i] * s[i] * r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int      failure = 0;
+  long int i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
diff --git a/examples/sunlinsol/spbcgs/parallel/CMakeLists.txt b/examples/sunlinsol/spbcgs/parallel/CMakeLists.txt
new file mode 100644
index 0000000..0855980
--- /dev/null
+++ b/examples/sunlinsol/spbcgs/parallel/CMakeLists.txt
@@ -0,0 +1,174 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPBCGS parallel examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
+
+# Examples using the SUNDIALS SPBCGS linear solver
+SET(sunlinsol_spbcgs_examples
+  "test_sunlinsol_spbcgs_parallel\;100 1 50 1e-3 0\;1\;4\;"
+  "test_sunlinsol_spbcgs_parallel\;100 2 50 1e-3 0\;1\;4\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_spbcgs_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecparallel_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspbcgs_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecparallel_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspbcgs_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+IF(MPI_MPICC)
+  # use MPI_MPICC as the compiler
+  SET(CMAKE_C_COMPILER ${MPI_MPICC})
+ELSE(MPI_MPICC)
+  # add MPI_INCLUDE_PATH to include directories
+  INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_spbcgs_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/parallel)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_spbcgs_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/parallel)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolspbcgs")
+
+  EXAMPLES2STRING(sunlinsol_spbcgs_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_spbcgs_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/parallel/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/parallel/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/parallel
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_parallel_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/parallel/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/parallel/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/parallel
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/spbcgs/parallel/test_sunlinsol_spbcgs_parallel.c b/examples/sunlinsol/spbcgs/parallel/test_sunlinsol_spbcgs_parallel.c
new file mode 100644
index 0000000..b8cc975
--- /dev/null
+++ b/examples/sunlinsol/spbcgs/parallel/test_sunlinsol_spbcgs_parallel.c
@@ -0,0 +1,590 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPBCGS module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_spbcgs.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+#include "mpi.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype Nloc;  /* local problem size */
+  N_Vector d;         /* matrix diagonal */
+  N_Vector s1;        /* scaling vectors supplied to SPBCGS */
+  N_Vector s2;
+  MPI_Comm comm;      /* communicator object */
+  int myid;           /* MPI process ID */
+  int nprocs;         /* total number of MPI processes */
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of Nloc (for check_vector routine) */
+sunindextype local_problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPBCGS Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPBCGS 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0 ;      /* overall pass/fail flag    */
+  int             mpierr;           /* mpi error flag            */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             pretype, maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* Set up MPI environment */
+  fails = MPI_Init(&argc, &argv);
+  if (check_flag(&fails, "MPI_Init", 1)) return 1;
+  ProbData.comm = MPI_COMM_WORLD;
+  fails = MPI_Comm_size(ProbData.comm, &(ProbData.nprocs));
+  if (check_flag(&fails, "MPI_Comm_size", 1)) return 1;
+  fails = MPI_Comm_rank(ProbData.comm, &(ProbData.myid));
+  if (check_flag(&fails, "MPI_Comm_rank", 1)) return 1;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 6) {
+    printf("ERROR: FIVE (5) Inputs required:\n");
+    printf("  Local problem size should be >0\n");
+    printf("  Preconditioning type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.Nloc = atol(argv[1]);
+  local_problem_size = ProbData.Nloc;
+  if (ProbData.Nloc <= 0) {
+    printf("ERROR: local problem size must be a positive integer\n");
+    return 1; 
+  }
+  pretype = atoi(argv[2]);
+  if ((pretype < 1) || (pretype > 2)) {
+    printf("ERROR: Preconditioning type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[3]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[4]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[5]);
+  SetTiming(print_timing);
+
+  if (ProbData.myid == 0) {
+    printf("\nSPBCGS linear solver test:\n");
+    printf("  nprocs = %i\n", ProbData.nprocs);
+    printf("  local/global problem sizes = %ld/%ld\n", (long int) ProbData.Nloc,
+           (long int) (ProbData.nprocs * ProbData.Nloc));
+    printf("  Preconditioning type = %i\n", pretype);
+    printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+    printf("  Solver Tolerance = %"GSYM"\n", tol);
+    printf("  timing output flag = %i\n\n", print_timing);
+  }
+  
+  /* Create vectors */
+  x = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                      ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(x, "N_VNew_Parallel", 0)) return 1;
+  xhat = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                         ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(xhat, "N_VNew_Parallel", 0)) return 1;
+  b = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                      ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(b, "N_VNew_Parallel", 0)) return 1;
+  ProbData.d = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                               ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.d, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s1 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s1, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s2 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s2, "N_VNew_Parallel", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.Nloc; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPBCGS linear solver */
+  LS = SUNSPBCGS(x, pretype, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE,
+                                 ProbData.myid);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, ProbData.myid);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup,
+                                           PSolve, ProbData.myid);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2,
+                                           ProbData.myid);
+  fails += Test_SUNLinSolInitialize(LS, ProbData.myid);
+  fails += Test_SUNLinSolSpace(LS, ProbData.myid);
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else if (ProbData.myid == 0)
+    printf("SUCCESS: SUNSPBCGS module passed all initialization tests\n\n");
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPBCGS module, problem 1, passed all tests\n\n");
+  }
+
+  
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPBCGS module, problem 2, passed all tests\n\n");
+  }
+
+  
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPBCGS module, problem 3, passed all tests\n\n");
+  }
+
+  
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPBCGS module, problem 4, passed all tests\n\n");
+  }
+
+  
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPBCGS module, problem 5, passed all tests\n\n");
+  }
+
+  
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPBCGS module, problem 6, passed all tests\n\n");
+  }
+
+  /* check if any other process failed */
+  mpierr = MPI_Allreduce(&passfail, &fails, 1, MPI_INT, MPI_MAX, ProbData.comm);
+  
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  MPI_Finalize();
+  return(fails);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2, vL, vR, vsL, vsR;
+  sunindextype i, Nloc;
+  int ierr;
+  UserData *ProbData;
+  MPI_Request SendReqL, SendReqR, RecvReqL, RecvReqR;
+  MPI_Status stat;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  Nloc = ProbData->Nloc;
+  
+  /* MPI equivalent of realtype type */
+  #if defined(SUNDIALS_SINGLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_FLOAT
+  #elif defined(SUNDIALS_DOUBLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_DOUBLE
+  #elif defined(SUNDIALS_EXTENDED_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_LONG_DOUBLE
+  #endif
+  
+  /* send/recv boundary data with neighbors */
+  vL = vR = ZERO;
+  vsL = v[0]*s2[0];
+  vsR = v[Nloc-1]*s2[Nloc-1];
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Irecv(&vL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     0, ProbData->comm, &SendReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Irecv(&vR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     1, ProbData->comm, &SendReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+    
+  
+  /* iterate through interior of local domain, performing product */
+  for (i=1; i<Nloc-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* wait on neighbor data to arrive */
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Wait(&RecvReqL, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Wait(&RecvReqR, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  
+  /* perform product at subdomain boundaries (note: vL/vR are zero at boundary)*/
+  z[0] = (-vL + FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];
+  z[Nloc-1] = (-v[Nloc-2]*s2[Nloc-2] + FIVE*v[Nloc-1]*s2[Nloc-1] - vR)/s1[Nloc-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->Nloc; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<local_problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/spbcgs/serial/CMakeLists.txt b/examples/sunlinsol/spbcgs/serial/CMakeLists.txt
new file mode 100644
index 0000000..f03c643
--- /dev/null
+++ b/examples/sunlinsol/spbcgs/serial/CMakeLists.txt
@@ -0,0 +1,159 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPBCGS examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS SPBCGS linear solver
+SET(sunlinsol_spbcgs_examples
+  "test_sunlinsol_spbcgs_serial\;100 1 100 1e-13 0\;"
+  "test_sunlinsol_spbcgs_serial\;100 2 100 1e-13 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_spbcgs_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspbcgs_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspbcgs_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_spbcgs_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_spbcgs_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/serial)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolspbcgs")
+
+  EXAMPLES2STRING(sunlinsol_spbcgs_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_spbcgs_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/serial/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/serial/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/serial
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/serial/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spbcgs/serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spbcgs/serial
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/spbcgs/serial/test_sunlinsol_spbcgs_serial.c b/examples/sunlinsol/spbcgs/serial/test_sunlinsol_spbcgs_serial.c
new file mode 100644
index 0000000..bc31ac9
--- /dev/null
+++ b/examples/sunlinsol/spbcgs/serial/test_sunlinsol_spbcgs_serial.c
@@ -0,0 +1,519 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPBCGS module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_spbcgs.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype N; /* problem size */
+  N_Vector d;     /* matrix diagonal */
+  N_Vector s1;    /* scaling vectors supplied to SPBCGS */
+  N_Vector s2;
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of the problem size (for check_vector routine) */
+sunindextype problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPBCGS Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPBCGS 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             pretype, maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 6) {
+    printf("ERROR: FIVE (5) Inputs required:\n");
+    printf("  Problem size should be >0\n");
+    printf("  Preconditioning type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.N = atol(argv[1]);
+  problem_size = ProbData.N;
+  if (ProbData.N <= 0) {
+    printf("ERROR: Problem size must be a positive integer\n");
+    return 1; 
+  }
+  pretype = atoi(argv[2]);
+  if ((pretype < 1) || (pretype > 2)) {
+    printf("ERROR: Preconditioning type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[3]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[4]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[5]);
+  SetTiming(print_timing);
+
+  printf("\nSPBCGS linear solver test:\n");
+  printf("  problem size = %ld\n", (long int) ProbData.N);
+  printf("  Preconditioning type = %i\n", pretype);
+  printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+  printf("  Solver Tolerance = %"GSYM"\n", tol);
+  printf("  timing output flag = %i\n\n", print_timing);
+  
+  /* Create vectors */
+  x = N_VNew_Serial(ProbData.N);
+  if (check_flag(x, "N_VNew_Serial", 0)) return 1;
+  xhat = N_VNew_Serial(ProbData.N);
+  if (check_flag(xhat, "N_VNew_Serial", 0)) return 1;
+  b = N_VNew_Serial(ProbData.N);
+  if (check_flag(b, "N_VNew_Serial", 0)) return 1;
+  ProbData.d = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.d, "N_VNew_Serial", 0)) return 1;
+  ProbData.s1 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s1, "N_VNew_Serial", 0)) return 1;
+  ProbData.s2 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s2, "N_VNew_Serial", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.N; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPBCGS linear solver */
+  LS = SUNSPBCGS(x, pretype, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE, 0);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, 0);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup, PSolve, 0);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2, 0);
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else {
+    printf("SUCCESS: SUNSPBCGS module passed all initialization tests\n\n");
+  }
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPBCGS module, problem 1, passed all tests\n\n");
+  }
+
+  
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPBCGS module, problem 2, passed all tests\n\n");
+  }
+
+  
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPBCGS module, problem 3, passed all tests\n\n");
+  }
+
+  
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPBCGS module, problem 4, passed all tests\n\n");
+  }
+
+  
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) { 
+    printf("FAIL: SUNSPBCGS module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPBCGS module, problem 5, passed all tests\n\n");
+  }
+
+
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPBCGSSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPBCGS module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPBCGS module, problem 6, passed all tests\n\n");
+  }
+
+
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  return(passfail);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2;
+  sunindextype i, N;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  N = ProbData->N;
+    
+  /* perform product at left domain bounday (note: v is zero at the boundary)*/
+  z[0] = (FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];
+  
+  /* iterate through interior of the domain, performing product */
+  for (i=1; i<N-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* perform product at right domain boundary boundary (note: v is zero at the boundary)*/  
+  z[N-1] = (-v[N-2]*s2[N-2] + FIVE*v[N-1]*s2[N-1])/s1[N-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->N; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/spfgmr/parallel/CMakeLists.txt b/examples/sunlinsol/spfgmr/parallel/CMakeLists.txt
new file mode 100644
index 0000000..7d86b7f
--- /dev/null
+++ b/examples/sunlinsol/spfgmr/parallel/CMakeLists.txt
@@ -0,0 +1,174 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPFGMR parallel examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
+
+# Examples using the SUNDIALS SPTFQMR linear solver
+SET(sunlinsol_spfgmr_examples
+  "test_sunlinsol_spfgmr_parallel\;100 1 50 1e-3 0\;1\;4\;"
+  "test_sunlinsol_spfgmr_parallel\;100 2 50 1e-3 0\;1\;4\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_spfgmr_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecparallel_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspfgmr_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecparallel_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspfgmr_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+IF(MPI_MPICC)
+  # use MPI_MPICC as the compiler
+  SET(CMAKE_C_COMPILER ${MPI_MPICC})
+ELSE(MPI_MPICC)
+  # add MPI_INCLUDE_PATH to include directories
+  INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_spfgmr_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # add example to regression tests
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/parallel)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_spfgmr_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/parallel)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolspfgmr")
+
+  EXAMPLES2STRING(sunlinsol_spfgmr_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_spfgmr_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/parallel/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/parallel/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/parallel
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_parallel_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/parallel/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/parallel/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/parallel
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/spfgmr/parallel/test_sunlinsol_spfgmr_parallel.c b/examples/sunlinsol/spfgmr/parallel/test_sunlinsol_spfgmr_parallel.c
new file mode 100644
index 0000000..8647997
--- /dev/null
+++ b/examples/sunlinsol/spfgmr/parallel/test_sunlinsol_spfgmr_parallel.c
@@ -0,0 +1,593 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPFGMR module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_spfgmr.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+#include "mpi.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype Nloc;  /* local problem size */
+  N_Vector d;         /* matrix diagonal */
+  N_Vector s1;        /* scaling vectors supplied to SPFGMR */
+  N_Vector s2;
+  MPI_Comm comm;      /* communicator object */
+  int myid;           /* MPI process ID */
+  int nprocs;         /* total number of MPI processes */
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of Nloc (for check_vector routine) */
+sunindextype local_problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPFGMR Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPFGMR 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ *       Here we use a diagonal preconditioner D, so the S*-inverse 
+ *       and S* in the product cancel one another.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  int             mpierr;           /* mpi error flag            */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             gstype, maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* Set up MPI environment */
+  fails = MPI_Init(&argc, &argv);
+  if (check_flag(&fails, "MPI_Init", 1)) return 1;
+  ProbData.comm = MPI_COMM_WORLD;
+  fails = MPI_Comm_size(ProbData.comm, &(ProbData.nprocs));
+  if (check_flag(&fails, "MPI_Comm_size", 1)) return 1;
+  fails = MPI_Comm_rank(ProbData.comm, &(ProbData.myid));
+  if (check_flag(&fails, "MPI_Comm_rank", 1)) return 1;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 6) {
+    printf("ERROR: FIVE (5) Inputs required:\n");
+    printf("  Local problem size should be >0\n");
+    printf("  Gram-Schmidt orthogonalization type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.Nloc = atol(argv[1]);
+  local_problem_size = ProbData.Nloc;
+  if (ProbData.Nloc <= 0) {
+    printf("ERROR: local problem size must be a positive integer\n");
+    return 1; 
+  }
+  gstype = atoi(argv[2]);
+  if ((gstype < 1) || (gstype > 2)) {
+    printf("ERROR: Gram-Schmidt orthogonalization type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[3]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[4]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[5]);
+  SetTiming(print_timing);
+
+  if (ProbData.myid == 0) {
+    printf("\nSPFGMR linear solver test:\n");
+    printf("  nprocs = %i\n", ProbData.nprocs);
+    printf("  local/global problem sizes = %ld/%ld\n", (long int) ProbData.Nloc,
+           (long int) (ProbData.nprocs * ProbData.Nloc));
+    printf("  Gram-Schmidt orthogonalization type = %i\n", gstype);
+    printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+    printf("  Solver Tolerance = %"GSYM"\n", tol);
+    printf("  timing output flag = %i\n\n", print_timing);
+  }
+  
+  /* Create vectors */
+  x = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                      ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(x, "N_VNew_Parallel", 0)) return 1;
+  xhat = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                         ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(xhat, "N_VNew_Parallel", 0)) return 1;
+  b = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                      ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(b, "N_VNew_Parallel", 0)) return 1;
+  ProbData.d = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                               ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.d, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s1 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s1, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s2 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s2, "N_VNew_Parallel", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.Nloc; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPFGMR linear solver */
+  LS = SUNSPFGMR(x, PREC_RIGHT, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE,
+                                 ProbData.myid);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, ProbData.myid);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup,
+                                           PSolve, ProbData.myid);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2,
+                                           ProbData.myid);
+  fails += Test_SUNLinSolInitialize(LS, ProbData.myid);
+  fails += Test_SUNLinSolSpace(LS, ProbData.myid);
+  fails += SUNSPFGMRSetGSType(LS, gstype);  
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else if (ProbData.myid == 0)
+    printf("SUCCESS: SUNSPFGMR module passed all initialization tests\n\n");
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPFGMR module, problem 1, passed all tests\n\n");
+  }
+
+  
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPFGMR module, problem 2, passed all tests\n\n");
+  }
+
+  
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPFGMR module, problem 3, passed all tests\n\n");
+  }
+
+  
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPFGMR module, problem 4, passed all tests\n\n");
+  }
+
+  
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPFGMR module, problem 5, passed all tests\n\n");
+  }
+
+  
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPFGMR module, problem 6, passed all tests\n\n");
+  }
+
+  /* check if any other process failed */
+  mpierr = MPI_Allreduce(&passfail, &fails, 1, MPI_INT, MPI_MAX, ProbData.comm);
+  
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  MPI_Finalize();
+  return(fails);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2, vL, vR, vsL, vsR;
+  sunindextype i, Nloc;
+  int ierr;
+  UserData *ProbData;
+  MPI_Request SendReqL, SendReqR, RecvReqL, RecvReqR;
+  MPI_Status stat;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  Nloc = ProbData->Nloc;
+  
+  /* MPI equivalent of realtype type */
+  #if defined(SUNDIALS_SINGLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_FLOAT
+  #elif defined(SUNDIALS_DOUBLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_DOUBLE
+  #elif defined(SUNDIALS_EXTENDED_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_LONG_DOUBLE
+  #endif
+  
+  /* send/recv boundary data with neighbors */
+  vL = vR = ZERO;
+  vsL = v[0]*s2[0];
+  vsR = v[Nloc-1]*s2[Nloc-1];
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Irecv(&vL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     0, ProbData->comm, &SendReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Irecv(&vR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     1, ProbData->comm, &SendReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+    
+  
+  /* iterate through interior of local domain, performing product */
+  for (i=1; i<Nloc-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* wait on neighbor data to arrive */
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Wait(&RecvReqL, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Wait(&RecvReqR, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  
+  /* perform product at subdomain boundaries (note: vL/vR are zero at boundary)*/
+  z[0] = (-vL + FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];
+  z[Nloc-1] = (-v[Nloc-2]*s2[Nloc-2] + FIVE*v[Nloc-1]*s2[Nloc-1] - vR)/s1[Nloc-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->Nloc; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int      failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<local_problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/spfgmr/serial/CMakeLists.txt b/examples/sunlinsol/spfgmr/serial/CMakeLists.txt
new file mode 100644
index 0000000..7596201
--- /dev/null
+++ b/examples/sunlinsol/spfgmr/serial/CMakeLists.txt
@@ -0,0 +1,159 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPFGMR examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS SPFGMR linear solver
+SET(sunlinsol_spfgmr_examples
+  "test_sunlinsol_spfgmr_serial\;100 1 100 1e-13 0\;"
+  "test_sunlinsol_spfgmr_serial\;100 2 100 1e-13 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_spfgmr_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspfgmr_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspfgmr_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_spfgmr_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_spfgmr_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/serial)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolspfgmr")
+
+  EXAMPLES2STRING(sunlinsol_spfgmr_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_spfgmr_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/serial/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/serial/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/serial
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/serial/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spfgmr/serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spfgmr/serial
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/spfgmr/serial/test_sunlinsol_spfgmr_serial.c b/examples/sunlinsol/spfgmr/serial/test_sunlinsol_spfgmr_serial.c
new file mode 100644
index 0000000..338d662
--- /dev/null
+++ b/examples/sunlinsol/spfgmr/serial/test_sunlinsol_spfgmr_serial.c
@@ -0,0 +1,522 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPFGMR module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_spfgmr.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype N; /* problem size */
+  N_Vector d;     /* matrix diagonal */
+  N_Vector s1;    /* scaling vectors supplied to SPFGMR */
+  N_Vector s2;
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of the problem size (for check_vector routine) */
+sunindextype problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPFGMR Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPFGMR 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ *       Here we use a diagonal preconditioner D, so the S*-inverse 
+ *       and S* in the product cancel one another.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             gstype, maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 6) {
+    printf("ERROR: FIVE (5) Inputs required:\n");
+    printf("  Problem size should be >0\n");
+    printf("  Gram-Schmidt orthogonalization type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.N = atol(argv[1]);
+  problem_size = ProbData.N;
+  if (ProbData.N <= 0) {
+    printf("ERROR: Problem size must be a positive integer\n");
+    return 1; 
+  }
+  gstype = atoi(argv[2]);
+  if ((gstype < 1) || (gstype > 2)) {
+    printf("ERROR: Gram-Schmidt orthogonalization type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[3]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[4]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[5]);
+  SetTiming(print_timing);
+
+  printf("\nSPFGMR linear solver test:\n");
+  printf("  problem size = %ld\n", (long int) ProbData.N);
+  printf("  Gram-Schmidt orthogonalization type = %i\n", gstype);
+  printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+  printf("  Solver Tolerance = %"GSYM"\n", tol);
+  printf("  timing output flag = %i\n\n", print_timing);
+  
+  /* Create vectors */
+  x = N_VNew_Serial(ProbData.N);
+  if (check_flag(x, "N_VNew_Serial", 0)) return 1;
+  xhat = N_VNew_Serial(ProbData.N);
+  if (check_flag(xhat, "N_VNew_Serial", 0)) return 1;
+  b = N_VNew_Serial(ProbData.N);
+  if (check_flag(b, "N_VNew_Serial", 0)) return 1;
+  ProbData.d = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.d, "N_VNew_Serial", 0)) return 1;
+  ProbData.s1 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s1, "N_VNew_Serial", 0)) return 1;
+  ProbData.s2 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s2, "N_VNew_Serial", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.N; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPFGMR linear solver */
+  LS = SUNSPFGMR(x, PREC_RIGHT, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE, 0);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, 0);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup, PSolve, 0);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2, 0);
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+  fails += SUNSPFGMRSetGSType(LS, gstype);  
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else {
+    printf("SUCCESS: SUNSPFGMR module passed all initialization tests\n\n");
+  }
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPFGMR module, problem 1, passed all tests\n\n");
+  }
+
+
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPFGMR module, problem 2, passed all tests\n\n");
+  }
+
+
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPFGMR module, problem 3, passed all tests\n\n");
+  }
+
+
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPFGMR module, problem 4, passed all tests\n\n");
+  }
+
+
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPFGMR module, problem 5, passed all tests\n\n");
+  }
+
+
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPFGMRSetPrecType(LS, PREC_RIGHT);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPFGMR module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPFGMR module, problem 6, passed all tests\n\n");
+  }
+
+
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  return(passfail);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2;
+  sunindextype i, N;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  N = ProbData->N;
+
+  /* perform product at the left domain boundary (note: v is zero at the boundary)*/ 
+  z[0] = (FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];   
+  
+  /* iterate through interior of local domain, performing product */
+  for (i=1; i<N-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* perform product at the right domain boundary (note: v is zero at the boundary)*/ 
+  z[N-1] = (-v[N-2]*s2[N-2] + FIVE*v[N-1]*s2[N-1])/s1[N-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->N; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int      failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/spgmr/parallel/CMakeLists.txt b/examples/sunlinsol/spgmr/parallel/CMakeLists.txt
new file mode 100644
index 0000000..7937e28
--- /dev/null
+++ b/examples/sunlinsol/spgmr/parallel/CMakeLists.txt
@@ -0,0 +1,176 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPGMR parallel examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
+
+# Examples using the SUNDIALS SPGMR linear solver
+SET(sunlinsol_spgmr_examples
+  "test_sunlinsol_spgmr_parallel\;100 1 1 50 1e-3 0\;1\;4\;"
+  "test_sunlinsol_spgmr_parallel\;100 1 2 50 1e-3 0\;1\;4\;"
+  "test_sunlinsol_spgmr_parallel\;100 2 1 50 1e-3 0\;1\;4\;"
+  "test_sunlinsol_spgmr_parallel\;100 2 2 50 1e-3 0\;1\;4\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_spgmr_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecparallel_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspgmr_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecparallel_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspgmr_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+IF(MPI_MPICC)
+  # use MPI_MPICC as the compiler
+  SET(CMAKE_C_COMPILER ${MPI_MPICC})
+ELSE(MPI_MPICC)
+  # add MPI_INCLUDE_PATH to include directories
+  INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_spgmr_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/parallel)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_spgmr_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/parallel)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolspgmr")
+
+  EXAMPLES2STRING(sunlinsol_spgmr_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_spgmr_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/parallel/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/parallel/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/parallel
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_parallel_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/parallel/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/parallel/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/parallel
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/spgmr/parallel/test_sunlinsol_spgmr_parallel.c b/examples/sunlinsol/spgmr/parallel/test_sunlinsol_spgmr_parallel.c
new file mode 100644
index 0000000..145faaa
--- /dev/null
+++ b/examples/sunlinsol/spgmr/parallel/test_sunlinsol_spgmr_parallel.c
@@ -0,0 +1,600 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPGMR module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+#include "mpi.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype Nloc;  /* local problem size */
+  N_Vector d;         /* matrix diagonal */
+  N_Vector s1;        /* scaling vectors supplied to SPGMR */
+  N_Vector s2;        
+  MPI_Comm comm;      /* communicator object */
+  int myid;           /* MPI process ID */
+  int nprocs;         /* total number of MPI processes */
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of Nloc (for check_vector routine) */
+sunindextype local_problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPGMR Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPGMR 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ *       Here we use a diagonal preconditioner D, so the S*-inverse 
+ *       and S* in the product cancel one another.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  int             mpierr;           /* mpi error flag            */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             gstype, pretype, maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* Set up MPI environment */
+  fails = MPI_Init(&argc, &argv);
+  if (check_flag(&fails, "MPI_Init", 1)) return 1;
+  ProbData.comm = MPI_COMM_WORLD;
+  fails = MPI_Comm_size(ProbData.comm, &(ProbData.nprocs));
+  if (check_flag(&fails, "MPI_Comm_size", 1)) return 1;
+  fails = MPI_Comm_rank(ProbData.comm, &(ProbData.myid));
+  if (check_flag(&fails, "MPI_Comm_rank", 1)) return 1;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 7) {
+    printf("ERROR: SIX (6) Inputs required:\n");
+    printf("  Local problem size should be >0\n");
+    printf("  Gram-Schmidt orthogonalization type should be 1 or 2\n");
+    printf("  Preconditioning type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.Nloc = atol(argv[1]);
+  local_problem_size = ProbData.Nloc;
+  if (ProbData.Nloc <= 0) {
+    printf("ERROR: local problem size must be a positive integer\n");
+    return 1; 
+  }
+  gstype = atoi(argv[2]);
+  if ((gstype < 1) || (gstype > 2)) {
+    printf("ERROR: Gram-Schmidt orthogonalization type must be either 1 or 2\n");
+    return 1; 
+  }
+  pretype = atoi(argv[3]);
+  if ((pretype < 1) || (pretype > 2)) {
+    printf("ERROR: Preconditioning type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[4]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[5]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[6]);
+  SetTiming(print_timing);
+
+  if (ProbData.myid == 0) {
+    printf("\nSPGMR linear solver test:\n");
+    printf("  nprocs = %i\n", ProbData.nprocs);
+    printf("  local/global problem sizes = %ld/%ld\n", (long int) ProbData.Nloc,
+           (long int) (ProbData.nprocs * ProbData.Nloc));
+    printf("  Gram-Schmidt orthogonalization type = %i\n", gstype);
+    printf("  Preconditioning type = %i\n", pretype);
+    printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+    printf("  Solver Tolerance = %"GSYM"\n", tol);
+    printf("  timing output flag = %i\n\n", print_timing);
+  }
+  
+  /* Create vectors */
+  x = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                      ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(x, "N_VNew_Parallel", 0)) return 1;
+  xhat = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                         ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(xhat, "N_VNew_Parallel", 0)) return 1;
+  b = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                      ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(b, "N_VNew_Parallel", 0)) return 1;
+  ProbData.d = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                               ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.d, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s1 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s1, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s2 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s2, "N_VNew_Parallel", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.Nloc; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPGMR linear solver */
+  LS = SUNSPGMR(x, pretype, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE, 
+                                 ProbData.myid);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, ProbData.myid);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup,
+                                           PSolve, ProbData.myid);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2,
+                                           ProbData.myid);
+  fails += Test_SUNLinSolInitialize(LS, ProbData.myid);
+  fails += Test_SUNLinSolSpace(LS, ProbData.myid);
+  fails += SUNSPGMRSetGSType(LS, gstype);  
+  if (fails) {
+    printf("FAIL: SUNSPGMR module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else if (ProbData.myid == 0)
+    printf("SUCCESS: SUNSPGMR module passed all initialization tests\n\n");
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPGMR module, problem 1, passed all tests\n\n");
+  }
+
+  
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPGMR module, problem 2, passed all tests\n\n");
+  }
+
+  
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPGMR module, problem 3, passed all tests\n\n");
+  }
+
+  
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPGMR module, problem 4, passed all tests\n\n");
+  }
+
+  
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPGMR module, problem 5, passed all tests\n\n");
+  }
+
+  
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPGMR module, problem 6, passed all tests\n\n");
+  }
+
+  /* check if any other process failed */
+  mpierr = MPI_Allreduce(&passfail, &fails, 1, MPI_INT, MPI_MAX, ProbData.comm);
+  
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  MPI_Finalize();
+  return(fails);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2, vL, vR, vsL, vsR;
+  sunindextype i, Nloc;
+  int ierr;
+  UserData *ProbData;
+  MPI_Request SendReqL, SendReqR, RecvReqL, RecvReqR;
+  MPI_Status stat;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  Nloc = ProbData->Nloc;
+  
+  /* MPI equivalent of realtype type */
+  #if defined(SUNDIALS_SINGLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_FLOAT
+  #elif defined(SUNDIALS_DOUBLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_DOUBLE
+  #elif defined(SUNDIALS_EXTENDED_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_LONG_DOUBLE
+  #endif
+  
+  /* send/recv boundary data with neighbors */
+  vL = vR = ZERO;
+  vsL = v[0]*s2[0];
+  vsR = v[Nloc-1]*s2[Nloc-1];
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Irecv(&vL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     0, ProbData->comm, &SendReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Irecv(&vR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     1, ProbData->comm, &SendReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+    
+  
+  /* iterate through interior of local domain, performing product */
+  for (i=1; i<Nloc-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* wait on neighbor data to arrive */
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Wait(&RecvReqL, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Wait(&RecvReqR, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  
+  /* perform product at subdomain boundaries (note: vL/vR are zero at boundary)*/
+  z[0] = (-vL + FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];
+  z[Nloc-1] = (-v[Nloc-2]*s2[Nloc-2] + FIVE*v[Nloc-1]*s2[Nloc-1] - vR)/s1[Nloc-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->Nloc; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<local_problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/spgmr/serial/CMakeLists.txt b/examples/sunlinsol/spgmr/serial/CMakeLists.txt
new file mode 100644
index 0000000..cce5a78
--- /dev/null
+++ b/examples/sunlinsol/spgmr/serial/CMakeLists.txt
@@ -0,0 +1,161 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPGMR examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS SPGMR linear solver
+SET(sunlinsol_spgmr_examples
+  "test_sunlinsol_spgmr_serial\;100 1 1 100 1e-13 0\;"
+  "test_sunlinsol_spgmr_serial\;100 2 1 100 1e-13 0\;"
+  "test_sunlinsol_spgmr_serial\;100 1 2 100 1e-13 0\;"
+  "test_sunlinsol_spgmr_serial\;100 2 2 100 1e-13 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_spgmr_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspgmr_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolspgmr_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_spgmr_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+    
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_spgmr_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/serial)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolspgmr")
+
+  EXAMPLES2STRING(sunlinsol_spgmr_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_spgmr_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/serial/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/serial/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/serial
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/serial/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/spgmr/serial/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/spgmr/serial
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/spgmr/serial/test_sunlinsol_spgmr_serial.c b/examples/sunlinsol/spgmr/serial/test_sunlinsol_spgmr_serial.c
new file mode 100644
index 0000000..fa77848
--- /dev/null
+++ b/examples/sunlinsol/spgmr/serial/test_sunlinsol_spgmr_serial.c
@@ -0,0 +1,529 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPGMR module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_spgmr.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype N; /* problem size */
+  N_Vector d;     /* matrix diagonal */
+  N_Vector s1;    /* scaling vectors supplied to SPGMR */
+  N_Vector s2;
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of the problem size (for check_vector routine) */
+sunindextype problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPGMR Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPGMR 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ *       Here we use a diagonal preconditioner D, so the S*-inverse 
+ *       and S* in the product cancel one another.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             gstype, pretype, maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 7) {
+    printf("ERROR: SIX (6) Inputs required:\n");
+    printf("  Problem size should be >0\n");
+    printf("  Gram-Schmidt orthogonalization type should be 1 or 2\n");
+    printf("  Preconditioning type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.N = atol(argv[1]);
+  problem_size = ProbData.N;
+  if (ProbData.N <= 0) {
+    printf("ERROR: Problem size must be a positive integer\n");
+    return 1; 
+  }
+  gstype = atoi(argv[2]);
+  if ((gstype < 1) || (gstype > 2)) {
+    printf("ERROR: Gram-Schmidt orthogonalization type must be either 1 or 2\n");
+    return 1; 
+  }
+  pretype = atoi(argv[3]);
+  if ((pretype < 1) || (pretype > 2)) {
+    printf("ERROR: Preconditioning type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[4]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[5]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[6]);
+  SetTiming(print_timing);
+
+  printf("\nSPGMR linear solver test:\n");
+  printf("  Problem size = %ld\n", (long int) ProbData.N);
+  printf("  Gram-Schmidt orthogonalization type = %i\n", gstype);
+  printf("  Preconditioning type = %i\n", pretype);
+  printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+  printf("  Solver Tolerance = %"GSYM"\n", tol);
+  printf("  timing output flag = %i\n\n", print_timing);
+  
+  /* Create vectors */
+  x = N_VNew_Serial(ProbData.N);
+  if (check_flag(x, "N_VNew_Serial", 0)) return 1;
+  xhat = N_VNew_Serial(ProbData.N);
+  if (check_flag(xhat, "N_VNew_Serial", 0)) return 1;
+  b = N_VNew_Serial(ProbData.N);
+  if (check_flag(b, "N_VNew_Serial", 0)) return 1;
+  ProbData.d = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.d, "N_VNew_Serial", 0)) return 1;
+  ProbData.s1 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s1, "N_VNew_Serial", 0)) return 1;
+  ProbData.s2 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s2, "N_VNew_Serial", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.N; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPGMR linear solver */
+  LS = SUNSPGMR(x, pretype, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE, 0);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, 0);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup, PSolve, 0);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2, 0);
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+  fails += SUNSPGMRSetGSType(LS, gstype);  
+  if (fails) {
+    printf("FAIL: SUNSPGMR module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else {
+    printf("SUCCESS: SUNSPGMR module passed all initialization tests\n\n");
+  }
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPGMR module, problem 1, passed all tests\n\n");
+  }
+
+
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPGMR module, problem 2, passed all tests\n\n");
+  }
+  
+
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPGMR module, problem 3, passed all tests\n\n");
+  }
+
+
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPGMR module, problem 4, passed all tests\n\n");
+  }
+
+
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPGMR module, problem 5, passed all tests\n\n");
+  }
+
+
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPGMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPGMR module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPGMR module, problem 6, passed all tests\n\n");
+  }
+
+
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  return(passfail);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2;
+  sunindextype i, N;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  N = ProbData->N;
+
+  /* perform product at the left domain boundary (note: v is zero at the boundary)*/
+  z[0] = (FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];
+    
+  /* iterate through interior of local domain, performing product */
+  for (i=1; i<N-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* perform product at the right domain boundary (note: v is zero at the boundary)*/ 
+  z[N-1] = (-v[N-2]*s2[N-2] + FIVE*v[N-1]*s2[N-1])/s1[N-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->N; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/sptfqmr/parallel/CMakeLists.txt b/examples/sunlinsol/sptfqmr/parallel/CMakeLists.txt
new file mode 100644
index 0000000..7ffe7da
--- /dev/null
+++ b/examples/sunlinsol/sptfqmr/parallel/CMakeLists.txt
@@ -0,0 +1,174 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPTFQMR parallel examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;nodes\;tasks\;type" where the
+# type is develop for examples excluded from 'make test' in releases
+
+# Examples using the SUNDIALS SPTFQMR linear solver
+SET(sunlinsol_sptfqmr_examples
+  "test_sunlinsol_sptfqmr_parallel\;100 1 50 1e-3 0\;1\;4\;"
+  "test_sunlinsol_sptfqmr_parallel\;100 2 50 1e-3 0\;1\;4\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_sptfqmr_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecparallel_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolsptfqmr_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecparallel_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolsptfqmr_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+IF(MPI_MPICC)
+  # use MPI_MPICC as the compiler
+  SET(CMAKE_C_COMPILER ${MPI_MPICC})
+ELSE(MPI_MPICC)
+  # add MPI_INCLUDE_PATH to include directories
+  INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
+ENDIF(MPI_MPICC)
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_sptfqmr_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 number_of_nodes)
+  LIST(GET example_tuple 3 number_of_tasks)
+  LIST(GET example_tuple 4 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+    IF(NOT MPI_MPICC)
+      TARGET_LINK_LIBRARIES(${example} ${MPI_LIBRARIES})
+    ENDIF()
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    MPI_NPROCS ${number_of_tasks}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/parallel)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_sptfqmr_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/parallel)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolsptfqmr")
+
+  EXAMPLES2STRING(sunlinsol_sptfqmr_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_sptfqmr_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_parallel_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/parallel/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/parallel/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/parallel
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_parallel_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/parallel/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/parallel/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/parallel
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/sptfqmr/parallel/test_sunlinsol_sptfqmr_parallel.c b/examples/sunlinsol/sptfqmr/parallel/test_sunlinsol_sptfqmr_parallel.c
new file mode 100644
index 0000000..b1bea38
--- /dev/null
+++ b/examples/sunlinsol/sptfqmr/parallel/test_sunlinsol_sptfqmr_parallel.c
@@ -0,0 +1,592 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPTFQMR module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_sptfqmr.h>
+#include <nvector/nvector_parallel.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+#include "mpi.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype Nloc;  /* local problem size */
+  N_Vector d;         /* matrix diagonal */
+  N_Vector s1;        /* scaling vectors supplied to SPTFQMR */
+  N_Vector s2;       
+  MPI_Comm comm;      /* communicator object */
+  int myid;           /* MPI process ID */
+  int nprocs;         /* total number of MPI processes */
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of Nloc (for check_vector routine) */
+sunindextype local_problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPTFQMR Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPTFQMR 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ *       Here we use a diagonal preconditioner D, so the S*-inverse 
+ *       and S* in the product cancel one another.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  int             mpierr;           /* mpi error flag            */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             pretype, maxl, print_timing;
+  sunindextype        i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* Set up MPI environment */
+  fails = MPI_Init(&argc, &argv);
+  if (check_flag(&fails, "MPI_Init", 1)) return 1;
+  ProbData.comm = MPI_COMM_WORLD;
+  fails = MPI_Comm_size(ProbData.comm, &(ProbData.nprocs));
+  if (check_flag(&fails, "MPI_Comm_size", 1)) return 1;
+  fails = MPI_Comm_rank(ProbData.comm, &(ProbData.myid));
+  if (check_flag(&fails, "MPI_Comm_rank", 1)) return 1;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 6) {
+    printf("ERROR: FIVE (5) Inputs required:\n");
+    printf("  Local problem size should be >0\n");
+    printf("  Preconditioning type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.Nloc = atol(argv[1]);
+  local_problem_size = ProbData.Nloc;
+  if (ProbData.Nloc <= 0) {
+    printf("ERROR: local problem size must be a positive integer\n");
+    return 1; 
+  }
+  pretype = atoi(argv[2]);
+  if ((pretype < 1) || (pretype > 2)) {
+    printf("ERROR: Preconditioning type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[3]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[4]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[5]);
+  SetTiming(print_timing);
+
+  if (ProbData.myid == 0) {
+    printf("\nSPTFQMR linear solver test:\n");
+    printf("  nprocs = %i\n", ProbData.nprocs);
+    printf("  local/global problem sizes = %ld/%ld\n", (long int) ProbData.Nloc,
+           (long int) (ProbData.nprocs * ProbData.Nloc));
+    printf("  Preconditioning type = %i\n", pretype);
+    printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+    printf("  Solver Tolerance = %"GSYM"\n", tol);
+    printf("  timing output flag = %i\n\n", print_timing);
+  }
+  
+  /* Create vectors */
+  x = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                      ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(x, "N_VNew_Parallel", 0)) return 1;
+  xhat = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                         ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(xhat, "N_VNew_Parallel", 0)) return 1;
+  b = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                        ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(b, "N_VNew_Parallel", 0)) return 1;
+  ProbData.d = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                               ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.d, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s1 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s1, "N_VNew_Parallel", 0)) return 1;
+  ProbData.s2 = N_VNew_Parallel(ProbData.comm, ProbData.Nloc,
+                                ProbData.nprocs * ProbData.Nloc);
+  if (check_flag(ProbData.s2, "N_VNew_Parallel", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.Nloc; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPTFQMR linear solver */
+  LS = SUNSPTFQMR(x, pretype, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE,
+                                 ProbData.myid);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, ProbData.myid);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup,
+                                           PSolve, ProbData.myid);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2,
+                                           ProbData.myid);
+  fails += Test_SUNLinSolInitialize(LS, ProbData.myid);
+  fails += Test_SUNLinSolSpace(LS, ProbData.myid);
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else if (ProbData.myid == 0)
+    printf("SUCCESS: SUNSPTFQMR module passed all initialization tests\n\n");
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPTFQMR module, problem 1, passed all tests\n\n");
+  }
+
+  
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPTFQMR module, problem 2, passed all tests\n\n");
+  }
+
+  
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPTFQMR module, problem 3, passed all tests\n\n");
+  }
+
+  
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPTFQMR module, problem 4, passed all tests\n\n");
+  }
+
+  
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPTFQMR module, problem 5, passed all tests\n\n");
+  }
+
+  
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.Nloc; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, ProbData.myid);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, ProbData.myid);
+  fails += Test_SUNLinSolLastFlag(LS, ProbData.myid);
+  fails += Test_SUNLinSolNumIters(LS, ProbData.myid);
+  fails += Test_SUNLinSolResNorm(LS, ProbData.myid);
+  fails += Test_SUNLinSolResid(LS, ProbData.myid);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else if (ProbData.myid == 0) {
+    printf("SUCCESS: SUNSPTFQMR module, problem 6, passed all tests\n\n");
+  }
+
+  /* check if any other process failed */
+  mpierr = MPI_Allreduce(&passfail, &fails, 1, MPI_INT, MPI_MAX, ProbData.comm);
+  
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  MPI_Finalize();
+  return(fails);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2, vL, vR, vsL, vsR;
+  sunindextype i, Nloc;
+  int ierr;
+  UserData *ProbData;
+  MPI_Request SendReqL, SendReqR, RecvReqL, RecvReqR;
+  MPI_Status stat;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  Nloc = ProbData->Nloc;
+  
+  /* MPI equivalent of realtype type */
+  #if defined(SUNDIALS_SINGLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_FLOAT
+  #elif defined(SUNDIALS_DOUBLE_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_DOUBLE
+  #elif defined(SUNDIALS_EXTENDED_PRECISION)
+  #define REALTYPE_MPI_TYPE MPI_LONG_DOUBLE
+  #endif
+  
+  /* send/recv boundary data with neighbors */
+  vL = vR = ZERO;
+  vsL = v[0]*s2[0];
+  vsR = v[Nloc-1]*s2[Nloc-1];
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Irecv(&vL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsL, 1, REALTYPE_MPI_TYPE, ProbData->myid-1,
+                     0, ProbData->comm, &SendReqL);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Irecv(&vR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     MPI_ANY_TAG, ProbData->comm, &RecvReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+    ierr = MPI_Isend(&vsR, 1, REALTYPE_MPI_TYPE, ProbData->myid+1,
+                     1, ProbData->comm, &SendReqR);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+    
+  
+  /* iterate through interior of local domain, performing product */
+  for (i=1; i<Nloc-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* wait on neighbor data to arrive */
+  if (ProbData->myid > 0) {                   /* left neighbor exists */
+    ierr = MPI_Wait(&RecvReqL, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  if (ProbData->myid < ProbData->nprocs-1) {  /* right neighbor exists */
+    ierr = MPI_Wait(&RecvReqR, &stat);
+    if (ierr != MPI_SUCCESS) return 1;
+  }
+  
+  /* perform product at subdomain boundaries (note: vL/vR are zero at boundary)*/
+  z[0] = (-vL + FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];
+  z[Nloc-1] = (-v[Nloc-2]*s2[Nloc-2] + FIVE*v[Nloc-1]*s2[Nloc-1] - vR)/s1[Nloc-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->Nloc; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<local_problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < local_problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/sptfqmr/serial/CMakeLists.txt b/examples/sunlinsol/sptfqmr/serial/CMakeLists.txt
new file mode 100644
index 0000000..e9bee6e
--- /dev/null
+++ b/examples/sunlinsol/sptfqmr/serial/CMakeLists.txt
@@ -0,0 +1,159 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SPTFQMR examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS SPTFQMR linear solver
+SET(sunlinsol_sptfqmr_examples
+  "test_sunlinsol_sptfqmr_serial\;100 1 100 1e-13 0\;"
+  "test_sunlinsol_sptfqmr_serial\;100 2 100 1e-13 0\;"
+  )
+
+# Dependencies for nvector examples
+SET(sunlinsol_sptfqmr_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_linearsolver
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ../..)
+
+# Specify libraries to link against (through the target that was used to
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVEC_LIB sundials_nvecserial_static)
+  SET(SUNLINSOL_LIB sundials_sunlinsolsptfqmr_static)
+ELSE()
+  SET(NVEC_LIB sundials_nvecserial_shared)
+  SET(SUNLINSOL_LIB sundials_sunlinsolsptfqmr_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVEC_LIB} ${SUNLINSOL_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_sptfqmr_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../../test_sunlinsol.h
+      ../../test_sunlinsol.c
+      ../../../../src/sundials/sundials_linearsolver.c
+      ../../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/serial)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_sptfqmr_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/serial)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolsptfqmr")
+
+  EXAMPLES2STRING(sunlinsol_sptfqmr_examples EXAMPLES)
+  EXAMPLES2STRING(sunlinsol_sptfqmr_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install
+  # CMakeLists.txt file for building the examples. This file  can then
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/serial/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/serial/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/serial
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for
+  # building the examples. This makefile can then be used as a template
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/serial/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/sptfqmr/serial/Makefile_ex
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/sptfqmr/serial
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/sptfqmr/serial/test_sunlinsol_sptfqmr_serial.c b/examples/sunlinsol/sptfqmr/serial/test_sunlinsol_sptfqmr_serial.c
new file mode 100644
index 0000000..9465cdf
--- /dev/null
+++ b/examples/sunlinsol/sptfqmr/serial/test_sunlinsol_sptfqmr_serial.c
@@ -0,0 +1,524 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SPTFQMR module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_sptfqmr.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define GSYM "Lg"
+#define ESYM "Le"
+#define FSYM "Lf"
+#else
+#define GSYM "g"
+#define ESYM "e"
+#define FSYM "f"
+#endif
+
+/* constants */
+#define FIVE      RCONST(5.0)
+#define THOUSAND  RCONST(1000.0)
+
+/* user data structure */
+typedef struct {
+  sunindextype N; /* problem size */
+  N_Vector d;     /* matrix diagonal */
+  N_Vector s1;    /* scaling vectors supplied to SPTFQMR */
+  N_Vector s2;
+} UserData;
+
+/* private functions */
+/*    matrix-vector product  */
+int ATimes(void* ProbData, N_Vector v, N_Vector z);
+/*    preconditioner setup */
+int PSetup(void* ProbData);
+/*    preconditioner solve */
+int PSolve(void* ProbData, N_Vector r, N_Vector z, realtype tol, int lr);
+/*    checks function return values  */
+static int check_flag(void *flagvalue, const char *funcname, int opt);
+/*    uniform random number generator in [0,1] */
+static realtype urand();
+
+/* global copy of problem size (for check_vector routine) */
+sunindextype problem_size;
+
+/* ----------------------------------------------------------------------
+ * SUNSPTFQMR Linear Solver Testing Routine
+ *
+ * We run multiple tests to exercise this solver:
+ * 1. simple tridiagonal system (no preconditioning)
+ * 2. simple tridiagonal system (Jacobi preconditioning)
+ * 3. tridiagonal system w/ scale vector s1 (no preconditioning)
+ * 4. tridiagonal system w/ scale vector s1 (Jacobi preconditioning)
+ * 5. tridiagonal system w/ scale vector s2 (no preconditioning)
+ * 6. tridiagonal system w/ scale vector s2 (Jacobi preconditioning)
+ *
+ * Note: We construct a tridiagonal matrix Ahat, a random solution xhat, 
+ *       and a corresponding rhs vector bhat = Ahat*xhat, such that each 
+ *       of these is unit-less.  To test row/column scaling, we use the 
+ *       matrix A = S1-inverse Ahat S2, rhs vector b = S1-inverse bhat, 
+ *       and solution vector x = (S2-inverse) xhat; hence the linear 
+ *       system has rows scaled by S1-inverse and columns scaled by S2, 
+ *       where S1 and S2 are the diagonal matrices with entries from the 
+ *       vectors s1 and s2, the 'scaling' vectors supplied to SPTFQMR 
+ *       having strictly positive entries.  When this is combined with 
+ *       preconditioning, assume that Phat is the desired preconditioner 
+ *       for Ahat, then our preconditioning matrix P \approx A should be
+ *         left prec:  P-inverse \approx S1-inverse Ahat-inverse S1
+ *         right prec:  P-inverse \approx S2-inverse Ahat-inverse S2.
+ *       Here we use a diagonal preconditioner D, so the S*-inverse 
+ *       and S* in the product cancel one another.
+ * 
+ * If this is run with 1 MPI task, our tests use the serial N_Vector 
+ * module; otherwise we use the MPI-parallel N_Vector module.
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails=0;          /* counter for test failures */
+  int             passfail=0;       /* overall pass/fail flag    */
+  SUNLinearSolver LS;               /* linear solver object      */
+  N_Vector        xhat, x, b;       /* test vectors              */
+  UserData        ProbData;         /* problem data structure    */
+  int             pretype, maxl, print_timing;
+  sunindextype    i;
+  realtype        *vecdata;
+  double          tol;
+
+  /* check inputs: local problem size, timing flag */
+  if (argc < 6) {
+    printf("ERROR: FIVE (5) Inputs required:\n");
+    printf("  Problem size should be >0\n");
+    printf("  Preconditioning type should be 1 or 2\n");
+    printf("  Maximum Krylov subspace dimension should be >0\n");
+    printf("  Solver tolerance should be >0\n");
+    printf("  timing output flag should be 0 or 1 \n");
+    return 1;
+  }
+  ProbData.N = atol(argv[1]);
+  problem_size = ProbData.N;
+  if (ProbData.N <= 0) {
+    printf("ERROR: Problem size must be a positive integer\n");
+    return 1; 
+  }
+  pretype = atoi(argv[2]);
+  if ((pretype < 1) || (pretype > 2)) {
+    printf("ERROR: Preconditioning type must be either 1 or 2\n");
+    return 1; 
+  }
+  maxl = atoi(argv[3]);
+  if (maxl <= 0) {
+    printf("ERROR: Maximum Krylov subspace dimension must be a positive integer\n");
+    return 1; 
+  }
+  tol = atof(argv[4]);
+  if (tol <= ZERO) {
+    printf("ERROR: Solver tolerance must be a positive real number\n");
+    return 1; 
+  }
+  print_timing = atoi(argv[5]);
+  SetTiming(print_timing);
+
+  printf("\nSPTFQMR linear solver test:\n");
+  printf("  Problem size = %ld\n", (long int) ProbData.N);
+  printf("  Preconditioning type = %i\n", pretype);
+  printf("  Maximum Krylov subspace dimension = %i\n", maxl);
+  printf("  Solver Tolerance = %"GSYM"\n", tol);
+  printf("  timing output flag = %i\n\n", print_timing);
+  
+  /* Create vectors */
+  x = N_VNew_Serial(ProbData.N);
+  if (check_flag(x, "N_VNew_Serial", 0)) return 1;
+  xhat = N_VNew_Serial(ProbData.N);
+  if (check_flag(xhat, "N_VNew_Serial", 0)) return 1;
+  b = N_VNew_Serial(ProbData.N);
+  if (check_flag(b, "N_VNew_Serial", 0)) return 1;
+  ProbData.d = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.d, "N_VNew_Serial", 0)) return 1;
+  ProbData.s1 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s1, "N_VNew_Serial", 0)) return 1;
+  ProbData.s2 = N_VNew_Serial(ProbData.N);
+  if (check_flag(ProbData.s2, "N_VNew_Serial", 0)) return 1;
+
+  /* Fill xhat vector with uniform random data in [1,2] */
+  vecdata = N_VGetArrayPointer(xhat);
+  for (i=0; i<ProbData.N; i++) 
+    vecdata[i] = ONE + urand();
+
+  /* Fill Jacobi vector with matrix diagonal */
+  N_VConst(FIVE, ProbData.d);
+  
+  /* Create SPTFQMR linear solver */
+  LS = SUNSPTFQMR(x, pretype, maxl);
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_ITERATIVE, 0);
+  fails += Test_SUNLinSolSetATimes(LS, &ProbData, ATimes, 0);
+  fails += Test_SUNLinSolSetPreconditioner(LS, &ProbData, PSetup, PSolve, 0);
+  fails += Test_SUNLinSolSetScalingVectors(LS, ProbData.s1, ProbData.s2, 0);
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module failed %i initialization tests\n\n", fails);
+    return 1;
+  } else {
+    printf("SUCCESS: SUNSPTFQMR module passed all initialization tests\n\n");
+  }
+
+  
+  /*** Test 1: simple Poisson-like solve (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+  
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 1, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPTFQMR module, problem 1, passed all tests\n\n");
+  }
+
+
+  /*** Test 2: simple Poisson-like solve (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE,  ProbData.s1);
+  N_VConst(ONE,  ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 2, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPTFQMR module, problem 2, passed all tests\n\n");
+  }
+
+
+  /*** Test 3: Poisson-like solve w/ scaled rows (no preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, PREC_NONE);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 3, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPTFQMR module, problem 3, passed all tests\n\n");
+  }
+
+
+  /*** Test 4: Poisson-like solve w/ scaled rows (Jacobi preconditioning) ***/
+
+  /* set scaling vectors */
+  vecdata = N_VGetArrayPointer(ProbData.s1);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+  N_VConst(ONE, ProbData.s2);
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 4, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPTFQMR module, problem 4, passed all tests\n\n");
+  }
+
+
+  /*** Test 5: Poisson-like solve w/ scaled columns (no preconditioning) ***/
+
+  /* set scaling vectors */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, PREC_NONE);
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 5, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPTFQMR module, problem 5, passed all tests\n\n");
+  }
+
+
+  /*** Test 6: Poisson-like solve w/ scaled columns (Jacobi preconditioning) ***/
+
+  /* set scaling vector, Jacobi solver vector */
+  N_VConst(ONE, ProbData.s1);
+  vecdata = N_VGetArrayPointer(ProbData.s2);
+  for (i=0; i<ProbData.N; i++)
+    vecdata[i] = ONE + THOUSAND*urand();
+
+  /* Fill x vector with scaled version */
+  N_VDiv(xhat,ProbData.s2,x);
+
+  /* Fill b vector with result of matrix-vector product */
+  fails = ATimes(&ProbData, x, b);
+  if (check_flag(&fails, "ATimes", 1)) return 1;
+
+  /* Run tests with this setup */
+  fails += SUNSPTFQMRSetPrecType(LS, pretype);  
+  fails += Test_SUNLinSolSetup(LS, NULL, 0);
+  fails += Test_SUNLinSolSolve(LS, NULL, x, b, tol, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolNumIters(LS, 0);
+  fails += Test_SUNLinSolResNorm(LS, 0);
+  fails += Test_SUNLinSolResid(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNSPTFQMR module, problem 6, failed %i tests\n\n", fails);
+    passfail += 1;
+  } else {
+    printf("SUCCESS: SUNSPTFQMR module, problem 6, passed all tests\n\n");
+  }
+
+
+  /* Free solver and vectors */
+  SUNLinSolFree(LS);
+  N_VDestroy(x);
+  N_VDestroy(xhat);
+  N_VDestroy(b);
+  N_VDestroy(ProbData.d);
+  N_VDestroy(ProbData.s1);
+  N_VDestroy(ProbData.s2);
+
+  return(passfail);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Private helper functions
+ * --------------------------------------------------------------------*/
+
+/* matrix-vector product  */
+int ATimes(void* Data, N_Vector v_vec, N_Vector z_vec)
+{
+  /* local variables */
+  realtype *v, *z, *s1, *s2;
+  sunindextype i, N;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  v = N_VGetArrayPointer(v_vec);
+  if (check_flag(v, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  s1 = N_VGetArrayPointer(ProbData->s1);
+  if (check_flag(s1, "N_VGetArrayPointer", 0)) return 1;
+  s2 = N_VGetArrayPointer(ProbData->s2);
+  if (check_flag(s2, "N_VGetArrayPointer", 0)) return 1;
+  N = ProbData->N;
+
+  /* perform product at the left domain boundary (note: v is zero at the boundary)*/
+  z[0] = (FIVE*v[0]*s2[0] - v[1]*s2[1])/s1[0];
+   
+  /* iterate through interior of local domain, performing product */
+  for (i=1; i<N-1; i++) 
+    z[i] = (-v[i-1]*s2[i-1] + FIVE*v[i]*s2[i] - v[i+1]*s2[i+1])/s1[i];
+
+  /* perform product at the right domain boundary (note: v is zero at the boundary)*/  
+  z[N-1] = (-v[N-2]*s2[N-2] + FIVE*v[N-1]*s2[N-1])/s1[N-1];
+  
+  /* return with success */
+  return 0;
+}
+  
+/* preconditioner setup -- nothing to do here since everything is already stored */
+int PSetup(void* Data) { return 0; }
+  
+/* preconditioner solve */
+int PSolve(void* Data, N_Vector r_vec, N_Vector z_vec, realtype tol, int lr)
+{
+  /* local variables */
+  realtype *r, *z, *d;
+  sunindextype i;
+  UserData *ProbData;
+  
+  /* access user data structure and vector data */
+  ProbData = (UserData *) Data;
+  r = N_VGetArrayPointer(r_vec);
+  if (check_flag(r, "N_VGetArrayPointer", 0)) return 1;
+  z = N_VGetArrayPointer(z_vec);
+  if (check_flag(z, "N_VGetArrayPointer", 0)) return 1;
+  d = N_VGetArrayPointer(ProbData->d);
+  if (check_flag(d, "N_VGetArrayPointer", 0)) return 1;
+  
+  /* iterate through domain, performing Jacobi solve */
+  for (i=0; i<ProbData->N; i++) 
+    z[i] = r[i] / d[i];
+
+  /* return with success */
+  return 0;
+}
+
+/* uniform random number generator */
+static realtype urand()
+{
+  return ((realtype) rand() / (realtype) RAND_MAX);
+}
+
+/* Check function return value based on "opt" input:
+     0:  function allocates memory so check for NULL pointer
+     1:  function returns a flag so check for flag != 0 */
+static int check_flag(void *flagvalue, const char *funcname, int opt)
+{
+  int *errflag;
+
+  /* Check if function returned NULL pointer - no memory allocated */
+  if (opt==0 && flagvalue==NULL) {
+    fprintf(stderr, "\nERROR: %s() failed - returned NULL pointer\n\n",
+	    funcname);
+    return 1; }
+
+  /* Check if flag != 0 */
+  if (opt==1) {
+    errflag = (int *) flagvalue;
+    if (*errflag != 0) {
+      fprintf(stderr, "\nERROR: %s() failed with flag = %d\n\n",
+	      funcname, *errflag);
+      return 1; }}
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  
+  /* check vector data */
+  for(i=0; i<problem_size; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], FIVE*tol*SUNRabs(Xdata[i]));
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    for(i=0; i < problem_size; i++)
+      maxerr = SUNMAX(SUNRabs(Xdata[i]-Ydata[i])/SUNRabs(Xdata[i]), maxerr);
+    printf("check err failure: maxerr = %g (tol = %g)\n",
+	   maxerr, FIVE*tol);
+    return(1);
+  }
+  else
+    return(0);
+}
+
+
diff --git a/examples/sunlinsol/superlumt/CMakeLists.txt b/examples/sunlinsol/superlumt/CMakeLists.txt
new file mode 100644
index 0000000..25b355d
--- /dev/null
+++ b/examples/sunlinsol/superlumt/CMakeLists.txt
@@ -0,0 +1,182 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sunlinsol SuperLU_MT examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using the SuperLU_MT linear solver
+SET(sunlinsol_superlumt_examples
+  "test_sunlinsol_superlumt\;300 0 1 0\;"
+  "test_sunlinsol_superlumt\;300 1 1 0\;"
+  "test_sunlinsol_superlumt\;1000 0 3 0\;develop"
+  "test_sunlinsol_superlumt\;1000 1 3 0\;develop"
+)
+
+# Dependencies for nvector examples
+SET(sunlinsol_superlumt_dependencies
+  test_sunlinsol
+  sundials_nvector
+  sundials_matrix
+  sundials_linearsolver
+)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVECS_LIB sundials_nvecserial_static)
+  SET(SUNMATS_LIB sundials_sunmatrixdense_static)
+  LIST(APPEND SUNMATS_LIB sundials_sunmatrixsparse_static)
+  SET(SUNLINSOLS_LIB sundials_sunlinsolsuperlumt_static)
+ELSE()
+  SET(NVECS_LIB sundials_nvecserial_shared)
+  SET(SUNMATS_LIB sundials_sunmatrixdense_shared)
+  LIST(APPEND SUNMATS_LIB sundials_sunmatrixsparse_shared)
+  SET(SUNLINSOLS_LIB sundials_sunlinsolsuperlumt_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVECS_LIB} ${SUNMATS_LIB} ${SUNLINSOLS_LIB} ${EXTRA_LINK_LIBS})
+
+LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
+
+IF(LAPACK_FOUND)
+  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
+ENDIF(LAPACK_FOUND)
+
+IF(BLAS_FOUND)
+  LIST(APPEND SUNDIALS_LIBS ${BLAS_LIBRARIES})
+ENDIF(BLAS_FOUND)
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunlinsol_superlumt_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunlinsol.h
+      ../test_sunlinsol.c
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_linearsolver.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/superlumt)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunlinsol_superlumt_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/superlumt)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunlinsolsuperlumt")
+  SET(LIBS "${LIBS} -lsundials_sunmatrixdense -lsundials_sunmatrixsparse")
+
+  # Set the link directory for the dense and sparse sunmatrix libraries
+  # The generated CMakeLists.txt does not use find_library() locate them
+  SET(EXTRA_LIBS_DIR "${libdir}")
+
+  EXAMPLES2STRING(sunlinsol_superlumt_examples EXAMPLES_SLUMT)
+  EXAMPLES2STRING(sunlinsol_superlumt_dependencies EXAMPLES_DEPENDENCIES_SLUMT)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunlinsol/superlumt/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/superlumt/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/superlumt
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunlinsol/superlumt/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunlinsol/superlumt/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunlinsol/superlumt
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunlinsol/superlumt/test_sunlinsol_superlumt.c b/examples/sunlinsol/superlumt/test_sunlinsol_superlumt.c
new file mode 100644
index 0000000..c4bb737
--- /dev/null
+++ b/examples/sunlinsol/superlumt/test_sunlinsol_superlumt.c
@@ -0,0 +1,189 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNLinSol SuperLUMT
+ * module implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sundials/sundials_types.h>
+#include <sunlinsol/sunlinsol_superlumt.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunlinsol.h"
+
+
+/* ----------------------------------------------------------------------
+ * SUNSuperLUMT Linear Solver Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int             fails = 0;          /* counter for test failures  */
+  sunindextype    N;                  /* matrix columns, rows       */
+  SUNLinearSolver LS;                 /* linear solver object       */
+  SUNMatrix       A, B;               /* test matrices              */
+  N_Vector        x, y, b;            /* test vectors               */
+  realtype        *matdata, *xdata;
+  int             mattype, num_threads, print_timing;
+  sunindextype    i, j, k;
+
+  /* check input and set matrix dimensions */
+  if (argc < 5){
+    printf("ERROR: FOUR (4) Inputs required: matrix size, matrix type (0/1), num_threads, print timing \n");
+    return(-1);
+  }
+
+  N = atol(argv[1]); 
+  if (N <= 0) {
+    printf("ERROR: matrix size must be a positive integer \n");
+    return(-1); 
+  }
+
+  mattype = atoi(argv[2]);
+  if ((mattype != 0) && (mattype != 1)) {
+    printf("ERROR: matrix type must be 0 or 1 \n");
+    return(-1); 
+  }
+  mattype = (mattype == 0) ? CSC_MAT : CSR_MAT;
+  
+  num_threads = atoi(argv[3]);
+  if (num_threads <= 0) {
+    printf("ERROR: number_threads must be a positive integer \n");
+    return(-1); 
+  }
+  
+  print_timing = atoi(argv[4]);
+  SetTiming(print_timing);
+
+  printf("\nSuperLUMT linear solver test: size %ld, type %i, num_threads %i\n\n",
+         (long int) N, mattype, num_threads);
+
+  /* Create matrices and vectors */
+  B = SUNDenseMatrix(N, N);
+  x = N_VNew_Serial(N);
+  y = N_VNew_Serial(N);
+  b = N_VNew_Serial(N);
+
+  /* Fill matrix with uniform random data in [0,1/N] */
+  for (k=0; k<5*N; k++) {
+    i = rand() % N;
+    j = rand() % N;
+    matdata = SUNDenseMatrix_Column(B,j);
+    matdata[i] = (realtype) rand() / (realtype) RAND_MAX / N;
+  }
+
+  /* Add identity to matrix */
+  fails = SUNMatScaleAddI(ONE, B);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatScaleAddI failure\n");
+    return(1);
+  }
+
+  /* Fill x vector with uniform random data in [0,1] */
+  xdata = N_VGetArrayPointer(x);
+  for (i=0; i<N; i++)
+    xdata[i] = (realtype) rand() / (realtype) RAND_MAX;
+
+  /* Create sparse matrix from dense, and destroy B */
+  A = SUNSparseFromDenseMatrix(B, ZERO, mattype);
+  SUNMatDestroy(B);
+
+  /* copy x into y to print in case of solver failure */
+  N_VScale(ONE, x, y);
+
+  /* create right-hand side vector for linear solve */
+  fails = SUNMatMatvec(A, x, b);
+  if (fails) {
+    printf("FAIL: SUNLinSol SUNMatMatvec failure\n");
+    return(1);
+  }
+  
+  /* Create SuperLUMT linear solver */
+  LS = SUNSuperLUMT(x, A, num_threads);
+  
+  /* Run Tests */
+  fails += Test_SUNLinSolInitialize(LS, 0);
+  fails += Test_SUNLinSolSetup(LS, A, 0);
+  fails += Test_SUNLinSolSolve(LS, A, x, b, 100*UNIT_ROUNDOFF, 0);
+ 
+  fails += Test_SUNLinSolGetType(LS, SUNLINEARSOLVER_DIRECT, 0);
+  fails += Test_SUNLinSolLastFlag(LS, 0);
+  fails += Test_SUNLinSolSpace(LS, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNLinSol module failed %i tests \n \n", fails);
+    printf("\nA =\n");
+    SUNSparseMatrix_Print(A,stdout);
+    printf("\nx (original) =\n");
+    N_VPrint_Serial(y);
+    printf("\nb =\n");
+    N_VPrint_Serial(b);
+    printf("\nx (computed) =\n");
+    N_VPrint_Serial(x);
+  } else {
+    printf("SUCCESS: SUNLinSol module passed all tests \n \n");
+  }
+
+  /* Free solver, matrix and vectors */
+  SUNLinSolFree(LS);
+  SUNMatDestroy(A);
+  N_VDestroy(x);
+  N_VDestroy(y);
+  N_VDestroy(b);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, local_length, maxloc;
+  realtype *Xdata, *Ydata, maxerr;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  local_length = N_VGetLength_Serial(X);
+  
+  /* check vector data */
+  for(i=0; i < local_length; i++)
+    failure += FNEQ(Xdata[i], Ydata[i], tol);
+
+  if (failure > ZERO) {
+    maxerr = ZERO;
+    maxloc = -1;
+    for(i=0; i < local_length; i++) {
+      if (SUNRabs(Xdata[i]-Ydata[i]) >  maxerr) {
+        maxerr = SUNRabs(Xdata[i]-Ydata[i]);
+        maxloc = i;
+      }
+    }
+    printf("check err failure: maxerr = %g at loc %li (tol = %g)\n",
+	   maxerr, (long int) maxloc, tol);
+    return(1);
+  }
+  else
+    return(0);
+}
diff --git a/examples/sunlinsol/test_sunlinsol.c b/examples/sunlinsol/test_sunlinsol.c
new file mode 100644
index 0000000..c2576cf
--- /dev/null
+++ b/examples/sunlinsol/test_sunlinsol.c
@@ -0,0 +1,429 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                David J. Gardner @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * These test functions are designed to check a SUNLinSol module
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <math.h> /* include isnan */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test_sunlinsol.h"
+
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+#include <time.h>
+#include <unistd.h>
+#endif
+
+
+/* private functions */
+static double get_time();
+
+int print_time = 0;
+
+#define PRINT_TIME(format, time) if(print_time) printf(format, time)
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolGetType Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolGetType(SUNLinearSolver S, SUNLinearSolver_Type sunid, int myid)
+{
+  double               start_time, stop_time;
+  SUNLinearSolver_Type mysunid;
+
+  start_time = get_time();   
+  mysunid = SUNLinSolGetType(S);
+  stop_time = get_time();   
+
+  if (sunid != mysunid) {
+    printf(">>> FAILED test -- SUNLinSolGetType, Proc %d \n", myid);
+    PRINT_TIME("    SUNLinSolGetType Time: %22.15e \n \n", stop_time - start_time);
+    return(1);
+  } else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolGetType \n");
+    PRINT_TIME("    SUNLinSolGetType Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Test_SUNLinSolLastFlag Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolLastFlag(SUNLinearSolver S, int myid)
+{
+  double   start_time, stop_time;
+  long int lastflag;
+
+  /* the only way to fail this test is if the function is NULL, 
+     which will cause a seg-fault */
+  start_time = get_time();   
+  lastflag = SUNLinSolLastFlag(S);
+  stop_time = get_time();   
+
+  if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolLastFlag (%ld) \n", lastflag);
+    PRINT_TIME("    SUNLinSolLastFlag Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * Test_SUNLinSolSpace Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolSpace(SUNLinearSolver S, int myid)
+{
+  int      failure;
+  double   start_time, stop_time;
+  long int lenrw, leniw;
+
+  /* call SUNLinSolSpace (failure based on output flag) */
+  start_time = get_time();   
+  failure = SUNLinSolSpace(S, &lenrw, &leniw);
+  stop_time = get_time();   
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolSpace, Proc %d \n", myid);
+    PRINT_TIME("    SUNLinSolSpace Time: %22.15e \n \n", stop_time - start_time);
+    return(1);
+  } else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolSpace, lenrw = %li, leniw = %li\n", lenrw, leniw);
+    PRINT_TIME("    SUNLinSolSpace Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolNumIters Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolNumIters(SUNLinearSolver S, int myid)
+{
+  int    numiters;
+  double start_time, stop_time;
+
+  /* the only way to fail this test is if the function is NULL, 
+     which will cause a seg-fault */
+  start_time = get_time();   
+  numiters = SUNLinSolNumIters(S);
+  stop_time = get_time();   
+
+  if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolNumIters (%d) \n", numiters);
+    PRINT_TIME("    SUNLinSolNumIters Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolResNorm Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolResNorm(SUNLinearSolver S, int myid)
+{
+  double start_time, stop_time, resnorm;
+
+  /* this test can fail if the function is NULL, which will cause a seg-fault */
+  start_time = get_time();   
+  resnorm = (double) SUNLinSolResNorm(S);
+  stop_time = get_time();   
+
+  /* this test can also fail if the return value is negative */
+  if (resnorm < ZERO){
+    printf(">>> FAILED test -- SUNLinSolResNorm returned %g on Proc %d \n", 
+           resnorm, myid);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolResNorm\n");
+    PRINT_TIME("    SUNLinSolResNorm Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolResid Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolResid(SUNLinearSolver S, int myid)
+{
+  double start_time, stop_time;
+  N_Vector resid;
+
+  /* this test can fail if the function returns NULL */
+  start_time = get_time();
+  resid = SUNLinSolResid(S);
+  stop_time = get_time();   
+
+  /* this test can also fail if the return value is negative */
+  if (resid == NULL){
+    printf(">>> FAILED test -- SUNLinSolResid returned NULL N_Vector on Proc %d \n", 
+           myid);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolResid\n");
+    PRINT_TIME("    SUNLinSolResid Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolSetATimes Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolSetATimes(SUNLinearSolver S, void *ATdata,
+                            ATimesFn ATimes, int myid)
+{
+  int     failure;
+  double  start_time, stop_time;
+
+  /* try calling SetATimes routine: should pass/fail based on expected input */
+  start_time = get_time();
+  failure = SUNLinSolSetATimes(S, ATdata, ATimes);
+  stop_time = get_time(); 
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolSetATimes returned %d on Proc %d \n", 
+           failure, myid);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolSetATimes \n");
+    PRINT_TIME("    SUNLinSolSetATimes Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolSetPreconditioner
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolSetPreconditioner(SUNLinearSolver S, void *Pdata,
+                                    PSetupFn PSetup, PSolveFn PSolve, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+
+  /* try calling SetPreconditioner routine: should pass/fail based on expected input */
+  start_time = get_time();
+  failure = SUNLinSolSetPreconditioner(S, Pdata, PSetup, PSolve);
+  stop_time = get_time(); 
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolSetPreconditioner returned %d on Proc %d \n", 
+           failure, myid);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolSetPreconditioner \n");
+    PRINT_TIME("    SUNLinSolSetPreconditioner Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolSetScalingVectors
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolSetScalingVectors(SUNLinearSolver S, N_Vector s1,
+                                    N_Vector s2, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+
+  /* try calling SetScalingVectors routine: should pass/fail based on expected input */
+  start_time = get_time();
+  failure = SUNLinSolSetScalingVectors(S, s1, s2);
+  stop_time = get_time(); 
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolSetScalingVectors returned %d on Proc %d \n", 
+           failure, myid);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolSetScalingVectors \n");
+    PRINT_TIME("    SUNLinSolSetScalingVectors Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolInitialize Test
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolInitialize(SUNLinearSolver S, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+
+  start_time = get_time(); 
+  failure = SUNLinSolInitialize(S);
+  stop_time = get_time(); 
+  
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolInitialize check, Proc %d \n", myid);
+    PRINT_TIME("    SUNLinSolInitialize Time: %22.15e \n \n", stop_time - start_time);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolInitialize \n");
+    PRINT_TIME("    SUNLinSolInitialize Time: %22.15e \n \n", stop_time - start_time);
+  }    
+  
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolSetup Test
+ *
+ * This test must follow Test_SUNLinSolInitialize
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolSetup(SUNLinearSolver S, SUNMatrix A, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+
+  start_time = get_time();
+  failure = SUNLinSolSetup(S, A);
+  stop_time = get_time(); 
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolSetup check, Proc %d \n", myid);
+    PRINT_TIME("    SUNLinSolSetup Time: %22.15e \n \n", stop_time - start_time);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolSetup \n");
+    PRINT_TIME("    SUNLinSolSetup Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNLinSolSolve Test
+ *
+ * This test must follow Test_SUNLinSolSetup.  Also, x must be the 
+ * solution to the linear system A*x = b (for the original A matrix); 
+ * while the 'A' that is supplied to this function should have been 
+ * 'setup' by the Test_SUNLinSolSetup() function prior to this call.
+ * --------------------------------------------------------------------*/
+int Test_SUNLinSolSolve(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                        N_Vector b, realtype tol, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+  N_Vector  y;
+
+  /* clone to create solution vector */
+  y = N_VClone(x);
+  N_VConst(ZERO, y);
+
+  /* perform solve */
+  start_time = get_time();
+  failure = SUNLinSolSolve(S, A, y, b, tol);
+  stop_time = get_time(); 
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolSolve returned %d on Proc %d \n", 
+           failure, myid);
+  }
+  if (failure < 0) {
+    N_VDestroy(y);
+    return(1);
+  }
+
+  /* Check solution, and copy y into x for return */
+  failure = check_vector(x, y, 10.0*tol);
+  N_VScale(ONE, y, x);
+  if (failure) {
+    printf(">>> FAILED test -- SUNLinSolSolve check, Proc %d \n", myid);
+    PRINT_TIME("    SUNLinSolSolve Time: %22.15e \n \n", stop_time - start_time);
+    N_VDestroy(y);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNLinSolSolve \n");
+    PRINT_TIME("    SUNLinSolSolve Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  N_VDestroy(y);
+  return(0);
+}
+
+
+/* ======================================================================
+ * Private functions
+ * ====================================================================*/
+
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+time_t base_time_tv_sec = 0; /* Base time; makes time values returned
+                                by get_time easier to read when
+                                printed since they will be zero
+                                based.
+                              */
+#endif
+
+void SetTiming(int onoff)
+{
+   print_time = onoff;
+
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+  struct timespec spec;  
+  clock_gettime( CLOCK_MONOTONIC_RAW, &spec );
+  base_time_tv_sec = spec.tv_sec;
+#endif
+}
+
+/* ----------------------------------------------------------------------
+ * Timer
+ * --------------------------------------------------------------------*/
+static double get_time()
+{
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+  struct timespec spec;  
+  clock_gettime( CLOCK_MONOTONIC_RAW, &spec );
+  double time = (double)(spec.tv_sec - base_time_tv_sec) + ((double)(spec.tv_nsec) / 1E9);
+#else
+  double time = 0;
+#endif
+  return time;
+}
+
+
diff --git a/examples/sunlinsol/test_sunlinsol.h b/examples/sunlinsol/test_sunlinsol.h
new file mode 100644
index 0000000..9984d5e
--- /dev/null
+++ b/examples/sunlinsol/test_sunlinsol.h
@@ -0,0 +1,67 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file contains the prototypes for functions to 
+ * test SUNLinearSolver module implementations. 
+ * -----------------------------------------------------------------
+ */
+
+#include <math.h>
+
+/* define constatnts */
+#define ZERO     RCONST(0.0)
+#define ONE      RCONST(1.0)
+
+/* NAN and floating point "equality" check, failure update macro */
+#if __STDC_VERSION__ >= 199901L
+#define FNEQ(a,b,tol) (isnan(a) ? 1 : ( SUNRabs((a)-(b)) > tol ))
+#else
+#define FNEQ(a,b,tol) (( SUNRabs((a)-(b)) > tol ))
+#endif
+
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+  /* Forward declarations for implementation specific utility functions */
+  int check_vector(N_Vector X, N_Vector Y, realtype tol);
+   
+  /* Test function declarations */
+  int Test_SUNLinSolGetType(SUNLinearSolver S, SUNLinearSolver_Type sunid, int myid);
+  int Test_SUNLinSolLastFlag(SUNLinearSolver S, int myid);
+  int Test_SUNLinSolSpace(SUNLinearSolver S, int myid);
+  int Test_SUNLinSolNumIters(SUNLinearSolver S, int myid);
+  int Test_SUNLinSolResNorm(SUNLinearSolver S, int myid);
+  int Test_SUNLinSolResid(SUNLinearSolver S, int myid);
+  int Test_SUNLinSolSetATimes(SUNLinearSolver S, void *ATdata,
+                              ATimesFn ATimes, int myid);
+  int Test_SUNLinSolSetPreconditioner(SUNLinearSolver S, void *Pdata,
+                                      PSetupFn PSetup, PSolveFn PSolve, int myid);
+  int Test_SUNLinSolSetScalingVectors(SUNLinearSolver S, N_Vector s1, 
+                                      N_Vector s2, int myid);
+  int Test_SUNLinSolInitialize(SUNLinearSolver S, int myid);
+  int Test_SUNLinSolSetup(SUNLinearSolver S, SUNMatrix A, int myid);
+  int Test_SUNLinSolSolve(SUNLinearSolver S, SUNMatrix A, N_Vector x,
+                          N_Vector b, realtype tol, int myid);
+
+  /* Timing function */
+  void SetTiming(int onoff);
+  
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/sunmatrix/band/CMakeLists.txt b/examples/sunmatrix/band/CMakeLists.txt
new file mode 100644
index 0000000..c197d13
--- /dev/null
+++ b/examples/sunmatrix/band/CMakeLists.txt
@@ -0,0 +1,161 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+#                David J. Gardner @ LLNL
+# -----------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for banded sunmatrix examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS banded matrix
+SET(sunmatrix_band_examples
+  "test_sunmatrix_band\;10 2 3 0\;"
+  "test_sunmatrix_band\;300 7 4 0\;"
+  "test_sunmatrix_band\;1000 8 8 0\;"
+  "test_sunmatrix_band\;5000 3 20 0\;"
+)
+
+# Dependencies for sunmatrix examples
+SET(sunmatrix_band_dependencies
+  test_sunmatrix
+  sundials_nvector
+  sundials_matrix
+)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVECS_LIB sundials_nvecserial_static)
+  SET(SUNMATS_LIB sundials_sunmatrixband_static)
+ELSE()
+  SET(NVECS_LIB sundials_nvecserial_shared)
+  SET(SUNMATS_LIB sundials_sunmatrixband_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVECS_LIB} ${SUNMATS_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunmatrix_band_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunmatrix.c ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunmatrix.c
+      ../test_sunmatrix.h
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/band)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunmatrix_band_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/band)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunmatrixband")
+
+  EXAMPLES2STRING(sunmatrix_band_examples EXAMPLES)
+  EXAMPLES2STRING(sunmatrix_band_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunmatrix/band/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunmatrix/band/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/band
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunmatrix/band/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunmatrix/band/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/band
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunmatrix/band/test_sunmatrix_band.c b/examples/sunmatrix/band/test_sunmatrix_band.c
new file mode 100644
index 0000000..4f3893c
--- /dev/null
+++ b/examples/sunmatrix/band/test_sunmatrix_band.c
@@ -0,0 +1,264 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNMatrix Band module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunmatrix.h"
+
+
+/* ----------------------------------------------------------------------
+ * Main SUNMatrix Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int          fails = 0;            /* counter for test failures  */
+  sunindextype cols, uband, lband;   /* matrix columns, bandwidths */
+  SUNMatrix    A, I;                 /* test matrices              */
+  N_Vector     x, y;                 /* test vectors               */
+  int          print_timing;
+  sunindextype i, j, k, kstart, kend, jstart, jend;
+  realtype     *colj, *xdata, *ydata;
+
+  /* check input and set vector length */
+  if (argc < 5){
+    printf("ERROR: FOUR (4) Inputs required: matrix cols, matrux uband, matrix lband, print timing \n");
+    return(-1);
+  }
+
+  cols = atol(argv[1]); 
+  if (cols <= 0) {
+    printf("ERROR: number of matrix columns must be a positive integer \n");
+    return(-1); 
+  }
+
+  uband = atol(argv[2]); 
+  if ((uband <= 0) || (uband >= cols)){
+    printf("ERROR: matrix upper bandwidth must be a positive integer, less than number of columns \n");
+    return(-1); 
+  }
+
+  lband = atol(argv[3]); 
+  if ((lband <= 0) || (lband >= cols)){
+    printf("ERROR: matrix lower bandwidth must be a positive integer, less than number of columns \n");
+    return(-1); 
+  }
+
+  print_timing = atoi(argv[4]);
+  SetTiming(print_timing);
+
+  printf("\nBand matrix test: size %ld, bandwidths %ld %ld\n\n",
+         (long int) cols, (long int) uband, (long int) lband);
+
+  /* Create matrices and vectors */
+  A = SUNBandMatrix(cols, uband, lband, uband);
+  I = SUNBandMatrix(cols, 0, 0, 0);
+  x = N_VNew_Serial(cols);
+  y = N_VNew_Serial(cols);
+
+  /* Fill matrices */
+  xdata = N_VGetArrayPointer(x);
+  ydata = N_VGetArrayPointer(y);
+  for (j=0; j<cols; j++) {
+    
+    /* identity matrix */
+    colj = SUNBandMatrix_Column(I, j);
+    colj[0] = RCONST(1.0);
+
+    /* A matrix */
+    colj = SUNBandMatrix_Column(A, j);
+    kstart = (j<uband) ? -j : -uband;
+    kend = (j>cols-1-lband) ? cols-1-j: lband;
+    for (k=kstart; k<=kend; k++)
+      colj[k] = j - k;    /* A(i,j) = j + (j-i) */
+  }
+
+  /* Fill vectors */
+  for (i=0; i<cols; i++) {
+
+    /* x vector */
+    xdata[i] = i;
+
+    /* y vector */
+    ydata[i] = RCONST(0.0);
+    jstart = SUNMAX(0, i-lband);
+    jend = SUNMIN(cols-1, i+uband);
+    for (j=jstart; j<=jend; j++)
+      ydata[i] += (j+j-i)*(j);
+  }
+
+  /* Run Tests */
+  fails += Test_SUNMatGetID(A, SUNMATRIX_BAND, 0);
+  fails += Test_SUNMatClone(A, 0);
+  fails += Test_SUNMatCopy(A, 0);
+  fails += Test_SUNMatZero(A, 0);
+  fails += Test_SUNMatScaleAdd(A, I, 0);
+  fails += Test_SUNMatScaleAddI(A, I, 0);
+  fails += Test_SUNMatMatvec(A, x, y, 0);
+  fails += Test_SUNMatSpace(A, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNMatrix module failed %i tests \n \n", fails);
+    printf("\nA =\n");
+    SUNBandMatrix_Print(A,stdout);
+    printf("\nI =\n");
+    SUNBandMatrix_Print(I,stdout);
+    printf("\nx =\n");
+    N_VPrint_Serial(x);
+    printf("\ny =\n");
+    N_VPrint_Serial(y);
+  } else {
+    printf("SUCCESS: SUNMatrix module passed all tests \n \n");
+  }
+
+  /* Free matrices and vectors */
+  SUNMatDestroy(A);
+  SUNMatDestroy(I);
+  N_VDestroy(x);
+  N_VDestroy(y);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Implementation-specific 'check' routines
+ * --------------------------------------------------------------------*/
+int check_matrix(SUNMatrix A, SUNMatrix B, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, j, istart, iend;
+  realtype *Acolj, *Bcolj;
+
+  /* check matrix type and dimensions */
+  if (SUNMatGetID(A) != SUNMatGetID(B))
+    return 1;
+  if (SUNBandMatrix_Columns(A) != SUNBandMatrix_Columns(B))
+    return 1;
+  if (SUNBandMatrix_Rows(A) != SUNBandMatrix_Rows(B))
+    return 1;
+  if (SUNBandMatrix_LowerBandwidth(A) != SUNBandMatrix_LowerBandwidth(B))
+    return 1;
+  if (SUNBandMatrix_UpperBandwidth(A) != SUNBandMatrix_UpperBandwidth(B))
+    return 1;
+  
+  /* check matrix data */
+  for (j=0; j<SUNBandMatrix_Columns(A); j++) {
+
+    /* access matrix columns */
+    Acolj = SUNBandMatrix_Column(A, j);
+    Bcolj = SUNBandMatrix_Column(B, j);
+
+    /* compare entries in this column */
+    istart = (j<SUNBandMatrix_UpperBandwidth(A)) ? -j : -SUNBandMatrix_UpperBandwidth(A);
+    iend = (j>SUNBandMatrix_Columns(A)-1-SUNBandMatrix_LowerBandwidth(A)) ?
+      SUNBandMatrix_Columns(A)-1-j : SUNBandMatrix_LowerBandwidth(A);
+    for (i=istart; i<=iend; i++)
+      failure += FNEQ(Acolj[i], Bcolj[i], tol);
+  }
+
+  if (failure > ZERO) {
+    printf("check_matrix failure, A = \n");
+    SUNBandMatrix_Print(A, stdout);
+    printf("B = \n");
+    SUNBandMatrix_Print(B, stdout);
+  }
+
+    
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+int check_matrix_entry(SUNMatrix A, realtype val, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, j, istart, iend;
+  realtype *Acolj;
+
+  /* check matrix data */
+  for (j=0; j<SUNBandMatrix_Columns(A); j++) {
+
+    /* access matrix column */
+    Acolj = SUNBandMatrix_Column(A, j);
+
+    /* compare entries in this column */
+    istart = (j<SUNBandMatrix_UpperBandwidth(A)) ? -j : -SUNBandMatrix_UpperBandwidth(A);
+    iend = (j>SUNBandMatrix_Columns(A)-1-SUNBandMatrix_LowerBandwidth(A)) ?
+      SUNBandMatrix_Columns(A)-1-j : SUNBandMatrix_LowerBandwidth(A);
+    for (i=istart; i<=iend; i++) {
+      if (FNEQ(Acolj[i], val, tol)) {
+        failure++;
+        printf("j = %li, Acolj[%li] = %g, val = %g\n",
+               (long int) j, (long int) i, Acolj[i], val);
+      }
+    }
+  }
+
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+int check_vector(N_Vector X, N_Vector Y, realtype tol)
+{
+  int failure = 0;
+  sunindextype i, local_length;
+  realtype *Xdata, *Ydata;
+  
+  Xdata = N_VGetArrayPointer(X);
+  Ydata = N_VGetArrayPointer(Y);
+  local_length = N_VGetLength_Serial(X);
+  
+  /* check vector data */
+  for(i=0; i < local_length; i++) {
+    failure += FNEQ(Xdata[i], Ydata[i], tol);
+  }
+  
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+booleantype has_data(SUNMatrix A)
+{
+  realtype *Adata = SUNBandMatrix_Data(A);
+  if (Adata == NULL)
+    return SUNFALSE;
+  else
+    return SUNTRUE;
+}
+
+booleantype is_square(SUNMatrix A)
+{
+  return SUNTRUE;
+}
+
diff --git a/examples/sunmatrix/dense/CMakeLists.txt b/examples/sunmatrix/dense/CMakeLists.txt
new file mode 100644
index 0000000..b74e519
--- /dev/null
+++ b/examples/sunmatrix/dense/CMakeLists.txt
@@ -0,0 +1,160 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+#                David J. Gardner @ LLNL
+# -----------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for dense sunmatrix examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS dense matrix
+SET(sunmatrix_dense_examples
+  "test_sunmatrix_dense\;100 100 0\;"
+  "test_sunmatrix_dense\;200 1000 0\;"
+  "test_sunmatrix_dense\;2000 100 0\;"
+  )
+
+# Dependencies for sunmatrix examples
+SET(sunmatrix_dense_dependencies
+  test_sunmatrix
+  sundials_nvector
+  sundials_matrix
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVECS_LIB sundials_nvecserial_static)
+  SET(SUNMATS_LIB sundials_sunmatrixdense_static)
+ELSE()
+  SET(NVECS_LIB sundials_nvecserial_shared)
+  SET(SUNMATS_LIB sundials_sunmatrixdense_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVECS_LIB} ${SUNMATS_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunmatrix_dense_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunmatrix.c ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunmatrix.c
+      ../test_sunmatrix.h
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/dense)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunmatrix_dense_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/dense)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunmatrixdense")
+
+  EXAMPLES2STRING(sunmatrix_dense_examples EXAMPLES)
+  EXAMPLES2STRING(sunmatrix_dense_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunmatrix/dense/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunmatrix/dense/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/dense
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunmatrix/dense/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunmatrix/dense/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/dense
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunmatrix/dense/test_sunmatrix_dense.c b/examples/sunmatrix/dense/test_sunmatrix_dense.c
new file mode 100644
index 0000000..a31741b
--- /dev/null
+++ b/examples/sunmatrix/dense/test_sunmatrix_dense.c
@@ -0,0 +1,263 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNMatrix Dense module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunmatrix.h"
+
+
+/* ----------------------------------------------------------------------
+ * Main SUNMatrix Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int          fails = 0;        /* counter for test failures  */
+  sunindextype matrows, matcols; /* vector length              */
+  N_Vector     x, y;             /* test vectors               */
+  realtype     *xdata, *ydata;   /* pointers to vector data    */
+  SUNMatrix    A, I;             /* test matrices              */
+  realtype     *Adata, *Idata;   /* pointers to matrix data    */
+  int          print_timing, square;
+  sunindextype i, j, m, n;
+
+  /* check input and set vector length */
+  if (argc < 4){
+    printf("ERROR: THREE (3) Input required: matrix rows, matrix cols, print timing \n");
+    return(-1);
+  }
+  
+  matrows = atol(argv[1]); 
+  if (matrows <= 0) {
+    printf("ERROR: number of rows must be a positive integer \n");
+    return(-1); 
+  }
+  
+  matcols = atol(argv[2]); 
+  if (matcols <= 0) {
+    printf("ERROR: number of cols must be a positive integer \n");
+    return(-1); 
+  }
+
+  print_timing = atoi(argv[3]);
+  SetTiming(print_timing);
+  
+  square = (matrows == matcols) ? 1 : 0;
+  printf("\nDense matrix test: size %ld by %ld\n\n",
+         (long int) matrows, (long int) matcols);
+  
+  /* Create vectors and matrices */
+  x = N_VNew_Serial(matcols);
+  y = N_VNew_Serial(matrows);
+  A = SUNDenseMatrix(matrows, matcols);
+  if (square)
+    I = SUNDenseMatrix(matrows, matcols);
+  
+  /* Fill matrices and vectors */
+  Adata = SUNDenseMatrix_Data(A);
+  for(j=0; j < matcols; j++) {
+    for(i=0; i < matrows; i++) {
+      Adata[j*matrows + i] = (j+1)*(i+j);
+    }
+  }
+
+  if (square) {
+    Idata = SUNDenseMatrix_Data(I);
+    for(i=0, j=0; i < matrows; i++, j++) {
+      Idata[j*matrows + i] = ONE;
+    }
+  }
+
+  xdata = N_VGetArrayPointer(x);
+  for(i=0; i < matcols; i++) {
+    xdata[i] = ONE / (i+1);
+  }
+
+  ydata = N_VGetArrayPointer(y);
+  for(i=0; i < matrows; i++) {
+    m = i;
+    n = m + matcols - 1;
+    ydata[i] = HALF*(n+1-m)*(n+m);
+  }
+    
+  /* SUNMatrix Tests */
+  fails += Test_SUNMatGetID(A, SUNMATRIX_DENSE, 0);
+  fails += Test_SUNMatClone(A, 0);
+  fails += Test_SUNMatCopy(A, 0);
+  fails += Test_SUNMatZero(A, 0);
+  fails += Test_SUNMatScaleAdd(A, I, 0);
+  if (square) 
+    fails += Test_SUNMatScaleAddI(A, I, 0);
+  fails += Test_SUNMatMatvec(A, x, y, 0);
+  fails += Test_SUNMatSpace(A, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNMatrix module failed %i tests \n \n", fails);
+    printf("\nA =\n");
+    SUNDenseMatrix_Print(A,stdout);
+    if (square) {
+      printf("\nI =\n");
+      SUNDenseMatrix_Print(I,stdout);
+    }
+    printf("\nx =\n");
+    N_VPrint_Serial(x);
+    printf("\ny =\n");
+    N_VPrint_Serial(y);
+  } else {
+    printf("SUCCESS: SUNMatrix module passed all tests \n \n");
+  }
+
+  /* Free vectors and matrices */
+  N_VDestroy_Serial(x);
+  N_VDestroy_Serial(y);
+  SUNMatDestroy(A);
+  if (square)
+    SUNMatDestroy(I);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Check matrix
+ * --------------------------------------------------------------------*/
+int check_matrix(SUNMatrix A, SUNMatrix B, realtype tol)
+{
+  int failure = 0;
+  realtype *Adata, *Bdata;
+  sunindextype Aldata, Bldata;
+  sunindextype i;
+  
+  /* get data pointers */
+  Adata = SUNDenseMatrix_Data(A);
+  Bdata = SUNDenseMatrix_Data(B);
+
+  /* get and check data lengths */
+  Aldata = SUNDenseMatrix_LData(A);
+  Bldata = SUNDenseMatrix_LData(B);
+
+  if (Aldata != Bldata) {
+    printf(">>> ERROR: check_matrix: Different data array lengths \n");
+    return(1);
+  }
+  
+  /* compare data */
+  for(i=0; i < Aldata; i++){
+    failure += FNEQ(Adata[i], Bdata[i], tol);
+  }
+
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+int check_matrix_entry(SUNMatrix A, realtype val, realtype tol)
+{
+  int failure = 0;
+  realtype *Adata;
+  sunindextype Aldata;
+  sunindextype i;
+  
+  /* get data pointer */
+  Adata = SUNDenseMatrix_Data(A);
+
+  /* compare data */
+  Aldata = SUNDenseMatrix_LData(A);
+  for(i=0; i < Aldata; i++){
+    failure += FNEQ(Adata[i], val, tol);
+  }
+
+  if (failure > ZERO) {
+    printf("Check_matrix_entry failures:\n");
+    for(i=0; i < Aldata; i++)
+      if (FNEQ(Adata[i], val, tol) != 0)
+        printf("  Adata[%ld] = %g != %g (err = %g)\n", (long int) i,
+               Adata[i], val, SUNRabs(Adata[i]-val));
+  }
+  
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+int check_vector(N_Vector x, N_Vector y, realtype tol)
+{
+  int failure = 0;
+  realtype *xdata, *ydata;
+  sunindextype xldata, yldata;
+  sunindextype i;
+
+  /* get vector data */
+  xdata = N_VGetArrayPointer(x);
+  ydata = N_VGetArrayPointer(y);
+
+  /* check data lengths */
+  xldata = N_VGetLength_Serial(x);
+  yldata = N_VGetLength_Serial(y);
+
+  if (xldata != yldata) {
+    printf(">>> ERROR: check_vector: Different data array lengths \n");
+    return(1);
+  }
+
+  /* check vector data */
+  for(i=0; i < xldata; i++)
+    failure += FNEQ(xdata[i], ydata[i], tol);
+
+  if (failure > ZERO) {
+    printf("Check_vector failures:\n");
+    for(i=0; i < xldata; i++)
+      if (FNEQ(xdata[i], ydata[i], tol) != 0)
+        printf("  xdata[%ld] = %g != %g (err = %g)\n", (long int) i,
+               xdata[i], ydata[i], SUNRabs(xdata[i]-ydata[i]));
+  }
+  
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+booleantype has_data(SUNMatrix A)
+{
+  realtype *Adata = SUNDenseMatrix_Data(A);
+  if (Adata == NULL)
+    return SUNFALSE;
+  else
+    return SUNTRUE;
+}
+
+booleantype is_square(SUNMatrix A)
+{
+  if (SUNDenseMatrix_Rows(A) == SUNDenseMatrix_Columns(A))
+    return SUNTRUE;
+  else
+    return SUNFALSE;
+}
diff --git a/examples/sunmatrix/sparse/CMakeLists.txt b/examples/sunmatrix/sparse/CMakeLists.txt
new file mode 100644
index 0000000..d02e11f
--- /dev/null
+++ b/examples/sunmatrix/sparse/CMakeLists.txt
@@ -0,0 +1,172 @@
+# ---------------------------------------------------------------
+# Programmer(s): Daniel Reynolds @ SMU
+#                David J. Gardner @ LLNL
+# -----------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for sparse sunmatrix examples
+# ---------------------------------------------------------------
+
+# Example lists are tuples "name\;args\;type" where the type is
+# 'develop' for examples excluded from 'make test' in releases
+
+# Examples using SUNDIALS sparse matrix
+SET(sunmatrix_sparse_examples
+  "test_sunmatrix_sparse\;400 400 0 0\;"
+  "test_sunmatrix_sparse\;450 450 1 0\;"
+  "test_sunmatrix_sparse\;200 1000 0 0\;"
+  "test_sunmatrix_sparse\;6000 350 0 0\;"
+  "test_sunmatrix_sparse\;500 5000 1 0\;"
+  "test_sunmatrix_sparse\;4000 800 1 0\;"
+)
+
+# Dependencies for sunmatrix examples
+SET(sunmatrix_sparse_dependencies
+  test_sunmatrix
+  sundials_nvector
+  sundials_matrix
+)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(. ..)
+
+# Specify libraries to link against (through the target that was used to 
+# generate them) based on the value of the variable LINK_LIBRARY_TYPE
+IF(LINK_LIBRARY_TYPE MATCHES "static")
+  SET(NVECS_LIB sundials_nvecserial_static)
+  SET(SUNMATS_LIB sundials_sunmatrixdense_static)
+  LIST(APPEND SUNMATS_LIB sundials_sunmatrixband_static)
+  LIST(APPEND SUNMATS_LIB sundials_sunmatrixsparse_static)
+ELSE()
+  SET(NVECS_LIB sundials_nvecserial_shared)
+  SET(SUNMATS_LIB sundials_sunmatrixdense_shared)
+  LIST(APPEND SUNMATS_LIB sundials_sunmatrixband_shared)
+  LIST(APPEND SUNMATS_LIB sundials_sunmatrixsparse_shared)
+ENDIF()
+
+# Set-up linker flags and link libraries
+SET(SUNDIALS_LIBS ${NVECS_LIB} ${SUNMATS_LIB} ${EXTRA_LINK_LIBS})
+
+
+# Add the build and install targets for each example
+FOREACH(example_tuple ${sunmatrix_sparse_examples})
+
+  # parse the example tuple
+  LIST(GET example_tuple 0 example)
+  LIST(GET example_tuple 1 example_args)
+  LIST(GET example_tuple 2 example_type)
+
+  # This is used to get around DLL linkage issue since we are
+  # manually including sundials_nvector.c here, which is normally in
+  # a library that is included.  If this is not set build system
+  # thinks nvector is externally linked.
+  IF(WIN32)
+    ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+  ENDIF(WIN32)
+
+  # check if this example has already been added, only need to add
+  # example source files once for testing with different inputs
+  IF(NOT TARGET ${example})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c
+      ../test_sunmatrix.c ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_nvector.c)
+
+    # folder to organize targets in an IDE
+    SET_TARGET_PROPERTIES(${example} PROPERTIES FOLDER "Examples")
+    
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  ENDIF()
+
+  # check if example args are provided and set the test name
+  IF("${example_args}" STREQUAL "")
+    SET(test_name ${example})
+  ELSE()
+    STRING(REGEX REPLACE " " "_" test_name ${example}_${example_args})
+  ENDIF()
+
+  # add example to regression tests
+  SUNDIALS_ADD_TEST(${test_name} ${example}
+    TEST_ARGS ${example_args}
+    EXAMPLE_TYPE ${example_type}
+    NODIFF)
+
+  # install example source files
+  IF(EXAMPLES_INSTALL)
+    INSTALL(FILES ${example}.c
+      ../test_sunmatrix.c
+      ../test_sunmatrix.h
+      ../../../src/sundials/sundials_matrix.c
+      ../../../src/sundials/sundials_nvector.c
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/sparse)
+  ENDIF()
+
+ENDFOREACH(example_tuple ${sunmatrix_sparse_examples})
+
+
+IF(EXAMPLES_INSTALL)
+
+  # Install the README file
+  INSTALL(FILES DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/sparse)
+
+  # Prepare substitution variables for Makefile and/or CMakeLists templates
+  SET(SOLVER_LIB "sundials_sunmatrixsparse")
+  SET(LIBS "${LIBS} -lsundials_sunmatrixdense -lsundials_sunmatrixband")
+
+  # Set the link directory for the dense and band sunmatrix libraries
+  # The generated CMakeLists.txt does not use find_library() locate them
+  SET(EXTRA_LIBS_DIR "${libdir}")
+
+  EXAMPLES2STRING(sunmatrix_sparse_examples EXAMPLES)
+  EXAMPLES2STRING(sunmatrix_sparse_dependencies EXAMPLES_DEPENDENCIES)
+
+  # Regardless of the platform we're on, we will generate and install 
+  # CMakeLists.txt file for building the examples. This file  can then 
+  # be used as a template for the user's own programs.
+
+  # generate CMakelists.txt in the binary directory
+  CONFIGURE_FILE(
+    ${PROJECT_SOURCE_DIR}/examples/templates/cmakelists_serial_C_ex.in
+    ${PROJECT_BINARY_DIR}/examples/sunmatrix/sparse/CMakeLists.txt
+    @ONLY
+    )
+
+  # install CMakelists.txt
+  INSTALL(
+    FILES ${PROJECT_BINARY_DIR}/examples/sunmatrix/sparse/CMakeLists.txt
+    DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/sparse
+    )
+
+  # On UNIX-type platforms, we also  generate and install a makefile for 
+  # building the examples. This makefile can then be used as a template 
+  # for the user's own programs.
+
+  IF(UNIX)
+    # generate Makefile and place it in the binary dir
+    CONFIGURE_FILE(
+      ${PROJECT_SOURCE_DIR}/examples/templates/makefile_serial_C_ex.in
+      ${PROJECT_BINARY_DIR}/examples/sunmatrix/sparse/Makefile_ex
+      @ONLY
+      )
+    # install the configured Makefile_ex as Makefile
+    INSTALL(
+      FILES ${PROJECT_BINARY_DIR}/examples/sunmatrix/sparse/Makefile_ex 
+      DESTINATION ${EXAMPLES_INSTALL_PATH}/sunmatrix/sparse
+      RENAME Makefile
+      )
+  ENDIF(UNIX)
+
+ENDIF(EXAMPLES_INSTALL)
diff --git a/examples/sunmatrix/sparse/test_sunmatrix_sparse.c b/examples/sunmatrix/sparse/test_sunmatrix_sparse.c
new file mode 100644
index 0000000..0336d62
--- /dev/null
+++ b/examples/sunmatrix/sparse/test_sunmatrix_sparse.c
@@ -0,0 +1,509 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the testing routine to check the SUNMatrix Sparse module 
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sundials/sundials_types.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+#include <nvector/nvector_serial.h>
+#include <sundials/sundials_math.h>
+#include "test_sunmatrix.h"
+
+
+/* ----------------------------------------------------------------------
+ * Main SUNMatrix Testing Routine
+ * --------------------------------------------------------------------*/
+int main(int argc, char *argv[]) 
+{
+  int          fails=0;                    /* counter for test failures  */
+  sunindextype matrows, matcols;           /* matrix dims                */
+  int          mattype;                    /* matrix storage type        */
+  N_Vector     x, y;                       /* test vectors               */
+  realtype*    vecdata;                    /* pointers to vector data    */
+  SUNMatrix    A, B, C, D, I;              /* test matrices              */
+  realtype*    matdata;                    /* pointer to matrix data     */
+  sunindextype i, j, k, kstart, kend, N, uband, lband, suband;
+  sunindextype *colptrs, *rowindices;
+  sunindextype *rowptrs, *colindices;
+  int          print_timing, square; 
+
+  /* check input and set vector length */
+  if (argc < 5){
+    printf("ERROR: FOUR (4) Input required: matrix rows, matrix cols, matrix type (0/1), print timing \n");
+    return(-1);
+  }
+  
+  matrows = atol(argv[1]); 
+  if (matrows < 1) {
+    printf("ERROR: number of rows must be a positive integer\n");
+    return(-1); 
+  }
+  
+  matcols = atol(argv[2]); 
+  if (matcols < 1) {
+    printf("ERROR: number of cols must be a positive integer\n");
+    return(-1); 
+  }
+  
+  k = atol(argv[3]); 
+  if ((k != 0) && (k != 1)) {
+    printf("ERROR: matrix type must be 0 or 1\n");
+    return(-1); 
+  }
+  mattype = (k == 0) ? CSC_MAT : CSR_MAT;
+  
+  print_timing = atoi(argv[4]);
+  SetTiming(print_timing);
+  
+  square = (matrows == matcols) ? 1 : 0;
+  printf("\nSparse matrix test: size %ld by %ld, type = %i\n\n",
+         (long int) matrows, (long int) matcols, mattype);
+
+    
+  /* check creating sparse matrix from dense matrix */
+  B = SUNDenseMatrix(5,6);
+  
+  matdata = SUNDenseMatrix_Data(B);
+  matdata[2]  = RCONST(1.0);    /* [ 0 2 0 0 7 0 ] */
+  matdata[5]  = RCONST(2.0);    /* [ 0 0 4 0 8 0 ] */
+  matdata[9]  = RCONST(3.0);    /* [ 1 0 0 0 0 0 ] */
+  matdata[11] = RCONST(4.0);    /* [ 0 0 5 6 0 0 ] */
+  matdata[13] = RCONST(5.0);    /* [ 0 3 0 0 0 9 ] */
+  matdata[18] = RCONST(6.0);
+  matdata[20] = RCONST(7.0);
+  matdata[21] = RCONST(8.0);
+  matdata[29] = RCONST(9.0);
+
+  if (mattype == CSR_MAT) {
+
+    /* Check CSR */
+    C = SUNSparseMatrix(5, 6, 9, CSR_MAT);
+    rowptrs = SUNSparseMatrix_IndexPointers(C);
+    colindices = SUNSparseMatrix_IndexValues(C);
+    matdata = SUNSparseMatrix_Data(C);
+    rowptrs[0] = 0;
+    matdata[0] = RCONST(2.0);   colindices[0] = 1;
+    matdata[1] = RCONST(7.0);   colindices[1] = 4;
+    rowptrs[1] = 2;
+    matdata[2] = RCONST(4.0);   colindices[2] = 2;
+    matdata[3] = RCONST(8.0);   colindices[3] = 4;
+    rowptrs[2] = 4;
+    matdata[4] = RCONST(1.0);   colindices[4] = 0;
+    rowptrs[3] = 5;
+    matdata[5] = RCONST(5.0);   colindices[5] = 2;
+    matdata[6] = RCONST(6.0);   colindices[6] = 3;
+    rowptrs[4] = 7;
+    matdata[7] = RCONST(3.0);   colindices[7] = 1;
+    matdata[8] = RCONST(9.0);   colindices[8] = 5;
+    rowptrs[5] = 9;
+
+    A = SUNSparseFromDenseMatrix(B, ZERO, CSR_MAT);
+    fails += check_matrix(A, C, 1e-15);
+
+    if (fails) {
+      printf("FAIL: SUNMatrix SparseFromDense CSR conversion failed\n");
+      return(1);
+    }
+
+    SUNMatDestroy(A);
+    SUNMatDestroy(C);
+
+  } else {
+  
+    /* Check CSC */
+    D = SUNSparseMatrix(5, 6, 9, CSC_MAT);
+    colptrs = SUNSparseMatrix_IndexPointers(D);
+    rowindices = SUNSparseMatrix_IndexValues(D);
+    matdata = SUNSparseMatrix_Data(D);
+    colptrs[0] = 0;
+    matdata[0] = RCONST(1.0);   rowindices[0] = 2;
+    colptrs[1] = 1;
+    matdata[1] = RCONST(2.0);   rowindices[1] = 0;
+    matdata[2] = RCONST(3.0);   rowindices[2] = 4;
+    colptrs[2] = 3;
+    matdata[3] = RCONST(4.0);   rowindices[3] = 1;
+    matdata[4] = RCONST(5.0);   rowindices[4] = 3;
+    colptrs[3] = 5;
+    matdata[5] = RCONST(6.0);   rowindices[5] = 3;
+    colptrs[4] = 6;
+    matdata[6] = RCONST(7.0);   rowindices[6] = 0;
+    matdata[7] = RCONST(8.0);   rowindices[7] = 1;
+    colptrs[5] = 8;
+    matdata[8] = RCONST(9.0);   rowindices[8] = 4;
+    colptrs[6] = 9;
+  
+    A = SUNSparseFromDenseMatrix(B, 1e-15, CSC_MAT);
+    fails += check_matrix(A, D, 1e-15);
+
+    if (fails) {
+      printf("FAIL: SUNMatrix SparseFromDense CSC conversion failed\n");
+      return(1);
+    }
+
+    SUNMatDestroy(A);
+    SUNMatDestroy(D);
+
+  }
+  SUNMatDestroy(B);
+
+  
+  /* check creating sparse matrix from banded matrix */
+  N = 7;
+  uband = 1;
+  lband = 2;                                   /* B(i,j) = j + (j-i) */
+  suband = 3;
+  B = SUNBandMatrix(N, uband, lband, suband);  /* B = [  0  2  0  0  0  0  0 ] */
+  for (j=0; j<N; j++) {                        /*     [ -1  1  3  0  0  0  0 ] */
+    matdata = SUNBandMatrix_Column(B, j);      /*     [ -2  0  2  4  0  0  0 ] */
+    kstart = (j<uband) ? -j : -uband;          /*     [  0 -1  1  3  5  0  0 ] */
+    kend = (j>N-1-lband) ? N-1-j: lband;       /*     [  0  0  0  2  4  6  0 ] */
+    for (k=kstart; k<=kend; k++)               /*     [  0  0  0  1  3  5  7 ] */
+      matdata[k] = j - k;                      /*     [  0  0  0  0  2  4  6 ] */
+  }
+
+  if (mattype == CSR_MAT) {
+
+    /* CSR */
+    C = SUNSparseMatrix(7, 7, 21, CSR_MAT);
+    rowptrs = SUNSparseMatrix_IndexPointers(C);
+    colindices = SUNSparseMatrix_IndexValues(C);
+    matdata = SUNSparseMatrix_Data(C);
+    rowptrs[ 0] = 0;
+    matdata[ 0] = RCONST(2.0);   colindices[ 0] = 1;
+    rowptrs[ 1] = 1;
+    matdata[ 1] = RCONST(-1.0);  colindices[ 1] = 0;
+    matdata[ 2] = RCONST(1.0);   colindices[ 2] = 1;
+    matdata[ 3] = RCONST(3.0);   colindices[ 3] = 2;
+    rowptrs[ 2] = 4;
+    matdata[ 4] = RCONST(-2.0);  colindices[ 4] = 0;
+    matdata[ 5] = RCONST(2.0);   colindices[ 5] = 2;
+    matdata[ 6] = RCONST(4.0);   colindices[ 6] = 3;
+    rowptrs[ 3] = 7;
+    matdata[ 7] = RCONST(-1.0);  colindices[ 7] = 1;
+    matdata[ 8] = RCONST(1.0);   colindices[ 8] = 2;
+    matdata[ 9] = RCONST(3.0);   colindices[ 9] = 3;
+    matdata[10] = RCONST(5.0);   colindices[10] = 4;
+    rowptrs[ 4] = 11;
+    matdata[11] = RCONST(2.0);   colindices[11] = 3;
+    matdata[12] = RCONST(4.0);   colindices[12] = 4;
+    matdata[13] = RCONST(6.0);   colindices[13] = 5;
+    rowptrs[ 5] = 14;
+    matdata[14] = RCONST(1.0);   colindices[14] = 3;
+    matdata[15] = RCONST(3.0);   colindices[15] = 4;
+    matdata[16] = RCONST(5.0);   colindices[16] = 5;
+    matdata[17] = RCONST(7.0);   colindices[17] = 6;
+    rowptrs[ 6] = 18;
+    matdata[18] = RCONST(2.0);   colindices[18] = 4;
+    matdata[19] = RCONST(4.0);   colindices[19] = 5;
+    matdata[20] = RCONST(6.0);   colindices[20] = 6;
+    rowptrs[ 7] = 21;
+  
+    A = SUNSparseFromBandMatrix(B, ZERO, CSR_MAT);
+    fails += check_matrix(A, C, 1e-15);
+
+    if (fails) {
+      printf("FAIL: SUNMatrix SparseFromBand CSR conversion failed\n");
+      return(1);
+    }
+
+    SUNMatDestroy(A);
+    SUNMatDestroy(C);
+
+  } else {
+    
+    /* Check CSC */
+    D = SUNSparseMatrix(7, 7, 21, CSC_MAT);
+    colptrs = SUNSparseMatrix_IndexPointers(D);
+    rowindices = SUNSparseMatrix_IndexValues(D);
+    matdata = SUNSparseMatrix_Data(D);
+    colptrs[ 0] = 0;
+    matdata[ 0] = RCONST(-1.0);  rowindices[ 0] = 1;
+    matdata[ 1] = RCONST(-2.0);  rowindices[ 1] = 2;
+    colptrs[ 1] = 2;
+    matdata[ 2] = RCONST(2.0);   rowindices[ 2] = 0;
+    matdata[ 3] = RCONST(1.0);   rowindices[ 3] = 1;
+    matdata[ 4] = RCONST(-1.0);  rowindices[ 4] = 3;
+    colptrs[ 2] = 5;
+    matdata[ 5] = RCONST(3.0);   rowindices[ 5] = 1;
+    matdata[ 6] = RCONST(2.0);   rowindices[ 6] = 2;
+    matdata[ 7] = RCONST(1.0);   rowindices[ 7] = 3;
+    colptrs[ 3] = 8;
+    matdata[ 8] = RCONST(4.0);   rowindices[ 8] = 2;
+    matdata[ 9] = RCONST(3.0);   rowindices[ 9] = 3;
+    matdata[10] = RCONST(2.0);   rowindices[10] = 4;
+    matdata[11] = RCONST(1.0);   rowindices[11] = 5;
+    colptrs[ 4] = 12;
+    matdata[12] = RCONST(5.0);   rowindices[12] = 3;
+    matdata[13] = RCONST(4.0);   rowindices[13] = 4;
+    matdata[14] = RCONST(3.0);   rowindices[14] = 5;
+    matdata[15] = RCONST(2.0);   rowindices[15] = 6;
+    colptrs[ 5] = 16;
+    matdata[16] = RCONST(6.0);   rowindices[16] = 4;
+    matdata[17] = RCONST(5.0);   rowindices[17] = 5;
+    matdata[18] = RCONST(4.0);   rowindices[18] = 6;
+    colptrs[ 6] = 19;
+    matdata[19] = RCONST(7.0);   rowindices[19] = 5;
+    matdata[20] = RCONST(6.0);   rowindices[20] = 6;
+    colptrs[ 7] = 21;
+
+    A = SUNSparseFromBandMatrix(B, 1e-15, CSC_MAT);
+    fails += check_matrix(A, D, 1e-15);
+
+    if (fails) {
+      printf("FAIL: SUNMatrix SparseFromBand CSC conversion failed\n");
+      return(1);
+    }
+
+    SUNMatDestroy(A);
+    SUNMatDestroy(D);
+  }
+  
+  SUNMatDestroy(B);
+
+
+  /* Create/fill I matrix */
+  if (square) {
+    I = SUNSparseMatrix(matrows, matcols, matcols, mattype);
+    matdata    = SUNSparseMatrix_Data(I);
+    colindices = SUNSparseMatrix_IndexValues(I);
+    rowptrs    = SUNSparseMatrix_IndexPointers(I);
+    for(i=0; i<matrows; i++) {
+      matdata[i] = ONE;
+      colindices[i] = i;
+      rowptrs[i] = i;
+    }
+    rowptrs[matrows] = matrows;
+  }
+  
+  /* Create/fill random dense matrix, create sparse from it */
+  B = SUNDenseMatrix(matrows, matcols);
+  for (k=0; k<3*matrows; k++) {
+    i = rand() % matrows;
+    j = rand() % matcols;
+    matdata = SUNDenseMatrix_Column(B,j);
+    matdata[i] = (realtype) rand() / (realtype) RAND_MAX;
+  }
+  A = SUNSparseFromDenseMatrix(B, ZERO, mattype);
+  
+  /* Create vectors and fill */
+  x = N_VNew_Serial(matcols);
+  y = N_VNew_Serial(matrows);
+  vecdata = N_VGetArrayPointer(x);
+  for(i=0; i<matcols; i++) 
+    vecdata[i] = (realtype) rand() / (realtype) RAND_MAX;
+  if (SUNMatMatvec(B, x, y) != 0) {
+    printf("FAIL: SUNMatrix module Dense matvec failure \n \n");
+    SUNMatDestroy(A);
+    SUNMatDestroy(B);
+    if (square)
+      SUNMatDestroy(I);
+    return(1);
+  }
+    
+  /* SUNMatrix Tests */
+  fails += Test_SUNMatGetID(A, SUNMATRIX_SPARSE, 0);
+  fails += Test_SUNMatClone(A, 0);
+  fails += Test_SUNMatCopy(A, 0);
+  fails += Test_SUNMatZero(A, 0);
+  fails += Test_SUNMatScaleAdd(A, I, 0);
+  if (square)
+    fails += Test_SUNMatScaleAddI(A, I, 0);
+  fails += Test_SUNMatMatvec(A, x, y, 0);
+  fails += Test_SUNMatSpace(A, 0);
+
+  /* Print result */
+  if (fails) {
+    printf("FAIL: SUNMatrix module failed %i tests \n \n", fails);
+    printf("\nA =\n");
+    SUNSparseMatrix_Print(A,stdout);
+    if (square) {
+      printf("\nI =\n");
+      SUNSparseMatrix_Print(I,stdout);
+    }
+    printf("\nx =\n");
+    N_VPrint_Serial(x);
+    printf("\ny =\n");
+    N_VPrint_Serial(y);
+  } else {
+    printf("SUCCESS: SUNMatrix module passed all tests \n \n");
+  }
+
+  /* Free vectors and matrices */
+  N_VDestroy_Serial(x);
+  N_VDestroy_Serial(y);
+  SUNMatDestroy(A);
+  if (square)
+    SUNMatDestroy(I);
+
+  return(fails);
+}
+
+/* ----------------------------------------------------------------------
+ * Check matrix
+ * --------------------------------------------------------------------*/
+int check_matrix(SUNMatrix A, SUNMatrix B, realtype tol)
+{
+  int failure = 0;
+  realtype *Adata, *Bdata;
+  sunindextype *Aindexptrs, *Bindexptrs;
+  sunindextype *Aindexvals, *Bindexvals;
+  sunindextype i, ANP, BNP, Annz, Bnnz;
+  
+  /* get matrix pointers */
+  Adata = SUNSparseMatrix_Data(A);
+  Aindexptrs = SUNSparseMatrix_IndexPointers(A);
+  Aindexvals = SUNSparseMatrix_IndexValues(A);
+  ANP = SUNSparseMatrix_NP(A);
+  Annz = Aindexptrs[ANP];
+  
+  Bdata = SUNSparseMatrix_Data(B);
+  Bindexptrs = SUNSparseMatrix_IndexPointers(B);
+  Bindexvals = SUNSparseMatrix_IndexValues(B);
+  BNP = SUNSparseMatrix_NP(B);
+  Bnnz = Bindexptrs[BNP];
+
+  /* matrices must have same sparsetype, shape and actual data lengths */
+  if (SUNMatGetID(A) != SUNMatGetID(B)) {
+    printf(">>> ERROR: check_matrix: Different storage types (%d vs %d)\n",
+           SUNMatGetID(A), SUNMatGetID(B));
+    return(1);
+  }
+  if (SUNSparseMatrix_SparseType(A) != SUNSparseMatrix_SparseType(B)) {
+    printf(">>> ERROR: check_matrix: Different storage types (%d vs %d)\n",
+           SUNSparseMatrix_SparseType(A), SUNSparseMatrix_SparseType(B));
+    return(1);
+  }
+  if (SUNSparseMatrix_Rows(A) != SUNSparseMatrix_Rows(B)) {
+    printf(">>> ERROR: check_matrix: Different numbers of rows (%ld vs %ld)\n",
+           (long int) SUNSparseMatrix_Rows(A), (long int) SUNSparseMatrix_Rows(B));
+    return(1);
+  }
+  if (SUNSparseMatrix_Columns(A) != SUNSparseMatrix_Columns(B)) {
+    printf(">>> ERROR: check_matrix: Different numbers of columns (%ld vs %ld)\n",
+           (long int) SUNSparseMatrix_Columns(A),
+           (long int) SUNSparseMatrix_Columns(B));
+    return(1);
+  }
+  if (Annz != Bnnz) {
+    printf(">>> ERROR: check_matrix: Different numbers of nonzeos (%ld vs %ld)\n",
+           (long int) Annz, (long int) Bnnz);
+    return(1);
+  }
+
+  /* compare sparsity patterns */
+  for (i=0; i<ANP; i++) 
+    failure += (Aindexptrs[i] != Bindexptrs[i]);
+  if (failure > ZERO) {
+    printf(">>> ERROR: check_matrix: Different indexptrs \n");
+    return(1);
+  }
+  for (i=0; i<Annz; i++) 
+    failure += (Aindexvals[i] != Bindexvals[i]);
+  if (failure > ZERO) {
+    printf(">>> ERROR: check_matrix: Different indexvals \n");
+    return(1);
+  }
+  
+  /* compare matrix values */
+  for(i=0; i<Annz; i++)
+    failure += FNEQ(Adata[i], Bdata[i], tol);
+  if (failure > ZERO) {
+    printf(">>> ERROR: check_matrix: Different entries \n");
+    return(1);
+  }
+
+  return(0);
+}
+
+int check_matrix_entry(SUNMatrix A, realtype val, realtype tol)
+{
+  int failure = 0;
+  realtype *Adata;
+  sunindextype *indexptrs;
+  sunindextype i, NP;
+  
+  /* get data pointer */
+  Adata = SUNSparseMatrix_Data(A);
+
+  /* compare data */
+  indexptrs = SUNSparseMatrix_IndexPointers(A);
+  NP = SUNSparseMatrix_NP(A);
+  for(i=0; i < indexptrs[NP]; i++){
+    failure += FNEQ(Adata[i], val, tol);
+  }
+
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+int check_vector(N_Vector x, N_Vector y, realtype tol)
+{
+  int failure = 0;
+  realtype *xdata, *ydata;
+  sunindextype xldata, yldata;
+  sunindextype i;
+
+  /* get vector data */
+  xdata = N_VGetArrayPointer(x);
+  ydata = N_VGetArrayPointer(y);
+
+  /* check data lengths */
+  xldata = N_VGetLength_Serial(x);
+  yldata = N_VGetLength_Serial(y);
+
+  if (xldata != yldata) {
+    printf(">>> ERROR: check_vector: Different data array lengths \n");
+    return(1);
+  }
+
+  /* check vector data */
+  for(i=0; i < xldata; i++){
+    failure += FNEQ(xdata[i], ydata[i], tol);
+  }
+
+  if (failure > ZERO)
+    return(1);
+  else
+    return(0);
+}
+
+booleantype has_data(SUNMatrix A)
+{
+  realtype *Adata = SUNSparseMatrix_Data(A);
+  if (Adata == NULL)
+    return SUNFALSE;
+  else
+    return SUNTRUE;
+}
+
+booleantype is_square(SUNMatrix A)
+{
+  if (SUNSparseMatrix_Rows(A) == SUNSparseMatrix_Columns(A))
+    return SUNTRUE;
+  else
+    return SUNFALSE;
+}
diff --git a/examples/sunmatrix/test_sunmatrix.c b/examples/sunmatrix/test_sunmatrix.c
new file mode 100644
index 0000000..3a83eff
--- /dev/null
+++ b/examples/sunmatrix/test_sunmatrix.c
@@ -0,0 +1,557 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Daniel R. Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * These test functions are designed to check a SUNMatrix module
+ * implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_math.h>
+
+#include <math.h> /* include isnan */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test_sunmatrix.h"
+
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+#include <time.h>
+#include <unistd.h>
+#endif
+
+
+/* private functions */
+static double get_time();
+
+int print_time = 0;
+
+#define PRINT_TIME(format, time) if(print_time) printf(format, time)
+
+
+/* ----------------------------------------------------------------------
+ * SUNMatGetID Test
+ * --------------------------------------------------------------------*/
+int Test_SUNMatGetID(SUNMatrix A, SUNMatrix_ID sunid, int myid)
+{
+  double       start_time, stop_time;
+  SUNMatrix_ID mysunid;
+
+  start_time = get_time();   
+  mysunid = SUNMatGetID(A);
+  stop_time = get_time();   
+
+  if (sunid != mysunid) {
+    printf(">>> FAILED test -- SUNMatGetID, Proc %d \n", myid);
+    PRINT_TIME("    SUNMatGetID Time: %22.15e \n \n", stop_time - start_time);
+    return(1);
+  } else if (myid == 0) {
+    printf("    PASSED test -- SUNMatGetID \n");
+    PRINT_TIME("    SUNMatGetID Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * N_VClone Test
+ *
+ * NOTE: This routine depends on SUNMatCopy to check matrix data.
+ * --------------------------------------------------------------------*/
+int Test_SUNMatClone(SUNMatrix A, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+  realtype  tol=1e-15;
+  SUNMatrix B;
+
+  /* clone vector */
+  start_time = get_time();   
+  B = SUNMatClone(A);
+  stop_time = get_time();   
+
+  /* check cloned matrix */
+  if (B == NULL) {
+    printf(">>> FAILED test -- SUNMatClone, Proc %d \n", myid);
+    printf("    After SUNMatClone, B == NULL \n \n");
+    return(1);
+  } 
+
+  /* check cloned matrix data */
+  if (!has_data(B)) {
+    printf(">>> FAILED test -- SUNMatClone, Proc %d \n", myid);
+    printf("    Matrix data == NULL \n \n");
+    SUNMatDestroy(B);
+    return(1);
+  }    
+
+  failure = SUNMatCopy(A, B);
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatCopy, Proc %d \n", myid);
+    SUNMatDestroy(B);
+    return(1);
+  }    
+
+  failure = check_matrix(B, A, tol);
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatClone, Proc %d \n", myid);
+    printf("    Failed SUNMatClone check \n \n");
+    SUNMatDestroy(B);
+    return(1);
+  }    
+
+  if (myid == 0) {
+    printf("    PASSED test -- N_VClone \n");
+    PRINT_TIME("    SUNMatClone Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  SUNMatDestroy(B); 
+  return(0);
+}
+
+
+
+/* ----------------------------------------------------------------------
+ * SUNMatZero Test
+ * --------------------------------------------------------------------*/
+int Test_SUNMatZero(SUNMatrix A, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+  realtype  tol=1e-15;
+  SUNMatrix B;
+
+  /* protect A */
+  B = SUNMatClone(A);
+
+  /* set matrix data to zero */
+  start_time = get_time();
+  failure = SUNMatZero(B);
+  stop_time = get_time(); 
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatZero returned %d on Proc %d \n", 
+           failure, myid);
+    SUNMatDestroy(B);
+    return(1);
+  }
+
+  /* A data should be a vector of zeros */
+  failure = check_matrix_entry(B, ZERO, tol);
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatZero check, Proc %d \n", myid);
+    PRINT_TIME("    SUNMatZero Time: %22.15e \n \n", stop_time - start_time);
+    SUNMatDestroy(B);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNMatZero \n");
+    PRINT_TIME("    SUNMatZero Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  SUNMatDestroy(B);
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNMatCopy Test
+ * --------------------------------------------------------------------*/
+int Test_SUNMatCopy(SUNMatrix A, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+  SUNMatrix B; 
+  realtype  tol=1e-15;
+
+  B = SUNMatClone(A);
+
+  /* copy matrix data */
+  start_time = get_time();
+  failure = SUNMatCopy(A, B);
+  stop_time = get_time(); 
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatCopy returned %d on Proc %d \n", 
+           failure, myid);
+    SUNMatDestroy(B);
+    return(1);
+  }
+
+  /* check matrix entries */
+  failure = check_matrix(B, A, tol);
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatCopy check, Proc %d \n", myid);
+    PRINT_TIME("    SUNMatCopy Time: %22.15e \n \n", stop_time - start_time);
+    SUNMatDestroy(B);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- N_VConst \n");
+    PRINT_TIME("    SUNMatCopy Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  SUNMatDestroy(B);
+  return(0);
+}
+
+
+
+/* ----------------------------------------------------------------------
+ * SUNMatScaleAdd Test: A = c * A + B 
+ *
+ * NOTE: Sparse matrices will need additional testing for possibly
+ * different sparsity patterns
+ * --------------------------------------------------------------------*/
+int Test_SUNMatScaleAdd(SUNMatrix A, SUNMatrix I, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+  SUNMatrix B, C, D;
+  realtype  tol=1e-15;
+
+  /* 
+   * Case 1: same sparsity/bandwith pattern
+   */
+
+  /* protect A */
+  B = SUNMatClone(A);
+  failure = SUNMatCopy(A, B);
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatCopy returned %d on Proc %d \n", 
+           failure, myid);
+    SUNMatDestroy(B);
+    return(1);
+  }
+
+  /* fill vector data */
+  start_time = get_time(); 
+  failure = SUNMatScaleAdd(NEG_ONE, B, B);
+  stop_time = get_time(); 
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatScaleAdd returned %d on Proc %d \n", 
+           failure, myid);
+    SUNMatDestroy(B);
+    return(1);
+  }
+  
+  /* check matrix entries */
+  failure = check_matrix_entry(B, ZERO, tol);
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatScaleAdd case 1 check, Proc %d \n", myid);
+    PRINT_TIME("    SUNMatScaleAdd Time: %22.15e \n \n", stop_time - start_time);
+    SUNMatDestroy(B);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNMatScaleAdd case 1 \n");
+    PRINT_TIME("    SUNMatScaleAdd Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  
+  /* 
+   * Case 2: different sparsity/bandwith patterns
+   */
+  if (is_square(A)) {
+
+    /* protect A and I */
+    D = SUNMatClone(A);
+    failure = SUNMatCopy(A, D);
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatCopy returned %d on Proc %d \n", 
+             failure, myid);
+      SUNMatDestroy(B);
+      SUNMatDestroy(D);
+      return(1);
+    }
+    C = SUNMatClone(I);
+    failure = SUNMatCopy(I, C);
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatCopy returned %d on Proc %d \n", 
+             failure, myid);
+      SUNMatDestroy(B);
+      SUNMatDestroy(C);
+      SUNMatDestroy(D);
+      return(1);
+    }
+
+    /* fill B and C */
+    start_time = get_time(); 
+    failure = SUNMatScaleAdd(ONE, D, I);
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatScaleAdd returned %d on Proc %d \n", 
+             failure, myid);
+      SUNMatDestroy(B);
+      SUNMatDestroy(C);
+      SUNMatDestroy(D);
+      return(1);
+    }
+    failure = SUNMatScaleAdd(ONE, C, A);
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatScaleAdd returned %d on Proc %d \n", 
+             failure, myid);
+      SUNMatDestroy(B);
+      SUNMatDestroy(C);
+      SUNMatDestroy(D);
+      return(1);
+    }
+    stop_time = get_time(); 
+
+    /* check matrix entries */
+    failure = check_matrix(D, C, tol);
+
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatScaleAdd case 2 check, Proc %d \n", myid);
+      PRINT_TIME("    SUNMatScaleAdd Time: %22.15e \n \n", stop_time - start_time);
+      SUNMatDestroy(B);
+      SUNMatDestroy(C);
+      SUNMatDestroy(D);
+      return(1);
+    }
+    else if (myid == 0) {
+      printf("    PASSED test -- SUNMatScaleAdd case 2 \n");
+      PRINT_TIME("    SUNMatScaleAdd Time: %22.15e \n \n", stop_time - start_time);
+    }    
+
+    SUNMatDestroy(C);
+    SUNMatDestroy(D);
+  }
+
+  SUNMatDestroy(B);
+  
+  return(0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * SUNMatScaleAddI Tests
+ *
+ * NOTE: Sparse matrices will need additional testing for possibly
+ * different sparsity patterns
+ * --------------------------------------------------------------------*/
+int Test_SUNMatScaleAddI(SUNMatrix A, SUNMatrix I, int myid)
+{
+  int       failure;
+  double    start_time, stop_time;
+  SUNMatrix B;
+  realtype  tol=1e-15;
+
+  /* protect A */
+  B = SUNMatClone(A);
+  
+  failure = SUNMatCopy(I, B);
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatCopy returned %d on Proc %d \n", 
+           failure, myid);
+    SUNMatDestroy(B);
+    return(1);
+  }
+  
+  /* fill vector data */
+  start_time = get_time(); 
+  failure = SUNMatScaleAddI(NEG_ONE, B);
+  stop_time = get_time(); 
+  
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatScaleAddI returned %d on Proc %d \n",
+           failure, myid);
+    SUNMatDestroy(B);
+    return(1);
+  }
+
+  /* check matrix */
+  failure = check_matrix_entry(B, ZERO, tol);
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatScaleAddI check, Proc %d \n", myid);
+    PRINT_TIME("    SUNMatScaleAddI Time: %22.15e \n \n", stop_time - start_time);
+    SUNMatDestroy(B);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNMatScaleAddI \n");
+    PRINT_TIME("    SUNMatScaleAddI Time: %22.15e \n \n", stop_time - start_time);
+  }    
+  
+  SUNMatDestroy(B);
+  return(0);
+}
+
+
+
+/* ----------------------------------------------------------------------
+ * SUNMatMatvec Test (y should be correct A*x product)
+ * --------------------------------------------------------------------*/
+int Test_SUNMatMatvec(SUNMatrix A, N_Vector x, N_Vector y, int myid)
+{
+  int      failure;
+  double   start_time, stop_time;
+  SUNMatrix B;
+  N_Vector  z, w;
+  realtype  tol=1e-14;
+
+  /* harder tests for square matrices */
+  if (is_square(A)) {
+    
+    /* protect A */
+    B = SUNMatClone(A);
+    failure = SUNMatCopy(A, B);
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatCopy returned %d on Proc %d \n", 
+             failure, myid);
+      SUNMatDestroy(B);
+      return(1);
+    }
+
+    /* compute matrix vector product */
+    failure = SUNMatScaleAddI(THREE,B);
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatScaleAddI returned %d on Proc %d \n", 
+             failure, myid);
+      SUNMatDestroy(B);
+      return(1);
+    }
+
+    z = N_VClone(y);
+    w = N_VClone(y);
+
+    start_time = get_time();
+    failure = SUNMatMatvec(B,x,z);
+    stop_time = get_time(); 
+
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatMatvec returned %d on Proc %d \n", 
+             failure, myid);
+      SUNMatDestroy(B);
+      return(1);
+    }
+  
+    N_VLinearSum(THREE,y,ONE,x,w);
+  
+    failure = check_vector(w,z,tol);
+
+    SUNMatDestroy(B);
+    N_VDestroy(z);
+    N_VDestroy(w);
+
+  } else {
+
+    z = N_VClone(y);
+
+    start_time = get_time();
+    failure = SUNMatMatvec(A,x,z);
+    stop_time = get_time(); 
+
+    if (failure) {
+      printf(">>> FAILED test -- SUNMatMatvec returned %d on Proc %d \n", 
+             failure, myid);
+      return(1);
+    }
+  
+    failure = check_vector(y,z,tol);
+
+    N_VDestroy(z);
+    
+  }
+  
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatMatvec check, Proc %d \n", myid);
+    PRINT_TIME("    SUNMatMatvec Time: %22.15e \n \n", stop_time - start_time);
+    return(1);
+  }
+  else if (myid == 0) {
+    printf("    PASSED test -- SUNMatMatvec \n");
+    PRINT_TIME("    SUNMatMatvec Time: %22.15e \n \n", stop_time - start_time);
+  }    
+
+  return(0);
+}
+
+
+
+/* ----------------------------------------------------------------------
+ * SUNMatSpace Test
+ * --------------------------------------------------------------------*/
+int Test_SUNMatSpace(SUNMatrix A, int myid)
+{
+  int      failure;
+  double   start_time, stop_time;
+  long int lenrw, leniw;
+
+  start_time = get_time();
+  failure = SUNMatSpace(A, &lenrw, &leniw);
+  stop_time = get_time();   
+
+  if (failure) {
+    printf(">>> FAILED test -- SUNMatSpace, Proc %d \n", myid);
+    PRINT_TIME("    SUNMatSpace Time: %22.15e \n \n", stop_time - start_time);
+    return(1);
+  } else if (myid == 0) {
+    printf("    PASSED test -- SUNMatSpace, lenrw = %li, leniw = %li\n", lenrw, leniw);
+    PRINT_TIME("    SUNMatSpace Time: %22.15e \n \n", stop_time - start_time);
+  }
+
+  return(0);
+}
+
+
+
+
+
+/* ======================================================================
+ * Private functions
+ * ====================================================================*/
+
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+time_t base_time_tv_sec = 0; /* Base time; makes time values returned
+                                by get_time easier to read when
+                                printed since they will be zero
+                                based.
+                              */
+#endif
+
+void SetTiming(int onoff)
+{
+   print_time = onoff;
+
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+  struct timespec spec;  
+  clock_gettime( CLOCK_MONOTONIC_RAW, &spec );
+  base_time_tv_sec = spec.tv_sec;
+#endif
+}
+
+/* ----------------------------------------------------------------------
+ * Timer
+ * --------------------------------------------------------------------*/
+static double get_time()
+{
+#if defined( SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS)
+  struct timespec spec;  
+  clock_gettime( CLOCK_MONOTONIC_RAW, &spec );
+  double time = (double)(spec.tv_sec - base_time_tv_sec) + ((double)(spec.tv_nsec) / 1E9);
+#else
+  double time = 0;
+#endif
+  return time;
+}
+
+
diff --git a/examples/sunmatrix/test_sunmatrix.h b/examples/sunmatrix/test_sunmatrix.h
new file mode 100644
index 0000000..eae7222
--- /dev/null
+++ b/examples/sunmatrix/test_sunmatrix.h
@@ -0,0 +1,66 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Daniel R. Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file contains the prototypes for functions to 
+ * test SUNMatrix module implementation. 
+ * -----------------------------------------------------------------
+ */
+
+#include <math.h>
+
+/* define constatnts */
+#define NEG_TWO  RCONST(-2.0)
+#define NEG_ONE  RCONST(-1.0)
+#define NEG_HALF RCONST(-0.5)
+#define ZERO     RCONST(0.0)
+#define HALF     RCONST(0.5)
+#define ONE      RCONST(1.0)
+#define TWO      RCONST(2.0)
+#define THREE    RCONST(3.0)
+
+/* NAN and floating point "equality" check, failure update macro */
+#if __STDC_VERSION__ >= 199901L
+#define FNEQ(a,b,tol) (isnan(a) ? 1 : ( SUNRabs((a)-(b))/SUNRabs(b) > tol ))
+#else
+#define FNEQ(a,b,tol) (( SUNRabs((a)-(b))/SUNRabs(b) > tol ))
+#endif
+
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+  /* Forward declarations for implementation specific utility functions */
+  int check_matrix(SUNMatrix A, SUNMatrix B, realtype tol);
+  int check_matrix_entry(SUNMatrix A, realtype val, realtype tol);
+  int check_vector(N_Vector X, N_Vector Y, realtype tol);
+  booleantype has_data(SUNMatrix A);
+  booleantype is_square(SUNMatrix A);
+   
+  /* Test function declarations */
+  int Test_SUNMatGetID(SUNMatrix A, SUNMatrix_ID sunid, int myid);
+  int Test_SUNMatClone(SUNMatrix A, int myid);
+  int Test_SUNMatZero(SUNMatrix A, int myid);
+  int Test_SUNMatCopy(SUNMatrix A, int myid);
+  int Test_SUNMatScaleAdd(SUNMatrix A, SUNMatrix I, int myid);
+  int Test_SUNMatScaleAddI(SUNMatrix A, SUNMatrix I, int myid);
+  int Test_SUNMatMatvec(SUNMatrix A, N_Vector x, N_Vector y, int myid);
+  int Test_SUNMatSpace(SUNMatrix A, int myid);
+
+  /* Timing function */
+  void SetTiming(int onoff);
+  
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/templates/cmakelists_pthreads_C_ex.in b/examples/templates/cmakelists_cuda_CUDA_ex.in
similarity index 51%
copy from examples/templates/cmakelists_pthreads_C_ex.in
copy to examples/templates/cmakelists_cuda_CUDA_ex.in
index fea6cbd..7b364e0 100644
--- a/examples/templates/cmakelists_pthreads_C_ex.in
+++ b/examples/templates/cmakelists_cuda_CUDA_ex.in
@@ -1,44 +1,40 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
+# Programmer: Slaven Peles @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
-# CMakeLists.txt for @SOLVER@ serial examples
+# CMakeLists.txt for @SOLVER@ CUDA examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
 
 # Specify project name
-PROJECT(@SOLVER at _pthreads_examples C)
+PROJECT(@SOLVER at _CUDA_cuda_examples)
+
+# Set the location of the CUDA toolkit used to build SUNDIALS
+set(CUDA_TOOLKIT_ROOT_DIR @CUDA_TOOLKIT_ROOT_DIR@)
+
+# Get the CUDA toolkit used to build sundials
+find_package(CUDA)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
 # Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
+SET(examples @EXAMPLES@)
+LIST(REMOVE_DUPLICATES examples)
 
 # Set names of examples specific dependency source files
 SET(examples_dependencies @EXAMPLES_DEPENDENCIES@)
@@ -62,24 +58,23 @@ FIND_LIBRARY(SUNDIALS_SOLVER_LIB
 
 # Find the NVECTOR library
 FIND_LIBRARY(SUNDIALS_NVEC_LIB
-  sundials_nvecserial ${SUNDIALS_LIB_DIR}
+  sundials_nveccuda ${SUNDIALS_LIB_DIR}
   DOC "NVECTOR library")
 
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set Blas/Lapack libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
-
 # List of all libraries
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
 
 # Build each example one by one
 FOREACH(example ${examples})
-  ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
+
+  # example source files
+  CUDA_ADD_EXECUTABLE(${example} ${example}.cu ${examples_dependencies})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
  
diff --git a/examples/templates/cmakelists_openmp_C_ex.in b/examples/templates/cmakelists_openmp_C_ex.in
index c12b5e3..cf9cdcc 100644
--- a/examples/templates/cmakelists_openmp_C_ex.in
+++ b/examples/templates/cmakelists_openmp_C_ex.in
@@ -1,33 +1,23 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ OpenMP examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -37,19 +27,28 @@ PROJECT(@SOLVER at _openmp_examples C)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
-LIST(REMOVE_DUPLICATES examples)
-
-# Set names of examples specific dependency source files
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
 SET(examples_dependencies @EXAMPLES_DEPENDENCIES@)
 
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+SET(examples_dependencies_bl @EXAMPLES_DEPENDENCIES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+SET(examples_dependencies_klu @EXAMPLES_DEPENDENCIES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
+SET(examples_dependencies_slumt @EXAMPLES_DEPENDENCIES_SLUMT@)
+
 # Specify path to SUNDIALS header files
 SET(SUNDIALS_INC_DIR
   @includedir@
   CACHE STRING
   "Location of SUNDIALS header files")
-  
+
 # Add path to SUNDIALS header files
 INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
 
@@ -70,29 +69,19 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
 # Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
 SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
 SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
 
-# List of all libraries
+# List of Sundials libraries shared across all examples
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
-
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
 
+# find OpenMP
 FIND_PACKAGE(OpenMP)
 IF(OPENMP_FOUND)
   SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
@@ -103,9 +92,89 @@ ELSE(OPENMP_FOUND)
   message(STATUS "Disabling OpenMP support, could not determine compiler flags")
 ENDIF(OPENMP_FOUND)
 
-# Build each example one by one
+# Build examples with SUNDIALS linear solvers one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
- 
+
+
+# Build each example with LAPACK linear solvers one by one
+IF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_bl})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
+IF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_klu})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
+
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_slumt})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/cmakelists_openmp_F77_ex.in b/examples/templates/cmakelists_openmp_F77_ex.in
index 3fba4e9..1947643 100644
--- a/examples/templates/cmakelists_openmp_F77_ex.in
+++ b/examples/templates/cmakelists_openmp_F77_ex.in
@@ -1,33 +1,23 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
-# CMakeLists.txt for @SOLVER@ openmp examples
+# CMakeLists.txt for @SOLVER@ OpenMP examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -37,9 +27,26 @@ PROJECT(F at SOLVER@_openmp_examples Fortran C)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
-LIST(REMOVE_DUPLICATES examples)
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
+
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
+
+# Specify path to SUNDIALS header files
+SET(SUNDIALS_INC_DIR
+  @includedir@
+  CACHE STRING
+  "Location of SUNDIALS header files")
+
+# Add path to SUNDIALS header files
+INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
 
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
@@ -51,7 +58,7 @@ FIND_LIBRARY(SUNDIALS_SOLVER_LIB
 
 FIND_LIBRARY(SUNDIALS_SOLVER_FLIB
   @SOLVER_FLIB@ ${SUNDIALS_LIB_DIR}
-  DOC "@SOLVER@ F77-C library")
+  DOC "@SOLVER@ Fortran-C library")
 
 # Find the NVECTOR library
 FIND_LIBRARY(SUNDIALS_NVEC_LIB
@@ -60,13 +67,20 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 
 FIND_LIBRARY(SUNDIALS_NVEC_FLIB
   sundials_fnvecopenmp ${SUNDIALS_LIB_DIR}
-  DOC "NVECTOR F77-C library")
+  DOC "NVECTOR Fortran-C library")
+
+# Set additional libraries
+SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
 # Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
 SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
 SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
 
 FIND_PACKAGE(OpenMP)
 IF(OPENMP_FOUND)
@@ -78,30 +92,118 @@ ELSE(OPENMP_FOUND)
   message(STATUS "Disabling OpenMP support, could not determine compiler flags")
 ENDIF(OPENMP_FOUND)
 
-# List of all libraries
-SET(SUNDIALS_LIBS 
-  ${SUNDIALS_SOLVER_FLIB} ${SUNDIALS_SOLVER_LIB}
-  ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB}
+# List of Sundials libraries shared across all examples
+SET(SUNDIALS_LIBS
+  ${SUNDIALS_SOLVER_FLIB}
+  ${SUNDIALS_SOLVER_LIB}
+  ${SUNDIALS_NVEC_FLIB}
+  ${SUNDIALS_NVEC_LIB}
   ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
 
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
 
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
-
-# Build each example one by one
+# Build examples with SUNDIALS linear solvers one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
 
+
+# Build each example with LAPACK linear solvers one by one
+IF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_FLIB
+      sundials_fsunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver Fortran-C library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB
+      sundials_fsunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
+IF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_FLIB
+      sundials_fsunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
+
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_FLIB
+      sundials_fsunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/cmakelists_parallel_CXX_ex.in b/examples/templates/cmakelists_parallel_CXX_ex.in
index 381a8ca..4a860b2 100644
--- a/examples/templates/cmakelists_parallel_CXX_ex.in
+++ b/examples/templates/cmakelists_parallel_CXX_ex.in
@@ -1,33 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
 # Programmer: Daniel R. Reynolds @ SMU
 # -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ parallel examples
 #
 # This file is generated from a template using  various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -69,32 +58,16 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
-SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
-SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
-
 # List of all libraries
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
-
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
 
 # Build each example one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.cpp)
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
diff --git a/examples/templates/cmakelists_parallel_C_ex.in b/examples/templates/cmakelists_parallel_C_ex.in
index 0f8b9f5..315b97c 100644
--- a/examples/templates/cmakelists_parallel_C_ex.in
+++ b/examples/templates/cmakelists_parallel_C_ex.in
@@ -1,33 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
 # Programmer: Radu Serban @ LLNL
 # -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ parallel examples
 #
 # This file is generated from a template using  various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -39,7 +28,6 @@ MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
 # Set the names of the examples to be built
 SET(examples @EXAMPLES@)
-LIST(REMOVE_DUPLICATES examples)
 
 # Set names of examples specific dependency source files
 SET(examples_dependencies @EXAMPLES_DEPENDENCIES@)
@@ -73,32 +61,16 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
-SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
-SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIESY@ CACHE STRING "PETSC libraries")
-
 # List of all libraries
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
-
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
 
 # Build each example one by one
 FOREACH(example ${examples})
+  
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
diff --git a/examples/templates/cmakelists_parallel_F77_ex.in b/examples/templates/cmakelists_parallel_F77_ex.in
index dc88376..5f2db12 100644
--- a/examples/templates/cmakelists_parallel_F77_ex.in
+++ b/examples/templates/cmakelists_parallel_F77_ex.in
@@ -1,33 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
 # Programmer: Radu Serban @ LLNL
 # -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ Fortran parallel examples
 #
 # This file is generated from a template using  various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -44,6 +33,15 @@ SET(examples @EXAMPLES@)
 SET(MPI_MPIF77 @MPIF77@ CACHE STRING "MPIF77 compiler script")
 SET(CMAKE_Fortran_COMPILER ${MPI_MPIF77})
 
+# Specify path to SUNDIALS header files
+SET(SUNDIALS_INC_DIR
+  @includedir@
+  CACHE STRING
+  "Location of SUNDIALS header files")
+
+# Add path to SUNDIALS header files
+INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
+
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
 
@@ -54,7 +52,7 @@ FIND_LIBRARY(SUNDIALS_SOLVER_LIB
 
 FIND_LIBRARY(SUNDIALS_SOLVER_FLIB
   @SOLVER_FLIB@ ${SUNDIALS_LIB_DIR}
-  DOC "@SOLVER@ F77-C library")
+  DOC "@SOLVER@ Fortran-C library")
 
 # Find the NVECTOR library
 FIND_LIBRARY(SUNDIALS_NVEC_LIB
@@ -63,40 +61,26 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 
 FIND_LIBRARY(SUNDIALS_NVEC_FLIB
   sundials_fnvecparallel ${SUNDIALS_LIB_DIR}
-  DOC "NVECTOR F77-C library")
+  DOC "NVECTOR Fortran-C library")
 
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
-SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
-SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
-
 # List of all libraries
 SET(SUNDIALS_LIBS 
-  ${SUNDIALS_SOLVER_FLIB} ${SUNDIALS_SOLVER_LIB} 
-  ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB} 
+  ${SUNDIALS_SOLVER_FLIB}
+  ${SUNDIALS_SOLVER_LIB} 
+  ${SUNDIALS_NVEC_FLIB}
+  ${SUNDIALS_NVEC_LIB} 
   ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
-
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
 
 # Build each example one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS}) 
+  
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
diff --git a/examples/templates/cmakelists_parallel_F90_ex.in b/examples/templates/cmakelists_parallel_F90_ex.in
index 3bd95fe..1f66f8a 100644
--- a/examples/templates/cmakelists_parallel_F90_ex.in
+++ b/examples/templates/cmakelists_parallel_F90_ex.in
@@ -1,33 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4944 $
-# $Date: 2016-09-21 21:48:35 -0700 (Wed, 21 Sep 2016) $
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
 # Programmer: Daniel R. Reynolds @ SMU
 # -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ Fortran parallel examples
 #
 # This file is generated from a template using  various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -44,6 +33,15 @@ SET(examples @EXAMPLES@)
 SET(MPI_MPIF90 @MPIF90@ CACHE STRING "MPIF90 compiler script")
 SET(CMAKE_Fortran_COMPILER ${MPI_MPIF90})
 
+# Specify path to SUNDIALS header files
+SET(SUNDIALS_INC_DIR
+  @includedir@
+  CACHE STRING
+  "Location of SUNDIALS header files")
+
+# Add path to SUNDIALS header files
+INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
+
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
 
@@ -63,35 +61,26 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 
 FIND_LIBRARY(SUNDIALS_NVEC_FLIB
   sundials_fnvecparallel ${SUNDIALS_LIB_DIR}
-  DOC "NVECTOR F90-C library")
+  DOC "NVECTOR Fortran-C library")
 
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
-SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
-SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-
 # List of all libraries
 SET(SUNDIALS_LIBS 
-  ${SUNDIALS_SOLVER_FLIB} ${SUNDIALS_SOLVER_LIB} 
-  ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB} 
+  ${SUNDIALS_SOLVER_FLIB}
+  ${SUNDIALS_SOLVER_LIB} 
+  ${SUNDIALS_NVEC_FLIB}
+  ${SUNDIALS_NVEC_LIB} 
   ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
 
 # Build each example one by one
 FOREACH(example ${examples})
+  
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f90)
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS}) 
+
+  # libraries to link agaisnt
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
diff --git a/examples/templates/cmakelists_parhyp_C_ex.in b/examples/templates/cmakelists_parhyp_C_ex.in
index 7c683fd..8a5891a 100644
--- a/examples/templates/cmakelists_parhyp_C_ex.in
+++ b/examples/templates/cmakelists_parhyp_C_ex.in
@@ -1,33 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
 # Programmer: Radu Serban @ LLNL
 # -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ parhyp examples
 #
 # This file is generated from a template using  various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -53,14 +42,8 @@ SET(SUNDIALS_INC_DIR
   CACHE STRING
   "Location of SUNDIALS header files")
 
-SET(HYPRE_INC_DIR
-  @HYPRE_INCLUDE_DIR@
-  CACHE STRING
-  "Location of HYPRE header files")
-
 # Add path to SUNDIALS header files
 INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
-INCLUDE_DIRECTORIES(${HYPRE_INC_DIR})
 
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
@@ -78,33 +61,20 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
-SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
-SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
+# Set hypre includes libraries
+INCLUDE_DIRECTORIES(@HYPRE_INCLUDE_DIR@)
 SET(HYPRE_LIBRARIES @HYPRE_LIBS@ CACHE STRING "HYPRE libraries")
 
 # List of all libraries
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
 
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
-
-IF(HYPRE_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${HYPRE_LIBRARIES})
-ENDIF(HYPRE_LIBRARIES)
-
 # Build each example one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${HYPRE_LIBRARIES})
+
 ENDFOREACH(example ${examples})
diff --git a/examples/templates/cmakelists_petsc_C_ex.in b/examples/templates/cmakelists_petsc_C_ex.in
index 4e3d9bd..85e9662 100644
--- a/examples/templates/cmakelists_petsc_C_ex.in
+++ b/examples/templates/cmakelists_petsc_C_ex.in
@@ -1,33 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
 # Programmer: Radu Serban @ LLNL
 # -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ petsc examples
 #
 # This file is generated from a template using  various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -53,14 +42,8 @@ SET(SUNDIALS_INC_DIR
   CACHE STRING
   "Location of SUNDIALS header files")
 
-SET(PETSC_INC_DIR
-  @PETSC_INCLUDE_DIR@
-  CACHE STRING
-  "Location of NVector PETSC header files")
-
 # Add path to SUNDIALS header files
 INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
-INCLUDE_DIRECTORIES(${PETSC_INC_DIR})
 
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
@@ -78,32 +61,20 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+# Set PETSc include and libraries
+INCLUDE_DIRECTORIES(@PETSC_INCLUDE_DIR@)
 SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
-SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
-SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
 
 # List of all libraries
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
 
 # Build each example one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} ${PETSC_LIBRARIES})
+
 ENDFOREACH(example ${examples})
diff --git a/examples/templates/cmakelists_pthreads_C_ex.in b/examples/templates/cmakelists_pthreads_C_ex.in
index fea6cbd..456a696 100644
--- a/examples/templates/cmakelists_pthreads_C_ex.in
+++ b/examples/templates/cmakelists_pthreads_C_ex.in
@@ -1,33 +1,23 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ serial examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -37,12 +27,22 @@ PROJECT(@SOLVER at _pthreads_examples C)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
-
-# Set names of examples specific dependency source files
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
 SET(examples_dependencies @EXAMPLES_DEPENDENCIES@)
 
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+SET(examples_dependencies_bl @EXAMPLES_DEPENDENCIES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+SET(examples_dependencies_klu @EXAMPLES_DEPENDENCIES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
+SET(examples_dependencies_slumt @EXAMPLES_DEPENDENCIES_SLUMT@)
+
 # Specify path to SUNDIALS header files
 SET(SUNDIALS_INC_DIR
   @includedir@
@@ -68,18 +68,103 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set Blas/Lapack libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+# Set other libraries libraries
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
+SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
+SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
 
-# List of all libraries
+# List of Sundials libraries shared across all examples
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
 
-# Build each example one by one
+
+# Build examples with SUNDIALS linear solvers one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
- 
+
+
+# Build each example with LAPACK linear solvers one by one
+IF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_bl})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
+IF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_klu})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
+
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_slumt})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/cmakelists_pthreads_F77_ex.in b/examples/templates/cmakelists_pthreads_F77_ex.in
index 280bba4..7132848 100644
--- a/examples/templates/cmakelists_pthreads_F77_ex.in
+++ b/examples/templates/cmakelists_pthreads_F77_ex.in
@@ -1,33 +1,23 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ pthreads examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -37,8 +27,26 @@ PROJECT(F at SOLVER@_pthreads_examples Fortran)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
+
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
+
+# Specify path to SUNDIALS header files
+SET(SUNDIALS_INC_DIR
+  @includedir@
+  CACHE STRING
+  "Location of SUNDIALS header files")
+
+# Add path to SUNDIALS header files
+INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
 
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
@@ -50,7 +58,7 @@ FIND_LIBRARY(SUNDIALS_SOLVER_LIB
 
 FIND_LIBRARY(SUNDIALS_SOLVER_FLIB
   @SOLVER_FLIB@ ${SUNDIALS_LIB_DIR}
-  DOC "@SOLVER@ F77-C library")
+  DOC "@SOLVER@ Fortran-C library")
 
 # Find the NVECTOR library
 FIND_LIBRARY(SUNDIALS_NVEC_LIB
@@ -59,42 +67,133 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 
 FIND_LIBRARY(SUNDIALS_NVEC_FLIB
   sundials_fnvecpthreads ${SUNDIALS_LIB_DIR}
-  DOC "NVECTOR F77-C library")
+  DOC "NVECTOR Fortran-C library")
 
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
 # Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
 SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
 SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
 
-# List of all libraries
-SET(SUNDIALS_LIBS 
-  ${SUNDIALS_SOLVER_FLIB} ${SUNDIALS_SOLVER_LIB}
-  ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB}
+# List of Sundials libraries shared across all examples
+SET(SUNDIALS_LIBS
+  ${SUNDIALS_SOLVER_FLIB}
+  ${SUNDIALS_SOLVER_LIB}
+  ${SUNDIALS_NVEC_FLIB}
+  ${SUNDIALS_NVEC_LIB}
   ${SUNDIALS_EXTRA_LIB})
+
+
+# Build examples with SUNDIALS linear solvers one by one
+FOREACH(example ${examples})
+
+  # example source files
+  ADD_EXECUTABLE(${example} ${example}.f)
+
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
+ENDFOREACH(example ${examples})
+
+
+# Build each example with LAPACK linear solvers one by one
 IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
 
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_FLIB
+      sundials_fsunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver Fortran-C library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB
+      sundials_fsunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
 
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
 IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
 
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
 
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_FLIB
+      sundials_fsunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
 
-# Build each example one by one
-FOREACH(example ${examples})
-  ADD_EXECUTABLE(${example} ${example}.f)
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
-ENDFOREACH(example ${examples})
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
 
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_FLIB
+      sundials_fsunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/cmakelists_pthreads_C_ex.in b/examples/templates/cmakelists_raja_CUDA_ex.in
similarity index 50%
copy from examples/templates/cmakelists_pthreads_C_ex.in
copy to examples/templates/cmakelists_raja_CUDA_ex.in
index fea6cbd..4e32dff 100644
--- a/examples/templates/cmakelists_pthreads_C_ex.in
+++ b/examples/templates/cmakelists_raja_CUDA_ex.in
@@ -1,44 +1,39 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
+# Programmer: Slaven Peles @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
-# CMakeLists.txt for @SOLVER@ serial examples
+# CMakeLists.txt for @SOLVER@ RAJA examples.
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using various variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
 
 # Specify project name
-PROJECT(@SOLVER at _pthreads_examples C)
+PROJECT(@SOLVER at _CXX_serial_examples)
+
+set(CMAKE_CXX_STANDARD 11)
+find_package(CUDA)
+
+SET(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} @RAJA_NVCC_FLAGS@)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
 # Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
+SET(examples @EXAMPLES@)
+LIST(REMOVE_DUPLICATES examples)
 
 # Set names of examples specific dependency source files
 SET(examples_dependencies @EXAMPLES_DEPENDENCIES@)
@@ -62,24 +57,26 @@ FIND_LIBRARY(SUNDIALS_SOLVER_LIB
 
 # Find the NVECTOR library
 FIND_LIBRARY(SUNDIALS_NVEC_LIB
-  sundials_nvecserial ${SUNDIALS_LIB_DIR}
+  sundials_nvecraja ${SUNDIALS_LIB_DIR}
   DOC "NVECTOR library")
 
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
-# Set Blas/Lapack libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+# Set raja includes and libraries
+INCLUDE_DIRECTORIES(@RAJA_INCLUDE_DIR@)
+SET(RAJA_LIBRARIES @RAJA_LIBRARIES@ CACHE STRING "RAJA libraries")
 
 # List of all libraries
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
 
 # Build each example one by one
 FOREACH(example ${examples})
-  ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
-  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+  
+  # example source files
+  CUDA_ADD_EXECUTABLE(${example} ${example}.cu ${examples_dependencies})
+  
+  # libraries to link against
+  TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS} -L at RAJA_LIB_DIR@ -lRAJA)
+
 ENDFOREACH(example ${examples})
- 
diff --git a/examples/templates/cmakelists_serial_CXX_ex.in b/examples/templates/cmakelists_serial_CXX_ex.in
index 43b224b..c85541c 100644
--- a/examples/templates/cmakelists_serial_CXX_ex.in
+++ b/examples/templates/cmakelists_serial_CXX_ex.in
@@ -1,33 +1,23 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Daniel R. Reynolds @ SMU
-# -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ serial examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -37,8 +27,17 @@ PROJECT(@SOLVER at _CXX_serial_examples CXX)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
+
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
 
 # Specify path to SUNDIALS header files
 SET(SUNDIALS_INC_DIR
@@ -66,28 +65,102 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
 # Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
 SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
 SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
 
-# List of all libraries
+# List of Sundials libraries shared across all examples
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
 
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
 
-# Build each example one by one
+# Build examples with SUNDIALS linear solvers one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.cpp)
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
- 
+
+
+# Build each example with LAPACK linear solvers one by one
+IF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.cpp)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
+IF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.cpp)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
+
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.cpp)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/cmakelists_serial_C_ex.in b/examples/templates/cmakelists_serial_C_ex.in
index d13301f..c468c64 100644
--- a/examples/templates/cmakelists_serial_C_ex.in
+++ b/examples/templates/cmakelists_serial_C_ex.in
@@ -1,33 +1,23 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ serial examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -37,13 +27,22 @@ PROJECT(@SOLVER at _serial_examples C)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
-LIST(REMOVE_DUPLICATES examples)
-
-# Set names of examples specific dependency source files
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
 SET(examples_dependencies @EXAMPLES_DEPENDENCIES@)
 
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+SET(examples_dependencies_bl @EXAMPLES_DEPENDENCIES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+SET(examples_dependencies_klu @EXAMPLES_DEPENDENCIES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
+SET(examples_dependencies_slumt @EXAMPLES_DEPENDENCIES_SLUMT@)
+
 # Specify path to SUNDIALS header files
 SET(SUNDIALS_INC_DIR
   @includedir@
@@ -66,36 +65,111 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
   sundials_nvecserial ${SUNDIALS_LIB_DIR}
   DOC "NVECTOR library")
 
+# Set an extra link directory if necessary (false if empty)
+IF(EXISTS @EXTRA_LIBS_DIR@)
+  LINK_DIRECTORIES(@EXTRA_LIBS_DIR@)
+ENDIF()
+
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
 # Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
 SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
 SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
 
-# List of all libraries
+# List of Sundials libraries shared across all examples
 SET(SUNDIALS_LIBS ${SUNDIALS_SOLVER_LIB} ${SUNDIALS_NVEC_LIB} ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
 
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
 
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
-
-# Build each example one by one
+# Build examples with SUNDIALS linear solvers one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies})
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
- 
+
+
+# Build each example with LAPACK linear solvers one by one
+IF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_bl})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
+IF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_klu})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
+
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.c ${examples_dependencies_slumt})
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/cmakelists_serial_F77_ex.in b/examples/templates/cmakelists_serial_F77_ex.in
index 9b39fff..a646067 100644
--- a/examples/templates/cmakelists_serial_F77_ex.in
+++ b/examples/templates/cmakelists_serial_F77_ex.in
@@ -1,33 +1,23 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ serial examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
 
 cmake_minimum_required(VERSION 2.8)
@@ -37,9 +27,26 @@ PROJECT(F at SOLVER@_serial_examples Fortran)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
-LIST(REMOVE_DUPLICATES examples)
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
+
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
+
+# Specify path to SUNDIALS header files
+SET(SUNDIALS_INC_DIR
+  @includedir@
+  CACHE STRING
+  "Location of SUNDIALS header files")
+
+# Add path to SUNDIALS header files
+INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
 
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
@@ -51,7 +58,7 @@ FIND_LIBRARY(SUNDIALS_SOLVER_LIB
 
 FIND_LIBRARY(SUNDIALS_SOLVER_FLIB
   @SOLVER_FLIB@ ${SUNDIALS_LIB_DIR}
-  DOC "@SOLVER@ F77-C library")
+  DOC "@SOLVER@ Fortran-C library")
 
 # Find the NVECTOR library
 FIND_LIBRARY(SUNDIALS_NVEC_LIB
@@ -60,41 +67,133 @@ FIND_LIBRARY(SUNDIALS_NVEC_LIB
 
 FIND_LIBRARY(SUNDIALS_NVEC_FLIB
   sundials_fnvecserial ${SUNDIALS_LIB_DIR}
-  DOC "NVECTOR F77-C library")
+  DOC "NVECTOR Fortran-C library")
 
 # Set additional libraries
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
 # Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
 SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
 SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
-SET(PETSC_LIBRARIES @PETSC_LIBRARIES@ CACHE STRING "PETSC libraries")
 
-# List of all libraries
-SET(SUNDIALS_LIBS 
-  ${SUNDIALS_SOLVER_FLIB} ${SUNDIALS_SOLVER_LIB}
-  ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB}
+# List of Sundials libraries shared across all examples
+SET(SUNDIALS_LIBS
+  ${SUNDIALS_SOLVER_FLIB}
+  ${SUNDIALS_SOLVER_LIB}
+  ${SUNDIALS_NVEC_FLIB}
+  ${SUNDIALS_NVEC_LIB}
   ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
-
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
-
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
 
-IF(PETSC_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${PETSC_LIBRARIES})
-ENDIF(PETSC_LIBRARIES)
 
-# Build each example one by one
+# Build examples with SUNDIALS linear solvers one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f)
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
 
+
+# Build each example with LAPACK linear solvers one by one
+IF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_FLIB
+      sundials_fsunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver Fortran-C library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB
+      sundials_fsunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
+IF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_FLIB
+      sundials_fsunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
+
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_FLIB
+      sundials_fsunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/cmakelists_serial_F90_ex.in b/examples/templates/cmakelists_serial_F90_ex.in
index 8641fa9..c57bd89 100644
--- a/examples/templates/cmakelists_serial_F90_ex.in
+++ b/examples/templates/cmakelists_serial_F90_ex.in
@@ -1,34 +1,25 @@
+# -*- mode: cmake -*-
 # -----------------------------------------------------------------
-# $Revision: 4824 $
-# $Date: 2016-07-24 16:39:04 -0700 (Sun, 24 Jul 2016) $
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Daniel R. Reynolds @ SMU
-# -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # CMakeLists.txt for @SOLVER@ serial examples
 #
-# This file is generated from a template using  various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user CMakeLists configuration files.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LAPACK_LIBRARIES. Otherwise, this variable should contain
-# an empty string or LAPACK_LIBRARIES-NOTFOUND. If this variable 
-# contains a valid library entry, we add it to each example traget
-# whether they use the Lapack module or not. This is done in order
-# to address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
-#
 # -----------------------------------------------------------------
+
 cmake_minimum_required(VERSION 2.8)
 
 # Specify project name
@@ -36,8 +27,26 @@ PROJECT(F90 at SOLVER@_serial_examples Fortran)
 
 MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
 
-# Set the names of the examples to be built
-SET(examples @EXAMPLES@ @EXAMPLES_BL@)
+# Examples using SUNDIALS linear solvers
+SET(examples @EXAMPLES@)
+
+# Examples using LAPACK linear solvers
+SET(examples_bl @EXAMPLES_BL@)
+
+# Examples using KLU linear solvers
+SET(examples_klu @EXAMPLES_KLU@)
+
+# Examples using SuperLU_MT linear solvers
+SET(examples_slumt @EXAMPLES_SLUMT@)
+
+# Specify path to SUNDIALS header files
+SET(SUNDIALS_INC_DIR
+  @includedir@
+  CACHE STRING
+  "Location of SUNDIALS header files")
+
+# Add path to SUNDIALS header files
+INCLUDE_DIRECTORIES(${SUNDIALS_INC_DIR})
 
 # Set search path for SUNDIALS libraries 
 SET(SUNDIALS_LIB_DIR @libdir@)
@@ -64,30 +73,127 @@ FIND_LIBRARY(SUNDIALS_NVEC_FLIB
 SET(SUNDIALS_EXTRA_LIB @LIBS@ CACHE STRING "Additional libraries")
 
 # Set other libraries libraries
-SET(LAPACK_LIBRARIES @BLAS_LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+SET(BLAS_LIBRARIES @BLAS_LIBS@ CACHE STRING "Blas libraries")
+SET(LAPACK_LIBRARIES @LAPACK_LIBS@ CACHE STRING "Lapack libraries")
+
+INCLUDE_DIRECTORIES(@SUPERLUMT_INCLUDE_DIR@)
 SET(SUPERLUMT_LIBRARIES @SUPERLUMT_LIBRARIES@ CACHE STRING "SuperLUMT libraries")
+
+INCLUDE_DIRECTORIES(@KLU_INCLUDE_DIR@)
 SET(KLU_LIBRARIES @KLU_LIBRARIES@ CACHE STRING "KLU libraries")
 
-# List of all libraries
-SET(SUNDIALS_LIBS 
-  ${SUNDIALS_SOLVER_FLIB} ${SUNDIALS_SOLVER_LIB}
-  ${SUNDIALS_NVEC_FLIB} ${SUNDIALS_NVEC_LIB}
+# List of Sundials libraries shared across all examples
+SET(SUNDIALS_LIBS
+  ${SUNDIALS_SOLVER_FLIB}
+  ${SUNDIALS_SOLVER_LIB}
+  ${SUNDIALS_NVEC_FLIB}
+  ${SUNDIALS_NVEC_LIB}
   ${SUNDIALS_EXTRA_LIB})
-IF(LAPACK_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${LAPACK_LIBRARIES})
-ENDIF(LAPACK_LIBRARIES)
 
-IF(SUPERLUMT_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${SUPERLUMT_LIBRARIES})
-ENDIF(SUPERLUMT_LIBRARIES)
 
-IF(KLU_LIBRARIES)
-  LIST(APPEND SUNDIALS_LIBS ${KLU_LIBRARIES})
-ENDIF(KLU_LIBRARIES)
-
-# Build each example one by one
+# Build examples with SUNDIALS linear solvers one by one
 FOREACH(example ${examples})
+
+  # example source files
   ADD_EXECUTABLE(${example} ${example}.f90)
+
+  # libraries to link against
   TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+
 ENDFOREACH(example ${examples})
 
+
+# Build each example with LAPACK linear solvers one by one
+IF(LAPACK_LIBRARIES)
+  FOREACH(example ${examples_bl})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_LIB
+      sundials_sunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKBAND_FLIB
+      sundials_fsunlinsollapackband ${SUNDIALS_LIB_DIR}
+      DOC "Sundials banded LAPACK linear solver Fortran-C library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_LIB
+      sundials_sunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB
+      sundials_fsunlinsollapackdense ${SUNDIALS_LIB_DIR}
+      DOC "Sundials dense LAPACK linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f90)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKBAND_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLLAPACKDENSE_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${LAPACK_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_bl})
+ENDIF()
+
+
+# Build each example with KLU linear solvers one by one
+IF(KLU_LIBRARIES)
+  FOREACH(example ${examples_klu})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_LIB
+      sundials_sunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLKLU_FLIB
+      sundials_fsunlinsolklu ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f90)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLKLU_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${KLU_LIBRARIES})
+
+  ENDFOREACH(example ${examples_klu})
+ENDIF()
+
+
+# Build each example with SuperLU_MT linear solvers one by one
+IF(SUPERLUMT_LIBRARIES)
+  FOREACH(example ${examples_slumt})
+
+    # Find the Sundials linear solver libraries
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_LIB
+      sundials_sunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver library")
+
+    FIND_LIBRARY(SUNDIALS_SUNLINSOLSLUMT_FLIB
+      sundials_fsunlinsolsuperlumt ${SUNDIALS_LIB_DIR}
+      DOC "Sundials KLU linear solver Fortran-C library")
+
+    # example source files
+    ADD_EXECUTABLE(${example} ${example}.f90)
+  
+    # libraries to link against
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_LIBS})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_LIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUNDIALS_SUNLINSOLSLUMT_FLIB})
+    TARGET_LINK_LIBRARIES(${example} ${SUPERLUMT_LIBRARIES})
+
+    IF(BLAS_LIBRARIES)
+      TARGET_LINK_LIBRARIES(${example} ${BLAS_LIBRARIES})
+    ENDIF()
+
+  ENDFOREACH(example ${examples_slumt})
+ENDIF()
diff --git a/examples/templates/makefile_cuda_CUDA_ex.in b/examples/templates/makefile_cuda_CUDA_ex.in
new file mode 100644
index 0000000..06f2c88
--- /dev/null
+++ b/examples/templates/makefile_cuda_CUDA_ex.in
@@ -0,0 +1,81 @@
+# -*- mode: makefile -*-
+# -----------------------------------------------------------------
+# Programmer: Slaven Peles @ LLNL
+# -----------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# -----------------------------------------------------------------
+# Makefile for @SOLVER@ CUDA examples
+#
+# This file is generated from a template using various variables
+# set at configuration time. It can be used as a template for
+# other user Makefiles.
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+prefix       = @prefix@
+exec_prefix  = @exec_prefix@
+includedir   = @includedir@
+libdir       = @libdir@
+
+NVCC     = @CUDA_NVCC_EXECUTABLE@
+NVCCFLAGS = 
+CPP      = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX      = @CXX@
+CXXFLAGS = @CXXFLAGS@
+LDFLAGS  = @LDFLAGS@
+LIBS     = @LIBS@
+CUDALIBS = @CUDA_CUDART_LIBRARY@
+
+LINKFLAGS = -Xlinker ,-rpath, at libdir@
+
+TMP_INCS = ${includedir}
+INCLUDES = $(addprefix -I, ${TMP_INCS})
+
+TMP_LIBRARIES_SUNDIALS = @SOLVER_LIB@ sundials_nveccuda
+LIBRARIES_SUNDIALS = ${addprefix -l, ${TMP_LIBRARIES_SUNDIALS}}
+
+LIBRARIES = ${LIBRARIES_SUNDIALS} ${LIBS}
+
+EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
+
+OBJECTS = ${EXAMPLES:=.o}
+OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
+
+# -----------------------------------------------------------------------------------------
+
+.SUFFIXES : .o .cu
+
+.c.o :
+	${NVCC} ${CPPFLAGS} ${NVCCFLAGS} ${INCLUDES} -c $<
+
+.cu.o :
+	${NVCC} ${CPPFLAGS} ${NVCCFLAGS} ${INCLUDES} -c $<
+
+# -----------------------------------------------------------------------------------------
+
+all: ${OBJECTS}
+	@for i in ${EXAMPLES} ; do \
+	  echo "${NVCC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${NVCCFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${NVCC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${NVCCFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${CUDALIBS} ${LINKFLAGS} ; \
+	done
+
+${OBJECTS}: ${OBJECTS_DEPENDENCIES}
+
+clean:
+	rm -f ${OBJECTS_DEPENDENCIES}
+	rm -f ${OBJECTS}
+	rm -f ${EXAMPLES}
+
+# -----------------------------------------------------------------------------------------
+
diff --git a/examples/templates/makefile_openmp_C_ex.in b/examples/templates/makefile_openmp_C_ex.in
index 2469d86..1f19d67 100644
--- a/examples/templates/makefile_openmp_C_ex.in
+++ b/examples/templates/makefile_openmp_C_ex.in
@@ -1,31 +1,23 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Steven Smith @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Steven Smith @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
-# Makefile for @SOLVER@ pthreads examples.
+# Makefile for @SOLVER@ OpenMP examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -44,19 +36,52 @@ LIBS     = @LIBS@
 
 LINKFLAGS = -Wl,-rpath, at libdir@
 
-INCLUDES = -I${includedir}
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecopenmp ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
-LIBRARIES_PETSC = @PETSC_LIBRARIES@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
 EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
 
 OBJECTS = ${EXAMPLES:=.o}
 OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+EXAMPLES_DEPENDENCIES_BL = @EXAMPLES_DEPENDENCIES_BL@
+
+OBJECTS_BL = ${EXAMPLES_BL:=.o}
+OBJECTS_DEPENDENCIES_BL = ${EXAMPLES_DEPENDENCIES_BL:=.o}
+
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+EXAMPLES_DEPENDENCIES_KLU = @EXAMPLES_DEPENDENCIES_KLU@
+
+OBJECTS_KLU = ${EXAMPLES_KLU:=.o}
+OBJECTS_DEPENDENCIES_KLU = ${EXAMPLES_DEPENDENCIES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+EXAMPLES_DEPENDENCIES_SLUMT = @EXAMPLES_DEPENDENCIES_SLUMT@
+
+OBJECTS_SLUMT = ${EXAMPLES_SLUMT:=.o}
+OBJECTS_DEPENDENCIES_SLUMT = ${EXAMPLES_DEPENDENCIES_SLUMT:=.o}
+
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .c
@@ -66,18 +91,43 @@ OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS}" ; \
-	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS} ; \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_BL} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_BL} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
 	done
-	
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_KLU} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_KLU} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_SLUMT} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_SLUMT} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
+	done
+
 ${OBJECTS}: ${OBJECTS_DEPENDENCIES}
 
+${OBJECTS_BL}: ${OBJECTS_DEPENDENCIES_BL}
+
+${OBJECTS_KLU}: ${OBJECTS_DEPENDENCIES_KLU}
+
+${OBJECTS_SLUMT}: ${OBJECTS_DEPENDENCIES_SLUMT}
+
 clean:
-	rm -f ${OBJECTS_DEPENDENCIES}
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS_DEPENDENCIES} ${OBJECTS_DEPENDENCIES_BL} ${OBJECTS_DEPENDENCIES_KLU} ${OBJECTS_DEPENDENCIES_SLUMT}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/examples/templates/makefile_openmp_F77_ex.in b/examples/templates/makefile_openmp_F77_ex.in
index 599e093..9053791 100644
--- a/examples/templates/makefile_openmp_F77_ex.in
+++ b/examples/templates/makefile_openmp_F77_ex.in
@@ -1,31 +1,27 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4074 $
-# $Date: 2014-04-23 14:13:52 -0700 (Wed, 23 Apr 2014) $
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Daniel R. Reynolds @ SMU
-# -----------------------------------------------------------------
-# Copyright (c) 2014, The Regents of the University of California.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ Fortran OpenMP examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -43,34 +39,77 @@ F77_LIBS    = @F77_LIBS@
 
 LINKFLAGS = -Wl,-rpath, at libdir@
 
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_fsunlinsollapackdense -lsundials_fsunlinsollapackband -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_fsunlinsolklu -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_fsunlinsolsuperlumt -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecopenmp -lsundials_nvecopenmp ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
-LIBRARIES_PETSC = @PETSC_LIBRARIES@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
+OBJECTS  = ${EXAMPLES:=.o}
 
-OBJECTS = ${EXAMPLES:=.o}
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+OBJECTS_BL  = ${EXAMPLES_BL:=.o}
+
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+OBJECTS_KLU  = ${EXAMPLES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+OBJECTS_SLUMT  = ${EXAMPLES_SLUMT:=.o}
 
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .f
 
 .f.o :
-	${F77} ${FFLAGS} -c $<
+	${F77} ${FFLAGS} ${INCLUDES} -c $<
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS}" ; \
-	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS} ; \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
+	done
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
 	done
 
 clean:
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/examples/templates/makefile_parallel_CXX_ex.in b/examples/templates/makefile_parallel_CXX_ex.in
index aef617d..671e61a 100644
--- a/examples/templates/makefile_parallel_CXX_ex.in
+++ b/examples/templates/makefile_parallel_CXX_ex.in
@@ -1,32 +1,26 @@
-# -----------------------------------------------------------------
-# $Revision: 4824 $
-# $Date: 2016-07-24 16:39:04 -0700 (Sun, 24 Jul 2016) $
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
 # Programmer: Daniel R. Reynolds @ SMU
 # -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ parallel examples
 #
 # This file is generated from a template using various variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, even the parallel ones which obviously cannot 
-# use the Lapack linear solver modules simply to address the case 
-# in which the SUNDIALS libraries are shared objects. In that case, 
-# the solver library references Lapack  symbols which must be 
-# always resolved by linking against the Blas/Lapack libraries. 
-# If only static SUNDIALS libraries have been built, it is not 
-# required to link the Blas/Lapack libraries for the parallel 
-# examples...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -42,23 +36,21 @@ CXX         = @CXX@
 CXXFLAGS    = @CXXFLAGS@
 LDFLAGS     = @LDFLAGS@
 LIBS        = @LIBS@
+
+LINKFLAGS = -Wl,-rpath, at libdir@
+
 MPICXX      = @MPICXX@
 MPI_INC_DIR = @MPI_INC_DIR@
 MPI_LIB_DIR = @MPI_LIB_DIR@
 MPI_LIBS    = @MPI_LIBS@
 MPI_FLAGS   = @MPI_FLAGS@
 
-LINKFLAGS = -Wl,-rpath, at libdir@
-
-INCLUDES = -I${includedir} -I${MPI_INC_DIR}
+TMP_INCS = ${includedir} ${MPI_INC_DIR}
+INCLUDES = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecparallel ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
 
 EXAMPLES = @EXAMPLES@
-
-OBJECTS = ${EXAMPLES:=.o}
+OBJECTS  = ${EXAMPLES:=.o}
 
 # -----------------------------------------------------------------------------------------
 
@@ -71,8 +63,8 @@ OBJECTS = ${EXAMPLES:=.o}
 
 all: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${MPICXX} -o $${i} $${i}.o ${MPI_FLAGS} ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS}" ; \
-	  ${MPICXX} -o $${i} $${i}.o ${MPI_FLAGS} ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS} ; \
+	  echo "${MPICXX} -o $${i} $${i}.o ${MPI_FLAGS} ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS}" ; \
+	  ${MPICXX} -o $${i} $${i}.o ${MPI_FLAGS} ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS} ; \
 	done
 
 clean:
diff --git a/examples/templates/makefile_parallel_C_ex.in b/examples/templates/makefile_parallel_C_ex.in
index 802d459..de63ad4 100644
--- a/examples/templates/makefile_parallel_C_ex.in
+++ b/examples/templates/makefile_parallel_C_ex.in
@@ -1,32 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
 # Programmer: Radu Serban @ LLNL
 # -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ parallel examples
 #
 # This file is generated from a template using various variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, even the parallel ones which obviously cannot 
-# use the Lapack linear solver modules simply to address the case 
-# in which the SUNDIALS libraries are shared objects. In that case, 
-# the solver library references Lapack  symbols which must be 
-# always resolved by linking against the Blas/Lapack libraries. 
-# If only static SUNDIALS libraries have been built, it is not 
-# required to link the Blas/Lapack libraries for the parallel 
-# examples...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -42,19 +32,18 @@ CC          = @CC@
 CFLAGS      = @CFLAGS@
 LDFLAGS     = @LDFLAGS@
 LIBS        = @LIBS@
+
 LINKFLAGS = -Wl,-rpath, at libdir@
+
 MPICC       = @MPICC@
 MPI_INC_DIR = @MPI_INC_DIR@
 MPI_LIB_DIR = @MPI_LIB_DIR@
 MPI_LIBS    = @MPI_LIBS@
 MPI_FLAGS   = @MPI_FLAGS@
 
-INCLUDES = -I${includedir} -I${MPI_INC_DIR}
+TMP_INCS  = ${includedir} ${MPI_INC_DIR}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecparallel ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
-LIBRARIES_PETSC = @PETSC_LIBRARIES@
 
 EXAMPLES = @EXAMPLES@
 EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
@@ -73,8 +62,8 @@ OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
 all: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS}" ; \
-	  ${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS} ; \
+	  echo "${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS}" ; \
+	  ${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS} ; \
 	done
 
 ${OBJECTS}: ${OBJECTS_DEPENDENCIES}
diff --git a/examples/templates/makefile_parallel_F77_ex.in b/examples/templates/makefile_parallel_F77_ex.in
index df4a8b3..8136336 100644
--- a/examples/templates/makefile_parallel_F77_ex.in
+++ b/examples/templates/makefile_parallel_F77_ex.in
@@ -1,33 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
 # Programmer: Radu Serban @ LLNL
 # -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ fortran parallel examples
 #
 # This file is generated from a template using various variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, even the parallel ones which obviously cannot 
-# use the Lapack linear solver modules simply to address the case 
-# in which the SUNDIALS libraries are shared objects. In that case, 
-# the solver library references Lapack  symbols which must be 
-# always resolved by linking against the Blas/Lapack libraries. 
-# If only static SUNDIALS libraries have been built, it is not 
-# required to link the Blas/Lapack libraries for the parallel 
-# examples...
-#
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -50,29 +39,26 @@ MPIF77_LNKR  = @MPIF77_LNKR@
 MPI_LIB_DIR  = @MPI_LIB_DIR@
 MPI_LIBS     = @MPI_LIBS@
 
+TMP_INCS = ${includedir} ${MPI_INC_DIR}
+INCLUDES = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecparallel -lsundials_nvecparallel ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
-LIBRARIES_PETSC = @PETSC_LIBRARIES@
 
 EXAMPLES = @EXAMPLES@
-
-OBJECTS = ${EXAMPLES:=.o}
+OBJECTS  = ${EXAMPLES:=.o}
 
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .f
 
 .f.o :
-	${MPIF77} ${FFLAGS} ${MPI_FLAGS} -I${MPI_INC_DIR} -c $<
+	${MPIF77} ${FFLAGS} ${MPI_FLAGS} -I${MPI_INC_DIR} ${INCLUDES} -c $<
 
 # -----------------------------------------------------------------------------------------
 
 all: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${MPIF77_LNKR} -o $${i} $${i}.o ${MPI_FLAGS} ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS}" ; \
-	  ${MPIF77_LNKR} -o $${i} $${i}.o ${MPI_FLAGS} ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS} ; \
+	  echo "${MPIF77_LNKR} -o $${i} $${i}.o ${MPI_FLAGS} ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS}" ; \
+	  ${MPIF77_LNKR} -o $${i} $${i}.o ${MPI_FLAGS} ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS} ; \
 	done
 
 clean:
diff --git a/examples/templates/makefile_parallel_F90_ex.in b/examples/templates/makefile_parallel_F90_ex.in
index b5bee6c..35a8312 100644
--- a/examples/templates/makefile_parallel_F90_ex.in
+++ b/examples/templates/makefile_parallel_F90_ex.in
@@ -1,33 +1,26 @@
-# -----------------------------------------------------------------
-# $Revision: 4824 $
-# $Date: 2016-07-24 16:39:04 -0700 (Sun, 24 Jul 2016) $
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
 # Programmer: Daniel R. Reynolds @ SMU
 # -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ fortran parallel examples
 #
 # This file is generated from a template using various variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, even the parallel ones which obviously cannot 
-# use the Lapack linear solver modules simply to address the case 
-# in which the SUNDIALS libraries are shared objects. In that case, 
-# the solver library references Lapack  symbols which must be 
-# always resolved by linking against the Blas/Lapack libraries. 
-# If only static SUNDIALS libraries have been built, it is not 
-# required to link the Blas/Lapack libraries for the parallel 
-# examples...
-#
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -41,36 +34,34 @@ F90FLAGS     = @F90FLAGS@
 F90_LDFLAGS  = @F90_LDFLAGS@
 F90_LIBS     = @F90_LIBS@
 
+LINKFLAGS = -Wl,-rpath, at libdir@
+
 MPIF90       = @MPIF90@
 MPI_INC_DIR  = @MPI_INC_DIR@
 MPI_FLAGS    = @MPI_FLAGS@
 MPI_LIB_DIR  = @MPI_LIB_DIR@
 MPI_LIBS     = @MPI_LIBS@
 
-LINKFLAGS = -Wl,-rpath, at libdir@
-
+TMP_INCS  = ${includedir} ${MPI_INC_DIR}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecparallel -lsundials_nvecparallel ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
 
 EXAMPLES = @EXAMPLES@
-
-OBJECTS = ${EXAMPLES:=.o}
+OBJECTS  = ${EXAMPLES:=.o}
 
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .f90
 
 .f90.o :
-	${MPIF90} ${F90FLAGS} ${MPI_FLAGS} -I${MPI_INC_DIR} -c $<
+	${MPIF90} ${F90FLAGS} ${MPI_FLAGS} -I${MPI_INC_DIR} ${INCLUDES} -c $<
 
 # -----------------------------------------------------------------------------------------
 
 all: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${MPIF90} -o $${i} $${i}.o ${MPI_FLAGS} ${F90_LDFLAGS} ${F90_LIBS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS}" ; \
-	  ${MPIF90} -o $${i} $${i}.o ${MPI_FLAGS} ${F90_LDFLAGS} ${F90_LIBS} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS} ; \
+	  echo "${MPIF90} -o $${i} $${i}.o ${MPI_FLAGS} ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS}" ; \
+	  ${MPIF90} -o $${i} $${i}.o ${MPI_FLAGS} ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS} ; \
 	done
 
 clean:
diff --git a/examples/templates/makefile_parhyp_C_ex.in b/examples/templates/makefile_parhyp_C_ex.in
index 9e56fdd..abbdf08 100644
--- a/examples/templates/makefile_parhyp_C_ex.in
+++ b/examples/templates/makefile_parhyp_C_ex.in
@@ -1,32 +1,22 @@
-# -----------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
 # Programmer: Radu Serban @ LLNL
 # -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
-# Makefile for @SOLVER@ parhyp examples
+# Makefile for @SOLVER@ hypre examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, even the parhyp ones which obviously cannot 
-# use the Lapack linear solver modules simply to address the case 
-# in which the SUNDIALS libraries are shared objects. In that case, 
-# the solver library references Lapack  symbols which must be 
-# always resolved by linking against the Blas/Lapack libraries. 
-# If only static SUNDIALS libraries have been built, it is not 
-# required to link the Blas/Lapack libraries for the parhyp 
-# examples...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -36,28 +26,32 @@ exec_prefix  = @exec_prefix@
 includedir   = @includedir@
 libdir       = @libdir@
 
-CPP         = @CPP@
-CPPFLAGS    = @CPPFLAGS@
-CC          = @CC@
-CFLAGS      = @CFLAGS@ @OpenMP_C_FLAGS@
-LDFLAGS     = @LDFLAGS@ @OpenMP_C_FLAGS@
-LIBS        = @LIBS@
+CPP      = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC       = @CC@
+CFLAGS   = @CFLAGS@ @OpenMP_C_FLAGS@
+LDFLAGS  = @LDFLAGS@ @OpenMP_C_FLAGS@
+LIBS     = @LIBS@
+
 LINKFLAGS = -Wl,-rpath, at libdir@
+
 MPICC       = @MPICC@
 MPI_INC_DIR = @MPI_INC_DIR@
 MPI_LIB_DIR = @MPI_LIB_DIR@
 MPI_LIBS    = @MPI_LIBS@
 MPI_FLAGS   = @MPI_FLAGS@
-HYPRE_INC_DIR = @HYPRE_INCLUDE_DIR@
-HYPRE_LIB_DIR = @HYPRE_LIB_DIR@
-HYPRE_LIBS    = @HYPRE_LIBRARIES@
-HYPRE_FLAGS   = @HYPRE_FLAGS@
 
-INCLUDES = -I${includedir} -I${MPI_INC_DIR} -I${HYPRE_INC_DIR}
-LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecparhyp ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
+# -----------------------------------------------------------------------------------------
+
+INCLUDES_HYPRE  = @HYPRE_INCLUDE_DIR@
+LIBRARIES_HYPRE = @HYPRE_LIBRARIES@
+LINKFLAGS_HYPRE = ${LINKFLAGS}:@HYPRE_LIBRARY_DIR@
+
+TMP_INCS = ${includedir} ${MPI_INC_DIR} ${INCLUDES_HYPRE}
+INCLUDES = $(addprefix -I, ${TMP_INCS})
+LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecparhyp ${LIBS} ${LIBRARIES_HYPRE}
+
+# -----------------------------------------------------------------------------------------
 
 EXAMPLES = @EXAMPLES@
 EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
@@ -76,8 +70,8 @@ OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
 all: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${HYPRE_LIBS} ${LINKFLAGS}" ; \
-	  ${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${HYPRE_LIBS} ${LINKFLAGS} ; \
+	  echo "${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS_HYPRE}" ; \
+	  ${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS_HYPRE} ; \
 	done
 
 ${OBJECTS}: ${OBJECTS_DEPENDENCIES}
diff --git a/examples/templates/makefile_petsc_C_ex.in b/examples/templates/makefile_petsc_C_ex.in
index 07ced4e..c8e5153 100644
--- a/examples/templates/makefile_petsc_C_ex.in
+++ b/examples/templates/makefile_petsc_C_ex.in
@@ -1,33 +1,27 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4456 $
-# $Date: 2015-03-28 20:22:03 -0700 (Sat, 28 Mar 2015) $
+# Programmer(s): Radu Serban @ LLNL
+#                Daniel R. Reynolds @ SMU
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-#             Daniel R. Reynolds @ SMU
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # -----------------------------------------------------------------
-# Makefile for @SOLVER@ parallel examples
+# Makefile for @SOLVER@ PETSc examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, even the parallel ones which obviously cannot 
-# use the Lapack linear solver modules simply to address the case 
-# in which the SUNDIALS libraries are shared objects. In that case, 
-# the solver library references Lapack  symbols which must be 
-# always resolved by linking against the Blas/Lapack libraries. 
-# If only static SUNDIALS libraries have been built, it is not 
-# required to link the Blas/Lapack libraries for the parallel 
-# examples...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -37,26 +31,32 @@ exec_prefix  = @exec_prefix@
 includedir   = @includedir@
 libdir       = @libdir@
 
-CPP         = @CPP@
-CPPFLAGS    = @CPPFLAGS@
-CC          = @CC@
-CFLAGS      = @CFLAGS@
-LDFLAGS     = @LDFLAGS@
-LIBS        = @LIBS@
+CPP      = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CC       = @CC@
+CFLAGS   = @CFLAGS@
+LDFLAGS  = @LDFLAGS@
+LIBS     = @LIBS@
+
 LINKFLAGS = -Wl,-rpath, at libdir@
+
 MPICC       = @MPICC@
 MPI_INC_DIR = @MPI_INC_DIR@
 MPI_LIB_DIR = @MPI_LIB_DIR@
 MPI_LIBS    = @MPI_LIBS@
 MPI_FLAGS   = @MPI_FLAGS@
-PETSC_LIBS = @PETSC_LIBRARIES@
-PETSC_INC_DIR = @PETSC_INCLUDE_DIR@
 
-INCLUDES = -I${includedir} -I${MPI_INC_DIR} -I${PETSC_INC_DIR}
-LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecpetsc ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
+# -----------------------------------------------------------------------------------------
+
+INCLUDES_PETSC  = @PETSC_INCLUDE_DIR@
+LIBRARIES_PETSC = @PETSC_LIBRARIES@
+LINKFLAGS_PETSC = ${LINKFLAGS}:@PETSC_LIBRARY_DIR@
+
+TMP_INCS = ${includedir} ${MPI_INC_DIR} ${INCLUDES_PETSC}
+INCLUDES = $(addprefix -I, ${TMP_INCS})
+LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecpetsc ${LIBS} ${LIBRARIES_PETSC}
+
+# -----------------------------------------------------------------------------------------
 
 EXAMPLES = @EXAMPLES@
 EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
@@ -75,8 +75,8 @@ OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
 all: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${PETSC_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS}" ; \
-	  ${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${PETSC_LIBS} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS} ; \
+	  echo "${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS_PETSC}" ; \
+	  ${MPICC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${MPI_FLAGS} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} -L${MPI_LIB_DIR} ${MPI_LIBS} ${LINKFLAGS_PETSC} ; \
 	done
 
 ${OBJECTS}: ${OBJECTS_DEPENDENCIES}
diff --git a/examples/templates/makefile_pthreads_C_ex.in b/examples/templates/makefile_pthreads_C_ex.in
index 9b80b69..cef0bbf 100644
--- a/examples/templates/makefile_pthreads_C_ex.in
+++ b/examples/templates/makefile_pthreads_C_ex.in
@@ -1,31 +1,23 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4824 $
-# $Date: 2016-07-24 16:39:04 -0700 (Sun, 24 Jul 2016) $
+# Programmer(s): Steven Smith @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Steven Smith @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
-# Makefile for @SOLVER@ pthreads examples.
+# Makefile for @SOLVER@ pthreads examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -41,20 +33,55 @@ CC       = @CC@
 CFLAGS   = @CFLAGS@
 LDFLAGS  = @LDFLAGS@ @CMAKE_THREAD_LIBS_INIT@
 LIBS     = @LIBS@
+
 LINKFLAGS = -Wl,-rpath, at libdir@
 
-INCLUDES = -I${includedir}
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecpthreads ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
 EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
 
 OBJECTS = ${EXAMPLES:=.o}
 OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+EXAMPLES_DEPENDENCIES_BL = @EXAMPLES_DEPENDENCIES_BL@
+
+OBJECTS_BL = ${EXAMPLES_BL:=.o}
+OBJECTS_DEPENDENCIES_BL = ${EXAMPLES_DEPENDENCIES_BL:=.o}
+
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+EXAMPLES_DEPENDENCIES_KLU = @EXAMPLES_DEPENDENCIES_KLU@
+
+OBJECTS_KLU = ${EXAMPLES_KLU:=.o}
+OBJECTS_DEPENDENCIES_KLU = ${EXAMPLES_DEPENDENCIES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+EXAMPLES_DEPENDENCIES_SLUMT = @EXAMPLES_DEPENDENCIES_SLUMT@
+
+OBJECTS_SLUMT = ${EXAMPLES_SLUMT:=.o}
+OBJECTS_DEPENDENCIES_SLUMT = ${EXAMPLES_DEPENDENCIES_SLUMT:=.o}
+
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .c
@@ -64,18 +91,43 @@ OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS}" ; \
-	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS} ; \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_BL} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_BL} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
+	done
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_KLU} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_KLU} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_SLUMT} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_SLUMT} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
 	done
 
 ${OBJECTS}: ${OBJECTS_DEPENDENCIES}
 
+${OBJECTS_BL}: ${OBJECTS_DEPENDENCIES_BL}
+
+${OBJECTS_KLU}: ${OBJECTS_DEPENDENCIES_KLU}
+
+${OBJECTS_SLUMT}: ${OBJECTS_DEPENDENCIES_SLUMT}
+
 clean:
-	rm -f ${OBJECTS_DEPENDENCIES}
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS_DEPENDENCIES} ${OBJECTS_DEPENDENCIES_BL} ${OBJECTS_DEPENDENCIES_KLU} ${OBJECTS_DEPENDENCIES_SLUMT}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/examples/templates/makefile_pthreads_F77_ex.in b/examples/templates/makefile_pthreads_F77_ex.in
index 3ee0acd..d345c5e 100644
--- a/examples/templates/makefile_pthreads_F77_ex.in
+++ b/examples/templates/makefile_pthreads_F77_ex.in
@@ -1,31 +1,27 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4074 $
-# $Date: 2014-04-23 14:13:52 -0700 (Wed, 23 Apr 2014) $
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Daniel R. Reynolds @ SMU
-# -----------------------------------------------------------------
-# Copyright (c) 2014, The Regents of the University of California.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ Fortran pthreads examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -43,34 +39,77 @@ F77_LIBS    = @F77_LIBS@
 
 LINKFLAGS = -Wl,-rpath, at libdir@
 
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_fsunlinsollapackdense -lsundials_fsunlinsollapackband -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_fsunlinsolklu -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_fsunlinsolsuperlumt -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecpthreads -lsundials_nvecpthreads ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
-LIBRARIES_PETSC = @PETSC_LIBRARIES@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
+OBJECTS  = ${EXAMPLES:=.o}
 
-OBJECTS = ${EXAMPLES:=.o}
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+OBJECTS_BL  = ${EXAMPLES_BL:=.o}
+
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+OBJECTS_KLU  = ${EXAMPLES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+OBJECTS_SLUMT  = ${EXAMPLES_SLUMT:=.o}
 
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .f
 
 .f.o :
-	${F77} ${FFLAGS} -c $<
+	${F77} ${FFLAGS} ${INCLUDES} -c $<
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS}" ; \
-	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS} ; \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
+	done
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
 	done
 
 clean:
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/examples/templates/makefile_raja_CUDA_ex.in b/examples/templates/makefile_raja_CUDA_ex.in
new file mode 100644
index 0000000..31dfc07
--- /dev/null
+++ b/examples/templates/makefile_raja_CUDA_ex.in
@@ -0,0 +1,83 @@
+# -*- mode: makefile -*-
+# -----------------------------------------------------------------
+# Programmer: Slaven Peles @ LLNL
+# -----------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# -----------------------------------------------------------------
+# Makefile for @SOLVER@ Raja (CUDA) examples
+#
+# This file is generated from a template using various variables
+# set at configuration time. It can be used as a template for
+# other user Makefiles.
+# -----------------------------------------------------------------
+
+SHELL = @SHELL@
+
+prefix       = @prefix@
+exec_prefix  = @exec_prefix@
+includedir   = @includedir@
+libdir       = @libdir@
+
+NVCC      = @CUDA_NVCC_EXECUTABLE@
+NVCCFLAGS =
+RAJAFLAGS = -std=c++11 --expt-extended-lambda 
+
+CPP      = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX      = @CXX@
+CXXFLAGS = @CXXFLAGS@
+LDFLAGS  = @LDFLAGS@
+LIBS     = @LIBS@
+
+LINKFLAGS = -Xlinker ,-rpath, at libdir@
+
+CUDALIBS = @CUDA_CUDART_LIBRARY@
+RAJALIBDIR = @RAJA_LIB_DIR@
+
+INCLUDES_RAJA = @RAJA_INCLUDE_DIR@
+
+TMP_INCS = ${includedir} ${INCLUDES_RAJA}
+INCLUDES = $(addprefix -I, ${TMP_INCS})
+LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecraja -lRAJA ${CUDALIBS} ${LIBS}
+
+EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
+
+OBJECTS = ${EXAMPLES:=.o}
+OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
+
+# -----------------------------------------------------------------------------------------
+
+.SUFFIXES : .o .cu
+
+.c.o :
+	${NVCC} ${CXXFLAGS} ${RAJAFLAGS} ${INCLUDES} -c $<
+
+.cu.o :
+	${NVCC} ${NVCCFLAGS} ${CXXFLAGS} ${RAJAFLAGS} ${INCLUDES} -c $<
+
+# -----------------------------------------------------------------------------------------
+
+all: ${OBJECTS}
+	@for i in ${EXAMPLES} ; do \
+	  echo "${NVCC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${NVCCFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${NVCC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${NVCCFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} -L${RAJALIBDIR} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+${OBJECTS}: ${OBJECTS_DEPENDENCIES}
+
+clean:
+	rm -f ${OBJECTS_DEPENDENCIES}
+	rm -f ${OBJECTS}
+	rm -f ${EXAMPLES}
+
+# -----------------------------------------------------------------------------------------
+
diff --git a/examples/templates/makefile_serial_CXX_ex.in b/examples/templates/makefile_serial_CXX_ex.in
index 7c7586d..25b5750 100644
--- a/examples/templates/makefile_serial_CXX_ex.in
+++ b/examples/templates/makefile_serial_CXX_ex.in
@@ -1,31 +1,27 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4944 $
-# $Date: 2016-09-21 21:48:35 -0700 (Wed, 21 Sep 2016) $
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Daniel R. Reynolds @ SMU
-# -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # -----------------------------------------------------------------
-# Makefile for @SOLVER@ serial examples.
+# Makefile for @SOLVER@ serial examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -38,21 +34,45 @@ libdir       = @libdir@
 CPP      = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CXX      = @CXX@
-CXXFLAGS   = @CXXFLAGS@
+CXXFLAGS = @CXXFLAGS@
 LDFLAGS  = @LDFLAGS@
 LIBS     = @LIBS@
 
 LINKFLAGS = -Wl,-rpath, at libdir@
 
-INCLUDES = -I${includedir}
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecserial ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
+OBJECTS  = ${EXAMPLES:=.o}
 
-OBJECTS = ${EXAMPLES:=.o}
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+OBJECTS_BL  = ${EXAMPLES_BL:=.o}
+
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+OBJECTS_KLU  = ${EXAMPLES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+OBJECTS_SLUMT  = ${EXAMPLES_SLUMT:=.o}
 
 # -----------------------------------------------------------------------------------------
 
@@ -63,15 +83,34 @@ OBJECTS = ${EXAMPLES:=.o}
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS}" ; \
-	  ${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS} ; \
+	  echo "${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
+	done
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${CXX} -o $${i} $${i}.o ${CXXFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
 	done
 
 clean:
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/examples/templates/makefile_serial_C_ex.in b/examples/templates/makefile_serial_C_ex.in
index 5a5460b..f090eee 100644
--- a/examples/templates/makefile_serial_C_ex.in
+++ b/examples/templates/makefile_serial_C_ex.in
@@ -1,31 +1,23 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2002, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
-# Makefile for @SOLVER@ serial examples.
+# Makefile for @SOLVER@ serial examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -44,19 +36,52 @@ LIBS     = @LIBS@
 
 LINKFLAGS = -Wl,-rpath, at libdir@
 
-INCLUDES = -I${includedir}
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_LIB@ -lsundials_nvecserial ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
-LIBRARIES_PETSC = @PETSC_LIBRARIES@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
 EXAMPLES_DEPENDENCIES = @EXAMPLES_DEPENDENCIES@
 
 OBJECTS = ${EXAMPLES:=.o}
 OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+EXAMPLES_DEPENDENCIES_BL = @EXAMPLES_DEPENDENCIES_BL@
+
+OBJECTS_BL = ${EXAMPLES_BL:=.o}
+OBJECTS_DEPENDENCIES_BL = ${EXAMPLES_DEPENDENCIES_BL:=.o}
+
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+EXAMPLES_DEPENDENCIES_KLU = @EXAMPLES_DEPENDENCIES_KLU@
+
+OBJECTS_KLU = ${EXAMPLES_KLU:=.o}
+OBJECTS_DEPENDENCIES_KLU = ${EXAMPLES_DEPENDENCIES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+EXAMPLES_DEPENDENCIES_SLUMT = @EXAMPLES_DEPENDENCIES_SLUMT@
+
+OBJECTS_SLUMT = ${EXAMPLES_SLUMT:=.o}
+OBJECTS_DEPENDENCIES_SLUMT = ${EXAMPLES_DEPENDENCIES_SLUMT:=.o}
+
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .c
@@ -66,18 +91,43 @@ OBJECTS_DEPENDENCIES = ${EXAMPLES_DEPENDENCIES:=.o}
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS}" ; \
-	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS} ; \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_BL} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_BL} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
+	done
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_KLU} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_KLU} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_SLUMT} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${CC} -o $${i} $${i}.o ${OBJECTS_DEPENDENCIES_SLUMT} ${CFLAGS} ${LDFLAGS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
 	done
 
 ${OBJECTS}: ${OBJECTS_DEPENDENCIES}
 
+${OBJECTS_BL}: ${OBJECTS_DEPENDENCIES_BL}
+
+${OBJECTS_KLU}: ${OBJECTS_DEPENDENCIES_KLU}
+
+${OBJECTS_SLUMT}: ${OBJECTS_DEPENDENCIES_SLUMT}
+
 clean:
-	rm -f ${OBJECTS_DEPENDENCIES}
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS_DEPENDENCIES} ${OBJECTS_DEPENDENCIES_BL} ${OBJECTS_DEPENDENCIES_KLU} ${OBJECTS_DEPENDENCIES_SLUMT}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/examples/templates/makefile_serial_F77_ex.in b/examples/templates/makefile_serial_F77_ex.in
index a31e37d..faf35ab 100644
--- a/examples/templates/makefile_serial_F77_ex.in
+++ b/examples/templates/makefile_serial_F77_ex.in
@@ -1,31 +1,23 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4958 $
-# $Date: 2016-09-23 14:02:13 -0700 (Fri, 23 Sep 2016) $
+# Programmer(s): Radu Serban @ LLNL
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Radu Serban @ LLNL
-# -----------------------------------------------------------------
-# Copyright (c) 2007, The Regents of the University of California.
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
 # Produced at the Lawrence Livermore National Laboratory.
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ Fortran serial examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -43,34 +35,77 @@ F77_LIBS    = @F77_LIBS@
 
 LINKFLAGS = -Wl,-rpath, at libdir@
 
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_fsunlinsollapackdense -lsundials_fsunlinsollapackband -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_fsunlinsolklu -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_fsunlinsolsuperlumt -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecserial -lsundials_nvecserial ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
-LIBRARIES_PETSC = @PETSC_LIBRARIES@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
+OBJECTS  = ${EXAMPLES:=.o}
+
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+OBJECTS_BL  = ${EXAMPLES_BL:=.o}
 
-OBJECTS = ${EXAMPLES:=.o}
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+OBJECTS_KLU  = ${EXAMPLES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+OBJECTS_SLUMT  = ${EXAMPLES_SLUMT:=.o}
 
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .f
 
 .f.o :
-	${F77} ${FFLAGS} -c $<
+	${F77} ${FFLAGS} ${INCLUDES} -c $<
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS}" ; \
-	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LIBRARIES_PETSC} ${LINKFLAGS} ; \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
+	done
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${F77_LNKR} -o $${i} $${i}.o ${F77_LDFLAGS} ${F77_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
 	done
 
 clean:
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/examples/templates/makefile_serial_F90_ex.in b/examples/templates/makefile_serial_F90_ex.in
index faeebdc..251053c 100644
--- a/examples/templates/makefile_serial_F90_ex.in
+++ b/examples/templates/makefile_serial_F90_ex.in
@@ -1,31 +1,27 @@
+# -*- mode: makefile -*-
 # -----------------------------------------------------------------
-# $Revision: 4824 $
-# $Date: 2016-07-24 16:39:04 -0700 (Sun, 24 Jul 2016) $
+# Programmer(s): Daniel R. Reynolds @ SMU
+#                David J. Gardner @ LLNL
 # -----------------------------------------------------------------
-# Programmer: Daniel R. Reynolds @ SMU
-# -----------------------------------------------------------------
-# Copyright (c) 2013, The Regents of the University of California.
-# Produced at the Lawrence Livermore National Laboratory.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2014, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # -----------------------------------------------------------------
 # Makefile for @SOLVER@ Fortran90 serial examples
 #
-# This file is generated from a template using various variables
+# This file is generated from a template using variables
 # set at configuration time. It can be used as a template for
 # other user Makefiles.
-#
-# Note: if the solver was successfully configured with Blas/Lapack
-# support, the Blas/Lapack libraries are specified through the 
-# variable LIBRARIES_BL. Otherwise, this variable should contain
-# an empty string. We include LIBRARIES_BL in the link line for
-# all examples, whether they use the Lapack module or not, to
-# address the case in which the SUNDIALS libraries are shared 
-# objects. In that case, the solver library references Lapack 
-# symbols which must be always resolved by linking against the
-# Blas/Lapack libraries. If only static SUNDIALS libraries have 
-# been built, it is not required to link the Blas/Lapack libraries
-# for examples that do not use that module...
 # -----------------------------------------------------------------
 
 SHELL = @SHELL@
@@ -42,33 +38,77 @@ F90_LIBS    = @F90_LIBS@
 
 LINKFLAGS = -Wl,-rpath, at libdir@
 
+# -----------------------------------------------------------------------------------------
+
+LIBRARIES_LAPACK = -lsundials_fsunlinsollapackdense -lsundials_fsunlinsollapackband -lsundials_sunlinsollapackdense -lsundials_sunlinsollapackband @LAPACK_LIBS@ @BLAS_LIBS@
+LINKFLAGS_LAPACK = ${LINKFLAGS}:@LAPACK_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+INCLUDES_KLU  = @KLU_INCLUDE_DIR@
+LIBRARIES_KLU = -lsundials_fsunlinsolklu -lsundials_sunlinsolklu @KLU_LIBS@
+LINKFLAGS_KLU = ${LINKFLAGS}:@KLU_LIBRARY_DIR@
+
+INCLUDES_SLUMT  = @SUPERLUMT_INCLUDE_DIR@
+LIBRARIES_SLUMT = -lsundials_fsunlinsolsuperlumt -lsundials_sunlinsolsuperlumt @SUPERLUMT_LIBS@ @BLAS_LIBS@
+LINKFLAGS_SLUMT = ${LINKFLAGS}:@SUPERLUMT_LIBRARY_DIR@:@BLAS_LIBRARY_DIR@
+
+TMP_INCS  = ${includedir} ${INCLUDES_SLUMT} ${INCLUDES_KLU}
+INCLUDES  = $(addprefix -I, ${TMP_INCS})
 LIBRARIES = -l at SOLVER_FLIB@ -l at SOLVER_LIB@ -lsundials_fnvecserial -lsundials_nvecserial ${LIBS}
-LIBRARIES_BL = @BLAS_LAPACK_LIBS@
-LIBRARIES_SLUMT = @SUPERLUMT_LIBS@
-LIBRARIES_KLU = @KLU_LIBS@
 
-EXAMPLES = @EXAMPLES@ @EXAMPLES_BL@
+# -----------------------------------------------------------------------------------------
+
+EXAMPLES = @EXAMPLES@
+OBJECTS  = ${EXAMPLES:=.o}
 
-OBJECTS = ${EXAMPLES:=.o}
+# LAPACK Examples
+EXAMPLES_BL = @EXAMPLES_BL@
+OBJECTS_BL  = ${EXAMPLES_BL:=.o}
+
+# KLU Examples
+EXAMPLES_KLU = @EXAMPLES_KLU@
+OBJECTS_KLU  = ${EXAMPLES_KLU:=.o}
+
+# SuperLU_MT Examples
+EXAMPLES_SLUMT = @EXAMPLES_SLUMT@
+OBJECTS_SLUMT  = ${EXAMPLES_SLUMT:=.o}
 
 # -----------------------------------------------------------------------------------------
 
 .SUFFIXES : .o .f90
 
 .f90.o :
-	${F90} ${F90FLAGS} -c $<
+	${F90} ${F90FLAGS} ${INCLUDES} -c $<
 
 # -----------------------------------------------------------------------------------------
 
-all: ${OBJECTS}
+all: examples examples_bl examples_klu examples_slumt
+
+examples: ${OBJECTS}
 	@for i in ${EXAMPLES} ; do \
-	  echo "${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS}" ; \
-	  ${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} -L${libdir} ${LIBRARIES} ${LIBRARIES_BL} ${LIBRARIES_SLUMT} ${LIBRARIES_KLU} ${LINKFLAGS} ; \
+	  echo "${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS}" ; \
+	  ${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LINKFLAGS} ; \
+	done
+
+examples_bl: ${OBJECTS_BL}
+	@for i in ${EXAMPLES_BL} ; do \
+	  echo "${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK}" ; \
+	  ${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_LAPACK} ${LINKFLAGS_LAPACK} ; \
+	done
+
+examples_klu: ${OBJECTS_KLU}
+	@for i in ${EXAMPLES_KLU} ; do \
+	  echo "${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU}" ; \
+	  ${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_KLU} ${LINKFLAGS_KLU} ; \
+	done
+
+examples_slumt: ${OBJECTS_SLUMT}
+	@for i in ${EXAMPLES_SLUMT} ; do \
+	  echo "${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT}" ; \
+	  ${F90} -o $${i} $${i}.o ${F90_LDFLAGS} ${F90_LIBS} ${INCLUDES} -L${libdir} ${LIBRARIES} ${LIBRARIES_SLUMT} ${LINKFLAGS_SLUMT} ; \
 	done
 
 clean:
-	rm -f ${OBJECTS}
-	rm -f ${EXAMPLES}
+	rm -f ${OBJECTS} ${OBJECTS_BL} ${OBJECTS_KLU} ${OBJECTS_SLUMT}
+	rm -f ${EXAMPLES} ${EXAMPLES_BL} ${EXAMPLES_KLU} ${EXAMPLES_SLUMT}
 
 # -----------------------------------------------------------------------------------------
-
diff --git a/include/arkode/arkode.h b/include/arkode/arkode.h
index 1a7123c..0bf0a6d 100644
--- a/include/arkode/arkode.h
+++ b/include/arkode/arkode.h
@@ -472,38 +472,38 @@ SUNDIALS_EXPORT void *ARKodeCreate();
                           | the problem is linear, and to tighten 
                           | the linear solver tolerances while 
                           | taking only one Newton iteration.
-                          | [FALSE]
+                          | [SUNFALSE]
                           |
  ARKodeSetNonlinear       | specifies that the implicit portion of 
                           | the problem is nonlinear.  Used to undo
                           | a previous call to ARKodeSetLinear.
-                          | [TRUE]
+                          | [SUNTRUE]
                           |
  ARKodeSetFixedPoint      | specifies that the implicit portion of 
                           | the problem should use the accelerated 
                           | fixed-point solver.
-                          | [FALSE]
+                          | [SUNFALSE]
                           |
  ARKodeSetNewton          | specifies that the implicit portion of 
                           | the problem should use the modified Newton 
                           | solver.  Used to undo a previous call to
                           | ARKodeSetFixedPoint.
-                          | [TRUE]
+                          | [SUNTRUE]
                           |
  ARKodeSetExplicit        | specifies that implicit portion of 
                           | problem is disabled, and to use an 
                           | explicit RK method.
-                          | [FALSE]
+                          | [SUNFALSE]
                           |
  ARKodeSetImplicit        | specifies that explicit portion of 
                           | problem is disabled, and to use an 
                           | implicit RK method.
-                          | [FALSE]
+                          | [SUNFALSE]
                           |
  ARKodeSetImEx            | specifies that problem has both 
                           | implicit and explicit parts, and to 
                           | use an ARK method.
-                          | [TRUE]
+                          | [SUNTRUE]
                           |
  ARKodeSetERKTable        | specifies to use a customized Butcher 
                           | table for the explicit portion of the 
@@ -1224,6 +1224,9 @@ SUNDIALS_EXPORT int ARKodeGetDky(void *arkode_mem, realtype t,
  ARKodeGetErrWeights returns the current error weight vector.
                      The user must allocate space for eweight.
 
+ ARKodeGetResWeights returns the current residual weight vector.
+                     The user must allocate space for rweight.
+
  ARKodeGetEstLocalErrors returns the vector of estimated local
                          errors. The user must allocate space
                          for ele.
@@ -1281,6 +1284,8 @@ SUNDIALS_EXPORT int ARKodeGetTolScaleFactor(void *arkode_mem,
 					    realtype *tolsfac);
 SUNDIALS_EXPORT int ARKodeGetErrWeights(void *arkode_mem, 
 					N_Vector eweight);
+SUNDIALS_EXPORT int ARKodeGetResWeights(void *arkode_mem, 
+					N_Vector rweight);
 SUNDIALS_EXPORT int ARKodeGetEstLocalErrors(void *arkode_mem, 
 					    N_Vector ele);
 SUNDIALS_EXPORT int ARKodeGetNumGEvals(void *arkode_mem, 
diff --git a/include/arkode/arkode_band.h b/include/arkode/arkode_band.h
deleted file mode 100644
index c96f764..0000000
--- a/include/arkode/arkode_band.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Header file for the ARKODE band linear solver, ARKBAND.
- *--------------------------------------------------------------*/
-
-#ifndef _ARKBAND_H
-#define _ARKBAND_H
-
-#include <arkode/arkode_direct.h>
-#include <sundials/sundials_band.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*---------------------------------------------------------------
- ARKBand:
-
- A call to the ARKBand function links the main ARKODE integrator
- with the ARKBAND linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- N is the size of the ODE system.
-
- mupper is the upper bandwidth of the band Jacobian
-        approximation.
-
- mlower is the lower bandwidth of the band Jacobian
-        approximation.
-
- The return value of ARKBand is one of:
-    ARKDLS_SUCCESS   if successful
-    ARKDLS_MEM_NULL  if the arkode memory was NULL
-    ARKDLS_MEM_FAIL  if there was a memory allocation failure
-    ARKDLS_ILL_INPUT if a required vector operation is missing or
-                       if a bandwidth has an illegal value.
----------------------------------------------------------------*/
-
-SUNDIALS_EXPORT int ARKBand(void *arkode_mem, long int N, 
-			    long int mupper, long int mlower);
-
-/*---------------------------------------------------------------
- ARKMassBand:
-
- A call to the ARKMassBand function links the mass matrix solve
- with the ARKBAND linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- N is the size of the ODE system.
-
- mupper is the upper bandwidth of the band Jacobian
-        approximation.
-
- mlower is the lower bandwidth of the band Jacobian
-        approximation.
-
- bmass is the user-supplied band mass matrix setup routine.
-
- The return value of ARKBand is one of:
-    ARKDLS_SUCCESS   if successful
-    ARKDLS_MEM_NULL  if the arkode memory was NULL
-    ARKDLS_MEM_FAIL  if there was a memory allocation failure
-    ARKDLS_ILL_INPUT if a required vector operation is missing or
-                       if a bandwidth has an illegal value.
----------------------------------------------------------------*/
-
-SUNDIALS_EXPORT int ARKMassBand(void *arkode_mem, long int N, 
-				long int mupper, long int mlower,
-				ARKDlsBandMassFn bmass);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_bandpre.h b/include/arkode/arkode_bandpre.h
index 0b905f8..723b7c2 100644
--- a/include/arkode/arkode_bandpre.h
+++ b/include/arkode/arkode_bandpre.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -17,8 +17,8 @@
  *---------------------------------------------------------------
  * This is the header file for the ARKBANDPRE module, which
  * provides a banded difference quotient Jacobian-based
- * preconditioner and solver routines for use with ARKSPGMR,
- * ARKSPBCG, ARKSPTFQMR, ARKSPFGMR or ARKPCG.
+ * preconditioner and solver routines for use with the ARKSPILS 
+ * interface.
  *
  * Summary:
  * These routines provide a band matrix preconditioner based on
@@ -28,37 +28,44 @@
  *   ml = lower half-bandwidth (number of sub-diagonals)
  * The routines generate a band matrix of bandwidth ml + mu + 1
  * and use this to form a preconditioner for use with the Krylov
- * linear solver in ARKSP*. Although this matrix is intended to
+ * linear solver in ARKSPILS. Although this matrix is intended to
  * approximate the Jacobian dfi/dy, it may be a very crude
  * approximation. The true Jacobian need not be banded, or its
  * true bandwith may be larger than ml + mu + 1, as long as the
  * banded approximation generated here is sufficiently accurate
  * to speed convergence as a preconditioner.
  *
+ * Note: this preconditioner does not work for IVPs involving
+ * a non-identity mass matrix.
+ *
  * Usage:
  *   The following is a summary of the usage of this module.
- *   Details of the calls to ARKodeCreate, ARKSp*,
+ *   Details of the calls to ARKodeCreate, ARKSpils*,
  *   and ARKode are available in the User Guide.
  *   To use these routines, the sequence of calls in the user
  *   main program should be as follows:
  *
  *   #include <arkode/arkode_bandpre.h>
- *   #include <nvector_serial.h>
+ *   #include <nvector_serial.h>   (or openmp or pthreads)
  *   ...
- *   Set y0
+ *   void *arkode_mem;
  *   ...
- *   arkode_mem = ARKodeCreate();
- *   ier = ARKodeInit(...);
+ *   Set y0
  *   ...
- *   flag = ARKSptfqmr(arkode_mem, pretype, maxl);
+ *   SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
  *     -or-
- *   flag = ARKSpgmr(arkode_mem, pretype, maxl);
+ *   SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
  *     -or-
- *   flag = ARKSpbcg(arkode_mem, pretype, maxl);
+ *   SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
  *     -or-
- *   flag = ARKSpfgmr(arkode_mem, pretype, maxl);
+ *   SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
  *     -or-
- *   flag = ARKPcg(arkode_mem, pretype, maxl);
+ *   SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+ *   ...
+ *   arkode_mem = ARKodeCreate();
+ *   ier = ARKodeInit(...);
+ *   ...
+ *   ier = ARKSpilsSetLinearSolver(arkode_mem, LS);
  *   ...
  *   flag = ARKBandPrecInit(arkode_mem, N, mu, ml);
  *   ...
@@ -67,13 +74,15 @@
  *   Free y0
  *   ...
  *   ARKodeFree(&arkode_mem);
- *
+ *   ...
+ *   SUNLinSolFree(LS);
+ *   ...
  * Notes:
  * (1) Include this file for the ARKBandPrecData type definition.
- * (2) In the ARKBandPrecAlloc call, the arguments N is the
+ * (2) In the ARKBandPrecAlloc call, the argument N is the
  *     problem dimension.
- * (3) In the ARKBPSp* call, the user is free to specify
- *     the input pretype and the optional input maxl.
+ * (3) In the linear solver creation call, the user is free to 
+ *     specify the input pretype and the optional input maxl.
  *--------------------------------------------------------------*/
 
 #ifndef _ARKBANDPRE_H
@@ -89,9 +98,9 @@ extern "C" {
 /*---------------------------------------------------------------
  ARKBandPrecInit:
 
- ARKBandPrecInit allocates and initializes the BANDPRE preconditioner
- module. This functino must be called AFTER one of the SPILS linear
- solver modules has been attached to the ARKODE integrator.
+ ARKBandPrecInit allocates and initializes the BANDPRE 
+ preconditioner module. This function must be called AFTER the
+ ARKSPILS linear solver interface has been created.
 
  The parameters of ARKBandPrecInit are as follows:
 
@@ -110,13 +119,13 @@ extern "C" {
    ARKSPILS_ILL_INPUT if an input has an illegal value
    ARKSPILS_MEM_FAIL if a memory allocation request failed
 
- NOTE: The band preconditioner assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKBandPrecInit will
-       first test for a compatible N_Vector internal
-       representation by checking for required functions.
+ NOTE: The band preconditioner assumes a serial/OpenMP/Pthreads
+       implementation of the NVECTOR package. Therefore, 
+       ARKBandPrecInit will first test for a compatible N_Vector 
+       internal representation by checking for required functions.
 ---------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKBandPrecInit(void *arkode_mem, long int N, 
-				    long int mu, long int ml);
+SUNDIALS_EXPORT int ARKBandPrecInit(void *arkode_mem, sunindextype N, 
+				    sunindextype mu, sunindextype ml);
 
 /*---------------------------------------------------------------
  Optional output functions : ARKBandPrecGet*
@@ -126,7 +135,7 @@ SUNDIALS_EXPORT int ARKBandPrecInit(void *arkode_mem, long int N,
 
  ARKBandPrecGetNumRhsEvals returns the number of calls made from
                           ARKBANDPRE to the user's right-hand side
-                          routine f.
+                          routine fi.
 
  The return value of ARKBandPrecGet* is one of:
    ARKSPILS_SUCCESS if no errors occurred
diff --git a/include/arkode/arkode_bbdpre.h b/include/arkode/arkode_bbdpre.h
index 363c80c..e9c91cf 100644
--- a/include/arkode/arkode_bbdpre.h
+++ b/include/arkode/arkode_bbdpre.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -17,9 +17,8 @@
  *---------------------------------------------------------------
  * This is the header file for the ARKBBDPRE module, for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with ARKSPGMR, ARKSPBCG, 
- * ARKSPTFQMR, ARKSPFGMR or ARKPCG, and the parallel implementation 
- * of the NVECTOR module.
+ * matrix with banded blocks, for use with the ARKSPILS 
+ * interface, and the MPI-parallel NVECTOR module.
  *
  * Summary:
  *
@@ -35,40 +34,49 @@
  * However, the banded Jacobian block kept by the scheme has
  * half-bandwiths mukeep and mlkeep, which may be smaller.
  *
+ * Note: this preconditioner does not work for IVPs involving
+ * a non-identity mass matrix.
+ *
  * The user's calling program should have the following form:
  *
  *   #include <nvector_parallel.h>
+ *   #include <arkode/arkode_spils.h>
  *   #include <arkode/arkode_bbdpre.h>
  *   ...
  *   void *arkode_mem;
  *   ...
  *   Set y0
  *   ...
+ *   SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+ *   ...
  *   arkode_mem = ARKodeCreate();
  *   ier = ARKodeInit(...);
  *   ...
- *   flag = ARKSpgmr(arkode_mem, pretype, maxl);
- *      -or-
- *   flag = ARKSpbcg(arkode_mem, pretype, maxl);
- *      -or-
- *   flag = ARKSptfqmr(arkode_mem, pretype, maxl);
- *      -or-
- *   flag = ARKSpfgmr(arkode_mem, pretype, maxl);
- *      -or-
- *   flag = ARKPcg(arkode_mem, pretype, maxl);
+ *   ier = ARKSpilsSetLinearSolver(arkode_mem, LS);
  *   ...
- *   flag = ARKBBDPrecInit(arkode_mem, Nlocal, mudq ,mldq,
+ *   flag = ARKBBDPrecInit(arkode_mem, Nlocal, mudq, mldq,
  *                         mukeep, mlkeep, dqrely, gloc, cfn);
  *   ...
  *   ier = ARKode(...);
  *   ...
+ *   Free y0
+ *   ...
  *   ARKodeFree(&arkode_mem);
+ *   ...
+ *   SUNLinSolFree(LS);
+ *   ...
  * 
- *   Free y0
- *
  * The user-supplied routines required are:
  *
- *   f    = function defining the ODE right-hand side f(t,y).
+ *   fi   = function defining the implicit ODE right-hand side fi(t,y).
  *
  *   gloc = function defining the approximation g(t,y).
  *
@@ -90,7 +98,7 @@
  *    For all four half-bandwidths, the values need not be the
  *    same on every processor.
  *
- * 3) The actual name of the user's f function is passed to
+ * 3) The actual name of the user's fi function is passed to
  *    ARKodeInit, and the names of the user's gloc and cfn
  *    functions are passed to ARKBBDPrecInit.
  *
@@ -104,8 +112,7 @@
  *    associated with this module also include nsetups banded LU
  *    factorizations, nlinsetups cfn calls, and npsolves banded
  *    backsolve calls, where nlinsetups and npsolves are
- *    integrator/ARKSPGMR/ARKSPBCG/ARKSPTFQMR/ARKSPFGMR/ARKPCG 
- *    optional outputs.
+ *    integrator/ARKSPILS optional outputs.
  *--------------------------------------------------------------*/
 
 #ifndef _ARKBBDPRE_H
@@ -121,10 +128,12 @@ extern "C" {
  Type: ARKLocalFn
 
  The user must supply a function g(t,y) which approximates the
- right-hand side function f for the system y'=f(t,y), and which
- is computed locally (without interprocess communication).
- (The case where g is mathematically identical to f is allowed.)
- The implementation of this function must have type ARKLocalFn.
+ implicit right-hand side function fi for the system 
+    My'=fe(t,y)+fi(t,y), 
+ and which is computed locally (without interprocess 
+ communication).  (The case where g is mathematically identical 
+ to fi is allowed.)  The implementation of this function must 
+ have type ARKLocalFn.
 
  This function takes as input the local vector size Nlocal, the
  independent variable value t, the local real dependent
@@ -133,15 +142,15 @@ extern "C" {
  store this in the vector g.
  (Allocation of memory for y and g is handled within the
  preconditioner module.)
- The user_data parameter is the same as that specified by the user
- through the ARKodeSetFdata routine.
+ The user_data parameter is the same as that specified by the 
+ user through the ARKodeSetUserData routine.
 
- A ARKLocalFn should return 0 if successful, a positive value if 
- a recoverable error occurred, and a negative value if an 
+ An ARKLocalFn should return 0 if successful, a positive value 
+ if a recoverable error occurred, and a negative value if an 
  unrecoverable error occurred.
 ---------------------------------------------------------------*/
-typedef int (*ARKLocalFn)(long int Nlocal, realtype t, N_Vector y,
-                          N_Vector g, void *user_data);
+typedef int (*ARKLocalFn)(sunindextype Nlocal, realtype t, 
+                          N_Vector y, N_Vector g, void *user_data);
 
 
 /*---------------------------------------------------------------
@@ -153,23 +162,24 @@ typedef int (*ARKLocalFn)(long int Nlocal, realtype t, N_Vector y,
 
  This function takes as input the local vector size Nlocal,
  the independent variable value t, the dependent variable
- vector y, and a pointer to the user-defined data block user_data.
- The user_data parameter is the same as that specified by the user
- through the ARKodeSetUserData routine. The ARKCommFn cfn is
- expected to save communicated data in space defined within the
- structure user_data. Note: A ARKCommFn cfn does not have a return value.
+ vector y, and a pointer to the user-defined data block 
+ user_data. The user_data parameter is the same as that 
+ specified by the user through the ARKodeSetUserData routine. 
+ The ARKCommFn cfn is expected to save communicated data in 
+ space defined within the structure user_data. 
+ Note: An ARKCommFn cfn does not have a return value.
 
  Each call to the ARKCommFn cfn is preceded by a call to the
- ARKRhsFn f with the same (t,y) arguments. Thus cfn can omit any
- communications done by f if relevant to the evaluation of g.
- If all necessary communication was done by f, the user can
- pass NULL for cfn in ARKBBDPrecInit (see below).
+ ARKRhsFn fi with the same (t,y) arguments. Thus cfn can omit 
+ any communications done by fi if relevant to the evaluation of 
+ g.  If all necessary communication was done by fi, the user 
+ can pass NULL for cfn in ARKBBDPrecInit (see below).
 
- A ARKCommFn should return 0 if successful, a positive value if 
- a recoverable error occurred, and a negative value if an 
+ An ARKCommFn should return 0 if successful, a positive value 
+ if a recoverable error occurred, and a negative value if an 
  unrecoverable error occurred.
 ---------------------------------------------------------------*/
-typedef int (*ARKCommFn)(long int Nlocal, realtype t, 
+typedef int (*ARKCommFn)(sunindextype Nlocal, realtype t, 
 			 N_Vector y, void *user_data);
 
 
@@ -213,23 +223,26 @@ typedef int (*ARKCommFn)(long int Nlocal, realtype t,
    ARKSPILS_ILL_INPUT if an input has an illegal value
    ARKSPILS_MEM_FAIL if a memory allocation request failed
 ---------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKBBDPrecInit(void *arkode_mem, long int Nlocal, 
-				   long int mudq, long int mldq, 
-				   long int mukeep, long int mlkeep, 
+SUNDIALS_EXPORT int ARKBBDPrecInit(void *arkode_mem, 
+                                   sunindextype Nlocal, 
+				   sunindextype mudq, 
+                                   sunindextype mldq, 
+				   sunindextype mukeep, 
+                                   sunindextype mlkeep, 
 				   realtype dqrely,
-				   ARKLocalFn gloc, ARKCommFn cfn);
+				   ARKLocalFn gloc,
+                                   ARKCommFn cfn);
 
 
 /*---------------------------------------------------------------
  ARKBBDPrecReInit:
 
  ARKBBDPrecReInit re-initializes the BBDPRE module when solving a
- sequence of problems of the same size with ARKSPGMR/ARKBBDPRE or
- ARKSPBCG/ARKBBDPRE or ARKSPTFQMR/ARKBBDPRE or ARKSPFGMR/ARKBBDPRE
- or ARKPCG/ARKBBDPRE provided there is no change in Nlocal, 
- mukeep, or mlkeep. After solving one problem, and after calling 
- ARKodeReInit to re-initialize the integrator for a subsequent 
- problem, call ARKBBDPrecReInit.
+ sequence of problems of the same size with ARKSPILS/ARKBBDPRE 
+ provided there is no change in Nlocal, mukeep, or mlkeep. After 
+ solving one problem, and after calling ARKodeReInit to 
+ re-initialize the integrator for a subsequent problem, call 
+ ARKBBDPrecReInit.
 
  All arguments have the same names and meanings as those
  of ARKBBDPrecInit.
@@ -240,8 +253,10 @@ SUNDIALS_EXPORT int ARKBBDPrecInit(void *arkode_mem, long int Nlocal,
    ARKSPILS_LMEM_NULL if the linear solver memory is NULL
    ARKSPILS_PMEM_NULL if the preconditioner memory is NULL
 ---------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKBBDPrecReInit(void *arkode_mem, long int mudq, 
-				     long int mldq, realtype dqrely);
+SUNDIALS_EXPORT int ARKBBDPrecReInit(void *arkode_mem, 
+                                     sunindextype mudq, 
+				     sunindextype mldq, 
+                                     realtype dqrely);
 
 
 /*---------------------------------------------------------------
diff --git a/include/arkode/arkode_dense.h b/include/arkode/arkode_dense.h
deleted file mode 100644
index 83da464..0000000
--- a/include/arkode/arkode_dense.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Header file for the ARKODE dense linear solver, ARKDENSE.
- *---------------------------------------------------------------*/
-
-#ifndef _ARKDENSE_H
-#define _ARKDENSE_H
-
-#include <arkode/arkode_direct.h>
-#include <sundials/sundials_dense.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-
-/*---------------------------------------------------------------
- Function: ARKDense
------------------------------------------------------------------
- A call to the ARKDense function links the main integrator with
- the ARKDENSE linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-            ARKodeCreate.
-
- N is the size of the ODE system.
-
- The return value of ARKDense is one of:
-    ARKDLS_SUCCESS   if successful
-    ARKDLS_MEM_NULL  if the arkode memory was NULL
-    ARKDLS_MEM_FAIL  if there was a memory allocation failure
-    ARKDLS_ILL_INPUT if a required vector operation is missing
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKDense(void *arkode_mem, long int N);
-
-/*---------------------------------------------------------------
- Function: ARKMassDense
------------------------------------------------------------------
- A call to the ARKMassDense function links the mass matrix solve
- with the ARKDENSE linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-            ARKodeCreate.
-
- N is the size of the ODE system.
-
- dmass is the user-supplied dense mass matrix setup function.
-
- The return value of ARKMassDense is one of:
-    ARKDLS_SUCCESS   if successful
-    ARKDLS_MEM_NULL  if the arkode memory was NULL
-    ARKDLS_MEM_FAIL  if there was a memory allocation failure
-    ARKDLS_ILL_INPUT if a required vector operation is missing
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassDense(void *arkode_mem, long int N, 
-				 ARKDlsDenseMassFn dmass);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_direct.h b/include/arkode/arkode_direct.h
index c919583..2a76549 100644
--- a/include/arkode/arkode_direct.h
+++ b/include/arkode/arkode_direct.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,13 +15,16 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Common header file for the direct linear solvers in ARKODE.
+ * Common header file for the direct linear solver interface in 
+ * ARKODE.
  *--------------------------------------------------------------*/
 
 #ifndef _ARKDLS_H
 #define _ARKDLS_H
 
 #include <sundials/sundials_direct.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_linearsolver.h>
 #include <sundials/sundials_nvector.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
@@ -30,7 +33,7 @@ extern "C" {
 
 
 /*===============================================================
-  ARKDIRECT CONSTANTS
+  ARKDLS Constants
 ===============================================================*/
 
 /* ARKDLS return values */
@@ -47,22 +50,23 @@ extern "C" {
 #define ARKDLS_MASSFUNC_UNRECVR -8
 #define ARKDLS_MASSFUNC_RECVR   -9
 
+#define ARKDLS_SUNMAT_FAIL      -10
 
+
+  
 /*===============================================================
-  FUNCTION TYPES
+ ARKDLS user-supplied function prototypes
 ===============================================================*/
 
 /*---------------------------------------------------------------
- Type: ARKDlsDenseJacFn
-
- A dense Jacobian approximation function Jac must be of type 
- ARKDlsDenseJacFn. Its parameters are:
+ Type: ARKDlsJacFn
 
- N   is the problem size.
+ A Jacobian approximation function Jac must be of type 
+ ARKDlsJacFn. Its parameters are:
 
- Jac is the dense matrix (of type DlsMat) that will be loaded
-     by a ARKDlsDenseJacFn with an approximation to the Jacobian 
-     matrix J = (df_i/dy_j) at the point (t,y). 
+ Jac is the SUNMatrix that will be loaded by a ARKDlsJacFn with
+     an approximation to the Jacobian matrix 
+     J = (df_i/dy_j) at the point (t,y). 
 
  t   is the current value of the independent variable.
 
@@ -72,36 +76,19 @@ extern "C" {
  fy  is the vector f(t,y).
 
  user_data is a pointer to user data - the same as the user_data
-     parameter passed to ARKodeSetFdata.
+     parameter passed to ARKodeSetUserData.
 
  tmp1, tmp2, and tmp3 are pointers to memory allocated for
- vectors of length N which can be used by a ARKDlsDenseJacFn
- as temporary storage or work space.
+     vectors of length N which can be used by a ARKDlsJacFn
+     as temporary storage or work space.
 
- A ARKDlsDenseJacFn should return 0 if successful, a positive 
+ A ARKDlsJacFn should return 0 if successful, a positive 
  value if a recoverable error occurred, and a negative value if 
  an unrecoverable error occurred.
 
- NOTE: The following are two efficient ways to load a dense Jac:         
- (1) (with macros - no explicit data structure references)      
-     for (j=0; j < Neq; j++) {                                  
-       col_j = DENSE_COL(Jac,j);                                 
-       for (i=0; i < Neq; i++) {                                
-         generate J_ij = the (i,j)th Jacobian element           
-         col_j[i] = J_ij;                                       
-       }                                                        
-     }                                                          
- (2) (without macros - explicit data structure references)      
-     for (j=0; j < Neq; j++) {                                  
-       col_j = (Jac->data)[j];                                   
-       for (i=0; i < Neq; i++) {                                
-         generate J_ij = the (i,j)th Jacobian element           
-         col_j[i] = J_ij;                                       
-       }                                                        
-     }                                                          
- A third way, using the DENSE_ELEM(A,i,j) macro, is much less   
- efficient in general.  It is only appropriate for use in small 
- problems in which efficiency of access is NOT a major concern. 
+ NOTE: See the relevant SUNMatrix implementation header files
+     and documentation for mechanisms to inquire about matrix 
+     dimensions, and for efficient ways to set matrix entries.
                                                                 
  NOTE: If the user's Jacobian routine needs other quantities,   
      they are accessible as follows: hcur (the current stepsize)
@@ -111,230 +98,125 @@ extern "C" {
      UNIT_ROUNDOFF defined in sundials_types.h.
 
 ---------------------------------------------------------------*/
-typedef int (*ARKDlsDenseJacFn)(long int N, realtype t,
-				N_Vector y, N_Vector fy, 
-				DlsMat Jac, void *user_data,
-				N_Vector tmp1, N_Vector tmp2, 
-				N_Vector tmp3);
+typedef int (*ARKDlsJacFn)(realtype t, N_Vector y, N_Vector fy, 
+                           SUNMatrix Jac, void *user_data,
+                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
   
 
 /*---------------------------------------------------------------
- Type: ARKDlsDenseMassFn
-
- A dense mass matrix approximation function Mass must be of type 
- ARKDlsDenseMassFn. Its parameters are:
+ Type: ARKDlsMassFn
 
- N   is the problem size.
+ A mass matrix approximation function Mass must be of type 
+ ARKDlsMassFn. Its parameters are:
 
  t   is the current value of the independent variable.
 
- M   is the dense matrix (of type DlsMat) that will be loaded
-     by a ARKDlsDenseMassFn with an approximation to the mass matrix.
+ M   is the SUNMatrix that will be loaded by a ARKDlsMassFn 
+     with an approximation to the mass matrix.
 
  user_data is a pointer to user data - the same as the user_data
-     parameter passed to ARKodeSetFdata.
+     parameter passed to ARKodeSetUserData.
 
  tmp1, tmp2, and tmp3 are pointers to memory allocated for
- vectors of length N which can be used by a ARKDlsDenseMassFn
+ vectors of length N which can be used by a ARKDlsMassFn
  as temporary storage or work space.
 
- A ARKDlsDenseMassFn should return 0 if successful, and a 
+ A ARKDlsMassFn should return 0 if successful, and a 
  negative value if an unrecoverable error occurred.
 
 ---------------------------------------------------------------*/
-typedef int (*ARKDlsDenseMassFn)(long int N, realtype t, DlsMat M, 
-				 void *user_data, N_Vector tmp1, 
-				 N_Vector tmp2, N_Vector tmp3);
+typedef int (*ARKDlsMassFn)(realtype t, SUNMatrix M, void *user_data, 
+                            N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
   
 
-/*---------------------------------------------------------------
- Type: ARKDlsBandJacFn
-
- A band Jacobian approximation function Jac must have the
- prototype given below. Its parameters are:
-
- N is the length of all vector arguments.
-
- mupper is the upper half-bandwidth of the approximate banded
- Jacobian. This parameter is the same as the mupper parameter
- passed by the user to the linear solver initialization function.
-
- mlower is the lower half-bandwidth of the approximate banded
- Jacobian. This parameter is the same as the mlower parameter
- passed by the user to the linear solver initialization function.
-
- t is the current value of the independent variable.
-
- y is the current value of the dependent variable vector,
-      namely the predicted value of y(t).
-
- fy is the vector f(t,y).
-
- Jac is the band matrix (of type DlsMat) that will be loaded
- by a ARKDlsBandJacFn with an approximation to the Jacobian matrix
- Jac = (df_i/dy_j) at the point (t,y).
- Three efficient ways to load J are:
-
- (1) (with macros - no explicit data structure references)
-    for (j=0; j < n; j++) {
-       col_j = BAND_COL(Jac,j);
-       for (i=j-mupper; i <= j+mlower; i++) {
-         generate J_ij = the (i,j)th Jacobian element
-         BAND_COL_ELEM(col_j,i,j) = J_ij;
-       }
-     }
-
- (2) (with BAND_COL macro, but without BAND_COL_ELEM macro)
-    for (j=0; j < n; j++) {
-       col_j = BAND_COL(Jac,j);
-       for (k=-mupper; k <= mlower; k++) {
-         generate J_ij = the (i,j)th Jacobian element, i=j+k
-         col_j[k] = J_ij;
-       }
-     }
-
- (3) (without macros - explicit data structure references)
-     offset = Jac->smu;
-     for (j=0; j < n; j++) {
-       col_j = ((Jac->data)[j])+offset;
-       for (k=-mupper; k <= mlower; k++) {
-         generate J_ij = the (i,j)th Jacobian element, i=j+k
-         col_j[k] = J_ij;
-       }
-     }
- Caution: Jac->smu is generally NOT the same as mupper.
-
- The BAND_ELEM(A,i,j) macro is appropriate for use in small
- problems in which efficiency of access is NOT a major concern.
-
- user_data is a pointer to user data - the same as the user_data
-          parameter passed to ARKodeSetFdata.
-
- NOTE: If the user's Jacobian routine needs other quantities,
-     they are accessible as follows: hcur (the current stepsize)
-     and ewt (the error weight vector) are accessible through
-     ARKodeGetCurrentStep and ARKodeGetErrWeights, respectively
-     (see arkode.h). The unit roundoff is available as
-     UNIT_ROUNDOFF defined in sundials_types.h
-
- tmp1, tmp2, and tmp3 are pointers to memory allocated for
- vectors of length N which can be used by a ARKDlsBandJacFn
- as temporary storage or work space.
-
- A ARKDlsBandJacFn should return 0 if successful, a positive value
- if a recoverable error occurred, and a negative value if an 
- unrecoverable error occurred.
----------------------------------------------------------------*/
-typedef int (*ARKDlsBandJacFn)(long int N, long int mupper, 
-			       long int mlower, realtype t, 
-			       N_Vector y, N_Vector fy, 
-			       DlsMat Jac, void *user_data,
-			       N_Vector tmp1, N_Vector tmp2, 
-			       N_Vector tmp3);
-
-/*---------------------------------------------------------------
- Type: ARKDlsBandMassFn
-
- A band mass matrix approximation function Mass must have the
- prototype given below. Its parameters are:
-
- N is the length of all vector arguments.
-
- mupper is the upper half-bandwidth of the approximate banded
- Jacobian. This parameter is the same as the mupper parameter
- passed by the user to the linear solver initialization function.
-
- mlower is the lower half-bandwidth of the approximate banded
- Jacobian. This parameter is the same as the mlower parameter
- passed by the user to the linear solver initialization function.
-
- t is the current value of the independent variable.
-
- M is the band matrix (of type DlsMat) that will be loaded
- by a ARKDlsBandMassFn with an approximation to the mass matrix
-
- user_data is a pointer to user data - the same as the user_data
-     parameter passed to ARKodeSetFdata.
-
- tmp1, tmp2, and tmp3 are pointers to memory allocated for
- vectors of length N which can be used by a ARKDlsBandMassFn
- as temporary storage or work space.
-
- A ARKDlsBandMassFn should return 0 if successful, and a negative 
- value if an unrecoverable error occurred.
----------------------------------------------------------------*/
-typedef int (*ARKDlsBandMassFn)(long int N, long int mupper, 
-				long int mlower, realtype t, 
-				DlsMat M, void *user_data, 
-				N_Vector tmp1, N_Vector tmp2, 
-				N_Vector tmp3);
-
-
 /*===============================================================
-  EXPORTED FUNCTIONS
+  ARKDLS Exported functions
 ===============================================================*/
 
 /*---------------------------------------------------------------
- Optional inputs to the ARKDLS linear solver:
-
- ARKDlsSetDenseJacFn specifies the dense Jacobian approximation
- routine to be used for a direct dense linear solver.
-
- ARKDlsSetBandJacFn specifies the band Jacobian approximation
- routine to be used for a direct band linear solver.
-
- By default, a difference quotient approximation, supplied with
- the solver is used.
+ Required inputs for the ARKDLS linear solver interface:
+
+ ARKDlsSetLinearSolver specifies the direct SUNLinearSolver 
+ object that ARKode should use.  This is required if ARKode is 
+ solving an implicit or IMEX IVP, and using a modified Newton 
+ solver.
+
+ ARKDlsSetMassLinearSolver specifies the direct SUNLinearSolver 
+ object (and user-provided function to fill the mass matrix) that
+ ARKode should use when solving mass-matrix linear systems.  This 
+ is required if ARKode is solving a problem with non-identity 
+ mass matrix and the user wishes to use a direct solver for these 
+ systems.
+
+ NOTE: when solving an implicit or IMEX IVP with non-identity mass
+ matrix and direct linear solver, both the system and mass matrices 
+ must have the same type (i.e. you cannot combine a direct system 
+ solver with an iterative mass matrix solver, or a dense and banded 
+ matrices, etc.).
 
  The return value is one of:
     ARKDLS_SUCCESS   if successful
     ARKDLS_MEM_NULL  if the ARKODE memory was NULL
-    ARKDLS_LMEM_NULL if the linear solver memory was NULL
+    ARKDLS_ILL_INPUT if the arguments are incompatible
 ---------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKDlsSetDenseJacFn(void *arkode_mem, 
-					ARKDlsDenseJacFn jac);
-SUNDIALS_EXPORT int ARKDlsSetBandJacFn(void *arkode_mem, 
-				       ARKDlsBandJacFn jac);
+SUNDIALS_EXPORT int ARKDlsSetLinearSolver(void *arkode_mem, 
+                                          SUNLinearSolver LS,
+                                          SUNMatrix A);
 
+SUNDIALS_EXPORT int ARKDlsSetMassLinearSolver(void *arkode_mem, 
+                                              SUNLinearSolver LS,
+                                              SUNMatrix M,
+                                              booleantype time_dep);
 
 /*---------------------------------------------------------------
- Optional inputs to the ARKDLS linear solver:
+ Optional inputs to the ARKDLS linear solver interface:
 
- ARKDlsSetDenseMassFn specifies the dense mass matrix 
- approximation routine to be used for a direct dense solver.
+ ARKDlsSetJacFn specifies the dense/band/sparse Jacobian
+ approximation routine to be used for a direct linear solver.
 
- ARKDlsSetBandMassFn specifies the band mass matrix approximation
- routine to be used for a direct band solver.
+ By default, a difference quotient approximation is used for 
+ dense/band; no default exists for sparse (so this must be 
+ user-supplied).
+
+ ARKDlsSetMassFn specifies the mass matrix approximation routine 
+ to be used for a direct linear solver.  As this must have already
+ been supplied to attach the direct mass linear solver to ARKode, 
+ this routine is provided to allow changing this function after it 
+ is initially set.
 
  The return value is one of:
-    ARKDLS_SUCCESS      if successful
-    ARKDLS_MEM_NULL     if the ARKODE memory was NULL
+    ARKDLS_SUCCESS   if successful
+    ARKDLS_MEM_NULL  if the ARKODE memory was NULL
+    ARKDLS_LMEM_NULL if the linear solver memory was NULL
     ARKDLS_MASSMEM_NULL if the mass matrix solver memory was NULL
 ---------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKDlsSetDenseMassFn(void *arkode_mem, 
-					 ARKDlsDenseMassFn mass);
-SUNDIALS_EXPORT int ARKDlsSetBandMassFn(void *arkode_mem, 
-					ARKDlsBandMassFn mass);
+SUNDIALS_EXPORT int ARKDlsSetJacFn(void *arkode_mem, ARKDlsJacFn jac);
+SUNDIALS_EXPORT int ARKDlsSetMassFn(void *arkode_mem, ARKDlsMassFn mass);
 
 
 /*---------------------------------------------------------------
  Optional outputs from the ARKDLS linear solver:
 
  ARKDlsGetWorkSpace   returns the real and integer workspace used
-                     by the direct linear solver.
- ARKDlsGetMassWorkSpace   returns the real and integer workspace used
-                     by the mass matrix direct linear solver.
+                      by the direct linear solver.
  ARKDlsGetNumJacEvals returns the number of calls made to the
-                     Jacobian evaluation routine jac.
- ARKDlsGetNumMassEvals returns the number of calls made to the
-                     mass matrix evaluation routine Mass.
+                      Jacobian evaluation routine jac.
  ARKDlsGetNumRhsEvals returns the number of calls to the user
-                     f routine due to finite difference Jacobian
-                     evaluation.
+                      f routine due to finite difference Jacobian
+                      evaluation.
  ARKDlsGetLastFlag    returns the last error flag set by any of
-                     the ARKDLS interface functions.
+                      the ARKDLS interface functions.
+
+ ARKDlsGetMassWorkSpace returns the real/integer workspace used
+                        by the mass matrix direct linear solver.
+ ARKDlsGetNumMassSetups returns the number of calls made to the
+                        mass matrix solver setup routine
+ ARKDlsGetNumMassSolves returns the number of calls made to the
+                        mass matrix solver 'solve' routine
+ ARKDlsGetNumMassMult   returns the number of calls made to the
+                        mass matrix-times-vector routine
  ARKDlsGetLastMassFlag  returns the last error flag set by any of
-                     the ARKDLS interface mass matrix functions.
+                        the ARKDLS mass functions
 
  The return value of ARKDlsGet* is one of:
     ARKDLS_SUCCESS   if successful
@@ -344,17 +226,22 @@ SUNDIALS_EXPORT int ARKDlsSetBandMassFn(void *arkode_mem,
 SUNDIALS_EXPORT int ARKDlsGetWorkSpace(void *arkode_mem, 
 				       long int *lenrwLS, 
 				       long int *leniwLS);
-SUNDIALS_EXPORT int ARKDlsGetMassWorkSpace(void *arkode_mem, 
-					   long int *lenrwMLS, 
-					   long int *leniwMLS);
 SUNDIALS_EXPORT int ARKDlsGetNumJacEvals(void *arkode_mem, 
 					 long int *njevals);
-SUNDIALS_EXPORT int ARKDlsGetNumMassEvals(void *arkode_mem, 
-					  long int *nmevals);
 SUNDIALS_EXPORT int ARKDlsGetNumRhsEvals(void *arkode_mem, 
 					 long int *nfevalsLS);
 SUNDIALS_EXPORT int ARKDlsGetLastFlag(void *arkode_mem, 
 				      long int *flag);
+
+SUNDIALS_EXPORT int ARKDlsGetMassWorkSpace(void *arkode_mem, 
+					   long int *lenrwMLS, 
+					   long int *leniwMLS);
+SUNDIALS_EXPORT int ARKDlsGetNumMassSetups(void *arkode_mem, 
+                                           long int *nmsetups);
+SUNDIALS_EXPORT int ARKDlsGetNumMassSolves(void *arkode_mem, 
+                                           long int *nmsolves);
+SUNDIALS_EXPORT int ARKDlsGetNumMassMult(void *arkode_mem, 
+                                         long int *nmmults);
 SUNDIALS_EXPORT int ARKDlsGetLastMassFlag(void *arkode_mem, 
 					  long int *flag);
 
diff --git a/include/arkode/arkode_klu.h b/include/arkode/arkode_klu.h
deleted file mode 100644
index 54269ac..0000000
--- a/include/arkode/arkode_klu.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Header file for the ARKKLU linear solver module.
- *---------------------------------------------------------------*/
-
-#ifndef _ARKKLU_H
-#define _ARKKLU_H
-
-#include "arkode/arkode_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-
-/*---------------------------------------------------------------
- Function: ARKKLU
------------------------------------------------------------------
- A call to the ARKKLU function links the main integrator with 
- the ARKKLU linear solver module.
-                                                                
- arkode_mem is the pointer to integrator memory returned by        
-            ARKodeCreate.             
-
- n is the size of the linear system (nrows = ncols = n)
-
- nnz is the maximum number of nonzeros in the sparse matrix
-     A = M + gamma*J
-                                                                
- The return value of ARKKLU is one of:
-     ARKSLS_SUCCESS   if successful
-     ARKSLS_MEM_NULL  if the ARKode memory was NULL
-     ARKSLS_MEM_FAIL  if there was a memory allocation failure   
-     ARKSLS_ILL_INPUT if a required vector operation is missing
-                                                                
- NOTE: The KLU linear solver assumes a serial implementation  
-       of the NVECTOR package. Therefore, ARKKLU will first
-       test for a compatible N_Vector internal representation
-       by checking that the function N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKKLU(void *arkode_mem, int n, int nnz, int sparsetype); 
-
-
-/*---------------------------------------------------------------
- Function: ARKMassKLU
------------------------------------------------------------------
- A call to the ARKMassKLU function links the mass matrix solve
- with the ARKKLU linear solver module.
-                                                                
- arkode_mem is the pointer to integrator memory returned by        
-            ARKodeCreate.             
-
- n is the size of the linear system (nrows = ncols = n)
-
- nnz is the maximum number of nonzeros in the sparse mass matrix
-                                                                
- smass is the user-supplied sparse mass matrix setup function.
-
- The return value of ARKMassKLU is one of:
-     ARKSLS_SUCCESS   if successful
-     ARKSLS_MEM_NULL  if the ARKode memory was NULL
-     ARKSLS_MEM_FAIL  if there was a memory allocation failure   
-     ARKSLS_ILL_INPUT if a required vector operation is missing
-                                                                
- NOTE: The KLU linear solver assumes a serial implementation  
-       of the NVECTOR package. Therefore, ARKKLU will first
-       test for a compatible N_Vector internal representation
-       by checking that the function N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassKLU(void *arkode_mem, int n, int nnz, int sparsetype,
-			       ARKSlsSparseMassFn smass); 
-
-
-/*
- * -----------------------------------------------------------------
- * ARKKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to CVKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is ARKSLS_SUCCESS = 0, ARKSLS_MEM_NULL = -1, 
- * ARKSLS_LMEM_NULL = -2, ARKSLS_ILL_INPUT = -3, or ARKSLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int ARKKLUReInit(void *arkode_mem, int n, int nnz, 
-				   int reinit_type);
-
-
-/*
- * -----------------------------------------------------------------
- * ARKMassKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to CVKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is ARKSLS_SUCCESS = 0, ARKSLS_MEM_NULL = -1, 
- * ARKSLS_MASSMEM_NULL = -8, ARKSLS_ILL_INPUT = -3, or ARKSLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int ARKMassKLUReInit(void *arkode_mem, int n, 
-				       int nnz, int reinit_type);
-
-/*================================================================
- Optional Input Specification Functions
-=================================================================*/
-
-/*---------------------------------------------------------------
- Function: ARKKLUSetOrdering 
------------------------------------------------------------------
- This routine sets the ordering used by KLU for reducing fill in 
- the system matrix solve.  Options for ordering_choice are: 
-        0 for AMD, 
-	1 for COLAMD, and 
-	2 for the natural ordering.
- The default used in ARKODE is 1 for COLAMD.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKKLUSetOrdering(void *arkode_mem, 
-				      int ordering_choice); 
-
-
-/*---------------------------------------------------------------
- Function: ARKMassKLUSetOrdering 
------------------------------------------------------------------
- This routine sets the ordering used by KLU for reducing fill in 
- the mass matrix solve.  Options for ordering_choice are: 
-        0 for AMD, 
-	1 for COLAMD, and 
-	2 for the natural ordering.
- The default used in ARKODE is 1 for COLAMD.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassKLUSetOrdering(void *arkode_mem, 
-					  int ordering_choice); 
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_lapack.h b/include/arkode/arkode_lapack.h
deleted file mode 100644
index 6f18050..0000000
--- a/include/arkode/arkode_lapack.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Header file for the ARKODE dense linear solver ARKLAPACK.
- *--------------------------------------------------------------*/
-
-#ifndef _ARKLAPACK_H
-#define _ARKLAPACK_H
-
-#include <arkode/arkode_direct.h>
-#include <sundials/sundials_lapack.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-
-/*===============================================================
-  EXPORTED FUNCTIONS
-===============================================================*/
-
-/*---------------------------------------------------------------
- ARKLapackDense:
-
- A call to the ARKLapackDense function links the main integrator
- with the ARKLAPACK linear solver using dense Jacobians.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- N is the size of the ODE system.
-
- The return value of ARKLapackDense is one of:
-    ARKLAPACK_SUCCESS   if successful
-    ARKLAPACK_MEM_NULL  if the ARKODE memory was NULL
-    ARKLAPACK_MEM_FAIL  if there was a memory allocation failure
-    ARKLAPACK_ILL_INPUT if a required vector operation is missing
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKLapackDense(void *arkode_mem, int N);
-
-
-/*---------------------------------------------------------------
- ARKMassLapackDense:
-
- A call to the ARKMassLapackDense function links the mass matrix 
- solve with the ARKLAPACK linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- N is the size of the ODE system.
-
- dmass is the user-supplied dense mass matrix setup routine.
-
- The return value of ARKMassLapackDense is one of:
-    ARKLAPACK_SUCCESS   if successful
-    ARKLAPACK_MEM_NULL  if the ARKODE memory was NULL
-    ARKLAPACK_MEM_FAIL  if there was a memory allocation failure
-    ARKLAPACK_ILL_INPUT if a required vector operation is missing
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassLapackDense(void *arkode_mem, int N, 
-				       ARKDlsDenseMassFn dmass);
-
-
-/*---------------------------------------------------------------
- ARKLapackBand:
-
- A call to the ARKLapackBand function links the main integrator
- with the ARKLAPACK linear solver using banded Jacobians. 
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- N is the size of the ODE system.
-
- mupper is the upper bandwidth of the band Jacobian approximation.
-
- mlower is the lower bandwidth of the band Jacobian approximation.
-
- The return value of ARKLapackBand is one of:
-    ARKLAPACK_SUCCESS   if successful
-    ARKLAPACK_MEM_NULL  if the ARKODE memory was NULL
-    ARKLAPACK_MEM_FAIL  if there was a memory allocation failure
-    ARKLAPACK_ILL_INPUT if a required vector operation is missing 
-                        or if a bandwidth has an illegal value.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKLapackBand(void *arkode_mem, int N, int mupper, int mlower);
-
-/*---------------------------------------------------------------
- ARKMassLapackBand:
-
- A call to the ARKMassLapackBand function links the mass matrix 
- solve with the ARKLAPACK linear solver. 
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- N is the size of the ODE system.
-
- mupper is the upper bandwidth of the band Jacobian approximation.
-
- mlower is the lower bandwidth of the band Jacobian approximation.
-
- bmass is the user-supplied band mass matrix setup routine.
-
- The return value of ARKLapackBand is one of:
-    ARKLAPACK_SUCCESS   if successful
-    ARKLAPACK_MEM_NULL  if the ARKODE memory was NULL
-    ARKLAPACK_MEM_FAIL  if there was a memory allocation failure
-    ARKLAPACK_ILL_INPUT if a required vector operation is missing 
-                        or if a bandwidth has an illegal value.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassLapackBand(void *arkode_mem, int N, int mupper, 
-				      int mlower, ARKDlsBandMassFn bmass);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_pcg.h b/include/arkode/arkode_pcg.h
deleted file mode 100644
index 545f4ca..0000000
--- a/include/arkode/arkode_pcg.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the header file for the ARKODE scaled preconditioned 
- * CG linear solver, ARKPCG.
- *--------------------------------------------------------------*/
-
-#ifndef _ARKPCG_H
-#define _ARKPCG_H
-
-#include <arkode/arkode.h>
-#include <arkode/arkode_spils.h>
-#include <sundials/sundials_pcg.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*---------------------------------------------------------------
- ARKPcg:
-
- A call to the ARKPcg function links the main ARKODE integrator
- with the ARKPCG linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
-           in iterative.h. These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.  However, since PCG requires a symmetric 
-	   linear operator, this flag is checked for any one of 
-	   PREC_LEFT, PREC_RIGHT and PREC_BOTH -- if any are 
-	   found then preconditioning is used.  It is assumed 
-	   that the preconditioner implements a symmetric linear 
-	   operator.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKPCG solver. Pass 0 to
-           use the default value ARKPCG_MAXL=5.
-
- The return value of ARKPcg is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKPcg(void *arkode_mem, int pretype, int maxl);
-
-
-/*---------------------------------------------------------------
- ARKMassPcg:
-
- A call to the ARKMassPcg function links the mass matrix solve
- with the ARKPCG linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
-           in iterative.h. These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.  However, since PCG requires a symmetric 
-	   linear operator, this flag is checked for any one of 
-	   PREC_LEFT, PREC_RIGHT and PREC_BOTH -- if any are 
-	   found then preconditioning is used.  It is assumed 
-	   that the preconditioner implements a symmetric linear 
-	   operator.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKPCG solver. Pass 0 to
-           use the default value ARKPCG_MAXL=5.
-
- mtimes    is the user-supplied mass-matrix-vector product 
-           routine.
-
- The return value of ARKMassPcg is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassPcg(void *arkode_mem, int pretype, int maxl, 
-			       ARKSpilsMassTimesVecFn mtimes,
-			       void *mtimes_data);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_sparse.h b/include/arkode/arkode_sparse.h
deleted file mode 100644
index f0b279e..0000000
--- a/include/arkode/arkode_sparse.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Header file for the generic ARKSLS linear solver module.
- *---------------------------------------------------------------*/
-
-#ifndef _ARKSPARSE_H
-#define _ARKSPARSE_H
-
-#include <sundials/sundials_sparse.h>
-#include <sundials/sundials_nvector.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-
-/*===============================================================
-  ARKSPARSE CONSTANTS
-===============================================================*/
-
-/* ARKSLS return values */
-#define ARKSLS_SUCCESS           0
-#define ARKSLS_MEM_NULL         -1
-#define ARKSLS_LMEM_NULL        -2
-#define ARKSLS_ILL_INPUT        -3
-#define ARKSLS_MEM_FAIL         -4
-#define ARKSLS_JAC_NOSET        -5
-#define ARKSLS_MASS_NOSET       -6
-#define ARKSLS_PACKAGE_FAIL     -7
-#define ARKSLS_MASSMEM_NULL     -8
-
-/* Additional last_flag values */
-#define ARKSLS_JACFUNC_UNRECVR  -9
-#define ARKSLS_JACFUNC_RECVR    -10
-#define ARKSLS_MASSFUNC_UNRECVR -11
-#define ARKSLS_MASSFUNC_RECVR   -12
-
-
-/*===============================================================
-  FUNCTION TYPES
-===============================================================*/
-
-/*-----------------------------------------------------------------
- Types : ARKSlsSparseJacFn
-
- A sparse Jacobian approximation function Jac must be of type
- ARKSlsSparseJacFn.  Its parameters are:
-
- t   is the current value of the independent variable t.
-                                                                
- y   is the current value of the dependent variable vector,
-     namely the predicted value of y(t)
-                                                                
- fy  is the vector f(t,y).
-     namely the predicted value of y'(t)
-                                                                
- JacMat is the compressed sparse column matrix (of type SlsMat)
-     to be loaded by an ARKSlsSparseJacFn routine with an 
-     approximation to the system Jacobian matrix
-            J = (df_i/dy_j) at the point (t,y). 
-     Note that JacMat is NOT preset to zero!
-     Matrix data is for the nonzero entries of the Jacobian stored 
-     in compressed column format.  Row indices of entries in 
-     column j are stored in JacMat->rowvals[colptrs[j]] 
-     through JacMat->rowvals[colptrs[j+i]-1]
-     and corresponding numerical values of the Jacobian are stored 
-     in the same entries of JacMat->data.
-
- J_data is a pointer to user Jacobian data - the same as the
-     user_data parameter passed to ARKodeSetFdata.
-                                                                
- tmp1, tmp2, tmp3 are pointers to memory allocated for
-     N_Vectors which can be used by an ARKSparseJacFn routine
-     as temporary storage or work space.
-                                                                
- A ARKSlsSparseJacFn should return 0 if successful, a positive 
- value if a recoverable error occurred, and a negative value if 
- a nonrecoverable error occurred. 
-
- NOTE: If the user's Jacobian routine needs other quantities,
-     they are accessible as follows: hcur (the current stepsize)
-     and ewt (the error weight vector) are accessible through
-     ARKodeGetCurrentStep and ARKodeGetErrWeights, respectively
-     (see arkode.h). The unit roundoff is available as
-     UNIT_ROUNDOFF defined in sundials_types.h.
-
----------------------------------------------------------------*/
-typedef int (*ARKSlsSparseJacFn)(realtype t,
-				 N_Vector y, N_Vector fy, 
-				 SlsMat JacMat, void *user_data,
-				 N_Vector tmp1, N_Vector tmp2, 
-				 N_Vector tmp3);
-
-/*-----------------------------------------------------------------
- Types : ARKSlsSparseMassFn
-
- A sparse mass matrix approximation function Mass must be of type
- ARKSlsSparseMassFn.  Its parameters are:
-
- t   is the current value of the independent variable t.
-                                                                
- MassMat is the compressed sparse column matrix (of type SlsMat)
-     to be loaded by an ARKSlsSparseJacFn routine with an 
-     approximation to the system mass matrix.  Note that MassMat 
-     is NOT preset to zero! Matrix data is for the nonzero entries 
-     of the mass matrix stored in compressed column format.  Row 
-     indices of entries in column j are stored in 
-     MassMat->rowvals[colptrs[j]] through 
-     MassMat->rowvals[colptrs[j+i]-1]
-     and corresponding numerical values of the mass matrix are 
-     stored in the same entries of MassMat->data.
-
- M_data is a pointer to user mass matrix data - the same as the
-     user_data parameter passed to ARKodeSetFdata.
-                                                                
- tmp1, tmp2, tmp3 are pointers to memory allocated for
-     N_Vectors which can be used by an ARKSparseJacFn routine
-     as temporary storage or work space.
-                                                                
- A ARKSlsSparseMassFn should return 0 if successful, a positive 
- value if a recoverable error occurred, and a negative int if a
- nonrecoverable error occurred. 
-
----------------------------------------------------------------*/
-typedef int (*ARKSlsSparseMassFn)(realtype t, SlsMat MassMat, 
-				  void *user_data, N_Vector tmp1, 
-				  N_Vector tmp2, N_Vector tmp3);
-
-
-/*===============================================================
-  EXPORTED FUNCTIONS
-===============================================================*/
-
-/*---------------------------------------------------------------
- Optional inputs to the ARKSLS linear solver:
-
- ARKSlsSetSparseJacFn specifies the Jacobian approximation
- routine to be used for a sparse direct linear solver.
-
- The return value is one of:
-    ARKSLS_SUCCESS   if successful
-    ARKSLS_MEM_NULL  if the ARKODE memory was NULL
-    ARKSLS_LMEM_NULL if the linear solver memory was NULL
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSlsSetSparseJacFn(void *arkode_mem, 
-					 ARKSlsSparseJacFn jac);
-
-/*---------------------------------------------------------------
- Optional inputs to the ARKSLS linear solver:
-
- ARKSlsSetSparseMassFn specifies the sparse mass matrix 
- approximation routine to be used for a sparse direct linear 
- solver.
-
- The return value is one of:
-    ARKSLS_SUCCESS   if successful
-    ARKSLS_MEM_NULL  if the ARKODE memory was NULL
-    ARKSLS_MASSMEM_NULL if the mass matrix solver memory was NULL
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSlsSetSparseMassFn(void *arkode_mem, 
-					  ARKSlsSparseMassFn mass);
-
-/*---------------------------------------------------------------
- Optional outputs from the ARKSLS linear solver:
-
- ARKSlsGetNumJacEvals returns the number of calls made to the
-                      Jacobian evaluation routine jac.
- ARKSlsGetNumMassEvals returns the number of calls made to the
-                      mass matrix evaluation routine Mass.
- ARKSlsGetLastFlag    returns the last error flag set by any of
-                      the ARKSLS interface functions.
- ARKSlsGetLastMassFlag returns the last error flag set by any of 
-                      the ARKSLS interface mass matrix functions.
-
- The return value of ARKSlsGet* is one of:
-    ARKSLS_SUCCESS   if successful
-    ARKSLS_MEM_NULL  if the IDA memory was NULL
-    ARKSLS_LMEM_NULL if the linear solver memory was NULL
-    ARKSLS_MASSMEM_NULL if the linear solver memory was NULL
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSlsGetNumJacEvals(void *arkode_mem, 
-					 long int *njevals);
-SUNDIALS_EXPORT int ARKSlsGetNumMassEvals(void *arkode_mem, 
-					  long int *nmevals);
-SUNDIALS_EXPORT int ARKSlsGetLastFlag(void *arkode_mem, 
-				      long int *flag);
-SUNDIALS_EXPORT int ARKSlsGetLastMassFlag(void *arkode_mem, 
-					  long int *flag);
-
-/*---------------------------------------------------------------
- The following function returns the name of the constant 
- associated with a ARKSLS return flag
----------------------------------------------------------------*/
-SUNDIALS_EXPORT char *ARKSlsGetReturnFlagName(long int flag);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_spbcgs.h b/include/arkode/arkode_spbcgs.h
deleted file mode 100644
index 2151d7b..0000000
--- a/include/arkode/arkode_spbcgs.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the header file for the ARKODE scaled preconditioned 
- * Bi-CGSTAB linear solver, ARKSPBCG.
- *--------------------------------------------------------------*/
-
-#ifndef _ARKSPBCG_H
-#define _ARKSPBCG_H
-
-#include <arkode/arkode.h>
-#include <arkode/arkode_spils.h>
-#include <sundials/sundials_spbcgs.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*---------------------------------------------------------------
- ARKSpbcg:
-
- A call to the ARKSpbcg function links the main ARKODE integrator
- with the ARKSPBCG linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
-           in iterative.h. These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPBCG solver. Pass 0 to
-           use the default value ARKSPBCG_MAXL=5.
-
- The return value of ARKSpbcg is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSpbcg(void *arkode_mem, int pretype, int maxl);
-
-
-/*---------------------------------------------------------------
- ARKMassSpbcg:
-
- A call to the ARKMassSpbcg function links the mass matrix solve
- with the ARKSPBCG linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
-           in iterative.h. These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPBCG solver. Pass 0 to
-           use the default value ARKSPBCG_MAXL=5.
-
- mtimes    is the user-supplied mass-matrix-vector product 
-           routine.
-
- The return value of ARKMassSpbcg is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassSpbcg(void *arkode_mem, int pretype, int maxl, 
-				 ARKSpilsMassTimesVecFn mtimes,
-				 void *mtimes_data);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_spfgmr.h b/include/arkode/arkode_spfgmr.h
deleted file mode 100644
index cd8f36d..0000000
--- a/include/arkode/arkode_spfgmr.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the header file for the ARKODE scaled preconditioned 
- * FGMRES linear solver, ARKSPFGMR.
- *--------------------------------------------------------------*/
-
-#ifndef _ARKSPFGMR_H
-#define _ARKSPFGMR_H
-
-#include <arkode/arkode.h>
-#include <arkode/arkode_spils.h>
-#include <sundials/sundials_spfgmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-
-/*---------------------------------------------------------------
- ARKSpfgmr:
-
- A call to ARKSpfgmr links the main ARKODE integrator with the 
- ARKSPFGMR linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined 
-           in sundials_iterative.h.
-           These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively. ARKSPFGMR only implements right 
-	   preconditioning, so if any one of PREC_LEFT, 
-	   PREC_RIGHT or PREC_BOTH are defined, it will default 
-	   to using the right preconditioner only.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPFGMR solver. Pass 0 to
-           use the default value ARKSPFGMR_MAXL=5.
-
- The return value of ARKSpfgmr is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSpfgmr(void *arkode_mem, int pretype, int maxl);
-
-
-/*---------------------------------------------------------------
- ARKMassSpfgmr:
-
- A call to ARKMassSpfgmr links the mass matrix solve
- with the ARKSPFGMR linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined 
-           in sundials_iterative.h.
-           These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively. ARKSPFGMR only implements right 
-	   preconditioning, so if any one of PREC_LEFT, 
-	   PREC_RIGHT or PREC_BOTH are defined, it will default 
-	   to using the right preconditioner only.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPFGMR solver. Pass 0 to
-           use the default value ARKSPFGMR_MAXL=5.
-
- mtimes    is the user-supplied mass-matrix-vector product 
-           routine.
-
- The return value of ARKMassSpfgmr is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassSpfgmr(void *arkode_mem, int pretype, int maxl, 
-				  ARKSpilsMassTimesVecFn mtimes,
-				  void *mtimes_data);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_spgmr.h b/include/arkode/arkode_spgmr.h
deleted file mode 100644
index 336e74a..0000000
--- a/include/arkode/arkode_spgmr.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the header file for the ARKODE scaled preconditioned 
- * GMRES linear solver, ARKSPGMR.
- *--------------------------------------------------------------*/
-
-#ifndef _ARKSPGMR_H
-#define _ARKSPGMR_H
-
-#include <arkode/arkode.h>
-#include <arkode/arkode_spils.h>
-#include <sundials/sundials_spgmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-
-/*---------------------------------------------------------------
- ARKSpgmr:
-
- A call to the ARKSpgmr function links the main ARKODE integrator
- with the ARKSPGMR linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined 
-           in sundials_iterative.h.
-           These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPGMR solver. Pass 0 to
-           use the default value ARKSPGMR_MAXL=5.
-
- The return value of ARKSpgmr is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSpgmr(void *arkode_mem, int pretype, int maxl);
-
-
-/*---------------------------------------------------------------
- ARKMassSpgmr:
-
- A call to the ARKMassSpgmr function links the mass matrix solve
- with the ARKSPGMR linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined 
-           in sundials_iterative.h.
-           These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPGMR solver. Pass 0 to
-           use the default value ARKSPGMR_MAXL=5.
-
- mtimes    is the user-supplied mass-matrix-vector product 
-           routine.
-
- The return value of ARKMassSpgmr is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
-
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassSpgmr(void *arkode_mem, int pretype, int maxl, 
-				 ARKSpilsMassTimesVecFn mtimes,
-				 void *mtimes_data);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_spils.h b/include/arkode/arkode_spils.h
index 54040f0..5016dc6 100644
--- a/include/arkode/arkode_spils.h
+++ b/include/arkode/arkode_spils.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,8 +15,8 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * This is the common header file for the Scaled, Preconditioned
- * Iterative Linear Solvers in ARKODE.
+ * Header file for the Scaled, Preconditioned Iterative Linear 
+ * Solver interface in ARKODE.
  *--------------------------------------------------------------*/
 
 #ifndef _ARKSPILS_H
@@ -24,14 +24,18 @@
 
 #include <sundials/sundials_iterative.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_linearsolver.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
+/*===============================================================
+ ARKSPILS Constants
+===============================================================*/
 
 /*---------------------------------------------------------------
- ARKSPILS return values 
+ ARKSPILS return values -- ADJUST CONSTANTS AS NECESSARY
 ---------------------------------------------------------------*/
 #define ARKSPILS_SUCCESS       0
 #define ARKSPILS_MEM_NULL     -1
@@ -41,6 +45,7 @@ extern "C" {
 #define ARKSPILS_PMEM_NULL    -5
 #define ARKSPILS_MASSMEM_NULL -6
 
+#define ARKSPILS_SUNLS_FAIL  -10
 
 /*---------------------------------------------------------------
  ARKSPILS solver constants:
@@ -59,12 +64,16 @@ extern "C" {
                    multiplied to get a tolerance on the linear
                    iteration
 ---------------------------------------------------------------*/
-#define ARKSPILS_MAXL   5
-#define ARKSPILS_MSBPRE 50
-#define ARKSPILS_DGMAX  RCONST(0.2)
+#define ARKSPILS_MSBPRE 50 /* -- TURN INTO A PARAMETER, MAKE THIS THE DEFAULT */
+#define ARKSPILS_DGMAX  RCONST(0.2) /* -- TURN INTO A PARAMETER, MAKE THIS THE DEFAULT */
 #define ARKSPILS_EPLIN  RCONST(0.05)
 
 
+  
+/*===============================================================
+ ARKSPILS user-supplied function prototypes
+===============================================================*/
+
 /*---------------------------------------------------------------
  Type: ARKSpilsPrecSetupFn
 
@@ -87,7 +96,7 @@ extern "C" {
  approximation to M.  This function will not be called in
  advance of every call to PrecSolve, but instead will be called
  only as often as necessary to achieve convergence within the
- Newton iteration.  If the PrecSolve function needs no
+ Inexact Newton iteration.  If the PrecSolve function needs no
  preparation, the PrecSetup function can be NULL.
 
  For greater efficiency, the PrecSetup function may save
@@ -113,18 +122,18 @@ extern "C" {
 
  jok     is an input flag indicating whether Jacobian-related
          data needs to be recomputed, as follows:
-           jok == FALSE means recompute Jacobian-related data
+           jok == SUNFALSE means recompute Jacobian-related data
                   from scratch.
-           jok == TRUE  means that Jacobian data, if saved from
+           jok == SUNTRUE  means that Jacobian data, if saved from
                   the previous PrecSetup call, can be reused
                   (with the current value of gamma).
-         A Precset call with jok == TRUE can only occur after
-         a call with jok == FALSE.
+         A Precset call with jok == SUNTRUE can only occur after
+         a call with jok == SUNFALSE.
 
  jcurPtr is a pointer to an output integer flag which is
          to be set by PrecSetup as follows:
-         Set *jcurPtr = TRUE if Jacobian data was recomputed.
-         Set *jcurPtr = FALSE if Jacobian data was not recomputed,
+         Set *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+         Set *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
                         but saved data was reused.
 
  gamma   is the scalar appearing in the Newton matrix.
@@ -132,11 +141,6 @@ extern "C" {
  user_data  is a pointer to user data - the same as the user_data
          parameter passed to the ARKodeSetUserData function.
 
- tmp1, tmp2, and tmp3 are pointers to memory allocated
-                      for N_Vectors which can be used by
-                      ARKSpilsPrecSetupFn as temporary storage or
-                      work space.
-
  NOTE: If the user's preconditioner needs other quantities,
        they are accessible as follows: hcur (the current stepsize)
        and ewt (the error weight vector) are accessible through
@@ -152,11 +156,9 @@ extern "C" {
    < 0 for an unrecoverable error (integration is halted).
 ---------------------------------------------------------------*/
 typedef int (*ARKSpilsPrecSetupFn)(realtype t, N_Vector y, 
-				   N_Vector fy, booleantype jok, 
-				   booleantype *jcurPtr,
-				   realtype gamma, void *user_data,
-				   N_Vector tmp1, N_Vector tmp2,
-				   N_Vector tmp3);
+                                   N_Vector fy, booleantype jok, 
+                                   booleantype *jcurPtr,
+                                   realtype gamma, void *user_data);
 
 
 /*---------------------------------------------------------------
@@ -197,9 +199,6 @@ typedef int (*ARKSpilsPrecSetupFn)(realtype t, N_Vector y,
  user_data  is a pointer to user data - the same as the user_data
          parameter passed to the ARKodeSetUserData function.
 
- tmp    is a pointer to memory allocated for an N_Vector
-        which can be used by PSolve for work space.
-
  Returned value:
  The value to be returned by the PrecSolve function is a flag
  indicating whether it was successful.  This value should be
@@ -208,10 +207,51 @@ typedef int (*ARKSpilsPrecSetupFn)(realtype t, N_Vector y,
    negative for an unrecoverable error (integration is halted).
 ---------------------------------------------------------------*/
 typedef int (*ARKSpilsPrecSolveFn)(realtype t, N_Vector y, 
-				   N_Vector fy, N_Vector r, 
-				   N_Vector z, realtype gamma, 
-				   realtype delta, int lr, 
-				   void *user_data, N_Vector tmp);
+                                   N_Vector fy, N_Vector r, 
+                                   N_Vector z, realtype gamma, 
+                                   realtype delta, int lr, 
+                                   void *user_data);
+
+
+/*---------------------------------------------------------------
+ Type: ARKSpilsJacTimesSetupFn
+
+ The user-supplied Jacobian-times-vector product setup function 
+ JacTimesSetup and the user-supplied Jacobian-times-vector 
+ product function JTimes together must generate the product
+ J*v for v, where J is the Jacobian df/dy, or an approximation 
+ to it, and v is a given vector. It should return 0 if 
+ successful a positive value for a recoverable error or a
+ negative value for an unrecoverable failure.
+
+ Each call to the JacTimesSetup function is preceded by a call 
+ to the RhsFn fi with the same (t,y) arguments.  Thus the 
+ JacTimesSetup function can use any auxiliary data that is 
+ computed and saved by the fi function and made accessible to 
+ JacTimesSetup.
+
+ A function JacTimesSetup must have the prototype given below.
+ Its parameters are as follows:
+
+ t       is the current value of the independent variable.
+
+ y       is the current value of the dependent variable vector,
+          namely the predicted value of y(t).
+
+ fy      is the vector f(t,y).
+
+ user_data  is a pointer to user data - the same as the user_data
+         parameter passed to the ARKodeSetUserData function.
+
+ Returned value:
+ The value to be returned by the JacTimesSetup function is a flag
+ indicating whether it was successful.  This value should be
+   0   if successful,
+   > 0 for a recoverable error (step will be retried),
+   < 0 for an unrecoverable error (integration is halted).
+---------------------------------------------------------------*/
+typedef int (*ARKSpilsJacTimesSetupFn)(realtype t, N_Vector y, 
+                                       N_Vector fy, void *user_data);
 
 
 /*---------------------------------------------------------------
@@ -244,9 +284,39 @@ typedef int (*ARKSpilsPrecSolveFn)(realtype t, N_Vector y,
             which can be used by Jtimes for work space.
 ---------------------------------------------------------------*/
 typedef int (*ARKSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, 
-				     realtype t, N_Vector y, 
-				     N_Vector fy, void *user_data, 
-				     N_Vector tmp);
+                                     realtype t, N_Vector y, 
+                                     N_Vector fy, void *user_data, 
+                                     N_Vector tmp);
+
+
+/*---------------------------------------------------------------
+ Type: ARKSpilsMassTimesSetupFn
+
+ The user-supplied mass matrix-times-vector product setup 
+ function MassTimesSetup and the user-supplied mass 
+ matrix-times-vector product function MTimes together must 
+ generate the product M*v for v, where M is the mass matrix, or 
+ an approximation to it, and v is a given vector. It should 
+ return 0 if successful a positive value for a recoverable error 
+ or a negative value for an unrecoverable failure.
+
+ A function MassTimesSetup must have the prototype given below.
+ Its parameters are as follows:
+
+ t       is the current value of the independent variable.
+
+ mtimes_data  is a pointer to user data - the same as the 
+         parameter passed to the ARKodeSetMassTimesVecFn
+         function.
+
+ Returned value:
+ The value to be returned by the MassTimesSetup function is a 
+ flag indicating whether it was successful.  This value should be
+   0   if successful,
+   > 0 for a recoverable error (step will be retried),
+   < 0 for an unrecoverable error (integration is halted).
+---------------------------------------------------------------*/
+typedef int (*ARKSpilsMassTimesSetupFn)(realtype t, void *mtimes_data);
 
 
 /*---------------------------------------------------------------
@@ -266,12 +336,12 @@ typedef int (*ARKSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv,
 
    t        is the current value of the independent variable.
 
-   user_data   is a pointer to user data, the same as the user_data
-            parameter passed to the ARKodeSetUserData function.
+   mtimes_data   is a pointer to user data, the same as the 
+            parameter passed to the ARKodeSetMassTimesVecFn 
+            function.
 ---------------------------------------------------------------*/
 typedef int (*ARKSpilsMassTimesVecFn)(N_Vector v, N_Vector Mv, 
-				      realtype t, void *user_data);
-
+                                      realtype t, void *mtimes_data);
 
 
 /*---------------------------------------------------------------
@@ -298,20 +368,13 @@ typedef int (*ARKSpilsMassTimesVecFn)(N_Vector v, N_Vector Mv,
  user_data  is a pointer to user data - the same as the user_data
          parameter passed to the ARKodeSetUserData function.
 
- tmp1, tmp2, and tmp3 are pointers to memory allocated
-                      for N_Vectors which can be used by
-                      ARKSpilsMassPrecSetupFn as temporary 
-                      storage or work space.
-
  Returned value:
  The value to be returned by the MPrecSetup function is a flag
  indicating whether it was successful.  This value should be
    0   if successful,
    < 0 for an unrecoverable error (integration is halted).
 ---------------------------------------------------------------*/
-typedef int (*ARKSpilsMassPrecSetupFn)(realtype t, void *user_data, 
-				       N_Vector tmp1, N_Vector tmp2, 
-				       N_Vector tmp3);
+typedef int (*ARKSpilsMassPrecSetupFn)(realtype t, void *user_data);
 
 
 /*---------------------------------------------------------------
@@ -346,9 +409,6 @@ typedef int (*ARKSpilsMassPrecSetupFn)(realtype t, void *user_data,
  user_data  is a pointer to user data - the same as the user_data
          parameter passed to the ARKodeSetUserData function.
 
- tmp    is a pointer to memory allocated for an N_Vector
-        which can be used by PSolve for work space.
-
  Returned value:
  The value to be returned by the MPrecSolve function is a flag
  indicating whether it was successful.  This value should be
@@ -356,36 +416,62 @@ typedef int (*ARKSpilsMassPrecSetupFn)(realtype t, void *user_data,
    negative for an unrecoverable error (integration is halted).
 ---------------------------------------------------------------*/
 typedef int (*ARKSpilsMassPrecSolveFn)(realtype t, N_Vector r, 
-				       N_Vector z, realtype delta, 
-				       int lr, void *user_data, 
-				       N_Vector tmp);
-
+                                       N_Vector z, realtype delta, 
+                                       int lr, void *user_data);
+  
+  
+/*===============================================================
+  ARKSPILS Exported functions
+===============================================================*/
 
 /*---------------------------------------------------------------
- Optional inputs to the ARKSPILS linear solver:
+ Required inputs for the ARKSPILS linear solver interface:
 
- ARKSpilsSetPrecType resets the type of preconditioner, pretype,
-                from the value previously set.
-                This must be one of PREC_NONE, PREC_LEFT, 
-                PREC_RIGHT, or PREC_BOTH.
+ ARKSpilsSetLinearSolver specifies the iterative SUNLinearSolver 
+ object that ARKode should use.  This is required if ARKode is 
+ solving an implicit or IMEX IVP, and using an inexact Newton 
+ solver.
 
- ARKSpilsSetGSType specifies the type of Gram-Schmidt
-                orthogonalization to be used. This must be one of
-                the two enumeration constants MODIFIED_GS or
-                CLASSICAL_GS defined in iterative.h. These 
-                correspond to using modified Gram-Schmidt and 
-                classical Gram-Schmidt, respectively.
-                Default value is MODIFIED_GS.
+ ARKSpilsSetMassLinearSolver specifies the iterative 
+ SUNLinearSolver object that ARKode should use for mass-matrix 
+ systems.  This is required if ARKode is solving a problem with 
+ non-identity mass matrix and the user wishes to use an iterative 
+ solver for these systems.
 
- ARKSpilsSetMaxl resets the maximum Krylov subspace size, maxl,
-                from the value previously set.
-                An input value <= 0, gives the default value.
+ NOTE: when solving an implicit or IMEX IVP with non-identity mass
+ matrix and iterative linear solver, both the system and mass solvers
+ must be iterative (i.e. you cannot combine a direct system 
+ solver with an iterative mass matrix solver, etc.).
+
+ The return value is one of:
+    ARKSPILS_SUCCESS   if successful
+    ARKSPILS_MEM_NULL  if the ARKODE memory was NULL
+    ARKSPILS_ILL_INPUT if the linear solver memory was NULL
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int ARKSpilsSetLinearSolver(void *arkode_mem, 
+                                            SUNLinearSolver LS);
+
+SUNDIALS_EXPORT int ARKSpilsSetMassLinearSolver(void *arkode_mem, 
+                                                SUNLinearSolver LS,
+                                                booleantype time_dep);
+
+  
+/*---------------------------------------------------------------
+ Optional inputs to the ARKSPILS linear solver -- ALL of these 
+ must be called AFTER the corresponding iterative linear solver 
+ object (system matrix or mass matrix) has been attached to the 
+ ARKode integrator).
 
  ARKSpilsSetEpsLin specifies the factor by which the tolerance on
                 the nonlinear iteration is multiplied to get a
                 tolerance on the linear iteration.
                 Default value is 0.05.
 
+ ARKSpilsSetMassEpsLin specifies the factor by which the tolerance
+                on the nonlinear iteration is multiplied to get a
+                tolerance on the mass matrix linear iteration.
+                Default value is 0.05.
+
  ARKSpilsSetPreconditioner specifies the PrecSetup and PrecSolve 
                 functions.  Default is NULL for both arguments 
                 (no preconditioning)
@@ -394,11 +480,15 @@ typedef int (*ARKSpilsMassPrecSolveFn)(realtype t, N_Vector r,
                 and MPrecSolve functions.  Default is NULL for 
                 both arguments (no preconditioning)
 
- ARKSpilsSetJacTimesVecFn specifies the jtimes function. Default 
-                is to use an internal finite difference 
-		approximation routine.
+ ARKSpilsSetJacTimes specifies the jtsetup and jtimes functions. 
+                Default is to use an internal finite difference 
+		approximation routine (no setup).
 
- ARKSpilsSetMassTimesVecFn specifies the mtimes function. No Default.
+ ARKSpilsSetMassTimes specifies the mtsetup and mtimes functions. 
+                Note that there do not exist built-in finite-
+                difference approximation routines for this, this 
+                function MUST be called with non-NULL 'mtimes' 
+                if ARKSpilsSetMassLinearSolver was called.
 
  The return value of ARKSpilsSet* is one of:
     ARKSPILS_SUCCESS      if successful
@@ -407,26 +497,21 @@ typedef int (*ARKSpilsMassPrecSolveFn)(realtype t, N_Vector r,
     ARKSPILS_MASSMEM_NULL if the mass matrix solver memory was NULL
     ARKSPILS_ILL_INPUT    if an input has an illegal value
 ---------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSpilsSetPrecType(void *arkode_mem, int pretype);
-SUNDIALS_EXPORT int ARKSpilsSetMassPrecType(void *arkode_mem, int pretype);
-SUNDIALS_EXPORT int ARKSpilsSetGSType(void *arkode_mem, int gstype);
-SUNDIALS_EXPORT int ARKSpilsSetMassGSType(void *arkode_mem, int gstype);
-SUNDIALS_EXPORT int ARKSpilsSetMaxl(void *arkode_mem, int maxl);
-SUNDIALS_EXPORT int ARKSpilsSetMassMaxl(void *arkode_mem, int maxl);
 SUNDIALS_EXPORT int ARKSpilsSetEpsLin(void *arkode_mem, realtype eplifac);
 SUNDIALS_EXPORT int ARKSpilsSetMassEpsLin(void *arkode_mem, realtype eplifac);
 SUNDIALS_EXPORT int ARKSpilsSetPreconditioner(void *arkode_mem, 
-					      ARKSpilsPrecSetupFn pset,
-					      ARKSpilsPrecSolveFn psolve);
+                                              ARKSpilsPrecSetupFn psetup,
+                                              ARKSpilsPrecSolveFn psolve);
 SUNDIALS_EXPORT int ARKSpilsSetMassPreconditioner(void *arkode_mem, 
-						  ARKSpilsMassPrecSetupFn pset,
-						  ARKSpilsMassPrecSolveFn psolve);
-SUNDIALS_EXPORT int ARKSpilsSetJacTimesVecFn(void *arkode_mem, 
-					     ARKSpilsJacTimesVecFn jtv);
-SUNDIALS_EXPORT int ARKSpilsSetMassTimesVecFn(void *arkode_mem, 
-					      ARKSpilsMassTimesVecFn mtv,
-					      void *mtimes_data);
-
+                                                  ARKSpilsMassPrecSetupFn psetup,
+                                                  ARKSpilsMassPrecSolveFn psolve);
+SUNDIALS_EXPORT int ARKSpilsSetJacTimes(void *arkode_mem, 
+                                        ARKSpilsJacTimesSetupFn jtsetup,
+                                        ARKSpilsJacTimesVecFn jtimes);
+SUNDIALS_EXPORT int ARKSpilsSetMassTimes(void *arkode_mem, 
+                                         ARKSpilsMassTimesSetupFn msetup,
+                                         ARKSpilsMassTimesVecFn mtimes,
+                                         void *mtimes_data);
 
 /*---------------------------------------------------------------
  Optional outputs from the ARKSPILS linear solver:
@@ -434,38 +519,22 @@ SUNDIALS_EXPORT int ARKSpilsSetMassTimesVecFn(void *arkode_mem,
  ARKSpilsGetWorkSpace returns the real and integer workspace used
                 by the SPILS module.
 
- ARKSpilsGetMassWorkSpace returns the real and integer workspace used
-                by the mass matrix SPILS module.
-
  ARKSpilsGetNumPrecEvals returns the number of preconditioner
                  evaluations, i.e. the number of calls made
-                 to PrecSetup with jok==FALSE.
-
- ARKSpilsGetNumMassPrecEvals returns the number of mass matrix 
-                 preconditioner evaluations, i.e. the number of 
-                 calls made to MPrecSetup.
+                 to PrecSetup with jok==SUNFALSE.
 
  ARKSpilsGetNumPrecSolves returns the number of calls made to
                  PrecSolve.
 
- ARKSpilsGetNumMassPrecSolves returns the number of calls made to
-                 MPrecSolve.
-
  ARKSpilsGetNumLinIters returns the number of linear iterations.
 
- ARKSpilsGetNumMassIters returns the number of mass matrix solver
-                  iterations.
-
  ARKSpilsGetNumConvFails returns the number of linear
                  convergence failures.
 
- ARKSpilsGetNumMassConvFails returns the number of mass matrix solver
-                 convergence failures.
-
+ ARKSpilsGetNumJTSetupEvals returns the number of calls to jtsetup.
+ 
  ARKSpilsGetNumJtimesEvals returns the number of calls to jtimes.
 
- ARKSpilsGetNumMtimesEvals returns the number of calls to mtimes.
-
  ARKSpilsGetNumRhsEvals returns the number of calls to the user
                  f routine due to finite difference Jacobian
                  times vector evaluation.
@@ -473,6 +542,24 @@ SUNDIALS_EXPORT int ARKSpilsSetMassTimesVecFn(void *arkode_mem,
  ARKSpilsGetLastFlag returns the last error flag set by any of
                  the ARKSPILS interface functions.
 
+ ARKSpilsGetMassWorkSpace returns the real and integer workspace used
+                by the mass matrix SPILS module.
+
+ ARKSpilsGetNumMassPrecEvals returns the number of mass matrix 
+                 preconditioner evaluations, i.e. the number of 
+                 calls made to MPrecSetup.
+
+ ARKSpilsGetNumMassPrecSolves returns the number of calls made to
+                 MPrecSolve.
+
+ ARKSpilsGetNumMassIters returns the number of mass matrix solver
+                  iterations.
+
+ ARKSpilsGetNumMassConvFails returns the number of mass matrix solver
+                 convergence failures.
+
+ ARKSpilsGetNumMtimesEvals returns the number of calls to mtimes.
+
  ARKSpilsGetLastMassFlag returns the last error flag set by any of
                  the ARKSPILS interface functions on the mass 
 		 matrix solve.
@@ -483,37 +570,40 @@ SUNDIALS_EXPORT int ARKSpilsSetMassTimesVecFn(void *arkode_mem,
     ARKSPILS_LMEM_NULL if the linear solver memory was NULL
 ---------------------------------------------------------------*/
 SUNDIALS_EXPORT int ARKSpilsGetWorkSpace(void *arkode_mem, 
-					 long int *lenrwLS, 
-					 long int *leniwLS);
-SUNDIALS_EXPORT int ARKSpilsGetMassWorkSpace(void *arkode_mem, 
-					     long int *lenrwMLS, 
-					     long int *leniwMLS);
+                                         long int *lenrwLS, 
+                                         long int *leniwLS);
 SUNDIALS_EXPORT int ARKSpilsGetNumPrecEvals(void *arkode_mem, 
-					    long int *npevals);
-SUNDIALS_EXPORT int ARKSpilsGetNumMassPrecEvals(void *arkode_mem, 
-						long int *nmpevals);
+                                            long int *npevals);
 SUNDIALS_EXPORT int ARKSpilsGetNumPrecSolves(void *arkode_mem, 
-					     long int *npsolves);
-SUNDIALS_EXPORT int ARKSpilsGetNumMassPrecSolves(void *arkode_mem, 
-						 long int *nmpsolves);
+                                             long int *npsolves);
 SUNDIALS_EXPORT int ARKSpilsGetNumLinIters(void *arkode_mem, 
-					   long int *nliters);
-SUNDIALS_EXPORT int ARKSpilsGetNumMassIters(void *arkode_mem, 
-					    long int *nmiters);
+                                           long int *nliters);
 SUNDIALS_EXPORT int ARKSpilsGetNumConvFails(void *arkode_mem, 
-					    long int *nlcfails);
-SUNDIALS_EXPORT int ARKSpilsGetNumMassConvFails(void *arkode_mem, 
-						long int *nmcfails);
+                                            long int *nlcfails);
+SUNDIALS_EXPORT int ARKSpilsGetNumJTSetupEvals(void *arkode_mem,
+                                               long int *njtsetups);
 SUNDIALS_EXPORT int ARKSpilsGetNumJtimesEvals(void *arkode_mem, 
-					      long int *njvevals);
-SUNDIALS_EXPORT int ARKSpilsGetNumMtimesEvals(void *arkode_mem, 
-					      long int *nmvevals);
+                                              long int *njvevals);
 SUNDIALS_EXPORT int ARKSpilsGetNumRhsEvals(void *arkode_mem, 
-					   long int *nfevalsLS); 
+                                           long int *nfevalsLS); 
 SUNDIALS_EXPORT int ARKSpilsGetLastFlag(void *arkode_mem, 
-					long int *flag);
+                                        long int *flag);
+  
+SUNDIALS_EXPORT int ARKSpilsGetMassWorkSpace(void *arkode_mem, 
+                                             long int *lenrwMLS, 
+                                             long int *leniwMLS);
+SUNDIALS_EXPORT int ARKSpilsGetNumMassPrecEvals(void *arkode_mem, 
+                                                long int *nmpevals);
+SUNDIALS_EXPORT int ARKSpilsGetNumMassPrecSolves(void *arkode_mem, 
+                                                 long int *nmpsolves);
+SUNDIALS_EXPORT int ARKSpilsGetNumMassIters(void *arkode_mem, 
+                                            long int *nmiters);
+SUNDIALS_EXPORT int ARKSpilsGetNumMassConvFails(void *arkode_mem, 
+                                                long int *nmcfails);
+SUNDIALS_EXPORT int ARKSpilsGetNumMtimesEvals(void *arkode_mem, 
+                                              long int *nmvevals);
 SUNDIALS_EXPORT int ARKSpilsGetLastMassFlag(void *arkode_mem, 
-					    long int *flag);
+                                            long int *flag);
 
 
 /*---------------------------------------------------------------
diff --git a/include/arkode/arkode_sptfqmr.h b/include/arkode/arkode_sptfqmr.h
deleted file mode 100644
index 946cebe..0000000
--- a/include/arkode/arkode_sptfqmr.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the header file for the ARKODE scaled preconditioned 
- * TFQMR linear solver, ARKSPTFQMR.
- *--------------------------------------------------------------*/
-
-#ifndef _ARKSPTFQMR_H
-#define _ARKSPTFQMR_H
-
-#include <arkode/arkode.h>
-#include <arkode/arkode_spils.h>
-#include <sundials/sundials_sptfqmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*---------------------------------------------------------------
- ARKSptfqmr:
-
- A call to the ARKSptfqmr function links the main ARKODE integrator
- with the ARKSPTFQMR linear solver.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
-           in iterative.h. These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPTFQMR solver. Pass 0 to
-           use the default value ARKSPILS_MAXL=5.
-
- The return value of ARKSptfqmr is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSptfqmr(void *arkode_mem, int pretype, int maxl);
-
-
-/*---------------------------------------------------------------
- ARKMassSptfqmr:
-
- A call to the ARKMassSptfqmr function links the mass matrix solve
- with the ARKSPTFQMR linear solver module.
-
- arkode_mem is the pointer to the integrator memory returned by
-           ARKodeCreate.
-
- pretype   is the type of user preconditioning to be done.
-           This must be one of the four enumeration constants
-           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
-           in iterative.h. These correspond to no preconditioning,
-           left preconditioning only, right preconditioning
-           only, and both left and right preconditioning,
-           respectively.
-
- maxl      is the maximum Krylov dimension. This is an
-           optional input to the ARKSPTFQMR solver. Pass 0 to
-           use the default value ARKSPILS_MAXL=5.
-
- mtimes    is the user-supplied mass-matrix-vector product 
-           routine.
-
- The return value of ARKMassSptfqmr is one of:
-    ARKSPILS_SUCCESS   if successful
-    ARKSPILS_MEM_NULL  if the arkode memory was NULL
-    ARKSPILS_MEM_FAIL  if there was a memory allocation failure
-    ARKSPILS_ILL_INPUT if a required vector operation is missing
- The above constants are defined in arkode_spils.h
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassSptfqmr(void *arkode_mem, int pretype, int maxl, 
-				   ARKSpilsMassTimesVecFn mtimes,
-				   void *mtimes_data);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/arkode/arkode_superlumt.h b/include/arkode/arkode_superlumt.h
deleted file mode 100644
index 5d980ce..0000000
--- a/include/arkode/arkode_superlumt.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Header file for the ARKSUPERLUMT linear solver module.
- *---------------------------------------------------------------*/
-
-#ifndef _ARKSUPERLUMT_H
-#define _ARKSUPERLUMT_H
-
-#include "arkode/arkode_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-
-/*---------------------------------------------------------------
- Function: ARKSuperLUMT
------------------------------------------------------------------
- A call to the ARKSuperLUMT function links the main integrator
- with the ARKSUPERLUMT linear solver module.
-
- arkode_mem is the pointer to integrator memory returned by
-            ARKodeCreate.
-
- num_threads is the number of hardware threads to use
-
- n is the number of rows in the linear system
-
- nnz is the maximum number of nonzeros in the sparse matrix
-     A = M + gamma*J
-
- The return value of ARKSuperLUMT is one of:
-     ARKSLS_SUCCESS   if successful
-     ARKSLS_MEM_NULL  if the ARKode memory was NULL
-     ARKSLS_MEM_FAIL  if there was a memory allocation failure
-     ARKSLS_ILL_INPUT if a required vector operation is missing
-
- NOTE: The ARKSUPERLUMT linear solver assumes a serial 
-       implementation of the NVECTOR package. Therefore, 
-       ARKSuperLUMT will first test for a compatible N_Vector
-       internal representation by checking that the function
-       N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSuperLUMT(void *arkode_mem, 
-				 int num_threads,
-				 int n, int nnz); 
-
-
-/*---------------------------------------------------------------
- Function: ARKMassSuperLUMT
------------------------------------------------------------------
- A call to the ARKMassSuperLUMT function links the mass matrix
- solve with the ARKSUPERLUMT linear solver module.
-
- arkode_mem is the pointer to integrator memory returned by
-            ARKodeCreate.
-
- num_threads is the number of hardware threads to use
-
- n is the number of rows in the sparse mass matrix
-
- nnz is the maximum number of nonzeros in the sparse mass matrix
-
- smass is the user-supplied sparse mass matrix setup function.
-
- The return value of ARKMassSuperLUMT is one of:
-     ARKSLS_SUCCESS   if successful
-     ARKSLS_MEM_NULL  if the ARKode memory was NULL
-     ARKSLS_MEM_FAIL  if there was a memory allocation failure
-     ARKSLS_ILL_INPUT if a required vector operation is missing
-
- NOTE: The ARKSUPERLUMT linear solver assumes a serial 
-       implementation of the NVECTOR package. Therefore, 
-       ARKMassSuperLUMT will first test for a compatible 
-       N_Vector internal representation by checking that the 
-       function N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassSuperLUMT(void *arkode_mem, 
-				     int num_threads,
-				     int n, int nnz,
-				     ARKSlsSparseMassFn smass); 
-
-
-/*================================================================
- Optional Input Specification Functions
-=================================================================*/
-
-/*---------------------------------------------------------------
- Function: ARKSuperLUMTSetOrdering 
------------------------------------------------------------------
- Sets the ordering used by ARKSuperLUMT for reducing fill in the 
- system matrix solve.  Options for ordering_choice are:
-     0 for natural ordering
-     1 for minimal degree ordering on A'*A
-     2 for minimal degree ordering on A'+A
-     3 for AMD ordering for unsymmetric matrices
- The default used in ARKODE is 3 for COLAMD.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKSuperLUMTSetOrdering(void *ark_mem, 
-					    int ordering_choice); 
-
-
-/*---------------------------------------------------------------
- Function: ARKMassSuperLUMTSetOrdering 
------------------------------------------------------------------
- Sets the ordering used by ARKMassSuperLUMT for reducing fill in 
- the mass matrix solve.  Options for ordering_choice are:
-     0 for natural ordering
-     1 for minimal degree ordering on A'*A
-     2 for minimal degree ordering on A'+A
-     3 for AMD ordering for unsymmetric matrices
- The default used in ARKODE is 3 for COLAMD.
----------------------------------------------------------------*/
-SUNDIALS_EXPORT int ARKMassSuperLUMTSetOrdering(void *ark_mem, 
-						int ordering_choice); 
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode.h b/include/cvode/cvode.h
index 13bac37..564c2b9 100644
--- a/include/cvode/cvode.h
+++ b/include/cvode/cvode.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban
  *                and Dan Shumaker @ LLNL
@@ -303,12 +303,12 @@ SUNDIALS_EXPORT void *CVodeCreate(int lmm, int iter);
  *                         | [10]
  *                         |
  * CVodeSetStabLimDet      | flag to turn on/off stability limit
- *                         | detection (TRUE = on, FALSE = off).
+ *                         | detection (SUNTRUE = on, SUNFALSE = off).
  *                         | When BDF is used and order is 3 or
  *                         | greater, CVsldet is called to detect
  *                         | stability limit.  If limit is detected,
  *                         | the order is reduced.
- *                         | [FALSE]
+ *                         | [SUNFALSE]
  *                         |
  * CVodeSetInitStep        | initial step size.
  *                         | [estimated by CVODE]
diff --git a/include/cvode/cvode_band.h b/include/cvode/cvode_band.h
deleted file mode 100644
index c80ae87..0000000
--- a/include/cvode/cvode_band.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODE band linear solver, CVBAND.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVBAND_H
-#define _CVBAND_H
-
-#include <cvode/cvode_direct.h>
-#include <sundials/sundials_band.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVBand
- * -----------------------------------------------------------------
- * A call to the CVBand function links the main CVODE integrator
- * with the CVBAND linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * mupper is the upper bandwidth of the band Jacobian
- *        approximation.
- *
- * mlower is the lower bandwidth of the band Jacobian
- *        approximation.
- *
- * The return value of CVBand is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the cvode memory was NULL
- *    CVDLS_MEM_FAIL  if there was a memory allocation failure
- *    CVDLS_ILL_INPUT if a required vector operation is missing or
- *                       if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVBand(void *cvode_mem, long int N, long int mupper, long int mlower);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_bandpre.h b/include/cvode/cvode_bandpre.h
index 771a1d5..a1107d8 100644
--- a/include/cvode/cvode_bandpre.h
+++ b/include/cvode/cvode_bandpre.h
@@ -1,78 +1,95 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for the CVBANDPRE module, which
  * provides a banded difference quotient Jacobian-based
- * preconditioner and solver routines for use with CVSPGMR,
- * CVSPBCG, or CVSPTFQMR.
- *
- * Summary:
- * These routines provide a band matrix preconditioner based on
- * difference quotients of the ODE right-hand side function f.
- * The user supplies parameters
- *   mu = upper half-bandwidth (number of super-diagonals)
- *   ml = lower half-bandwidth (number of sub-diagonals)
- * The routines generate a band matrix of bandwidth ml + mu + 1
- * and use this to form a preconditioner for use with the Krylov
- * linear solver in CVSP*. Although this matrix is intended to
- * approximate the Jacobian df/dy, it may be a very crude
- * approximation. The true Jacobian need not be banded, or its
- * true bandwith may be larger than ml + mu + 1, as long as the
- * banded approximation generated here is sufficiently accurate
- * to speed convergence as a preconditioner.
- *
- * Usage:
- *   The following is a summary of the usage of this module.
- *   Details of the calls to CVodeCreate, CVodeInit, CVSp*,
- *   and CVode are available in the User Guide.
- *   To use these routines, the sequence of calls in the user
- *   main program should be as follows:
- *
- *   #include <cvode/cvode_bandpre.h>
- *   #include <nvector_serial.h>
- *   ...
- *   Set y0
- *   ...
- *   cvode_mem = CVodeCreate(...);
- *   ier = CVodeInit(...);
- *   ...
- *   flag = CVSptfqmr(cvode_mem, pretype, maxl);
- *     -or-
- *   flag = CVSpgmr(cvode_mem, pretype, maxl);
- *     -or-
- *   flag = CVSpbcg(cvode_mem, pretype, maxl);
- *   ...
- *   flag = CVBandPrecInit(cvode_mem, N, mu, ml);
- *   ...
- *   flag = CVode(...);
- *   ...
- *   Free y0
- *   ...
- *   CVodeFree(&cvode_mem);
- *
- * Notes:
- * (1) Include this file for the CVBandPrecData type definition.
- * (2) In the CVBandPrecAlloc call, the arguments N is the
- *     problem dimension.
- * (3) In the CVBPSp* call, the user is free to specify
- *     the input pretype and the optional input maxl.
+ * preconditioner and solver routines for use with the CVSPILS 
+ * interface.
  * -----------------------------------------------------------------
  */
 
+
+/*-----------------------------------------------------------------
+  SUMMARY
+
+  These routines provide a band matrix preconditioner based on
+  difference quotients of the ODE right-hand side function f.
+  The user supplies parameters
+    mu = upper half-bandwidth (number of super-diagonals)
+    ml = lower half-bandwidth (number of sub-diagonals)
+  The routines generate a band matrix of bandwidth ml + mu + 1
+  and use this to form a preconditioner for use with the Krylov
+  linear solver through the CVSPILS interface. Although this 
+  matrix is intended to approximate the Jacobian df/dy, it may 
+  be a very crude approximation. The true Jacobian need not be 
+  banded, or its true bandwith may be larger than ml + mu + 1, 
+  as long as the banded approximation generated here is 
+  sufficiently accurate to speed convergence as a preconditioner.
+ 
+  Usage:
+    The following is a summary of the usage of this module.
+    Details of the calls to CVodeCreate, CVodeInit, CVSp*,
+    and CVode are available in the User Guide.
+    To use these routines, the sequence of calls in the user
+    main program should be as follows:
+ 
+    #include <cvode/cvode_bandpre.h>
+    #include <nvector_serial.h>   (or openmp or pthreads)
+    ...
+    void *cvode_mem;
+    ...
+    Set y0
+    ...
+    SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+    ...
+    cvode_mem = CVodeCreate(...);
+    flag = CVodeInit(...);
+    ...
+    flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+    ...
+    flag = CVBandPrecInit(cvode_mem, N, mu, ml);
+    ...
+    flag = CVode(...);
+    ...
+    Free y0
+    ...
+    CVodeFree(&cvode_mem);
+    ...
+    SUNLinSolFree(LS);
+    ...
+ 
+  Notes:
+  (1) Include this file for the CVBandPrecData type definition.
+  (2) In the CVBandPrecInit call, the argument N is the
+      problem dimension.
+  (3) In the linear solver creation call, the user is free to
+      specify the input pretype and the optional input maxl.
+  -----------------------------------------------------------------*/
+
 #ifndef _CVBANDPRE_H
 #define _CVBANDPRE_H
 
@@ -83,60 +100,60 @@ extern "C" {
 #endif
 
 
-/*
- * -----------------------------------------------------------------
- * Function : CVBandPrecInit
- * -----------------------------------------------------------------
- * CVBandPrecInit allocates and initializes the BANDPRE preconditioner
- * module. This functino must be called AFTER one of the SPILS linear
- * solver modules has been attached to the CVODE integrator.
- *
- * The parameters of CVBandPrecInit are as follows:
- *
- * cvode_mem is the pointer to CVODE memory returned by CVodeCreate.
- *
- * N is the problem size.
- *
- * mu is the upper half bandwidth.
- *
- * ml is the lower half bandwidth.
- *
- * The return value of CVBandPrecInit is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_ILL_INPUT if an input has an illegal value
- *   CVSPILS_MEM_FAIL if a memory allocation request failed
- *
- * NOTE: The band preconditioner assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVBandPrecInit will
- *       first test for a compatible N_Vector internal
- *       representation by checking for required functions.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Function : CVBandPrecInit
+  -----------------------------------------------------------------
+  CVBandPrecInit allocates and initializes the BANDPRE preconditioner
+  module. This function must be called AFTER the CVSPILS linear
+  solver interface has been created.
+ 
+  The parameters of CVBandPrecInit are as follows:
+ 
+  cvode_mem is the pointer to CVODE memory returned by CVodeCreate.
+ 
+  N is the problem size.
+ 
+  mu is the upper half bandwidth.
+ 
+  ml is the lower half bandwidth.
+ 
+  The return value of CVBandPrecInit is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_ILL_INPUT if an input has an illegal value
+    CVSPILS_MEM_FAIL if a memory allocation request failed
+ 
+  NOTE: The band preconditioner assumes a serial/OpenMP/Pthreads
+        implementation of the NVECTOR package. Therefore, 
+        CVBandPrecInit will first test for a compatible N_Vector 
+        internal representation by checking for required functions.
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBandPrecInit(void *cvode_mem, sunindextype N,
+                                   sunindextype mu, sunindextype ml);
 
-SUNDIALS_EXPORT int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml);
-
-/*
- * -----------------------------------------------------------------
- * Optional output functions : CVBandPrecGet*
- * -----------------------------------------------------------------
- * CVBandPrecGetWorkSpace returns the real and integer work space used
- *                        by CVBANDPRE.
- * CVBandPrecGetNumRhsEvals returns the number of calls made from
- *                          CVBANDPRE to the user's right-hand side
- *                          routine f.
- *
- * The return value of CVBandPrecGet* is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  Optional output functions : CVBandPrecGet*
+  -----------------------------------------------------------------
+  CVBandPrecGetWorkSpace returns the real and integer work space used
+                         by CVBANDPRE.
+  CVBandPrecGetNumRhsEvals returns the number of calls made from
+                           CVBANDPRE to the user's right-hand side
+                           routine f.
+ 
+  The return value of CVBandPrecGet* is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP);
+SUNDIALS_EXPORT int CVBandPrecGetWorkSpace(void *cvode_mem,
+                                           long int *lenrwLS,
+                                           long int *leniwLS);
+SUNDIALS_EXPORT int CVBandPrecGetNumRhsEvals(void *cvode_mem,
+                                             long int *nfevalsBP);
 
 
 #ifdef __cplusplus
diff --git a/include/cvode/cvode_bbdpre.h b/include/cvode/cvode_bbdpre.h
index 15535b0..4dce07e 100644
--- a/include/cvode/cvode_bbdpre.h
+++ b/include/cvode/cvode_bbdpre.h
@@ -1,109 +1,125 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Michael Wittman, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *    Michael Wittman, Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for the CVBBDPRE module, for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with CVSPGMR/CVSPBCG/CVSPTFQMR, 
- * and the parallel implementation of the NVECTOR module.
- *
- * Summary:
- *
- * These routines provide a preconditioner matrix that is
- * block-diagonal with banded blocks. The blocking corresponds
- * to the distribution of the dependent variable vector y among
- * the processors. Each preconditioner block is generated from
- * the Jacobian of the local part (on the current processor) of a
- * given function g(t,y) approximating f(t,y). The blocks are
- * generated by a difference quotient scheme on each processor
- * independently. This scheme utilizes an assumed banded
- * structure with given half-bandwidths, mudq and mldq.
- * However, the banded Jacobian block kept by the scheme has
- * half-bandwiths mukeep and mlkeep, which may be smaller.
- *
- * The user's calling program should have the following form:
- *
- *   #include <nvector_parallel.h>
- *   #include <cvode/cvode_bbdpre.h>
- *   ...
- *   void *cvode_mem;
- *   ...
- *   Set y0
- *   ...
- *   cvode_mem = CVodeCreate(...);
- *   ier = CVodeInit(...);
- *   ...
- *   flag = CVSpgmr(cvode_mem, pretype, maxl);
- *      -or-
- *   flag = CVSpbcg(cvode_mem, pretype, maxl);
- *      -or-
- *   flag = CVSptfqmr(cvode_mem, pretype, maxl);
- *   ...
- *   flag = CVBBDPrecInit(cvode_mem, Nlocal, mudq ,mldq,
- *                        mukeep, mlkeep, dqrely, gloc, cfn);
- *   ...
- *   ier = CVode(...);
- *   ...
- *   CVodeFree(&cvode_mem);
- * 
- *   Free y0
- *
- * The user-supplied routines required are:
- *
- *   f    = function defining the ODE right-hand side f(t,y).
- *
- *   gloc = function defining the approximation g(t,y).
- *
- *   cfn  = function to perform communication need for gloc.
- *
- * Notes:
- *
- * 1) This header file is included by the user for the definition
- *    of the CVBBDData type and for needed function prototypes.
- *
- * 2) The CVBBDPrecInit call includes half-bandwiths mudq and mldq
- *    to be used in the difference quotient calculation of the
- *    approximate Jacobian. They need not be the true
- *    half-bandwidths of the Jacobian of the local block of g,
- *    when smaller values may provide a greater efficiency.
- *    Also, the half-bandwidths mukeep and mlkeep of the retained
- *    banded approximate Jacobian block may be even smaller,
- *    to reduce storage and computation costs further.
- *    For all four half-bandwidths, the values need not be the
- *    same on every processor.
- *
- * 3) The actual name of the user's f function is passed to
- *    CVodeInit, and the names of the user's gloc and cfn
- *    functions are passed to CVBBDPrecInit.
- *
- * 4) The pointer to the user-defined data block user_data, which is
- *    set through CVodeSetUserData is also available to the user in
- *    gloc and cfn.
- *
- * 5) Optional outputs specific to this module are available by
- *    way of routines listed below. These include work space sizes
- *    and the cumulative number of gloc calls. The costs
- *    associated with this module also include nsetups banded LU
- *    factorizations, nlinsetups cfn calls, and npsolves banded
- *    backsolve calls, where nlinsetups and npsolves are
- *    integrator/CVSPGMR/CVSPBCG/CVSPTFQMR optional outputs.
+ * matrix with banded blocks, for use with the CVSPILS interface,
+ * and the MPI-parallel implementation of the NVECTOR module.
  * -----------------------------------------------------------------
  */
 
+
+/*----------------------------------------------------------------- 
+  Summary:
+ 
+  These routines provide a preconditioner matrix that is
+  block-diagonal with banded blocks. The blocking corresponds
+  to the distribution of the dependent variable vector y among
+  the processors. Each preconditioner block is generated from
+  the Jacobian of the local part (on the current processor) of a
+  given function g(t,y) approximating f(t,y). The blocks are
+  generated by a difference quotient scheme on each processor
+  independently. This scheme utilizes an assumed banded
+  structure with given half-bandwidths, mudq and mldq.
+  However, the banded Jacobian block kept by the scheme has
+  half-bandwiths mukeep and mlkeep, which may be smaller.
+ 
+  The user's calling program should have the following form:
+ 
+    #include <nvector_parallel.h>
+    #include <cvode/cvode_spils.h>
+    #include <cvode/cvode_bbdpre.h>
+    ...
+    void *cvode_mem;
+    ...
+    Set y0
+    ...
+    SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+    ...
+    cvode_mem = CVodeCreate(...);
+    flag = CVodeInit(...);
+    ...
+    flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+    ...
+    flag = CVBBDPrecInit(cvode_mem, Nlocal, mudq ,mldq,
+                         mukeep, mlkeep, dqrely, gloc, cfn);
+    ...
+    flag = CVode(...);
+    ...
+    CVodeFree(&cvode_mem);
+    ...
+    Free y0
+    ...
+    CVodeFree(&cvode_mem);
+    ...
+    SUNLinSolFree(LS);
+    ...
+ 
+  The user-supplied routines required are:
+ 
+    f    = function defining the ODE right-hand side f(t,y).
+ 
+    gloc = function defining the approximation g(t,y).
+ 
+    cfn  = function to perform communication need for gloc.
+ 
+  Notes:
+ 
+  1) This header file is included by the user for the definition
+     of the CVBBDData type and for needed function prototypes.
+ 
+  2) The CVBBDPrecInit call includes half-bandwiths mudq and mldq
+     to be used in the difference quotient calculation of the
+     approximate Jacobian. They need not be the true
+     half-bandwidths of the Jacobian of the local block of g,
+     when smaller values may provide a greater efficiency.
+     Also, the half-bandwidths mukeep and mlkeep of the retained
+     banded approximate Jacobian block may be even smaller,
+     to reduce storage and computation costs further.
+     For all four half-bandwidths, the values need not be the
+     same on every processor.
+ 
+  3) The actual name of the user's f function is passed to
+     CVodeInit, and the names of the user's gloc and cfn
+     functions are passed to CVBBDPrecInit.
+ 
+  4) The pointer to the user-defined data block user_data, which is
+     set through CVodeSetUserData is also available to the user in
+     gloc and cfn.
+ 
+  5) Optional outputs specific to this module are available by
+     way of routines listed below. These include work space sizes
+     and the cumulative number of gloc calls. The costs
+     associated with this module also include nsetups banded LU
+     factorizations, nlinsetups cfn calls, and npsolves banded
+     backsolve calls, where nlinsetups and npsolves are
+     integrator/CVSPILS optional outputs.
+  -----------------------------------------------------------------*/
+
 #ifndef _CVBBDPRE_H
 #define _CVBBDPRE_H
 
@@ -113,158 +129,158 @@
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * Type : CVLocalFn
- * -----------------------------------------------------------------
- * The user must supply a function g(t,y) which approximates the
- * right-hand side function f for the system y'=f(t,y), and which
- * is computed locally (without interprocess communication).
- * (The case where g is mathematically identical to f is allowed.)
- * The implementation of this function must have type CVLocalFn.
- *
- * This function takes as input the local vector size Nlocal, the
- * independent variable value t, the local real dependent
- * variable vector y, and a pointer to the user-defined data
- * block user_data. It is to compute the local part of g(t,y) and
- * store this in the vector g.
- * (Allocation of memory for y and g is handled within the
- * preconditioner module.)
- * The user_data parameter is the same as that specified by the user
- * through the CVodeSetFdata routine.
- *
- * A CVLocalFn should return 0 if successful, a positive value if 
- * a recoverable error occurred, and a negative value if an 
- * unrecoverable error occurred.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type : CVLocalFn
+  -----------------------------------------------------------------
+  The user must supply a function g(t,y) which approximates the
+  right-hand side function f for the system y'=f(t,y), and which
+  is computed locally (without interprocess communication).
+  (The case where g is mathematically identical to f is allowed.)
+  The implementation of this function must have type CVLocalFn.
+ 
+  This function takes as input the local vector size Nlocal, the
+  independent variable value t, the local real dependent
+  variable vector y, and a pointer to the user-defined data
+  block user_data. It is to compute the local part of g(t,y) and
+  store this in the vector g.
+  (Allocation of memory for y and g is handled within the
+  preconditioner module.)
+  The user_data parameter is the same as that specified by the user
+  through the CVodeSetUserdata routine.
+ 
+  A CVLocalFn should return 0 if successful, a positive value if 
+  a recoverable error occurred, and a negative value if an 
+  unrecoverable error occurred.
+  -----------------------------------------------------------------*/
+typedef int (*CVLocalFn)(sunindextype Nlocal, realtype t, 
+                         N_Vector y, N_Vector g, void *user_data);
 
-typedef int (*CVLocalFn)(long int Nlocal, realtype t, N_Vector y,
-                         N_Vector g, void *user_data);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVCommFn
- * -----------------------------------------------------------------
- * The user may supply a function of type CVCommFn which performs
- * all interprocess communication necessary to evaluate the
- * approximate right-hand side function described above.
- *
- * This function takes as input the local vector size Nlocal,
- * the independent variable value t, the dependent variable
- * vector y, and a pointer to the user-defined data block user_data.
- * The user_data parameter is the same as that specified by the user
- * through the CVodeSetUserData routine. The CVCommFn cfn is
- * expected to save communicated data in space defined within the
- * structure user_data. Note: A CVCommFn cfn does not have a return value.
- *
- * Each call to the CVCommFn cfn is preceded by a call to the
- * CVRhsFn f with the same (t,y) arguments. Thus cfn can omit any
- * communications done by f if relevant to the evaluation of g.
- * If all necessary communication was done by f, the user can
- * pass NULL for cfn in CVBBDPrecInit (see below).
- *
- * A CVCommFn should return 0 if successful, a positive value if 
- * a recoverable error occurred, and a negative value if an 
- * unrecoverable error occurred.
- * -----------------------------------------------------------------
- */
 
-typedef int (*CVCommFn)(long int Nlocal, realtype t, N_Vector y,
-                        void *user_data);
+/*-----------------------------------------------------------------
+  Type : CVCommFn
+  -----------------------------------------------------------------
+  The user may supply a function of type CVCommFn which performs
+  all interprocess communication necessary to evaluate the
+  approximate right-hand side function described above.
+ 
+  This function takes as input the local vector size Nlocal,
+  the independent variable value t, the dependent variable
+  vector y, and a pointer to the user-defined data block 
+  user_data. The user_data parameter is the same as that 
+  specified by the user through the CVodeSetUserData routine. 
+  The CVCommFn cfn is expected to save communicated data in 
+  space defined within the structure user_data. 
+  Note: A CVCommFn cfn does not have a return value.
+ 
+  Each call to the CVCommFn cfn is preceded by a call to the
+  CVRhsFn f with the same (t,y) arguments. Thus cfn can omit any
+  communications done by f if relevant to the evaluation of g.
+  If all necessary communication was done by f, the user can
+  pass NULL for cfn in CVBBDPrecInit (see below).
+ 
+  A CVCommFn should return 0 if successful, a positive value if 
+  a recoverable error occurred, and a negative value if an 
+  unrecoverable error occurred.
+  -----------------------------------------------------------------*/
+typedef int (*CVCommFn)(sunindextype Nlocal, realtype t, 
+                        N_Vector y, void *user_data);
 
-/*
- * -----------------------------------------------------------------
- * Function : CVBBDPrecInit
- * -----------------------------------------------------------------
- * CVBBDPrecInit allocates and initializes the BBD preconditioner.
- *
- * The parameters of CVBBDPrecInit are as follows:
- *
- * cvode_mem is the pointer to the integrator memory.
- *
- * Nlocal is the length of the local block of the vectors y etc.
- *        on the current processor.
- *
- * mudq, mldq are the upper and lower half-bandwidths to be used
- *            in the difference quotient computation of the local
- *            Jacobian block.
- *
- * mukeep, mlkeep are the upper and lower half-bandwidths of the
- *                retained banded approximation to the local Jacobian
- *                block.
- *
- * dqrely is an optional input. It is the relative increment
- *        in components of y used in the difference quotient
- *        approximations. To specify the default, pass 0.
- *        The default is dqrely = sqrt(unit roundoff).
- *
- * gloc is the name of the user-supplied function g(t,y) that
- *      approximates f and whose local Jacobian blocks are
- *      to form the preconditioner.
- *
- * cfn is the name of the user-defined function that performs
- *     necessary interprocess communication for the
- *     execution of gloc.
- *
- * The return value of CVBBDPrecInit is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_ILL_INPUT if an input has an illegal value
- *   CVSPILS_MEM_FAIL if a memory allocation request failed
- * -----------------------------------------------------------------
- */
 
-SUNDIALS_EXPORT int CVBBDPrecInit(void *cvode_mem, long int Nlocal, 
-                                  long int mudq, long int mldq, 
-                                  long int mukeep, long int mlkeep, 
+/*-----------------------------------------------------------------
+  Function : CVBBDPrecInit
+  -----------------------------------------------------------------
+  CVBBDPrecInit allocates and initializes the BBD preconditioner.
+ 
+  The parameters of CVBBDPrecInit are as follows:
+ 
+  cvode_mem is the pointer to the integrator memory.
+ 
+  Nlocal is the length of the local block of the vectors y etc.
+         on the current processor.
+ 
+  mudq, mldq are the upper and lower half-bandwidths to be used
+             in the difference quotient computation of the local
+             Jacobian block.
+ 
+  mukeep, mlkeep are the upper and lower half-bandwidths of the
+                 retained banded approximation to the local Jacobian
+                 block.
+ 
+  dqrely is an optional input. It is the relative increment
+         in components of y used in the difference quotient
+         approximations. To specify the default, pass 0.
+         The default is dqrely = sqrt(unit roundoff).
+ 
+  gloc is the name of the user-supplied function g(t,y) that
+       approximates f and whose local Jacobian blocks are
+       to form the preconditioner.
+ 
+  cfn is the name of the user-defined function that performs
+      necessary interprocess communication for the
+      execution of gloc.
+ 
+  The return value of CVBBDPrecInit is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_ILL_INPUT if an input has an illegal value
+    CVSPILS_MEM_FAIL if a memory allocation request failed
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBBDPrecInit(void *cvode_mem,
+                                  sunindextype Nlocal, 
+                                  sunindextype mudq,
+                                  sunindextype mldq, 
+                                  sunindextype mukeep,
+                                  sunindextype mlkeep, 
                                   realtype dqrely,
-                                  CVLocalFn gloc, CVCommFn cfn);
+                                  CVLocalFn gloc,
+                                  CVCommFn cfn);
 
-/*
- * -----------------------------------------------------------------
- * Function : CVBBDPrecReInit
- * -----------------------------------------------------------------
- * CVBBDPrecReInit re-initializes the BBDPRE module when solving a
- * sequence of problems of the same size with CVSPGMR/CVBBDPRE or
- * CVSPBCG/CVBBDPRE or CVSPTFQMR/CVBBDPRE provided there is no change 
- * in Nlocal, mukeep, or mlkeep. After solving one problem, and after 
- * calling CVodeReInit to re-initialize the integrator for a subsequent 
- * problem, call CVBBDPrecReInit.
- *
- * All arguments have the same names and meanings as those
- * of CVBBDPrecInit.
- *
- * The return value of CVBBDPrecReInit is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
 
-SUNDIALS_EXPORT int CVBBDPrecReInit(void *cvode_mem, long int mudq, long int mldq,
+/*-----------------------------------------------------------------
+  Function : CVBBDPrecReInit
+  -----------------------------------------------------------------
+  CVBBDPrecReInit re-initializes the BBDPRE module when solving a
+  sequence of problems of the same size with CVSPILS/CVBBDPRE 
+  provided there is no change in Nlocal, mukeep, or mlkeep. After 
+  solving one problem, and after calling CVodeReInit to 
+  re-initialize the integrator for a subsequent problem, call 
+  CVBBDPrecReInit.
+ 
+  All arguments have the same names and meanings as those
+  of CVBBDPrecInit.
+ 
+  The return value of CVBBDPrecReInit is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBBDPrecReInit(void *cvode_mem,
+                                    sunindextype mudq,
+                                    sunindextype mldq,
 				    realtype dqrely);
 
-/*
- * -----------------------------------------------------------------
- * BBDPRE optional output extraction routines
- * -----------------------------------------------------------------
- * CVBBDPrecGetWorkSpace returns the BBDPRE real and integer work space
- *                       sizes.
- * CVBBDPrecGetNumGfnEvals returns the number of calls to gfn.
- *
- * The return value of CVBBDPrecGet* is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  BBDPRE optional output extraction routines
+  -----------------------------------------------------------------
+  CVBBDPrecGetWorkSpace returns the BBDPRE real and integer work 
+                        space sizes.
+  CVBBDPrecGetNumGfnEvals returns the number of calls to gfn.
+ 
+  The return value of CVBBDPrecGet* is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP);
+SUNDIALS_EXPORT int CVBBDPrecGetWorkSpace(void *cvode_mem,
+                                          long int *lenrwLS,
+                                          long int *leniwLS);
+SUNDIALS_EXPORT int CVBBDPrecGetNumGfnEvals(void *cvode_mem,
+                                            long int *ngevalsBBDP);
 
 #ifdef __cplusplus
 }
diff --git a/include/cvode/cvode_dense.h b/include/cvode/cvode_dense.h
deleted file mode 100644
index d9636f5..0000000
--- a/include/cvode/cvode_dense.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODE dense linear solver, CVDENSE.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVDENSE_H
-#define _CVDENSE_H
-
-#include <cvode/cvode_direct.h>
-#include <sundials/sundials_dense.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function: CVDense
- * -----------------------------------------------------------------
- * A call to the CVDense function links the main integrator with
- * the CVDENSE linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * The return value of CVDense is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the cvode memory was NULL
- *    CVDLS_MEM_FAIL  if there was a memory allocation failure
- *    CVDLS_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDense(void *cvode_mem, long int N);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_diag.h b/include/cvode/cvode_diag.h
index e3d1ba9..5db6e52 100644
--- a/include/cvode/cvode_diag.h
+++ b/include/cvode/cvode_diag.h
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
diff --git a/include/cvode/cvode_direct.h b/include/cvode/cvode_direct.h
index 79e96e4..f4e1d37 100644
--- a/include/cvode/cvode_direct.h
+++ b/include/cvode/cvode_direct.h
@@ -1,45 +1,44 @@
-/*
+/* ----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common header file for the direct linear solvers in CVODE.
- * -----------------------------------------------------------------
- */
+ * Common header file for the direct linear solver interface in 
+ * CVODE.
+ * -----------------------------------------------------------------*/
 
 #ifndef _CVDLS_H
 #define _CVDLS_H
 
 #include <sundials/sundials_direct.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_linearsolver.h>
 #include <sundials/sundials_nvector.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * =================================================================
- *              C V D I R E C T     C O N S T A N T S
- * =================================================================
- */
+/*=================================================================
+  CVDLS Constants
+  =================================================================*/
 
-/* 
- * -----------------------------------------------------------------
- * CVDLS return values 
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  return values 
+  -----------------------------------------------------------------*/
 
 #define CVDLS_SUCCESS           0
 #define CVDLS_MEM_NULL         -1
@@ -51,235 +50,135 @@ extern "C" {
 
 #define CVDLS_JACFUNC_UNRECVR  -5
 #define CVDLS_JACFUNC_RECVR    -6
-
-/*
- * =================================================================
- *              F U N C T I O N   T Y P E S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Type: CVDlsDenseJacFn
- * -----------------------------------------------------------------
- *
- * A dense Jacobian approximation function Jac must be of type 
- * CVDlsDenseJacFn. Its parameters are:
- *
- * N   is the problem size.
- *
- * Jac is the dense matrix (of type DlsMat) that will be loaded
- *     by a CVDlsDenseJacFn with an approximation to the Jacobian 
- *     matrix J = (df_i/dy_j) at the point (t,y). 
- *
- * t   is the current value of the independent variable.
- *
- * y   is the current value of the dependent variable vector,
- *     namely the predicted value of y(t).
- *
- * fy  is the vector f(t,y).
- *
- * user_data is a pointer to user data - the same as the user_data
- *     parameter passed to CVodeSetFdata.
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated for
- * vectors of length N which can be used by a CVDlsDenseJacFn
- * as temporary storage or work space.
- *
- * A CVDlsDenseJacFn should return 0 if successful, a positive 
- * value if a recoverable error occurred, and a negative value if 
- * an unrecoverable error occurred.
- *
- * -----------------------------------------------------------------
- *
- * NOTE: The following are two efficient ways to load a dense Jac:         
- * (1) (with macros - no explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = DENSE_COL(Jac,j);                                 
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * (2) (without macros - explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = (Jac->data)[j];                                   
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * A third way, using the DENSE_ELEM(A,i,j) macro, is much less   
- * efficient in general.  It is only appropriate for use in small 
- * problems in which efficiency of access is NOT a major concern. 
- *                                                                
- * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     CVodeGetCurrentStep and CVodeGetErrWeights, respectively 
- *     (see cvode.h). The unit roundoff is available as 
- *     UNIT_ROUNDOFF defined in sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
+#define CVDLS_SUNMAT_FAIL      -7
   
+/*=================================================================
+  Function Types
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Type: CVDlsJacFn
+  -----------------------------------------------------------------
+ 
+  A Jacobian approximation function Jac must be of type CVDlsJacFn.
+  Its parameters are:
+ 
+  Jac is the SUNMatrix matrix that will be loaded by a CVDlsJacFn 
+  with an approximation to the Jacobian 
+      matrix J = (df_i/dy_j) at the point (t,y). 
+ 
+  t   is the current value of the independent variable.
+ 
+  y   is the current value of the dependent variable vector,
+      namely the predicted value of y(t).
+ 
+  fy  is the vector f(t,y).
+ 
+  user_data is a pointer to user data - the same as the user_data
+      parameter passed to CVodeSetUserdata.
+ 
+  tmp1, tmp2, and tmp3 are pointers to memory allocated for
+  vectors of length N which can be used by a CVDlsJacFn
+  as temporary storage or work space.
+ 
+  A CVDlsJacFn should return 0 if successful, a positive 
+  value if a recoverable error occurred, and a negative value if 
+  an unrecoverable error occurred.
+ 
+  -----------------------------------------------------------------
+ 
+  NOTE: See the relevant SUNMatrix implementation header files and
+      documentation for mechanisms to inquire about matrix 
+      dimensions, and for efficient ways to set matrix entries.
+                                                                 
+  NOTE: If the user's Jacobian routine needs other quantities,   
+      they are accessible as follows: hcur (the current stepsize)
+      and ewt (the error weight vector) are accessible through   
+      CVodeGetCurrentStep and CVodeGetErrWeights, respectively 
+      (see cvode.h). The unit roundoff is available as 
+      UNIT_ROUNDOFF defined in sundials_types.h.
+ 
+  -----------------------------------------------------------------*/
+typedef int (*CVDlsJacFn)(realtype t, N_Vector y, N_Vector fy, 
+                          SUNMatrix Jac, void *user_data,
+                          N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+
   
-typedef int (*CVDlsDenseJacFn)(long int N, realtype t,
-			       N_Vector y, N_Vector fy, 
-			       DlsMat Jac, void *user_data,
-			       N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+/*=================================================================
+  Exported Functions
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Required inputs to the CVDLS linear solver interface
+  -----------------------------------------------------------------
+ 
+  CVDlsSetLinearSolver specifies the direct SUNLinearSolver object
+  that should be used.  This is required if CVode is solving a 
+  problem using the Newton nonlinear solver (not the function 
+  iteration).
+ 
+  The return value is one of:
+     CVDLS_SUCCESS   if successful
+     CVDLS_MEM_NULL  if the CVODE memory was NULL
+     CVDLS_MEM_FAIL  if the a memory allocation request failed
+     CVDLS_ILL_INPUT if the arguments are incompatible
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVDlsSetLinearSolver(void *cvode_mem, 
+                                         SUNLinearSolver LS,
+                                         SUNMatrix A);
   
-/*
- * -----------------------------------------------------------------
- * Type: CVDlsBandJacFn
- * -----------------------------------------------------------------
- *
- * A band Jacobian approximation function Jac must have the
- * prototype given below. Its parameters are:
- *
- * N is the length of all vector arguments.
- *
- * mupper is the upper half-bandwidth of the approximate banded
- * Jacobian. This parameter is the same as the mupper parameter
- * passed by the user to the linear solver initialization function.
- *
- * mlower is the lower half-bandwidth of the approximate banded
- * Jacobian. This parameter is the same as the mlower parameter
- * passed by the user to the linear solver initialization function.
- *
- * t is the current value of the independent variable.
- *
- * y is the current value of the dependent variable vector,
- *      namely the predicted value of y(t).
- *
- * fy is the vector f(t,y).
- *
- * Jac is the band matrix (of type DlsMat) that will be loaded
- * by a CVDlsBandJacFn with an approximation to the Jacobian matrix
- * Jac = (df_i/dy_j) at the point (t,y).
- * Three efficient ways to load J are:
- *
- * (1) (with macros - no explicit data structure references)
- *    for (j=0; j < n; j++) {
- *       col_j = BAND_COL(Jac,j);
- *       for (i=j-mupper; i <= j+mlower; i++) {
- *         generate J_ij = the (i,j)th Jacobian element
- *         BAND_COL_ELEM(col_j,i,j) = J_ij;
- *       }
- *     }
- *
- * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro)
- *    for (j=0; j < n; j++) {
- *       col_j = BAND_COL(Jac,j);
- *       for (k=-mupper; k <= mlower; k++) {
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k
- *         col_j[k] = J_ij;
- *       }
- *     }
- *
- * (3) (without macros - explicit data structure references)
- *     offset = Jac->smu;
- *     for (j=0; j < n; j++) {
- *       col_j = ((Jac->data)[j])+offset;
- *       for (k=-mupper; k <= mlower; k++) {
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k
- *         col_j[k] = J_ij;
- *       }
- *     }
- * Caution: Jac->smu is generally NOT the same as mupper.
- *
- * The BAND_ELEM(A,i,j) macro is appropriate for use in small
- * problems in which efficiency of access is NOT a major concern.
- *
- * user_data is a pointer to user data - the same as the user_data
- *          parameter passed to CVodeSetFdata.
- *
- * NOTE: If the user's Jacobian routine needs other quantities,
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through
- *     CVodeGetCurrentStep and CVodeGetErrWeights, respectively
- *     (see cvode.h). The unit roundoff is available as
- *     UNIT_ROUNDOFF defined in sundials_types.h
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated for
- * vectors of length N which can be used by a CVDlsBandJacFn
- * as temporary storage or work space.
- *
- * A CVDlsBandJacFn should return 0 if successful, a positive value
- * if a recoverable error occurred, and a negative value if an 
- * unrecoverable error occurred.
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVDlsBandJacFn)(long int N, long int mupper, long int mlower,
-			      realtype t, N_Vector y, N_Vector fy, 
-			      DlsMat Jac, void *user_data,
-			      N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the CVDLS linear solver
- * -----------------------------------------------------------------
- *
- * CVDlsSetDenseJacFn specifies the dense Jacobian approximation
- * routine to be used for a direct dense linear solver.
- *
- * CVDlsSetBandJacFn specifies the band Jacobian approximation
- * routine to be used for a direct band linear solver.
- *
- * By default, a difference quotient approximation, supplied with
- * the solver is used.
- *
- * The return value is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the CVODE memory was NULL
- *    CVDLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac);
-SUNDIALS_EXPORT int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the CVDLS linear solver
- * -----------------------------------------------------------------
- *
- * CVDlsGetWorkSpace   returns the real and integer workspace used
- *                     by the direct linear solver.
- * CVDlsGetNumJacEvals returns the number of calls made to the
- *                     Jacobian evaluation routine jac.
- * CVDlsGetNumRhsEvals returns the number of calls to the user
- *                     f routine due to finite difference Jacobian
- *                     evaluation.
- * CVDlsGetLastFlag    returns the last error flag set by any of
- *                     the CVDLS interface functions.
- *
- * The return value of CVDlsGet* is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the CVODE memory was NULL
- *    CVDLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals);
-SUNDIALS_EXPORT int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS);
-SUNDIALS_EXPORT int CVDlsGetLastFlag(void *cvode_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a CVDLS return flag
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  Optional inputs to the CVDLS linear solver
+  -----------------------------------------------------------------
+ 
+  CVDlsSetJacFn specifies the dense/band/sparse Jacobian
+  approximation routine to be used for a direct linear solver.
+  By default, a difference quotient approximation is used for 
+  dense/band; no default exists for sparse (so this must 
+  be user-supplied).
+ 
+  The return value is one of:
+     CVDLS_SUCCESS   if successful
+     CVDLS_MEM_NULL  if the CVODE memory was NULL
+     CVDLS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVDlsSetJacFn(void *cvode_mem, CVDlsJacFn jac);
+
+/*-----------------------------------------------------------------
+  Optional outputs from the CVDLS linear solver interface
+  -----------------------------------------------------------------
+ 
+  CVDlsGetWorkSpace   returns the real and integer workspace used
+                      by the direct linear solver.
+  CVDlsGetNumJacEvals returns the number of calls made to the
+                      Jacobian evaluation routine jac.
+  CVDlsGetNumRhsEvals returns the number of calls to the user
+                      f routine due to finite difference Jacobian
+                      evaluation.
+  CVDlsGetLastFlag    returns the last error flag set by any of
+                      the CVDLS interface functions.
+ 
+  The return value of CVDlsGet* is one of:
+     CVDLS_SUCCESS   if successful
+     CVDLS_MEM_NULL  if the CVODE memory was NULL
+     CVDLS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+
+SUNDIALS_EXPORT int CVDlsGetWorkSpace(void *cvode_mem,
+                                      long int *lenrwLS,
+                                      long int *leniwLS);
+SUNDIALS_EXPORT int CVDlsGetNumJacEvals(void *cvode_mem,
+                                        long int *njevals);
+SUNDIALS_EXPORT int CVDlsGetNumRhsEvals(void *cvode_mem,
+                                        long int *nfevalsLS);
+SUNDIALS_EXPORT int CVDlsGetLastFlag(void *cvode_mem,
+                                     long int *flag);
+
+/*-----------------------------------------------------------------
+  The following function returns the name of the constant 
+  associated with a CVDLS return flag
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT char *CVDlsGetReturnFlagName(long int flag);
 
 
diff --git a/include/cvode/cvode_klu.h b/include/cvode/cvode_klu.h
deleted file mode 100644
index f0259d5..0000000
--- a/include/cvode/cvode_klu.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVKLU linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVKLU_H
-#define _CVKLU_H
-
-#include "cvode/cvode_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVKLU
- * -----------------------------------------------------------------
- * A call to the CVKLU function links the main integrator      
- * with the CVKLU linear solver module.                        
- *                                                                
- * cv_mem is the pointer to integrator memory returned by        
- *     CVCreate.             
- *
- *                                                                
- * CVKLU returns:                                              
- *     CVSLU_SUCCESS   = 0  if successful                              
- *     CVSLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     CVSLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The KLU linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, CVKLU will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLU(void *cv_mem, int n, int nnz, int sparsetype); 
-
-/*
- * -----------------------------------------------------------------
- * CVKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to CVKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is CVSLS_SUCCESS = 0, CVSLS_MEM_NULL = -1,
- * CVSLS_LMEM_NULL = -2, CVSLS_ILL_INPUT = -3, or CVSLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLUReInit(void *cv_mem_v, int n, int nnz, 
-				  int reinit_type);
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in CVODE is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLUSetOrdering(void *cv_mem, int ordering_choice); 
-
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_lapack.h b/include/cvode/cvode_lapack.h
deleted file mode 100644
index 96495a5..0000000
--- a/include/cvode/cvode_lapack.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Header file for the CVODE dense linear solver CVLAPACK.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVLAPACK_H
-#define _CVLAPACK_H
-
-#include <cvode/cvode_direct.h>
-#include <sundials/sundials_lapack.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Function : CVLapackDense
- * -----------------------------------------------------------------
- * A call to the CVLapackDense function links the main integrator
- * with the CVLAPACK linear solver using dense Jacobians.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * The return value of CVLapackDense is one of:
- *    CVLAPACK_SUCCESS   if successful
- *    CVLAPACK_MEM_NULL  if the CVODE memory was NULL
- *    CVLAPACK_MEM_FAIL  if there was a memory allocation failure
- *    CVLAPACK_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVLapackDense(void *cvode_mem, int N);
-
-/*
- * -----------------------------------------------------------------
- * Function : CVLapackBand
- * -----------------------------------------------------------------
- * A call to the CVLapackBand function links the main integrator
- * with the CVLAPACK linear solver using banded Jacobians. 
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * mupper is the upper bandwidth of the band Jacobian approximation.
- *
- * mlower is the lower bandwidth of the band Jacobian approximation.
- *
- * The return value of CVLapackBand is one of:
- *    CVLAPACK_SUCCESS   if successful
- *    CVLAPACK_MEM_NULL  if the CVODE memory was NULL
- *    CVLAPACK_MEM_FAIL  if there was a memory allocation failure
- *    CVLAPACK_ILL_INPUT if a required vector operation is missing or
- *                       if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_sparse.h b/include/cvode/cvode_sparse.h
deleted file mode 100644
index a4a1511..0000000
--- a/include/cvode/cvode_sparse.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the Sparse linear solver module in IDA.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSPARSE_H
-#define _CVSPARSE_H
-
-#include <sundials/sundials_sparse.h>
-#include <sundials/sundials_nvector.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * C V S P A R S E    C O N S T A N T S
- * =================================================================
- */
-
-/* 
- * -----------------------------------------------------------------
- * CVSLS return values 
- * -----------------------------------------------------------------
- */
-
-#define CVSLS_SUCCESS           0
-#define CVSLS_MEM_NULL         -1
-#define CVSLS_LMEM_NULL        -2
-#define CVSLS_ILL_INPUT        -3
-#define CVSLS_MEM_FAIL         -4
-#define CVSLS_JAC_NOSET        -5
-#define CVSLS_PACKAGE_FAIL     -6
-
-/* Additional last_flag values */
-
-#define CVSLS_JACFUNC_UNRECVR  -7
-#define CVSLS_JACFUNC_RECVR    -8
-
-/* Return values for the adjoint module */
-#define CVSLS_NO_ADJ           -101
-#define CVSLS_LMEMB_NULL       -102
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : CVSlsSparseJacFn
- * -----------------------------------------------------------------
- *
- * A sparse Jacobian approximation function jac must be of type 
- * CVSlsSparseJacFn.
- * Its parameters are:                     
- *                                                                
- * t   is the current value of the independent variable t.        
- *                                                                
- * y   is the current value of the dependent variable vector,     
- *     namely the predicted value of y(t).                     
- *                                                                
- * fy  is the vector f(t,y).
- *     namely the predicted value of y'(t).                    
- *                                                                
- * JacMat is the compressed sparse column matrix (of type SlsMat)
- *     to be loaded by an CVSlsSparseJacFn routine with an approximation
- *     to the system Jacobian matrix
- *            J = J = (df_i/dy_j) at the point (t,y). 
- *     Note that JacMat is NOT preset to zero!
- *     Matrix data is for the nonzero entries of the Jacobian stored in
- *     compressed column format.  Row indices of entries in 
- *     column j are stored in J->rowvals[colptrs[j]] 
- *     through J->rowvals[colptrs[j+i]-1]
- *     and corresponding numerical values of the Jacobian are stored 
- *     in the same entries of J->data.
- * 
- * J_data is a pointer to user Jacobian data - the same as the    
- *     user_data parameter passed to CVodeSetFdata.                     
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an CVSparseJacFn routine 
- *     as temporary storage or work space.                     
- *                                                                
- * A CVSlsSparseJacFn should return                                
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- *
- * -----------------------------------------------------------------
- *
-  * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     CVodeGetCurrentStep and CVodeGetErrWeights, respectively 
- *     (see cvode.h). The unit roundoff is available as 
- *     UNIT_ROUNDOFF defined in sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
-  
-  
-typedef int (*CVSlsSparseJacFn)(realtype t,
-		     N_Vector y, N_Vector fy, 
-		     SlsMat JacMat, void *user_data,
-		     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the CVSPARSE linear solver
- * -----------------------------------------------------------------
- * CVSlsSetSparseJacFn specifies the Jacobian approximation
- * routine to be used for a sparse direct linear solver.
- *
- * The return value is one of:
- *    CVSLS_SUCCESS   if successful
- *    CVSLS_MEM_NULL  if the CVODE memory was NULL
- *    CVSLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSlsSetSparseJacFn(void *cvode_mem, CVSlsSparseJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the CVSLS linear solver
- * -----------------------------------------------------------------
- *
- * CVSlsGetNumJacEvals returns the number of calls made to the
- *                      Jacobian evaluation routine jac.
- * CVSlsGetLastFlag    returns the last error flag set by any of
- *                      the IDADLS interface functions.
- *
- * The return value of IDADlsGet* is one of:
- *    CVSLS_SUCCESS   if successful
- *    CVSLS_MEM_NULL  if the IDA memory was NULL
- *    CVSLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSlsGetNumJacEvals(void *ida_mem, long int *njevals);
-SUNDIALS_EXPORT int CVSlsGetLastFlag(void *ida_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a CVSLS return flag
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT char *CVSlsGetReturnFlagName(long int flag);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_spbcgs.h b/include/cvode/cvode_spbcgs.h
deleted file mode 100644
index f6c1714..0000000
--- a/include/cvode/cvode_spbcgs.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODE scaled preconditioned 
- * Bi-CGSTAB linear solver, CVSPBCG.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSPBCG_H
-#define _CVSPBCG_H
-
-#include <cvode/cvode_spils.h>
-#include <sundials/sundials_spbcgs.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcg
- * -----------------------------------------------------------------
- * A call to the CVSpbcg function links the main CVODE integrator
- * with the CVSPBCG linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * pretype   is the type of user preconditioning to be done.
- *           This must be one of the four enumeration constants
- *           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
- *           in iterative.h. These correspond to no preconditioning,
- *           left preconditioning only, right preconditioning
- *           only, and both left and right preconditioning,
- *           respectively.
- *
- * maxl      is the maximum Krylov dimension. This is an
- *           optional input to the CVSPBCG solver. Pass 0 to
- *           use the default value CVSPBCG_MAXL=5.
- *
- * The return value of CVSpbcg is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_MEM_FAIL  if there was a memory allocation failure
- *    CVSPILS_ILL_INPUT if a required vector operation is missing
- * The above constants are defined in cvode_spils.h
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpbcg(void *cvode_mem, int pretype, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_spgmr.h b/include/cvode/cvode_spgmr.h
deleted file mode 100644
index 10c05a1..0000000
--- a/include/cvode/cvode_spgmr.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODE scaled preconditioned GMRES 
- * linear solver, CVSPGMR.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSPGMR_H
-#define _CVSPGMR_H
-
-#include <cvode/cvode_spils.h>
-#include <sundials/sundials_spgmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpgmr
- * -----------------------------------------------------------------
- * A call to the CVSpgmr function links the main CVODE integrator
- * with the CVSPGMR linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * pretype   is the type of user preconditioning to be done.
- *           This must be one of the four enumeration constants
- *           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined 
- *           in sundials_iterative.h.
- *           These correspond to no preconditioning,
- *           left preconditioning only, right preconditioning
- *           only, and both left and right preconditioning,
- *           respectively.
- *
- * maxl      is the maximum Krylov dimension. This is an
- *           optional input to the CVSPGMR solver. Pass 0 to
- *           use the default value CVSPGMR_MAXL=5.
- *
- * The return value of CVSpgmr is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_MEM_FAIL  if there was a memory allocation failure
- *    CVSPILS_ILL_INPUT if a required vector operation is missing
- * The above constants are defined in cvode_spils.h
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpgmr(void *cvode_mem, int pretype, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_spils.h b/include/cvode/cvode_spils.h
index 9207b5b..cb4e785 100644
--- a/include/cvode/cvode_spils.h
+++ b/include/cvode/cvode_spils.h
@@ -1,42 +1,40 @@
-/*
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *     Scott D. Cohen, Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the common header file for the Scaled, Preconditioned
- * Iterative Linear Solvers in CVODE.
- * -----------------------------------------------------------------
- */
+ * This is the header file for the Scaled, Preconditioned Iterative 
+ * Linear Solver interface in CVODE.
+ * -----------------------------------------------------------------*/
 
 #ifndef _CVSPILS_H
 #define _CVSPILS_H
 
 #include <sundials/sundials_iterative.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_linearsolver.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
 
-/*
- * -----------------------------------------------------------------
- * CVSPILS return values 
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVSPILS return values 
+  -----------------------------------------------------------------*/
 
 #define CVSPILS_SUCCESS          0
 #define CVSPILS_MEM_NULL        -1
@@ -44,323 +42,353 @@ extern "C" {
 #define CVSPILS_ILL_INPUT       -3
 #define CVSPILS_MEM_FAIL        -4
 #define CVSPILS_PMEM_NULL       -5
+#define CVSPILS_SUNLS_FAIL      -6
 
-/*
- * -----------------------------------------------------------------
- * CVSPILS solver constants
- * -----------------------------------------------------------------
- * CVSPILS_MAXL   : default value for the maximum Krylov
- *                  dimension
- *
- * CVSPILS_MSBPRE : maximum number of steps between
- *                  preconditioner evaluations
- *
- * CVSPILS_DGMAX  : maximum change in gamma between
- *                  preconditioner evaluations
- *
- * CVSPILS_EPLIN  : default value for factor by which the
- *                  tolerance on the nonlinear iteration is
- *                  multiplied to get a tolerance on the linear
- *                  iteration
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVSPILS solver constants
+  -----------------------------------------------------------------
+  CVSPILS_MSBPRE : maximum number of steps between
+                   preconditioner evaluations
+ 
+  CVSPILS_DGMAX  : maximum change in gamma between
+                   preconditioner evaluations
+ 
+  CVSPILS_EPLIN  : default value for factor by which the
+                   tolerance on the nonlinear iteration is
+                   multiplied to get a tolerance on the linear
+                   iteration
+  -----------------------------------------------------------------*/
 
-#define CVSPILS_MAXL   5
 #define CVSPILS_MSBPRE 50
 #define CVSPILS_DGMAX  RCONST(0.2)
 #define CVSPILS_EPLIN  RCONST(0.05)
 
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSetupFn
- * -----------------------------------------------------------------
- * The user-supplied preconditioner setup function PrecSetup and
- * the user-supplied preconditioner solve function PrecSolve
- * together must define left and right preconditoner matrices
- * P1 and P2 (either of which may be trivial), such that the
- * product P1*P2 is an approximation to the Newton matrix
- * M = I - gamma*J.  Here J is the system Jacobian J = df/dy,
- * and gamma is a scalar proportional to the integration step
- * size h.  The solution of systems P z = r, with P = P1 or P2,
- * is to be carried out by the PrecSolve function, and PrecSetup
- * is to do any necessary setup operations.
- *
- * The user-supplied preconditioner setup function PrecSetup
- * is to evaluate and preprocess any Jacobian-related data
- * needed by the preconditioner solve function PrecSolve.
- * This might include forming a crude approximate Jacobian,
- * and performing an LU factorization on the resulting
- * approximation to M.  This function will not be called in
- * advance of every call to PrecSolve, but instead will be called
- * only as often as necessary to achieve convergence within the
- * Newton iteration.  If the PrecSolve function needs no
- * preparation, the PrecSetup function can be NULL.
- *
- * For greater efficiency, the PrecSetup function may save
- * Jacobian-related data and reuse it, rather than generating it
- * from scratch.  In this case, it should use the input flag jok
- * to decide whether to recompute the data, and set the output
- * flag *jcurPtr accordingly.
- *
- * Each call to the PrecSetup function is preceded by a call to
- * the RhsFn f with the same (t,y) arguments.  Thus the PrecSetup
- * function can use any auxiliary data that is computed and
- * saved by the f function and made accessible to PrecSetup.
- *
- * A function PrecSetup must have the prototype given below.
- * Its parameters are as follows:
- *
- * t       is the current value of the independent variable.
- *
- * y       is the current value of the dependent variable vector,
- *          namely the predicted value of y(t).
- *
- * fy      is the vector f(t,y).
- *
- * jok     is an input flag indicating whether Jacobian-related
- *         data needs to be recomputed, as follows:
- *           jok == FALSE means recompute Jacobian-related data
- *                  from scratch.
- *           jok == TRUE  means that Jacobian data, if saved from
- *                  the previous PrecSetup call, can be reused
- *                  (with the current value of gamma).
- *         A Precset call with jok == TRUE can only occur after
- *         a call with jok == FALSE.
- *
- * jcurPtr is a pointer to an output integer flag which is
- *         to be set by PrecSetup as follows:
- *         Set *jcurPtr = TRUE if Jacobian data was recomputed.
- *         Set *jcurPtr = FALSE if Jacobian data was not recomputed,
- *                        but saved data was reused.
- *
- * gamma   is the scalar appearing in the Newton matrix.
- *
- * user_data  is a pointer to user data - the same as the user_data
- *         parameter passed to the CVodeSetUserData function.
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated
- *                      for N_Vectors which can be used by
- *                      CVSpilsPrecSetupFn as temporary storage or
- *                      work space.
- *
- * NOTE: If the user's preconditioner needs other quantities,
- *       they are accessible as follows: hcur (the current stepsize)
- *       and ewt (the error weight vector) are accessible through
- *       CVodeGetCurrentStep and CVodeGetErrWeights, respectively).
- *       The unit roundoff is available as UNIT_ROUNDOFF defined in
- *       sundials_types.h.
- *
- * Returned value:
- * The value to be returned by the PrecSetup function is a flag
- * indicating whether it was successful.  This value should be
- *   0   if successful,
- *   > 0 for a recoverable error (step will be retried),
- *   < 0 for an unrecoverable error (integration is halted).
- * -----------------------------------------------------------------
- */
 
+/*===============================================================
+  CVSPILS user-supplied function prototypes
+  ===============================================================*/
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsPrecSetupFn
+  -----------------------------------------------------------------
+  The user-supplied preconditioner setup function PrecSetup and
+  the user-supplied preconditioner solve function PrecSolve
+  together must define left and right preconditoner matrices
+  P1 and P2 (either of which may be trivial), such that the
+  product P1*P2 is an approximation to the Newton matrix
+  M = I - gamma*J.  Here J is the system Jacobian J = df/dy,
+  and gamma is a scalar proportional to the integration step
+  size h.  The solution of systems P z = r, with P = P1 or P2,
+  is to be carried out by the PrecSolve function, and PrecSetup
+  is to do any necessary setup operations.
+ 
+  The user-supplied preconditioner setup function PrecSetup
+  is to evaluate and preprocess any Jacobian-related data
+  needed by the preconditioner solve function PrecSolve.
+  This might include forming a crude approximate Jacobian,
+  and performing an LU factorization on the resulting
+  approximation to M.  This function will not be called in
+  advance of every call to PrecSolve, but instead will be called
+  only as often as necessary to achieve convergence within the
+  Inexact Newton iteration.  If the PrecSolve function needs no
+  preparation, the PrecSetup function can be NULL.
+ 
+  For greater efficiency, the PrecSetup function may save
+  Jacobian-related data and reuse it, rather than generating it
+  from scratch.  In this case, it should use the input flag jok
+  to decide whether to recompute the data, and set the output
+  flag *jcurPtr accordingly.
+ 
+  Each call to the PrecSetup function is preceded by a call to
+  the RhsFn f with the same (t,y) arguments.  Thus the PrecSetup
+  function can use any auxiliary data that is computed and
+  saved by the f function and made accessible to PrecSetup.
+ 
+  A function PrecSetup must have the prototype given below.
+  Its parameters are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+           namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  jok     is an input flag indicating whether Jacobian-related
+          data needs to be recomputed, as follows:
+            jok == SUNFALSE means recompute Jacobian-related data
+                   from scratch.
+            jok == SUNTRUE  means that Jacobian data, if saved from
+                   the previous PrecSetup call, can be reused
+                   (with the current value of gamma).
+          A Precset call with jok == SUNTRUE can only occur after
+          a call with jok == SUNFALSE.
+ 
+  jcurPtr is a pointer to an output integer flag which is
+          to be set by PrecSetup as follows:
+          Set *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+          Set *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
+                         but saved data was reused.
+ 
+  gamma   is the scalar appearing in the Newton matrix.
+ 
+  user_data  is a pointer to user data - the same as the user_data
+          parameter passed to the CVodeSetUserData function.
+ 
+  NOTE: If the user's preconditioner needs other quantities,
+        they are accessible as follows: hcur (the current stepsize)
+        and ewt (the error weight vector) are accessible through
+        CVodeGetCurrentStep and CVodeGetErrWeights, respectively).
+        The unit roundoff is available as UNIT_ROUNDOFF defined in
+        sundials_types.h.
+ 
+  Returned value:
+  The value to be returned by the PrecSetup function is a flag
+  indicating whether it was successful.  This value should be
+    0   if successful,
+    > 0 for a recoverable error (step will be retried),
+    < 0 for an unrecoverable error (integration is halted).
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsPrecSetupFn)(realtype t, N_Vector y, N_Vector fy,
                                   booleantype jok, booleantype *jcurPtr,
-                                  realtype gamma, void *user_data,
-                                  N_Vector tmp1, N_Vector tmp2,
-                                  N_Vector tmp3);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSolveFn
- * -----------------------------------------------------------------
- * The user-supplied preconditioner solve function PrecSolve
- * is to solve a linear system P z = r in which the matrix P is
- * one of the preconditioner matrices P1 or P2, depending on the
- * type of preconditioning chosen.
- *
- * A function PrecSolve must have the prototype given below.
- * Its parameters are as follows:
- *
- * t      is the current value of the independent variable.
- *
- * y      is the current value of the dependent variable vector.
- *
- * fy     is the vector f(t,y).
- *
- * r      is the right-hand side vector of the linear system.
- *
- * z      is the output vector computed by PrecSolve.
- *
- * gamma  is the scalar appearing in the Newton matrix.
- *
- * delta  is an input tolerance for use by PSolve if it uses
- *        an iterative method in its solution.  In that case,
- *        the residual vector Res = r - P z of the system
- *        should be made less than delta in weighted L2 norm,
- *        i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta.
- *        Note: the error weight vector ewt can be obtained
- *        through a call to the routine CVodeGetErrWeights.
- *
- * lr     is an input flag indicating whether PrecSolve is to use
- *        the left preconditioner P1 or right preconditioner
- *        P2: lr = 1 means use P1, and lr = 2 means use P2.
- *
- * user_data  is a pointer to user data - the same as the user_data
- *         parameter passed to the CVodeSetUserData function.
- *
- * tmp    is a pointer to memory allocated for an N_Vector
- *        which can be used by PSolve for work space.
- *
- * Returned value:
- * The value to be returned by the PrecSolve function is a flag
- * indicating whether it was successful.  This value should be
- *   0 if successful,
- *   positive for a recoverable error (step will be retried),
- *   negative for an unrecoverable error (integration is halted).
- * -----------------------------------------------------------------
- */
+                                  realtype gamma, void *user_data);
 
+/*-----------------------------------------------------------------
+  Type : CVSpilsPrecSolveFn
+  -----------------------------------------------------------------
+  The user-supplied preconditioner solve function PrecSolve
+  is to solve a linear system P z = r in which the matrix P is
+  one of the preconditioner matrices P1 or P2, depending on the
+  type of preconditioning chosen.
+ 
+  A function PrecSolve must have the prototype given below.
+  Its parameters are as follows:
+ 
+  t      is the current value of the independent variable.
+ 
+  y      is the current value of the dependent variable vector.
+ 
+  fy     is the vector f(t,y).
+ 
+  r      is the right-hand side vector of the linear system.
+ 
+  z      is the output vector computed by PrecSolve.
+ 
+  gamma  is the scalar appearing in the Newton matrix.
+ 
+  delta  is an input tolerance for use by PSolve if it uses
+         an iterative method in its solution.  In that case,
+         the residual vector Res = r - P z of the system
+         should be made less than delta in weighted L2 norm,
+         i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta.
+         Note: the error weight vector ewt can be obtained
+         through a call to the routine CVodeGetErrWeights.
+ 
+  lr     is an input flag indicating whether PrecSolve is to use
+         the left preconditioner P1 or right preconditioner
+         P2: lr = 1 means use P1, and lr = 2 means use P2.
+ 
+  user_data  is a pointer to user data - the same as the user_data
+          parameter passed to the CVodeSetUserData function.
+ 
+  Returned value:
+  The value to be returned by the PrecSolve function is a flag
+  indicating whether it was successful.  This value should be
+    0 if successful,
+    positive for a recoverable error (step will be retried),
+    negative for an unrecoverable error (integration is halted).
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsPrecSolveFn)(realtype t, N_Vector y, N_Vector fy,
-                                  N_Vector r, N_Vector z,
-                                  realtype gamma, realtype delta,
-                                  int lr, void *user_data, N_Vector tmp);
+                                  N_Vector r, N_Vector z, realtype gamma, 
+                                  realtype delta, int lr, void *user_data);
 
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsJacTimesVecFn
- * -----------------------------------------------------------------
- * The user-supplied function jtimes is to generate the product
- * J*v for given v, where J is the Jacobian df/dy, or an
- * approximation to it, and v is a given vector. It should return
- * 0 if successful a positive value for a recoverable error or 
- * a negative value for an unrecoverable failure.
- *
- * A function jtimes must have the prototype given below. Its
- * parameters are as follows:
- *
- *   v        is the N_Vector to be multiplied by J.
- *
- *   Jv       is the output N_Vector containing J*v.
- *
- *   t        is the current value of the independent variable.
- *
- *   y        is the current value of the dependent variable
- *            vector.
- *
- *   fy       is the vector f(t,y).
- *
- *   user_data   is a pointer to user data, the same as the user_data
- *            parameter passed to the CVodeSetUserData function.
- *
- *   tmp      is a pointer to memory allocated for an N_Vector
- *            which can be used by Jtimes for work space.
- * -----------------------------------------------------------------
- */
+/*---------------------------------------------------------------
+  Type: CVSpilsJacTimesSetupFn
+ 
+  The user-supplied Jacobian-times-vector product setup function 
+  JacTimesSetup and the user-supplied Jacobian-times-vector 
+  product function JTimes together must generate the product
+  J*v for v, where J is the Jacobian df/dy, or an approximation 
+  to it, and v is a given vector. 
+ 
+  Each call to the JacTimesSetup function is preceded by a call 
+  to the RhsFn fi with the same (t,y) arguments.  Thus the 
+  JacTimesSetup function can use any auxiliary data that is 
+  computed and saved by the f function and made accessible to 
+  JacTimesSetup.
+ 
+  A function JacTimesSetup must have the prototype given below.
+  Its parameters are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+           namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  user_data  is a pointer to user data - the same as the user_data
+          parameter passed to the CVodeSetUserData function.
+ 
+  Returned value:
+  The value to be returned by the JacTimesSetup function is a flag
+  indicating whether it was successful.  This value should be
+    0   if successful,
+    > 0 for a recoverable error (step will be retried),
+    < 0 for an unrecoverable error (integration is halted).
+  ---------------------------------------------------------------*/
+typedef int (*CVSpilsJacTimesSetupFn)(realtype t, N_Vector y, 
+                                      N_Vector fy, void *user_data);
 
+  
+/*-----------------------------------------------------------------
+  Type : CVSpilsJacTimesVecFn
+  -----------------------------------------------------------------
+  The user-supplied function jtimes is to generate the product
+  J*v for given v, where J is the Jacobian df/dy, or an
+  approximation to it, and v is a given vector. It should return
+  0 if successful a positive value for a recoverable error or 
+  a negative value for an unrecoverable failure.
+ 
+  A function jtimes must have the prototype given below. Its
+  parameters are as follows:
+ 
+    v        is the N_Vector to be multiplied by J.
+ 
+    Jv       is the output N_Vector containing J*v.
+ 
+    t        is the current value of the independent variable.
+ 
+    y        is the current value of the dependent variable
+             vector.
+ 
+    fy       is the vector f(t,y).
+ 
+    user_data   is a pointer to user data, the same as the user_data
+             parameter passed to the CVodeSetUserData function.
+ 
+    tmp      is a pointer to memory allocated for an N_Vector
+             which can be used by Jtimes for work space.
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t,
                                     N_Vector y, N_Vector fy,
                                     void *user_data, N_Vector tmp);
 
 
+/*=================================================================
+   CVSPILS Exported functions
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the CVSPILS linear solver
- * -----------------------------------------------------------------
- *
- * CVSpilsSetPrecType resets the type of preconditioner, pretype,
- *                from the value previously set.
- *                This must be one of PREC_NONE, PREC_LEFT, 
- *                PREC_RIGHT, or PREC_BOTH.
- *
- * CVSpilsSetGSType specifies the type of Gram-Schmidt
- *                orthogonalization to be used. This must be one of
- *                the two enumeration constants MODIFIED_GS or
- *                CLASSICAL_GS defined in iterative.h. These correspond
- *                to using modified Gram-Schmidt and classical
- *                Gram-Schmidt, respectively.
- *                Default value is MODIFIED_GS.
- *
- * CVSpilsSetMaxl resets the maximum Krylov subspace size, maxl,
- *                from the value previously set.
- *                An input value <= 0, gives the default value.
- *
- * CVSpilsSetEpsLin specifies the factor by which the tolerance on
- *                the nonlinear iteration is multiplied to get a
- *                tolerance on the linear iteration.
- *                Default value is 0.05.
- *
- * CVSpilsSetPreconditioner specifies the PrecSetup and PrecSolve functions.
- *                Default is NULL for both arguments (no preconditioning)
- *
- * CVSpilsSetJacTimesVecFn specifies the jtimes function. Default is to 
- *                use an internal finite difference approximation routine.
- *
- * The return value of CVSpilsSet* is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_LMEM_NULL if the linear solver memory was NULL
- *    CVSPILS_ILL_INPUT if an input has an illegal value
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Required inputs to the CVSPILS linear solver interface
+  -----------------------------------------------------------------
+ 
+  CVSpilsSetLinearSolver specifies the iterative SUNLinearSolver 
+  object that CVode should use.  This is required if CVode is 
+  solving a problem with the Newton nonlinear solver (i.e. not the 
+  functional iteration).
+ 
+  The return value is one of:
+     CVSPILS_SUCCESS   if successful
+     CVSPILS_MEM_NULL  if the CVODE memory was NULL
+     CVSPILS_MEM_FAIL  if the a memory allocation request failed
+     CVSPILS_ILL_INPUT if the linear solver memory was NULL
+ ---------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVSpilsSetLinearSolver(void *cvode_mem, 
+                                           SUNLinearSolver LS);
+
+  
+/*-----------------------------------------------------------------
+  Optional inputs to the CVSPILS linear solver
+  -----------------------------------------------------------------
+ 
+  CVSpilsSetEpsLin specifies the factor by which the tolerance on
+                 the nonlinear iteration is multiplied to get a
+                 tolerance on the linear iteration.
+                 Default value is 0.05.
+ 
+  CVSpilsSetPreconditioner specifies the PrecSetup and PrecSolve 
+                 functions.  Default is NULL for both arguments 
+                 (no preconditioning)
+ 
+  CVSpilsSetJacTimes specifies the jtsetup and jtimes functions. 
+                 Default is to use an internal finite difference 
+                 approximation routine with no extra jtsetup.
+ 
+  The return value of CVSpilsSet* is one of:
+     CVSPILS_SUCCESS   if successful
+     CVSPILS_MEM_NULL  if the cvode memory was NULL
+     CVSPILS_LMEM_NULL if the linear solver memory was NULL
+     CVSPILS_ILL_INPUT if an input has an illegal value
+  -----------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int CVSpilsSetPrecType(void *cvode_mem, int pretype);
-SUNDIALS_EXPORT int CVSpilsSetGSType(void *cvode_mem, int gstype);
-SUNDIALS_EXPORT int CVSpilsSetMaxl(void *cvode_mem, int maxl);
 SUNDIALS_EXPORT int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac);
 SUNDIALS_EXPORT int CVSpilsSetPreconditioner(void *cvode_mem, 
                                              CVSpilsPrecSetupFn pset,
                                              CVSpilsPrecSolveFn psolve);
-SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFn(void *cvode_mem, 
-                                            CVSpilsJacTimesVecFn jtv);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the CVSPILS linear solver
- * -----------------------------------------------------------------
- * CVSpilsGetWorkSpace returns the real and integer workspace used
- *                by the SPILS module.
- *
- * CVSpilsGetNumPrecEvals returns the number of preconditioner
- *                 evaluations, i.e. the number of calls made
- *                 to PrecSetup with jok==FALSE.
- *
- * CVSpilsGetNumPrecSolves returns the number of calls made to
- *                 PrecSolve.
- *
- * CVSpilsGetNumLinIters returns the number of linear iterations.
- *
- * CVSpilsGetNumConvFails returns the number of linear
- *                 convergence failures.
- *
- * CVSpilsGetNumJtimesEvals returns the number of calls to jtimes.
- *
- * CVSpilsGetNumRhsEvals returns the number of calls to the user
- *                 f routine due to finite difference Jacobian
- *                 times vector evaluation.
- *
- * CVSpilsGetLastFlag returns the last error flag set by any of
- *                 the CVSPILS interface functions.
- *
- * The return value of CVSpilsGet* is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
+SUNDIALS_EXPORT int CVSpilsSetJacTimes(void *cvode_mem,
+                                       CVSpilsJacTimesSetupFn jtsetup,
+                                       CVSpilsJacTimesVecFn jtimes);
 
-SUNDIALS_EXPORT int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals);
-SUNDIALS_EXPORT int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves);
-SUNDIALS_EXPORT int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters);
-SUNDIALS_EXPORT int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails);
-SUNDIALS_EXPORT int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals);
-SUNDIALS_EXPORT int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); 
-SUNDIALS_EXPORT int CVSpilsGetLastFlag(void *cvode_mem, long int *flag);
+/*-----------------------------------------------------------------
+  Optional outputs from the CVSPILS linear solver
+  -----------------------------------------------------------------
+  CVSpilsGetWorkSpace returns the real and integer workspace used
+                 by the SPILS module.
+ 
+  CVSpilsGetNumPrecEvals returns the number of preconditioner
+                  evaluations, i.e. the number of calls made
+                  to PrecSetup with jok==SUNFALSE.
+ 
+  CVSpilsGetNumPrecSolves returns the number of calls made to
+                  PrecSolve.
+ 
+  CVSpilsGetNumLinIters returns the number of linear iterations.
+ 
+  CVSpilsGetNumConvFails returns the number of linear
+                  convergence failures.
+ 
+  CVSpilsGetNumJTSetupEvals returns the number of calls to jtsetup.
+ 
+  CVSpilsGetNumJtimesEvals returns the number of calls to jtimes.
+ 
+  CVSpilsGetNumRhsEvals returns the number of calls to the user
+                  f routine due to finite difference Jacobian
+                  times vector evaluation.
+ 
+  CVSpilsGetLastFlag returns the last error flag set by any of
+                  the CVSPILS interface functions.
+ 
+  The return value of CVSpilsGet* is one of:
+     CVSPILS_SUCCESS   if successful
+     CVSPILS_MEM_NULL  if the cvode memory was NULL
+     CVSPILS_LMEM_NULL if the linear solver memory was NULL
+ -----------------------------------------------------------------*/
 
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a CVSPILS return flag
- * -----------------------------------------------------------------
- */
+SUNDIALS_EXPORT int CVSpilsGetWorkSpace(void *cvode_mem,
+                                        long int *lenrwLS,
+                                        long int *leniwLS);
+SUNDIALS_EXPORT int CVSpilsGetNumPrecEvals(void *cvode_mem,
+                                           long int *npevals);
+SUNDIALS_EXPORT int CVSpilsGetNumPrecSolves(void *cvode_mem,
+                                            long int *npsolves);
+SUNDIALS_EXPORT int CVSpilsGetNumLinIters(void *cvode_mem,
+                                          long int *nliters);
+SUNDIALS_EXPORT int CVSpilsGetNumConvFails(void *cvode_mem,
+                                           long int *nlcfails);
+SUNDIALS_EXPORT int CVSpilsGetNumJTSetupEvals(void *cvode_mem,
+                                              long int *njtsetups);
+SUNDIALS_EXPORT int CVSpilsGetNumJtimesEvals(void *cvode_mem,
+                                             long int *njvevals);
+SUNDIALS_EXPORT int CVSpilsGetNumRhsEvals(void *cvode_mem,
+                                          long int *nfevalsLS); 
+SUNDIALS_EXPORT int CVSpilsGetLastFlag(void *cvode_mem,
+                                       long int *flag);
 
+/*-----------------------------------------------------------------
+  The following function returns the name of the constant 
+  associated with a CVSPILS return flag
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT char *CVSpilsGetReturnFlagName(long int flag);
 
 #ifdef __cplusplus
diff --git a/include/cvode/cvode_sptfqmr.h b/include/cvode/cvode_sptfqmr.h
deleted file mode 100644
index 179d818..0000000
--- a/include/cvode/cvode_sptfqmr.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODE scaled preconditioned TFQMR 
- * linear solver, CVSPTFQMR.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSPTFQMR_H
-#define _CVSPTFQMR_H
-
-#include <cvode/cvode_spils.h>
-#include <sundials/sundials_sptfqmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmr
- * -----------------------------------------------------------------
- * A call to the CVSptfqmr function links the main CVODE integrator
- * with the CVSPTFQMR linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * pretype   is the type of user preconditioning to be done.
- *           This must be one of the four enumeration constants
- *           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
- *           in iterative.h. These correspond to no preconditioning,
- *           left preconditioning only, right preconditioning
- *           only, and both left and right preconditioning,
- *           respectively.
- *
- * maxl      is the maximum Krylov dimension. This is an
- *           optional input to the CVSPTFQMR solver. Pass 0 to
- *           use the default value CVSPILS_MAXL=5.
- *
- * The return value of CVSptfqmr is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_MEM_FAIL  if there was a memory allocation failure
- *    CVSPILS_ILL_INPUT if a required vector operation is missing
- * The above constants are defined in cvode_spils.h
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSptfqmr(void *cvode_mem, int pretype, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvode/cvode_superlumt.h b/include/cvode/cvode_superlumt.h
deleted file mode 100644
index 1638876..0000000
--- a/include/cvode/cvode_superlumt.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4177 $
- * $Date: 2014-07-23 11:56:06 -0700 (Wed, 23 Jul 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDASuperLUMT linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSUPERLUMT_H
-#define _CVSUPERLUMT_H
-
-#include "cvode/cvode_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSuperLUMT
- * -----------------------------------------------------------------
- * A call to the CVSuperLUMT function links the main integrator      
- * with the CVSuperLUMT linear solver module.                        
- *                                                                
- * cv_mem is the pointer to integrator memory returned by        
- *     CVCreate.             
- *
- *                                                                
- * CVSuperLUMT returns:                                              
- *     CVSLU_SUCCESS   = 0  if successful                              
- *     CVSLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     CVSLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The CVSuperLUMT linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, CVSuperLUMT will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVSuperLUMT(void *cv_mem, int num_threads,
-				  int n, int nnz); 
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVSuperLUMTSetOrdering sets the ordering used by CVSuperLUMT for 
- * reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVSuperLUMTSetOrdering(void *cv_mem, 
-					     int ordering_choice); 
-
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes.h b/include/cvodes/cvodes.h
index 7c32757..6fcad3a 100644
--- a/include/cvodes/cvodes.h
+++ b/include/cvodes/cvodes.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -956,12 +956,12 @@ SUNDIALS_EXPORT void CVodeQuadSensFree(void *cvode_mem);
  *                         | [10]
  *                         |
  * CVodeSetStabLimDet      | flag to turn on/off stability limit
- *                         | detection (TRUE = on, FALSE = off).
+ *                         | detection (SUNTRUE = on, SUNFALSE = off).
  *                         | When BDF is used and order is 3 or
  *                         | greater, CVsldet is called to detect
  *                         | stability limit.  If limit is detected,
  *                         | the order is reduced.
- *                         | [FALSE]
+ *                         | [SUNFALSE]
  *                         |
  * CVodeSetInitStep        | initial step size.
  *                         | [estimated by CVODES]
@@ -1053,7 +1053,7 @@ SUNDIALS_EXPORT int CVodeSetNoInactiveRootWarn(void *cvode_mem);
  *                      | the error control?
  *                      | If yes, tolerances for quadrature are
  *                      | required (see CVodeQuad**tolerances) 
- *                      | [errconQ = FALSE]
+ *                      | [errconQ = SUNFALSE]
  *                      |
  * -----------------------------------------------------------------
  * If successful, these functions return CV_SUCCESS. If an argument
@@ -1096,7 +1096,7 @@ SUNDIALS_EXPORT int CVodeSetQuadErrCon(void *cvode_mem, booleantype errconQ);
  *                            |
  * CVodeSetSensErrCon         | are sensitivity variables considered in
  *                            | the error control?
- *                            | [FALSE]
+ *                            | [SUNFALSE]
  *                            |
  * CVodeSetSensMaxNonlinIters | Maximum number of nonlinear solver
  *                            | iterations at one solution.
@@ -1126,7 +1126,7 @@ SUNDIALS_EXPORT int CVodeSetSensParams(void *cvode_mem, realtype *p, realtype *p
  *                        | considered in the error control?
  *                        | If yes, tolerances for quadrature
  *                        | sensitivity variables are required.
- *                        | [errconQS = FALSE]
+ *                        | [errconQS = SUNFALSE]
  *                        |
  * -----------------------------------------------------------------
  * If successful, these functions return CV_SUCCESS. If an argument
diff --git a/include/cvodes/cvodes_band.h b/include/cvodes/cvodes_band.h
deleted file mode 100644
index 59f0bb4..0000000
--- a/include/cvodes/cvodes_band.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the band linear solver CSVBAND.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSBAND_H
-#define _CVSBAND_H
-
-#include <cvodes/cvodes_direct.h>
-#include <sundials/sundials_band.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVBand
- * -----------------------------------------------------------------
- * A call to the CVBand function links the main CVODE integrator
- * with the CVSBAND linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * mupper is the upper bandwidth of the band Jacobian
- *        approximation.
- *
- * mlower is the lower bandwidth of the band Jacobian
- *        approximation.
- *
- * The return value of CVBand is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the cvode memory was NULL
- *    CVDLS_MEM_FAIL  if there was a memory allocation failure
- *    CVDLS_ILL_INPUT if a required vector operation is missing or
- *                     if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVBand(void *cvode_mem, long int N, long int mupper, long int mlower);
-
-/*
- * -----------------------------------------------------------------
- * Function: CVBandB
- * -----------------------------------------------------------------
- * CVBandB links the main CVODE integrator with the CVSBAND
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVBandB(void *cvode_mem, int which,
-                            long int nB, long int mupperB, long int mlowerB);
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_bandpre.h b/include/cvodes/cvodes_bandpre.h
index bd2f196..3985ece 100644
--- a/include/cvodes/cvodes_bandpre.h
+++ b/include/cvodes/cvodes_bandpre.h
@@ -1,24 +1,26 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for the CVSBANDPRE module, which
  * provides a banded difference quotient Jacobian-based
- * preconditioner and solver routines for use with CVSPGMR,
- * CVSPBCG, or CVSPTFQMR.
+ * preconditioner and solver routines for use with the CVSSPILS
+ * iterative linear solver interface.
  *
  * Part I contains type definitions and function prototypes for using
  * CVSBANDPRE on forward problems (IVP integration and/or FSA)
@@ -37,146 +39,147 @@
 extern "C" {
 #endif
 
-/* 
- * =================================================================
- * PART I - forward problems
- * =================================================================
- */
+/*=================================================================
+  PART I - forward problems
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- *
- * SUMMARY
- * 
- * These routines provide a band matrix preconditioner based on
- * difference quotients of the ODE right-hand side function f.
- * The user supplies parameters
- *   mu = upper half-bandwidth (number of super-diagonals)
- *   ml = lower half-bandwidth (number of sub-diagonals)
- * The routines generate a band matrix of bandwidth ml + mu + 1
- * and use this to form a preconditioner for use with the Krylov
- * linear solver in CVSP*. Although this matrix is intended to
- * approximate the Jacobian df/dy, it may be a very crude
- * approximation. The true Jacobian need not be banded, or its
- * true bandwith may be larger than ml + mu + 1, as long as the
- * banded approximation generated here is sufficiently accurate
- * to speed convergence as a preconditioner.
- *
- * Usage:
- *   The following is a summary of the usage of this module.
- *   Details of the calls to CVodeCreate, CVodeInit, CVSp*,
- *   and CVode are available in the User Guide.
- *   To use these routines, the sequence of calls in the user
- *   main program should be as follows:
- *
- *   #include <cvodes/cvodes_bandpre.h>
- *   #include <nvector_serial.h>
- *   ...
- *   Set y0
- *   ...
- *   cvode_mem = CVodeCreate(...);
- *   ier = CVodeInit(...);
- *   ...
- *   flag = CVSptfqmr(cvode_mem, pretype, maxl);
- *     -or-
- *   flag = CVSpgmr(cvode_mem, pretype, maxl);
- *     -or-
- *   flag = CVSpbcg(cvode_mem, pretype, maxl);
- *   ...
- *   flag = CVBandPrecInit(cvode_mem, N, mu, ml);
- *   ...
- *   flag = CVode(...);
- *   ...
- *   Free y0
- *   ...
- *   CVodeFree(&cvode_mem);
- *
- * Notes:
- * (1) Include this file for the CVBandPrecData type definition.
- * (2) In the CVBandPrecInit call, the arguments N is the
- *     problem dimension.
- * (3) In the CVBPSp* call, the user is free to specify
- *     the input pretype and the optional input maxl.
- * -----------------------------------------------------------------
- */
-
-
-/*
- * -----------------------------------------------------------------
- * Function : CVBandPrecInit
- * -----------------------------------------------------------------
- * CVBandPrecInit allocates and initializes the BANDPRE preconditioner
- * module. This functino must be called AFTER one of the SPILS linear
- * solver modules has been attached to the CVODE integrator.
- *
- * The parameters of CVBandPrecInit are as follows:
- *
- * cvode_mem is the pointer to CVODE memory returned by CVodeCreate.
- *
- * N is the problem size.
- *
- * mu is the upper half bandwidth.
- *
- * ml is the lower half bandwidth.
- *
- * The return value of CVBandPrecInit is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_ILL_INPUT if an input has an illegal value
- *   CVSPILS_MEM_FAIL if a memory allocation request failed
- *
- * NOTE: The band preconditioner assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVBandPrecInit will
- *       first test for a compatible N_Vector internal
- *       representation by checking for required functions.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  SUMMARY
+  
+  These routines provide a band matrix preconditioner based on
+  difference quotients of the ODE right-hand side function f.
+  The user supplies parameters
+    mu = upper half-bandwidth (number of super-diagonals)
+    ml = lower half-bandwidth (number of sub-diagonals)
+  The routines generate a band matrix of bandwidth ml + mu + 1
+  and use this to form a preconditioner for use with the Krylov
+  linear solver through the CVSPILS interface. Although this 
+  matrix is intended to approximate the Jacobian df/dy, it may 
+  be a very crude approximation. The true Jacobian need not be 
+  banded, or its true bandwith may be larger than ml + mu + 1, 
+  as long as the banded approximation generated here is 
+  sufficiently accurate to speed convergence as a preconditioner.
+ 
+  Usage:
+    The following is a summary of the usage of this module.
+    Details of the calls to CVodeCreate, CVodeInit, CVSp*,
+    and CVode are available in the User Guide.
+    To use these routines, the sequence of calls in the user
+    main program should be as follows:
+ 
+    #include <cvodes/cvodes_bandpre.h>
+    #include <nvector_serial.h>   (or openmp or pthreads)
+    ...
+    void *cvode_mem;
+    ...
+    Set y0
+    ...
+    SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+    ...
+    cvode_mem = CVodeCreate(...);
+    flag = CVodeInit(...);
+    ...
+    flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+    ...
+    flag = CVBandPrecInit(cvode_mem, N, mu, ml);
+    ...
+    flag = CVode(...);
+    ...
+    Free y0
+    ...
+    CVodeFree(&cvode_mem);
+    ...
+    SUNLinSolFree(LS);
+    ...
+ 
+  Notes:
+  (1) Include this file for the CVBandPrecData type definition.
+  (2) In the CVBandPrecInit call, the arguments N is the
+      problem dimension.
+  (3) In the linear solver creation call, the user is free to
+      specify the input pretype and the optional input maxl.
+  -----------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml);
 
-/*
- * -----------------------------------------------------------------
- * Optional output functions : CVBandPrecGet*
- * -----------------------------------------------------------------
- * CVBandPrecGetWorkSpace returns the real and integer work space used
- *                        by CVBANDPRE.
- * CVBandPrecGetNumRhsEvals returns the number of calls made from
- *                          CVBANDPRE to the user's right-hand side
- *                          routine f.
- *
- * The return value of CVBandPrecGet* is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Function : CVBandPrecInit
+  -----------------------------------------------------------------
+  CVBandPrecInit allocates and initializes the BANDPRE preconditioner
+  module. This function must be called AFTER the CVSPILS linear
+  solver interface has been created.
+ 
+  The parameters of CVBandPrecInit are as follows:
+ 
+  cvode_mem is the pointer to CVODE memory returned by CVodeCreate.
+ 
+  N is the problem size.
+ 
+  mu is the upper half bandwidth.
+ 
+  ml is the lower half bandwidth.
+ 
+  The return value of CVBandPrecInit is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_ILL_INPUT if an input has an illegal value
+    CVSPILS_MEM_FAIL if a memory allocation request failed
+ 
+  NOTE: The band preconditioner assumes a serial/OpenMP/Pthreads
+        implementation of the NVECTOR package. Therefore, 
+        CVBandPrecInit will first test for a compatible N_Vector 
+        internal representation by checking for required functions.
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBandPrecInit(void *cvode_mem, sunindextype N,
+                                   sunindextype mu, sunindextype ml);
 
-SUNDIALS_EXPORT int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP);
+/*-----------------------------------------------------------------
+  Optional output functions : CVBandPrecGet*
+  -----------------------------------------------------------------
+  CVBandPrecGetWorkSpace returns the real and integer work space used
+                         by CVBANDPRE.
+  CVBandPrecGetNumRhsEvals returns the number of calls made from
+                           CVBANDPRE to the user's right-hand side
+                           routine f.
+ 
+  The return value of CVBandPrecGet* is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBandPrecGetWorkSpace(void *cvode_mem,
+                                           long int *lenrwLS,
+                                           long int *leniwLS);
+SUNDIALS_EXPORT int CVBandPrecGetNumRhsEvals(void *cvode_mem,
+                                             long int *nfevalsBP);
 
-/* 
- * =================================================================
- * PART II - backward problems
- * =================================================================
- */
 
-/*
- * -----------------------------------------------------------------
- * Functions: CVBandPrecInitB, CVBPSp*B
- * -----------------------------------------------------------------
- * Interface functions for the CVBANDPRE preconditioner to be used
- * on the backward phase.
- *
- * CVBandPrecInitB interfaces to the CVBANDPRE preconditioner
- * for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
+/*=================================================================
+  PART II - backward problems
+  =================================================================*/
 
+/*-----------------------------------------------------------------
+  Functions: CVBandPrecInitB
+  -----------------------------------------------------------------
+  Interface functions for the CVBANDPRE preconditioner to be used
+  on the backward phase.
+ 
+  CVBandPrecInitB interfaces to the CVBANDPRE preconditioner
+  for the backward integration.
+  The 'which' argument is the int returned by CVodeCreateB.
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT int CVBandPrecInitB(void *cvode_mem, int which,
-                                    long int nB, long int muB, long int mlB);
+                                    sunindextype nB, sunindextype muB,
+                                    sunindextype mlB);
 
 #ifdef __cplusplus
 }
diff --git a/include/cvodes/cvodes_bbdpre.h b/include/cvodes/cvodes_bbdpre.h
index bd711ed..d74e203 100644
--- a/include/cvodes/cvodes_bbdpre.h
+++ b/include/cvodes/cvodes_bbdpre.h
@@ -1,25 +1,26 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for the CVBBDPRE module, for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with CVSPGMR/CVSPBCG/CVSPTFQMR, 
- * and the parallel implementation of the NVECTOR module.
- *
+ * matrix with banded blocks, for use with the CVSPILS interface,
+ * and the MPI-parallel implementation of the NVECTOR module.
  *
  * Part I contains type definitions and function prototypes for using
  * CVBBDPRE on forward problems (IVP integration and/or FSA)
@@ -38,296 +39,295 @@
 extern "C" {
 #endif
 
-/* 
- * =================================================================
- * PART I - forward problems
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- *
- * SUMMARY
- *
- * These routines provide a preconditioner matrix that is
- * block-diagonal with banded blocks. The blocking corresponds
- * to the distribution of the dependent variable vector y among
- * the processors. Each preconditioner block is generated from
- * the Jacobian of the local part (on the current processor) of a
- * given function g(t,y) approximating f(t,y). The blocks are
- * generated by a difference quotient scheme on each processor
- * independently. This scheme utilizes an assumed banded
- * structure with given half-bandwidths, mudq and mldq.
- * However, the banded Jacobian block kept by the scheme has
- * half-bandwiths mukeep and mlkeep, which may be smaller.
- *
- * The user's calling program should have the following form:
- *
- *   #include <cvodes/cvodes_bbdpre.h>
- *   #include <nvector_parallel.h>
- *   ...
- *   void *cvode_mem;
- *   ...
- *   Set y0
- *   ...
- *   cvode_mem = CVodeCreate(...);
- *   ier = CVodeInit(...);
- *   ...
- *   flag = CVSpgmr(cvode_mem, pretype, maxl);
- *      -or-
- *   flag = CVSpbcg(cvode_mem, pretype, maxl);
- *      -or-
- *   flag = CVSptfqmr(cvode_mem, pretype, maxl);
- *   ...
- *   flag = CVBBDPrecInit(cvode_mem, Nlocal, mudq ,mldq,
- *                        mukeep, mlkeep, dqrely, gloc, cfn);
- *   ...
- *   ier = CVode(...);
- *   ...
- *   CVodeFree(&cvode_mem);
- * 
- *   Free y0
- *
- * The user-supplied routines required are:
- *
- *   f    = function defining the ODE right-hand side f(t,y).
- *
- *   gloc = function defining the approximation g(t,y).
- *
- *   cfn  = function to perform communication need for gloc.
- *
- * Notes:
- *
- * 1) This header file is included by the user for the definition
- *    of the CVBBDData type and for needed function prototypes.
- *
- * 2) The CVBBDPrecInit call includes half-bandwiths mudq and mldq
- *    to be used in the difference quotient calculation of the
- *    approximate Jacobian. They need not be the true
- *    half-bandwidths of the Jacobian of the local block of g,
- *    when smaller values may provide a greater efficiency.
- *    Also, the half-bandwidths mukeep and mlkeep of the retained
- *    banded approximate Jacobian block may be even smaller,
- *    to reduce storage and computation costs further.
- *    For all four half-bandwidths, the values need not be the
- *    same on every processor.
- *
- * 3) The actual name of the user's f function is passed to
- *    CVodeInit, and the names of the user's gloc and cfn
- *    functions are passed to CVBBDPrecInit.
- *
- * 4) The pointer to the user-defined data block user_data, which is
- *    set through CVodeSetUserData is also available to the user in
- *    gloc and cfn.
- *
- * 5) Optional outputs specific to this module are available by
- *    way of routines listed below. These include work space sizes
- *    and the cumulative number of gloc calls. The costs
- *    associated with this module also include nsetups banded LU
- *    factorizations, nlinsetups cfn calls, and npsolves banded
- *    backsolve calls, where nlinsetups and npsolves are
- *    integrator/CVSPGMR/CVSPBCG/CVSPTFQMR optional outputs.
- * -----------------------------------------------------------------
- */
+/*=================================================================
+  PART I - forward problems
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- * Type : CVLocalFn
- * -----------------------------------------------------------------
- * The user must supply a function g(t,y) which approximates the
- * right-hand side function f for the system y'=f(t,y), and which
- * is computed locally (without interprocess communication).
- * (The case where g is mathematically identical to f is allowed.)
- * The implementation of this function must have type CVLocalFn.
- *
- * This function takes as input the local vector size Nlocal, the
- * independent variable value t, the local real dependent
- * variable vector y, and a pointer to the user-defined data
- * block user_data. It is to compute the local part of g(t,y) and
- * store this in the vector g.
- * (Allocation of memory for y and g is handled within the
- * preconditioner module.)
- * The user_data parameter is the same as that specified by the user
- * through the CVodeSetFdata routine.
- *
- * A CVLocalFn should return 0 if successful, a positive value if 
- * a recoverable error occurred, and a negative value if an 
- * unrecoverable error occurred.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  SUMMARY
+ 
+  These routines provide a preconditioner matrix that is
+  block-diagonal with banded blocks. The blocking corresponds
+  to the distribution of the dependent variable vector y among
+  the processors. Each preconditioner block is generated from
+  the Jacobian of the local part (on the current processor) of a
+  given function g(t,y) approximating f(t,y). The blocks are
+  generated by a difference quotient scheme on each processor
+  independently. This scheme utilizes an assumed banded
+  structure with given half-bandwidths, mudq and mldq.
+  However, the banded Jacobian block kept by the scheme has
+  half-bandwiths mukeep and mlkeep, which may be smaller.
+ 
+  The user's calling program should have the following form:
+ 
+    #include <cvodes/cvodes_spils.h>
+    #include <cvodes/cvodes_bbdpre.h>
+    #include <nvector_parallel.h>
+    ...
+    void *cvode_mem;
+    ...
+    Set y0
+    ...
+    SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+    ...
+    cvode_mem = CVodeCreate(...);
+    flag = CVodeInit(...);
+    ...
+    flag = CVSpilsSetLinearSolver(cvode_mem, LS);
+    ...
+    flag = CVBBDPrecInit(cvode_mem, Nlocal, mudq ,mldq,
+                         mukeep, mlkeep, dqrely, gloc, cfn);
+    ...
+    flag = CVode(...);
+    ...
+    CVodeFree(&cvode_mem);
+    ...
+    Free y0
+    ...
+    CVodeFree(&cvode_mem);
+    ...
+    SUNLinSolFree(LS);
+    ...
+ 
+  The user-supplied routines required are:
+ 
+    f    = function defining the ODE right-hand side f(t,y).
+ 
+    gloc = function defining the approximation g(t,y).
+ 
+    cfn  = function to perform communication need for gloc.
+ 
+  Notes:
+ 
+  1) This header file is included by the user for the definition
+     of the CVBBDData type and for needed function prototypes.
+ 
+  2) The CVBBDPrecInit call includes half-bandwiths mudq and mldq
+     to be used in the difference quotient calculation of the
+     approximate Jacobian. They need not be the true
+     half-bandwidths of the Jacobian of the local block of g,
+     when smaller values may provide a greater efficiency.
+     Also, the half-bandwidths mukeep and mlkeep of the retained
+     banded approximate Jacobian block may be even smaller,
+     to reduce storage and computation costs further.
+     For all four half-bandwidths, the values need not be the
+     same on every processor.
+ 
+  3) The actual name of the user's f function is passed to
+     CVodeInit, and the names of the user's gloc and cfn
+     functions are passed to CVBBDPrecInit.
+ 
+  4) The pointer to the user-defined data block user_data, which is
+     set through CVodeSetUserData is also available to the user in
+     gloc and cfn.
+ 
+  5) Optional outputs specific to this module are available by
+     way of routines listed below. These include work space sizes
+     and the cumulative number of gloc calls. The costs
+     associated with this module also include nsetups banded LU
+     factorizations, nlinsetups cfn calls, and npsolves banded
+     backsolve calls, where nlinsetups and npsolves are
+     integrator/CVSPILS optional outputs.
+  -----------------------------------------------------------------*/
 
-typedef int (*CVLocalFn)(long int Nlocal, realtype t, 
+/*-----------------------------------------------------------------
+  Type : CVLocalFn
+  -----------------------------------------------------------------
+  The user must supply a function g(t,y) which approximates the
+  right-hand side function f for the system y'=f(t,y), and which
+  is computed locally (without interprocess communication).
+  (The case where g is mathematically identical to f is allowed.)
+  The implementation of this function must have type CVLocalFn.
+ 
+  This function takes as input the local vector size Nlocal, the
+  independent variable value t, the local real dependent
+  variable vector y, and a pointer to the user-defined data
+  block user_data. It is to compute the local part of g(t,y) and
+  store this in the vector g.
+  (Allocation of memory for y and g is handled within the
+  preconditioner module.)
+  The user_data parameter is the same as that specified by the user
+  through the CVodeSetUserdata routine.
+ 
+  A CVLocalFn should return 0 if successful, a positive value if 
+  a recoverable error occurred, and a negative value if an 
+  unrecoverable error occurred.
+  -----------------------------------------------------------------*/
+typedef int (*CVLocalFn)(sunindextype Nlocal, realtype t, 
 			 N_Vector y, N_Vector g, void *user_data);
 
-/*
- * -----------------------------------------------------------------
- * Type : CVCommFn
- * -----------------------------------------------------------------
- * The user may supply a function of type CVCommFn which performs
- * all interprocess communication necessary to evaluate the
- * approximate right-hand side function described above.
- *
- * This function takes as input the local vector size Nlocal,
- * the independent variable value t, the dependent variable
- * vector y, and a pointer to the user-defined data block user_data.
- * The user_data parameter is the same as that specified by the user
- * through the CVodeSetUserData routine. The CVCommFn cfn is
- * expected to save communicated data in space defined within the
- * structure user_data. Note: A CVCommFn cfn does not have a return value.
- *
- * Each call to the CVCommFn cfn is preceded by a call to the
- * CVRhsFn f with the same (t,y) arguments. Thus cfn can omit any
- * communications done by f if relevant to the evaluation of g.
- * If all necessary communication was done by f, the user can
- * pass NULL for cfn in CVBBDPrecInit (see below).
- *
- * A CVCommFn should return 0 if successful, a positive value if 
- * a recoverable error occurred, and a negative value if an 
- * unrecoverable error occurred.
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVCommFn)(long int Nlocal, realtype t, 
-			N_Vector y,
-			void *user_data);
-
-/*
- * -----------------------------------------------------------------
- * Function : CVBBDPrecInit
- * -----------------------------------------------------------------
- * CVBBDPrecInit allocates and initializes the BBD preconditioner.
- *
- * The parameters of CVBBDPrecInit are as follows:
- *
- * cvode_mem is the pointer to the integrator memory.
- *
- * Nlocal is the length of the local block of the vectors y etc.
- *        on the current processor.
- *
- * mudq, mldq are the upper and lower half-bandwidths to be used
- *            in the difference quotient computation of the local
- *            Jacobian block.
- *
- * mukeep, mlkeep are the upper and lower half-bandwidths of the
- *                retained banded approximation to the local Jacobian
- *                block.
- *
- * dqrely is an optional input. It is the relative increment
- *        in components of y used in the difference quotient
- *        approximations. To specify the default, pass 0.
- *        The default is dqrely = sqrt(unit roundoff).
- *
- * gloc is the name of the user-supplied function g(t,y) that
- *      approximates f and whose local Jacobian blocks are
- *      to form the preconditioner.
- *
- * cfn is the name of the user-defined function that performs
- *     necessary interprocess communication for the
- *     execution of gloc.
- *
- * The return value of CVBBDPrecInit is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_ILL_INPUT if an input has an illegal value
- *   CVSPILS_MEM_FAIL if a memory allocation request failed
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  Type : CVCommFn
+  -----------------------------------------------------------------
+  The user may supply a function of type CVCommFn which performs
+  all interprocess communication necessary to evaluate the
+  approximate right-hand side function described above.
+ 
+  This function takes as input the local vector size Nlocal,
+  the independent variable value t, the dependent variable
+  vector y, and a pointer to the user-defined data block 
+  user_data. The user_data parameter is the same as that 
+  specified by the user through the CVodeSetUserData routine. 
+  The CVCommFn cfn is expected to save communicated data in 
+  space defined within the structure user_data. 
+  Note: A CVCommFn cfn does not have a return value.
+ 
+  Each call to the CVCommFn cfn is preceded by a call to the
+  CVRhsFn f with the same (t,y) arguments. Thus cfn can omit any
+  communications done by f if relevant to the evaluation of g.
+  If all necessary communication was done by f, the user can
+  pass NULL for cfn in CVBBDPrecInit (see below).
+ 
+  A CVCommFn should return 0 if successful, a positive value if 
+  a recoverable error occurred, and a negative value if an 
+  unrecoverable error occurred.
+  -----------------------------------------------------------------*/
+typedef int (*CVCommFn)(sunindextype Nlocal, realtype t, 
+			N_Vector y, void *user_data);
 
-SUNDIALS_EXPORT int CVBBDPrecInit(void *cvode_mem, long int Nlocal, 
-                                  long int mudq, long int mldq, 
-                                  long int mukeep, long int mlkeep, 
+  
+/*-----------------------------------------------------------------
+  Function : CVBBDPrecInit
+  -----------------------------------------------------------------
+  CVBBDPrecInit allocates and initializes the BBD preconditioner.
+ 
+  The parameters of CVBBDPrecInit are as follows:
+ 
+  cvode_mem is the pointer to the integrator memory.
+ 
+  Nlocal is the length of the local block of the vectors y etc.
+         on the current processor.
+ 
+  mudq, mldq are the upper and lower half-bandwidths to be used
+             in the difference quotient computation of the local
+             Jacobian block.
+ 
+  mukeep, mlkeep are the upper and lower half-bandwidths of the
+                 retained banded approximation to the local Jacobian
+                 block.
+ 
+  dqrely is an optional input. It is the relative increment
+         in components of y used in the difference quotient
+         approximations. To specify the default, pass 0.
+         The default is dqrely = sqrt(unit roundoff).
+ 
+  gloc is the name of the user-supplied function g(t,y) that
+       approximates f and whose local Jacobian blocks are
+       to form the preconditioner.
+ 
+  cfn is the name of the user-defined function that performs
+      necessary interprocess communication for the
+      execution of gloc.
+ 
+  The return value of CVBBDPrecInit is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_ILL_INPUT if an input has an illegal value
+    CVSPILS_MEM_FAIL if a memory allocation request failed
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBBDPrecInit(void *cvode_mem,
+                                  sunindextype Nlocal, 
+                                  sunindextype mudq,
+                                  sunindextype mldq, 
+                                  sunindextype mukeep,
+                                  sunindextype mlkeep, 
                                   realtype dqrely,
-                                  CVLocalFn gloc, CVCommFn cfn);
+                                  CVLocalFn gloc,
+                                  CVCommFn cfn);
 
-/*
- * -----------------------------------------------------------------
- * Function : CVBBDPrecReInit
- * -----------------------------------------------------------------
- * CVBBDPrecReInit re-initializes the BBDPRE module when solving a
- * sequence of problems of the same size with CVSPGMR/CVBBDPRE,
- * CVSPBCG/CVBBDPRE, or CVSPTFQMR/CVBBDPRE provided there is no change 
- * in Nlocal, mukeep, or mlkeep. After solving one problem, and after 
- * calling CVodeReInit to re-initialize the integrator for a subsequent 
- * problem, call CVBBDPrecReInit.
- *
- * All arguments have the same names and meanings as those
- * of CVBBDPrecInit.
- *
- * The return value of CVBBDPrecReInit is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVBBDPrecReInit(void *cvode_mem, long int mudq, long int mldq,
+  
+/*-----------------------------------------------------------------
+  Function : CVBBDPrecReInit
+  -----------------------------------------------------------------
+  CVBBDPrecReInit re-initializes the BBDPRE module when solving a
+  sequence of problems of the same size with CVSPILS/CVBBDPRE 
+  provided there is no change in Nlocal, mukeep, or mlkeep. After 
+  solving one problem, and after calling CVodeReInit to 
+  re-initialize the integrator for a subsequent problem, call 
+  CVBBDPrecReInit.
+ 
+  All arguments have the same names and meanings as those
+  of CVBBDPrecInit.
+ 
+  The return value of CVBBDPrecReInit is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBBDPrecReInit(void *cvode_mem,
+                                    sunindextype mudq,
+                                    sunindextype mldq,
                                     realtype dqrely);
 
-/*
- * -----------------------------------------------------------------
- * CVBBDPRE optional output extraction routines
- * -----------------------------------------------------------------
- * CVBBDPrecGetWorkSpace returns the BBDPRE real and integer work space
- *                       sizes.
- * CVBBDPrecGetNumGfnEvals returns the number of calls to gfn.
- *
- * The return value of CVBBDPrecGet* is one of:
- *   CVSPILS_SUCCESS if no errors occurred
- *   CVSPILS_MEM_NULL if the integrator memory is NULL
- *   CVSPILS_LMEM_NULL if the linear solver memory is NULL
- *   CVSPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  BBDPRE optional output extraction routines
+  -----------------------------------------------------------------
+  CVBBDPrecGetWorkSpace returns the BBDPRE real and integer work 
+                        space sizes.
+  CVBBDPrecGetNumGfnEvals returns the number of calls to gfn.
+ 
+  The return value of CVBBDPrecGet* is one of:
+    CVSPILS_SUCCESS if no errors occurred
+    CVSPILS_MEM_NULL if the integrator memory is NULL
+    CVSPILS_LMEM_NULL if the linear solver memory is NULL
+    CVSPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
 
 SUNDIALS_EXPORT int CVBBDPrecGetWorkSpace(void *cvode_mem,
-                                          long int *lenrwBBDP, long int *leniwBBDP);
-SUNDIALS_EXPORT int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP);
-
-/* 
- * =================================================================
- * PART II - backward problems
- * =================================================================
- */
+                                          long int *lenrwBBDP,
+                                          long int *leniwBBDP);
+SUNDIALS_EXPORT int CVBBDPrecGetNumGfnEvals(void *cvode_mem,
+                                            long int *ngevalsBBDP);
 
-/*
- * -----------------------------------------------------------------
- * Types: CVLocalFnB and CVCommFnB
- * -----------------------------------------------------------------
- * Local approximation function and inter-process communication
- * function for the BBD preconditioner on the backward phase.
- * -----------------------------------------------------------------
- */
+  
+/*=================================================================
+  PART II - backward problems
+  =================================================================*/
 
-typedef int (*CVLocalFnB)(long int NlocalB, realtype t, 
-			  N_Vector y, 
-			  N_Vector yB, N_Vector gB,
+/*-----------------------------------------------------------------
+  Types: CVLocalFnB and CVCommFnB
+  -----------------------------------------------------------------
+  Local approximation function and inter-process communication
+  function for the BBD preconditioner on the backward phase.
+  -----------------------------------------------------------------*/
+typedef int (*CVLocalFnB)(sunindextype NlocalB, realtype t, 
+			  N_Vector y, N_Vector yB, N_Vector gB,
 			  void *user_dataB);
-  
-typedef int (*CVCommFnB)(long int NlocalB, realtype t,
-			 N_Vector y, 
-			 N_Vector yB,
-			 void *user_dataB);
+typedef int (*CVCommFnB)(sunindextype NlocalB, realtype t,
+			 N_Vector y, N_Vector yB, void *user_dataB);
 
-/*
- * -----------------------------------------------------------------
- * Functions: CVBBDPrecInitB, CVBBDSp*B, CVBBDPrecReInit
- * -----------------------------------------------------------------
- * Interface functions for the CVBBDPRE preconditioner to be used on
- * the backward phase.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
 
-SUNDIALS_EXPORT int CVBBDPrecInitB(void *cvode_mem, int which, long int NlocalB,
-                                   long int mudqB, long int mldqB,
-                                   long int mukeepB, long int mlkeepB,
+/*-----------------------------------------------------------------
+  Functions: CVBBDPrecInitB, CVBBDPrecReInit
+  -----------------------------------------------------------------
+  Interface functions for the CVBBDPRE preconditioner to be used on
+  the backward phase.
+  The 'which' argument is the int returned by CVodeCreateB.
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVBBDPrecInitB(void *cvode_mem, int which,
+                                   sunindextype NlocalB,
+                                   sunindextype mudqB,
+                                   sunindextype mldqB,
+                                   sunindextype mukeepB,
+                                   sunindextype mlkeepB,
                                    realtype dqrelyB,
-                                   CVLocalFnB glocB, CVCommFnB cfnB);
-
+                                   CVLocalFnB glocB,
+                                   CVCommFnB cfnB);
 SUNDIALS_EXPORT int CVBBDPrecReInitB(void *cvode_mem, int which, 
-                                     long int mudqB, long int mldqB,
+                                     sunindextype mudqB,
+                                     sunindextype mldqB,
                                      realtype dqrelyB);
 
 #ifdef __cplusplus
diff --git a/include/cvodes/cvodes_dense.h b/include/cvodes/cvodes_dense.h
deleted file mode 100644
index 60a91e2..0000000
--- a/include/cvodes/cvodes_dense.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the dense linear solver CVSDENSE.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSDENSE_H
-#define _CVSDENSE_H
-
-#include <cvodes/cvodes_direct.h>
-#include <sundials/sundials_dense.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function: CVDense
- * -----------------------------------------------------------------
- * A call to the CVDense function links the main integrator with
- * the CVSDENSE linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * The return value of CVDense is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the cvode memory was NULL
- *    CVDLS_MEM_FAIL  if there was a memory allocation failure
- *    CVDLS_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDense(void *cvode_mem, long int N);
-
-/*
- * -----------------------------------------------------------------
- * Function: CVDenseB
- * -----------------------------------------------------------------
- * CVDenseB links the main CVODE integrator with the CVSDENSE
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDenseB(void *cvode_mem, int which, long int nB);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_diag.h b/include/cvodes/cvodes_diag.h
index 2e67ea8..3765bbc 100644
--- a/include/cvodes/cvodes_diag.h
+++ b/include/cvodes/cvodes_diag.h
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
diff --git a/include/cvodes/cvodes_direct.h b/include/cvodes/cvodes_direct.h
index ccd99a5..f18212e 100644
--- a/include/cvodes/cvodes_direct.h
+++ b/include/cvodes/cvodes_direct.h
@@ -1,21 +1,23 @@
-/*
+/* ----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common header file for the direct linear solvers in CVODES.
+ * Common header file for the direct linear solver interface in 
+ * CVODES.
  *
  * Part I contains type definitions and function prototypes for 
  * using a CVDLS linear solver on forward problems (IVP 
@@ -23,30 +25,28 @@
  *
  * Part II contains type definitions and function prototypes for 
  * using a CVDLS linear solver on adjoint (backward) problems
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _CVSDLS_H
 #define _CVSDLS_H
 
 #include <sundials/sundials_direct.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_linearsolver.h>
 #include <sundials/sundials_nvector.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * =================================================================
- * C V S D I R E C T     C O N S T A N T S
- * =================================================================
- */
+/*=================================================================
+  CVSDLS Constants
+  =================================================================*/
 
-/* 
- * -----------------------------------------------------------------
- * CVSDIRECT return values 
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  return values 
+  -----------------------------------------------------------------*/
 
 #define CVDLS_SUCCESS           0
 #define CVDLS_MEM_NULL         -1
@@ -58,353 +58,220 @@ extern "C" {
 
 #define CVDLS_JACFUNC_UNRECVR  -5
 #define CVDLS_JACFUNC_RECVR    -6
+#define CVDLS_SUNMAT_FAIL      -7
 
 /* Return values for the adjoint module */
 
 #define CVDLS_NO_ADJ           -101
 #define CVDLS_LMEMB_NULL       -102
 
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
 
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type: CVDlsDenseJacFn
- * -----------------------------------------------------------------
- *
- * A dense Jacobian approximation function Jac must be of type 
- * CVDlsDenseJacFn. Its parameters are:
- *
- * N   is the problem size.
- *
- * Jac is the dense matrix (of type DlsMat) that will be loaded
- *     by a CVDlsDenseJacFn with an approximation to the Jacobian 
- *     matrix J = (df_i/dy_j) at the point (t,y). 
- *
- * t   is the current value of the independent variable.
- *
- * y   is the current value of the dependent variable vector,
- *     namely the predicted value of y(t).
- *
- * fy  is the vector f(t,y).
- *
- * user_data is a pointer to user data - the same as the user_data
- *     parameter passed to CVodeSetFdata.
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated for
- * vectors of length N which can be used by a CVDlsDenseJacFn
- * as temporary storage or work space.
- *
- * A CVDlsDenseJacFn should return 0 if successful, a positive 
- * value if a recoverable error occurred, and a negative value if 
- * an unrecoverable error occurred.
- *
- * -----------------------------------------------------------------
- *
- * NOTE: The following are two efficient ways to load a dense Jac:         
- * (1) (with macros - no explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = DENSE_COL(Jac,j);                                 
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * (2) (without macros - explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = (Jac->data)[j];                                   
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * A third way, using the DENSE_ELEM(A,i,j) macro, is much less   
- * efficient in general.  It is only appropriate for use in small 
- * problems in which efficiency of access is NOT a major concern. 
- *                                                                
- * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     CVodeGetCurrentStep and CVodeGetErrWeights, respectively 
- *     (see cvode.h). The unit roundoff is available as 
- *     UNIT_ROUNDOFF defined in sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
-  
+/*=================================================================
+  PART I:  Forward Problems
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  FUNCTION TYPES
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Type: CVDlsJacFn
+  -----------------------------------------------------------------
+ 
+  A Jacobian approximation function Jac must be of type CVDlsJacFn. 
+  Its parameters are:
+ 
+  Jac is the SUNMatrix that will be loaded by a CVDlsJacFn with an 
+      approximation to the Jacobian matrix J = (df_i/dy_j) at 
+      the point (t,y). 
+ 
+  t   is the current value of the independent variable.
+ 
+  y   is the current value of the dependent variable vector,
+      namely the predicted value of y(t).
+ 
+  fy  is the vector f(t,y).
+ 
+  user_data is a pointer to user data - the same as the user_data
+      parameter passed to CVodeSetUserdata.
+ 
+  tmp1, tmp2, and tmp3 are pointers to memory allocated for
+  vectors of length N which can be used by a CVDlsJacFn
+  as temporary storage or work space.
+ 
+  A CVDlsJacFn should return 0 if successful, a positive 
+  value if a recoverable error occurred, and a negative value if 
+  an unrecoverable error occurred.
+ 
+  -----------------------------------------------------------------
+
+  NOTE: See the relevant SUNMatrix implementation header files and
+      documentation for mechanisms to inquire about matrix 
+      dimensions, and for efficient ways to set matrix entries.
+                                                                 
+  NOTE: If the user's Jacobian routine needs other quantities,   
+      they are accessible as follows: hcur (the current stepsize)
+      and ewt (the error weight vector) are accessible through   
+      CVodeGetCurrentStep and CVodeGetErrWeights, respectively 
+      (see cvode.h). The unit roundoff is available as 
+      UNIT_ROUNDOFF defined in sundials_types.h.
+ 
+  -----------------------------------------------------------------*/
+typedef int (*CVDlsJacFn)(realtype t, N_Vector y, N_Vector fy, 
+                          SUNMatrix Jac, void *user_data,
+                          N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
   
-typedef int (*CVDlsDenseJacFn)(long int N, realtype t,
-			       N_Vector y, N_Vector fy, 
-			       DlsMat Jac, void *user_data,
-			       N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-  
-/*
- * -----------------------------------------------------------------
- * Type: CVDlsBandJacFn
- * -----------------------------------------------------------------
- *
- * A band Jacobian approximation function Jac must have the
- * prototype given below. Its parameters are:
- *
- * N is the length of all vector arguments.
- *
- * mupper is the upper half-bandwidth of the approximate banded
- * Jacobian. This parameter is the same as the mupper parameter
- * passed by the user to the linear solver initialization function.
- *
- * mlower is the lower half-bandwidth of the approximate banded
- * Jacobian. This parameter is the same as the mlower parameter
- * passed by the user to the linear solver initialization function.
- *
- * t is the current value of the independent variable.
- *
- * y is the current value of the dependent variable vector,
- *      namely the predicted value of y(t).
- *
- * fy is the vector f(t,y).
- *
- * Jac is the band matrix (of type DlsMat) that will be loaded
- * by a CVDlsBandJacFn with an approximation to the Jacobian matrix
- * Jac = (df_i/dy_j) at the point (t,y).
- * Three efficient ways to load J are:
- *
- * (1) (with macros - no explicit data structure references)
- *    for (j=0; j < n; j++) {
- *       col_j = BAND_COL(Jac,j);
- *       for (i=j-mupper; i <= j+mlower; i++) {
- *         generate J_ij = the (i,j)th Jacobian element
- *         BAND_COL_ELEM(col_j,i,j) = J_ij;
- *       }
- *     }
- *
- * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro)
- *    for (j=0; j < n; j++) {
- *       col_j = BAND_COL(Jac,j);
- *       for (k=-mupper; k <= mlower; k++) {
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k
- *         col_j[k] = J_ij;
- *       }
- *     }
- *
- * (3) (without macros - explicit data structure references)
- *     offset = Jac->smu;
- *     for (j=0; j < n; j++) {
- *       col_j = ((Jac->data)[j])+offset;
- *       for (k=-mupper; k <= mlower; k++) {
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k
- *         col_j[k] = J_ij;
- *       }
- *     }
- * Caution: Jac->smu is generally NOT the same as mupper.
- *
- * The BAND_ELEM(A,i,j) macro is appropriate for use in small
- * problems in which efficiency of access is NOT a major concern.
- *
- * user_data is a pointer to user data - the same as the user_data
- *          parameter passed to CVodeSetFdata.
- *
- * NOTE: If the user's Jacobian routine needs other quantities,
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through
- *     CVodeGetCurrentStep and CVodeGetErrWeights, respectively
- *     (see cvode.h). The unit roundoff is available as
- *     UNIT_ROUNDOFF defined in sundials_types.h
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated for
- * vectors of length N which can be used by a CVDlsBandJacFn
- * as temporary storage or work space.
- *
- * A CVDlsBandJacFn should return 0 if successful, a positive value
- * if a recoverable error occurred, and a negative value if an 
- * unrecoverable error occurred.
- * -----------------------------------------------------------------
- */
 
-typedef int (*CVDlsBandJacFn)(long int N, long int mupper, long int mlower,
-			      realtype t, N_Vector y, N_Vector fy, 
-			      DlsMat Jac, void *user_data,
-			      N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS 
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the CVDLS linear solver
- * -----------------------------------------------------------------
- *
- * CVDlsSetDenseJacFn specifies the dense Jacobian approximation
- * routine to be used for a direct dense linear solver.
- *
- * CVDlsSetBandJacFn specifies the band Jacobian approximation
- * routine to be used for a direct band linear solver.
- *
- * By default, a difference quotient approximation, supplied with
- * the solver is used.
- *
- * The return value is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the CVODE memory was NULL
- *    CVDLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac);
-SUNDIALS_EXPORT int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the CVSDIRECT linear solver
- * -----------------------------------------------------------------
- *
- * CVDlsGetWorkSpace   returns the real and integer workspace used
- *                     by the direct linear solver.
- * CVDlsGetNumJacEvals returns the number of calls made to the
- *                     Jacobian evaluation routine jac.
- * CVDlsGetNumRhsEvals returns the number of calls to the user
- *                     f routine due to finite difference Jacobian
- *                     evaluation.
- * CVDlsGetLastFlag    returns the last error flag set by any of
- *                     the CVSDIRECT interface functions.
- *
- * The return value of CVDlsGet* is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the CVODES memory was NULL
- *    CVDLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals);
-SUNDIALS_EXPORT int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS);
-SUNDIALS_EXPORT int CVDlsGetLastFlag(void *cvode_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a CVSDIRECT return flag
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  EXPORTED FUNCTIONS 
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Required inputs to the CVSDLS linear solver interface
+  -----------------------------------------------------------------
+ 
+  CVDlsSetLinearSolver specifies the direct SUNLinearSolver object
+  that should be used.  This is required if CVodes is solving a 
+  problem using the Newton nonlinear solver (not the function 
+  iteration).
+ 
+  The return value is one of:
+     CVDLS_SUCCESS   if successful
+     CVDLS_MEM_NULL  if the CVODE memory was NULL
+     CVDLS_ILL_INPUT if the arguments are incompatible
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVDlsSetLinearSolver(void *cvode_mem, 
+                                         SUNLinearSolver LS,
+                                         SUNMatrix A);
 
+  
+/*-----------------------------------------------------------------
+  Optional inputs to the CVSDLS linear solver
+  -----------------------------------------------------------------
+ 
+  CVDlsSetJacFn specifies the dense/band/sparse Jacobian
+  approximation routine to be used for a direct linear solver.
+  By default, a difference quotient approximation is used for 
+  dense/band; no default exists for sparse (so this must be 
+  user-supplied).
+ 
+  The return value is one of:
+     CVDLS_SUCCESS   if successful
+     CVDLS_MEM_NULL  if the CVODE memory was NULL
+     CVDLS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVDlsSetJacFn(void *cvode_mem, CVDlsJacFn jac);
+
+
+/*-----------------------------------------------------------------
+  Optional outputs from the CVSSDLS linear solver interface
+  -----------------------------------------------------------------
+ 
+  CVDlsGetWorkSpace   returns the real and integer workspace used
+                      by the direct linear solver.
+  CVDlsGetNumJacEvals returns the number of calls made to the
+                      Jacobian evaluation routine jac.
+  CVDlsGetNumRhsEvals returns the number of calls to the user
+                      f routine due to finite difference Jacobian
+                      evaluation.
+  CVDlsGetLastFlag    returns the last error flag set by any of
+                      the CVSDIRECT interface functions.
+ 
+  The return value of CVDlsGet* is one of:
+     CVDLS_SUCCESS   if successful
+     CVDLS_MEM_NULL  if the CVODES memory was NULL
+     CVDLS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+
+SUNDIALS_EXPORT int CVDlsGetWorkSpace(void *cvode_mem,
+                                      long int *lenrwLS,
+                                      long int *leniwLS);
+SUNDIALS_EXPORT int CVDlsGetNumJacEvals(void *cvode_mem,
+                                        long int *njevals);
+SUNDIALS_EXPORT int CVDlsGetNumRhsEvals(void *cvode_mem,
+                                        long int *nfevalsLS);
+SUNDIALS_EXPORT int CVDlsGetLastFlag(void *cvode_mem,
+                                     long int *flag);
+
+/*-----------------------------------------------------------------
+  The following function returns the name of the constant 
+  associated with a CVSDLS return flag
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT char *CVDlsGetReturnFlagName(long int flag);
 
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type: CVDlsDenseJacFnB
- * -----------------------------------------------------------------
- * A dense Jacobian approximation function jacB for the adjoint
- * (backward) problem must have the prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVDlsDenseJacFnB)(long int nB, realtype t,
-				N_Vector y, 
-				N_Vector yB, N_Vector fyB,
-				DlsMat JB, void *user_dataB, 
-				N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * Type: CVDlsDenseJacFnBS
- * -----------------------------------------------------------------
- * A dense Jacobian approximation function jacBS for the adjoint
- * (backward) problem, sensitivity-dependent case,  must have the
- *  prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVDlsDenseJacFnBS)(long int nB, realtype t,
-				N_Vector y, N_Vector *yS,
-				N_Vector yB, N_Vector fyB,
-				DlsMat JB, void *user_dataB, 
-				N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVDlsBandJacFnB
- * -----------------------------------------------------------------
- * A band Jacobian approximation function jacB for the adjoint 
- * (backward) problem must have the prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVDlsBandJacFnB)(long int nB, long int mupperB, long int mlowerB,
-			       realtype t, N_Vector y,
-			       N_Vector yB, N_Vector fyB,
-			       DlsMat JB, void *user_dataB, 
-			       N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVDlsBandJacFnBS
- * -----------------------------------------------------------------
- * A band Jacobian approximation function jacBS for the adjoint 
- * (backward) problem, sensitivity-dependent case, must have the
- * prototype given below.
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVDlsBandJacFnBS)(long int nB, long int mupperB, long int mlowerB,
-			       realtype t, N_Vector y, N_Vector *yS,
-			       N_Vector yB, N_Vector fyB,
-			       DlsMat JB, void *user_dataB,
-			       N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS 
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Functions: CVDlsSet*JacFnB and CVDlsSet*JacFnBS
- * -----------------------------------------------------------------
- * CVDlsSetDenseJacFnB and CVDlsSetBandJacFnB specify the dense and
- * band Jacobian functions, respectively, to be used by a
- * CVSDIRECT linear solver for the backward integration phase, when
- * the backward problem does not depend on forward sensitivities.
- * CVDlsSetDenseJacFnBS and CVDlsSetBandJacFnBS specify the Jacobian
- * functions when the backward problem does depend on sensitivities.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVDlsSetDenseJacFnB(void *cvode_mem, int which,
-                                        CVDlsDenseJacFnB jacB);
-
-SUNDIALS_EXPORT int CVDlsSetDenseJacFnBS(void *cvode_mem, int which,
-                                         CVDlsDenseJacFnBS jacBS);
-
-SUNDIALS_EXPORT int CVDlsSetBandJacFnB(void *cvode_mem, int which,
-                                       CVDlsBandJacFnB jacB);
-
-SUNDIALS_EXPORT int CVDlsSetBandJacFnBS(void *cvode_mem, int which,
-                                        CVDlsBandJacFnBS jacBS);
+/*=================================================================
+  PART II:  Backward Problems
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  FUNCTION TYPES
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Type: CVDlsJacFnB
+  -----------------------------------------------------------------
+  A Jacobian approximation function jacB for the adjoint
+  (backward) problem must have the prototype given below. 
+  -----------------------------------------------------------------*/
+typedef int (*CVDlsJacFnB)(realtype t, N_Vector y, N_Vector yB,
+                           N_Vector fyB, SUNMatrix JB,
+                           void *user_dataB, N_Vector tmp1B,
+                           N_Vector tmp2B, N_Vector tmp3B);
+
+/*-----------------------------------------------------------------
+  Type: CVDlsJacFnBS
+  -----------------------------------------------------------------
+  A Jacobian approximation function jacBS for the adjoint
+  (backward) problem, sensitivity-dependent case,  must have the
+  prototype given below. 
+  -----------------------------------------------------------------*/
+typedef int (*CVDlsJacFnBS)(realtype t, N_Vector y, N_Vector *yS,
+                            N_Vector yB, N_Vector fyB, SUNMatrix JB,
+                            void *user_dataB, N_Vector tmp1B,
+                            N_Vector tmp2B, N_Vector tmp3B);
+
+
+/*-----------------------------------------------------------------
+  EXPORTED FUNCTIONS 
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Required inputs for the CVSDLS linear solver interface:
+
+  CVDlsSetLinearSolverB specifies the direct SUNLinearSolver 
+  object that should be used for backward integration. The 
+  'which' argument is the int returned by CVodeCreateB.
+
+  The return value is one of:
+    CVDLS_SUCCESS   if successful
+    CVDLS_MEM_NULL  if the cvode memory was NULL
+    CVDLS_ILL_INPUT if the arguments are incompatible
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVDlsSetLinearSolverB(void *cvode_mem,
+                                          int which,
+                                          SUNLinearSolver LS,
+                                          SUNMatrix A);
+  
+/*-----------------------------------------------------------------
+  Functions: CVDlsSetJacFnB and CVDlsSetJacFnBS
+  -----------------------------------------------------------------
+  CVDlsSetJacFnB specifies the Jacobian function to be used by a
+  CVSDLS linear solver for the backward integration phase, when
+  the backward problem does not depend on forward sensitivities.
+  CVDlsSetJacFnBS specifies the Jacobian function when the backward
+  problem does depend on sensitivities.
+
+  The 'which' argument is the int returned by CVodeCreateB.
+ 
+  The return value is one of:
+     CVDLS_SUCCESS   if successful
+     CVDLS_MEM_NULL  if the CVODE memory was NULL
+     CVDLS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVDlsSetJacFnB(void *cvode_mem, int which,
+                                   CVDlsJacFnB jacB);
+SUNDIALS_EXPORT int CVDlsSetJacFnBS(void *cvode_mem, int which,
+                                    CVDlsJacFnBS jacBS);
 
 #ifdef __cplusplus
 }
diff --git a/include/cvodes/cvodes_klu.h b/include/cvodes/cvodes_klu.h
deleted file mode 100644
index 5aecedc..0000000
--- a/include/cvodes/cvodes_klu.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVKLU linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSKLU_H
-#define _CVSKLU_H
-
-#include "cvodes/cvodes_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVKLU
- * -----------------------------------------------------------------
- * A call to the CVKLU function links the main integrator      
- * with the CVKLU linear solver module.                        
- *                                                                
- * cv_mem is the pointer to integrator memory returned by        
- *     CVCreate.             
- *
- *                                                                
- * CVKLU returns:                                              
- *     CVSLU_SUCCESS   = 0  if successful                              
- *     CVSLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     CVSLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The KLU linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, CVKLU will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLU(void *cv_mem, int n, int nnz, int sparsetype); 
-
-/*
- * -----------------------------------------------------------------
- * CVKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to CVKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is CVSLS_SUCCESS = 0, CVSLS_MEM_NULL = -1,
- * CVSLS_LMEM_NULL = -2, CVSLS_ILL_INPUT = -3, or CVSLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLUReInit(void *cv_mem_v, int n, int nnz, 
-				  int reinit_type);
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in CVODE is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLUSetOrdering(void *cv_mem, int ordering_choice); 
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Function: CVKLUB
- * -----------------------------------------------------------------
- * CVKLUB is a wrapper around CVKLU. It attaches the CVKLU linear
- * solver to the backward problem memory block.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLUB(void *cvode_mem, int which, int n, int nnz, int sparsetype);
-
-
-/*
- * -----------------------------------------------------------------
- * Function: CVKLUReInitB
- * -----------------------------------------------------------------
- * CVKLUReInitB is a wrapper around CVKLUReInit. 
- * CVKLUReInitB pulls off the memory block associated with the
- * which parameter and reinitializes the KLU solver associated with that block.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLUReInitB(void *cvode_mem, int which, int n, int nnz, int reinit_type);
-
-/*
- * -----------------------------------------------------------------
- * Function: CVKLUSetOrderingB
- * -----------------------------------------------------------------
- * CVKLUSetOrderingB is a wrapper around CVKLUSetOrdering. 
- * CVKLUSetOrderingB pulls off the memory block associated with the
- * which parameter and sets the ordering for the solver associated with that block.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVKLUSetOrderingB(void *cv_mem, int which, int ordering_choice); 
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_lapack.h b/include/cvodes/cvodes_lapack.h
deleted file mode 100644
index 49304e7..0000000
--- a/include/cvodes/cvodes_lapack.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Header file for the CVODES dense linear solver CVSLAPACK.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSLAPACK_H
-#define _CVSLAPACK_H
-
-#include <cvodes/cvodes_direct.h>
-#include <sundials/sundials_lapack.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function: CVLapackDense
- * -----------------------------------------------------------------
- * A call to the CVLapackDense function links the main integrator
- * with the CVSLAPACK linear solver using dense Jacobians.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * The return value of CVLapackDense is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the CVODES memory was NULL
- *    CVDLS_MEM_FAIL  if there was a memory allocation failure
- *    CVDLS_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVLapackDense(void *cvode_mem, int N);
-
-/*
- * -----------------------------------------------------------------
- * Function: CVLapackBand
- * -----------------------------------------------------------------
- * A call to the CVLapackBand function links the main integrator
- * with the CVSLAPACK linear solver using banded Jacobians. 
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * N is the size of the ODE system.
- *
- * mupper is the upper bandwidth of the band Jacobian approximation.
- *
- * mlower is the lower bandwidth of the band Jacobian approximation.
- *
- * The return value of CVLapackBand is one of:
- *    CVDLS_SUCCESS   if successful
- *    CVDLS_MEM_NULL  if the CVODES memory was NULL
- *    CVDLS_MEM_FAIL  if there was a memory allocation failure
- *    CVDLS_ILL_INPUT if a required vector operation is missing or
- *                       if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower);
-
-/*
- * -----------------------------------------------------------------
- * Function: CVLapackDenseB
- * -----------------------------------------------------------------
- * CVLapackDenseB links the main CVODE integrator with the dense
- * CVSLAPACK linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVLapackDenseB(void *cvode_mem, int which, int nB);
-
-/*
- * -----------------------------------------------------------------
- * Function: CVLapackBandB
- * -----------------------------------------------------------------
- * CVLapackBandB links the main CVODE integrator with the band
- * CVSLAPACK linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVLapackBandB(void *cvode_mem, int which,
-                                  int nB, int mupperB, int mlowerB);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_sparse.h b/include/cvodes/cvodes_sparse.h
deleted file mode 100644
index 432840c..0000000
--- a/include/cvodes/cvodes_sparse.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the Sparse linear solver module in CVODES.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSSPARSE_H
-#define _CVSSPARSE_H
-
-#include <sundials/sundials_sparse.h>
-#include <sundials/sundials_nvector.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * C V S S P A R S E     C O N S T A N T S
- * =================================================================
- */
-
-/* 
- * -----------------------------------------------------------------
- * CVSSPARSE return values 
- * -----------------------------------------------------------------
- */
-
-#define CVSLS_SUCCESS           0
-#define CVSLS_MEM_NULL         -1
-#define CVSLS_LMEM_NULL        -2
-#define CVSLS_ILL_INPUT        -3
-#define CVSLS_MEM_FAIL         -4
-#define CVSLS_JAC_NOSET        -5
-#define CVSLS_PACKAGE_FAIL     -6
-
-/* Additional last_flag values */
-
-#define CVSLS_JACFUNC_UNRECVR  -7
-#define CVSLS_JACFUNC_RECVR    -8
-
-/* Return values for the adjoint module */
-
-#define CVSLS_NO_ADJ           -101
-#define CVSLS_LMEMB_NULL       -102
-
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : CVSlsSparseJacFn
- * -----------------------------------------------------------------
- *
- * A sparse Jacobian approximation function jac must be of type 
- * CVSlsSparseJacFn.
- * Its parameters are:                     
- *                                                                
- * t   is the current value of the independent variable t.        
- *                                                                
- * y   is the current value of the dependent variable vector,     
- *     namely the predicted value of y(t).                     
- *                                                                
- * fy  is the vector f(t,y).
- *     namely the predicted value of y'(t).                    
- *                                                                
- * JacMat is the compressed sparse column matrix (of type SlsMat)
- *     to be loaded by an CVSlsSparseJacFn routine with an approximation
- *     to the system Jacobian matrix
- *            J = J = (df_i/dy_j) at the point (t,y). 
- *     Note that JacMat is NOT preset to zero!
- *     Matrix data is for the nonzero entries of the Jacobian stored in
- *     compressed column format.  Row indices of entries in 
- *     column j are stored in J->rowvals[colptrs[j]] 
- *     through J->rowvals[colptrs[j+i]-1]
- *     and corresponding numerical values of the Jacobian are stored 
- *     in the same entries of J->data.
- * 
- * J_data is a pointer to user Jacobian data - the same as the    
- *     user_data parameter passed to CVodeSetFdata.                     
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an CVSparseJacFn routine 
- *     as temporary storage or work space.                     
- *                                                                
- * A CVSlsSparseJacFn should return                                
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- *
- * -----------------------------------------------------------------
- *
-  * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     CVodeGetCurrentStep and CVodeGetErrWeights, respectively 
- *     (see cvode.h). The unit roundoff is available as 
- *     UNIT_ROUNDOFF defined in sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
-  
-  
-typedef int (*CVSlsSparseJacFn)(realtype t,
-		     N_Vector y, N_Vector fy, 
-		     SlsMat JacMat, void *user_data,
-		     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the CVSPARSE linear solver
- * -----------------------------------------------------------------
- * CVSlsSetSparseJacFn specifies the Jacobian approximation
- * routine to be used for a sparse direct linear solver.
- *
- * The return value is one of:
- *    CVSLS_SUCCESS   if successful
- *    CVSLS_MEM_NULL  if the CVODE memory was NULL
- *    CVSLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSlsSetSparseJacFn(void *cvode_mem, CVSlsSparseJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the CVSLS linear solver
- * -----------------------------------------------------------------
- *
- * CVSlsGetNumJacEvals returns the number of calls made to the
- *                      Jacobian evaluation routine jac.
- * CVSlsGetLastFlag    returns the last error flag set by any of
- *                      the CVSLS interface functions.
- *
- * The return value of CVSlsGet* is one of:
- *    CVSLS_SUCCESS   if successful
- *    CVSLS_MEM_NULL  if the IDA memory was NULL
- *    CVSLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSlsGetNumJacEvals(void *cvode_mem, long int *njevals);
-SUNDIALS_EXPORT int CVSlsGetLastFlag(void *cvode_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a CVSLS return flag
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT char *CVSlsGetReturnFlagName(long int flag);
-
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type: CVSlsSparseJacFnB
- * -----------------------------------------------------------------
- * A sparse Jacobian approximation function jacB for the adjoint
- * (backward) problem must have the prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVSlsSparseJacFnB)(realtype t, N_Vector y, 
-				 N_Vector yB, N_Vector fyB,
-				 SlsMat JB, void *user_dataB, 
-				 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * Type: CVSlsSparseJacFnBS
- * -----------------------------------------------------------------
- * A sparse Jacobian approximation function jacBS for the adjoint
- * (backward) problem, sensitivity-dependent case,  must have the
- *  prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVSlsSparseJacFnBS)(realtype t,
-				  N_Vector y, N_Vector *yS,
-				  N_Vector yB, N_Vector fyB,
-				  SlsMat JB, void *user_dataB, 
-				  N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS 
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Functions: CVSlsSetSparseJacFnB and CVSlsSetSparseJacFnBS
- * -----------------------------------------------------------------
- * CVSlsSetSparseJacFnB specifies the sparse Jacobian functions to 
- * be used by a CVSPARSE linear solver for the backward integration phase
- * when the backward problem does not depend on forward sensitivities.
- * CVSlsSetSparseJacFnBS specifies the Jacobian
- * functions when the backward problem does depend on sensitivities.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSlsSetSparseJacFnB(void *cv_mem, int which, 
-					 CVSlsSparseJacFnB jacB);
-SUNDIALS_EXPORT int CVSlsSetSparseJacFnBS(void *cv_mem, int which, 
-					  CVSlsSparseJacFnBS jacBS);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_spbcgs.h b/include/cvodes/cvodes_spbcgs.h
deleted file mode 100644
index da87907..0000000
--- a/include/cvodes/cvodes_spbcgs.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4490 $
- * $Date: 2015-04-30 16:55:37 -0700 (Thu, 30 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODES scaled preconditioned 
- * Bi-CGSTAB linear solver, CVSPBCG.
- *
- * Part I contains function prototypes for using CVSPBCG on forward 
- * problems (IVP integration and/or FSA)
- *
- * Part II contains function prototypes for using CVSPBCG on adjoint 
- * (backward) problems
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSSPBCG_H
-#define _CVSSPBCG_H
-
-#include <cvodes/cvodes_spils.h>
-#include <sundials/sundials_spbcgs.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcg
- * -----------------------------------------------------------------
- * A call to the CVSpbcg function links the main CVODE integrator
- * with the CVSPBCG linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * pretype   is the type of user preconditioning to be done.
- *           This must be one of the four enumeration constants
- *           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
- *           in iterative.h. These correspond to no preconditioning,
- *           left preconditioning only, right preconditioning
- *           only, and both left and right preconditioning,
- *           respectively.
- *
- * maxl      is the maximum Krylov dimension. This is an
- *           optional input to the CVSPBCG solver. Pass 0 to
- *           use the default value CVSPILS_MAXL=5.
- *
- * The return value of CVSpbcg is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_MEM_FAIL  if there was a memory allocation failure
- *    CVSPILS_ILL_INPUT if a required vector operation is missing
- * The above constants are defined in cvodes_spils.h
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpbcg(void *cvode_mem, int pretype, int maxl);
-
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function: CVSpbcgB
- * -----------------------------------------------------------------
- * CVSpbcgB links the main CVODES integrator with the CVSpbcg
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpbcgB(void *cvode_mem, int which,
-                             int pretypeB, int maxlB);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_spgmr.h b/include/cvodes/cvodes_spgmr.h
deleted file mode 100644
index ff79405..0000000
--- a/include/cvodes/cvodes_spgmr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODES scaled preconditioned 
- * GMRES linear solver, CVSPGMR.
- *
- * Part I contains function prototypes for using CVSPGMR on forward 
- * problems (IVP integration and/or FSA)
- *
- * Part II contains function prototypes for using CVSPGMR on adjoint 
- * (backward) problems
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSSPGMR_H
-#define _CVSSPGMR_H
-
-#include <cvodes/cvodes_spils.h>
-#include <sundials/sundials_spgmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpgmr
- * -----------------------------------------------------------------
- * A call to the CVSpgmr function links the main CVODE integrator
- * with the CVSPGMR linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * pretype   is the type of user preconditioning to be done.
- *           This must be one of the four enumeration constants
- *           NONE, LEFT, RIGHT, or BOTH defined in iterative.h.
- *           These correspond to no preconditioning,
- *           left preconditioning only, right preconditioning
- *           only, and both left and right preconditioning,
- *           respectively.
- *
- * maxl      is the maximum Krylov dimension. This is an
- *           optional input to the CVSPGMR solver. Pass 0 to
- *           use the default value CVSPILS_MAXL=5.
- *
- * The return value of CVSpgmr is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_MEM_FAIL  if there was a memory allocation failure
- *    CVSPILS_ILL_INPUT if a required vector operation is missing
- * The above constants are defined in cvodes_spils.h
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpgmr(void *cvode_mem, int pretype, int maxl);
-
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function: CVSpgmrB
- * -----------------------------------------------------------------
- * CVSpgmrB links the main CVODES integrator with the CVSpgmr
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpgmrB(void *cvode_mem, int which,
-                             int pretypeB, int maxlB);
-  
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_spils.h b/include/cvodes/cvodes_spils.h
index 252d911..d40ecdb 100644
--- a/include/cvodes/cvodes_spils.h
+++ b/include/cvodes/cvodes_spils.h
@@ -1,22 +1,23 @@
-/*
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the common header file for the Scaled, Preconditioned
- * Iterative Linear Solvers in CVODES.
+ * This is the header file for the Scaled, Preconditioned Iterative 
+ * Linear Solver interface in CVODES.
  *
  * Part I contains type definitions and functions for using the 
  * iterative linear solvers on forward problems 
@@ -24,24 +25,22 @@
  *
  * Part II contains type definitions and functions for using the 
  * iterative linear solvers on adjoint (backward) problems
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _CVSSPILS_H
 #define _CVSSPILS_H
 
 #include <sundials/sundials_iterative.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_linearsolver.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * CVSPILS return values
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVSSPILS return values 
+  -----------------------------------------------------------------*/
 
 #define CVSPILS_SUCCESS          0
 #define CVSPILS_MEM_NULL        -1
@@ -49,454 +48,480 @@ extern "C" {
 #define CVSPILS_ILL_INPUT       -3
 #define CVSPILS_MEM_FAIL        -4
 #define CVSPILS_PMEM_NULL       -5
+#define CVSPILS_SUNLS_FAIL      -6
 
 /* Return values for the adjoint module */
 
 #define CVSPILS_NO_ADJ          -101
 #define CVSPILS_LMEMB_NULL      -102
 
-/*
- * -----------------------------------------------------------------
- * CVSPILS solver constants
- * -----------------------------------------------------------------
- * CVSPILS_MAXL   : default value for the maximum Krylov
- *                  dimension
- *
- * CVSPILS_MSBPRE : maximum number of steps between
- *                  preconditioner evaluations
- *
- * CVSPILS_DGMAX  : maximum change in gamma between
- *                  preconditioner evaluations
- *
- * CVSPILS_EPLIN  : default value for factor by which the
- *                  tolerance on the nonlinear iteration is
- *                  multiplied to get a tolerance on the linear
- *                  iteration
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVSSPILS solver constants
+  -----------------------------------------------------------------
+  CVSPILS_MSBPRE : maximum number of steps between
+                   preconditioner evaluations
+ 
+  CVSPILS_DGMAX  : maximum change in gamma between
+                   preconditioner evaluations
+ 
+  CVSPILS_EPLIN  : default value for factor by which the
+                   tolerance on the nonlinear iteration is
+                   multiplied to get a tolerance on the linear
+                   iteration
+  -----------------------------------------------------------------*/
 
-#define CVSPILS_MAXL   5
 #define CVSPILS_MSBPRE 50
 #define CVSPILS_DGMAX  RCONST(0.2)
 #define CVSPILS_EPLIN  RCONST(0.05)
 
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSetupFn
- * -----------------------------------------------------------------
- * The user-supplied preconditioner setup function PrecSetup and
- * the user-supplied preconditioner solve function PrecSolve
- * together must define left and right preconditoner matrices
- * P1 and P2 (either of which may be trivial), such that the
- * product P1*P2 is an approximation to the Newton matrix
- * M = I - gamma*J.  Here J is the system Jacobian J = df/dy,
- * and gamma is a scalar proportional to the integration step
- * size h.  The solution of systems P z = r, with P = P1 or P2,
- * is to be carried out by the PrecSolve function, and PrecSetup
- * is to do any necessary setup operations.
- *
- * The user-supplied preconditioner setup function PrecSetup
- * is to evaluate and preprocess any Jacobian-related data
- * needed by the preconditioner solve function PrecSolve.
- * This might include forming a crude approximate Jacobian,
- * and performing an LU factorization on the resulting
- * approximation to M.  This function will not be called in
- * advance of every call to PrecSolve, but instead will be called
- * only as often as necessary to achieve convergence within the
- * Newton iteration.  If the PrecSolve function needs no
- * preparation, the PrecSetup function can be NULL.
- *
- * For greater efficiency, the PrecSetup function may save
- * Jacobian-related data and reuse it, rather than generating it
- * from scratch.  In this case, it should use the input flag jok
- * to decide whether to recompute the data, and set the output
- * flag *jcurPtr accordingly.
- *
- * Each call to the PrecSetup function is preceded by a call to
- * the RhsFn f with the same (t,y) arguments.  Thus the PrecSetup
- * function can use any auxiliary data that is computed and
- * saved by the f function and made accessible to PrecSetup.
- *
- * A function PrecSetup must have the prototype given below.
- * Its parameters are as follows:
- *
- * t       is the current value of the independent variable.
- *
- * y       is the current value of the dependent variable vector,
- *          namely the predicted value of y(t).
- *
- * fy      is the vector f(t,y).
- *
- * jok     is an input flag indicating whether Jacobian-related
- *         data needs to be recomputed, as follows:
- *           jok == FALSE means recompute Jacobian-related data
- *                  from scratch.
- *           jok == TRUE  means that Jacobian data, if saved from
- *                  the previous PrecSetup call, can be reused
- *                  (with the current value of gamma).
- *         A Precset call with jok == TRUE can only occur after
- *         a call with jok == FALSE.
- *
- * jcurPtr is a pointer to an output integer flag which is
- *         to be set by PrecSetup as follows:
- *         Set *jcurPtr = TRUE if Jacobian data was recomputed.
- *         Set *jcurPtr = FALSE if Jacobian data was not recomputed,
- *                        but saved data was reused.
- *
- * gamma   is the scalar appearing in the Newton matrix.
- *
- * user_data  is a pointer to user data - the same as the user_data
- *         parameter passed to the CVodeSetUserData function.
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated
- *                      for N_Vectors which can be used by
- *                      CVSpilsPrecSetupFn as temporary storage or
- *                      work space.
- *
- * NOTE: If the user's preconditioner needs other quantities,
- *       they are accessible as follows: hcur (the current stepsize)
- *       and ewt (the error weight vector) are accessible through
- *       CVodeGetCurrentStep and CVodeGetErrWeights, respectively).
- *       The unit roundoff is available as UNIT_ROUNDOFF defined in
- *       sundials_types.h.
- *
- * Returned value:
- * The value to be returned by the PrecSetup function is a flag
- * indicating whether it was successful.  This value should be
- *   0   if successful,
- *   > 0 for a recoverable error (step will be retried),
- *   < 0 for an unrecoverable error (integration is halted).
- * -----------------------------------------------------------------
- */
-
+/*-----------------------------------------------------------------
+  PART I - forward problems
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsPrecSetupFn
+  -----------------------------------------------------------------
+  The user-supplied preconditioner setup function PrecSetup and
+  the user-supplied preconditioner solve function PrecSolve
+  together must define left and right preconditoner matrices
+  P1 and P2 (either of which may be trivial), such that the
+  product P1*P2 is an approximation to the Newton matrix
+  M = I - gamma*J.  Here J is the system Jacobian J = df/dy,
+  and gamma is a scalar proportional to the integration step
+  size h.  The solution of systems P z = r, with P = P1 or P2,
+  is to be carried out by the PrecSolve function, and PrecSetup
+  is to do any necessary setup operations.
+ 
+  The user-supplied preconditioner setup function PrecSetup
+  is to evaluate and preprocess any Jacobian-related data
+  needed by the preconditioner solve function PrecSolve.
+  This might include forming a crude approximate Jacobian,
+  and performing an LU factorization on the resulting
+  approximation to M.  This function will not be called in
+  advance of every call to PrecSolve, but instead will be called
+  only as often as necessary to achieve convergence within the
+  Inexact Newton iteration.  If the PrecSolve function needs no
+  preparation, the PrecSetup function can be NULL.
+ 
+  For greater efficiency, the PrecSetup function may save
+  Jacobian-related data and reuse it, rather than generating it
+  from scratch.  In this case, it should use the input flag jok
+  to decide whether to recompute the data, and set the output
+  flag *jcurPtr accordingly.
+ 
+  Each call to the PrecSetup function is preceded by a call to
+  the RhsFn f with the same (t,y) arguments.  Thus the PrecSetup
+  function can use any auxiliary data that is computed and
+  saved by the f function and made accessible to PrecSetup.
+ 
+  A function PrecSetup must have the prototype given below.
+  Its parameters are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+           namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  jok     is an input flag indicating whether Jacobian-related
+          data needs to be recomputed, as follows:
+            jok == SUNFALSE means recompute Jacobian-related data
+                   from scratch.
+            jok == SUNTRUE  means that Jacobian data, if saved from
+                   the previous PrecSetup call, can be reused
+                   (with the current value of gamma).
+          A Precset call with jok == SUNTRUE can only occur after
+          a call with jok == SUNFALSE.
+ 
+  jcurPtr is a pointer to an output integer flag which is
+          to be set by PrecSetup as follows:
+          Set *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+          Set *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
+                         but saved data was reused.
+ 
+  gamma   is the scalar appearing in the Newton matrix.
+ 
+  user_data  is a pointer to user data - the same as the user_data
+          parameter passed to the CVodeSetUserData function.
+ 
+  NOTE: If the user's preconditioner needs other quantities,
+        they are accessible as follows: hcur (the current stepsize)
+        and ewt (the error weight vector) are accessible through
+        CVodeGetCurrentStep and CVodeGetErrWeights, respectively).
+        The unit roundoff is available as UNIT_ROUNDOFF defined in
+        sundials_types.h.
+ 
+  Returned value:
+  The value to be returned by the PrecSetup function is a flag
+  indicating whether it was successful.  This value should be
+    0   if successful,
+    > 0 for a recoverable error (step will be retried),
+    < 0 for an unrecoverable error (integration is halted).
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsPrecSetupFn)(realtype t, N_Vector y, N_Vector fy,
 				  booleantype jok, booleantype *jcurPtr,
-				  realtype gamma, void *user_data,
-				  N_Vector tmp1, N_Vector tmp2,
-				  N_Vector tmp3);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSolveFn
- * -----------------------------------------------------------------
- * The user-supplied preconditioner solve function PrecSolve
- * is to solve a linear system P z = r in which the matrix P is
- * one of the preconditioner matrices P1 or P2, depending on the
- * type of preconditioning chosen.
- *
- * A function PrecSolve must have the prototype given below.
- * Its parameters are as follows:
- *
- * t      is the current value of the independent variable.
- *
- * y      is the current value of the dependent variable vector.
- *
- * fy     is the vector f(t,y).
- *
- * r      is the right-hand side vector of the linear system.
- *
- * z      is the output vector computed by PrecSolve.
- *
- * gamma  is the scalar appearing in the Newton matrix.
- *
- * delta  is an input tolerance for use by PSolve if it uses
- *        an iterative method in its solution.  In that case,
- *        the residual vector Res = r - P z of the system
- *        should be made less than delta in weighted L2 norm,
- *        i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta.
- *        Note: the error weight vector ewt can be obtained
- *        through a call to the routine CVodeGetErrWeights.
- *
- * lr     is an input flag indicating whether PrecSolve is to use
- *        the left preconditioner P1 or right preconditioner
- *        P2: lr = 1 means use P1, and lr = 2 means use P2.
- *
- * user_data is a pointer to user data - the same as the user_data
- *        parameter passed to the CVodeSetUserData function.
- *
- * tmp    is a pointer to memory allocated for an N_Vector
- *        which can be used by PSolve for work space.
- *
- * Returned value:
- * The value to be returned by the PrecSolve function is a flag
- * indicating whether it was successful.  This value should be
- *   0 if successful,
- *   positive for a recoverable error (step will be retried),
- *   negative for an unrecoverable error (integration is halted).
- * -----------------------------------------------------------------
- */
-
+				  realtype gamma, void *user_data);
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsPrecSolveFn
+  -----------------------------------------------------------------
+  The user-supplied preconditioner solve function PrecSolve
+  is to solve a linear system P z = r in which the matrix P is
+  one of the preconditioner matrices P1 or P2, depending on the
+  type of preconditioning chosen.
+ 
+  A function PrecSolve must have the prototype given below.
+  Its parameters are as follows:
+ 
+  t      is the current value of the independent variable.
+ 
+  y      is the current value of the dependent variable vector.
+ 
+  fy     is the vector f(t,y).
+ 
+  r      is the right-hand side vector of the linear system.
+ 
+  z      is the output vector computed by PrecSolve.
+ 
+  gamma  is the scalar appearing in the Newton matrix.
+ 
+  delta  is an input tolerance for use by PSolve if it uses
+         an iterative method in its solution.  In that case,
+         the residual vector Res = r - P z of the system
+         should be made less than delta in weighted L2 norm,
+         i.e., sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta.
+         Note: the error weight vector ewt can be obtained
+         through a call to the routine CVodeGetErrWeights.
+ 
+  lr     is an input flag indicating whether PrecSolve is to use
+         the left preconditioner P1 or right preconditioner
+         P2: lr = 1 means use P1, and lr = 2 means use P2.
+ 
+  user_data is a pointer to user data - the same as the user_data
+         parameter passed to the CVodeSetUserData function.
+ 
+  Returned value:
+  The value to be returned by the PrecSolve function is a flag
+  indicating whether it was successful.  This value should be
+    0 if successful,
+    positive for a recoverable error (step will be retried),
+    negative for an unrecoverable error (integration is halted).
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsPrecSolveFn)(realtype t, N_Vector y, N_Vector fy,
-				  N_Vector r, N_Vector z,
-				  realtype gamma, realtype delta,
-				  int lr, void *user_data, N_Vector tmp);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsJacTimesVecFn
- * -----------------------------------------------------------------
- * The user-supplied function jtimes is to generate the product
- * J*v for given v, where J is the Jacobian df/dy, or an
- * approximation to it, and v is a given vector. It should return
- * 0 if successful a positive value for a recoverable error or 
- * a negative value for an unrecoverable failure.
- *
- * A function jtimes must have the prototype given below. Its
- * parameters are as follows:
- *
- *   v        is the N_Vector to be multiplied by J.
- *
- *   Jv       is the output N_Vector containing J*v.
- *
- *   t        is the current value of the independent variable.
- *
- *   y        is the current value of the dependent variable
- *            vector.
- *
- *   fy       is the vector f(t,y).
- *
- *   user_data   is a pointer to user data, the same as the user_data
- *            parameter passed to the CVodeSetUserData function. 
- *
- *   tmp      is a pointer to memory allocated for an N_Vector
- *            which can be used by Jtimes for work space.
- * -----------------------------------------------------------------
- */
-
+				  N_Vector r, N_Vector z, realtype gamma, 
+				  realtype delta, int lr, void *user_data);
+
+/*---------------------------------------------------------------
+  Type: CVSpilsJacTimesSetupFn
+ 
+  The user-supplied Jacobian-times-vector product setup function 
+  JacTimesSetup and the user-supplied Jacobian-times-vector 
+  product function JTimes together must generate the product
+  J*v for v, where J is the Jacobian df/dy, or an approximation 
+  to it, and v is a given vector. It should return 0 if 
+  successful a positive value for a recoverable error or a
+  negative value for an unrecoverable failure.
+ 
+  Each call to the JacTimesSetup function is preceded by a call 
+  to the RhsFn fi with the same (t,y) arguments.  Thus the 
+  JacTimesSetup function can use any auxiliary data that is 
+  computed and saved by the f function and made accessible to 
+  JacTimesSetup.
+ 
+  A function JacTimesSetup must have the prototype given below.
+  Its parameters are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+           namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  user_data  is a pointer to user data - the same as the user_data
+          parameter passed to the CVodeSetUserData function.
+ 
+  Returned value:
+  The value to be returned by the JacTimesSetup function is a flag
+  indicating whether it was successful.  This value should be
+    0   if successful,
+    > 0 for a recoverable error (step will be retried),
+    < 0 for an unrecoverable error (integration is halted).
+  ---------------------------------------------------------------*/
+typedef int (*CVSpilsJacTimesSetupFn)(realtype t, N_Vector y, 
+                                      N_Vector fy, void *user_data);
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsJacTimesVecFn
+  -----------------------------------------------------------------
+  The user-supplied function jtimes is to generate the product
+  J*v for given v, where J is the Jacobian df/dy, or an
+  approximation to it, and v is a given vector. It should return
+  0 if successful a positive value for a recoverable error or 
+  a negative value for an unrecoverable failure.
+ 
+  A function jtimes must have the prototype given below. Its
+  parameters are as follows:
+ 
+    v        is the N_Vector to be multiplied by J.
+ 
+    Jv       is the output N_Vector containing J*v.
+ 
+    t        is the current value of the independent variable.
+ 
+    y        is the current value of the dependent variable
+             vector.
+ 
+    fy       is the vector f(t,y).
+ 
+    user_data   is a pointer to user data, the same as the user_data
+             parameter passed to the CVodeSetUserData function. 
+ 
+    tmp      is a pointer to memory allocated for an N_Vector
+             which can be used by Jtimes for work space.
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv, realtype t,
 				    N_Vector y, N_Vector fy,
 				    void *user_data, N_Vector tmp);
 
+/*=================================================================
+  CVSSPILS Exported functions
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Required inputs to the CVSSPILS linear solver interface
+  -----------------------------------------------------------------
+ 
+  CVSpilsSetLinearSolver specifies the iterative SUNLinearSolver 
+  object that CVode should use.  This is required if CVode is 
+  solving a problem with the Newton nonlinear solver (i.e. not the 
+  functional iteration).
+ 
+  The return value is one of:
+     CVSPILS_SUCCESS   if successful
+     CVSPILS_MEM_NULL  if the CVODE memory was NULL
+     CVSPILS_ILL_INPUT if the linear solver memory was NULL
+ ---------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVSpilsSetLinearSolver(void *cvode_mem, 
+                                           SUNLinearSolver LS);
+
+
+/*-----------------------------------------------------------------
+  Optional inputs to the CVSSPILS linear solver
+  -----------------------------------------------------------------
+ 
+  CVSpilsSetEpsLin specifies the factor by which the tolerance on
+                 the nonlinear iteration is multiplied to get a
+                 tolerance on the linear iteration.
+                 Default value is 0.05.
+ 
+  CVSpilsSetPreconditioner specifies the PrecSetup and PrecSolve 
+                 functions.  Default is NULL for both arguments 
+                 (no preconditioning)
+ 
+  CVSpilsSetJacTimes specifies the jtsetup and jtimes functions. 
+                 Default is to use an internal finite difference 
+                 approximation routine with no extra jtsetup.
+ 
+  The return value of CVSpilsSet* is one of:
+     CVSPILS_SUCCESS   if successful
+     CVSPILS_MEM_NULL  if the cvode memory was NULL
+     CVSPILS_LMEM_NULL if the linear solver memory was NULL
+     CVSPILS_ILL_INPUT if an input has an illegal value
+  -----------------------------------------------------------------*/
 
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the CVSPILS linear solver
- * -----------------------------------------------------------------
- *
- * CVSpilsSetPrecType resets the type of preconditioner, pretype,
- *                from the value previously set.
- *                This must be one of PREC_NONE, PREC_LEFT, 
- *                PREC_RIGHT, or PREC_BOTH.
- *
- * CVSpilsSetGSType specifies the type of Gram-Schmidt
- *                orthogonalization to be used. This must be one of
- *                the two enumeration constants MODIFIED_GS or
- *                CLASSICAL_GS defined in iterative.h. These correspond
- *                to using modified Gram-Schmidt and classical
- *                Gram-Schmidt, respectively.
- *                Default value is MODIFIED_GS.
- *
- * CVSpilsSetMaxl resets the maximum Krylov subspace size, maxl,
- *                from the value previously set.
- *                An input value <= 0, gives the default value.
- *
- * CVSpilsSetEpsLin specifies the factor by which the tolerance on
- *                the nonlinear iteration is multiplied to get a
- *                tolerance on the linear iteration.
- *                Default value is 0.05.
- *
- * CVSpilsSetPreconditioner specifies the PrecSetup and PrecSolve functions.
- *                Default is NULL for both arguments (no preconditioning).
- *
- * CVSpilsSetJacTimesVecFn specifies the jtimes function. Default is to use 
- *                an internal finite difference approximation routine.
- *
- * The return value of CVSpilsSet* is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_LMEM_NULL if the linear solver memory was NULL
- *    CVSPILS_ILL_INPUT if an input has an illegal value
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpilsSetPrecType(void *cvode_mem, int pretype);
-SUNDIALS_EXPORT int CVSpilsSetGSType(void *cvode_mem, int gstype);
-SUNDIALS_EXPORT int CVSpilsSetMaxl(void *cvode_mem, int maxl);
 SUNDIALS_EXPORT int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac);
 SUNDIALS_EXPORT int CVSpilsSetPreconditioner(void *cvode_mem,
                                              CVSpilsPrecSetupFn pset, 
 					     CVSpilsPrecSolveFn psolve);
-SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFn(void *cvode_mem,
-                                            CVSpilsJacTimesVecFn jtv);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the CVSPILS linear solver
- * -----------------------------------------------------------------
- * CVSpilsGetWorkSpace returns the real and integer workspace used
- *                by the SPILS module.
- *
- * CVSpilsGetNumPrecEvals returns the number of preconditioner
- *                 evaluations, i.e. the number of calls made
- *                 to PrecSetup with jok==FALSE.
- *
- * CVSpilsGetNumPrecSolves returns the number of calls made to
- *                 PrecSolve.
- *
- * CVSpilsGetNumLinIters returns the number of linear iterations.
- *
- * CVSpilsGetNumConvFails returns the number of linear
- *                 convergence failures.
- *
- * CVSpilsGetNumJtimesEvals returns the number of calls to jtimes.
- *
- * CVSpilsGetNumRhsEvals returns the number of calls to the user
- *                 f routine due to finite difference Jacobian
- *                 times vector evaluation.
- *
- * CVSpilsGetLastFlag returns the last error flag set by any of
- *                 the CVSPILS interface functions.
- *
- * The return value of CVSpilsGet* is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals);
-SUNDIALS_EXPORT int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves);
-SUNDIALS_EXPORT int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters);
-SUNDIALS_EXPORT int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails);
-SUNDIALS_EXPORT int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals);
-SUNDIALS_EXPORT int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS); 
-SUNDIALS_EXPORT int CVSpilsGetLastFlag(void *cvode_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a CVSPILS return flag
- * -----------------------------------------------------------------
- */
-  
+SUNDIALS_EXPORT int CVSpilsSetJacTimes(void *cvode_mem,
+                                       CVSpilsJacTimesSetupFn jtsetup,
+                                       CVSpilsJacTimesVecFn jtimes);
+
+/*-----------------------------------------------------------------
+  Optional outputs from the CVSSPILS linear solver
+  -----------------------------------------------------------------
+  CVSpilsGetWorkSpace returns the real and integer workspace used
+                 by the SPILS module.
+ 
+  CVSpilsGetNumPrecEvals returns the number of preconditioner
+                  evaluations, i.e. the number of calls made
+                  to PrecSetup with jok==SUNFALSE.
+ 
+  CVSpilsGetNumPrecSolves returns the number of calls made to
+                  PrecSolve.
+ 
+  CVSpilsGetNumLinIters returns the number of linear iterations.
+ 
+  CVSpilsGetNumConvFails returns the number of linear
+                  convergence failures.
+ 
+  CVSpilsGetNumJTSetupEvals returns the number of calls to jtsetup.
+ 
+  CVSpilsGetNumJtimesEvals returns the number of calls to jtimes.
+ 
+  CVSpilsGetNumRhsEvals returns the number of calls to the user
+                  f routine due to finite difference Jacobian
+                  times vector evaluation.
+ 
+  CVSpilsGetLastFlag returns the last error flag set by any of
+                  the CVSPILS interface functions.
+ 
+  The return value of CVSpilsGet* is one of:
+     CVSPILS_SUCCESS   if successful
+     CVSPILS_MEM_NULL  if the cvode memory was NULL
+     CVSPILS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+
+SUNDIALS_EXPORT int CVSpilsGetWorkSpace(void *cvode_mem,
+                                        long int *lenrwLS,
+                                        long int *leniwLS);
+SUNDIALS_EXPORT int CVSpilsGetNumPrecEvals(void *cvode_mem,
+                                           long int *npevals);
+SUNDIALS_EXPORT int CVSpilsGetNumPrecSolves(void *cvode_mem,
+                                            long int *npsolves);
+SUNDIALS_EXPORT int CVSpilsGetNumLinIters(void *cvode_mem,
+                                          long int *nliters);
+SUNDIALS_EXPORT int CVSpilsGetNumConvFails(void *cvode_mem,
+                                           long int *nlcfails);
+SUNDIALS_EXPORT int CVSpilsGetNumJTSetupEvals(void *cvode_mem,
+                                              long int *njtsetups);
+SUNDIALS_EXPORT int CVSpilsGetNumJtimesEvals(void *cvode_mem,
+                                             long int *njvevals);
+SUNDIALS_EXPORT int CVSpilsGetNumRhsEvals(void *cvode_mem,
+                                          long int *nfevalsLS); 
+SUNDIALS_EXPORT int CVSpilsGetLastFlag(void *cvode_mem,
+                                       long int *flag);
+
+/*-----------------------------------------------------------------
+  The following function returns the name of the constant 
+  associated with a CVSSPILS return flag
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT char *CVSpilsGetReturnFlagName(long int flag);
 
 
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSetupFnB
- * -----------------------------------------------------------------
- * A function PrecSetupB for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVSpilsPrecSetupFnB)(realtype t, N_Vector y,
-                                   N_Vector yB, N_Vector fyB,
-                                   booleantype jokB,
-                                   booleantype *jcurPtrB, realtype gammaB,
-                                   void *user_dataB,
-                                   N_Vector tmp1B, N_Vector tmp2B,
-                                   N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSetupFnBS
- * -----------------------------------------------------------------
- * A function PrecSetupBS for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVSpilsPrecSetupFnBS)(realtype t, N_Vector y, N_Vector *yS,
-                                    N_Vector yB, N_Vector fyB,
-                                    booleantype jokB,
-                                    booleantype *jcurPtrB, realtype gammaB,
-                                    void *user_dataB,
-                                    N_Vector tmp1B, N_Vector tmp2B,
-                                    N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSolveFnB
- * -----------------------------------------------------------------
- * A function PrecSolveB for the adjoint (backward) problem  must 
- * have the prototype given below.
- * -----------------------------------------------------------------
- */
-
-typedef int (*CVSpilsPrecSolveFnB)(realtype t, N_Vector y,
-                                   N_Vector yB, N_Vector fyB,
-                                   N_Vector rB, N_Vector zB,
-                                   realtype gammaB, realtype deltaB,
-                                   int lrB, void *user_dataB, N_Vector tmpB);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsPrecSolveFnBS
- * -----------------------------------------------------------------
- * A function PrecSolveBS for the adjoint (backward) problem  must 
- * have the prototype given below.
- * -----------------------------------------------------------------
- */
-
+/*-----------------------------------------------------------------
+  PART II - backward problems
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsPrecSetupFnB
+  -----------------------------------------------------------------
+  A function PrecSetupB for the adjoint (backward) problem must 
+  have the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*CVSpilsPrecSetupFnB)(realtype t, N_Vector y, N_Vector yB,
+                                   N_Vector fyB, booleantype jokB,
+                                   booleantype *jcurPtrB,
+                                   realtype gammaB, void *user_dataB);
+
+
+/*----------------------------------------------------------------
+  Type : CVSpilsPrecSetupFnBS
+  -----------------------------------------------------------------
+  A function PrecSetupBS for the adjoint (backward) problem must 
+  have the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*CVSpilsPrecSetupFnBS)(realtype t, N_Vector y,
+                                    N_Vector *yS, N_Vector yB,
+                                    N_Vector fyB, booleantype jokB,
+                                    booleantype *jcurPtrB,
+                                    realtype gammaB, void *user_dataB);
+
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsPrecSolveFnB
+  -----------------------------------------------------------------
+  A function PrecSolveB for the adjoint (backward) problem  must 
+  have the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*CVSpilsPrecSolveFnB)(realtype t, N_Vector y, N_Vector yB, 
+                                   N_Vector fyB, N_Vector rB, 
+                                   N_Vector zB, realtype gammaB,
+                                   realtype deltaB, int lrB,
+                                   void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsPrecSolveFnBS
+  -----------------------------------------------------------------
+  A function PrecSolveBS for the adjoint (backward) problem  must 
+  have the prototype given below.
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsPrecSolveFnBS)(realtype t, N_Vector y, N_Vector *yS,
                                     N_Vector yB, N_Vector fyB,
                                     N_Vector rB, N_Vector zB,
                                     realtype gammaB, realtype deltaB,
-                                    int lrB, void *user_dataB, N_Vector tmpB);
-
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsJacTimesVecFnB
- * -----------------------------------------------------------------
- * A function jtimesB for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
-
+                                    int lrB, void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsJacTimesSetupFnB
+  -----------------------------------------------------------------
+  A function jtsetupB for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*CVSpilsJacTimesSetupFnB)(realtype t, N_Vector y, N_Vector yB,
+                                       N_Vector fyB, void *jac_dataB);
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsJacTimesSetupFnBS
+  -----------------------------------------------------------------
+  A function jtsetupBS for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*CVSpilsJacTimesSetupFnBS)(realtype t, N_Vector y,
+                                        N_Vector *yS, N_Vector yB,
+                                        N_Vector fyB, void *jac_dataB);
+
+/*-----------------------------------------------------------------
+  Type : CVSpilsJacTimesVecFnB
+  -----------------------------------------------------------------
+  A function jtimesB for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsJacTimesVecFnB)(N_Vector vB, N_Vector JvB, realtype t,
                                      N_Vector y, N_Vector yB, N_Vector fyB,
                                      void *jac_dataB, N_Vector tmpB);
 
-/*
- * -----------------------------------------------------------------
- * Type : CVSpilsJacTimesVecFnBS
- * -----------------------------------------------------------------
- * A function jtimesBS for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
-
+/*-----------------------------------------------------------------
+  Type : CVSpilsJacTimesVecFnBS
+  -----------------------------------------------------------------
+  A function jtimesBS for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
 typedef int (*CVSpilsJacTimesVecFnBS)(N_Vector vB, N_Vector JvB,
                                       realtype t, N_Vector y, N_Vector *yS,
                                       N_Vector yB, N_Vector fyB,
                                       void *jac_dataB, N_Vector tmpB);
 
-/*
- * -----------------------------------------------------------------
- * Functions
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Each CVSpilsSet***B or CVSpilsSet***BS function below links the
- * main CVODES integrator with the corresponding CVSpilsSet***
- * optional input function for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Functions
+  -----------------------------------------------------------------*/
+
+/*---------------------------------------------------------------
+  Required input for the CVSSPILS linear solver interface:
+
+  CVSpilsSetLinearSolverB specifies the iterative SUNLinearSolver 
+  object that should be used for the backwards integration.  The 
+  'which' argument is the int returned by CVodeCreateB.
+
+  The return value is one of:
+     CVSPILS_SUCCESS   if successful
+     CVSPILS_MEM_NULL  if the cvode memory was NULL
+     CVSPILS_ILL_INPUT if the linear solver memory was NULL
+  ---------------------------------------------------------------*/
+SUNDIALS_EXPORT int CVSpilsSetLinearSolverB(void *cvode_mem,
+                                            int which,
+                                            SUNLinearSolver LS);
+
+/*-----------------------------------------------------------------
+  Each CVSpilsSet***B or CVSpilsSet***BS function below links the
+  main CVODES integrator with the corresponding CVSpilsSet***
+  optional input function for the backward integration.
+  The 'which' argument is the int returned by CVodeCreateB.
+  -----------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int CVSpilsSetPrecTypeB(void *cvode_mem, int which, int pretypeB);
-SUNDIALS_EXPORT int CVSpilsSetGSTypeB(void *cvode_mem, int which, int gstypeB);
 SUNDIALS_EXPORT int CVSpilsSetEpsLinB(void *cvode_mem, int which, realtype eplifacB);
-SUNDIALS_EXPORT int CVSpilsSetMaxlB(void *cvode_mem, int which, int maxlB);
 
 SUNDIALS_EXPORT int CVSpilsSetPreconditionerB(void *cvode_mem, int which, 
                                               CVSpilsPrecSetupFnB psetB,
@@ -505,11 +530,12 @@ SUNDIALS_EXPORT int CVSpilsSetPreconditionerBS(void *cvode_mem, int which,
                                                CVSpilsPrecSetupFnBS psetBS,
 					       CVSpilsPrecSolveFnBS psolveBS);
 
-SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which, 
-                                             CVSpilsJacTimesVecFnB jtvB);
-SUNDIALS_EXPORT int CVSpilsSetJacTimesVecFnBS(void *cvode_mem, int which, 
-                                              CVSpilsJacTimesVecFnBS jtvBS);
-
+SUNDIALS_EXPORT int CVSpilsSetJacTimesB(void *cvode_mem, int which, 
+                                        CVSpilsJacTimesSetupFnB jtsetupB,
+                                        CVSpilsJacTimesVecFnB jtimesB);
+SUNDIALS_EXPORT int CVSpilsSetJacTimesBS(void *cvode_mem, int which, 
+                                         CVSpilsJacTimesSetupFnBS jtsetupBS,
+                                         CVSpilsJacTimesVecFnBS jtimesBS);
 
 #ifdef __cplusplus
 }
diff --git a/include/cvodes/cvodes_sptfqmr.h b/include/cvodes/cvodes_sptfqmr.h
deleted file mode 100644
index f898eda..0000000
--- a/include/cvodes/cvodes_sptfqmr.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4488 $
- * $Date: 2015-04-29 16:39:48 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVODES scaled preconditioned TFQMR 
- * linear solver, CVSPTFQMR.
- *
- * Part I contains function prototypes for using CVSPTFQMR on forward 
- * problems (IVP integration and/or FSA)
- *
- * Part II contains function prototypes for using CVSPTFQMR on adjoint 
- * (backward) problems
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSSPTFQMR_H
-#define _CVSSPTFQMR_H
-
-#include <cvodes/cvodes_spils.h>
-#include <sundials/sundials_sptfqmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmr
- * -----------------------------------------------------------------
- * A call to the CVSptfqmr function links the main CVODE integrator
- * with the CVSPTFQMR linear solver.
- *
- * cvode_mem is the pointer to the integrator memory returned by
- *           CVodeCreate.
- *
- * pretype   is the type of user preconditioning to be done.
- *           This must be one of the four enumeration constants
- *           PREC_NONE, PREC_LEFT, PREC_RIGHT, or PREC_BOTH defined
- *           in iterative.h. These correspond to no preconditioning,
- *           left preconditioning only, right preconditioning
- *           only, and both left and right preconditioning,
- *           respectively.
- *
- * maxl      is the maximum Krylov dimension. This is an
- *           optional input to the CVSPTFQMR solver. Pass 0 to
- *           use the default value CVSPILS_MAXL=5.
- *
- * The return value of CVSptfqmr is one of:
- *    CVSPILS_SUCCESS   if successful
- *    CVSPILS_MEM_NULL  if the cvode memory was NULL
- *    CVSPILS_MEM_FAIL  if there was a memory allocation failure
- *    CVSPILS_ILL_INPUT if a required vector operation is missing
- * The above constants are defined in cvodes_spils.h
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSptfqmr(void *cvode_mem, int pretype, int maxl);
-
-
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function: CVSptfqmrB
- * -----------------------------------------------------------------
- * CVSptfqmrB links the main CVODES integrator with the CVSptfqmr
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int CVSptfqmrB(void *cvode_mem, int which,
-                               int pretypeB, int maxlB);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/cvodes/cvodes_superlumt.h b/include/cvodes/cvodes_superlumt.h
deleted file mode 100644
index 2f437cc..0000000
--- a/include/cvodes/cvodes_superlumt.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Rev $
- * $Date $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the CVSuperLUMT linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSSUPERLUMT_H
-#define _CVSSUPERLUMT_H
-
-#include "cvodes/cvodes_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSuperLUMT
- * -----------------------------------------------------------------
- * A call to the CVSuperLUMT function links the main integrator      
- * with the CVSuperLUMT linear solver module.                        
- *                                                                
- * cv_mem is the pointer to integrator memory returned by        
- *     CVCreate.             
- *
- *                                                                
- * CVSuperLUMT returns:                                              
- *     CVSLU_SUCCESS   = 0  if successful                              
- *     CVSLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     CVSLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The CVSuperLUMT linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, CVSuperLUMT will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVSuperLUMT(void *cv_mem, int num_threads,
-				  int n, int nnz); 
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVSuperLUMTSetOrdering sets the ordering used by CVSuperLUMT for 
- * reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int CVSuperLUMTSetOrdering(void *cv_mem, 
-					     int ordering_choice); 
-
-
-/*
- * -----------------------------------------------------------------
- * Function: CVSuperLUMTB
- * -----------------------------------------------------------------
- * CVSuperLUMTB links the main CVODES integrator with the CVSuperLUMT
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
- 
-  SUNDIALS_EXPORT int CVSuperLUMTB(void *cvode_mem, int which, int num_threads, 
-				   int nB, int nnzB);
- 
- 
-/*
- * -----------------------------------------------------------------
- * Function: CVSuperLUMTSetOrderingB
- * -----------------------------------------------------------------
- * CVSuperLUMTSetOrderingB pulls off the memory block associated with the
- * which parameter and sets the ordering for the solver associated with that block.
- * The 'which' argument is the int returned by CVodeCreateB.
- * -----------------------------------------------------------------
- */
- 
-  SUNDIALS_EXPORT int CVSuperLUMTSetOrderingB(void *cvode_mem, int which, 
-					      int ordering_choice);
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida.h b/include/ida/ida.h
index c9ceab1..6279339 100644
--- a/include/ida/ida.h
+++ b/include/ida/ida.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4845 $
- * $Date: 2016-08-03 15:45:09 -0700 (Wed, 03 Aug 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Allan G. Taylor, Alan C. Hindmarsh, Radu Serban,
  *                and Aaron Collier @ LLNL
@@ -291,9 +291,9 @@ SUNDIALS_EXPORT void *IDACreate(void);
  * IDASetSuppressAlg    | flag to indicate whether or not to      
  *                      | suppress algebraic variables in the     
  *                      | local error tests:                      
- *                      | FALSE = do not suppress;                 
- *                      | TRUE = do suppress;                     
- *                      | [FALSE]                                 
+ *                      | SUNFALSE = do not suppress;                 
+ *                      | SUNTRUE = do suppress;                     
+ *                      | [SUNFALSE]                                 
  *                      | NOTE: if suppressed algebraic variables 
  *                      | is selected, the nvector 'id' must be   
  *                      | supplied for identification of those    
@@ -516,18 +516,21 @@ SUNDIALS_EXPORT int IDAWFtolerances(void *ida_mem, IDAEwtFn efun);
  *                        |                                        
  * IDASetLineSearchOffIC  | a boolean flag to turn off the        
  *                        | linesearch algorithm.                 
- *                        | [FALSE]                               
+ *                        | [SUNFALSE]                               
  *                        |                                        
  * IDASetStepToleranceIC  | positive lower bound on the norm of   
  *                        | a Newton step.                        
  *                        | [(unit roundoff)^(2/3)                
- *                                                                
+ *                        |                                        
+ * IDASetMaxBacksIC       | maximum number of linesearch backtrack
+ *                        | operations per Newton iteration.
+ *                        | [100]
+ *
  * ---------------------------------------------------------------- 
  * Return flag:
  *   IDA_SUCCESS   if successful
  *   IDA_MEM_NULL  if the ida memory is NULL
  *   IDA_ILL_INPUT if an argument has an illegal value
- *
  * ----------------------------------------------------------------
  */
 
@@ -537,6 +540,7 @@ SUNDIALS_EXPORT int IDASetMaxNumJacsIC(void *ida_mem, int maxnj);
 SUNDIALS_EXPORT int IDASetMaxNumItersIC(void *ida_mem, int maxnit);
 SUNDIALS_EXPORT int IDASetLineSearchOffIC(void *ida_mem, booleantype lsoff);
 SUNDIALS_EXPORT int IDASetStepToleranceIC(void *ida_mem, realtype steptol);
+SUNDIALS_EXPORT int IDASetMaxBacksIC(void *ida_mem, int maxbacks);
 
 /*
  * -----------------------------------------------------------------
diff --git a/include/ida/ida_band.h b/include/ida/ida_band.h
deleted file mode 100644
index 1f2242d..0000000
--- a/include/ida/ida_band.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDABAND linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDABAND_H
-#define _IDABAND_H
-
-#include <ida/ida_direct.h>
-#include <sundials/sundials_band.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDABand
- * -----------------------------------------------------------------
- * A call to the IDABand function links the main integrator       
- * with the IDABAND linear solver module.                         
- *                                                                
- * ida_mem is the pointer to the integrator memory returned by    
- *         IDACreate.                                                   
- *                                                                
- * mupper is the upper bandwidth of the banded Jacobian matrix.   
- *                                                                
- * mlower is the lower bandwidth of the banded Jacobian matrix.   
- *                                                                
- * The return values of IDABand are:                              
- *     IDADLS_SUCCESS   = 0  if successful                            
- *     IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure 
- *     IDADLS_ILL_INPUT = -2 if the input was illegal or NVECTOR bad. 
- *                                                                
- * NOTE: The band linear solver assumes a serial implementation   
- *       of the NVECTOR package. Therefore, IDABand will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the N_VGetArrayPointer function exists.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDABand(void *ida_mem, long int Neq, long int mupper, long int mlower);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_bbdpre.h b/include/ida/ida_bbdpre.h
index 4c790fc..ec909ba 100644
--- a/include/ida/ida_bbdpre.h
+++ b/include/ida/ida_bbdpre.h
@@ -1,25 +1,26 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU,
+ *      Alan C. Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for the IDABBDPRE module, for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with IDA and
- * IDASPGMR/IDASPBCG/IDASPTFQMR.
+ * matrix with banded blocks, for use with IDA and the
+ * IDASpils solver interface.
  *
  * Summary:
  *
@@ -38,19 +39,28 @@
  * The user's calling program should have the following form:
  *
  *   #include <ida/ida_bbdpre.h>
+ *   #include <ida/ida_spils.h>
  *   #include <nvector_parallel.h>
  *   ...
+ *   void *ida_mem;
+ *   ...
  *   y0  = N_VNew_Parallel(...);
  *   yp0 = N_VNew_Parallel(...);
  *   ...
+ *   SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+ *   ...
  *   ida_mem = IDACreate(...);
  *   ier = IDAInit(...);
  *   ...
- *   flag = IDASptfqmr(ida_mem, maxl);
- *       -or-
- *   flag = IDASpgmr(ida_mem, maxl);
- *       -or-
- *   flag = IDASpbcg(ida_mem, maxl);
+ *   ier = IDASpilsSetLinearSolver(ida_mem, LS);
  *   ...
  *   flag = IDABBDPrecInit(ida_mem, Nlocal, mudq, mldq,
  *                         mukeep, mlkeep, dq_rel_yy, Gres, Gcomm);
@@ -58,9 +68,12 @@
  *   ier = IDASolve(...);
  *   ...
  *   IDAFree(&ida_mem);
- *
+ *   ...
  *   N_VDestroy(y0);
  *   N_VDestroy(yp0);
+ *   ...
+ *   SUNLinSolFree(LS);
+ *   ...
  *
  * The user-supplied routines required are:
  *
@@ -128,10 +141,11 @@ extern "C" {
  * the current solution vector yy, the current solution
  * derivative vector yp, and a pointer to the user-defined data
  * block user_data. It is to compute the local part of G(t,y,y')
- * and store it in the vector gval. (Providing memory for yy and
- * gval is handled within this preconditioner module.) It is
- * expected that this routine will save communicated data in work
- * space defined by the user, and made available to the
+ * and store it in the vector gval. 
+ * (Allocation of memory for yy and gval is handled within the 
+ * preconditioner module.) 
+ * It is expected that this routine will save communicated data 
+ * in work space defined by the user, and made available to the
  * preconditioner function for the problem. The user_data
  * parameter is the same as that passed by the user to the
  * IDASetUserdata routine.
@@ -141,7 +155,7 @@ extern "C" {
  * -----------------------------------------------------------------
  */
 
-typedef int (*IDABBDLocalFn)(long int Nlocal, realtype tt,
+typedef int (*IDABBDLocalFn)(sunindextype Nlocal, realtype tt,
 			     N_Vector yy, N_Vector yp, N_Vector gval,
 			     void *user_data);
 
@@ -173,7 +187,7 @@ typedef int (*IDABBDLocalFn)(long int Nlocal, realtype tt,
  * -----------------------------------------------------------------
  */
 
-typedef int (*IDABBDCommFn)(long int Nlocal, realtype tt,
+typedef int (*IDABBDCommFn)(sunindextype Nlocal, realtype tt,
 			    N_Vector yy, N_Vector yp,
 			    void *user_data);
 
@@ -220,11 +234,15 @@ typedef int (*IDABBDCommFn)(long int Nlocal, realtype tt,
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem, long int Nlocal,
-                                   long int mudq, long int mldq,
-                                   long int mukeep, long int mlkeep,
+SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem,
+                                   sunindextype Nlocal,
+                                   sunindextype mudq,
+                                   sunindextype mldq,
+                                   sunindextype mukeep,
+                                   sunindextype mlkeep,
                                    realtype dq_rel_yy,
-                                   IDABBDLocalFn Gres, IDABBDCommFn Gcomm);
+                                   IDABBDLocalFn Gres,
+                                   IDABBDCommFn Gcomm);
 
 /*
  * -----------------------------------------------------------------
@@ -232,10 +250,10 @@ SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem, long int Nlocal,
  * -----------------------------------------------------------------
  * IDABBDPrecReInit reinitializes the IDABBDPRE module when
  * solving a sequence of problems of the same size with
- * IDASPGMR/IDABBDPRE, IDASPBCG/IDABBDPRE, or IDASPTFQMR/IDABBDPRE
- * provided there is no change in Nlocal, mukeep, or mlkeep. After
- * solving one problem, and after calling IDAReInit to reinitialize
- * the integrator for a subsequent problem, call IDABBDPrecReInit.
+ * IDASPILS/IDABBDPRE provided there is no change in Nlocal, mukeep, 
+ * or mlkeep. After solving one problem, and after calling IDAReInit 
+ * to reinitialize the integrator for a subsequent problem, call 
+ * IDABBDPrecReInit.
  *
  * All arguments have the same names and meanings as those
  * of IDABBDPrecInit.
@@ -249,7 +267,8 @@ SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem, long int Nlocal,
  */
 
 SUNDIALS_EXPORT int IDABBDPrecReInit(void *ida_mem,
-				     long int mudq, long int mldq,
+				     sunindextype mudq,
+                                     sunindextype mldq,
 				     realtype dq_rel_yy);
 
 /*
@@ -270,8 +289,10 @@ SUNDIALS_EXPORT int IDABBDPrecReInit(void *ida_mem,
  */
 
 SUNDIALS_EXPORT int IDABBDPrecGetWorkSpace(void *ida_mem, 
-                                           long int *lenrwBBDP, long int *leniwBBDP);
-SUNDIALS_EXPORT int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP);
+                                           long int *lenrwBBDP,
+                                           long int *leniwBBDP);
+SUNDIALS_EXPORT int IDABBDPrecGetNumGfnEvals(void *ida_mem,
+                                             long int *ngevalsBBDP);
 
 #ifdef __cplusplus
 }
diff --git a/include/ida/ida_dense.h b/include/ida/ida_dense.h
deleted file mode 100644
index 3ea763e..0000000
--- a/include/ida/ida_dense.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDADENSE linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDADENSE_H
-#define _IDADENSE_H
-
-#include <ida/ida_direct.h>
-#include <sundials/sundials_dense.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDADense
- * -----------------------------------------------------------------
- * A call to the IDADense function links the main integrator      
- * with the IDADENSE linear solver module.                        
- *                                                                
- * ida_mem is the pointer to integrator memory returned by        
- *     IDACreate.                                                 
- *                                                                
- * Neq  is the problem size                                       
- *                                                                
- * IDADense returns:                                              
- *     IDADLS_SUCCESS   = 0  if successful                              
- *     IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     IDADLS_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The dense linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, IDADense will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADense(void *ida_mem, long int Neq); 
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_direct.h b/include/ida/ida_direct.h
index 401b719..e99fe01 100644
--- a/include/ida/ida_direct.h
+++ b/include/ida/ida_direct.h
@@ -1,21 +1,23 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4525 $
- * $Date: 2015-08-12 16:28:00 -0700 (Wed, 12 Aug 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common header file for the direct linear solvers in IDA.
+ * Common header file for the direct linear solver interface in IDA.
  * -----------------------------------------------------------------
  */
 
@@ -23,24 +25,19 @@
 #define _IDADLS_H
 
 #include <sundials/sundials_direct.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_linearsolver.h>
 #include <sundials/sundials_nvector.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * =================================================================
- *              I D A D I R E C T     C O N S T A N T S
- * =================================================================
- */
-
-/* 
- * -----------------------------------------------------------------
- * IDADLS return values 
- * -----------------------------------------------------------------
- */
+/*=================================================================
+   IDADLS Constants
+  =================================================================*/
 
+/* IDADLS return values */
 #define IDADLS_SUCCESS           0
 #define IDADLS_MEM_NULL         -1
 #define IDADLS_LMEM_NULL        -2
@@ -48,255 +45,147 @@ extern "C" {
 #define IDADLS_MEM_FAIL         -4
 
 /* Additional last_flag values */
-
 #define IDADLS_JACFUNC_UNRECVR  -5
 #define IDADLS_JACFUNC_RECVR    -6
+#define IDADLS_SUNMAT_FAIL      -7
+
+
+/*=================================================================
+   IDADLS user-supplied function prototypes
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Type: IDADlsJacFn
+
+  A Jacobian approximation function Jac must be of type IDADlsJacFn.
+  Its parameters are:                     
+                                                                 
+  t   is the current value of the independent variable.
+                                                                 
+  y   is the current value of the dependent variable vector,     
+      namely the predicted value of y(t).                     
+                                                                 
+  yp  is the current value of the derivative vector y',          
+      namely the predicted value of y'(t).                    
+                                                                 
+  r   is the residual vector F(tt,yy,yp).                     
+                                                                 
+  c_j is the scalar in the system Jacobian, proportional to 
+      the inverse of the step size h.
+                                                                 
+  user_data is a pointer to user Jacobian data - the same as the    
+      user_data parameter passed to IDASetUserData.                     
+                                                                 
+  Jac is the SUNMatrix to be loaded by an IDADlsJacFn routine 
+      with an approximation to the system Jacobian matrix                                  
+             J = dF/dy + c_j *dF/dy'
+      at the given point (t,y,y'), where the ODE system is given 
+      by F(t,y,y') = 0.   
+
+      Note that Jac is NOT preset to zero!
+                                                                 
+  tmp1, tmp2, tmp3 are pointers to memory allocated for          
+      N_Vectors which can be used by an IDADlsDenseJacFn routine 
+      as temporary storage or work space.                     
+                                                                 
+  A IDADlsDenseJacFn should return                                
+      0 if successful,                                           
+      a positive int if a recoverable error occurred, or         
+      a negative int if a nonrecoverable error occurred.         
+  In the case of a recoverable error return, the integrator will 
+  attempt to recover by reducing the stepsize (which changes c_j).
+ 
+  NOTE: See the relevant SUNMatrix implementation header files
+      and documentation for mechanisms to inquire about matrix 
+      dimensions, and for efficient ways to set matrix entries.
+                                                                
+                                                                
+  NOTE: If the user's Jacobian routine needs other quantities,   
+      they are accessible as follows: hcur (the current stepsize)
+      and ewt (the error weight vector) are accessible through   
+      IDAGetCurrentStep and IDAGetErrWeights, respectively, but this
+      requires including in user_data a pointer to the solver memory.
+      The unit roundoff is available as UNIT_ROUNDOFF defined in
+      sundials_types.h.
+ 
+  -----------------------------------------------------------------*/
+typedef int (*IDADlsJacFn)(realtype t, realtype c_j, N_Vector y,
+                           N_Vector yp, N_Vector r, SUNMatrix Jac,
+                           void *user_data, N_Vector tmp1,
+                           N_Vector tmp2, N_Vector tmp3);
+
+
+/*=================================================================
+   IDADLS Exported functions
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Required inputs for the IDADLS linear solver interface:
+
+  IDADlsSetLinearSolver specifies the direct SUNLinearSolver 
+  object that IDA should use.
+
+  The return value is one of:
+    IDADLS_SUCCESS   if successful
+    IDADLS_MEM_NULL  if the IDA memory was NULL
+    IDADLS_ILL_INPUT if the arguments are incompatible
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsSetLinearSolver(void *ida_mem, 
+                                          SUNLinearSolver LS,
+                                          SUNMatrix A);
+
+
+/*---------------------------------------------------------------
+ Optional inputs to the IDADLS linear solver interface:
+
+ IDADlsSetJacFn specifies the dense Jacobian approximation
+ routine to be used for a direct dense linear solver.
+ 
+ By default, a difference quotient approximation is used for 
+ dense and band; no default exists for sparse (so this must 
+ be user-supplied).
+ 
+ The return value is one of:
+    IDADLS_SUCCESS   if successful
+    IDADLS_MEM_NULL  if the IDA memory was NULL
+    IDADLS_LMEM_NULL if the linear solver memory was NULL
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsSetJacFn(void *ida_mem, IDADlsJacFn jac);
 
-/*
- * =================================================================
- *              F U N C T I O N   T Y P E S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDADlsDenseJacFn
- * -----------------------------------------------------------------
- *
- * A dense Jacobian approximation function djac must be of type 
- * IDADlsDenseJacFn.
- * Its parameters are:                     
- *                                                                
- * N   is the problem size, and length of all vector arguments.   
- *                                                                
- * t   is the current value of the independent variable t.        
- *                                                                
- * y   is the current value of the dependent variable vector,     
- *     namely the predicted value of y(t).                     
- *                                                                
- * yp  is the current value of the derivative vector y',          
- *     namely the predicted value of y'(t).                    
- *                                                                
- * r   is the residual vector F(tt,yy,yp).                     
- *                                                                
- * c_j is the scalar in the system Jacobian, proportional to 
- *     the inverse of the step size h.
- *                                                                
- * user_data is a pointer to user Jacobian data - the same as the    
- *     user_data parameter passed to IDASetUserData.                     
- *                                                                
- * Jac is the dense matrix (of type DlsMat) to be loaded by  
- *     an IDADlsDenseJacFn routine with an approximation to the   
- *     system Jacobian matrix                                  
- *            J = dF/dy + c_j *dF/dy'                            
- *     at the given point (t,y,y'), where the ODE system is    
- *     given by F(t,y,y') = 0.
- *     Note that Jac is NOT preset to zero!
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an IDADlsDenseJacFn routine 
- *     as temporary storage or work space.                     
- *                                                                
- * A IDADlsDenseJacFn should return                                
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- * In the case of a recoverable error return, the integrator will 
- * attempt to recover by reducing the stepsize (which changes c_j).
- *
- * -----------------------------------------------------------------
- *
- * NOTE: The following are two efficient ways to load a dense Jac:         
- * (1) (with macros - no explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = LAPACK_DENSE_COL(Jac,j);                                 
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * (2) (without macros - explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = (Jac->data)[j];                                   
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * A third way, using the LAPACK_DENSE_ELEM(A,i,j) macro, is much less   
- * efficient in general.  It is only appropriate for use in small 
- * problems in which efficiency of access is NOT a major concern. 
- *                                                                
- * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     IDAGetCurrentStep and IDAGetErrWeights, respectively, but this
- *     requires including in user_data a pointer to the solver memory.
- *     The unit roundoff is available as UNIT_ROUNDOFF defined in
- *     sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
   
-  
-typedef int (*IDADlsDenseJacFn)(long int N, realtype t, realtype c_j,
-				N_Vector y, N_Vector yp, N_Vector r, 
-				DlsMat Jac, void *user_data,
-				N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-/*
- * -----------------------------------------------------------------
- * Types : IDADlsBandJacFn
- * -----------------------------------------------------------------
- * A banded Jacobian approximation function bjac must have the    
- * prototype given below. Its parameters are:                     
- *                                                                
- * Neq is the problem size, and length of all vector arguments.   
- *                                                                
- * mupper is the upper bandwidth of the banded Jacobian matrix.   
- *                                                                
- * mlower is the lower bandwidth of the banded Jacobian matrix.   
- *                                                                
- * tt is the current value of the independent variable t.        
- *                                                                
- * yy is the current value of the dependent variable vector,     
- *    namely the predicted value of y(t).                     
- *                                                                
- * yp is the current value of the derivative vector y',          
- *    namely the predicted value of y'(t).                    
- *                                                                
- * rr is the residual vector F(tt,yy,yp).                     
- *                                                                
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *                                                                
- * user_data  is a pointer to user Jacobian data - the same as the    
- *    user_data parameter passed to IDASetUserData.                      
- *                                                                
- * Jac is the band matrix (of type BandMat) to be loaded by    
- *     an IDADlsBandJacFn routine with an approximation to the    
- *     system Jacobian matrix                                  
- *            J = dF/dy + c_j *dF/dy'                             
- *     at the given point (t,y,y'), where the DAE system is    
- *     given by F(t,y,y') = 0.  Jac is preset to zero, so only 
- *     the nonzero elements need to be loaded.  See note below.
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an IDADlsBandJacFn routine  
- *     as temporary storage or work space.                     
- *                                                                
- * An IDADlsBandJacFn function should return                                 
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- * In the case of a recoverable error return, the integrator will 
- * attempt to recover by reducing the stepsize (which changes c_j).
- *
- * -----------------------------------------------------------------
- *
- * NOTE: The following are two efficient ways to load Jac:
- *                                                                
- * (1) (with macros - no explicit data structure references)      
- *    for (j=0; j < Neq; j++) {                                   
- *       col_j = BAND_COL(Jac,j);                                  
- *       for (i=j-mupper; i <= j+mlower; i++) {                   
- *         generate J_ij = the (i,j)th Jacobian element           
- *         BAND_COL_ELEM(col_j,i,j) = J_ij;                       
- *       }                                                        
- *     }                                                          
- *                                                                
- * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro)     
- *    for (j=0; j < Neq; j++) {                                   
- *       col_j = BAND_COL(Jac,j);                                  
- *       for (k=-mupper; k <= mlower; k++) {                      
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k    
- *         col_j[k] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- *                                                                
- * A third way, using the BAND_ELEM(A,i,j) macro, is much less    
- * efficient in general.  It is only appropriate for use in small 
- * problems in which efficiency of access is NOT a major concern. 
- *                                                                
- * NOTE: If the user's Jacobian routine needs other quantities,   
- *       they are accessible as follows: hcur (the current stepsize)
- *       and ewt (the error weight vector) are accessible through   
- *       IDAGetCurrentStep and IDAGetErrWeights, respectively, but this
- *       requires including in user_data a pointer to the solver memory.
- *       The unit roundoff is available as UNIT_ROUNDOFF defined in
- *       sundials_types.h                   
- *                                                                
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDADlsBandJacFn)(long int N, long int mupper, long int mlower,
-			       realtype t, realtype c_j, 
-			       N_Vector y, N_Vector yp, N_Vector r,
-			       DlsMat Jac, void *user_data,
-			       N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-  
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the IDADLS linear solver
- * -----------------------------------------------------------------
- * IDADlsSetDenseJacFn specifies the dense Jacobian approximation
- * routine to be used for a direct dense linear solver.
- *
- * IDADlsSetBandJacFn specifies the band Jacobian approximation
- * routine to be used for a direct band linear solver.
- *
- * By default, a difference quotient approximation, supplied with
- * the solver is used.
- *
- * The return value is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDA memory was NULL
- *    IDADLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADlsSetDenseJacFn(void *ida_mem, IDADlsDenseJacFn jac);
-SUNDIALS_EXPORT int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the IDADLS linear solver
- * -----------------------------------------------------------------
- *
- * IDADlsGetWorkSpace   returns the real and integer workspace used
- *                      by the direct linear solver.
- * IDADlsGetNumJacEvals returns the number of calls made to the
- *                      Jacobian evaluation routine jac.
- * IDADlsGetNumResEvals returns the number of calls to the user
- *                      F routine due to finite difference Jacobian
- *                      evaluation.
- * IDADlsGetLastFlag    returns the last error flag set by any of
- *                      the IDADLS interface functions.
- *
- * The return value of IDADlsGet* is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDA memory was NULL
- *    IDADLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int IDADlsGetNumJacEvals(void *ida_mem, long int *njevals);
-SUNDIALS_EXPORT int IDADlsGetNumResEvals(void *ida_mem, long int *nfevalsLS);
-SUNDIALS_EXPORT int IDADlsGetLastFlag(void *ida_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a IDADLS return flag
- * -----------------------------------------------------------------
- */
-
+/*---------------------------------------------------------------
+ Optional outputs from the IDADLS linear solver
+
+ IDADlsGetWorkSpace   returns the real and integer workspace used
+                      by the direct linear solver.
+ IDADlsGetNumJacEvals returns the number of calls made to the
+                      Jacobian evaluation routine jac.
+ IDADlsGetNumResEvals returns the number of calls to the user
+                      F routine due to finite difference Jacobian
+                      evaluation.
+ IDADlsGetLastFlag    returns the last error flag set by any of
+                      the IDADLS interface functions.
+
+ The return value of IDADlsGet* is one of:
+    IDADLS_SUCCESS   if successful
+    IDADLS_MEM_NULL  if the IDA memory was NULL
+    IDADLS_LMEM_NULL if the linear solver memory was NULL
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsGetWorkSpace(void *ida_mem,
+                                       long int *lenrwLS,
+                                       long int *leniwLS);
+SUNDIALS_EXPORT int IDADlsGetNumJacEvals(void *ida_mem,
+                                         long int *njevals);
+SUNDIALS_EXPORT int IDADlsGetNumResEvals(void *ida_mem,
+                                         long int *nfevalsLS);
+SUNDIALS_EXPORT int IDADlsGetLastFlag(void *ida_mem,
+                                      long int *flag);
+
+
+/*---------------------------------------------------------------
+ The following function returns the name of the constant 
+ associated with a IDADLS return flag
+---------------------------------------------------------------*/
 SUNDIALS_EXPORT char *IDADlsGetReturnFlagName(long int flag);
 
 
diff --git a/include/ida/ida_klu.h b/include/ida/ida_klu.h
deleted file mode 100644
index 79c03b3..0000000
--- a/include/ida/ida_klu.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDAKLU linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDAKLU_H
-#define _IDAKLU_H
-
-#include "ida/ida_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDAKLU
- * -----------------------------------------------------------------
- * A call to the IDAKLU function links the main integrator      
- * with the IDAKLU linear solver module.                        
- *                                                                
- * ida_mem is the pointer to integrator memory returned by        
- *     IDACreate.             
- *
- *                                                                
- * IDAKLU returns:                                              
- *     IDASLU_SUCCESS   = 0  if successful                              
- *     IDASLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     IDASLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The KLU linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, IDAKLU will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLU(void *ida_mem, int n, int nnz, int sparesetype); 
-
-/*
- * -----------------------------------------------------------------
- * IDAKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to IDAKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is IDASLS_SUCCESS = 0, IDASLS_MEM_NULL = -1, 
- * IDASLS_LMEM_NULL = -2, IDASLS_ILL_INPUT = -3, or IDASLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDAKLUReInit(void *ida_mem_v, int n, int nnz, 
-				 int reinit_type);
-
-/*
- * -----------------------------------------------------------------
- * Function: IDAKLUB
- * -----------------------------------------------------------------
- * IDAKLUB links the main IDAS integrator with the IDAKLU
- * linear solver for the backward integration.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLUB(void *ida_mem, int which, int nB, int nnzB);
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDAKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in IDA is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLUSetOrdering(void *ida_mem, int ordering_choice); 
-
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_lapack.h b/include/ida/ida_lapack.h
deleted file mode 100644
index 2a16130..0000000
--- a/include/ida/ida_lapack.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Header file for the IDA dense linear solver IDALAPACK.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDALAPACK_H
-#define _IDALAPACK_H
-
-#include <ida/ida_direct.h>
-#include <sundials/sundials_lapack.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDALapackDense
- * -----------------------------------------------------------------
- * A call to the IDALapackDense function links the main integrator
- * with the IDALAPACK linear solver using dense Jacobians.
- *
- * ida_mem is the pointer to the integrator memory returned by
- *           IDACreate.
- *
- * N is the size of the ODE system.
- *
- * The return value of IDALapackDense is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDA memory was NULL
- *    IDADLS_MEM_FAIL  if there was a memory allocation failure
- *    IDADLS_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDALapackDense(void *ida_mem, int N);
-
-/*
- * -----------------------------------------------------------------
- * Function : IDALapackBand
- * -----------------------------------------------------------------
- * A call to the IDALapackBand function links the main integrator
- * with the IDALAPACK linear solver using banded Jacobians. 
- *
- * ida_mem is the pointer to the integrator memory returned by
- *           IDACreate.
- *
- * N is the size of the ODE system.
- *
- * mupper is the upper bandwidth of the band Jacobian approximation.
- *
- * mlower is the lower bandwidth of the band Jacobian approximation.
- *
- * The return value of IDALapackBand is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDA memory was NULL
- *    IDADLS_MEM_FAIL  if there was a memory allocation failure
- *    IDADLS_ILL_INPUT if a required vector operation is missing
- *                        or if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDALapackBand(void *ida_mem, int N, int mupper, int mlower);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_sparse.h b/include/ida/ida_sparse.h
deleted file mode 100644
index 0aae45f..0000000
--- a/include/ida/ida_sparse.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4423 $
- * $Date: 2015-03-08 17:23:10 -0700 (Sun, 08 Mar 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the Sparse linear solver module in IDA.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASPARSE_H
-#define _IDASPARSE_H
-
-#include <sundials/sundials_sparse.h>
-#include <sundials/sundials_nvector.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * I D A S S P A R S E    C O N S T A N T S
- * =================================================================
- */
-
-/* 
- * -----------------------------------------------------------------
- * IDASLS return values 
- * -----------------------------------------------------------------
- */
-
-#define IDASLS_SUCCESS           0
-#define IDASLS_MEM_NULL         -1
-#define IDASLS_LMEM_NULL        -2
-#define IDASLS_ILL_INPUT        -3
-#define IDASLS_MEM_FAIL         -4
-#define IDASLS_JAC_NOSET        -5
-#define IDASLS_PACKAGE_FAIL     -6
-
-/* Additional last_flag values */
-
-#define IDASLS_JACFUNC_UNRECVR  -7
-#define IDASLS_JACFUNC_RECVR    -8
-
-/* Return values for the adjoint module */
-#define IDASLS_NO_ADJ           -101
-#define IDASLS_LMEMB_NULL       -102
-
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASlsSparseJacFn
- * -----------------------------------------------------------------
- *
- * A sparse Jacobian approximation function jaceval must be of type 
- * IDASlsSparseJacFn.
- * Its parameters are:                     
- *                                                                
- * t   is the current value of the independent variable t.        
- *                                                                
- * c_j is the scalar in the system Jacobian, proportional to 
- *     the inverse of the step size h.
- *                                                                
- * y   is the current value of the dependent variable vector,     
- *     namely the predicted value of y(t).                     
- *                                                                
- * yp  is the current value of the derivative vector y',          
- *     namely the predicted value of y'(t).                    
- *                                                                
- * r   is the residual vector F(tt,yy,yp).                     
- *                                                                
- * JacMat is the compressed sparse column matrix (of type SlsMat)
- *     to be loaded by an IDASlsSparseJacFn routine with an approximation
- *     to the system Jacobian matrix
- *            J = dF/dy' + c_j*dF/dy                            
- *     at the given point (t,y,y'), where the ODE system is    
- *     given by F(t,y,y') = 0.
- *     Note that JacMat is NOT preset to zero!
- *     Matrix data is for the nonzero entries of the Jacobian are stored in
- *     compressed column format.  Row indices of entries in 
- *     column j are stored in J->data[colptrs[j]] 
- *     through J->data[colptrs[j+i]-1]
- *     and corresponding numerical values of the Jacobian are stored 
- *     in the same entries of a.
- * 
- * user_data is a pointer to user Jacobian data - the same as the    
- *     user_data parameter passed to IDASetRdata.                     
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an IDASparseJacFn routine 
- *     as temporary storage or work space.                     
- *                                                                
- * A IDASlsSparseJacFn should return                                
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- * In the case of a recoverable error return, the integrator will 
- * attempt to recover by reducing the stepsize (which changes cj).
- *
- * -----------------------------------------------------------------
- *
-  * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     IDAGetCurrentStep and IDAGetErrWeights, respectively 
- *     (see ida.h). The unit roundoff is available as 
- *     UNIT_ROUNDOFF defined in sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
-  
-  
-typedef int (*IDASlsSparseJacFn)(realtype t, realtype c_j,
-		     N_Vector y, N_Vector yp, N_Vector r, 
-		     SlsMat JacMat, void *user_data,
-		     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the IDASPARSE linear solver
- * -----------------------------------------------------------------
- * IDASlsSetSparseJacFn specifies the Jacobian approximation
- * routine to be used for a sparse direct linear solver.
- *
- * The return value is one of:
- *    IDASLS_SUCCESS   if successful
- *    IDASLS_MEM_NULL  if the IDA memory was NULL
- *    IDASLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASlsSetSparseJacFn(void *ida_mem, IDASlsSparseJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the IDASLS linear solver
- * -----------------------------------------------------------------
- *
- * IDASlsGetWorkSpace   returns the real and integer workspace used
- *                      by the direct linear solver.
- * IDASlsGetNumJacEvals returns the number of calls made to the
- *                      Jacobian evaluation routine jac.
- * IDASlsGetLastFlag    returns the last error flag set by any of
- *                      the IDADLS interface functions.
- *
- * The return value of IDADlsGet* is one of:
- *    IDASLS_SUCCESS   if successful
- *    IDASLS_MEM_NULL  if the IDA memory was NULL
- *    IDASLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASlsGetNumJacEvals(void *ida_mem, long int *njevals);
-SUNDIALS_EXPORT int IDASlsGetLastFlag(void *ida_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a IDASLS return flag
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT char *IDASlsGetReturnFlagName(long int flag);
-
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type: IDASlsSparseJacFnB
- * -----------------------------------------------------------------
- * A sparse Jacobian approximation function JacB for the adjoint
- * (backward) problem must have the prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASlsSparseJacFnB)(realtype tt, realtype c_jB, 
-	      	     N_Vector yy, N_Vector yp,
-		     N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-		     SlsMat JacMatB, void *user_dataB, 
-		     N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * Type: IDASlsSparseJacFnBS
- * -----------------------------------------------------------------
- * A dense Jacobian approximation function JacBS for the adjoint
- * (backward) problem, sensitivity-dependent case, must have the
- *  prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASlsSparseJacFnBS)(realtype tt, realtype c_jB, 
-	      	     N_Vector yy, N_Vector yp,
-		     N_Vector *yS, N_Vector *ypS,
-		     N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-		     SlsMat JacMatB, void *user_dataB, 
-		     N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS 
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Functions: IDASlsSetSparseJacFnB and IDASlsSetSparseJacFnBS
- * -----------------------------------------------------------------
- * IDASlsSetSparseJacFnB specifies the sparse Jacobian functions to 
- * be used by a IDASPARSE linear solver for the backward integration phase
- * when the backward problem does not depend on forward sensitivities.
- * IDASlsSetSparseJacFnBS specifies the Jacobian
- * functions when the backward problem does depend on sensitivities.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASlsSetSparseJacFnB(void *ida_mem, int which, 
-					  IDASlsSparseJacFnB jacB);
-SUNDIALS_EXPORT int IDASlsSetSparseJacFnBS(void *ida_mem, int which, 
-					  IDASlsSparseJacFnBS jacBS);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_spbcgs.h b/include/ida/ida_spbcgs.h
deleted file mode 100644
index 9b49c35..0000000
--- a/include/ida/ida_spbcgs.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the public header file for the IDA scaled preconditioned
- * Bi-CGSTAB linear solver module, IDASPBCG.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASPBCG_H
-#define _IDASPBCG_H
-
-#include <ida/ida_spils.h>
-#include <sundials/sundials_spbcgs.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcg
- * -----------------------------------------------------------------
- * A call to the IDASpbcg function links the main integrator with
- * the IDASPBCG linear solver module. Its parameters are as
- * follows:
- *
- * IDA_mem   is the pointer to memory block returned by IDACreate.
- *
- * maxl      is the maximum Krylov subspace dimension, an
- *           optional input. Pass 0 to use the default value.
- *           Otherwise pass a positive integer.
- *
- * The return values of IDASpbcg are:
- *    IDASPILS_SUCCESS    if successful
- *    IDASPILS_MEM_NULL   if the ida memory was NULL
- *    IDASPILS_MEM_FAIL   if there was a memory allocation failure
- *    IDASPILS_ILL_INPUT  if there was illegal input.
- * The above constants are defined in ida_spils.h
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASpbcg(void *ida_mem, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_spgmr.h b/include/ida/ida_spgmr.h
deleted file mode 100644
index 2a4247a..0000000
--- a/include/ida/ida_spgmr.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDA Scaled Preconditioned GMRES     
- * linear solver module, IDASPGMR.                                 
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASPGMR_H
-#define _IDASPGMR_H
-
-#include <ida/ida_spils.h>
-#include <sundials/sundials_spgmr.h>
-
-#ifdef __cplusplus     /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- *                                                                
- * Function : IDASpgmr                                            
- * -----------------------------------------------------------------
- * A call to the IDASpgmr function links the main integrator with 
- * the IDASPGMR linear solver module.  Its parameters are as      
- * follows:                                                       
- *                                                                
- * IDA_mem   is the pointer to memory block returned by IDACreate.
- *                                                                
- * maxl      is the maximum Krylov subspace dimension, an         
- *           optional input.  Pass 0 to use the default value,    
- *           MIN(Neq, 5).  Otherwise pass a positive integer.     
- *                                                                
- * The return values of IDASpgmr are:                             
- *    IDASPILS_SUCCESS    if successful                            
- *    IDASPILS_MEM_NULL   if the ida memory was NULL
- *    IDASPILS_MEM_FAIL   if there was a memory allocation failure 
- *    IDASPILS_ILL_INPUT  if there was illegal input.              
- * The above constants are defined in ida_spils.h
- *                                                                
- * -----------------------------------------------------------------
- */                                                                
-
-SUNDIALS_EXPORT int IDASpgmr(void *ida_mem, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_spils.h b/include/ida/ida_spils.h
index d99ad93..779d97a 100644
--- a/include/ida/ida_spils.h
+++ b/include/ida/ida_spils.h
@@ -1,22 +1,24 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmers: Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *         Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the common header file for the Scaled and Preconditioned
- * Iterative Linear Solvers in IDA.
+ * Header file for the Scaled and Preconditioned Iterative Linear 
+ * Solver interface in IDA.
  * -----------------------------------------------------------------
  */
 
@@ -25,16 +27,15 @@
 
 #include <sundials/sundials_iterative.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_linearsolver.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/* 
- * -----------------------------------------------------------------
- * IDASPILS return values 
- * -----------------------------------------------------------------
- */
+/*===============================================================
+  IDASPILS Constants
+  ===============================================================*/
 
 #define IDASPILS_SUCCESS     0
 #define IDASPILS_MEM_NULL   -1 
@@ -42,282 +43,324 @@ extern "C" {
 #define IDASPILS_ILL_INPUT  -3
 #define IDASPILS_MEM_FAIL   -4
 #define IDASPILS_PMEM_NULL  -5
+#define IDASPILS_SUNLS_FAIL -6
 
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSetupFn
- * -----------------------------------------------------------------
- * The optional user-supplied functions PrecSetup and PrecSolve
- * together must define the left preconditoner matrix P
- * approximating the system Jacobian matrix
- *    J = dF/dy + c_j*dF/dy'
- * (where the DAE system is F(t,y,y') = 0), and solve the linear
- * systems P z = r.   PrecSetup is to do any necessary setup
- * operations, and PrecSolve is to compute the solution of
- * P z = r.
- *
- * The preconditioner setup function PrecSetup is to evaluate and
- * preprocess any Jacobian-related data needed by the
- * preconditioner solve function PrecSolve.  This might include
- * forming a crude approximate Jacobian, and performing an LU
- * factorization on it.  This function will not be called in
- * advance of every call to PrecSolve, but instead will be called
- * only as often as necessary to achieve convergence within the
- * Newton iteration.  If the PrecSolve function needs no
- * preparation, the PrecSetup function can be NULL.
- *
- * Each call to the PrecSetup function is preceded by a call to
- * the system function res with the same (t,y,y') arguments.
- * Thus the PrecSetup function can use any auxiliary data that is
- * computed and saved by the res function and made accessible
- * to PrecSetup.
- *
- * A preconditioner setup function PrecSetup must have the
- * prototype given below.  Its parameters are as follows:
- *
- * tt  is the current value of the independent variable t.
- *
- * yy  is the current value of the dependent variable vector,
- *     namely the predicted value of y(t).
- *
- * yp  is the current value of the derivative vector y',
- *     namely the predicted value of y'(t).
- *
- * rr  is the current value of the residual vector F(t,y,y').
- *
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *
- * user_data is a pointer to user data, the same as the user_data
- *     parameter passed to IDASetUserData.
- *
- * tmp1, tmp2, tmp3 are pointers to vectors of type N_Vector
- *     which can be used by an IDASpilsPrecSetupFn routine
- *     as temporary storage or work space.
- *
- * NOTE: If the user's preconditioner needs other quantities,
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through
- *     IDAGetCurrentStep and IDAGetErrWeights, respectively (see
- *     ida.h). The unit roundoff is available as
- *     UNIT_ROUNDOFF defined in sundials_types.h
- *
- * The IDASpilsPrecSetupFn should return
- *     0 if successful,
- *     a positive int if a recoverable error occurred, or
- *     a negative int if a nonrecoverable error occurred.
- * In the case of a recoverable error return, the integrator will
- * attempt to recover by reducing the stepsize (which changes cj).
- * -----------------------------------------------------------------
- */
+  
+/*===============================================================
+  IDASPILS user-supplied function prototypes
+  ===============================================================*/
+  
+/*---------------------------------------------------------------
+  Type: IDASpilsPrecSetupFn
 
-typedef int (*IDASpilsPrecSetupFn)(realtype tt,
-				   N_Vector yy, N_Vector yp, N_Vector rr,
-				   realtype c_j, void *user_data,
-				   N_Vector tmp1, N_Vector tmp2,
-				   N_Vector tmp3);
+  The optional user-supplied functions PrecSetup and PrecSolve
+  together must define the left preconditoner matrix P
+  approximating the system Jacobian matrix
+     J = dF/dy + c_j*dF/dy'
+  (where the DAE system is F(t,y,y') = 0), and solve the linear
+  systems P z = r.   PrecSetup is to do any necessary setup
+  operations, and PrecSolve is to compute the solution of
+  P z = r.
+ 
+  The preconditioner setup function PrecSetup is to evaluate and
+  preprocess any Jacobian-related data needed by the
+  preconditioner solve function PrecSolve.  This might include
+  forming a crude approximate Jacobian, and performing an LU
+  factorization on it.  This function will not be called in
+  advance of every call to PrecSolve, but instead will be called
+  only as often as necessary to achieve convergence within the
+  Newton iteration.  If the PrecSolve function needs no
+  preparation, the PrecSetup function can be NULL when passed to
+  IDASpilsSetPreconditioner().
+ 
+  Each call to the PrecSetup function is preceded by a call to
+  the system function res with the same (t,y,y') arguments.
+  Thus the PrecSetup function can use any auxiliary data that is
+  computed and saved by the res function and made accessible
+  to PrecSetup.
+ 
+  A preconditioner setup function PrecSetup must have the
+  prototype given below.  Its parameters are as follows:
+ 
+  tt  is the current value of the independent variable t.
+ 
+  yy  is the current value of the dependent variable vector,
+      namely the predicted value of y(t).
+ 
+  yp  is the current value of the derivative vector y',
+      namely the predicted value of y'(t).
+ 
+  rr  is the current value of the residual vector F(t,y,y').
+ 
+  c_j is the scalar in the system Jacobian, proportional to 1/hh.
+ 
+  user_data is a pointer to user data, the same as the user_data
+      parameter passed to IDASetUserData.
+ 
+  NOTE: If the user's preconditioner needs other quantities,
+      they are accessible as follows: hcur (the current stepsize)
+      and ewt (the error weight vector) are accessible through
+      IDAGetCurrentStep and IDAGetErrWeights, respectively (see
+      ida.h). The unit roundoff is available as
+      UNIT_ROUNDOFF defined in sundials_types.h
+ 
+  The IDASpilsPrecSetupFn should return
+      0 if successful,
+      a positive int if a recoverable error occurred, or
+      a negative int if a nonrecoverable error occurred.
+  In the case of a recoverable error return, the integrator will
+  attempt to recover by reducing the stepsize (which changes cj).
+  ---------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSetupFn)(realtype tt, N_Vector yy,
+                                   N_Vector yp, N_Vector rr,
+				   realtype c_j, void *user_data);
 
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSolveFn
- * -----------------------------------------------------------------
- * The optional user-supplied function PrecSolve must compute a
- * solution to the linear system P z = r, where P is the left
- * preconditioner defined by the user.  If no preconditioning
- * is desired, pass NULL for PrecSolve to IDASp*.
- *
- * A preconditioner solve function PrecSolve must have the
- * prototype given below.  Its parameters are as follows:
- *
- * tt is the current value of the independent variable t.
- *
- * yy is the current value of the dependent variable vector y.
- *
- * yp is the current value of the derivative vector y'.
- *
- * rr is the current value of the residual vector F(t,y,y').
- *
- * rvec is the input right-hand side vector r.
- *
- * zvec is the computed solution vector z.
- *
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *
- * delta is an input tolerance for use by PrecSolve if it uses an
- *     iterative method in its solution.   In that case, the
- *     the residual vector r - P z of the system should be
- *     made less than delta in weighted L2 norm, i.e.,
- *            sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta .
- *     Note: the error weight vector ewt can be obtained
- *     through a call to the routine IDAGetErrWeights.
- *
- * user_data is a pointer to user data, the same as the user_data
- *     parameter passed to IDASetUserData.
- *
- * tmp is an N_Vector which can be used by the PrecSolve
- *     routine as temporary storage or work space.
- *
- * The IDASpilsPrecSolveFn should return
- *     0 if successful,
- *     a positive int if a recoverable error occurred, or
- *     a negative int if a nonrecoverable error occurred.
- * Following a recoverable error, the integrator will attempt to
- * recover by updating the preconditioner and/or reducing the
- * stepsize.
- * -----------------------------------------------------------------
- */
+  
+/*---------------------------------------------------------------
+  Type: IDASpilsPrecSolveFn
 
-typedef int (*IDASpilsPrecSolveFn)(realtype tt,
-				   N_Vector yy, N_Vector yp, N_Vector rr,
+  The optional user-supplied function PrecSolve must compute a
+  solution to the linear system P z = r, where P is the left
+  preconditioner defined by the user.  If no preconditioning
+  is desired, pass NULL for PrecSolve to 
+  IDASpilsSetPreconditioner() (or do not call that routine at 
+  all).
+ 
+  A preconditioner solve function PrecSolve must have the
+  prototype given below.  Its parameters are as follows:
+ 
+  tt is the current value of the independent variable t.
+ 
+  yy is the current value of the dependent variable vector y.
+ 
+  yp is the current value of the derivative vector y'.
+ 
+  rr is the current value of the residual vector F(t,y,y').
+ 
+  rvec is the input right-hand side vector r.
+ 
+  zvec is the computed solution vector z.
+ 
+  c_j is the scalar in the system Jacobian, proportional to 1/hh.
+ 
+  delta is an input tolerance for use by PrecSolve if it uses an
+      iterative method in its solution.   In that case, the
+      the residual vector r - P z of the system should be
+      made less than delta in weighted L2 norm, i.e.,
+             sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta .
+      Note: the error weight vector ewt can be obtained
+      through a call to the routine IDAGetErrWeights.
+ 
+  user_data is a pointer to user data, the same as the user_data
+      parameter passed to IDASetUserData.
+ 
+  The IDASpilsPrecSolveFn should return
+      0 if successful,
+      a positive int if a recoverable error occurred, or
+      a negative int if a nonrecoverable error occurred.
+  Following a recoverable error, the integrator will attempt to
+  recover by updating the preconditioner and/or reducing the
+  stepsize.
+  ---------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSolveFn)(realtype tt, N_Vector yy,
+                                   N_Vector yp, N_Vector rr,
 				   N_Vector rvec, N_Vector zvec,
-				   realtype c_j, realtype delta, void *user_data,
-				   N_Vector tmp);
+				   realtype c_j, realtype delta,
+                                   void *user_data);
 
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsJacTimesVecFn
- * -----------------------------------------------------------------
- * The user-supplied function jtimes is to generate the product
- * J*v for given v, where J is the Jacobian matrix
- *    J = dF/dy + c_j*dF/dy'
- *  or an approximation to it, and v is a given vector.
- * It should return 0 if successful and a nonzero int otherwise.
- *
- * A function jtimes must have the prototype given below. Its
- * parameters are as follows:
- *
- *   tt   is the current value of the independent variable.
- *
- *   yy   is the current value of the dependent variable vector,
- *        namely the predicted value of y(t).
- *
- *   yp   is the current value of the derivative vector y',
- *        namely the predicted value of y'(t).
- *
- *   rr   is the current value of the residual vector F(t,y,y').
- *
- *   v    is the N_Vector to be multiplied by J.
- *
- *   Jv   is the output N_Vector containing J*v.
- *
- *   c_j  is the scalar in the system Jacobian, proportional
- *        to 1/hh.
- *
- *   user_data is a pointer to user data, the same as the
- *        pointer passed to IDASetUserData.
- *
- *   tmp1, tmp2 are two N_Vectors which can be used by Jtimes for
- *         work space.
- * -----------------------------------------------------------------
- */
+/*---------------------------------------------------------------
+ Type: IDASpilsJacTimesSetupFn
 
-typedef int (*IDASpilsJacTimesVecFn)(realtype tt,
-				     N_Vector yy, N_Vector yp, N_Vector rr,
+ The user-supplied Jacobian-times-vector product setup function 
+ JacTimesSetup and the user-supplied Jacobian-times-vector 
+ product function JTimes together must generate the product
+ J*v for v, where J is the Jacobian matrix
+     J = dF/dy + c_j*dF/dy'
+ or an approximation to it, and v is a given vector. 
+
+ Each call to the JacTimesSetup function is preceded by a call 
+ to the residual res with the same (t,y) arguments.  Thus the 
+ JacTimesSetup function can use any auxiliary data that is 
+ computed and saved by the res function and made accessible to 
+ JacTimesSetup.
+
+ A function JacTimesSetup must have the prototype given below.
+ Its parameters are as follows:
+
+ t       is the current value of the independent variable.
+
+ y       is the current value of the dependent variable vector,
+          namely the predicted value of y(t).
+
+ fy      is the vector f(t,y).
+
+ user_data  is a pointer to user data - the same as the user_data
+         parameter passed to the IDASetUserData function.
+
+ Returned value:
+ The value to be returned by the JacTimesSetup function is a flag
+ indicating whether it was successful.  This value should be
+   0   if successful,
+   > 0 for a recoverable error (step will be retried),
+   < 0 for an unrecoverable error (integration is halted).
+  ---------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesSetupFn)(realtype tt, N_Vector yy,
+                                       N_Vector yp, N_Vector rr,
+                                       realtype c_j, void *user_data);
+
+
+/*---------------------------------------------------------------
+  Type: IDASpilsJacTimesVecFn
+
+  The user-supplied function jtimes is to generate the product
+  J*v for given v, where J is the Jacobian matrix
+     J = dF/dy + c_j*dF/dy'
+   or an approximation to it, and v is a given vector.
+  It should return 0 if successful and a nonzero int otherwise.
+ 
+  A function jtimes must have the prototype given below. Its
+  parameters are as follows:
+ 
+    tt   is the current value of the independent variable.
+ 
+    yy   is the current value of the dependent variable vector,
+         namely the predicted value of y(t).
+ 
+    yp   is the current value of the derivative vector y',
+         namely the predicted value of y'(t).
+ 
+    rr   is the current value of the residual vector F(t,y,y').
+ 
+    v    is the N_Vector to be multiplied by J.
+ 
+    Jv   is the output N_Vector containing J*v.
+ 
+    c_j  is the scalar in the system Jacobian, proportional
+         to 1/hh.
+ 
+    user_data is a pointer to user data, the same as the
+         pointer passed to IDASetUserData.
+ 
+    tmp1, tmp2 are two N_Vectors which can be used by Jtimes for
+          work space.
+  ---------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesVecFn)(realtype tt, N_Vector yy,
+                                     N_Vector yp, N_Vector rr,
 				     N_Vector v, N_Vector Jv,
 				     realtype c_j, void *user_data,
 				     N_Vector tmp1, N_Vector tmp2);
 
 
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the IDASPILS linear solver                  
- * -----------------------------------------------------------------
- *                                                                
- * IDASpilsSetPreconditioner specifies the PrecSetup and PrecSolve 
- *           functions.
- *           Default is NULL for both arguments.
- * IDASpilsSetJacTimesVecFn specifies the jtimes function.        
- *           Default is to use an internal finite difference      
- *           approximation routine.                           
- * IDASpilsSetGSType specifies the type of Gram-Schmidt           
- *           orthogonalization to be used. This must be one of    
- *           the two enumeration constants MODIFIED_GS or         
- *           CLASSICAL_GS defined in iterativ.h. These correspond 
- *           to using modified Gram-Schmidt and classical         
- *           Gram-Schmidt, respectively.                          
- *           Default value is MODIFIED_GS.                        
- *           Only for IDASPGMR.
- * IDASpilsSetMaxRestarts specifies the maximum number of restarts
- *           to be used in the GMRES algorithm.  maxrs must be a  
- *           non-negative integer.  Pass 0 to specify no restarts.
- *           Default is 5.                                        
- *           Only for IDASPGMR.
- * IDASpbcgSetMaxl specifies the maximum Krylov subspace size. 
- *           Default is 5.
- *           Only for IDASPBCG and IDASPTFQMR.
- * IDASpilsSetEpsLin specifies the factor in the linear iteration 
- *           convergence test constant.                           
- *           Default is 0.05                                      
- * IDASpilsSetIncrementFactor specifies a factor in the increments
- *           to yy used in the difference quotient approximations 
- *           to matrix-vector products Jv.                        
- *           Default is 1.0                                       
- *                                                                
- * The return value of IDASpilsSet* is one of:
- *    IDASPILS_SUCCESS   if successful
- *    IDASPILS_MEM_NULL  if the ida memory was NULL
- *    IDASPILS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
+/*===============================================================
+  IDASPILS Exported functions
+  ===============================================================*/
+
+/*---------------------------------------------------------------
+  Required inputs for the IDASPILS linear solver interface:
+
+  IDASpilsSetLinearSolver specifies the iterative SUNLinearSolver 
+  object that IDA should use.  
 
+  The return value is one of:
+     IDASPILS_SUCCESS   if successful
+     IDASPILS_MEM_NULL  if the IDA memory was NULL
+     IDASPILS_ILL_INPUT if the linear solver memory was NULL
+  ---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDASpilsSetLinearSolver(void *ida_mem, 
+                                            SUNLinearSolver LS);
+
+  
+/*---------------------------------------------------------------
+  Optional inputs to the IDASPILS linear solver -- ALL of these 
+  must be called AFTER the corresponding iterative linear solver 
+  object has been attached to IDA).
+
+  IDASpilsSetPreconditioner specifies the PrecSetup and PrecSolve
+            functions.
+            Default is NULL for both arguments.
+  IDASpilsSetJacTimes specifies the jtsetup and jtimes functions.
+            Default is to use an internal finite difference
+            approximation routine for the jtimes (with no setup).
+  IDASpilsSetEpsLin specifies the factor in the linear iteration
+            convergence test constant.
+            Default is 0.05
+  IDASpilsSetIncrementFactor specifies a factor in the increments
+            to yy used in the difference quotient approximations
+            to matrix-vector products Jv.
+            Default is 1.0
+                                                                 
+  The return value of IDASpilsSet* is one of:
+     IDASPILS_SUCCESS   if successful
+     IDASPILS_MEM_NULL  if the ida memory was NULL
+     IDASPILS_LMEM_NULL if the linear solver memory was NULL
+  ---------------------------------------------------------------*/
 SUNDIALS_EXPORT int IDASpilsSetPreconditioner(void *ida_mem,
                                               IDASpilsPrecSetupFn pset, 
 					      IDASpilsPrecSolveFn psolve);
-SUNDIALS_EXPORT int IDASpilsSetJacTimesVecFn(void *ida_mem,
-                                             IDASpilsJacTimesVecFn jtv);
+SUNDIALS_EXPORT int IDASpilsSetJacTimes(void *ida_mem,
+                                        IDASpilsJacTimesSetupFn jtsetup,
+                                        IDASpilsJacTimesVecFn jtimes);
 
-SUNDIALS_EXPORT int IDASpilsSetGSType(void *ida_mem, int gstype);
-SUNDIALS_EXPORT int IDASpilsSetMaxRestarts(void *ida_mem, int maxrs);
-SUNDIALS_EXPORT int IDASpilsSetMaxl(void *ida_mem, int maxl);
 SUNDIALS_EXPORT int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac);
-SUNDIALS_EXPORT int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac);
+SUNDIALS_EXPORT int IDASpilsSetIncrementFactor(void *ida_mem,
+                                               realtype dqincfac);
 
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the IDASPILS linear solver               
- *----------------------------------------------------------------
- *                                                                
- * IDASpilsGetWorkSpace returns the real and integer workspace used 
- *     by IDASPILS.                                                  
- * IDASpilsGetNumPrecEvals returns the number of preconditioner   
- *     evaluations, i.e. the number of calls made to PrecSetup    
- *     with jok==FALSE.                                           
- * IDASpilsGetNumPrecSolves returns the number of calls made to   
- *     PrecSolve.                                                 
- * IDASpilsGetNumLinIters returns the number of linear iterations.
- * IDASpilsGetNumConvFails returns the number of linear           
- *     convergence failures.                                      
- * IDASpilsGetNumJtimesEvals returns the number of calls to jtimes
- * IDASpilsGetNumResEvals returns the number of calls to the user 
- *     res routine due to finite difference Jacobian times vector 
- *     evaluation.                                                
- * IDASpilsGetLastFlag returns the last error flag set by any of
- *     the IDASPILS interface functions.
- *                                                                
- * The return value of IDASpilsGet* is one of:
- *    IDASPILS_SUCCESS   if successful
- *    IDASPILS_MEM_NULL  if the ida memory was NULL
- *    IDASPILS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */                                                                
 
-SUNDIALS_EXPORT int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals);
-SUNDIALS_EXPORT int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves);
-SUNDIALS_EXPORT int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters);
-SUNDIALS_EXPORT int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails);
-SUNDIALS_EXPORT int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals);
-SUNDIALS_EXPORT int IDASpilsGetNumResEvals(void *ida_mem, long int *nrevalsLS); 
-SUNDIALS_EXPORT int IDASpilsGetLastFlag(void *ida_mem, long int *flag);
+/*---------------------------------------------------------------
+  Optional outputs from the IDASPILS linear solver interface:
+                                                                 
+  IDASpilsGetWorkSpace returns the real and integer workspace used 
+      by IDASPILS.                                                  
 
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with an IDASPILS return flag
- * -----------------------------------------------------------------
- */
+  IDASpilsGetNumPrecEvals returns the number of preconditioner   
+      evaluations, i.e. the number of calls made to PrecSetup    
+      with jok==SUNFALSE.                                           
 
-SUNDIALS_EXPORT char *IDASpilsGetReturnFlagName(long int flag);
+  IDASpilsGetNumPrecSolves returns the number of calls made to   
+      PrecSolve.                                                 
+
+  IDASpilsGetNumLinIters returns the number of linear iterations.
 
+  IDASpilsGetNumConvFails returns the number of linear           
+      convergence failures.                                      
+
+  IDASpilsGetNumJtimesEvals returns the number of calls to jtimes
+
+  IDASpilsGetNumResEvals returns the number of calls to the user 
+      res routine due to finite difference Jacobian times vector 
+      evaluation.                                                
+
+  IDASpilsGetLastFlag returns the last error flag set by any of
+      the IDASPILS interface functions.
+                                                                 
+  The return value of IDASpilsGet* is one of:
+     IDASPILS_SUCCESS   if successful
+     IDASPILS_MEM_NULL  if the ida memory was NULL
+     IDASPILS_LMEM_NULL if the linear solver memory was NULL
+  ---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDASpilsGetWorkSpace(void *ida_mem,
+                                         long int *lenrwLS,
+                                         long int *leniwLS);
+SUNDIALS_EXPORT int IDASpilsGetNumPrecEvals(void *ida_mem,
+                                            long int *npevals);
+SUNDIALS_EXPORT int IDASpilsGetNumPrecSolves(void *ida_mem,
+                                             long int *npsolves);
+SUNDIALS_EXPORT int IDASpilsGetNumLinIters(void *ida_mem,
+                                           long int *nliters);
+SUNDIALS_EXPORT int IDASpilsGetNumConvFails(void *ida_mem,
+                                            long int *nlcfails);
+SUNDIALS_EXPORT int IDASpilsGetNumJtimesEvals(void *ida_mem,
+                                              long int *njvevals);
+SUNDIALS_EXPORT int IDASpilsGetNumResEvals(void *ida_mem,
+                                           long int *nrevalsLS); 
+SUNDIALS_EXPORT int IDASpilsGetLastFlag(void *ida_mem,
+                                        long int *flag);
+
+/*---------------------------------------------------------------
+  The following function returns the name of the constant 
+  associated with an IDASPILS return flag
+  ---------------------------------------------------------------*/
+SUNDIALS_EXPORT char *IDASpilsGetReturnFlagName(long int flag);
 
 #ifdef __cplusplus
 }
diff --git a/include/ida/ida_sptfqmr.h b/include/ida/ida_sptfqmr.h
deleted file mode 100644
index 50f0325..0000000
--- a/include/ida/ida_sptfqmr.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the public header file for the IDA scaled preconditioned
- * TFQMR linear solver module, IDASPTFQMR.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASPTFQMR_H
-#define _IDASPTFQMR_H
-
-#include <ida/ida_spils.h>
-#include <sundials/sundials_sptfqmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmr
- * -----------------------------------------------------------------
- * A call to the IDASptfqmr function links the main integrator with
- * the IDASPTFQMR linear solver module. Its parameters are as
- * follows:
- *
- * IDA_mem  is the pointer to memory block returned by IDACreate.
- *
- * maxl     is the maximum Krylov subspace dimension, an
- *          optional input. Pass 0 to use the default value.
- *          Otherwise pass a positive integer.
- *
- * The return values of IDASptfqmr are:
- *    IDASPILS_SUCCESS    if successful
- *    IDASPILS_MEM_NULL   if the ida memory was NULL
- *    IDASPILS_MEM_FAIL   if there was a memory allocation failure
- *    IDASPILS_ILL_INPUT  if there was illegal input.
- * The above constants are defined in ida_spils.h
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASptfqmr(void *ida_mem, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/ida/ida_superlumt.h b/include/ida/ida_superlumt.h
deleted file mode 100644
index 3269991..0000000
--- a/include/ida/ida_superlumt.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4179 $
- * $Date: 2014-07-23 12:16:01 -0700 (Wed, 23 Jul 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDASuperLUMT linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASUPERLUMT_H
-#define _IDASUPERLUMT_H
-
-#include "ida/ida_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-/*
- * -----------------------------------------------------------------
- * Function : IDASuperLUMT
- * -----------------------------------------------------------------
- * A call to the IDASuperLUMT function links the main integrator      
- * with the IDASuperLUMT linear solver module.                        
- *                                                                
- * ida_mem is the pointer to integrator memory returned by        
- *     IDACreate.             
- *
- * num_threads is the number of threads that SuperLUMT should invoke     
- *                                                                
- * IDASuperLUMT returns:                                              
- *     IDASLU_SUCCESS   = 0  if successful                              
- *     IDASLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     IDASLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The SuperLUMT linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, IDASuperLUMT will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDASuperLUMT(void *ida_mem, int num_threads, 
-				   int n, int nnz); 
-
-/*
- * -----------------------------------------------------------------
- * Function: IDASuperLUMTB
- * -----------------------------------------------------------------
- * IDASuperLUMTB links the main IDAS integrator with the IDASuperLUMT
- * linear solver for the backward integration.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDASuperLUMTB(void *ida_mem, int num_threads, 
-				    int which, int mB, int nB, int nnzB);
-
-
-
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDASuperLUMTSetOrdering sets the ordering used by SuperLUMT for 
- * reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDASuperLUMTSetOrdering(void *ida_mem, 
-					      int ordering_choice); 
-
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas.h b/include/idas/idas.h
index 19509a1..d804444 100644
--- a/include/idas/idas.h
+++ b/include/idas/idas.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4845 $
- * $Date: 2016-08-03 15:45:09 -0700 (Wed, 03 Aug 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -473,9 +473,9 @@ SUNDIALS_EXPORT void *IDACreate(void);
  * IDASetSuppressAlg    | flag to indicate whether or not to      
  *                      | suppress algebraic variables in the     
  *                      | local error tests:                      
- *                      | FALSE = do not suppress;                 
- *                      | TRUE = do suppress;                     
- *                      | [FALSE]                                 
+ *                      | SUNFALSE = do not suppress;                 
+ *                      | SUNTRUE = do suppress;                     
+ *                      | [SUNFALSE]                                 
  *                      | NOTE: if suppressed algebraic variables 
  *                      | is selected, the nvector 'id' must be   
  *                      | supplied for identification of those    
@@ -698,18 +698,21 @@ SUNDIALS_EXPORT int IDAWFtolerances(void *ida_mem, IDAEwtFn efun);
  *                        |                                        
  * IDASetLineSearchOffIC  | a boolean flag to turn off the        
  *                        | linesearch algorithm.                 
- *                        | [FALSE]                               
+ *                        | [SUNFALSE]                               
  *                        |                                        
  * IDASetStepToleranceIC  | positive lower bound on the norm of   
  *                        | a Newton step.                        
  *                        | [(unit roundoff)^(2/3)                
- *                                                                
+ *                        |                                        
+ * IDASetMaxBacksIC       | maximum number of linesearch backtrack
+ *                        | operations per Newton iteration.
+ *                        | [100]
+ *
  * ---------------------------------------------------------------- 
  * Return flag:
  *   IDA_SUCCESS   if successful
  *   IDA_MEM_NULL  if the IDAS memory is NULL
  *   IDA_ILL_INPUT if an argument has an illegal value
- *
  * ----------------------------------------------------------------
  */
 
@@ -719,6 +722,7 @@ SUNDIALS_EXPORT int IDASetMaxNumJacsIC(void *ida_mem, int maxnj);
 SUNDIALS_EXPORT int IDASetMaxNumItersIC(void *ida_mem, int maxnit);
 SUNDIALS_EXPORT int IDASetLineSearchOffIC(void *ida_mem, booleantype lsoff);
 SUNDIALS_EXPORT int IDASetStepToleranceIC(void *ida_mem, realtype steptol);
+SUNDIALS_EXPORT int IDASetMaxBacksIC(void *ida_mem, int maxbacks);
 
 /*
  * -----------------------------------------------------------------
@@ -765,7 +769,7 @@ SUNDIALS_EXPORT int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g);
  *                      | the error control?
  *                      | If yes, set tolerances for quadrature
  *                      | integration. 
- *                      | [errconQ = FALSE]
+ *                      | [errconQ = SUNFALSE]
  *                      |
  * -----------------------------------------------------------------
  * If successful, the function return IDA_SUCCESS. If an argument
@@ -863,7 +867,7 @@ SUNDIALS_EXPORT int IDAQuadSVtolerances(void *ida_mem, realtype reltolQ, N_Vecto
  *                          |                                         
  * IDASetSensErrCon         | are sensitivity variables considered in 
  *                          | the error control?                      
- *                          | [TRUE]                                  
+ *                          | [SUNTRUE]                                  
  *                          |                                         
  * IDASetSensMaxNonlinIters | Maximum number of nonlinear solver  
  *                          | iterations for sensitivity systems  
diff --git a/include/idas/idas_band.h b/include/idas/idas_band.h
deleted file mode 100644
index 774c379..0000000
--- a/include/idas/idas_band.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDAS band linear solver
- * module, IDABAND. It interfaces between the band module and the
- * integrator when a banded linear solver is appropriate.
- *
- * Part I contains type definitions and function prototypes for using
- * IDABAND on forward problems (DAE integration and/or FSA)
- *
- * Part II contains type definitions and function prototypes for using
- * IDABAND on adjoint (backward) problems
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASBAND_H
-#define _IDASBAND_H
-
-#include <idas/idas_direct.h>
-#include <sundials/sundials_band.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDABand
- * -----------------------------------------------------------------
- * A call to the IDABand function links the main integrator       
- * with the IDABAND linear solver module.                         
- *                                                                
- * ida_mem is the pointer to the integrator memory returned by    
- *         IDACreate.                                                   
- *                                                                
- * mupper is the upper bandwidth of the banded Jacobian matrix.   
- *                                                                
- * mlower is the lower bandwidth of the banded Jacobian matrix.   
- *                                                                
- * The return values of IDABand are:                              
- *     IDADLS_SUCCESS   = 0  if successful                            
- *     IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure 
- *     IDADLS_ILL_INPUT = -2 if the input was illegal or NVECTOR bad. 
- *                                                                
- * NOTE: The band linear solver assumes a serial implementation   
- *       of the NVECTOR package. Therefore, IDABand will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the N_VGetArrayPointer function exists.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDABand(void *ida_mem,
-                            long int Neq, long int mupper, long int mlower);
-
-/*
- * -----------------------------------------------------------------
- * Function: IDABandB
- * -----------------------------------------------------------------
- * IDABandB links the main IDAS integrator with the IDABAND
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDABandB(void *idaadj_mem, int which, 
-                             long int NeqB, long int mupperB, long int mlowerB);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_bbdpre.h b/include/idas/idas_bbdpre.h
index 50d6d6d..8101a75 100644
--- a/include/idas/idas_bbdpre.h
+++ b/include/idas/idas_bbdpre.h
@@ -1,25 +1,27 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU,
+ *      Alan C. Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for the IDABBDPRE module, for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with IDAS and
- * IDASpgmr/IDASpbcg/IDASptfqmr.
+ * matrix with banded blocks, for use with IDAS and the
+ * IDASpils solver interface.
+ * -----------------------------------------------------------------
  */
 
 #ifndef _IDASBBDPRE_H
@@ -31,300 +33,297 @@
 extern "C" {
 #endif
 
-/* 
- * =================================================================
- * PART I - forward problems
- * =================================================================
- */
+/*=================================================================
+  PART I - forward problems
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- *
- * SUMMARY
- *
- * These routines provide a preconditioner matrix that is
- * block-diagonal with banded blocks. The blocking corresponds
- * to the distribution of the dependent variable vector y among
- * the processors. Each preconditioner block is generated from
- * the Jacobian of the local part (on the current processor) of a
- * given function G(t,y,y') approximating F(t,y,y'). The blocks
- * are generated by a difference quotient scheme on each processor
- * independently. This scheme utilizes an assumed banded structure
- * with given half-bandwidths, mudq and mldq. However, the banded
- * Jacobian block kept by the scheme has half-bandwiths mukeep and
- * mlkeep, which may be smaller.
- *
- * The user's calling program should have the following form:
- *
- *   #include <idas/idas_bbdpre.h>
- *   #include <nvector_parallel.h>
- *   ...
- *   y0  = N_VNew_Parallel(...);
- *   yp0 = N_VNew_Parallel(...);
- *   ...
- *   ida_mem = IDACreate(...);
- *   ier = IDAInit(...);
- *   ...
- *   flag = IDASptfqmr(ida_mem, maxl);
- *       -or-
- *   flag = IDASpgmr(ida_mem, maxl);
- *       -or-
- *   flag = IDASpbcg(ida_mem, maxl);
- *   ...
- *   flag = IDABBDPrecInit(ida_mem, Nlocal, mudq, mldq,
- *                         mukeep, mlkeep, dq_rel_yy, Gres, Gcomm);
- *   ...
- *   ier = IDASolve(...);
- *   ...
- *   IDAFree(&ida_mem);
- *
- *   N_VDestroy(y0);
- *   N_VDestroy(yp0);
- *
- * The user-supplied routines required are:
- *
- *   res  is the function F(t,y,y') defining the DAE system to
- *   be solved:  F(t,y,y') = 0.
- *
- *   Gres  is the function defining a local approximation
- *   G(t,y,y') to F, for the purposes of the preconditioner.
- *
- *   Gcomm  is the function performing communication needed
- *   for Glocal.
- *
- * Notes:
- *
- * 1) This header file is included by the user for the definition
- *    of the IBBDPrecData type and for needed function prototypes.
- *
- * 2) The IDABBDPrecInit call includes half-bandwidths mudq and
- *    mldq to be used in the approximate Jacobian. They need
- *    not be the true half-bandwidths of the Jacobian of the
- *    local block of G, when smaller values may provide a greater
- *    efficiency. Similarly, mukeep and mlkeep, specifying the
- *    bandwidth kept for the approximate Jacobian, need not be
- *    the true half-bandwidths. Also, mukeep, mlkeep, mudq, and
- *    mldq need not be the same on every processor.
- *
- * 3) The actual name of the user's res function is passed to
- *    IDAInit, and the names of the user's Gres and Gcomm
- *    functions are passed to IDABBDPrecInit.        
- *
- * 4) The pointer to the user-defined data block user_data, which
- *    is set through IDASetUserData is also available to the user
- *    in glocal and gcomm.
- *
- * 5) Optional outputs specific to this module are available by
- *    way of routines listed below. These include work space sizes
- *    and the cumulative number of glocal calls. The costs
- *    associated with this module also include nsetups banded LU
- *    factorizations, nsetups gcomm calls, and nps banded
- *    backsolve calls, where nsetups and nps are integrator
- *    optional outputs.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Summary:
+ 
+  These routines provide a preconditioner matrix that is
+  block-diagonal with banded blocks. The blocking corresponds
+  to the distribution of the dependent variable vector y among
+  the processors. Each preconditioner block is generated from
+  the Jacobian of the local part (on the current processor) of a
+  given function G(t,y,y') approximating F(t,y,y'). The blocks
+  are generated by a difference quotient scheme on each processor
+  independently. This scheme utilizes an assumed banded structure
+  with given half-bandwidths, mudq and mldq. However, the banded
+  Jacobian block kept by the scheme has half-bandwiths mukeep and
+  mlkeep, which may be smaller.
+ 
+  The user's calling program should have the following form:
+ 
+    #include <idas/idas_bbdpre.h>
+    #include <idas/idas_spils.h>
+    #include <nvector_parallel.h>
+    ...
+    void *ida_mem;
+    ...
+    y0  = N_VNew_Parallel(...);
+    yp0 = N_VNew_Parallel(...);
+    ...
+    SUNLinearSolver LS = SUNSPBCGS(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPFGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPGMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNSPTFQMR(y0, pretype, maxl);
+      -or-
+    SUNLinearSolver LS = SUNPCG(y0, pretype, maxl);
+    ...
+    ida_mem = IDACreate(...);
+    ier = IDAInit(...);
+    ...
+    flag = IDASpilsSetLinearSolver(ida_mem, LS);
+    ...
+    flag = IDABBDPrecInit(ida_mem, Nlocal, mudq, mldq,
+                          mukeep, mlkeep, dq_rel_yy, Gres, Gcomm);
+    ...
+    ier = IDASolve(...);
+    ...
+    IDAFree(&ida_mem);
+    ...
+    SUNLinSolFree(LS);
+    ...
+    N_VDestroy(y0);
+    N_VDestroy(yp0);
+    ...
+ 
+  The user-supplied routines required are:
+ 
+    res  is the function F(t,y,y') defining the DAE system to
+    be solved:  F(t,y,y') = 0.
+ 
+    Gres  is the function defining a local approximation
+    G(t,y,y') to F, for the purposes of the preconditioner.
+ 
+    Gcomm  is the function performing communication needed
+    for Glocal.
+ 
+  Notes:
+ 
+  1) This header file is included by the user for the definition
+     of the IBBDPrecData type and for needed function prototypes.
+ 
+  2) The IDABBDPrecInit call includes half-bandwidths mudq and
+     mldq to be used in the approximate Jacobian. They need
+     not be the true half-bandwidths of the Jacobian of the
+     local block of G, when smaller values may provide a greater
+     efficiency. Similarly, mukeep and mlkeep, specifying the
+     bandwidth kept for the approximate Jacobian, need not be
+     the true half-bandwidths. Also, mukeep, mlkeep, mudq, and
+     mldq need not be the same on every processor.
+ 
+  3) The actual name of the user's res function is passed to
+     IDAInit, and the names of the user's Gres and Gcomm
+     functions are passed to IDABBDPrecInit.        
+ 
+  4) The pointer to the user-defined data block user_data, which
+     is set through IDASetUserData is also available to the user
+     in glocal and gcomm.
+ 
+  5) Optional outputs specific to this module are available by
+     way of routines listed below. These include work space sizes
+     and the cumulative number of glocal calls. The costs
+     associated with this module also include nsetups banded LU
+     factorizations, nsetups gcomm calls, and nps banded
+     backsolve calls, where nsetups and nps are integrator
+     optional outputs.
+  -----------------------------------------------------------------*/
 
-/*
- * -----------------------------------------------------------------
- * Type : IDABBDLocalFn
- * -----------------------------------------------------------------
- * The user must supply a function G(t,y,y') which approximates
- * the function F for the system F(t,y,y') = 0, and which is
- * computed locally (without interprocess communication).
- * (The case where G is mathematically identical to F is allowed.)
- * The implementation of this function must have type IDABBDLocalFn.
- *
- * This function takes as input the independent variable value tt,
- * the current solution vector yy, the current solution
- * derivative vector yp, and a pointer to the user-defined data
- * block user_data. It is to compute the local part of G(t,y,y')
- * and store it in the vector gval. (Providing memory for yy and
- * gval is handled within this preconditioner module.) It is
- * expected that this routine will save communicated data in work
- * space defined by the user, and made available to the
- * preconditioner function for the problem. The user_data
- * parameter is the same as that passed by the user to the
- * IDAMalloc routine.
- *
- * An IDABBDLocalFn Gres is to return an int, defined in the same
- * way as for the residual function: 0 (success), +1 or -1 (fail).
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  Type : IDABBDLocalFn
 
-typedef int (*IDABBDLocalFn)(long int Nlocal, realtype tt,
+  The user must supply a function G(t,y,y') which approximates
+  the function F for the system F(t,y,y') = 0, and which is
+  computed locally (without interprocess communication).
+  (The case where G is mathematically identical to F is allowed.)
+  The implementation of this function must have type IDABBDLocalFn.
+ 
+  This function takes as input the independent variable value tt,
+  the current solution vector yy, the current solution
+  derivative vector yp, and a pointer to the user-defined data
+  block user_data. It is to compute the local part of G(t,y,y')
+  and store it in the vector gval. (Providing memory for yy and
+  gval is handled within this preconditioner module.) It is
+  expected that this routine will save communicated data in work
+  space defined by the user, and made available to the
+  preconditioner function for the problem. The user_data
+  parameter is the same as that passed by the user to the
+  IDAMalloc routine.
+ 
+  An IDABBDLocalFn Gres is to return an int, defined in the same
+  way as for the residual function: 0 (success), +1 or -1 (fail).
+  -----------------------------------------------------------------*/
+typedef int (*IDABBDLocalFn)(sunindextype Nlocal, realtype tt,
 			     N_Vector yy, N_Vector yp, N_Vector gval,
 			     void *user_data);
 
-/*
- * -----------------------------------------------------------------
- * Type : IDABBDCommFn
- * -----------------------------------------------------------------
- * The user may supply a function of type IDABBDCommFn which
- * performs all interprocess communication necessary to
- * evaluate the approximate system function described above.
- *
- * This function takes as input the solution vectors yy and yp,
- * and a pointer to the user-defined data block user_data. The
- * user_data parameter is the same as that passed by the user to
- * the IDASetUserData routine.
- *
- * The IDABBDCommFn Gcomm is expected to save communicated data in
- * space defined with the structure *user_data.
- *
- * A IDABBDCommFn Gcomm returns an int value equal to 0 (success),
- * > 0 (recoverable error), or < 0 (unrecoverable error).
- *
- * Each call to the IDABBDCommFn is preceded by a call to the system
- * function res with the same vectors yy and yp. Thus the
- * IDABBDCommFn gcomm can omit any communications done by res if
- * relevant to the evaluation of the local function glocal.
- * A NULL communication function can be passed to IDABBDPrecInit
- * if all necessary communication was done by res.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type : IDABBDCommFn
+  -----------------------------------------------------------------
+  The user may supply a function of type IDABBDCommFn which
+  performs all interprocess communication necessary to
+  evaluate the approximate system function described above.
+ 
+  This function takes as input the solution vectors yy and yp,
+  and a pointer to the user-defined data block user_data. The
+  user_data parameter is the same as that passed by the user to
+  the IDASetUserData routine.
+ 
+  The IDABBDCommFn Gcomm is expected to save communicated data in
+  space defined with the structure *user_data.
+ 
+  A IDABBDCommFn Gcomm returns an int value equal to 0 (success),
+  > 0 (recoverable error), or < 0 (unrecoverable error).
+ 
+  Each call to the IDABBDCommFn is preceded by a call to the system
+  function res with the same vectors yy and yp. Thus the
+  IDABBDCommFn gcomm can omit any communications done by res if
+  relevant to the evaluation of the local function glocal.
+  A NULL communication function can be passed to IDABBDPrecInit
+  if all necessary communication was done by res.
+  -----------------------------------------------------------------*/
+typedef int (*IDABBDCommFn)(sunindextype Nlocal, realtype tt,
+			    N_Vector yy, N_Vector yp, void *user_data);
 
-typedef int (*IDABBDCommFn)(long int Nlocal, realtype tt,
-			    N_Vector yy, N_Vector yp,
-			    void *user_data);
+/*-----------------------------------------------------------------
+  Function : IDABBDPrecInit
 
-/*
- * -----------------------------------------------------------------
- * Function : IDABBDPrecInit
- * -----------------------------------------------------------------
- * IDABBDPrecInit allocates and initializes the BBD preconditioner.
- *
- * The parameters of IDABBDPrecInit are as follows:
- *
- * ida_mem  is a pointer to the memory blockreturned by IDACreate.
- *
- * Nlocal  is the length of the local block of the vectors yy etc.
- *         on the current processor.
- *
- * mudq, mldq  are the upper and lower half-bandwidths to be used
- *             in the computation of the local Jacobian blocks.
- *
- * mukeep, mlkeep are the upper and lower half-bandwidths to be
- *                used in saving the Jacobian elements in the local
- *                block of the preconditioner matrix PP.
- *
- * dq_rel_yy is an optional input. It is the relative increment
- *           to be used in the difference quotient routine for
- *           Jacobian calculation in the preconditioner. The
- *           default is sqrt(unit roundoff), and specified by
- *           passing dq_rel_yy = 0.
- *
- * Gres    is the name of the user-supplied function G(t,y,y')
- *         that approximates F and whose local Jacobian blocks
- *         are to form the preconditioner.
- *
- * Gcomm   is the name of the user-defined function that performs
- *         necessary interprocess communication for the
- *         execution of glocal.
- *
- * The return value of IDABBDPrecInit is one of:
- *   IDASPILS_SUCCESS if no errors occurred
- *   IDASPILS_MEM_NULL if the integrator memory is NULL
- *   IDASPILS_LMEM_NULL if the linear solver memory is NULL
- *   IDASPILS_ILL_INPUT if an input has an illegal value
- *   IDASPILS_MEM_FAIL if a memory allocation request failed
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem, long int Nlocal,
-                                   long int mudq, long int mldq,
-                                   long int mukeep, long int mlkeep,
+  IDABBDPrecInit allocates and initializes the BBD preconditioner.
+ 
+  The parameters of IDABBDPrecInit are as follows:
+ 
+  ida_mem  is a pointer to the memory blockreturned by IDACreate.
+ 
+  Nlocal  is the length of the local block of the vectors yy etc.
+          on the current processor.
+ 
+  mudq, mldq  are the upper and lower half-bandwidths to be used
+              in the computation of the local Jacobian blocks.
+ 
+  mukeep, mlkeep are the upper and lower half-bandwidths to be
+                 used in saving the Jacobian elements in the local
+                 block of the preconditioner matrix PP.
+ 
+  dq_rel_yy is an optional input. It is the relative increment
+            to be used in the difference quotient routine for
+            Jacobian calculation in the preconditioner. The
+            default is sqrt(unit roundoff), and specified by
+            passing dq_rel_yy = 0.
+ 
+  Gres    is the name of the user-supplied function G(t,y,y')
+          that approximates F and whose local Jacobian blocks
+          are to form the preconditioner.
+ 
+  Gcomm   is the name of the user-defined function that performs
+          necessary interprocess communication for the
+          execution of glocal.
+ 
+  The return value of IDABBDPrecInit is one of:
+    IDASPILS_SUCCESS if no errors occurred
+    IDASPILS_MEM_NULL if the integrator memory is NULL
+    IDASPILS_LMEM_NULL if the linear solver memory is NULL
+    IDASPILS_ILL_INPUT if an input has an illegal value
+    IDASPILS_MEM_FAIL if a memory allocation request failed
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDABBDPrecInit(void *ida_mem,
+                                   sunindextype Nlocal,
+                                   sunindextype mudq,
+                                   sunindextype mldq,
+                                   sunindextype mukeep,
+                                   sunindextype mlkeep,
                                    realtype dq_rel_yy,
-                                   IDABBDLocalFn Gres, IDABBDCommFn Gcomm);
+                                   IDABBDLocalFn Gres,
+                                   IDABBDCommFn Gcomm);
 
-/*
- * -----------------------------------------------------------------
- * Function : IDABBDPrecReInit
- * -----------------------------------------------------------------
- * IDABBDPrecReInit reinitializes the IDABBDPRE module when
- * solving a sequence of problems of the same size with
- * IDASPGMR/IDABBDPRE, IDASPBCG/IDABBDPRE, or IDASPTFQMR/IDABBDPRE
- * provided there is no change in Nlocal, mukeep, or mlkeep. After
- * solving one problem, and after calling IDAReInit to reinitialize
- * the integrator for a subsequent problem, call IDABBDPrecReInit.
- *
- * All arguments have the same names and meanings as those
- * of IDABBDPrecInit.
- *
- * The return value of IDABBDPrecReInit is one of:
- *   IDASPILS_SUCCESS if no errors occurred
- *   IDASPILS_MEM_NULL if the integrator memory is NULL
- *   IDASPILS_LMEM_NULL if the linear solver memory is NULL
- *   IDASPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Function : IDABBDPrecReInit
 
+  IDABBDPrecReInit reinitializes the IDABBDPRE module when
+  solving a sequence of problems of the same size with
+  IDASPILS/IDABBDPRE provided there is no change in Nlocal, mukeep, 
+  or mlkeep. After solving one problem, and after calling IDAReInit 
+  to reinitialize the integrator for a subsequent problem, call 
+  IDABBDPrecReInit.
+ 
+  All arguments have the same names and meanings as those
+  of IDABBDPrecInit.
+ 
+  The return value of IDABBDPrecReInit is one of:
+    IDASPILS_SUCCESS if no errors occurred
+    IDASPILS_MEM_NULL if the integrator memory is NULL
+    IDASPILS_LMEM_NULL if the linear solver memory is NULL
+    IDASPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT int IDABBDPrecReInit(void *ida_mem,
-				     long int mudq, long int mldq,
+                                     sunindextype mudq, 
+				     sunindextype mldq,
 				     realtype dq_rel_yy);
 
-/*
- * -----------------------------------------------------------------
- * Optional outputs for IDABBDPRE
- * -----------------------------------------------------------------
- * IDABBDPrecGetWorkSpace returns the real and integer work space
- *                        for IDABBDPRE.
- * IDABBDPrecGetNumGfnEvals returns the number of calls to the
- *                          user Gres function.
- * 
- * The return value of IDABBDPrecGet* is one of:
- *   IDASPILS_SUCCESS if no errors occurred
- *   IDASPILS_MEM_NULL if the integrator memory is NULL
- *   IDASPILS_LMEM_NULL if the linear solver memory is NULL
- *   IDASPILS_PMEM_NULL if the preconditioner memory is NULL
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Optional outputs for IDABBDPRE
 
+  IDABBDPrecGetWorkSpace returns the real and integer work space
+                         for IDABBDPRE.
+  IDABBDPrecGetNumGfnEvals returns the number of calls to the
+                           user Gres function.
+  
+  The return value of IDABBDPrecGet* is one of:
+    IDASPILS_SUCCESS if no errors occurred
+    IDASPILS_MEM_NULL if the integrator memory is NULL
+    IDASPILS_LMEM_NULL if the linear solver memory is NULL
+    IDASPILS_PMEM_NULL if the preconditioner memory is NULL
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT int IDABBDPrecGetWorkSpace(void *ida_mem, 
-                                           long int *lenrwBBDP, long int *leniwBBDP);
-SUNDIALS_EXPORT int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP);
+                                           long int *lenrwBBDP,
+                                           long int *leniwBBDP);
+SUNDIALS_EXPORT int IDABBDPrecGetNumGfnEvals(void *ida_mem,
+                                             long int *ngevalsBBDP);
 
-/* 
- * =================================================================
- * PART II - backward problems
- * =================================================================
- */
 
-/*
- * -----------------------------------------------------------------
- * Types: IDALocalFnB and IDACommFnB
- * -----------------------------------------------------------------
- * Local approximation function and inter-process communication
- * function for the BBD preconditioner on the backward phase.
- * -----------------------------------------------------------------
- */
-typedef int (*IDABBDLocalFnB)(long int NlocalB, realtype tt,
-			      N_Vector yy, N_Vector yp, 
-			      N_Vector yyB, N_Vector ypB, N_Vector gvalB,
-			      void *user_dataB);
+/*=================================================================
+  PART II - backward problems
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Types: IDALocalFnB and IDACommFnB
 
-typedef int (*IDABBDCommFnB)(long int NlocalB, realtype tt,
+  Local approximation function and inter-process communication
+  function for the BBD preconditioner on the backward phase.
+  -----------------------------------------------------------------*/
+typedef int (*IDABBDLocalFnB)(sunindextype NlocalB, realtype tt,
+			      N_Vector yy, N_Vector yp,
+                              N_Vector yyB, N_Vector ypB,
+                              N_Vector gvalB, void *user_dataB);
+typedef int (*IDABBDCommFnB)(sunindextype NlocalB, realtype tt,
 			     N_Vector yy, N_Vector yp,
 			     N_Vector yyB, N_Vector ypB,
 			     void *user_dataB);
 
-/*
- * -----------------------------------------------------------------
- * Functions: IDABBDPrecInitB, IDABBDPrecReInit
- * -----------------------------------------------------------------
- * Interface functions for the IDABBDPRE preconditioner to be used
- * on the backward phase.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Functions: IDABBDPrecInitB, IDABBDPrecReInit
 
-SUNDIALS_EXPORT int IDABBDPrecInitB(void *ida_mem, int which, long int NlocalB,
-                                    long int mudqB, long int mldqB,
-                                    long int mukeepB, long int mlkeepB,
+  Interface functions for the IDABBDPRE preconditioner to be used
+  on the backward phase.
+  The 'which' argument is the int returned by IDACreateB.
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDABBDPrecInitB(void *ida_mem, int which,
+                                    sunindextype NlocalB,
+                                    sunindextype mudqB,
+                                    sunindextype mldqB,
+                                    sunindextype mukeepB,
+                                    sunindextype mlkeepB,
                                     realtype dq_rel_yyB,
-                                    IDABBDLocalFnB GresB, IDABBDCommFnB GcommB);
-
+                                    IDABBDLocalFnB GresB,
+                                    IDABBDCommFnB GcommB);
 SUNDIALS_EXPORT int IDABBDPrecReInitB(void *ida_mem, int which, 
-                                      long int mudqB, long int mldqB, realtype dq_rel_yyB);
+                                      sunindextype mudqB,
+                                      sunindextype mldqB,
+                                      realtype dq_rel_yyB);
 
 #ifdef __cplusplus
 }
diff --git a/include/idas/idas_dense.h b/include/idas/idas_dense.h
deleted file mode 100644
index 2fb2ec7..0000000
--- a/include/idas/idas_dense.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDADENSE linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASDENSE_H
-#define _IDASDENSE_H
-
-#include <idas/idas_direct.h>
-#include <sundials/sundials_dense.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDADense
- * -----------------------------------------------------------------
- * A call to the IDADense function links the main integrator      
- * with the IDADENSE linear solver module.                        
- *                                                                
- * ida_mem is the pointer to integrator memory returned by        
- *     IDACreate.                                                 
- *                                                                
- * Neq  is the problem size                                       
- *                                                                
- * IDADense returns:                                              
- *     IDADLS_SUCCESS   = 0  if successful                              
- *     IDADLS_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     IDADLS_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The dense linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, IDADense will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADense(void *ida_mem, long int Neq); 
-
-/*
- * -----------------------------------------------------------------
- * Function: IDADenseB
- * -----------------------------------------------------------------
- * IDADenseB links the main IDAS integrator with the IDADENSE
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADenseB(void *ida_mem, int which, long int NeqB);
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_direct.h b/include/idas/idas_direct.h
index d26833b..a6b6836 100644
--- a/include/idas/idas_direct.h
+++ b/include/idas/idas_direct.h
@@ -1,21 +1,23 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common header file for the direct linear solvers in IDAS.
+ * Common header file for the direct linear solver interface in IDAS
  * -----------------------------------------------------------------
  */
 
@@ -23,396 +25,248 @@
 #define _IDADLS_H
 
 #include <sundials/sundials_direct.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_linearsolver.h>
 #include <sundials/sundials_nvector.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * =================================================================
- * I D A S D I R E C T     C O N S T A N T S
- * =================================================================
- */
-
-/* 
- * -----------------------------------------------------------------
- * IDASDIRECT return values 
- * -----------------------------------------------------------------
- */
+/*=================================================================
+  IDASDLS Constants
+  =================================================================*/
 
+/* IDASDLS return values */
 #define IDADLS_SUCCESS           0
 #define IDADLS_MEM_NULL         -1
 #define IDADLS_LMEM_NULL        -2
 #define IDADLS_ILL_INPUT        -3
 #define IDADLS_MEM_FAIL         -4
 
-
 /* Additional last_flag values */
-
 #define IDADLS_JACFUNC_UNRECVR  -5
 #define IDADLS_JACFUNC_RECVR    -6
+#define IDADLS_SUNMAT_FAIL      -7
 
 /* Return values for the adjoint module */
 #define IDADLS_NO_ADJ           -101
 #define IDADLS_LMEMB_NULL       -102
 
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDADlsDenseJacFn
- * -----------------------------------------------------------------
- *
- * A dense Jacobian approximation function djac must be of type 
- * IDADlsDenseJacFn.
- * Its parameters are:                     
- *                                                                
- * N   is the problem size, and length of all vector arguments.   
- *                                                                
- * t   is the current value of the independent variable t.        
- *                                                                
- * y   is the current value of the dependent variable vector,     
- *     namely the predicted value of y(t).                     
- *                                                                
- * yp  is the current value of the derivative vector y',          
- *     namely the predicted value of y'(t).                    
- *                                                                
- * f   is the residual vector F(tt,yy,yp).                     
- *                                                                
- * c_j is the scalar in the system Jacobian, proportional to 
- *     the inverse of the step size h.
- *                                                                
- * user_data is a pointer to user Jacobian data - the same as the    
- *     user_data parameter passed to IDASetUserData.                     
- *                                                                
- * Jac is the dense matrix (of type DlsMat) to be loaded by  
- *     an IDADlsDenseJacFn routine with an approximation to the   
- *     system Jacobian matrix                                  
- *            J = dF/dy' + gamma*dF/dy                            
- *     at the given point (t,y,y'), where the ODE system is    
- *     given by F(t,y,y') = 0.
- *     Note that Jac is NOT preset to zero!
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an IDADlsDenseJacFn routine 
- *     as temporary storage or work space.                     
- *                                                                
- * A IDADlsDenseJacFn should return                                
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- * In the case of a recoverable error return, the integrator will 
- * attempt to recover by reducing the stepsize (which changes cj).
- *
- * -----------------------------------------------------------------
- *
- * NOTE: The following are two efficient ways to load a dense Jac:         
- * (1) (with macros - no explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = LAPACK_DENSE_COL(Jac,j);                                 
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * (2) (without macros - explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = (Jac->data)[j];                                   
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * A third way, using the LAPACK_DENSE_ELEM(A,i,j) macro, is much less   
- * efficient in general.  It is only appropriate for use in small 
- * problems in which efficiency of access is NOT a major concern. 
- *                                                                
- * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     IDAGetCurrentStep and IDAGetErrWeights, respectively 
- *     (see ida.h). The unit roundoff is available as 
- *     UNIT_ROUNDOFF defined in sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
-  
-  
-typedef int (*IDADlsDenseJacFn)(long int N, realtype t, realtype c_j,
-				N_Vector y, N_Vector yp, N_Vector r, 
-				DlsMat Jac, void *user_data,
-				N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-/*
- * -----------------------------------------------------------------
- * Types : IDADlsBandJacFn
- * -----------------------------------------------------------------
- * A banded Jacobian approximation function bjac must have the    
- * prototype given below. Its parameters are:                     
- *                                                                
- * Neq is the problem size, and length of all vector arguments.   
- *                                                                
- * mupper is the upper bandwidth of the banded Jacobian matrix.   
- *                                                                
- * mlower is the lower bandwidth of the banded Jacobian matrix.   
- *                                                                
- * tt is the current value of the independent variable t.        
- *                                                                
- * yy is the current value of the dependent variable vector,     
- *    namely the predicted value of y(t).                     
- *                                                                
- * yp is the current value of the derivative vector y',          
- *    namely the predicted value of y'(t).                    
- *                                                                
- * rr is the residual vector F(tt,yy,yp).                     
- *                                                                
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *                                                                
- * user_data  is a pointer to user Jacobian data - the same as the    
- *    user_data parameter passed to IDASetUserData.                      
- *                                                                
- * Jac is the band matrix (of type BandMat) to be loaded by    
- *     an IDADlsBandJacFn routine with an approximation to the    
- *     system Jacobian matrix                                  
- *            J = dF/dy + cj*dF/dy'                             
- *     at the given point (t,y,y'), where the DAE system is    
- *     given by F(t,y,y') = 0.  Jac is preset to zero, so only 
- *     the nonzero elements need to be loaded.  See note below.
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an IDADlsBandJacFn routine  
- *     as temporary storage or work space.                     
- *                                                                
- * An IDADlsBandJacFn function should return                                 
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- * In the case of a recoverable error return, the integrator will 
- * attempt to recover by reducing the stepsize (which changes cj).
- *
- * -----------------------------------------------------------------
- *
- * NOTE: The following are two efficient ways to load Jac:
- *                                                                
- * (1) (with macros - no explicit data structure references)      
- *    for (j=0; j < Neq; j++) {                                   
- *       col_j = BAND_COL(Jac,j);                                  
- *       for (i=j-mupper; i <= j+mlower; i++) {                   
- *         generate J_ij = the (i,j)th Jacobian element           
- *         BAND_COL_ELEM(col_j,i,j) = J_ij;                       
- *       }                                                        
- *     }                                                          
- *                                                                
- * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro)     
- *    for (j=0; j < Neq; j++) {                                   
- *       col_j = BAND_COL(Jac,j);                                  
- *       for (k=-mupper; k <= mlower; k++) {                      
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k    
- *         col_j[k] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- *                                                                
- * A third way, using the BAND_ELEM(A,i,j) macro, is much less    
- * efficient in general.  It is only appropriate for use in small 
- * problems in which efficiency of access is NOT a major concern. 
- *                                                                
- * NOTE: If the user's Jacobian routine needs other quantities,   
- *       they are accessible as follows: hcur (the current stepsize)
- *       and ewt (the error weight vector) are accessible through   
- *       IDAGetCurrentStep and IDAGetErrWeights, respectively (see  
- *       ida.h). The unit roundoff is available as                  
- *       UNIT_ROUNDOFF defined in sundials_types.h                   
- *                                                                
- * -----------------------------------------------------------------
- */
+/*=================================================================
+  PART I:  Forward Problems
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  FUNCTION TYPES
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Type : IDADlsJacFn
+ 
+  A Jacobian approximation function Jac must be of type IDADlsJacFn.
+  Its parameters are:                     
+                                                                 
+  t   is the current value of the independent variable.
+                                                                 
+  y   is the current value of the dependent variable vector,     
+      namely the predicted value of y(t).                     
+                                                                 
+  yp  is the current value of the derivative vector y',          
+      namely the predicted value of y'(t).                    
+                                                                 
+  r   is the residual vector F(tt,yy,yp).                     
+                                                                 
+  c_j is the scalar in the system Jacobian, proportional to 
+      the inverse of the step size h.
+                                                                 
+  user_data is a pointer to user Jacobian data - the same as the    
+      user_data parameter passed to IDASetUserData.                     
+                                                                 
+  Jac is the SUNMatrix to be loaded by an IDADlsJacFn routine 
+      with an approximation to the system Jacobian matrix                                  
+             J = dF/dy + c_j *dF/dy'
+      at the given point (t,y,y'), where the ODE system is given 
+      by F(t,y,y') = 0.   
+
+      Note that Jac is NOT preset to zero!
+                                                                 
+  tmp1, tmp2, tmp3 are pointers to memory allocated for          
+      N_Vectors which can be used by an IDADlsDenseJacFn routine 
+      as temporary storage or work space.                     
+                                                                 
+  A IDADlsDenseJacFn should return                                
+      0 if successful,                                           
+      a positive int if a recoverable error occurred, or         
+      a negative int if a nonrecoverable error occurred.         
+  In the case of a recoverable error return, the integrator will 
+  attempt to recover by reducing the stepsize (which changes c_j).
+ 
+  NOTE: See the relevant SUNMatrix implementation header files
+      and documentation for mechanisms to inquire about matrix 
+      dimensions, and for efficient ways to set matrix entries.
+                                                                
+                                                                
+  NOTE: If the user's Jacobian routine needs other quantities,   
+      they are accessible as follows: hcur (the current stepsize)
+      and ewt (the error weight vector) are accessible through   
+      IDAGetCurrentStep and IDAGetErrWeights, respectively, but this
+      requires including in user_data a pointer to the solver memory.
+      The unit roundoff is available as UNIT_ROUNDOFF defined in
+      sundials_types.h.
+ 
+  -----------------------------------------------------------------*/
+typedef int (*IDADlsJacFn)(realtype t, realtype c_j, N_Vector y,
+                           N_Vector yp, N_Vector r, SUNMatrix Jac,
+                           void *user_data, N_Vector tmp1,
+                           N_Vector tmp2, N_Vector tmp3);
 
-typedef int (*IDADlsBandJacFn)(long int N, long int mupper, long int mlower,
-			       realtype t, realtype c_j, 
-			       N_Vector y, N_Vector yp, N_Vector r,
-			       DlsMat Jac, void *user_data,
-			       N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
   
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the IDADLS linear solver
- * -----------------------------------------------------------------
- * IDADlsSetDenseJacFn specifies the dense Jacobian approximation
- * routine to be used for a direct dense linear solver.
- *
- * IDADlsSetBandJacFn specifies the band Jacobian approximation
- * routine to be used for a direct band linear solver.
- *
- * By default, a difference quotient approximation, supplied with
- * the solver is used.
- *
- * The return value is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDA memory was NULL
- *    IDADLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADlsSetDenseJacFn(void *ida_mem, IDADlsDenseJacFn jac);
-SUNDIALS_EXPORT int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the IDADLS linear solver
- * -----------------------------------------------------------------
- *
- * IDADlsGetWorkSpace   returns the real and integer workspace used
- *                      by the direct linear solver.
- * IDADlsGetNumJacEvals returns the number of calls made to the
- *                      Jacobian evaluation routine jac.
- * IDADlsGetNumResEvals returns the number of calls to the user
- *                      f routine due to finite difference Jacobian
- *                      evaluation.
- * IDADlsGetLastFlag    returns the last error flag set by any of
- *                      the IDADLS interface functions.
- *
- * The return value of IDADlsGet* is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDA memory was NULL
- *    IDADLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int IDADlsGetNumJacEvals(void *ida_mem, long int *njevals);
-SUNDIALS_EXPORT int IDADlsGetNumResEvals(void *ida_mem, long int *nfevalsLS);
-SUNDIALS_EXPORT int IDADlsGetLastFlag(void *ida_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a IDADLS return flag
- * -----------------------------------------------------------------
- */
-
+/*=================================================================
+   IDASDLS Exported functions
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Required inputs for the IDASDLS linear solver interface:
+
+  IDADlsSetLinearSolver specifies the direct SUNLinearSolver 
+  object that IDAS should use.
+
+  The return value is one of:
+    IDADLS_SUCCESS   if successful
+    IDADLS_MEM_NULL  if the IDA memory was NULL
+    IDADLS_ILL_INPUT if the arguments are incompatible
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsSetLinearSolver(void *ida_mem, 
+                                          SUNLinearSolver LS,
+                                          SUNMatrix A);
+
+
+/*---------------------------------------------------------------
+  Optional inputs to the IDADLS linear solver interface:
+
+  IDADlsSetJacFn specifies the dense Jacobian approximation
+  routine to be used for a direct dense linear solver.
+ 
+  By default, a difference quotient approximation is used for 
+  dense and band; no default exists for sparse (so this must
+  be user-supplied).
+ 
+  The return value is one of:
+     IDADLS_SUCCESS   if successful
+     IDADLS_MEM_NULL  if the IDA memory was NULL
+     IDADLS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsSetJacFn(void *ida_mem, IDADlsJacFn jac);
+
+
+/*---------------------------------------------------------------
+ Optional outputs from the IDADLS linear solver
+
+ IDADlsGetWorkSpace   returns the real and integer workspace used
+                      by the direct linear solver.
+ IDADlsGetNumJacEvals returns the number of calls made to the
+                      Jacobian evaluation routine jac.
+ IDADlsGetNumResEvals returns the number of calls to the user
+                      F routine due to finite difference Jacobian
+                      evaluation.
+ IDADlsGetLastFlag    returns the last error flag set by any of
+                      the IDADLS interface functions.
+
+ The return value of IDADlsGet* is one of:
+    IDADLS_SUCCESS   if successful
+    IDADLS_MEM_NULL  if the IDA memory was NULL
+    IDADLS_LMEM_NULL if the linear solver memory was NULL
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsGetWorkSpace(void *ida_mem,
+                                       long int *lenrwLS,
+                                       long int *leniwLS);
+SUNDIALS_EXPORT int IDADlsGetNumJacEvals(void *ida_mem,
+                                         long int *njevals);
+SUNDIALS_EXPORT int IDADlsGetNumResEvals(void *ida_mem,
+                                         long int *nfevalsLS);
+SUNDIALS_EXPORT int IDADlsGetLastFlag(void *ida_mem,
+                                      long int *flag);
+
+/*---------------------------------------------------------------
+ The following function returns the name of the constant 
+ associated with a IDADLS return flag
+---------------------------------------------------------------*/
 SUNDIALS_EXPORT char *IDADlsGetReturnFlagName(long int flag);
 
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type: IDADlsDenseJacFnB
- * -----------------------------------------------------------------
- * A dense Jacobian approximation function JacB for the adjoint
- * (backward) problem must have the prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDADlsDenseJacFnB)(long int NeqB, realtype tt, realtype c_jB, 
-				 N_Vector yy, N_Vector yp,
-				 N_Vector yyB, N_Vector ypB, N_Vector rrB,
-				 DlsMat JacB, void *user_dataB, 
-				 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * Type: IDADlsDenseJacFnBS
- * -----------------------------------------------------------------
- * A dense Jacobian approximation function JacBS for the adjoint
- * (backward) problem, sensitivity-dependent case, must have the
- *  prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDADlsDenseJacFnBS)(long int NeqB, realtype tt, realtype c_jB, 
-				 N_Vector yy, N_Vector yp,
-				 N_Vector *yS, N_Vector *ypS,
-				 N_Vector yyB, N_Vector ypB, N_Vector rrB,
-				 DlsMat JacB, void *user_dataB, 
-				 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * Type : IDADlsBandJacFnB
- * -----------------------------------------------------------------
- * A band Jacobian approximation function JacB for the adjoint 
- * (backward) problem must have the prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDADlsBandJacFnB)(long int NeqB, long int mupperB, long int mlowerB, 
-				realtype tt, realtype c_jB, 
-				N_Vector yy, N_Vector yp,
-				N_Vector yyB, N_Vector ypB, N_Vector rrB,
-				DlsMat JacB, void *user_dataB,
-				N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
   
-/*
- * -----------------------------------------------------------------
- * Type : IDADlsBandJacFnBS
- * -----------------------------------------------------------------
- * A band Jacobian approximation function JacBS for the adjoint 
- * (backward) problem, sensitivity-dependent case, must have the
- *  prototype given below. 
- * -----------------------------------------------------------------
- */
+/*=================================================================
+  PART II:  Backward Problems
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  FUNCTION TYPES
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Type: IDADlsJacFnB
+
+  A Jacobian approximation function JacB for the adjoint (backward) 
+  problem must have the prototype given below. 
+  -----------------------------------------------------------------*/
+typedef int (*IDADlsJacFnB)(realtype tt, realtype c_jB, N_Vector yy, 
+                            N_Vector yp, N_Vector yyB, N_Vector ypB,
+                            N_Vector rrB, SUNMatrix JacB,
+                            void *user_dataB, N_Vector tmp1B,
+                            N_Vector tmp2B, N_Vector tmp3B);
+
+
+/*-----------------------------------------------------------------
+  Type: IDADlsJacFnBS
+
+  A Jacobian approximation function JacBS for the adjoint (backward) 
+  problem, sensitivity-dependent case, must have the prototype given 
+  below. 
+  -----------------------------------------------------------------*/
+typedef int (*IDADlsJacFnBS)(realtype tt, realtype c_jB, N_Vector yy, 
+                             N_Vector yp, N_Vector *yS, N_Vector *ypS,
+                             N_Vector yyB, N_Vector ypB, N_Vector rrB,
+                             SUNMatrix JacB, void *user_dataB, 
+                             N_Vector tmp1B, N_Vector tmp2B,
+                             N_Vector tmp3B);
 
-typedef int (*IDADlsBandJacFnBS)(long int NeqB, long int mupperB, long int mlowerB, 
-				realtype tt, realtype c_jB, 
-				N_Vector yy, N_Vector yp,
-				N_Vector *yS, N_Vector *ypS,
-				N_Vector yyB, N_Vector ypB, N_Vector rrB,
-				DlsMat JacB, void *user_dataB,
-				N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-  
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS 
- * -----------------------------------------------------------------
- */
-
-/*
- * --------------------------------------------------------------------
- * Functions: IDADlsSet*JacFnB and IDADlsSet*JacFnBS
- * --------------------------------------------------------------------
- * IDADlsSetDenseJacFnB and IDADlsSetBandJacFnB specify the dense
- * and band Jacobian functions, respectively, to be used by a
- * IDASDIRECT linear solver for the backward integration phase, when
- * the backward problem does not depend on forward sensitivities.
- * IDADlsSetDenseJacFnBS and IDADlsSetBandJacFnBS specify the Jacobian
- * functions when the backward problem does depend on sensitivities.
- * The 'which' argument is the int returned by IDACreateB.
- * --------------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDADlsSetDenseJacFnB(void *ida_mem, int which, IDADlsDenseJacFnB jacB);
-SUNDIALS_EXPORT int IDADlsSetDenseJacFnBS(void *ida_mem, int which, IDADlsDenseJacFnBS jacBS);
 
-SUNDIALS_EXPORT int IDADlsSetBandJacFnB(void *idaa_mem, int which, IDADlsBandJacFnB jacB);
-SUNDIALS_EXPORT int IDADlsSetBandJacFnBS(void *idaa_mem, int which, IDADlsBandJacFnBS jacBS);
+  
+/*-----------------------------------------------------------------
+  Exported functions
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Required inputs for the IDASDLS linear solver interface:
+
+  IDADlsSetLinearSolverB specifies the direct SUNLinearSolver 
+  object that IDAS should use for backward integration. The 
+  'which' argument is the int returned by IDACreateB.
+
+  The return value is one of:
+    IDADLS_SUCCESS   if successful
+    IDADLS_MEM_NULL  if the IDA memory was NULL
+    IDADLS_ILL_INPUT if the arguments are incompatible
+---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsSetLinearSolverB(void *ida_mem,
+                                           int which,
+                                           SUNLinearSolver LS,
+                                           SUNMatrix A);
+
+/*--------------------------------------------------------------------
+  Functions: IDADlsSetJacFnB and IDADlsSetJacFnBS
+
+  IDADlsSetJacFnB specifies the Jacobian function to be used by a
+  IDASDLS linear solver for the backward integration phase, when
+  the backward problem does not depend on forward sensitivities.
+  IDADlsSetJacFnBS specifies the Jacobian function when the backward 
+  problem does depend on sensitivities.
+  The 'which' argument is the int returned by IDACreateB.
+  --------------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDADlsSetJacFnB(void *ida_mem, int which,
+                                    IDADlsJacFnB jacB);
+SUNDIALS_EXPORT int IDADlsSetJacFnBS(void *ida_mem, int which,
+                                     IDADlsJacFnBS jacBS);
 
 
 #ifdef __cplusplus
diff --git a/include/idas/idas_klu.h b/include/idas/idas_klu.h
deleted file mode 100644
index 8db561a..0000000
--- a/include/idas/idas_klu.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDAKLU linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASKLU_H
-#define _IDASKLU_H
-
-#include "idas/idas_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDAKLU
- * -----------------------------------------------------------------
- * A call to the IDAKLU function links the main integrator      
- * with the IDAKLU linear solver module.                        
- *                                                                
- * ida_mem is the pointer to integrator memory returned by        
- *     IDACreate.             
- *
- *                                                                
- * IDAKLU returns:                                              
- *     IDASLU_SUCCESS   = 0  if successful                              
- *     IDASLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     IDASLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The KLU linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, IDAKLU will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLU(void *ida_mem, int n, int nnz, int sparesetype); 
-
-/*
- * -----------------------------------------------------------------
- * IDAKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to IDAKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is IDASLS_SUCCESS = 0, IDASLS_MEM_NULL = -1, 
- * IDASLS_LMEM_NULL = -2, IDASLS_ILL_INPUT = -3, or IDASLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLUReInit(void *ida_mem_v, int n, int nnz, 
-				   int reinit_type);
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDAKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in KINSOL is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLUSetOrdering(void *ida_mem, int ordering_choice); 
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-
-/*
- * -----------------------------------------------------------------
- * Function: IDAKLUB
- * -----------------------------------------------------------------
- * IDAKLUB links the main IDAS integrator with the IDAKLU
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLUB(void *ida_mem, int which, int nB, int nnzB, int sparsetype);
-
-
-/*
- * -----------------------------------------------------------------
- * Function: IDAKLUReInitB
- * -----------------------------------------------------------------
- * IDAKLUReInitB pulls off the memory block associated with the which parameter
- * and reinitializes the KLU solver associated with that memory block.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLUReInitB(void *ida_mem, int which, int nB, int nnzB, int reinit_type);
-
-
-/*
- * -----------------------------------------------------------------
- * Function: IDAKLUSetOrderingB
- * -----------------------------------------------------------------
- * IDAKLUSetOrderingB pulls off the memory block associated with the which parameter
- * and sets the ordering for the KLU solver associated with that memory block.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDAKLUSetOrderingB(void *ida_mem, int which, int ordering_choiceB);
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_lapack.h b/include/idas/idas_lapack.h
deleted file mode 100644
index 8e5b778..0000000
--- a/include/idas/idas_lapack.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Header file for the IDAS dense linear solver IDASLAPACK.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDALAPACK_H
-#define _IDALAPACK_H
-
-#include <idas/idas_direct.h>
-#include <sundials/sundials_lapack.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : IDALapackDense
- * -----------------------------------------------------------------
- * A call to the IDALapackDense function links the main integrator
- * with the IDALAPACK linear solver using dense Jacobians.
- *
- * ida_mem is the pointer to the integrator memory returned by
- *           IDACreate.
- *
- * N is the size of the DAE system.
- *
- * The return value of IDALapackDense is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDAS memory was NULL
- *    IDADLS_MEM_FAIL  if there was a memory allocation failure
- *    IDADLS_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDALapackDense(void *ida_mem, int N);
-
-/*
- * -----------------------------------------------------------------
- * Function : IDALapackBand
- * -----------------------------------------------------------------
- * A call to the IDALapackBand function links the main integrator
- * with the IDALAPACK linear solver using banded Jacobians. 
- *
- * ida_mem is the pointer to the integrator memory returned by
- *           IDACreate.
- *
- * N is the size of the ODE system.
- *
- * mupper is the upper bandwidth of the band Jacobian approximation.
- *
- * mlower is the lower bandwidth of the band Jacobian approximation.
- *
- * The return value of IDALapackBand is one of:
- *    IDADLS_SUCCESS   if successful
- *    IDADLS_MEM_NULL  if the IDAS memory was NULL
- *    IDADLS_MEM_FAIL  if there was a memory allocation failure
- *    IDADLS_ILL_INPUT if a required vector operation is missing
- *                        or if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDALapackBand(void *ida_mem, int N, int mupper, int mlower);
-
-/*
- * -----------------------------------------------------------------
- * Function: IDALapackDenseB
- * -----------------------------------------------------------------
- * IDALapackDenseB links the main IDAS integrator with the dense
- * IDALAPACK linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDALapackDenseB(void *ida_mem, int which, int NeqB);
-
-/*
- * -----------------------------------------------------------------
- * Function: IDALapackBandB
- * -----------------------------------------------------------------
- * IDALapackBandB links the main IDAS integrator with the band
- * IDALAPACK linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDALapackBandB(void *ida_mem, int which, int NeqB, int mupperB, int mlowerB);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_sparse.h b/include/idas/idas_sparse.h
deleted file mode 100644
index 9ddd7b3..0000000
--- a/include/idas/idas_sparse.h
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the Sparse linear solver module in IDAS.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASSPARSE_H
-#define _IDASSPARSE_H
-
-#include <sundials/sundials_sparse.h>
-#include <sundials/sundials_nvector.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * I D A S S P A R S E    C O N S T A N T S
- * =================================================================
- */
-
-/* 
- * -----------------------------------------------------------------
- * IDASSLS return values 
- * -----------------------------------------------------------------
- */
-
-#define IDASLS_SUCCESS           0
-#define IDASLS_MEM_NULL         -1
-#define IDASLS_LMEM_NULL        -2
-#define IDASLS_ILL_INPUT        -3
-#define IDASLS_MEM_FAIL         -4
-#define IDASLS_JAC_NOSET        -5
-#define IDASLS_PACKAGE_FAIL     -6
-
-/* Additional last_flag values */
-
-#define IDASLS_JACFUNC_UNRECVR  -7
-#define IDASLS_JACFUNC_RECVR    -8
-
-/* Return values for the adjoint module */
-#define IDASLS_NO_ADJ           -101
-#define IDASLS_LMEMB_NULL       -102
-
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASlsSparseJacFn
- * -----------------------------------------------------------------
- *
- * A sparse Jacobian approximation function jaceval must be of type 
- * IDASlsSparseJacFn.
- * Its parameters are:                     
- *                                                                
- * t   is the current value of the independent variable t.        
- *                                                                
- * c_j is the scalar in the system Jacobian, proportional to 
- *     the inverse of the step size h.
- *                                                                
- * y   is the current value of the dependent variable vector,     
- *     namely the predicted value of y(t).                     
- *                                                                
- * yp  is the current value of the derivative vector y',          
- *     namely the predicted value of y'(t).                    
- *                                                                
- * f   is the residual vector F(tt,yy,yp).                     
- *                                                                
- * JacMat is the compressed sparse column matrix (of type SlsMat)
- *     to be loaded by an IDASlsSparseJacFn routine with an approximation
- *     to the system Jacobian matrix
- *            J = dF/dy' + gamma*dF/dy                            
- *     at the given point (t,y,y'), where the ODE system is    
- *     given by F(t,y,y') = 0.
- *     Note that JacMat is NOT preset to zero!
- *     Matrix data is for the nonzero entries of the Jacobian are stored in
- *     compressed column format.  Row indices of entries in 
- *     column j are stored in J->data[colptrs[j]] 
- *     through J->data[colptrs[j+i]-1]
- *     and corresponding numerical values of the Jacobian are stored 
- *     in the same entries of a.
- * 
- * user_data is a pointer to user Jacobian data - the same as the    
- *     user_data parameter passed to IDASetRdata.                     
- *                                                                
- * tmp1, tmp2, tmp3 are pointers to memory allocated for          
- *     N_Vectors which can be used by an IDASparseJacFn routine 
- *     as temporary storage or work space.                     
- *                                                                
- * A IDASlsSparseJacFn should return                                
- *     0 if successful,                                           
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- * In the case of a recoverable error return, the integrator will 
- * attempt to recover by reducing the stepsize (which changes cj).
- *
- * -----------------------------------------------------------------
- *
-  * NOTE: If the user's Jacobian routine needs other quantities,   
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through   
- *     IDAGetCurrentStep and IDAGetErrWeights, respectively 
- *     (see ida.h). The unit roundoff is available as 
- *     UNIT_ROUNDOFF defined in sundials_types.h.
- *
- * -----------------------------------------------------------------
- */
-  
-  
-typedef int (*IDASlsSparseJacFn)(realtype t, realtype c_j,
-		     N_Vector y, N_Vector yp, N_Vector r, 
-		     SlsMat JacMat, void *user_data,
-		     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the IDASSPARSE linear solver
- * -----------------------------------------------------------------
- * IDASlsSetSparseJacFn specifies the Jacobian approximation
- * routine to be used for a sparse direct linear solver.
- *
- * The return value is one of:
- *    IDASLS_SUCCESS   if successful
- *    IDASLS_MEM_NULL  if the IDA memory was NULL
- *    IDASLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASlsSetSparseJacFn(void *ida_mem, IDASlsSparseJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the IDASLS linear solver
- * -----------------------------------------------------------------
- *
- * IDASlsGetWorkSpace   returns the real and integer workspace used
- *                      by the direct linear solver.
- * IDASlsGetNumJacEvals returns the number of calls made to the
- *                      Jacobian evaluation routine jac.
- * IDASlsGetLastFlag    returns the last error flag set by any of
- *                      the IDADLS interface functions.
- *
- * The return value of IDADlsGet* is one of:
- *    IDASLS_SUCCESS   if successful
- *    IDASLS_MEM_NULL  if the IDA memory was NULL
- *    IDASLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASlsGetNumJacEvals(void *ida_mem, long int *njevals);
-SUNDIALS_EXPORT int IDASlsGetLastFlag(void *ida_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a IDASLS return flag
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT char *IDASlsGetReturnFlagName(long int flag);
-
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type: IDASlsSparseJacFnB
- * -----------------------------------------------------------------
- * A sparse Jacobian approximation function JacB for the adjoint
- * (backward) problem must have the prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASlsSparseJacFnB)(realtype tt, realtype c_jB, 
-	      	     N_Vector yy, N_Vector yp,
-		     N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-		     SlsMat JacMatB, void *user_dataB, 
-		     N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * Type: IDASlsSparseJacFnBS
- * -----------------------------------------------------------------
- * A dense Jacobian approximation function JacBS for the adjoint
- * (backward) problem, sensitivity-dependent case, must have the
- *  prototype given below. 
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASlsSparseJacFnBS)(realtype tt, realtype c_jB, 
-	      	     N_Vector yy, N_Vector yp,
-		     N_Vector *yS, N_Vector *ypS,
-		     N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-		     SlsMat JacMatB, void *user_dataB, 
-		     N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS 
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Functions: IDASlsSetSparseJacFnB and IDASlsSetSparseJacFnBS
- * -----------------------------------------------------------------
- * IDASlsSetSparseJacFnB specifies the sparse Jacobian functions to 
- * be used by a IDASSPARSE linear solver for the backward integration phase
- * when the backward problem does not depend on forward sensitivities.
- * IDASlsSetSparseJacFnBS specifies the Jacobian
- * functions when the backward problem does depend on sensitivities.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASlsSetSparseJacFnB(void *ida_mem, int which, 
-					  IDASlsSparseJacFnB jacB);
-SUNDIALS_EXPORT int IDASlsSetSparseJacFnBS(void *ida_mem, int which, 
-					  IDASlsSparseJacFnBS jacBS);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_spbcgs.h b/include/idas/idas_spbcgs.h
deleted file mode 100644
index 4264504..0000000
--- a/include/idas/idas_spbcgs.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the public header file for the IDAS scaled preconditioned
- * Bi-CGSTAB linear solver module, IDASPBCG.
- *
- * Part I contains function prototypes for using IDASPBCG on forward 
- * problems (DAE integration and/or FSA)
- *
- * Part II contains function prototypes for using IDASPBCG on adjoint 
- * (backward) problems
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASSPBCG_H
-#define _IDASSPBCG_H
-
-#include <idas/idas_spils.h>
-#include <sundials/sundials_spbcgs.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcg
- * -----------------------------------------------------------------
- * A call to the IDASpbcg function links the main integrator with
- * the IDASPBCG linear solver module. Its parameters are as
- * follows:
- *
- * IDA_mem   is the pointer to memory block returned by IDACreate.
- *
- * maxl      is the maximum Krylov subspace dimension, an
- *           optional input. Pass 0 to use the default value.
- *           Otherwise pass a positive integer.
- *
- * The return values of IDASpbcg are:
- *    IDASPILS_SUCCESS    if successful
- *    IDASPILS_MEM_NULL   if the IDAS memory was NULL
- *    IDASPILS_MEM_FAIL   if there was a memory allocation failure
- *    IDASPILS_ILL_INPUT  if there was illegal input.
- * The above constants are defined in idas_spils.h
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASpbcg(void *ida_mem, int maxl);
-
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function: IDASpbcgB
- * -----------------------------------------------------------------
- * IDASpbcgB links the main IDAS integrator with the IDASpbcg
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASpbcgB(void *ida_mem, int which, int maxlB);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_spgmr.h b/include/idas/idas_spgmr.h
deleted file mode 100644
index 9b15566..0000000
--- a/include/idas/idas_spgmr.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDAS Scaled Preconditioned GMRES     
- * linear solver module, IDASPGMR.                                 
- *
- * Part I contains function prototypes for using IDASPGMR on forward 
- * problems (DAE integration and/or FSA)
- *
- * Part II contains function prototypes for using IDASPGMR on adjoint 
- * (backward) problems
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASSPGMR_H
-#define _IDASSPGMR_H
-
-#include <idas/idas_spils.h>
-#include <sundials/sundials_spgmr.h>
-
-#ifdef __cplusplus     /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- *                                                                
- * Function : IDASpgmr                                            
- * -----------------------------------------------------------------
- * A call to the IDASpgmr function links the main integrator with 
- * the IDASPGMR linear solver module.  Its parameters are as      
- * follows:                                                       
- *                                                                
- * IDA_mem   is the pointer to memory block returned by IDACreate.
- *                                                                
- * maxl      is the maximum Krylov subspace dimension, an         
- *           optional input.  Pass 0 to use the default value,    
- *           MIN(Neq, 5).  Otherwise pass a positive integer.     
- *                                                                
- * The return values of IDASpgmr are:                             
- *    IDASPILS_SUCCESS    if successful                            
- *    IDASPILS_MEM_NULL   if the IDAS memory was NULL
- *    IDASPILS_MEM_FAIL   if there was a memory allocation failure 
- *    IDASPILS_ILL_INPUT  if there was illegal input.              
- * The above constants are defined in idas_spils.h
- *                                                                
- * -----------------------------------------------------------------
- */                                                                
-
-SUNDIALS_EXPORT int IDASpgmr(void *ida_mem, int maxl);
-
-
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function: IDASpgmrB
- * -----------------------------------------------------------------
- * IDASpgmrB links the main IDAS integrator with the IDASpgmr
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASpgmrB(void *ida_mem, int which, int maxlB);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_spils.h b/include/idas/idas_spils.h
index 58ac018..8a85175 100644
--- a/include/idas/idas_spils.h
+++ b/include/idas/idas_spils.h
@@ -1,22 +1,24 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
  * ----------------------------------------------------------------- 
- * Programmers: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the common header file for the Scaled and Preconditioned
- * Iterative Linear Solvers in IDAS.
+ * Header file for the Scaled and Preconditioned Iterative Linear 
+ * Solvers interface in IDAS.
  * -----------------------------------------------------------------
  */
 
@@ -25,16 +27,15 @@
 
 #include <sundials/sundials_iterative.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_linearsolver.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/* 
- * -----------------------------------------------------------------
- * IDASPILS return values 
- * -----------------------------------------------------------------
- */
+/*===============================================================
+  IDASPILS Return Values
+  ===============================================================*/
 
 #define IDASPILS_SUCCESS     0
 #define IDASPILS_MEM_NULL   -1 
@@ -42,436 +43,484 @@ extern "C" {
 #define IDASPILS_ILL_INPUT  -3
 #define IDASPILS_MEM_FAIL   -4
 #define IDASPILS_PMEM_NULL  -5
+#define IDASPILS_SUNLS_FAIL -6
 
 /* Return values for the adjoint module */
 
 #define IDASPILS_NO_ADJ          -101
 #define IDASPILS_LMEMB_NULL      -102
 
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSetupFn
- * -----------------------------------------------------------------
- * The optional user-supplied functions PrecSetup and PrecSolve
- * together must define the left preconditoner matrix P
- * approximating the system Jacobian matrix
- *    J = dF/dy + c_j*dF/dy'
- * (where the DAE system is F(t,y,y') = 0), and solve the linear
- * systems P z = r.   PrecSetup is to do any necessary setup
- * operations, and PrecSolve is to compute the solution of
- * P z = r.
- *
- * The preconditioner setup function PrecSetup is to evaluate and
- * preprocess any Jacobian-related data needed by the
- * preconditioner solve function PrecSolve.  This might include
- * forming a crude approximate Jacobian, and performing an LU
- * factorization on it.  This function will not be called in
- * advance of every call to PrecSolve, but instead will be called
- * only as often as necessary to achieve convergence within the
- * Newton iteration.  If the PrecSolve function needs no
- * preparation, the PrecSetup function can be NULL.
- *
- * Each call to the PrecSetup function is preceded by a call to
- * the system function res with the same (t,y,y') arguments.
- * Thus the PrecSetup function can use any auxiliary data that is
- * computed and saved by the res function and made accessible
- * to PrecSetup.
- *
- * A preconditioner setup function PrecSetup must have the
- * prototype given below.  Its parameters are as follows:
- *
- * tt  is the current value of the independent variable t.
- *
- * yy  is the current value of the dependent variable vector,
- *     namely the predicted value of y(t).
- *
- * yp  is the current value of the derivative vector y',
- *     namely the predicted value of y'(t).
- *
- * rr  is the current value of the residual vector F(t,y,y').
- *
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *
- * user_data is a pointer to user data, the same as the user_data
- *     parameter passed to IDASetUserData.
- *
- * tmp1, tmp2, tmp3 are pointers to vectors of type N_Vector
- *     which can be used by an IDASpilsPrecSetupFn routine
- *     as temporary storage or work space.
- *
- * NOTE: If the user's preconditioner needs other quantities,
- *     they are accessible as follows: hcur (the current stepsize)
- *     and ewt (the error weight vector) are accessible through
- *     IDAGetCurrentStep and IDAGetErrWeights, respectively (see
- *     ida.h). The unit roundoff is available as
- *     UNIT_ROUNDOFF defined in sundials_types.h
- *
- * The IDASpilsPrecSetupFn should return
- *     0 if successful,
- *     a positive int if a recoverable error occurred, or
- *     a negative int if a nonrecoverable error occurred.
- * In the case of a recoverable error return, the integrator will
- * attempt to recover by reducing the stepsize (which changes cj).
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASpilsPrecSetupFn)(realtype tt,
-				   N_Vector yy, N_Vector yp, N_Vector rr,
-				   realtype c_j, void *user_data,
-				   N_Vector tmp1, N_Vector tmp2,
-				   N_Vector tmp3);
+/*===============================================================
+  PART I - forward problems
+  ===============================================================*/
 
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSolveFn
- * -----------------------------------------------------------------
- * The optional user-supplied function PrecSolve must compute a
- * solution to the linear system P z = r, where P is the left
- * preconditioner defined by the user.  If no preconditioning
- * is desired, pass NULL for PrecSolve to IDASp*.
- *
- * A preconditioner solve function PrecSolve must have the
- * prototype given below.  Its parameters are as follows:
- *
- * tt is the current value of the independent variable t.
- *
- * yy is the current value of the dependent variable vector y.
- *
- * yp is the current value of the derivative vector y'.
- *
- * rr is the current value of the residual vector F(t,y,y').
- *
- * rvec is the input right-hand side vector r.
- *
- * zvec is the computed solution vector z.
- *
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *
- * delta is an input tolerance for use by PrecSolve if it uses an
- *     iterative method in its solution.   In that case, the
- *     the residual vector r - P z of the system should be
- *     made less than delta in weighted L2 norm, i.e.,
- *            sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta .
- *     Note: the error weight vector ewt can be obtained
- *     through a call to the routine IDAGetErrWeights.
- *
- * user_data is a pointer to user data, the same as the user_data
- *     parameter passed to IDASetUserData.
- *
- * tmp is an N_Vector which can be used by the PrecSolve
- *     routine as temporary storage or work space.
- *
- * The IDASpilsPrecSolveFn should return
- *     0 if successful,
- *     a positive int if a recoverable error occurred, or
- *     a negative int if a nonrecoverable error occurred.
- * Following a recoverable error, the integrator will attempt to
- * recover by updating the preconditioner and/or reducing the
- * stepsize.
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASpilsPrecSolveFn)(realtype tt,
-				   N_Vector yy, N_Vector yp, N_Vector rr,
+/*---------------------------------------------------------------
+  IDASPILS user-supplied function prototypes
+  ---------------------------------------------------------------*/
+  
+/*-----------------------------------------------------------------
+  Type : IDASpilsPrecSetupFn
+
+  The optional user-supplied functions PrecSetup and PrecSolve
+  together must define the left preconditoner matrix P
+  approximating the system Jacobian matrix
+     J = dF/dy + c_j*dF/dy'
+  (where the DAE system is F(t,y,y') = 0), and solve the linear
+  systems P z = r.   PrecSetup is to do any necessary setup
+  operations, and PrecSolve is to compute the solution of
+  P z = r.
+ 
+  The preconditioner setup function PrecSetup is to evaluate and
+  preprocess any Jacobian-related data needed by the
+  preconditioner solve function PrecSolve.  This might include
+  forming a crude approximate Jacobian, and performing an LU
+  factorization on it.  This function will not be called in
+  advance of every call to PrecSolve, but instead will be called
+  only as often as necessary to achieve convergence within the
+  Newton iteration.  If the PrecSolve function needs no
+  preparation, the PrecSetup function can be NULL.
+ 
+  Each call to the PrecSetup function is preceded by a call to
+  the system function res with the same (t,y,y') arguments.
+  Thus the PrecSetup function can use any auxiliary data that is
+  computed and saved by the res function and made accessible
+  to PrecSetup.
+ 
+  A preconditioner setup function PrecSetup must have the
+  prototype given below.  Its parameters are as follows:
+ 
+  tt  is the current value of the independent variable t.
+ 
+  yy  is the current value of the dependent variable vector,
+      namely the predicted value of y(t).
+ 
+  yp  is the current value of the derivative vector y',
+      namely the predicted value of y'(t).
+ 
+  rr  is the current value of the residual vector F(t,y,y').
+ 
+  c_j is the scalar in the system Jacobian, proportional to 1/hh.
+ 
+  user_data is a pointer to user data, the same as the user_data
+      parameter passed to IDASetUserData.
+ 
+  NOTE: If the user's preconditioner needs other quantities,
+      they are accessible as follows: hcur (the current stepsize)
+      and ewt (the error weight vector) are accessible through
+      IDAGetCurrentStep and IDAGetErrWeights, respectively (see
+      ida.h). The unit roundoff is available as
+      UNIT_ROUNDOFF defined in sundials_types.h
+ 
+  The IDASpilsPrecSetupFn should return
+      0 if successful,
+      a positive int if a recoverable error occurred, or
+      a negative int if a nonrecoverable error occurred.
+  In the case of a recoverable error return, the integrator will
+  attempt to recover by reducing the stepsize (which changes cj).
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSetupFn)(realtype tt, N_Vector yy,
+                                   N_Vector yp, N_Vector rr,
+				   realtype c_j, void *user_data);
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsPrecSolveFn
+
+  The optional user-supplied function PrecSolve must compute a
+  solution to the linear system P z = r, where P is the left
+  preconditioner defined by the user.  If no preconditioning
+  is desired, pass NULL for PrecSolve to IDASp*.
+ 
+  A preconditioner solve function PrecSolve must have the
+  prototype given below.  Its parameters are as follows:
+ 
+  tt is the current value of the independent variable t.
+ 
+  yy is the current value of the dependent variable vector y.
+ 
+  yp is the current value of the derivative vector y'.
+ 
+  rr is the current value of the residual vector F(t,y,y').
+ 
+  rvec is the input right-hand side vector r.
+ 
+  zvec is the computed solution vector z.
+ 
+  c_j is the scalar in the system Jacobian, proportional to 1/hh.
+ 
+  delta is an input tolerance for use by PrecSolve if it uses an
+      iterative method in its solution.   In that case, the
+      the residual vector r - P z of the system should be
+      made less than delta in weighted L2 norm, i.e.,
+             sqrt [ Sum (Res[i]*ewt[i])^2 ] < delta .
+      Note: the error weight vector ewt can be obtained
+      through a call to the routine IDAGetErrWeights.
+ 
+  user_data is a pointer to user data, the same as the user_data
+      parameter passed to IDASetUserData.
+ 
+  The IDASpilsPrecSolveFn should return
+      0 if successful,
+      a positive int if a recoverable error occurred, or
+      a negative int if a nonrecoverable error occurred.
+  Following a recoverable error, the integrator will attempt to
+  recover by updating the preconditioner and/or reducing the
+  stepsize.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSolveFn)(realtype tt, N_Vector yy,
+                                   N_Vector yp, N_Vector rr,
 				   N_Vector rvec, N_Vector zvec,
-				   realtype c_j, realtype delta, void *user_data,
-				   N_Vector tmp);
-
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsJacTimesVecFn
- * -----------------------------------------------------------------
- * The user-supplied function jtimes is to generate the product
- * J*v for given v, where J is the Jacobian matrix
- *    J = dF/dy + c_j*dF/dy'
- *  or an approximation to it, and v is a given vector.
- * It should return 0 if successful and a nonzero int otherwise.
- *
- * A function jtimes must have the prototype given below. Its
- * parameters are as follows:
- *
- *   tt   is the current value of the independent variable.
- *
- *   yy   is the current value of the dependent variable vector,
- *        namely the predicted value of y(t).
- *
- *   yp   is the current value of the derivative vector y',
- *        namely the predicted value of y'(t).
- *
- *   rr   is the current value of the residual vector F(t,y,y').
- *
- *   v    is the N_Vector to be multiplied by J.
- *
- *   Jv   is the output N_Vector containing J*v.
- *
- *   c_j  is the scalar in the system Jacobian, proportional
- *        to 1/hh.
- *
- *   user_data is a pointer to user data, the same as the
- *        pointer passed to IDASetUserData.
- *
- *   tmp1, tmp2 are two N_Vectors which can be used by Jtimes for
- *         work space.
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASpilsJacTimesVecFn)(realtype tt,
-				     N_Vector yy, N_Vector yp, N_Vector rr,
+				   realtype c_j, realtype delta,
+                                   void *user_data);
+
+/*---------------------------------------------------------------
+ Type: IDASpilsJacTimesSetupFn
+
+ The user-supplied Jacobian-times-vector product setup function 
+ JacTimesSetup and the user-supplied Jacobian-times-vector 
+ product function JTimes together must generate the product
+ J*v for v, where J is the Jacobian matrix
+     J = dF/dy + c_j*dF/dy'
+ or an approximation to it, and v is a given vector. 
+
+ Each call to the JacTimesSetup function is preceded by a call 
+ to the residual res with the same (t,y) arguments.  Thus the 
+ JacTimesSetup function can use any auxiliary data that is 
+ computed and saved by the res function and made accessible to 
+ JacTimesSetup.
+
+ A function JacTimesSetup must have the prototype given below.
+ Its parameters are as follows:
+
+ t       is the current value of the independent variable.
+
+ y       is the current value of the dependent variable vector,
+          namely the predicted value of y(t).
+
+ fy      is the vector f(t,y).
+
+ user_data  is a pointer to user data - the same as the user_data
+         parameter passed to the IDASetUserData function.
+
+ Returned value:
+ The value to be returned by the JacTimesSetup function is a flag
+ indicating whether it was successful.  This value should be
+   0   if successful,
+   > 0 for a recoverable error (step will be retried),
+   < 0 for an unrecoverable error (integration is halted).
+  ---------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesSetupFn)(realtype tt, N_Vector yy,
+                                       N_Vector yp, N_Vector rr,
+                                       realtype c_j, void *user_data);
+
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsJacTimesVecFn
+
+  The user-supplied function jtimes is to generate the product
+  J*v for given v, where J is the Jacobian matrix
+     J = dF/dy + c_j*dF/dy'
+   or an approximation to it, and v is a given vector.
+  It should return 0 if successful and a nonzero int otherwise.
+ 
+  A function jtimes must have the prototype given below. Its
+  parameters are as follows:
+ 
+    tt   is the current value of the independent variable.
+ 
+    yy   is the current value of the dependent variable vector,
+         namely the predicted value of y(t).
+ 
+    yp   is the current value of the derivative vector y',
+         namely the predicted value of y'(t).
+ 
+    rr   is the current value of the residual vector F(t,y,y').
+ 
+    v    is the N_Vector to be multiplied by J.
+ 
+    Jv   is the output N_Vector containing J*v.
+ 
+    c_j  is the scalar in the system Jacobian, proportional
+         to 1/hh.
+ 
+    user_data is a pointer to user data, the same as the
+         pointer passed to IDASetUserData.
+ 
+    tmp1, tmp2 are two N_Vectors which can be used by Jtimes for
+          work space.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesVecFn)(realtype tt, N_Vector yy, 
+				     N_Vector yp, N_Vector rr,
 				     N_Vector v, N_Vector Jv,
 				     realtype c_j, void *user_data,
 				     N_Vector tmp1, N_Vector tmp2);
 
 
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the IDASPILS linear solver                  
- * -----------------------------------------------------------------
- *                                                                
- * IDASpilsSetPreconditioner specifies the PrecSetup and PrecSolve 
- *           functions, as well as a pointer to user preconditioner 
- *           data. This pointer is passed to PrecSetup and PrecSolve
- *           every time these routines are called.
- *           Default is NULL for al three arguments.
- * IDASpilsSetJacTimesVecFn specifies the jtimes function.        
- *           Default is to use an internal finite difference      
- *           approximation routine.                          
- * IDASpilsSetGSType specifies the type of Gram-Schmidt           
- *           orthogonalization to be used. This must be one of    
- *           the two enumeration constants MODIFIED_GS or         
- *           CLASSICAL_GS defined in iterativ.h. These correspond 
- *           to using modified Gram-Schmidt and classical         
- *           Gram-Schmidt, respectively.                          
- *           Default value is MODIFIED_GS.                        
- *           Only for IDASPGMR.
- * IDASpilsSetMaxRestarts specifies the maximum number of restarts
- *           to be used in the GMRES algorithm.  maxrs must be a  
- *           non-negative integer.  Pass 0 to specify no restarts.
- *           Default is 5.                                        
- *           Only for IDASPGMR.
- * IDASpbcgSetMaxl specifies the maximum Krylov subspace size. 
- *           Default is 5.
- *           Only for IDASPBCG and IDASPTFQMR.
- * IDASpilsSetEpsLin specifies the factor in the linear iteration 
- *           convergence test constant.                           
- *           Default is 0.05                                      
- * IDASpilsSetIncrementFactor specifies a factor in the increments
- *           to yy used in the difference quotient approximations 
- *           to matrix-vector products Jv.                        
- *           Default is 1.0                                       
- *                                                                
- * The return value of IDASpilsSet* is one of:
- *    IDASPILS_SUCCESS   if successful
- *    IDASPILS_MEM_NULL  if the IDAS memory was NULL
- *    IDASPILS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
+/*---------------------------------------------------------------
+  IDASPILS Exported functions
+  ---------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int IDASpilsSetPreconditioner(void *ida_mem,
-                                              IDASpilsPrecSetupFn pset, 
-					      IDASpilsPrecSolveFn psolve);
-SUNDIALS_EXPORT int IDASpilsSetJacTimesVecFn(void *ida_mem,
-                                             IDASpilsJacTimesVecFn jtv);
-
-SUNDIALS_EXPORT int IDASpilsSetGSType(void *ida_mem, int gstype);
-SUNDIALS_EXPORT int IDASpilsSetMaxRestarts(void *ida_mem, int maxrs);
-SUNDIALS_EXPORT int IDASpilsSetMaxl(void *ida_mem, int maxl);
-SUNDIALS_EXPORT int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac);
-SUNDIALS_EXPORT int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac);
 
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the IDASPILS linear solver               
- *----------------------------------------------------------------
- *                                                                
- * IDASpilsGetWorkSpace returns the real and integer workspace used 
- *     by IDASPILS.                                                  
- * IDASpilsGetNumPrecEvals returns the number of preconditioner   
- *     evaluations, i.e. the number of calls made to PrecSetup    
- *     with jok==FALSE.                                           
- * IDASpilsGetNumPrecSolves returns the number of calls made to   
- *     PrecSolve.                                                 
- * IDASpilsGetNumLinIters returns the number of linear iterations.
- * IDASpilsGetNumConvFails returns the number of linear           
- *     convergence failures.                                      
- * IDASpilsGetNumJtimesEvals returns the number of calls to jtimes
- * IDASpilsGetNumResEvals returns the number of calls to the user 
- *     res routine due to finite difference Jacobian times vector 
- *     evaluation.                                                
- * IDASpilsGetLastFlag returns the last error flag set by any of
- *     the IDASPILS interface functions.
- *                                                                
- * The return value of IDASpilsGet* is one of:
- *    IDASPILS_SUCCESS   if successful
- *    IDASPILS_MEM_NULL  if the IDAS memory was NULL
- *    IDASPILS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */                                                                
+/*---------------------------------------------------------------
+  Required inputs for the IDASPILS linear solver interface:
 
-SUNDIALS_EXPORT int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS);
-SUNDIALS_EXPORT int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals);
-SUNDIALS_EXPORT int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves);
-SUNDIALS_EXPORT int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters);
-SUNDIALS_EXPORT int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails);
-SUNDIALS_EXPORT int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals);
-SUNDIALS_EXPORT int IDASpilsGetNumResEvals(void *ida_mem, long int *nrevalsLS); 
-SUNDIALS_EXPORT int IDASpilsGetLastFlag(void *ida_mem, long int *flag);
+  IDASpilsSetLinearSolver specifies the iterative SUNLinearSolver 
+  object that IDA should use.  
 
+  The return value is one of:
+     IDASPILS_SUCCESS   if successful
+     IDASPILS_MEM_NULL  if the IDA memory was NULL
+     IDASPILS_ILL_INPUT if the linear solver memory was NULL
+  ---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDASpilsSetLinearSolver(void *ida_mem, 
+                                            SUNLinearSolver LS);
 
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a IDASPILS return flag
- * -----------------------------------------------------------------
- */
   
+/*-----------------------------------------------------------------
+  Optional inputs to the IDASPILS linear solver -- ALL of these 
+  must be called AFTER the corresponding iterative linear solver 
+  object has been attached to IDA).
+                                                                 
+  IDASpilsSetPreconditioner specifies the PrecSetup and PrecSolve 
+            functions, as well as a pointer to user preconditioner 
+            data. This pointer is passed to PrecSetup and PrecSolve
+            every time these routines are called.
+            Default is NULL for al three arguments.
+  IDASpilsSetJacTimes specifies the jtimes function.        
+            Default is to use an internal finite difference      
+            approximation routine.                          
+  IDASpilsSetEpsLin specifies the factor in the linear iteration 
+            convergence test constant.                           
+            Default is 0.05                                      
+  IDASpilsSetIncrementFactor specifies a factor in the increments
+            to yy used in the difference quotient approximations 
+            to matrix-vector products Jv.                        
+            Default is 1.0                                       
+                                                                 
+  The return value of IDASpilsSet* is one of:
+     IDASPILS_SUCCESS   if successful
+     IDASPILS_MEM_NULL  if the IDAS memory was NULL
+     IDASPILS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDASpilsSetPreconditioner(void *ida_mem,
+                                              IDASpilsPrecSetupFn pset, 
+					      IDASpilsPrecSolveFn psolve);
+SUNDIALS_EXPORT int IDASpilsSetJacTimes(void *ida_mem,
+                                        IDASpilsJacTimesSetupFn jtsetup,
+                                        IDASpilsJacTimesVecFn jtimes);
+SUNDIALS_EXPORT int IDASpilsSetEpsLin(void *ida_mem,
+                                      realtype eplifac);
+SUNDIALS_EXPORT int IDASpilsSetIncrementFactor(void *ida_mem,
+                                               realtype dqincfac);
+
+/*-----------------------------------------------------------------
+  Optional outputs from the IDASPILS linear solver interface:
+                                                                 
+  IDASpilsGetWorkSpace returns the real and integer workspace used 
+      by IDASPILS.                                                  
+
+  IDASpilsGetNumPrecEvals returns the number of preconditioner   
+      evaluations, i.e. the number of calls made to PrecSetup    
+      with jok==SUNFALSE.                                           
+
+  IDASpilsGetNumPrecSolves returns the number of calls made to   
+      PrecSolve.                                                 
+
+  IDASpilsGetNumLinIters returns the number of linear iterations.
+
+  IDASpilsGetNumConvFails returns the number of linear           
+      convergence failures.                                      
+
+  IDASpilsGetNumJtimesEvals returns the number of calls to jtimes
+
+  IDASpilsGetNumResEvals returns the number of calls to the user 
+      res routine due to finite difference Jacobian times vector 
+      evaluation.                                                
+
+  IDASpilsGetLastFlag returns the last error flag set by any of
+      the IDASPILS interface functions.
+                                                                 
+  The return value of IDASpilsGet* is one of:
+     IDASPILS_SUCCESS   if successful
+     IDASPILS_MEM_NULL  if the IDAS memory was NULL
+     IDASPILS_LMEM_NULL if the linear solver memory was NULL
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDASpilsGetWorkSpace(void *ida_mem,
+                                         long int *lenrwLS,
+                                         long int *leniwLS);
+SUNDIALS_EXPORT int IDASpilsGetNumPrecEvals(void *ida_mem,
+                                            long int *npevals);
+SUNDIALS_EXPORT int IDASpilsGetNumPrecSolves(void *ida_mem,
+                                             long int *npsolves);
+SUNDIALS_EXPORT int IDASpilsGetNumLinIters(void *ida_mem,
+                                           long int *nliters);
+SUNDIALS_EXPORT int IDASpilsGetNumConvFails(void *ida_mem,
+                                            long int *nlcfails);
+SUNDIALS_EXPORT int IDASpilsGetNumJtimesEvals(void *ida_mem,
+                                              long int *njvevals);
+SUNDIALS_EXPORT int IDASpilsGetNumResEvals(void *ida_mem,
+                                           long int *nrevalsLS); 
+SUNDIALS_EXPORT int IDASpilsGetLastFlag(void *ida_mem,
+                                        long int *flag);
+
+
+/*-----------------------------------------------------------------
+  The following function returns the name of the constant 
+  associated with a IDASPILS return flag
+  -----------------------------------------------------------------*/
 SUNDIALS_EXPORT char *IDASpilsGetReturnFlagName(long int flag);
 
 
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSetupFnB
- * -----------------------------------------------------------------
- * A function PrecSetupB for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
-typedef int (*IDASpilsPrecSetupFnB)(realtype tt, 
-				    N_Vector yy, N_Vector yp,
-				    N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-				    realtype c_jB, void *user_dataB,
-				    N_Vector tmp1B, N_Vector tmp2B, 
-				    N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSetupFnBS
- * -----------------------------------------------------------------
- * A function PrecSetupBS for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
-typedef int (*IDASpilsPrecSetupFnBS)(realtype tt,
-                                     N_Vector yy, N_Vector yp,
-                                     N_Vector *yyS, N_Vector *ypS,
-                                     N_Vector yyB, N_Vector ypB, N_Vector rrB,
-                                     realtype c_jB, void *user_dataB,
-                                     N_Vector tmp1B, N_Vector tmp2B,
-                                     N_Vector tmp3B);
-
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSolveFnB
- * -----------------------------------------------------------------
- * A function PrecSolveB for the adjoint (backward) problem  must 
- * have the prototype given below.
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASpilsPrecSolveFnB)(realtype tt, 
-				    N_Vector yy, N_Vector yp,
-				    N_Vector yyB, N_Vector ypB, N_Vector rrB, 
+  
+/*=================================================================
+  PART II - backward problems
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsPrecSetupFnB
+
+  A function PrecSetupB for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSetupFnB)(realtype tt, N_Vector yy, 
+				    N_Vector yp, N_Vector yyB, 
+				    N_Vector ypB, N_Vector rrB, 
+				    realtype c_jB, void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsPrecSetupFnBS
+
+  A function PrecSetupBS for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSetupFnBS)(realtype tt, N_Vector yy, 
+                                     N_Vector yp, N_Vector *yyS, 
+                                     N_Vector *ypS, N_Vector yyB, 
+                                     N_Vector ypB, N_Vector rrB,
+                                     realtype c_jB, void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsPrecSolveFnB
+
+  A function PrecSolveB for the adjoint (backward) problem  must 
+  have the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSolveFnB)(realtype tt, N_Vector yy,  
+				    N_Vector yp, N_Vector yyB, 
+				    N_Vector ypB, N_Vector rrB, 
 				    N_Vector rvecB, N_Vector zvecB,
 				    realtype c_jB, realtype deltaB,
-				    void *user_dataB, N_Vector tmpB);
-
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsPrecSolveFnBS
- * -----------------------------------------------------------------
- * A function PrecSolveBS for the adjoint (backward) problem  must 
- * have the prototype given below.
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASpilsPrecSolveFnBS)(realtype tt,
-                                     N_Vector yy, N_Vector yp,
-                                     N_Vector *yyS, N_Vector *ypS,
-                                     N_Vector yyB, N_Vector ypB, N_Vector rrB,
+				    void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsPrecSolveFnBS
+
+  A function PrecSolveBS for the adjoint (backward) problem  must 
+  have the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsPrecSolveFnBS)(realtype tt, N_Vector yy, 
+                                     N_Vector yp, N_Vector *yyS, 
+                                     N_Vector *ypS, N_Vector yyB, 
+                                     N_Vector ypB, N_Vector rrB,
                                      N_Vector rvecB, N_Vector zvecB,
                                      realtype c_jB, realtype deltaB,
-                                     void *user_dataB, N_Vector tmpB);
-
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsJacTimesVecFnB
- * -----------------------------------------------------------------
- * A function jtimesB for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
-
-typedef int (*IDASpilsJacTimesVecFnB)(realtype t,
-				      N_Vector yy, N_Vector yp,
-				      N_Vector yyB, N_Vector ypB, N_Vector rrB,
+                                     void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsJacTimesSetupFnB
+
+  A function jtsetupB for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesSetupFnB)(realtype t, N_Vector yy,
+                                        N_Vector yp, N_Vector yyB,
+                                        N_Vector ypB, N_Vector rrB,
+                                        realtype c_jB, void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsJacTimesSetupFnBS
+
+  A function jtsetupBS for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesSetupFnBS)(realtype t, N_Vector yy, 
+                                         N_Vector yp, N_Vector *yyS,
+                                         N_Vector *ypS, N_Vector yyB,
+                                         N_Vector ypB, N_Vector rrB,
+                                         realtype c_jB, void *user_dataB);
+
+/*-----------------------------------------------------------------
+  Type : IDASpilsJacTimesVecFnB
+
+  A function jtimesB for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesVecFnB)(realtype t, N_Vector yy, 
+				      N_Vector yp, N_Vector yyB, 
+				      N_Vector ypB, N_Vector rrB,
 				      N_Vector vB, N_Vector JvB, 
 				      realtype c_jB, void *user_dataB, 
 				      N_Vector tmp1B, N_Vector tmp2B);
 
-/*
- * -----------------------------------------------------------------
- * Type : IDASpilsJacTimesVecFnBS
- * -----------------------------------------------------------------
- * A function jtimesBS for the adjoint (backward) problem must have 
- * the prototype given below.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type : IDASpilsJacTimesVecFnBS
 
-typedef int (*IDASpilsJacTimesVecFnBS)(realtype t,
-                                       N_Vector yy, N_Vector yp,
-                                       N_Vector *yyS, N_Vector *ypS,
-                                       N_Vector yyB, N_Vector ypB, N_Vector rrB,
+  A function jtimesBS for the adjoint (backward) problem must have 
+  the prototype given below.
+  -----------------------------------------------------------------*/
+typedef int (*IDASpilsJacTimesVecFnBS)(realtype t, N_Vector yy, 
+                                       N_Vector yp, N_Vector *yyS, 
+                                       N_Vector *ypS, N_Vector yyB, 
+                                       N_Vector ypB, N_Vector rrB,
                                        N_Vector vB, N_Vector JvB, 
                                        realtype c_jB, void *user_dataB, 
                                        N_Vector tmp1B, N_Vector tmp2B);
 
-/*
- * -----------------------------------------------------------------
- * Functions
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Each IDASpilsSet***B or IDASpilsSet***BS function below links the
- * main IDAS integrator with the corresponding IDASpilsSet***
- * optional input function for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASpilsSetGSTypeB(void *ida_mem, int which, int gstypeB);
-SUNDIALS_EXPORT int IDASpilsSetMaxRestartsB(void *ida_mem, int which, int maxrsB);
-SUNDIALS_EXPORT int IDASpilsSetEpsLinB(void *ida_mem, int which, realtype eplifacB);
-SUNDIALS_EXPORT int IDASpilsSetMaxlB(void *ida_mem, int which, int maxlB);
+  
+/*---------------------------------------------------------------
+  Required input for the IDASPILS linear solver interface:
+
+  IDASpilsSetLinearSolverB specifies the iterative SUNLinearSolver 
+  object that IDA should use for the backwards integration.  The 
+  'which' argument is the int returned by IDACreateB.
+
+  The return value is one of:
+     IDASPILS_SUCCESS   if successful
+     IDASPILS_MEM_NULL  if the IDA memory was NULL
+     IDASPILS_ILL_INPUT if the linear solver memory was NULL
+  ---------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDASpilsSetLinearSolverB(void *ida_mem,
+                                             int which,
+                                             SUNLinearSolver LS);
+
+ 
+/*-----------------------------------------------------------------
+  Optional Set Routines
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Each IDASpilsSet***B or IDASpilsSet***BS function below links the
+  main IDAS integrator with the corresponding IDASpilsSet***
+  optional input function for the backward integration.
+  The 'which' argument is the int returned by IDACreateB.
+  -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int IDASpilsSetEpsLinB(void *ida_mem, int which,
+                                       realtype eplifacB);
 SUNDIALS_EXPORT int IDASpilsSetIncrementFactorB(void *ida_mem, int which, 
                                                 realtype dqincfacB);
-
 SUNDIALS_EXPORT int IDASpilsSetPreconditionerB(void *ida_mem, int which,
                                                IDASpilsPrecSetupFnB psetB,
 					       IDASpilsPrecSolveFnB psolveB);
 SUNDIALS_EXPORT int IDASpilsSetPreconditionerBS(void *ida_mem, int which,
                                                 IDASpilsPrecSetupFnBS psetBS,
                                                 IDASpilsPrecSolveFnBS psolveBS);
-
-SUNDIALS_EXPORT int IDASpilsSetJacTimesVecFnB(void *ida_mem, int which,
-                                              IDASpilsJacTimesVecFnB jtvB);
-SUNDIALS_EXPORT int IDASpilsSetJacTimesVecFnBS(void *ida_mem, int which,
-                                               IDASpilsJacTimesVecFnBS jtvBS);
-
-
-
+SUNDIALS_EXPORT int IDASpilsSetJacTimesB(void *ida_mem, int which,
+                                         IDASpilsJacTimesSetupFnB jtsetupB,
+                                         IDASpilsJacTimesVecFnB jtimesB);
+SUNDIALS_EXPORT int IDASpilsSetJacTimesBS(void *ida_mem, int which,
+                                          IDASpilsJacTimesSetupFnBS jtsetupBS,
+                                          IDASpilsJacTimesVecFnBS jtimesBS);
+
+ 
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/idas/idas_sptfqmr.h b/include/idas/idas_sptfqmr.h
deleted file mode 100644
index 0d22174..0000000
--- a/include/idas/idas_sptfqmr.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4489 $
- * $Date: 2015-04-29 17:15:44 -0700 (Wed, 29 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the public header file for the IDAS scaled preconditioned
- * TFQMR linear solver module, IDASPTFQMR.
- *
- * Part I contains function prototypes for using IDASPTFQMR on forward 
- * problems (DAE integration and/or FSA)
- *
- * Part II contains function prototypes for using IDASPTFQMR on adjoint 
- * (backward) problems
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASSPTFQMR_H
-#define _IDASSPTFQMR_H
-
-#include <idas/idas_spils.h>
-#include <sundials/sundials_sptfqmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/* 
- * -----------------------------------------------------------------
- * PART I - forward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmr
- * -----------------------------------------------------------------
- * A call to the IDASptfqmr function links the main integrator with
- * the IDASPTFQMR linear solver module. Its parameters are as
- * follows:
- *
- * IDA_mem  is the pointer to memory block returned by IDACreate.
- *
- * maxl     is the maximum Krylov subspace dimension, an
- *          optional input. Pass 0 to use the default value.
- *          Otherwise pass a positive integer.
- *
- * The return values of IDASptfqmr are:
- *    IDASPILS_SUCCESS    if successful
- *    IDASPILS_MEM_NULL   if the IDAS memory was NULL
- *    IDASPILS_MEM_FAIL   if there was a memory allocation failure
- *    IDASPILS_ILL_INPUT  if there was illegal input.
- * The above constants are defined in idas_spils.h
- *
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int IDASptfqmr(void *ida_mem, int maxl);
-
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Function: IDASptfqmrB
- * -----------------------------------------------------------------
- * IDASptfqmrB links the main IDAS integrator with the IDASptfqmr
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-
-SUNDIALS_EXPORT int IDASptfqmrB(void *ida_mem, int which, int maxlB);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/idas/idas_superlumt.h b/include/idas/idas_superlumt.h
deleted file mode 100644
index 2606b7d..0000000
--- a/include/idas/idas_superlumt.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4491 $
- * $Date: 2015-04-30 16:56:10 -0700 (Thu, 30 Apr 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the IDASuperLUMT linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASSUPERLUMT_H
-#define _IDASSUPERLUMT_H
-
-#include "idas/idas_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-/*
- * -----------------------------------------------------------------
- * Function : IDASuperLUMT
- * -----------------------------------------------------------------
- * A call to the IDASuperLUMT function links the main integrator      
- * with the IDASuperLUMT linear solver module.                        
- *                                                                
- * ida_mem is the pointer to integrator memory returned by        
- *     IDACreate.             
- *
- * num_threads is the number of threads that SuperLUMT should invoke     
- *                                                                
- * IDASuperLUMT returns:                                              
- *     IDASLU_SUCCESS   = 0  if successful                              
- *     IDASLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     IDASLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The SuperLUMT linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, IDASuperLUMT will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDASuperLUMT(void *ida_mem, int num_threads, 
-				   int n, int nnz); 
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDASuperLUMTSetOrdering sets the ordering used by SuperLUMT for 
- * reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDASuperLUMTSetOrdering(void *ida_mem, 
-					      int ordering_choice); 
-
-
-
-/*
- * -----------------------------------------------------------------
- * Function: IDASuperLUMTB
- * -----------------------------------------------------------------
- * IDASuperLUMTB links the main IDAS integrator with the IDASuperLUMT
- * linear solver for the backward integration.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int IDASuperLUMTB(void *ida_mem, int which, int num_threads, 
-				    int nB, int nnzB);
-
-
-/*
- * -----------------------------------------------------------------
- * Function: IDASuperLUMTSetOrderingB
- * -----------------------------------------------------------------
- * IDASuperLUMTSetOrderingB pulls off the memory block associated with the which parameter
- * and sets the ordering for the KLU solver associated with that memory block.
- * The 'which' argument is the int returned by IDACreateB.
- * -----------------------------------------------------------------
- */
-  SUNDIALS_EXPORT int IDASuperLUMTSetOrderingB(void *ida_mem, int which, 
-					      int ordering_choiceB); 
-
-
-  
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol.h b/include/kinsol/kinsol.h
index 4ea5604..74fffea 100644
--- a/include/kinsol/kinsol.h
+++ b/include/kinsol/kinsol.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4423 $
- * $Date: 2015-03-08 17:23:10 -0700 (Sun, 08 Mar 2015) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
@@ -291,15 +291,15 @@ SUNDIALS_EXPORT void *KINCreate(void);
  * KINSetNoInitSetup      | flag controlling whether or not the
  *                        | KINSol routine makes an initial call
  *                        | to the linear solver setup routine (lsetup)
- *                        | (possible values are TRUE and FALSE)
- *                        | [FALSE]
+ *                        | (possible values are SUNTRUE and SUNFALSE)
+ *                        | [SUNFALSE]
  *                        |
  * KINSetNoResMon         | flag controlling whether or not the nonlinear
  *                        | residual monitoring scheme is used to control
- *                        | Jacobian updating (possible values are TRUE
- *                        | and FALSE)
- *                        | [FALSE if using direct linear solver]
- *                        | [TRUE if using inexact linear solver]
+ *                        | Jacobian updating (possible values are SUNTRUE
+ *                        | and SUNFALSE)
+ *                        | [SUNFALSE if using direct linear solver]
+ *                        | [SUNTRUE if using inexact linear solver]
  *                        |
  * KINSetMaxSetupCalls    | mbset, number of nonlinear iteraions, such 
  *                        | that a call to the linear solver setup routine
@@ -373,13 +373,13 @@ SUNDIALS_EXPORT void *KINCreate(void);
  *                        | of eps is bounded below by 0.01*fnormtol
  *                        | (see KINSetFuncNormTol)
  *                        |
- *                        |  FALSE  constrain value of eps by setting
- *                        |         to the following:
+ *                        |  SUNFALSE  constrain value of eps by setting
+ *                        |            to the following:
  *                        |
- *                        |          eps = MAX{0.01*fnormtol, eps}
+ *                        |            eps = MAX{0.01*fnormtol, eps}
  *                        |
- *                        |  TRUE  do not constrain value of eps
- *                        | [FALSE]
+ *                        |  SUNTRUE   do not constrain value of eps
+ *                        | [SUNFALSE]
  *                        |
  * KINSetMaxNewtonStep    | maximum scaled length of Newton step
  *                        | (reset to value of one if user-supplied
diff --git a/include/kinsol/kinsol_band.h b/include/kinsol/kinsol_band.h
deleted file mode 100644
index c79b111..0000000
--- a/include/kinsol/kinsol_band.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the KINSOL band linear solver, KINBAND.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINBAND_H
-#define _KINBAND_H
-
-#include <kinsol/kinsol_direct.h>
-#include <sundials/sundials_band.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : KINBand
- * -----------------------------------------------------------------
- * A call to the KINBand function links the main solver with the 
- * KINBAND linear solver. Its arguments are as follows:
- *
- * kinmem - pointer to the integrator memory returned by KINCreate.
- *
- * N      - problem size
- *
- * mupper - upper bandwidth of the band Jacobian
- *
- * mlower - lower bandwidth of the band Jacobian
- *
- * The return value of KINBand is one of:
- *    KINDLS_SUCCESS   if successful
- *    KINDLS_MEM_NULL  if the kinsol memory was NULL
- *    KINDLS_MEM_FAIL  if there was a memory allocation failure
- *    KINDLS_ILL_INPUT if a required vector operation is missing
- *                        or if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINBand(void *kinmem, long int N, long int mupper, long int mlower);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_bbdpre.h b/include/kinsol/kinsol_bbdpre.h
index 3df7cd3..01353e9 100644
--- a/include/kinsol/kinsol_bbdpre.h
+++ b/include/kinsol/kinsol_bbdpre.h
@@ -1,24 +1,26 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan Hindmarsh, Radu Serban, and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * Programmer(s): Alan Hindmarsh, Radu Serban, and Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for the KINBBDPRE module, for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with KINSol, KINSp*,
- * and the parallel implementaion of the NVECTOR module.
+ * matrix with banded blocks, for use with the KINSPILS interface,
+ * and the MPI-parallel implementaion of the NVECTOR module.
  *
  * Summary:
  *
@@ -44,16 +46,24 @@
  *   ...
  *   MPI_Init(&argc,&argv);
  *   ...
+ *   void *kin_mem;
+ *   ...
  *   tmpl = N_VNew_Parallel(...);
  *   ...
  *   kin_mem = KINCreate();
  *   flag = KINInit(kin_mem,...,tmpl);
  *   ...
- *   flag = KINSptfqmr(kin_mem,...);
- *         -or-
- *   flag = KINSpbcg(kin_mem,...);
- *         -or-
- *   flag = KINSpgmr(kin_mem,...);
+ *   SUNLinearSolver LS = SUNSPBCGS(tmpl, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPFGMR(tmpl, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPGMR(tmpl, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNSPTFQMR(tmpl, pretype, maxl);
+ *     -or-
+ *   SUNLinearSolver LS = SUNPCG(tmpl, pretype, maxl);
+ *   ...
+ *   ier = KINSpilsSetLinearSolver(cvode_mem, LS);
  *   ...
  *   flag = KINBBDPrecInit(kin_mem,...);
  *   ...
@@ -61,6 +71,8 @@
  *   ...
  *   KINFree(&kin_mem);
  *   ...
+ *   SUNLinSolFree(LS);
+ *   ...
  *   N_VDestroy_Parallel(tmpl);
  *   ...
  *   MPI_Finalize();
@@ -116,9 +128,9 @@ extern "C" {
 #define KINBBDPRE_FUNC_UNRECVR   -12
 /*
  * -----------------------------------------------------------------
- * Type : KINCommFn
+ * Type : KINBBDCommFn
  * -----------------------------------------------------------------
- * The user must supply a function of type KINCommFn which
+ * The user must supply a function of type KINBBDCommFn which
  * performs all inter-process communication necessary to
  * evaluate the approximate system function described above.
  *
@@ -126,33 +138,34 @@ extern "C" {
  * the solution vector u, and a pointer to the user-defined
  * data block user_data.
  *
- * The KINCommFn gcomm is expected to save communicated data in
+ * The KINBBDCommFn gcomm is expected to save communicated data in
  * space defined with the structure *user_data.
  *
- * Each call to the KINCommFn is preceded by a call to the system
+ * Each call to the KINBBDCommFn is preceded by a call to the system
  * function func at the current iterate uu. Thus functions of the
- * type KINCommFn can omit any communications done by f (func) if
- * relevant to the evaluation of the KINLocalFn function. If all
+ * type KINBBDCommFn can omit any communications done by f (func) if
+ * relevant to the evaluation of the KINBBDLocalFn function. If all
  * necessary communication was done in func, the user can pass
  * NULL for gcomm in the call to KINBBDPrecInit (see below).
  *
- * A KINCommFn function should return 0 if successful or
+ * A KINBBDCommFn function should return 0 if successful or
  * a non-zero value if an error occured.
  * -----------------------------------------------------------------
  */
 
-typedef int (*KINCommFn)(long int Nlocal, N_Vector u, void *user_data);
+typedef int (*KINBBDCommFn)(sunindextype Nlocal, N_Vector u,
+                         void *user_data);
 
 /*
  * -----------------------------------------------------------------
- * Type : KINLocalFn
+ * Type : KINBBDLocalFn
  * -----------------------------------------------------------------
  * The user must supply a function g(u) which approximates the
  * function f for the system f(u) = 0, and which is computed
  * locally (without inter-process communication). Note: The case
  * where g is mathematically identical to f is allowed.
  *
- * The implementation of this function must have type KINLocalFn
+ * The implementation of this function must have type KINBBDLocalFn
  * and take as input the local vector size Nlocal, the local
  * solution vector uu, the returned local g values vector, and a
  * pointer to the user-defined data block user_data. It is to
@@ -162,12 +175,12 @@ typedef int (*KINCommFn)(long int Nlocal, N_Vector u, void *user_data);
  * save communicated data in work space defined by the user and
  * made available to the preconditioner function for the problem.
  *
- * A KINLocalFn function should return 0 if successful or
+ * A KINBBDLocalFn function should return 0 if successful or
  * a non-zero value if an error occured.
  * -----------------------------------------------------------------
  */
 
-typedef int (*KINLocalFn)(long int Nlocal, N_Vector uu,
+typedef int (*KINBBDLocalFn)(sunindextype Nlocal, N_Vector uu,
                           N_Vector gval, void *user_data);
 
 /*
@@ -212,11 +225,13 @@ typedef int (*KINLocalFn)(long int Nlocal, N_Vector uu,
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT int KINBBDPrecInit(void *kinmem, long int Nlocal, 
-                                   long int mudq, long int mldq,
-                                   long int mukeep, long int mlkeep,
+SUNDIALS_EXPORT int KINBBDPrecInit(void *kinmem, sunindextype Nlocal, 
+                                   sunindextype mudq,
+                                   sunindextype mldq,
+                                   sunindextype mukeep,
+                                   sunindextype mlkeep,
                                    realtype dq_rel_uu, 
-                                   KINLocalFn gloc, KINCommFn gcomm);
+                                   KINBBDLocalFn gloc, KINBBDCommFn gcomm);
 
 /*
  * -----------------------------------------------------------------
@@ -228,8 +243,11 @@ SUNDIALS_EXPORT int KINBBDPrecInit(void *kinmem, long int Nlocal,
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT int KINBBDPrecGetWorkSpace(void *kinmem, long int *lenrwBBDP, long int *leniwBBDP);
-SUNDIALS_EXPORT int KINBBDPrecGetNumGfnEvals(void *kinmem, long int *ngevalsBBDP);
+SUNDIALS_EXPORT int KINBBDPrecGetWorkSpace(void *kinmem,
+                                           long int *lenrwBBDP,
+                                           long int *leniwBBDP);
+SUNDIALS_EXPORT int KINBBDPrecGetNumGfnEvals(void *kinmem,
+                                             long int *ngevalsBBDP);
 
 #ifdef __cplusplus
 }
diff --git a/include/kinsol/kinsol_dense.h b/include/kinsol/kinsol_dense.h
deleted file mode 100644
index c44196b..0000000
--- a/include/kinsol/kinsol_dense.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the KINSOL dense linear solver module, 
- * KINDENSE.
- * -----------------------------------------------------------------
- */
-
-#include <kinsol/kinsol_direct.h>
-#include <sundials/sundials_dense.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-#ifndef _KINDENSE_H
-#define _KINDENSE_H
-
-/*
- * -----------------------------------------------------------------
- * Function : KINDense
- * -----------------------------------------------------------------
- * A call to the KINDense function links the main solver with the
- * KINDENSE linear solver. Its arguments are as follows:
- *
- * kinmem - pointer to an internal memory block allocated during a
- *          prior call to KINCreate
- *
- * N      - problem size
- *
- * The return value of KINDense is one of:
- *    KINDLS_SUCCESS   if successful
- *    KINDLS_MEM_NULL  if the kinsol memory was NULL
- *    KINDLS_MEM_FAIL  if there was a memory allocation failure
- *    KINDLS_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINDense(void *kinmem, long int N);
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/include/kinsol/kinsol_direct.h b/include/kinsol/kinsol_direct.h
index 288ab8a..d813971 100644
--- a/include/kinsol/kinsol_direct.h
+++ b/include/kinsol/kinsol_direct.h
@@ -1,19 +1,21 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * Common header file for the direct linear solvers in KINSOL.
  * -----------------------------------------------------------------
@@ -23,6 +25,8 @@
 #define _KINDLS_H
 
 #include <sundials/sundials_direct.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_linearsolver.h>
 #include <sundials/sundials_nvector.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
@@ -49,8 +53,8 @@ extern "C" {
 
 /* Additional last_flag values */
 
-#define KINDLS_JACFUNC_UNRECVR  -5
-#define KINDLS_JACFUNC_RECVR    -6
+#define KINDLS_JACFUNC_ERR      -5
+#define KINDLS_SUNMAT_FAIL      -6
 
 /*
  * =================================================================
@@ -60,13 +64,11 @@ extern "C" {
 
 /*
  * -----------------------------------------------------------------
- * Type: KINDlsDenseJacFn
+ * Type: KINDlsJacFn
  * -----------------------------------------------------------------
  *
- * A dense Jacobian approximation function Jac must be of type 
- * KINDlsDenseJacFn. Its parameters are:
- *
- * N        - problem size.
+ * A Jacobian approximation function Jac must be of type KINDlsJacFn.
+ * Its parameters are:
  *
  * u        - current iterate (unscaled) [input]
  *
@@ -74,151 +76,70 @@ extern "C" {
  *            system function evaluated at current iterate:
  *            fu = F(u) [input]
  *
- * J        - dense matrix (of type DlsMat) that will be loaded
- *            by a KINDlsDenseJacFn with an approximation to the
- *            Jacobian matrix J = (dF_i/dy_j).
+ * J        - SUNMatrix that will be loaded by a KINDlsJacFn with
+ *            an approximation to the Jacobian matrix 
+ *            J = (dF_i/dy_j).
  *
- * user_data   - pointer to user data - the same as the user_data
- *            parameter passed to KINSetFdata.
+ * user_data  - pointer to user data - the same as the user_data
+ *              parameter passed to KINSetFdata.
  *
  * tmp1, tmp2 - available scratch vectors (volatile storage)
  *
- * A KINDlsDenseJacFn should return 0 if successful, a positive 
- * value if a recoverable error occurred, and a negative value if 
- * an unrecoverable error occurred.
+ * A KINDlsJacFn should return 0 if successful or a non-zero value
+ * otherwise.
  *
  * -----------------------------------------------------------------
  *
- * NOTE: The following are two efficient ways to load a dense Jac:         
- * (1) (with macros - no explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = DENSE_COL(Jac,j);                                 
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * (2) (without macros - explicit data structure references)      
- *     for (j=0; j < Neq; j++) {                                  
- *       col_j = (Jac->data)[j];                                   
- *       for (i=0; i < Neq; i++) {                                
- *         generate J_ij = the (i,j)th Jacobian element           
- *         col_j[i] = J_ij;                                       
- *       }                                                        
- *     }                                                          
- * A third way, using the DENSE_ELEM(A,i,j) macro, is much less   
- * efficient in general.  It is only appropriate for use in small 
- * problems in which efficiency of access is NOT a major concern. 
+ * NOTE: See the relevant SUNMatrix implementation header files and
+ *     documentation for mechanisms to inquire about matrix 
+ *     dimensions, and for efficient ways to set matrix entries.
  *                                                                
  * -----------------------------------------------------------------
  */
   
+typedef int (*KINDlsJacFn)(N_Vector u, N_Vector fu, SUNMatrix J,
+                           void *user_data, N_Vector tmp1,
+                           N_Vector tmp2);
   
-typedef int (*KINDlsDenseJacFn)(long int N,
-				N_Vector u, N_Vector fu, 
-				DlsMat J, void *user_data,
-				N_Vector tmp1, N_Vector tmp2);
-  
+
+/*
+ * =================================================================
+ *            E X P O R T E D    F U N C T I O N S 
+ * =================================================================
+ */
+
 /*
  * -----------------------------------------------------------------
- * Type: KINDlsBandJacFn
+ * Required inputs to the KINDLS linear solver interface
  * -----------------------------------------------------------------
  *
- * A band Jacobian approximation function Jac must have the
- * prototype given below. Its parameters are:
- *
- * N is the problem size
- *
- * mupper is the upper half-bandwidth of the approximate banded
- * Jacobian. This parameter is the same as the mupper parameter
- * passed by the user to the linear solver initialization function.
- *
- * mlower is the lower half-bandwidth of the approximate banded
- * Jacobian. This parameter is the same as the mlower parameter
- * passed by the user to the linear solver initialization function.
- *
- * u        - current iterate (unscaled) [input]
- *
- * fu       - vector (type N_Vector) containing result of nonlinear
- *            system function evaluated at current iterate:
- *            fu = F(uu) [input]
- *
- * J        - band matrix (of type DlsMat) that will be loaded by a
- *            KINDlsBandJacFn with an approximation to the Jacobian
- *            matrix Jac = (dF_i/dy_j).
- *
- * user_data   - pointer to user data - the same as the user_data
- *            parameter passed to KINSetFdata.
- *
- * tmp1, tmp2 - available scratch vectors (volatile storage)
- *
- * A KINDlsBandJacFn should return 0 if successful, a positive value
- * if a recoverable error occurred, and a negative value if an 
- * unrecoverable error occurred.
- *
- * -----------------------------------------------------------------
- *
- * NOTE. Three efficient ways to load J are:
- *
- * (1) (with macros - no explicit data structure references)
- *    for (j=0; j < n; j++) {
- *       col_j = BAND_COL(Jac,j);
- *       for (i=j-mupper; i <= j+mlower; i++) {
- *         generate J_ij = the (i,j)th Jacobian element
- *         BAND_COL_ELEM(col_j,i,j) = J_ij;
- *       }
- *     }
- *
- * (2) (with BAND_COL macro, but without BAND_COL_ELEM macro)
- *    for (j=0; j < n; j++) {
- *       col_j = BAND_COL(Jac,j);
- *       for (k=-mupper; k <= mlower; k++) {
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k
- *         col_j[k] = J_ij;
- *       }
- *     }
- *
- * (3) (without macros - explicit data structure references)
- *     offset = Jac->smu;
- *     for (j=0; j < n; j++) {
- *       col_j = ((Jac->data)[j])+offset;
- *       for (k=-mupper; k <= mlower; k++) {
- *         generate J_ij = the (i,j)th Jacobian element, i=j+k
- *         col_j[k] = J_ij;
- *       }
- *     }
- * Caution: Jac->smu is generally NOT the same as mupper.
- *
- * The BAND_ELEM(A,i,j) macro is appropriate for use in small
- * problems in which efficiency of access is NOT a major concern.
+ * KINDlsSetLinearSolver specifies the direct SUNLinearSolver object
+ * that should be used.  This is required if KINSOL is solving a 
+ * problem using the Newton or Picard nonlinear solvers with a 
+ * direct linear solver  (i.e. not the fixed point or accelerated 
+ * fixed-point solvers).
  *
+ * The return value is one of:
+ *    KINDLS_SUCCESS   if successful
+ *    KINDLS_MEM_NULL  if the KINSOL memory was NULL
+ *    KINDLS_ILL_INPUT if the arguments are incompatible
  * -----------------------------------------------------------------
  */
 
-typedef int (*KINDlsBandJacFn)(long int N, long int mupper, long int mlower,
-			       N_Vector u, N_Vector fu, 
-			       DlsMat J, void *user_data,
-			       N_Vector tmp1, N_Vector tmp2);
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
+SUNDIALS_EXPORT int KINDlsSetLinearSolver(void *kinmem, 
+                                          SUNLinearSolver LS,
+                                          SUNMatrix A);
 /*
  * -----------------------------------------------------------------
  * Optional inputs to the KINDLS linear solver
  * -----------------------------------------------------------------
  *
- * KINDlsSetDenseJacFn specifies the dense Jacobian approximation
- * routine to be used for a direct dense linear solver.
- *
- * KINDlsSetBandJacFn specifies the band Jacobian approximation
- * routine to be used for a direct band linear solver.
+ * KINDlsSetJacFn specifies the dense/band/sparse Jacobian 
+ * approximation routine to be used for a direct linear solver.
  *
- * By default, a difference quotient approximation, supplied with
- * the solver is used.
+ * By default, a difference quotient approximation is used for
+ * dense/band; no default exists for sparse (so this must 
+ * be user-supplied).
  *
  * The return value is one of:
  *    KINDLS_SUCCESS   if successful
@@ -227,8 +148,7 @@ typedef int (*KINDlsBandJacFn)(long int N, long int mupper, long int mlower,
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT int KINDlsSetDenseJacFn(void *kinmem, KINDlsDenseJacFn jac);
-SUNDIALS_EXPORT int KINDlsSetBandJacFn(void *kinmem, KINDlsBandJacFn jac);
+SUNDIALS_EXPORT int KINDlsSetJacFn(void *kinmem, KINDlsJacFn jac);
 
 /*
  * -----------------------------------------------------------------
@@ -245,7 +165,7 @@ SUNDIALS_EXPORT int KINDlsSetBandJacFn(void *kinmem, KINDlsBandJacFn jac);
  * KINDlsGetLastFlag     returns the last error flag set by any of
  *                       the KINDLS interface functions.
  * KINDlsGetReturnFlagName returns the name of the constant
- *                       associated with a KINDLS return flag
+ *                         associated with a KINDLS return flag
  *
  * The return value of KINDlsGet* is one of:
  *    KINDLS_SUCCESS   if successful
@@ -254,9 +174,9 @@ SUNDIALS_EXPORT int KINDlsSetBandJacFn(void *kinmem, KINDlsBandJacFn jac);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT int KINDlsGetWorkSpace(void *kinmem, long int *lenrwB, long int *leniwB);
-SUNDIALS_EXPORT int KINDlsGetNumJacEvals(void *kinmem, long int *njevalsB);
-SUNDIALS_EXPORT int KINDlsGetNumFuncEvals(void *kinmem, long int *nfevalsB);
+SUNDIALS_EXPORT int KINDlsGetWorkSpace(void *kinmem, long int *lenrw, long int *leniw);
+SUNDIALS_EXPORT int KINDlsGetNumJacEvals(void *kinmem, long int *njevals);
+SUNDIALS_EXPORT int KINDlsGetNumFuncEvals(void *kinmem, long int *nfevals);
 SUNDIALS_EXPORT int KINDlsGetLastFlag(void *kinmem, long int *flag);
 SUNDIALS_EXPORT char *KINDlsGetReturnFlagName(long int flag);
 
diff --git a/include/kinsol/kinsol_klu.h b/include/kinsol/kinsol_klu.h
deleted file mode 100644
index d023d34..0000000
--- a/include/kinsol/kinsol_klu.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the KINKLU linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINKLU_H
-#define _KINKLU_H
-
-#include "kinsol/kinsol_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : KINKLU
- * -----------------------------------------------------------------
- * A call to the KINKLU function links the main integrator      
- * with the KINKLU linear solver module.                        
- *                                                                
- * kin_mem is the pointer to integrator memory returned by        
- *     KINCreate.             
- *
- *                                                                
- * KINKLU returns:                                              
- *     KINSLU_SUCCESS   = 0  if successful                              
- *     KINSLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     KINSLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The KLU linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, KINKLU will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int KINKLU(void *kin_mem, int n, int nnz, int sparsetype); 
-
-/*
- * -----------------------------------------------------------------
- * Function : KINKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to KINKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is KINSLS_SUCCESS = 0, KINSLS_MEM_NULL = -1, 
- * KINSLS_LMEM_NULL = -2, KINSLS_ILL_INPUT = -3, or KINSLS_MEM_FAIL = -4.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int KINKLUReInit(void *kin_mem, int n, int nnz, 
-				   int reinit_type); 
-
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * KINKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in KINSOL is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int KINKLUSetOrdering(void *kin_mem, int ordering_choice); 
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_lapack.h b/include/kinsol/kinsol_lapack.h
deleted file mode 100644
index 03aa4af..0000000
--- a/include/kinsol/kinsol_lapack.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Header file for the KINSOL dense linear solver KINLAPACK.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINLAPACK_H
-#define _KINLAPACK_H
-
-#include <kinsol/kinsol_direct.h>
-#include <sundials/sundials_lapack.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Function : KINLapackDense
- * -----------------------------------------------------------------
- * A call to the KINLapackDense function links the main solver
- * with the KINLAPACK linear solver using dense Jacobians.
- *
- * kinmem is the pointer to the solver memory returned by KINCreate.
- *
- * N is the size of the ODE system.
- *
- * The return value of KINLapackDense is one of:
- *    KINDLS_SUCCESS   if successful
- *    KINDLS_MEM_NULL  if the KINSOL memory was NULL
- *    KINDLS_MEM_FAIL  if there was a memory allocation failure
- *    KINDLS_ILL_INPUT if a required vector operation is missing
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINLapackDense(void *kinmem, int N);
-
-/*
- * -----------------------------------------------------------------
- * Function : KINLapackBand
- * -----------------------------------------------------------------
- * A call to the KINLapackBand function links the main solver
- * with the KINLAPACK linear solver using banded Jacobians. 
- *
- * kinmem is the pointer to the solver memory returned by KINCreate.
- *
- * N is the size of the ODE system.
- *
- * mupper is the upper bandwidth of the band Jacobian approximation.
- *
- * mlower is the lower bandwidth of the band Jacobian approximation.
- *
- * The return value of KINLapackBand is one of:
- *    KINDLS_SUCCESS   if successful
- *    KINDLS_MEM_NULL  if the KINSOL memory was NULL
- *    KINDLS_MEM_FAIL  if there was a memory allocation failure
- *    KINDLS_ILL_INPUT if a required vector operation is missing
- *                        or if a bandwidth has an illegal value.
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINLapackBand(void *kinmem, int N, int mupper, int mlower);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_sparse.h b/include/kinsol/kinsol_sparse.h
deleted file mode 100644
index 92ca1a4..0000000
--- a/include/kinsol/kinsol_sparse.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4268 $
- * $Date: 2014-11-14 16:37:06 -0800 (Fri, 14 Nov 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the Sparse linear solver module in KINSOL.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINSOLSPARSE_H
-#define _KINSOLSPARSE_H
-
-#include "sundials/sundials_sparse.h"
-#include "sundials/sundials_nvector.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * K I N S O L S P A R S E    C O N S T A N T S
- * =================================================================
- */
-
-/* 
- * -----------------------------------------------------------------
- * KINSLS return values 
- * -----------------------------------------------------------------
- */
-
-#define KINSLS_SUCCESS           0
-#define KINSLS_MEM_NULL         -1
-#define KINSLS_LMEM_NULL        -2
-#define KINSLS_ILL_INPUT        -3
-#define KINSLS_MEM_FAIL         -4
-#define KINSLS_JAC_NOSET        -5
-#define KINSLS_PACKAGE_FAIL     -6
-
-/* Additional last_flag values */
-
-#define KINSLS_JACFUNC_UNRECVR  -7
-#define KINSLS_JACFUNC_RECVR    -8
-
-/*
- * -----------------------------------------------------------------
- * FUNCTION TYPES
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : KINSlsSparseJacFn
- * -----------------------------------------------------------------
- *
- * A sparse Jacobian approximation function jaceval must be of type 
- * KINSlsSparseJacFn.
- * Its parameters are:                     
- *                                                                
- * u   is the current value of the dependent variable vector     
- *                                                                
- * fval is the residual vector F(tt,yy,yp).                     
- *                                                                
- * JacMat is the compressed sparse column matrix (of type SlsMat)
- *     to be loaded by an KINSlsSparseJacFn routine with an approximation
- *     to the system Jacobian matrix
- *            J = dF/dy
- *     Note that JacMat is NOT preset to zero!
- *     Matrix data is for the nonzero entries of the Jacobian are stored in
- *     compressed column format.  Row indices of entries in 
- *     column j are stored in J->data[colptrs[j]] 
- *     through J->data[colptrs[j+i]-1]
- *     and corresponding numerical values of the Jacobian are stored 
- *     in the same entries of a.
- * 
- * user_data is a pointer to user Jacobian data 
- *                                                                
- * vtemp1 and vtemp2 are pointers to memory allocated for          
- *     N_Vectors which can be used by an KINSparseJacFn routine 
- *     as temporary storage or work space.                     
- *                                                                
- * A KINSlsSparseJacFn should return                                
- *     0 if successful,                      
- *     1 if successful but the user code indicates a new factorization
- *       of the Jacobian is required
- *     a positive int if a recoverable error occurred, or         
- *     a negative int if a nonrecoverable error occurred.         
- *
- * -----------------------------------------------------------------
- */
-  
-  
-typedef int (*KINSlsSparseJacFn)(N_Vector u, N_Vector fval, 
-		     SlsMat JacMat, void *user_data,
-		     N_Vector vtemp1, N_Vector vtemp2);
-
-/*
- * =================================================================
- *            E X P O R T E D    F U N C T I O N S 
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Optional inputs to the KINSPARSE linear solver
- * -----------------------------------------------------------------
- * KINSlsSetSparseJacFn specifies the Jacobian approximation
- * routine to be used for a sparse direct linear solver.
- *
- * The return value is one of:
- *    KINSLS_SUCCESS   if successful
- *    KINSLS_MEM_NULL  if the IDA memory was NULL
- *    KINSLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINSlsSetSparseJacFn(void *kin_mem_v, KINSlsSparseJacFn jac);
-
-/*
- * -----------------------------------------------------------------
- * Optional outputs from the KINSLS linear solver
- * -----------------------------------------------------------------
- *
- * KINSlsGetNumJacEvals returns the number of calls made to the
- *                      Jacobian evaluation routine jac.
- * KINSlsGetLastFlag    returns the last error flag set by any of
- *                      the KINSLS interface functions.
- *
- * The return value of KINSlsGet* is one of:
- *    KINSLS_SUCCESS   if successful
- *    KINSLS_MEM_NULL  if the KINSOL memory was NULL
- *    KINSLS_LMEM_NULL if the linear solver memory was NULL
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINSlsGetNumJacEvals(void *kin_mem, long int *njevals);
-SUNDIALS_EXPORT int KINSlsGetLastFlag(void *kin_mem, long int *flag);
-
-/*
- * -----------------------------------------------------------------
- * The following function returns the name of the constant 
- * associated with a IDASLS return flag
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT char *KINSlsGetReturnFlagName(long int flag);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_spbcgs.h b/include/kinsol/kinsol_spbcgs.h
deleted file mode 100644
index 07cd9ad..0000000
--- a/include/kinsol/kinsol_spbcgs.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the public header file for the KINSOL scaled preconditioned
- * Bi-CGSTAB linear solver module, KINSPBCG.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINSPBCG_H
-#define _KINSPBCG_H
-
-#include <kinsol/kinsol_spils.h>
-#include <sundials/sundials_spbcgs.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpbcg
- * -----------------------------------------------------------------
- * KINSpbcg links the main KINSOL solver module with the SPBCG
- * linear solver module. The routine establishes the inter-module
- * interface by setting the generic KINSOL pointers linit, lsetup,
- * lsolve, and lfree to KINSpbcgInit, KINSpbcgSetup, KINSpbcgSolve,
- * and KINSpbcgFree, respectively.
- *
- *  kinmem  pointer to an internal memory block allocated during a
- *          prior call to KINCreate
- *
- *  maxl  maximum allowable dimension of Krylov subspace (passing
- *        a value of 0 (zero) will cause the default value
- *        KINSPILS_MAXL (predefined constant) to be used)
- *
- * If successful, KINSpbcg returns KINSPILS_SUCCESS. If an error
- * occurs, then KINSpbcg returns an error code (negative integer
- * value).
- *
- * -----------------------------------------------------------------
- * KINSpbcg Return Values
- * -----------------------------------------------------------------
- * The possible return values for the KINSpbcg subroutine are the
- * following:
- *
- * KINSPILS_SUCCESS : means the KINSPBCG linear solver module
- *                    (implementation of the Bi-CGSTAB method) was
- *                    successfully initialized - allocated system
- *                    memory and set shared variables to default
- *                    values [0]
- *
- * KINSPILS_MEM_NULL : means a NULL KINSOL memory block pointer
- *                     was given (must call the KINCreate and
- *                     KINMalloc memory allocation subroutines
- *                     prior to calling KINSpbcg) [-1]
- *
- * KINSPILS_MEM_FAIL : means either insufficient system resources
- *                     were available to allocate memory for the
- *                     main KINSPBCG data structure (type
- *                     KINSpbcgMemRec), or the SpbcgMalloc subroutine
- *                     failed (unable to allocate enough system
- *                     memory for vector storate and/or the main
- *                     SPBCG data structure (type SpbcgMemRec)) [-4]
- *
- * KINSPILS_ILL_INPUT : means either a supplied parameter was invalid,
- *                      or the NVECTOR implementation is NOT
- *                      compatible [-3]
- *
- * The above constants are defined in kinsol_spils.h
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINSpbcg(void *kinmem, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_spfgmr.h b/include/kinsol/kinsol_spfgmr.h
deleted file mode 100644
index 4639a4d..0000000
--- a/include/kinsol/kinsol_spfgmr.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL, based on kinsol_spgmr.h
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the KINSOL Scaled Preconditioned GMRES     
- * linear solver module, KINSPFGMR.    
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINSPFGMR_H
-#define _KINSPFGMR_H
-
-#include <kinsol/kinsol_spils.h>
-#include <sundials/sundials_spfgmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpfgmr
- * -----------------------------------------------------------------
- * KINSpfgmr links the main KINSOL solver module with the SPFGMR
- * linear solver module. The routine establishes the inter-module
- * interface by setting the generic KINSOL pointers linit, lsetup,
- * lsolve, and lfree to KINSpfgmrInit, KINSpfgmrSetup, KINSpfgmrSolve,
- * and KINSpfgmrFree, respectively.
- *
- *  kinmem  pointer to an internal memory block allocated during a
- *          prior call to KINCreate
- *
- *  maxl  maximum allowable dimension of Krylov subspace (passing
- *        a value of 0 (zero) will cause the default value
- *        KINSPILS_MAXL (predefined constant) to be used)
- *
- * -----------------------------------------------------------------
- * KINSpfgmr Return Values
- * -----------------------------------------------------------------
- *
- * The possible return values for the KINSpfgmr subroutine are the
- * following:
- *
- * KINSPILS_SUCCESS : means the KINSPFGMR linear solver module
- *                    (implementation of the GMRES method) was
- *                    successfully initialized - allocated system
- *                    memory and set shared variables to default
- *                    values [0]
- *
- * KINSPILS_MEM_NULL : means a NULL KINSOL memory block pointer was
- *                     given (must call the KINCreate and KINMalloc
- *                     memory allocation subroutines prior to
- *                     calling KINSpfgmr) [-1]
- *
- * KINSPILS_MEM_FAIL : means either insufficient system resources
- *                     were available to allocate memory for the main
- *                     KINSPFGMR data structure (type KINSpfgmrMemRec),
- *                     or the SpfgmrMalloc subroutine failed (unable
- *                     to allocate enough system memory for vector
- *                     storage and/or the main SPFGMR data structure
- *                     (type SpfgmrMemRec)) [-4]
- *
- * KINSPILS_ILL_INPUT : means a supplied parameter was invalid
- *                      (check error message) [-3]
- *
- * The above constants are defined in kinsol_spils.h
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINSpfgmr(void *kinmem, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_spgmr.h b/include/kinsol/kinsol_spgmr.h
deleted file mode 100644
index a6faf68..0000000
--- a/include/kinsol/kinsol_spgmr.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
- *                Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the KINSOL Scaled Preconditioned GMRES     
- * linear solver module, KINSPGMR.    
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINSPGMR_H
-#define _KINSPGMR_H
-
-#include <kinsol/kinsol_spils.h>
-#include <sundials/sundials_spgmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpgmr
- * -----------------------------------------------------------------
- * KINSpgmr links the main KINSOL solver module with the SPGMR
- * linear solver module. The routine establishes the inter-module
- * interface by setting the generic KINSOL pointers linit, lsetup,
- * lsolve, and lfree to KINSpgmrInit, KINSpgmrSetup, KINSpgmrSolve,
- * and KINSpgmrFree, respectively.
- *
- *  kinmem  pointer to an internal memory block allocated during a
- *          prior call to KINCreate
- *
- *  maxl  maximum allowable dimension of Krylov subspace (passing
- *        a value of 0 (zero) will cause the default value
- *        KINSPILS_MAXL (predefined constant) to be used)
- *
- * -----------------------------------------------------------------
- * KINSpgmr Return Values
- * -----------------------------------------------------------------
- *
- * The possible return values for the KINSpgmr subroutine are the
- * following:
- *
- * KINSPILS_SUCCESS : means the KINSPGMR linear solver module
- *                    (implementation of the GMRES method) was
- *                    successfully initialized - allocated system
- *                    memory and set shared variables to default
- *                    values [0]
- *
- * KINSPILS_MEM_NULL : means a NULL KINSOL memory block pointer was
- *                     given (must call the KINCreate and KINMalloc
- *                     memory allocation subroutines prior to
- *                     calling KINSpgmr) [-1]
- *
- * KINSPILS_MEM_FAIL : means either insufficient system resources
- *                     were available to allocate memory for the main
- *                     KINSPGMR data structure (type KINSpgmrMemRec),
- *                     or the SpgmrMalloc subroutine failed (unable
- *                     to allocate enough system memory for vector
- *                     storage and/or the main SPGMR data structure
- *                     (type SpgmrMemRec)) [-4]
- *
- * KINSPILS_ILL_INPUT : means a supplied parameter was invalid
- *                      (check error message) [-3]
- *
- * The above constants are defined in kinsol_spils.h
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINSpgmr(void *kinmem, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_spils.h b/include/kinsol/kinsol_spils.h
index 2597f48..bc60dd8 100644
--- a/include/kinsol/kinsol_spils.h
+++ b/include/kinsol/kinsol_spils.h
@@ -1,20 +1,22 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Scott Cohen, Alan Hindmarsh, Radu Serban, 
+ *                  and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the common header file for the Scaled Preconditioned
  * Iterative Linear Solvers in KINSOL.
@@ -26,293 +28,286 @@
 
 #include <sundials/sundials_iterative.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_linearsolver.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * KINSPILS return values
- * -----------------------------------------------------------------
- */
-
-#define KINSPILS_SUCCESS    0
+/*------------------------------------------------------------------
+  KINSPILS return values
+  ------------------------------------------------------------------*/
 
-#define KINSPILS_MEM_NULL  -1
-#define KINSPILS_LMEM_NULL -2
-#define KINSPILS_ILL_INPUT -3
-#define KINSPILS_MEM_FAIL  -4
-#define KINSPILS_PMEM_NULL -5
+#define KINSPILS_SUCCESS     0
 
-/*
- * -----------------------------------------------------------------
- * KINSPILS solver constant
- * -----------------------------------------------------------------
- * KINSPILS_MAXL : default maximum dimension of Krylov subspace
- * -----------------------------------------------------------------
- */
+#define KINSPILS_MEM_NULL   -1
+#define KINSPILS_LMEM_NULL  -2
+#define KINSPILS_ILL_INPUT  -3
+#define KINSPILS_MEM_FAIL   -4
+#define KINSPILS_PMEM_NULL  -5
+#define KINSPILS_SUNLS_FAIL -6
 
-#define KINSPILS_MAXL 10
+/*------------------------------------------------------------------
+  Type : KINSpilsPrecSetupFn
 
-/*
- * -----------------------------------------------------------------
- * Type : KINSpilsPrecSetupFn
- * -----------------------------------------------------------------
- * The user-supplied preconditioner setup subroutine should
- * compute the right-preconditioner matrix P (stored in memory
- * block referenced by P_data pointer) used to form the
- * scaled preconditioned linear system:
- *
- *  (Df*J(uu)*(P^-1)*(Du^-1)) * (Du*P*x) = Df*(-F(uu))
- *
- * where Du and Df denote the diagonal scaling matrices whose
- * diagonal elements are stored in the vectors uscale and
- * fscale, repsectively.
- *
- * The preconditioner setup routine (referenced by iterative linear
- * solver modules via pset (type KINSpilsPrecSetupFn)) will not be
- * called prior to every call made to the psolve function, but will
- * instead be called only as often as necessary to achieve convergence
- * of the Newton iteration.
- *
- * Note: If the psolve routine requires no preparation, then a
- * preconditioner setup function need not be given.
- *
- *  uu  current iterate (unscaled) [input]
- *
- *  uscale  vector (type N_Vector) containing diagonal elements
- *          of scaling matrix for vector uu [input]
- *
- *  fval  vector (type N_Vector) containing result of nonliear
- *        system function evaluated at current iterate:
- *        fval = F(uu) [input]
- *
- *  fscale  vector (type N_Vector) containing diagonal elements
- *          of scaling matrix for fval [input]
- *
- *  user_data  pointer to user-allocated data memory block
- *
- *  vtemp1/vtemp2  available scratch vectors (temporary storage)
- *
- * If successful, the function should return 0 (zero). If an error
- * occurs, then the routine should return a non-zero integer value.
- * -----------------------------------------------------------------
- */
+  The user-supplied preconditioner setup subroutine should compute
+  the right-preconditioner matrix P (stored in memory block
+  referenced by pdata pointer) used to form the scaled
+  preconditioned linear system:
+  
+    (Df*J(uu)*(P^-1)*(Du^-1)) * (Du*P*x) = Df*(-F(uu))
+  
+  where Du and Df denote the diagonal scaling matrices whose
+  diagonal elements are stored in the vectors uscale and fscale,
+  repsectively.
+ 
+  The preconditioner setup routine (referenced by iterative linear
+  solver modules via pset (type KINSpilsPrecSetupFn)) will not be
+  called prior to every call made to the psolve function, but will
+  instead be called only as often as necessary to achieve
+  convergence of the Newton iteration.
+ 
+  Note: If the psolve routine requires no preparation, then a
+  preconditioner setup function need not be given.
+ 
+    uu  current iterate (unscaled) [input]
+ 
+    uscale  vector (type N_Vector) containing diagonal elements
+            of scaling matrix for vector uu [input]
+ 
+    fval  vector (type N_Vector) containing result of nonliear
+          system function evaluated at current iterate:
+          fval = F(uu) [input]
+ 
+    fscale  vector (type N_Vector) containing diagonal elements
+            of scaling matrix for fval [input]
+ 
+    user_data  pointer to user-allocated data memory block
+ 
+  If successful, the function should return 0 (zero). If an error
+  occurs, then the routine should return a non-zero integer value.
+  -----------------------------------------------------------------*/
 
 typedef int (*KINSpilsPrecSetupFn)(N_Vector uu, N_Vector uscale,
                                    N_Vector fval, N_Vector fscale,
-                                   void *user_data, N_Vector vtemp1,
-				   N_Vector vtemp2);
+                                   void *user_data);
 
-/*
- * -----------------------------------------------------------------
- * Type : KINSpilsPrecSolveFn
- * -----------------------------------------------------------------
- * The user-supplied preconditioner solve subroutine (referenced
- * by iterative linear solver modules via psolve (type
- * KINSpilsPrecSolveFn)) should solve a (scaled) preconditioned
- * linear system of the generic form P*z = r, where P denotes the
- * right-preconditioner matrix computed by the pset routine.
- *
- *  uu  current iterate (unscaled) [input]
- *
- *  uscale  vector (type N_Vector) containing diagonal elements
- *          of scaling matrix for vector uu [input]
- *
- *  fval  vector (type N_Vector) containing result of nonliear
- *        system function evaluated at current iterate:
- *        fval = F(uu) [input]
- *
- *  fscale  vector (type N_Vector) containing diagonal elements
- *          of scaling matrix for fval [input]
- *
- *  vv  vector initially set to the right-hand side vector r, but
- *      which upon return contains a solution of the linear system
- *      P*z = r [input/output]
- *
- *  user_data  pointer to user-allocated data memory block
- *
- *  vtemp  available scratch vector (volatile storage)
- *
- * If successful, the function should return 0 (zero). If a
- * recoverable error occurs, then the subroutine should return
- * a positive integer value (in this case, KINSOL attempts to
- * correct by calling the preconditioner setup function if the 
- * preconditioner information is out of date). If an unrecoverable 
- * error occurs, then the preconditioner solve function should return 
- * a negative integer value.
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Type : KINSpilsPrecSolveFn
+
+  The user-supplied preconditioner solve subroutine (referenced
+  by iterative linear solver modules via psolve (type
+  KINSpilsPrecSolveFn)) should solve a (scaled) preconditioned
+  linear system of the generic form P*z = r, where P denotes the
+  right-preconditioner matrix computed by the pset routine.
+  
+   uu  current iterate (unscaled) [input]
+ 
+   uscale  vector (type N_Vector) containing diagonal elements
+           of scaling matrix for vector uu [input]
+ 
+   fval  vector (type N_Vector) containing result of nonliear
+         system function evaluated at current iterate:
+         fval = F(uu) [input]
+ 
+   fscale  vector (type N_Vector) containing diagonal elements
+           of scaling matrix for fval [input]
+ 
+   vv  vector initially set to the right-hand side vector r, but
+       which upon return contains a solution of the linear system
+       P*z = r [input/output]
+ 
+   user_data  pointer to user-allocated data memory block
+ 
+  If successful, the function should return 0 (zero). If a
+  recoverable error occurs, then the subroutine should return
+  a positive integer value (in this case, KINSOL attempts to
+  correct by calling the preconditioner setup function if the 
+  preconditioner information is out of date). If an unrecoverable 
+  error occurs, then the preconditioner solve function should return 
+  a negative integer value.
+  ------------------------------------------------------------------*/
 
 typedef int (*KINSpilsPrecSolveFn)(N_Vector uu, N_Vector uscale, 
                                    N_Vector fval, N_Vector fscale, 
-                                   N_Vector vv, void *user_data,
-                                   N_Vector vtemp);
-
-/*
- * -----------------------------------------------------------------
- * Type : KINSpilsJacTimesVecFn
- * -----------------------------------------------------------------
- * The (optional) user-supplied matrix-vector product subroutine
- * (referenced internally via jtimes (type KINSpilsJacTimesVecFn))
- * is used to compute Jv = J(uu)*v (system Jacobian applied to a
- * given vector). If a user-defined routine is not given, then the
- * private routine is used.
- *
- *  v  unscaled variant of vector to be multiplied by J(uu) [input]
- *
- *  Jv  vector containing result of matrix-vector product J(uu)*v
- *      [output]
- *
- *  uu  current iterate (unscaled) [input]
- *
- *  new_uu  flag (reset by user) indicating if the iterate uu
- *          has been updated in the interim - Jacobian needs
- *          to be updated/reevaluated, if appropriate, unless
- *          new_uu = FALSE [input/output]
- *
- *  user_data  pointer to user data, the same as the user_data
- *          parameter passed to the KINSetUserData function.
- *
- * If successful, the function should return 0 (zero). If an error
- * occurs, then the routine should return a non-zero integer value.
- * -----------------------------------------------------------------
- */
+                                   N_Vector vv, void *user_data);
 
+/*------------------------------------------------------------------
+  Type : KINSpilsJacTimesVecFn
+  
+  The (optional) user-supplied matrix-vector product subroutine
+  (referenced internally via jtimes (type KINSpilsJacTimesVecFn))
+  is used to compute Jv = J(uu)*v (system Jacobian applied to a
+  given vector). If a user-defined routine is not given, then the
+  private routine is used.
+ 
+   v  unscaled variant of vector to be multiplied by J(uu) [input]
+ 
+   Jv  vector containing result of matrix-vector product J(uu)*v
+       [output]
+ 
+   uu  current iterate (unscaled) [input]
+ 
+   new_uu  flag (reset by user) indicating if the iterate uu
+           has been updated in the interim - Jacobian needs
+           to be updated/reevaluated, if appropriate, unless
+           new_uu = SUNFALSE [input/output]
+ 
+   user_data  pointer to user data, the same as the user_data
+              parameter passed to the KINSetUserData function.
+ 
+  If successful, the function should return 0 (zero). If an error
+  occurs, then the routine should return a non-zero integer value.
+  ------------------------------------------------------------------*/
+  
 typedef int (*KINSpilsJacTimesVecFn)(N_Vector v, N_Vector Jv,
                                      N_Vector uu, booleantype *new_uu, 
                                      void *J_data);
 
 
+/*==================================================================
+  KINSPILS Exported functions
+  ==================================================================*/
 
+/*------------------------------------------------------------------
+  Required inputs to the KINSPILS linear solver interface
+ 
+  KINSpilsSetLinearSolver specifies the iterative SUNLinearSolver 
+  object that KINSOL should use.  This is required if KINSOL is 
+  solving a problem with the Newton or Picard nonlinear solvers 
+  with an iterative linear solver (i.e. not the fixed-point or
+  accelerated fixed-point solvers).
+ 
+  The return value is one of:
+     KINSPILS_SUCCESS   if successful
+     KINSPILS_MEM_NULL  if the KINSOL memory was NULL
+     KINSPILS_ILL_INPUT if the linear solver memory was NULL
+  ------------------------------------------------------------------*/
 
+SUNDIALS_EXPORT int KINSpilsSetLinearSolver(void *kinmem, 
+                                            SUNLinearSolver LS);
 
-/*
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- * The following functions can be called to set optional inputs:
- *
- *       Function Name       |   Optional Input  [Default Value]
- *                           |
- * -----------------------------------------------------------------
- *                           |
- * KINSpilsSetMaxRestarts    | maximum number of times the SPGMR
- *                           | (scaled preconditioned GMRES) linear
- *                           | solver can be restarted
- *                           | [0]
- *                           |
- * KINSpilsSetPreconditioner | used to set the following:
- *                           |   (a) name of user-supplied routine
- *                           |       used to compute a preconditioner
- *                           |       matrix for the given linear
- *                           |       system (pset)
- *                           |       [NULL]
- *                           |   (b) name of user-supplied routine
- *                           |       used to apply preconditioner to
- *                           |       linear system (psolve)
- *                           |       [NULL]
- *                           |
- * KINSpilsSetJacTimesVecFn  | used to set the following the name
- *                           | of user-supplied subroutine used to 
- *                           | compute the matrix-vector product J(u)*v,
- *                           | where J denotes the system Jacobian.
- *                           | [KINSpilsDQJtimes]
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Optional Input Specification Functions
+
+  The following functions can be called to set optional inputs:
+ 
+	Function Name	    |	Optional Input	[Default Value]
+			    |
+  ------------------------------------------------------------------
+  KINSpilsSetPreconditioner | used to set the following:
+			    |	(a) name of user-supplied routine
+			    |	    used to compute a preconditioner
+			    |	    matrix for the given linear
+			    |	    system (pset)
+			    |	    [NULL]
+			    |	(b) name of user-supplied routine
+			    |	    used to apply preconditioner to
+			    |	    linear system (psolve)
+			    |	    [NULL]
+			    |
+  KINSpilsSetJacTimesVecFn  | used to set the name of the
+			    | user-supplied subroutine for computing
+			    | the matrix-vector product J(u)*v,
+			    | where J denotes the system Jacobian.
+			    | [KINSpilsDQJtimes]
+  ------------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int KINSpilsSetMaxRestarts(void *kinmem, int maxrs);
 SUNDIALS_EXPORT int KINSpilsSetPreconditioner(void *kinmem,
-					      KINSpilsPrecSetupFn pset,
+					      KINSpilsPrecSetupFn psetup,
 					      KINSpilsPrecSolveFn psolve);
 SUNDIALS_EXPORT int KINSpilsSetJacTimesVecFn(void *kinmem,
                                              KINSpilsJacTimesVecFn jtv);
 
-/*
- * -----------------------------------------------------------------
- * KINSpilsSet* Return Values
- * -----------------------------------------------------------------
- * The possible return values for the KINSpilsSet* subroutines
- * are the following:
- *
- * KINSPILS_SUCCESS : means the associated parameter was successfully
- *                    set [0]
- *
- * KINSPILS_ILL_INPUT : means the supplied parameter was invalid
- *                      (check error message) [-3]
- *
- * KINSPILS_MEM_NULL : means a NULL KINSOL memory block pointer
- *                     was given [-1]
- *
- * KINSPILS_LMEM_NULL : means system memory has not yet been
- *                      allocated for the linear solver 
- *                      (lmem == NULL) [-2]
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  KINSpilsSet* Return Values
 
-/*
- * -----------------------------------------------------------------
- * Optional Output Extraction Functions
- * -----------------------------------------------------------------
- * The following functions can be called to get optional outputs
- * and statistical information related to the KINSPILS linear
- * solvers:
- *
- *        Function Name       |      Returned Value
- *                            |
- * -----------------------------------------------------------------
- *                            |
- * KINSpilsGetWorkSpace       | returns both integer workspace size
- *                            | (total number of long int-sized blocks
- *                            | of memory allocated  for
- *                            | vector storage), and real workspace
- *                            | size (total number of realtype-sized
- *                            | blocks of memory allocated
- *                            | for vector storage)
- *                            |
- * KINSpilsGetNumPrecEvals    | total number of preconditioner
- *                            | evaluations (number of calls made
- *                            | to the user-defined pset routine)
- *                            |
- * KINSpilsGetNumPrecSolves   | total number of times preconditioner
- *                            | was applied to linear system (number
- *                            | of calls made to the user-supplied
- *                            | psolve function)
- *                            |
- * KINSpilsGetNumLinIters     | total number of linear iterations
- *                            | performed
- *                            |
- * KINSpilsGetNumConvFails    | total number of linear convergence
- *                            | failures
- *                            |
- * KINSpilsGetNumJtimesEvals  | total number of times the matrix-
- *                            | vector product J(u)*v was computed
- *                            | (number of calls made to the jtimes
- *                            | subroutine)
- *                            |
- * KINSpilsGetNumFuncEvals    | total number of evaluations of the
- *                            | system function F(u) (number of
- *                            | calls made to the user-supplied
- *                            | func routine by the linear solver
- *                            | module member subroutines)
- *                            |
- * KINSpilsGetLastFlag        | returns the last flag returned by
- *                            | the linear solver
- *                            |
- * KINSpilsGetReturnFlagName  | returns the name of the constant
- *                            | associated with a KINSPILS return flag
- * -----------------------------------------------------------------
- */
+  The possible return values for the KINSpilsSet* subroutines
+  are the following:
+ 
+  KINSPILS_SUCCESS : means the associated parameter was successfully
+		     set [0]
+ 
+  KINSPILS_ILL_INPUT : means the supplied parameter was invalid
+		       (check error message) [-3]
+ 
+  KINSPILS_MEM_NULL : means a NULL KINSOL memory block pointer
+		      was given [-1]
+ 
+  KINSPILS_LMEM_NULL : means system memory has not yet been
+		       allocated for the linear solver 
+		       (lmem == NULL) [-2]
+  ------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------
+  Optional Output Extraction Functions
+
+  The following functions can be called to get optional outputs
+  and statistical information related to the KINSPILS linear
+  solvers:
+ 
+	 Function Name	     |	    Returned Value
+			     |
+  ------------------------------------------------------------------
+			     |
+  KINSpilsGetWorkSpace	     | returns both integer workspace size
+			     | (total number of long int-sized blocks
+			     | of memory allocated for
+			     | vector storage), and real workspace
+			     | size (total number of realtype-sized
+			     | blocks of memory allocated
+			     | for vector storage)
+			     |
+  KINSpilsGetNumPrecEvals    | total number of preconditioner
+			     | evaluations (number of calls made
+			     | to the user-defined pset routine)
+			     |
+  KINSpilsGetNumPrecSolves   | total number of times preconditioner
+			     | was applied to linear system (number
+			     | of calls made to the user-supplied
+			     | psolve function)
+			     |
+  KINSpilsGetNumLinIters     | total number of linear iterations
+			     | performed
+			     |
+  KINSpilsGetNumConvFails    | total number of linear convergence
+			     | failures
+			     |
+  KINSpilsGetNumJtimesEvals  | total number of times the matrix-
+			     | vector product J(u)*v was computed
+			     | (number of calls made to the jtimes
+			     | subroutine)
+			     |
+  KINSpilsGetNumFuncEvals    | total number of evaluations of the
+			     | system function F(u) (number of
+			     | calls made to the user-supplied
+			     | func routine by the linear solver
+			     | module member subroutines)
+			     |
+  KINSpilsGetLastFlag	     | returns the last flag returned by
+			     | the linear solver
+			     |
+  KINSpilsGetReturnFlagName  | returns the name of the constant
+			     | associated with a KINSPILS return flag
+  ------------------------------------------------------------------*/
 
-SUNDIALS_EXPORT int KINSpilsGetWorkSpace(void *kinmem, long int *lenrwSG, long int *leniwSG);
-SUNDIALS_EXPORT int KINSpilsGetNumPrecEvals(void *kinmem, long int *npevals);
-SUNDIALS_EXPORT int KINSpilsGetNumPrecSolves(void *kinmem, long int *npsolves);
-SUNDIALS_EXPORT int KINSpilsGetNumLinIters(void *kinmem, long int *nliters);
-SUNDIALS_EXPORT int KINSpilsGetNumConvFails(void *kinmem, long int *nlcfails);
-SUNDIALS_EXPORT int KINSpilsGetNumJtimesEvals(void *kinmem, long int *njvevals);
-SUNDIALS_EXPORT int KINSpilsGetNumFuncEvals(void *kinmem, long int *nfevalsS); 
-SUNDIALS_EXPORT int KINSpilsGetLastFlag(void *kinmem, long int *flag);
+SUNDIALS_EXPORT int KINSpilsGetWorkSpace(void *kinmem,
+                                         long int *lenrwLS,
+                                         long int *leniwLS);
+SUNDIALS_EXPORT int KINSpilsGetNumPrecEvals(void *kinmem,
+                                            long int *npevals);
+SUNDIALS_EXPORT int KINSpilsGetNumPrecSolves(void *kinmem,
+                                             long int *npsolves);
+SUNDIALS_EXPORT int KINSpilsGetNumLinIters(void *kinmem,
+                                           long int *nliters);
+SUNDIALS_EXPORT int KINSpilsGetNumConvFails(void *kinmem,
+                                            long int *nlcfails);
+SUNDIALS_EXPORT int KINSpilsGetNumJtimesEvals(void *kinmem,
+                                              long int *njvevals);
+SUNDIALS_EXPORT int KINSpilsGetNumFuncEvals(void *kinmem,
+                                            long int *nfevals); 
+SUNDIALS_EXPORT int KINSpilsGetLastFlag(void *kinmem,
+                                        long int *flag);
 SUNDIALS_EXPORT char *KINSpilsGetReturnFlagName(long int flag);
 
 
diff --git a/include/kinsol/kinsol_sptfqmr.h b/include/kinsol/kinsol_sptfqmr.h
deleted file mode 100644
index cda1d89..0000000
--- a/include/kinsol/kinsol_sptfqmr.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the public header file for the KINSOL scaled preconditioned
- * TFQMR linear solver module, KINSPTFQMR.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINSPTFQMR_H
-#define _KINSPTFQMR_H
-
-#include <kinsol/kinsol_spils.h>
-#include <sundials/sundials_sptfqmr.h>
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSptfqmr
- * -----------------------------------------------------------------
- * KINSptfqmr links the main KINSOL solver module with the SPTFQMR
- * linear solver module. The routine establishes the inter-module
- * interface by setting the generic KINSOL pointers linit, lsetup,
- * lsolve, and lfree to KINSptfqmrInit, KINSptfqmrSetup, KINSptfqmrSolve,
- * and KINSptfqmrFree, respectively.
- *
- *  kinmem  pointer to an internal memory block allocated during a
- *          prior call to KINCreate
- *
- *  maxl  maximum allowable dimension of Krylov subspace (passing
- *        a value of 0 (zero) will cause the default value
- *        KINSPTFQMR_MAXL (predefined constant) to be used)
- *
- * If successful, KINSptfqmr returns KINSPTFQMR_SUCCESS. If an error
- * occurs, then KINSptfqmr returns an error code (negative integer
- * value).
- *
- * -----------------------------------------------------------------
- * KINSptfqmr Return Values
- * -----------------------------------------------------------------
- * The possible return values for the KINSptfqmr subroutine are the
- * following:
- *
- * KINSPTFQMR_SUCCESS : means the KINSPTFQMR linear solver module
- *                      (implementation of the TFQMR method) was
- *                      successfully initialized - allocated system
- *                      memory and set shared variables to default
- *                      values [0]
- *
- * KINSPTFQMR_MEM_NULL : means a NULL KINSOL memory block pointer
- *                       was given (must call the KINCreate and
- *                       KINMalloc memory allocation subroutines
- *                       prior to calling KINSptfqmr) [-1]
- *
- * KINSPTFQMR_MEM_FAIL : means either insufficient system resources
- *                       were available to allocate memory for the
- *                       main KINSPTFQMR data structure (type
- *                       KINSptfqmrMemRec), or the SptfqmrMalloc
- *                       subroutine failed (unable to allocate enough
- *                       system memory for vector storate and/or the
- *                       main SPTFQMR data structure
- *                       (type SptfqmrMemRec)) [-4]
- *
- * KINSPTFQMR_ILL_INPUT : means either a supplied parameter was invalid,
- *                        or the NVECTOR implementation is NOT
- *                        compatible [-3]
- *
- * The above constants are defined in kinsol_spils.h
- * -----------------------------------------------------------------
- */
-
-SUNDIALS_EXPORT int KINSptfqmr(void *kinmem, int maxl);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/kinsol/kinsol_superlumt.h b/include/kinsol/kinsol_superlumt.h
deleted file mode 100644
index 89cb8e9..0000000
--- a/include/kinsol/kinsol_superlumt.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4181 $
- * $Date: 2014-07-23 12:43:06 -0700 (Wed, 23 Jul 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the header file for the KINSuperLUMT linear solver module.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINSUPERLUMT_H
-#define _KINSUPERLUMT_H
-
-#include "kinsol/kinsol_sparse.h"
-#include "sundials/sundials_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSuperLUMT
- * -----------------------------------------------------------------
- * A call to the KINSuperLUMT function links the main integrator      
- * with the KINSuperLUMT linear solver module.                        
- *                                                                
- * kin_mem is the pointer to integrator memory returned by        
- *     KINCreate.       
- *
- * num_threads is the number of threads that SuperLUMT should invoke         
- *
- *                                                                
- * KINSuperLUMT returns:                                              
- *     KINSLU_SUCCESS   = 0  if successful                              
- *     KINSLU_LMEM_FAIL = -1 if there was a memory allocation failure   
- *     KINSLU_ILL_INPUT = -2 if NVECTOR found incompatible           
- *                                                                
- * NOTE: The SuperLUMT linear solver assumes a serial implementation  
- *       of the NVECTOR package. Therefore, KINSuperLUMT will first
- *       test for a compatible N_Vector internal representation
- *       by checking that the functions N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int KINSuperLUMT(void *kin_mem, int num_threads,
-				   int n, int nnz); 
-
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * KINSuperLUMTSetOrdering sets the ordering used by SuperLUMT for 
- * reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-  SUNDIALS_EXPORT int KINSuperLUMTSetOrdering(void *kin_mem, 
-					      int ordering_choice); 
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/nvector/cuda/ThreadPartitioning.hpp b/include/nvector/cuda/ThreadPartitioning.hpp
new file mode 100644
index 0000000..ad0b1f6
--- /dev/null
+++ b/include/nvector/cuda/ThreadPartitioning.hpp
@@ -0,0 +1,178 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ */
+
+
+
+#ifndef _THREAD_PARTITIONING_HPP_
+#define _THREAD_PARTITIONING_HPP_
+
+#include <iostream>
+#include <cuda_runtime.h>
+
+namespace suncudavec
+{
+
+template<class T, class I>
+class StreamPartitioning
+{
+public:
+  StreamPartitioning(I N, unsigned block)
+: block_(block),
+  grid_((N + block - 1) / block)
+{
+}
+
+  explicit StreamPartitioning(StreamPartitioning<T, I>& p)
+  : block_(p.block_),
+    grid_(p.grid_)
+  {
+  }
+
+  unsigned grid() const
+  {
+    return grid_;
+  }
+
+  unsigned block() const
+  {
+    return block_;
+  }
+
+private:
+  unsigned block_;
+  unsigned grid_;
+};
+
+
+template<class T, class I=int>
+class ReducePartitioning
+{
+public:
+  ReducePartitioning(I N, unsigned block)
+: block_(block),
+  grid_((N + (block_ * 2 - 1)) / (block_ * 2)),
+  shMemSize_(block_*sizeof(T))
+{
+    allocateBuffer();
+}
+
+  explicit ReducePartitioning(StreamPartitioning<T, I>& p)
+  : block_(p.block_),
+    grid_(p.grid_),
+    shMemSize_(p.shMemSize_)
+  {
+    allocateBuffer();
+  }
+
+  ~ReducePartitioning()
+  {
+    cudaError_t err;
+    if (bufferSize_ > 0)
+      free(h_buffer_);
+    if (bufferSize_ > 0)
+    {
+      err = cudaFree(d_buffer_);
+      if(err != cudaSuccess)
+        std::cerr << "Failed to free device vector (error code " << err << ")!\n";
+    }
+  }
+
+  int setPartitioning(I N, unsigned& grid, unsigned& block, unsigned& shMemSize)
+  {
+    block = block_;
+    grid  = (N + (block * 2 - 1)) / (block * 2);
+    shMemSize = block * sizeof(T);
+
+    return 0;
+  }
+
+  unsigned grid() const
+  {
+    return grid_;
+  }
+
+  unsigned block() const
+  {
+    return block_;
+  }
+
+  unsigned shmem() const
+  {
+    return shMemSize_;
+  }
+
+  unsigned int buffSize()
+  {
+    return bufferSize_;
+  }
+
+  T* devBuffer()
+  {
+    return d_buffer_;
+  }
+
+  const T* devBuffer() const
+  {
+    return d_buffer_;
+  }
+
+  T* hostBuffer()
+  {
+    return h_buffer_;
+  }
+
+  const T* hostBuffer() const
+  {
+    return h_buffer_;
+  }
+
+  void copyFromDevBuffer(unsigned int n) const
+  {
+    cudaError_t err = cudaMemcpy(h_buffer_, d_buffer_, n*sizeof(T), cudaMemcpyDeviceToHost);
+    if(err != cudaSuccess)
+      std::cerr << "Failed to copy vector from device to host (error code " << err << ")!\n";
+  }
+
+private:
+  int allocateBuffer()
+  {
+    bufferSize_ = grid_ * sizeof(T);
+    h_buffer_ = static_cast<T*>(malloc(bufferSize_));
+    if(h_buffer_ == NULL)
+      std::cerr << "Failed to allocate host vector!\n";
+
+    cudaError_t err;
+    err = cudaMalloc((void**) &d_buffer_, bufferSize_);
+    if(err != cudaSuccess)
+      std::cerr << "Failed to allocate device vector (error code " << err << ")!\n";
+
+    return 0;
+  }
+
+private:
+  unsigned block_;
+  unsigned grid_;
+  unsigned shMemSize_;
+  T* d_buffer_;
+  T* h_buffer_;
+  unsigned bufferSize_;
+
+};
+
+
+} // namespace suncudavec
+
+#endif // _THREAD_PARTITIONING_HPP_
diff --git a/include/nvector/cuda/Vector.hpp b/include/nvector/cuda/Vector.hpp
new file mode 100644
index 0000000..aceb7f6
--- /dev/null
+++ b/include/nvector/cuda/Vector.hpp
@@ -0,0 +1,190 @@
+/*
+ * -----------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * -----------------------------------------------------------------
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ */
+
+
+/**
+ * Vector class
+ *
+ * Manages vector data layout for CUDA implementation of N_Vector.
+ *
+ */
+
+#ifndef _NVECTOR_HPP_
+#define _NVECTOR_HPP_
+
+#include <cstdlib>
+#include <iostream>
+
+#include <cuda_runtime.h>
+#include "ThreadPartitioning.hpp"
+
+#include <nvector/nvector_cuda.h>
+
+namespace suncudavec
+{
+
+template <typename T, typename I>
+class Vector : public _N_VectorContent_Cuda
+{
+public:
+  Vector(I N)
+  : size_(N),
+    mem_size_(N*sizeof(T)),
+    ownPartitioning_(true)
+  {
+    // Set partitioning
+    partStream_ = new StreamPartitioning<T, I>(N, 256);
+    partReduce_ = new ReducePartitioning<T, I>(N, 256);
+
+    allocate();
+  }
+
+  /// Copy constructor does not copy values
+  explicit Vector(const Vector& v)
+  : size_(v.size()),
+    mem_size_(size_*sizeof(T)),
+    partStream_(v.partStream_),
+    partReduce_(v.partReduce_),
+    ownPartitioning_(false)
+  {
+    allocate();
+  }
+
+  ~Vector()
+  {
+    if (ownPartitioning_)
+    {
+      delete partReduce_;
+      delete partStream_;
+    }
+    clear();
+  }
+
+
+  void allocate()
+  {
+    cudaError_t err;
+    h_vec_ = static_cast<T*>(malloc(mem_size_));
+    if(h_vec_ == NULL)
+      std::cerr << "Failed to allocate host vector!\n";
+    err = cudaMalloc((void**) &d_vec_, mem_size_);
+    if(err != cudaSuccess)
+      std::cerr << "Failed to allocate device vector (error code " << err << ")!\n";
+  }
+
+  void clear()
+  {
+    free(h_vec_);
+    cudaError_t err = cudaFree(d_vec_);
+    if(err != cudaSuccess)
+      std::cerr << "Failed to free device vector (error code " << err << ")!\n";
+  }
+
+  int size() const
+  {
+    return size_;
+  }
+
+  T* host()
+  {
+    return h_vec_;
+  }
+
+  const T* host() const
+  {
+    return h_vec_;
+  }
+
+  T* device()
+  {
+    return d_vec_;
+  }
+
+  const T* device() const
+  {
+    return d_vec_;
+  }
+
+  void copyToDev()
+  {
+    cudaError_t err = cudaMemcpy(d_vec_, h_vec_, mem_size_, cudaMemcpyHostToDevice);
+    if(err != cudaSuccess)
+      std::cerr << "Failed to copy vector from host to device (error code " << err << ")!\n";
+  }
+
+  void copyFromDev()
+  {
+    cudaError_t err = cudaMemcpy(h_vec_, d_vec_, mem_size_, cudaMemcpyDeviceToHost);
+    if(err != cudaSuccess)
+      std::cerr << "Failed to copy vector from device to host (error code " << err << ")!\n";
+  }
+
+  StreamPartitioning<T, I>& partStream() const
+  {
+    return *partStream_;
+  }
+
+  ReducePartitioning<T, I>& partReduce() const
+  {
+    return *partReduce_;
+  }
+
+private:
+  I size_;
+  I mem_size_;
+  T* h_vec_;
+  T* d_vec_;
+  StreamPartitioning<T, I>* partStream_;
+  ReducePartitioning<T, I>* partReduce_;
+  bool ownPartitioning_;
+};
+
+
+
+
+
+// Vector extractor
+template <typename T, typename I>
+inline Vector<T, I> *extract(N_Vector v)
+{ 
+  return static_cast<Vector<T, I>*>(v->content);
+}
+
+// Get Vector device data
+template <typename T, typename I>
+inline T *getDevData(N_Vector v)
+{
+  Vector<T,I> *vp = static_cast<Vector<T, I>*>(v->content);
+  return vp->device();
+}
+
+// Get Vector length
+template <typename T, typename I>
+inline I getSize(N_Vector v)
+{
+  Vector<T,I> *vp = static_cast<Vector<T, I>*>(v->content);
+  return vp->size();
+}
+
+} // namespace suncudavec
+
+
+
+
+#endif // _NVECTOR_HPP_
diff --git a/include/nvector/cuda/VectorKernels.cuh b/include/nvector/cuda/VectorKernels.cuh
new file mode 100644
index 0000000..6681c7b
--- /dev/null
+++ b/include/nvector/cuda/VectorKernels.cuh
@@ -0,0 +1,1083 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ */
+
+
+#ifndef _VECTOR_KERNELS_CUH_
+#define _VECTOR_KERNELS_CUH_
+
+#include <limits>
+#include <cuda_runtime.h>
+
+
+namespace suncudavec
+{
+
+/* -----------------------------------------------------------------
+ * The namespace for CUDA kernels
+ *
+ * Reduction CUDA kernels in nvector are based in part on "reduction"
+ * example in NVIDIA Corporation CUDA Samples, and parallel reduction
+ * examples in textbook by J. Cheng at al. "CUDA C Programming".
+ * -----------------------------------------------------------------
+ */
+namespace math_kernels
+{
+
+
+/**
+ * Sets all elements of the vector X to constant value a.
+ * 
+ */
+
+template <typename T, typename I>
+__global__ void
+setConstKernel(T a, T *X, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    X[i] = a;
+  }
+}
+
+
+/**
+ * Computes linear sum (combination) of two vectors.
+ * 
+ */
+
+template <typename T, typename I>
+__global__ void
+linearSumKernel(T a, const T *X, T b, const T *Y, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = a*X[i] + b*Y[i];
+  }
+}
+
+
+/**
+ * Elementwise product of two vectors.
+ *
+ */
+
+template <typename T, typename I>
+__global__ void
+prodKernel(const T *X, const T *Y, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = X[i]*Y[i];
+  }
+}
+
+
+/**
+ * Elementwise division of two vectors.
+ *
+ */
+
+template <typename T, typename I>
+__global__ void
+divKernel(const T *X, const T *Y, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = X[i]/Y[i];
+  }
+}
+
+
+/**
+ * Scale vector with scalar value 'a'.
+ *
+ */
+
+template <typename T, typename I>
+__global__ void
+scaleKernel(T a, const T *X, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = a*X[i];
+  }
+}
+
+
+/**
+ * Stores absolute values of vector X elements into vector Z.
+ *
+ */
+
+template <typename T, typename I>
+__global__ void
+absKernel(const T *X, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = abs(X[i]);
+  }
+}
+
+
+/**
+ * Elementwise inversion.
+ *
+ */
+
+template <typename T, typename I>
+__global__ void
+invKernel(const T *X, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = 1.0/(X[i]);
+  }
+}
+
+
+/**
+ * Add constant 'c' to each vector element.
+ *
+ */
+
+template <typename T, typename I>
+__global__ void
+addConstKernel(T a, const T *X, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = a + X[i];
+  }
+}
+
+
+/**
+ * Compare absolute values of vector 'X' with constant 'c'.
+ *
+ */
+
+template <typename T, typename I>
+__global__ void
+compareKernel(T c, const T *X, T *Z, I n)
+{
+  I i = blockDim.x * blockIdx.x + threadIdx.x;
+
+  if (i < n)
+  {
+    Z[i] = (abs(X[i]) >= c) ? 1.0 : 0.0;
+  }
+}
+
+
+/*
+ * Sums all elements of the vector.
+ *    
+ */
+template <typename T, typename I>
+__global__ void
+sumReduceKernel(const T *x, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T sum = 0.0;
+
+  // First reduction step before storing data in shared memory.
+  if (i < n)
+    sum = x[i];
+  if (i + blockDim.x < n)
+    sum += x[i+blockDim.x];
+  shmem[tid] = sum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      sum += shmem[tid + j];
+      shmem[tid] = sum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = sum;
+}
+
+
+/*
+ * Dot product of two vectors.
+ *    
+ */
+template <typename T, typename I>
+__global__ void
+dotProdKernel(const T *x, const T *y, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T sum = 0.0;
+
+  // First reduction step before storing data in shared memory.
+  if (i < n)
+    sum = x[i] * y[i];
+  if (i + blockDim.x < n)
+    sum += ( x[i+blockDim.x] * y[i+blockDim.x]);
+  shmem[tid] = sum;
+  __syncthreads();
+
+  // Perform blockwise reduction in shared memory
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      sum += shmem[tid + j];
+      shmem[tid] = sum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = sum;
+}
+
+
+/*
+ * Finds max norm the vector.
+ *    
+ */
+template <typename T, typename I>
+__global__ void
+maxNormKernel(const T *x, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T maximum = 0.0;
+
+  // First reduction step before storing data in shared memory.
+  if (i < n)
+    maximum = abs(x[i]);
+  if (i + blockDim.x < n)
+    maximum = max(abs(x[i+blockDim.x]), maximum);
+  shmem[tid] = maximum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      maximum = max(shmem[tid + j], maximum);
+      shmem[tid] = maximum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = maximum;
+}
+
+
+/*
+ * Weighted root mean square norm of a vector.
+ *    
+ */
+template <typename T, typename I>
+__global__ void
+wrmsNormKernel(const T *x, const T *w, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T sum = 0.0;
+
+  // First reduction step before storing data in shared memory.
+  if (i < n)
+    sum = x[i] * w[i] * x[i] * w[i];
+  if (i + blockDim.x < n)
+    sum += ( x[i+blockDim.x] * w[i+blockDim.x] * x[i+blockDim.x] * w[i+blockDim.x] );
+
+  shmem[tid] = sum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1)
+  {
+    if (tid < j) {
+      sum += shmem[tid + j];
+      shmem[tid] = sum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = sum;
+}
+
+/*
+ * Weighted root mean square norm of a vector values selected by id.
+ *
+ */
+template <typename T, typename I>
+__global__ void
+wrmsNormMaskKernel(const T *x, const T *w, const T *id, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T sum = 0.0;
+
+  // First reduction step before storing data in shared memory.
+  if (i < n && id[i] > 0.0)
+    sum = x[i] * w[i] * x[i] * w[i];
+  if ((i + blockDim.x < n) && (id[i] > 0.0))
+    sum += ( x[i+blockDim.x] * w[i+blockDim.x] * x[i+blockDim.x] * w[i+blockDim.x]);
+  shmem[tid] = sum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      sum += shmem[tid + j];
+      shmem[tid] = sum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = sum;
+}
+
+/*
+ * Finds min value in the vector.
+ *    
+ */
+template <typename T, typename I>
+__global__ void
+findMinKernel(T MAX_VAL, const T *x, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T minimum = MAX_VAL;
+
+  // First reduction step before storing data in shared memory.
+  if (i < n)
+    minimum = x[i];
+  if (i + blockDim.x < n)
+    minimum = min((x[i+blockDim.x]), minimum);
+  shmem[tid] = minimum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      minimum = min(shmem[tid + j], minimum);
+      shmem[tid] = minimum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = minimum;
+}
+
+
+/*
+ * Weighted root mean square notm of a vector.
+ *
+ */
+template <typename T, typename I>
+__global__ void
+L1NormKernel(const T *x, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T sum = 0.0;
+  // First reduction step before storing data in shared memory.
+  if (i < n)
+    sum = abs(x[i]);
+  if (i + blockDim.x < n)
+    sum += abs(x[i+blockDim.x]);
+  shmem[tid] = sum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      sum += shmem[tid + j];
+      shmem[tid] = sum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = sum;
+}
+
+/*
+ * Vector inverse  z[i] = 1/x[i] with check for zeros. Reduction is performed
+ * to flag the result if any x[i] = 0.
+ *
+ */
+template <typename T, typename I>
+__global__ void
+invTestKernel(const T *x, T *z, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  T flag;
+
+  // First reduction step before storing data in shared memory.
+  if (i < n && x[i] == 0.0) {
+    flag = 1.0;
+  } else {
+    flag = 0.0;
+    z[i] = 1.0/x[i];
+  }
+
+  if (i + blockDim.x < n && x[i + blockDim.x] == 0.0)
+  {
+    flag += 1.0;
+  }
+  else
+  {
+    z[i + blockDim.x] = 1.0/x[i + blockDim.x];
+  }
+
+  shmem[tid] = flag;
+  __syncthreads();
+
+  // Inverse calculation is done. Perform reduction block-wise in shared
+  // to find if any x[i] = 0.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      flag += shmem[tid + j];
+      shmem[tid] = flag;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = flag;
+}
+
+/*
+ * Checks if inequality constraints are satisfied. Constraint check
+ * results are stored in vector 'm'. A reduction is performed to set a
+ * flag > 0 if any of the constraints is violated.
+ *
+ */
+template <typename T, typename I>
+__global__ void
+constrMaskKernel(const T *c, const T *x, T *m, T *out, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  // First reduction step before storing data in shared memory.
+
+  // test1 = true if test failed
+  bool test1 = (abs(c[i]) > 1.5 && c[i]*x[i] <= 0.0) ||
+      (abs(c[i]) > 0.5 && c[i]*x[i] <  0.0);
+  T sum = m[i] = (i < n && test1) ? 1.0 : 0.0;
+
+  // test2 = true if test failed
+  bool test2 = (abs(c[i + blockDim.x]) > 1.5 && c[i + blockDim.x]*x[i + blockDim.x] <= 0.0) ||
+      (abs(c[i + blockDim.x]) > 0.5 && c[i + blockDim.x]*x[i + blockDim.x] <  0.0);
+  m[i+blockDim.x] = (i+blockDim.x < n && test2) ? 1.0 : 0.0;
+  sum += m[i+blockDim.x];
+
+  shmem[tid] = sum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      sum += shmem[tid + j];
+      shmem[tid] = sum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    out[blockIdx.x] = sum;
+}
+
+
+
+/*
+ * Finds minimum component-wise quotient.
+ *
+ */
+template <typename T, typename I>
+__global__ void
+minQuotientKernel(const T MAX_VAL, const T *num, const T *den, T *min_quotient, I n)
+{
+  extern __shared__ T shmem[];
+
+  I tid = threadIdx.x;
+  I i = blockIdx.x*(blockDim.x*2) + threadIdx.x;
+
+  // Initialize "minimum" to maximum floating point value.
+  T minimum = MAX_VAL;
+  const T zero = static_cast<T>(0.0);
+
+  // Load vector quotient in the shared memory. Skip if the denominator
+  // value is zero.
+  if (i < n && den[i] != zero)
+    minimum = num[i]/den[i];
+
+  // First level of reduction is upon storing values to shared memory.
+  if (i + blockDim.x < n && den[i + blockDim.x] != zero)
+    minimum = min(num[i+blockDim.x]/den[i+blockDim.x], minimum);
+
+  shmem[tid] = minimum;
+  __syncthreads();
+
+  // Perform reduction block-wise in shared memory.
+  for (I j = blockDim.x/2; j > 0; j >>= 1) {
+    if (tid < j) {
+      minimum = min(shmem[tid + j], minimum);
+      shmem[tid] = minimum;
+    }
+    __syncthreads();
+  }
+
+  // Copy reduction result for each block to global memory
+  if (tid == 0)
+    min_quotient[blockIdx.x] = minimum;
+}
+
+
+} // namespace math_kernels
+
+
+
+
+template <typename T, typename I>
+inline cudaError_t setConst(T a, Vector<T,I>& X)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::setConstKernel<<<grid, block>>>(a, X.device(), X.size());
+  return cudaGetLastError();
+}
+
+template <typename T, typename I>
+inline cudaError_t linearSum(T a, const Vector<T,I>& X, T b, const Vector<T,I>& Y, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::linearSumKernel<<<grid, block>>>(a, X.device(), b, Y.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+template <typename T, typename I>
+inline cudaError_t prod(const Vector<T,I>& X, const Vector<T,I>& Y, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::prodKernel<<<grid, block>>>(X.device(), Y.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+template <typename T, typename I>
+inline cudaError_t div(const Vector<T,I>& X, const Vector<T,I>& Y, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::divKernel<<<grid, block>>>(X.device(), Y.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+template <typename T, typename I>
+inline cudaError_t scale(T const a, const Vector<T,I>& X, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::scaleKernel<<<grid, block>>>(a, X.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+template <typename T, typename I>
+inline cudaError_t absVal(const Vector<T,I>& X, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::absKernel<<<grid, block>>>(X.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+template <typename T, typename I>
+inline cudaError_t inv(const Vector<T,I>& X, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::invKernel<<<grid, block>>>(X.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+template <typename T, typename I>
+inline cudaError_t addConst(T const a, const Vector<T,I>& X, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::addConstKernel<<<grid, block>>>(a, X.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+
+template <typename T, typename I>
+inline cudaError_t compare(T const c, const Vector<T,I>& X, Vector<T,I>& Z)
+{
+  // Set partitioning
+  StreamPartitioning<T, I>& p = X.partStream();
+  const I grid                = p.grid();
+  const unsigned block        = p.block();
+
+  math_kernels::compareKernel<<<grid, block>>>(c, X.device(), Z.device(), X.size());
+  return cudaGetLastError();
+}
+
+
+template <typename T, typename I>
+inline T dotProd(const Vector<T,I>& x, const Vector<T,I>& y)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::dotProdKernel<T,I><<< grid, block, shMemSize >>>(x.device(), y.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // Rerun reduction kernel
+    math_kernels::sumReduceKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    gpu_result += p.hostBuffer()[i];
+  }
+  return gpu_result;
+}
+
+template <typename T, typename I>
+inline T maxNorm(const Vector<T,I>& x)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::maxNormKernel<T,I><<< grid, block, shMemSize >>>(x.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // (Re)run reduction kernel
+    math_kernels::maxNormKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    if (p.hostBuffer()[i] > gpu_result)
+      gpu_result = p.hostBuffer()[i];
+  }
+  return gpu_result;
+}
+
+template <typename T, typename I>
+inline T wrmsNorm(const Vector<T,I>& x, const Vector<T,I>& w)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::wrmsNormKernel<T,I><<< grid, block, shMemSize >>>(x.device(), w.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // (Re)run reduction kernel
+    math_kernels::sumReduceKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    gpu_result += p.hostBuffer()[i];
+  }
+  return sqrt(gpu_result/x.size());
+}
+
+template <typename T, typename I>
+inline T wrmsNormMask(const Vector<T,I>& x, const Vector<T,I>& w, const Vector<T,I>& id)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::wrmsNormMaskKernel<T,I><<< grid, block, shMemSize >>>(x.device(), w.device(), id.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // (Re)run reduction kernel
+    math_kernels::sumReduceKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    gpu_result += p.hostBuffer()[i];
+  }
+  return sqrt(gpu_result/x.size());
+}
+
+template <typename T, typename I>
+inline T findMin(const Vector<T,I>& x)
+{
+  T maxVal = std::numeric_limits<T>::max();
+
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::findMinKernel<T,I><<< grid, block, shMemSize >>>(maxVal, x.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // Rerun reduction kernel
+    math_kernels::findMinKernel<T,I><<< grid, block, shMemSize >>>(maxVal, p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    if (p.hostBuffer()[i] < gpu_result)
+      gpu_result = p.hostBuffer()[i];
+  }
+  return gpu_result;
+}
+
+
+template <typename T, typename I>
+inline T wL2Norm(const Vector<T,I>& x, const Vector<T,I>& y)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::wrmsNormKernel<T,I><<< grid, block, shMemSize >>>(x.device(), y.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // Rerun reduction kernel
+    math_kernels::sumReduceKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    gpu_result += p.hostBuffer()[i];
+  }
+  return sqrt(gpu_result);
+}
+
+
+template <typename T, typename I>
+inline T L1Norm(const Vector<T,I>& x)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::L1NormKernel<T,I><<< grid, block, shMemSize >>>(x.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // Rerun reduction kernel
+    math_kernels::sumReduceKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    gpu_result += p.hostBuffer()[i];
+  }
+  return gpu_result;
+}
+
+
+template <typename T, typename I>
+inline bool invTest(const Vector<T,I>& x, Vector<T,I>& z)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::invTestKernel<T,I><<< grid, block, shMemSize >>>(x.device(), z.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // Rerun reduction kernel
+    math_kernels::sumReduceKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    gpu_result += p.hostBuffer()[i];
+  }
+  return !(gpu_result > 0.0);
+}
+
+
+template <typename T, typename I>
+inline bool constrMask(const Vector<T,I>& c, const Vector<T,I>& x, Vector<T,I>& m)
+{
+  // Set partitioning
+  ReducePartitioning<T, I>& p = x.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::constrMaskKernel<T,I><<< grid, block, shMemSize >>>(c.device(), x.device(), m.device(), p.devBuffer(), x.size());
+
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // Rerun reduction kernel
+    math_kernels::sumReduceKernel<T,I><<< grid, block, shMemSize >>>(p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    gpu_result += p.hostBuffer()[i];
+  }
+  return (gpu_result < 0.5);
+}
+
+
+template <typename T, typename I>
+inline T minQuotient(const Vector<T,I>& num, const Vector<T,I>& den)
+{
+  // Starting value for min reduction
+  T maxVal = std::numeric_limits<T>::max();
+
+  // Set partitioning
+  ReducePartitioning<T, I>& p = num.partReduce();
+  unsigned grid               = p.grid();
+  unsigned block              = p.block();
+  unsigned shMemSize          = p.shmem();
+
+  math_kernels::minQuotientKernel<T,I><<< grid, block, shMemSize >>>(maxVal, num.device(), den.device(), p.devBuffer(), num.size());
+
+  // All quotients are computed by now. Find the minimum.
+  unsigned n = grid;
+  unsigned nmax = 2*block;
+  while (n > nmax)
+  {
+    // Recompute partitioning
+    p.setPartitioning(n, grid, block, shMemSize);
+
+    // Rerun reduction kernel
+    math_kernels::findMinKernel<T,I><<< grid, block, shMemSize >>>(maxVal, p.devBuffer(), p.devBuffer(), n);
+    n = grid;
+  }
+
+  // Finish reduction on CPU if there are less than two blocks of data left.
+  p.copyFromDevBuffer(n);
+
+  T gpu_result = p.hostBuffer()[0];
+  for (unsigned int i=1; i<n; i++)
+  {
+    if (p.hostBuffer()[i] < gpu_result)
+      gpu_result = p.hostBuffer()[i];
+  }
+  return gpu_result;
+}
+
+
+
+} // namespace nvec
+
+
+
+#endif // _VECTOR_KERNELS_CUH_
diff --git a/include/nvector/nvector_cuda.h b/include/nvector/nvector_cuda.h
new file mode 100644
index 0000000..963cf4d
--- /dev/null
+++ b/include/nvector/nvector_cuda.h
@@ -0,0 +1,265 @@
+/* ----------------------------------------------------------------- 
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the CUDA implementation of the
+ * NVECTOR module.
+ *
+ * Part I contains declarations specific to the CUDA
+ * implementation of the supplied NVECTOR module.
+ *
+ * Part II contains the prototype for the constructor N_VNew_Cuda
+ * as well as implementation-specific prototypes for various useful
+ * vector operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic N_Vector structure can be found
+ *     in the header file sundials_nvector.h.
+ *
+ *   - The definitions of the types 'realtype' and 'sunindextype' can
+ *     be found in the header file sundials_types.h, and it may be
+ *     changed (at the configuration stage) according to the user's needs.
+ *     The sundials_types.h file also contains the definition
+ *     for the type 'booleantype'.
+ *
+ *   - N_Vector arguments to arithmetic vector operations need not
+ *     be distinct. For example, the following call:
+ *
+ *       N_VLinearSum_Cuda(a,x,b,y,y);
+ *
+ *     (which stores the result of the operation a*x+b*y in y)
+ *     is legal.
+ * -----------------------------------------------------------------*/
+
+#ifndef _NVECTOR_CUDA_H
+#define _NVECTOR_CUDA_H
+
+#include <sundials/sundials_nvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+    
+    
+/*
+ * -----------------------------------------------------------------
+ * PART I: CUDA implementation of N_Vector
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * CUDA implementation of the N_Vector 'content' is in C++ class
+ * Vector. The class inherits from structure _N_VectorContent_Cuda
+ * to create C <--> C++ interface.
+ */
+
+struct _N_VectorContent_Cuda {};
+
+typedef struct _N_VectorContent_Cuda *N_VectorContent_Cuda;
+
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by nvector_cuda
+ * 
+ * CONSTRUCTORS:
+ *    N_VNew_Cuda
+ *    N_VNewEmpty_Cuda
+ *    N_VMake_Cuda
+ *    N_VCloneVectorArray_Cuda
+ *    N_VCloneVectorArrayEmpty_Cuda
+ * DESTRUCTORS:
+ *    N_VDestroy_Cuda
+ *    N_VDestroyVectorArray_Cuda
+ * OTHER:
+ *    N_VGetHostArrayPointer_Cuda
+ *    N_VGetDeviceArrayPointer_Cuda
+ *    N_VPrint_Cuda
+ *    N_VPrintFile_Cuda
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNew_Cuda
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a CUDA vector.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNew_Cuda(sunindextype vec_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNewEmpty_Cuda
+ * -----------------------------------------------------------------
+ * This function creates a new CUDA N_Vector with an empty (NULL)
+ * data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNewEmpty_Cuda(sunindextype vec_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VMake_Cuda
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a CUDA vector
+ * with a user-supplied data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VMake_Cuda(N_VectorContent_Cuda c);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArray_Cuda
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' CUDA vectors by
+ * cloning a given vector w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Cuda(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArrayEmpty_Cuda
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' CUDA vectors each
+ * with an empty (NULL) data array by cloning w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Cuda(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VDestroyVectorArray_Cuda
+ * -----------------------------------------------------------------
+ * This function frees an array of CUDA vectors created with 
+ * N_VCloneVectorArray_Cuda or N_VCloneVectorArrayEmpty_Cuda.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VDestroyVectorArray_Cuda(N_Vector *vs, int count);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VGetLength_Cuda
+ * -----------------------------------------------------------------
+ * This function returns the length of the vector.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT sunindextype N_VGetLength_Cuda(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VGetHostArrayPointer_Cuda
+ * -----------------------------------------------------------------
+ * This function returns pointer to the host raw data.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype *N_VGetHostArrayPointer_Cuda(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VGetDeviceArrayPointer_Cuda
+ * -----------------------------------------------------------------
+ * This function returns pointer to the device raw data.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype *N_VGetDeviceArrayPointer_Cuda(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCopyTotDevice_Cuda
+ * -----------------------------------------------------------------
+ * This function copies host data to the device.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VCopyToDevice_Cuda(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCopyTotDevice_Cuda
+ * -----------------------------------------------------------------
+ * This function copies vector data from the device to the host.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VCopyFromDevice_Cuda(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VPrint_Cuda
+ * -----------------------------------------------------------------
+ * This function prints the content of a CUDA vector to stdout.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrint_Cuda(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VPrintFile_Cuda
+ * -----------------------------------------------------------------
+ * This function prints the content of a CUDA vector to outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_Cuda(N_Vector v, FILE *outfile);
+
+/*
+ * -----------------------------------------------------------------
+ * CUDA implementations of various useful vector operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Cuda(N_Vector w);
+SUNDIALS_EXPORT N_Vector N_VClone_Cuda(N_Vector w);
+SUNDIALS_EXPORT void N_VDestroy_Cuda(N_Vector v);
+SUNDIALS_EXPORT void N_VSpace_Cuda(N_Vector v, sunindextype *lrw, sunindextype *liw);
+
+SUNDIALS_EXPORT void N_VLinearSum_Cuda(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VConst_Cuda(realtype c, N_Vector z);
+SUNDIALS_EXPORT void N_VProd_Cuda(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VDiv_Cuda(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VScale_Cuda(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAbs_Cuda(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VInv_Cuda(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAddConst_Cuda(N_Vector x, realtype b, N_Vector z);
+SUNDIALS_EXPORT realtype N_VDotProd_Cuda(N_Vector x, N_Vector y);
+SUNDIALS_EXPORT realtype N_VMaxNorm_Cuda(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWrmsNorm_Cuda(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VWrmsNormMask_Cuda(N_Vector x, N_Vector w, N_Vector id);
+SUNDIALS_EXPORT realtype N_VMin_Cuda(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWL2Norm_Cuda(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VL1Norm_Cuda(N_Vector x);
+SUNDIALS_EXPORT void N_VCompare_Cuda(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VInvTest_Cuda(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VConstrMask_Cuda(N_Vector c, N_Vector x, N_Vector m);
+SUNDIALS_EXPORT realtype N_VMinQuotient_Cuda(N_Vector num, N_Vector denom);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/nvector/nvector_openmp.h b/include/nvector/nvector_openmp.h
index d9cf4c8..f033c1b 100644
--- a/include/nvector/nvector_openmp.h
+++ b/include/nvector/nvector_openmp.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4869 $
- * $Date: 2016-08-19 10:34:20 -0700 (Fri, 19 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner and Carol S. Woodward @ LLNL
  * -----------------------------------------------------------------
  * Acknowledgements: This NVECTOR module is based on the NVECTOR 
@@ -52,8 +48,7 @@
  *
  *     (which stores the result of the operation a*x+b*y in y)
  *     is legal.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _NVECTOR_OPENMP_H
 #define _NVECTOR_OPENMP_H
@@ -76,7 +71,7 @@ extern "C" {
    the data */
 
 struct _N_VectorContent_OpenMP {
-  long int length;
+  sunindextype length;
   booleantype own_data;
   realtype *data;
   int num_threads;
@@ -93,7 +88,7 @@ typedef struct _N_VectorContent_OpenMP *N_VectorContent_OpenMP;
  * are assumed:
  *
  * N_Vector v;
- * long int i;
+ * sunindextype i;
  *
  * (1) NV_CONTENT_OMP
  *
@@ -161,6 +156,7 @@ typedef struct _N_VectorContent_OpenMP *N_VectorContent_OpenMP;
  * OTHER:
  *    N_VGetLength_OpenMP
  *    N_VPrint_OpenMP
+ *    N_VPrintFile_OpenMP
  * -----------------------------------------------------------------
  */
 
@@ -172,7 +168,7 @@ typedef struct _N_VectorContent_OpenMP *N_VectorContent_OpenMP;
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VNew_OpenMP(long int vec_length, int num_threads);
+SUNDIALS_EXPORT N_Vector N_VNew_OpenMP(sunindextype vec_length, int num_threads);
 
 /*
  * -----------------------------------------------------------------
@@ -183,7 +179,7 @@ SUNDIALS_EXPORT N_Vector N_VNew_OpenMP(long int vec_length, int num_threads);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VNewEmpty_OpenMP(long int vec_length, int num_threads);
+SUNDIALS_EXPORT N_Vector N_VNewEmpty_OpenMP(sunindextype vec_length, int num_threads);
 
 /*
  * -----------------------------------------------------------------
@@ -194,7 +190,7 @@ SUNDIALS_EXPORT N_Vector N_VNewEmpty_OpenMP(long int vec_length, int num_threads
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VMake_OpenMP(long int vec_length, realtype *v_data, int num_threads);
+SUNDIALS_EXPORT N_Vector N_VMake_OpenMP(sunindextype vec_length, realtype *v_data, int num_threads);
 
 /*
  * -----------------------------------------------------------------
@@ -237,7 +233,7 @@ SUNDIALS_EXPORT void N_VDestroyVectorArray_OpenMP(N_Vector *vs, int count);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int N_VGetLength_OpenMP(N_Vector v);
+SUNDIALS_EXPORT sunindextype N_VGetLength_OpenMP(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
@@ -251,6 +247,16 @@ SUNDIALS_EXPORT void N_VPrint_OpenMP(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
+ * Function : N_VPrintFile_OpenMP
+ * -----------------------------------------------------------------
+ * This function prints the content of a OpenMP vector to outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_OpenMP(N_Vector v, FILE *outfile);
+
+/*
+ * -----------------------------------------------------------------
  * OpenMP implementations of various useful vector operations
  * -----------------------------------------------------------------
  */
@@ -259,7 +265,7 @@ SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID_OpenMP(N_Vector v);
 SUNDIALS_EXPORT N_Vector N_VCloneEmpty_OpenMP(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VClone_OpenMP(N_Vector w);
 SUNDIALS_EXPORT void N_VDestroy_OpenMP(N_Vector v);
-SUNDIALS_EXPORT void N_VSpace_OpenMP(N_Vector v, long int *lrw, long int *liw);
+SUNDIALS_EXPORT void N_VSpace_OpenMP(N_Vector v, sunindextype *lrw, sunindextype *liw);
 SUNDIALS_EXPORT realtype *N_VGetArrayPointer_OpenMP(N_Vector v);
 SUNDIALS_EXPORT void N_VSetArrayPointer_OpenMP(realtype *v_data, N_Vector v);
 SUNDIALS_EXPORT void N_VLinearSum_OpenMP(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
diff --git a/include/nvector/nvector_parallel.h b/include/nvector/nvector_parallel.h
index e725451..e8096b6 100644
--- a/include/nvector/nvector_parallel.h
+++ b/include/nvector/nvector_parallel.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4867 $
- * $Date: 2016-08-19 10:05:14 -0700 (Fri, 19 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
  *                and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -48,14 +44,14 @@
  *
  *     (which stores the result of the operation a*x+b*y in y)
  *     is legal.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _NVECTOR_PARALLEL_H
 #define _NVECTOR_PARALLEL_H
 
 #include <mpi.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_mpi_types.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -68,32 +64,14 @@ extern "C" {
  * -----------------------------------------------------------------
  */
 
-/* define MPI data types */
-
-#if defined(SUNDIALS_SINGLE_PRECISION)
-
-#define PVEC_REAL_MPI_TYPE MPI_FLOAT
-
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-
-#define PVEC_REAL_MPI_TYPE MPI_DOUBLE
-
-#elif defined(SUNDIALS_EXTENDED_PRECISION)
-
-#define PVEC_REAL_MPI_TYPE MPI_LONG_DOUBLE
-
-#endif
-
-#define PVEC_INTEGER_MPI_TYPE MPI_LONG
-
 /* parallel implementation of the N_Vector 'content' structure
    contains the global and local lengths of the vector, a pointer
    to an array of 'realtype components', the MPI communicator,
    and a flag indicating ownership of the data */
 
 struct _N_VectorContent_Parallel {
-  long int local_length;   /* local vector length         */
-  long int global_length;  /* global vector length        */
+  sunindextype local_length;   /* local vector length         */
+  sunindextype global_length;  /* global vector length        */
   booleantype own_data;    /* ownership of data           */
   realtype *data;          /* local data array            */
   MPI_Comm comm;           /* pointer to MPI communicator */
@@ -110,7 +88,7 @@ typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel;
  * are assumed:
  *
  * N_Vector v;
- * long int v_len, s_len, i;
+ * sunindextype v_len, s_len, i;
  *
  * (1) NV_CONTENT_P
  *
@@ -196,6 +174,7 @@ typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel;
  *    N_VGetLength_Parallel
  *    N_VGetLocalLength_Parallel
  *    N_VPrint_Parallel
+ *    N_VPrintFile_Parallel
  * -----------------------------------------------------------------
  */
 
@@ -208,8 +187,8 @@ typedef struct _N_VectorContent_Parallel *N_VectorContent_Parallel;
  */
 
 SUNDIALS_EXPORT N_Vector N_VNew_Parallel(MPI_Comm comm, 
-                                         long int local_length,
-                                         long int global_length);
+                                         sunindextype local_length,
+                                         sunindextype global_length);
 
 /*
  * -----------------------------------------------------------------
@@ -221,8 +200,8 @@ SUNDIALS_EXPORT N_Vector N_VNew_Parallel(MPI_Comm comm,
  */
 
 SUNDIALS_EXPORT N_Vector N_VNewEmpty_Parallel(MPI_Comm comm, 
-                                              long int local_length,
-                                              long int global_length);
+                                              sunindextype local_length,
+                                              sunindextype global_length);
 
 /*
  * -----------------------------------------------------------------
@@ -234,8 +213,8 @@ SUNDIALS_EXPORT N_Vector N_VNewEmpty_Parallel(MPI_Comm comm,
  */
 
 SUNDIALS_EXPORT N_Vector N_VMake_Parallel(MPI_Comm comm, 
-                                          long int local_length,
-                                          long int global_length,
+                                          sunindextype local_length,
+                                          sunindextype global_length,
                                           realtype *v_data);
 
 /*
@@ -281,7 +260,7 @@ SUNDIALS_EXPORT void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int N_VGetLength_Parallel(N_Vector v);
+SUNDIALS_EXPORT sunindextype N_VGetLength_Parallel(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
@@ -291,13 +270,14 @@ SUNDIALS_EXPORT long int N_VGetLength_Parallel(N_Vector v);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int N_VGetLocalLength_Parallel(N_Vector v);
+SUNDIALS_EXPORT sunindextype N_VGetLocalLength_Parallel(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
  * Function : N_VPrint_Parallel
  * -----------------------------------------------------------------
- * This function prints the content of a parallel vector to stdout.
+ * This function prints the local content of a parallel vector to
+ * stdout.
  * -----------------------------------------------------------------
  */
 
@@ -305,6 +285,17 @@ SUNDIALS_EXPORT void N_VPrint_Parallel(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
+ * Function : N_VPrintFile_Parallel
+ * -----------------------------------------------------------------
+ * This function prints the local content of a parallel vector to
+ * outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_Parallel(N_Vector v, FILE *outfile);
+
+/*
+ * -----------------------------------------------------------------
  * parallel implementations of the vector operations
  * -----------------------------------------------------------------
  */
@@ -313,7 +304,7 @@ SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID_Parallel(N_Vector v);
 SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Parallel(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VClone_Parallel(N_Vector w);
 SUNDIALS_EXPORT void N_VDestroy_Parallel(N_Vector v);
-SUNDIALS_EXPORT void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw);
+SUNDIALS_EXPORT void N_VSpace_Parallel(N_Vector v, sunindextype *lrw, sunindextype *liw);
 SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Parallel(N_Vector v);
 SUNDIALS_EXPORT void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v);
 SUNDIALS_EXPORT void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
diff --git a/include/nvector/nvector_parhyp.h b/include/nvector/nvector_parhyp.h
index e3777ca..24c6451 100644
--- a/include/nvector/nvector_parhyp.h
+++ b/include/nvector/nvector_parhyp.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Jean M. Sexton @ SMU
  *                Slaven Peles @ LLNL
  * ----------------------------------------------------------------- 
@@ -47,14 +43,14 @@
  *
  *     (which stores the result of the operation a*x+b*y in y)
  *     is legal.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _NVECTOR_PARHYP_H
 #define _NVECTOR_PARHYP_H
 
 #include <mpi.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_mpi_types.h>
 
 /* hypre header files */
 #include <_hypre_parcsr_mv.h>
@@ -70,18 +66,6 @@ extern "C" {
  * -----------------------------------------------------------------
  */
 
-/* define MPI data types */
-
-#if defined(SUNDIALS_SINGLE_PRECISION)
-  #define PVEC_REAL_MPI_TYPE MPI_FLOAT
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-  #define PVEC_REAL_MPI_TYPE MPI_DOUBLE
-#elif defined(SUNDIALS_EXTENDED_PRECISION)
-  #define PVEC_REAL_MPI_TYPE MPI_LONG_DOUBLE
-#endif
-
-#define PVEC_INTEGER_MPI_TYPE MPI_LONG
-
 /* 
  * Parallel implementation of the N_Vector 'content' structure
  * contains the global and local lengths of the vector, a pointer
@@ -89,8 +73,8 @@ extern "C" {
  * and a flag indicating ownership of the data. 
  */
 struct _N_VectorContent_ParHyp {
-  long int local_length;      /* local vector length         */
-  long int global_length;     /* global vector length        */
+  sunindextype local_length;      /* local vector length         */
+  sunindextype global_length;     /* global vector length        */
   booleantype own_parvector;  /* ownership of HYPRE vector   */
   MPI_Comm comm;              /* pointer to MPI communicator */
 
@@ -116,6 +100,7 @@ typedef struct _N_VectorContent_ParHyp *N_VectorContent_ParHyp;
  *    N_VGetVector_ParHyp
  * OTHER:
  *    N_VPrint_ParHyp
+ *    N_VPrintFile_ParHyp
  * -----------------------------------------------------------------
  */
 
@@ -129,8 +114,8 @@ typedef struct _N_VectorContent_ParHyp *N_VectorContent_ParHyp;
  */
 
 SUNDIALS_EXPORT N_Vector N_VNewEmpty_ParHyp(MPI_Comm comm, 
-                                            long int local_length,
-                                            long int global_length);
+                                            sunindextype local_length,
+                                            sunindextype global_length);
 
 /*
  * -----------------------------------------------------------------
@@ -191,7 +176,8 @@ SUNDIALS_EXPORT hypre_ParVector *N_VGetVector_ParHyp(N_Vector v);
  * -----------------------------------------------------------------
  * Function : N_VPrint_ParHyp
  * -----------------------------------------------------------------
- * This function prints the content of a parallel vector to stdout.
+ * This function prints the local content of a parallel vector to
+ * stdout.
  * -----------------------------------------------------------------
  */
 
@@ -199,6 +185,17 @@ SUNDIALS_EXPORT void N_VPrint_ParHyp(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
+ * Function : N_VPrintFile_ParHyp
+ * -----------------------------------------------------------------
+ * This function prints the local content of a parallel vector to
+ * outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_ParHyp(N_Vector v, FILE *outfile);
+
+/*
+ * -----------------------------------------------------------------
  * parallel implementations of the vector operations
  * -----------------------------------------------------------------
  */
@@ -207,7 +204,7 @@ SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID_ParHyp(N_Vector v);
 SUNDIALS_EXPORT N_Vector N_VCloneEmpty_ParHyp(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VClone_ParHyp(N_Vector w);
 SUNDIALS_EXPORT void N_VDestroy_ParHyp(N_Vector v);
-SUNDIALS_EXPORT void N_VSpace_ParHyp(N_Vector v, long int *lrw, long int *liw);
+SUNDIALS_EXPORT void N_VSpace_ParHyp(N_Vector v, sunindextype *lrw, sunindextype *liw);
 SUNDIALS_EXPORT realtype *N_VGetArrayPointer_ParHyp(N_Vector v);
 SUNDIALS_EXPORT void N_VSetArrayPointer_ParHyp(realtype *v_data, N_Vector v);
 SUNDIALS_EXPORT void N_VLinearSum_ParHyp(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
diff --git a/include/nvector/nvector_petsc.h b/include/nvector/nvector_petsc.h
index 0690129..c5201c2 100644
--- a/include/nvector/nvector_petsc.h
+++ b/include/nvector/nvector_petsc.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision:$
- * $Date:$
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Slaven Peles @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -43,8 +39,7 @@
  *
  *     (which stores the result of the operation a*x+b*y in y)
  *     is legal.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _NVECTOR_PETSC_H
 #define _NVECTOR_PETSC_H
@@ -52,6 +47,7 @@
 #include <mpi.h>
 #include <petscvec.h>
 #include <sundials/sundials_nvector.h>
+#include <sundials/sundials_mpi_types.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -64,32 +60,14 @@ extern "C" {
  * -----------------------------------------------------------------
  */
 
-/* define MPI data types */
-
-#if defined(SUNDIALS_SINGLE_PRECISION)
-
-#define PVEC_REAL_MPI_TYPE MPI_FLOAT
-
-#elif defined(SUNDIALS_DOUBLE_PRECISION)
-
-#define PVEC_REAL_MPI_TYPE MPI_DOUBLE
-
-#elif defined(SUNDIALS_EXTENDED_PRECISION)
-
-#define PVEC_REAL_MPI_TYPE MPI_LONG_DOUBLE
-
-#endif
-
-#define PVEC_INTEGER_MPI_TYPE MPI_LONG
-
 /* parallel implementation of the N_Vector 'content' structure
    contains the global and local lengths of the vector, a pointer
    to the underlying PETSc vector, the MPI communicator,
    and a flag indicating ownership of the PETSc vector */
 
 struct _N_VectorContent_Petsc {
-  long int local_length;   /* copy of local vector length  */
-  long int global_length;  /* copy of global vector length */
+  sunindextype local_length;   /* copy of local vector length  */
+  sunindextype global_length;  /* copy of global vector length */
   booleantype own_data;    /* ownership of data            */
   Vec *pvec;               /* pointer to PETSc vector      */
   MPI_Comm comm;           /* copy of MPI communicator     */
@@ -111,6 +89,7 @@ typedef struct _N_VectorContent_Petsc *N_VectorContent_Petsc;
  * OTHER:
  *    N_VGetVector_Petsc
  *    N_VPrint_Petsc
+ *    N_VPrintFile_Petsc
  * -----------------------------------------------------------------
  */
 
@@ -125,8 +104,8 @@ typedef struct _N_VectorContent_Petsc *N_VectorContent_Petsc;
  */
 
 SUNDIALS_EXPORT N_Vector N_VNewEmpty_Petsc(MPI_Comm comm, 
-                                           long int local_length,
-                                           long int global_length);
+                                           sunindextype local_length,
+                                           sunindextype global_length);
 
 /*
  * -----------------------------------------------------------------
@@ -203,6 +182,17 @@ SUNDIALS_EXPORT void N_VPrint_Petsc(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
+ * Function : N_VPrintFile_Petsc
+ * -----------------------------------------------------------------
+ * This function prints the local content of a parallel vector to
+ * outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_Petsc(N_Vector v, const char fname[]);
+
+/*
+ * -----------------------------------------------------------------
  * PETSc implementations of the vector operations
  * -----------------------------------------------------------------
  */
@@ -211,7 +201,7 @@ SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID_Petsc(N_Vector v);
 SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Petsc(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VClone_Petsc(N_Vector w);
 SUNDIALS_EXPORT void N_VDestroy_Petsc(N_Vector v);
-SUNDIALS_EXPORT void N_VSpace_Petsc(N_Vector v, long int *lrw, long int *liw);
+SUNDIALS_EXPORT void N_VSpace_Petsc(N_Vector v, sunindextype *lrw, sunindextype *liw);
 SUNDIALS_EXPORT void N_VSetArrayPointer_Petsc(realtype *v_data, N_Vector v);
 SUNDIALS_EXPORT void N_VLinearSum_Petsc(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
 SUNDIALS_EXPORT void N_VConst_Petsc(realtype c, N_Vector z);
diff --git a/include/nvector/nvector_pthreads.h b/include/nvector/nvector_pthreads.h
index e73d839..1cb52f7 100644
--- a/include/nvector/nvector_pthreads.h
+++ b/include/nvector/nvector_pthreads.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4869 $
- * $Date: 2016-08-19 10:34:20 -0700 (Fri, 19 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * Acknowledgements: This NVECTOR module is based on the NVECTOR 
@@ -53,8 +49,7 @@
  *
  *     (which stores the result of the operation a*x+b*y in y)
  *     is legal.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _NVECTOR_PTHREADS_H
 #define _NVECTOR_PTHREADS_H
@@ -78,7 +73,7 @@ extern "C" {
    ownership of the data */
 
 struct _N_VectorContent_Pthreads {
-  long int length;
+  sunindextype length;
   booleantype own_data;
   realtype *data;
   int num_threads;
@@ -89,8 +84,8 @@ typedef struct _N_VectorContent_Pthreads *N_VectorContent_Pthreads;
 
 /* structure to allow threads to share data */
 struct _Pthreads_Data{
-  long int start;                /* starting index for loop  */ 
-  long int end;                  /* ending index for loop    */
+  sunindextype start;                /* starting index for loop  */ 
+  sunindextype end;                  /* ending index for loop    */
   realtype c1, c2;               /* scaler values            */
   realtype *v1, *v2, *v3;        /* vector data              */
   realtype *global_val;          /* shared global variable   */
@@ -109,7 +104,7 @@ typedef struct _Pthreads_Data Pthreads_Data;
  * are assumed:
  *
  * N_Vector v;
- * long int i;
+ * sunindextype i;
  *
  * (1) NV_CONTENT_PT
  *
@@ -182,6 +177,7 @@ typedef struct _Pthreads_Data Pthreads_Data;
  * OTHER:
  *    N_VGetLength_Pthreads
  *    N_VPrint_Pthreads
+ *    N_VPrintFile_Pthreads
  * -----------------------------------------------------------------
  */
 
@@ -193,7 +189,7 @@ typedef struct _Pthreads_Data Pthreads_Data;
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VNew_Pthreads(long int vec_length, int n_threads);
+SUNDIALS_EXPORT N_Vector N_VNew_Pthreads(sunindextype vec_length, int n_threads);
 
 /*
  * -----------------------------------------------------------------
@@ -204,7 +200,7 @@ SUNDIALS_EXPORT N_Vector N_VNew_Pthreads(long int vec_length, int n_threads);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VNewEmpty_Pthreads(long int vec_length, int n_threads);
+SUNDIALS_EXPORT N_Vector N_VNewEmpty_Pthreads(sunindextype vec_length, int n_threads);
 
 /*
  * -----------------------------------------------------------------
@@ -215,7 +211,7 @@ SUNDIALS_EXPORT N_Vector N_VNewEmpty_Pthreads(long int vec_length, int n_threads
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VMake_Pthreads(long int vec_length, int n_threads, realtype *v_data);
+SUNDIALS_EXPORT N_Vector N_VMake_Pthreads(sunindextype vec_length, int n_threads, realtype *v_data);
 
 /*
  * -----------------------------------------------------------------
@@ -258,7 +254,7 @@ SUNDIALS_EXPORT void N_VDestroyVectorArray_Pthreads(N_Vector *vs, int count);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int N_VGetLength_Pthreads(N_Vector v);
+SUNDIALS_EXPORT sunindextype N_VGetLength_Pthreads(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
@@ -272,6 +268,16 @@ SUNDIALS_EXPORT void N_VPrint_Pthreads(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
+ * Function : N_VPrintFile_Pthreads
+ * -----------------------------------------------------------------
+ * This function prints the content of a pthreads vector to outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_Pthreads(N_Vector v, FILE *outfile);
+
+/*
+ * -----------------------------------------------------------------
  * pthreads implementations of various useful vector operations
  * -----------------------------------------------------------------
  */
@@ -280,7 +286,7 @@ SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID_Pthreads(N_Vector v);
 SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Pthreads(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VClone_Pthreads(N_Vector w);
 SUNDIALS_EXPORT void N_VDestroy_Pthreads(N_Vector v);
-SUNDIALS_EXPORT void N_VSpace_Pthreads(N_Vector v, long int *lrw, long int *liw);
+SUNDIALS_EXPORT void N_VSpace_Pthreads(N_Vector v, sunindextype *lrw, sunindextype *liw);
 SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Pthreads(N_Vector v);
 SUNDIALS_EXPORT void N_VSetArrayPointer_Pthreads(realtype *v_data, N_Vector v);
 SUNDIALS_EXPORT void N_VLinearSum_Pthreads(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
diff --git a/include/nvector/nvector_raja.h b/include/nvector/nvector_raja.h
new file mode 100644
index 0000000..c40901e
--- /dev/null
+++ b/include/nvector/nvector_raja.h
@@ -0,0 +1,266 @@
+/* ----------------------------------------------------------------- 
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the RAJA implementation of the
+ * NVECTOR module.
+ *
+ * Part I contains declarations specific to the RAJA
+ * implementation of the supplied NVECTOR module.
+ *
+ * Part II contains the prototype for the constructor N_VNew_Raja
+ * as well as implementation-specific prototypes for various useful
+ * vector operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic N_Vector structure can be found
+ *     in the header file sundials_nvector.h.
+ *
+ *   - The definition of the type 'realtype' can be found in the
+ *     header file sundials_types.h, and it may be changed (at the 
+ *     configuration stage) according to the user's needs. 
+ *     The sundials_types.h file also contains the definition
+ *     for the type 'booleantype'.
+ *
+ *   - N_Vector arguments to arithmetic vector operations need not
+ *     be distinct. For example, the following call:
+ *
+ *       N_VLinearSum_Raja(a,x,b,y,y);
+ *
+ *     (which stores the result of the operation a*x+b*y in y)
+ *     is legal.
+ * -----------------------------------------------------------------*/
+
+#ifndef _NVECTOR_RAJA_H
+#define _NVECTOR_RAJA_H
+
+#include <sundials/sundials_nvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+    
+    
+/*
+ * -----------------------------------------------------------------
+ * PART I: RAJA implementation of N_Vector
+ * -----------------------------------------------------------------
+ */
+
+/* RAJA implementation of the N_Vector 'content' structure
+   contains the length of the vector, a pointer to an array
+   of 'realtype' components, and a flag indicating ownership of
+   the data */
+
+struct _N_VectorContent_Raja {};
+
+typedef struct _N_VectorContent_Raja *N_VectorContent_Raja;
+
+
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by nvector_raja
+ * 
+ * CONSTRUCTORS:
+ *    N_VNew_Raja
+ *    N_VNewEmpty_Raja
+ *    N_VMake_Raja
+ *    N_VCloneVectorArray_Raja
+ *    N_VCloneVectorArrayEmpty_Raja
+ * DESTRUCTORS:
+ *    N_VDestroy_Raja
+ *    N_VDestroyVectorArray_Raja
+ * OTHER:
+ *    N_VGetLength_Raja
+ *    N_VGetHostArrayPointer_Raja
+ *    N_VGetDeviceArrayPointer_Raja
+ *    N_VPrint_Raja
+ *    N_VPrintFile_Raja
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNew_Raja
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a RAJA vector.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNew_Raja(sunindextype vec_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VNewEmpty_Raja
+ * -----------------------------------------------------------------
+ * This function creates a new RAJA N_Vector with an empty (NULL)
+ * data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VNewEmpty_Raja(sunindextype vec_length);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VMake_Raja
+ * -----------------------------------------------------------------
+ * This function creates and allocates memory for a RAJA vector
+ * with a user-supplied data array.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector N_VMake_Raja(N_VectorContent_Raja c);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArray_Raja
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' RAJA vectors by
+ * cloning a given vector w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArray_Raja(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCloneVectorArrayEmpty_Raja
+ * -----------------------------------------------------------------
+ * This function creates an array of 'count' RAJA vectors each
+ * with an empty (NULL) data array by cloning w.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector *N_VCloneVectorArrayEmpty_Raja(int count, N_Vector w);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VDestroyVectorArray_Raja
+ * -----------------------------------------------------------------
+ * This function frees an array of RAJA vectors created with 
+ * N_VCloneVectorArray_Raja or N_VCloneVectorArrayEmpty_Raja.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VDestroyVectorArray_Raja(N_Vector *vs, int count);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VGetLength_Raja
+ * -----------------------------------------------------------------
+ * This function returns the length of the vector.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT sunindextype N_VGetLength_Raja(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VGetHostArrayPointer_Raja
+ * -----------------------------------------------------------------
+ * This function returns pointer to the host raw data.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype *N_VGetHostArrayPointer_Raja(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VGetDeviceArrayPointer_Raja
+ * -----------------------------------------------------------------
+ * This function returns pointer to the device raw data.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT realtype *N_VGetDeviceArrayPointer_Raja(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCopyTotDevice_Raja
+ * -----------------------------------------------------------------
+ * This function copies host data to the device.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VCopyToDevice_Raja(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VCopyTotDevice_Raja
+ * -----------------------------------------------------------------
+ * This function copies vector data from the device to the host.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VCopyFromDevice_Raja(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VPrint_Raja
+ * -----------------------------------------------------------------
+ * This function prints the content of a RAJA vector to stdout.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrint_Raja(N_Vector v);
+
+/*
+ * -----------------------------------------------------------------
+ * Function : N_VPrintFile_Raja
+ * -----------------------------------------------------------------
+ * This function prints the content of a RAJA vector to outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_Raja(N_Vector v, FILE *outfile);
+
+/*
+ * -----------------------------------------------------------------
+ * RAJA implementations of various useful vector operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID_Raja(N_Vector v);
+SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Raja(N_Vector w);
+SUNDIALS_EXPORT N_Vector N_VClone_Raja(N_Vector w);
+SUNDIALS_EXPORT void N_VDestroy_Raja(N_Vector v);
+SUNDIALS_EXPORT void N_VSpace_Raja(N_Vector v, sunindextype *lrw, sunindextype *liw);
+SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Raja(N_Vector v);
+SUNDIALS_EXPORT void N_VSetArrayPointer_Raja(realtype *v_data, N_Vector v);
+SUNDIALS_EXPORT void N_VLinearSum_Raja(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VConst_Raja(realtype c, N_Vector z);
+SUNDIALS_EXPORT void N_VProd_Raja(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VDiv_Raja(N_Vector x, N_Vector y, N_Vector z);
+SUNDIALS_EXPORT void N_VScale_Raja(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAbs_Raja(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VInv_Raja(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT void N_VAddConst_Raja(N_Vector x, realtype b, N_Vector z);
+SUNDIALS_EXPORT realtype N_VDotProd_Raja(N_Vector x, N_Vector y);
+SUNDIALS_EXPORT realtype N_VMaxNorm_Raja(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWrmsNorm_Raja(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VWrmsNormMask_Raja(N_Vector x, N_Vector w, N_Vector id);
+SUNDIALS_EXPORT realtype N_VMin_Raja(N_Vector x);
+SUNDIALS_EXPORT realtype N_VWL2Norm_Raja(N_Vector x, N_Vector w);
+SUNDIALS_EXPORT realtype N_VL1Norm_Raja(N_Vector x);
+SUNDIALS_EXPORT void N_VCompare_Raja(realtype c, N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VInvTest_Raja(N_Vector x, N_Vector z);
+SUNDIALS_EXPORT booleantype N_VConstrMask_Raja(N_Vector c, N_Vector x, N_Vector m);
+SUNDIALS_EXPORT realtype N_VMinQuotient_Raja(N_Vector num, N_Vector denom);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/nvector/nvector_serial.h b/include/nvector/nvector_serial.h
index a943707..a7e071b 100644
--- a/include/nvector/nvector_serial.h
+++ b/include/nvector/nvector_serial.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4867 $
- * $Date: 2016-08-19 10:05:14 -0700 (Fri, 19 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
  *                and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -48,8 +44,7 @@
  *
  *     (which stores the result of the operation a*x+b*y in y)
  *     is legal.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _NVECTOR_SERIAL_H
 #define _NVECTOR_SERIAL_H
@@ -72,7 +67,7 @@ extern "C" {
    the data */
 
 struct _N_VectorContent_Serial {
-  long int length;
+  sunindextype length;
   booleantype own_data;
   realtype *data;
 };
@@ -88,7 +83,7 @@ typedef struct _N_VectorContent_Serial *N_VectorContent_Serial;
  * are assumed:
  *
  * N_Vector v;
- * long int i;
+ * sunindextype i;
  *
  * (1) NV_CONTENT_S
  *
@@ -154,6 +149,7 @@ typedef struct _N_VectorContent_Serial *N_VectorContent_Serial;
  * OTHER:
  *    N_VGetLength_Serial
  *    N_VPrint_Serial
+ *    N_VPrintFile_Serial
  * -----------------------------------------------------------------
  */
 
@@ -165,7 +161,7 @@ typedef struct _N_VectorContent_Serial *N_VectorContent_Serial;
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VNew_Serial(long int vec_length);
+SUNDIALS_EXPORT N_Vector N_VNew_Serial(sunindextype vec_length);
 
 /*
  * -----------------------------------------------------------------
@@ -176,7 +172,7 @@ SUNDIALS_EXPORT N_Vector N_VNew_Serial(long int vec_length);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(long int vec_length);
+SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(sunindextype vec_length);
 
 /*
  * -----------------------------------------------------------------
@@ -187,7 +183,7 @@ SUNDIALS_EXPORT N_Vector N_VNewEmpty_Serial(long int vec_length);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT N_Vector N_VMake_Serial(long int vec_length, realtype *v_data);
+SUNDIALS_EXPORT N_Vector N_VMake_Serial(sunindextype vec_length, realtype *v_data);
 
 /*
  * -----------------------------------------------------------------
@@ -230,7 +226,7 @@ SUNDIALS_EXPORT void N_VDestroyVectorArray_Serial(N_Vector *vs, int count);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int N_VGetLength_Serial(N_Vector v);
+SUNDIALS_EXPORT sunindextype N_VGetLength_Serial(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
@@ -244,6 +240,16 @@ SUNDIALS_EXPORT void N_VPrint_Serial(N_Vector v);
 
 /*
  * -----------------------------------------------------------------
+ * Function : N_VPrintFile_Serial
+ * -----------------------------------------------------------------
+ * This function prints the content of a serial vector to outfile.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void N_VPrintFile_Serial(N_Vector v, FILE *outfile);
+
+/*
+ * -----------------------------------------------------------------
  * serial implementations of various useful vector operations
  * -----------------------------------------------------------------
  */
@@ -252,7 +258,7 @@ SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID_Serial(N_Vector v);
 SUNDIALS_EXPORT N_Vector N_VCloneEmpty_Serial(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VClone_Serial(N_Vector w);
 SUNDIALS_EXPORT void N_VDestroy_Serial(N_Vector v);
-SUNDIALS_EXPORT void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw);
+SUNDIALS_EXPORT void N_VSpace_Serial(N_Vector v, sunindextype *lrw, sunindextype *liw);
 SUNDIALS_EXPORT realtype *N_VGetArrayPointer_Serial(N_Vector v);
 SUNDIALS_EXPORT void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v);
 SUNDIALS_EXPORT void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
diff --git a/include/nvector/raja/Vector.hpp b/include/nvector/raja/Vector.hpp
new file mode 100644
index 0000000..1f34668
--- /dev/null
+++ b/include/nvector/raja/Vector.hpp
@@ -0,0 +1,157 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ */
+
+
+/**
+ * Vector class
+ *
+ * Manages vector data layout for RAJA implementation of N_Vector.
+ *
+ */
+
+#ifndef _NVECTOR_RAJA_HPP_
+#define _NVECTOR_RAJA_HPP_
+
+#include <cstdlib>
+#include <iostream>
+
+#include <nvector/nvector_raja.h>
+
+namespace sunrajavec
+{
+
+template <typename T, typename I>
+class Vector : public _N_VectorContent_Raja
+{
+public:
+  Vector(I N) : size_(N), mem_size_(N*sizeof(T))
+  {
+    allocate();
+  }
+
+  /// Copy constructor does not copy values
+  explicit Vector(const Vector& v)
+  : size_(v.size()),
+    mem_size_(size_*sizeof(T))
+  {
+    allocate();
+  }
+
+  ~Vector()
+  {
+    clear();
+  }
+
+
+  void allocate()
+  {
+    cudaError_t err;
+    h_vec_ = static_cast<T*>(malloc(mem_size_));
+    if(h_vec_ == NULL)
+      std::cout << "Failed to allocate host vector!\n";
+    err = cudaMalloc((void**) &d_vec_, mem_size_);
+    if(err != cudaSuccess)
+      std::cout << "Failed to allocate device vector (error code " << err << ")!\n";
+  }
+
+  void clear()
+  {
+    cudaError_t err;
+    free(h_vec_);
+    err = cudaFree(d_vec_);
+    if(err != cudaSuccess)
+      std::cout << "Failed to free device vector (error code " << err << ")!\n";
+  }
+
+  int size() const
+  {
+    return size_;
+  }
+
+  T* host()
+  {
+    return h_vec_;
+  }
+
+  const T* host() const
+  {
+    return h_vec_;
+  }
+
+  T* device()
+  {
+    return d_vec_;
+  }
+
+  const T* device() const
+  {
+    return d_vec_;
+  }
+
+  void copyToDev()
+  {
+    cudaError_t err = cudaMemcpy(d_vec_, h_vec_, mem_size_, cudaMemcpyHostToDevice);
+    if(err != cudaSuccess)
+      std::cout << "Failed to copy vector from host to device (error code " << err << ")!\n";
+  }
+
+  void copyFromDev()
+  {
+    cudaError_t err = cudaMemcpy(h_vec_, d_vec_, mem_size_, cudaMemcpyDeviceToHost);
+    if(err != cudaSuccess)
+      std::cout << "Failed to copy vector from device to host (error code " << err << ")!\n";
+  }
+
+private:
+  I size_;
+  I mem_size_;
+  T* h_vec_;
+  T* d_vec_;
+};
+
+
+
+
+
+// Extract Vector from N_Vector
+template <typename T, typename I>
+inline Vector<T, I>* extract(N_Vector v)
+{
+  return static_cast<Vector<T, I>*>(v->content);
+}
+
+// Get Vector device data
+template <typename T, typename I>
+inline T* getDevData(N_Vector v)
+{
+  Vector<T,I>* vp = static_cast<Vector<T, I>*>(v->content);
+  return vp->device();
+}
+
+// Get Vector length
+template <typename T, typename I>
+inline I getSize(N_Vector v)
+{
+  Vector<T,I>* vp = static_cast<Vector<T, I>*>(v->content);
+  return vp->size();
+}
+
+
+} // namespace sunrajavec
+
+
+
+#endif // _NVECTOR_RAJA_HPP_
diff --git a/include/sundials/sundials_band.h b/include/sundials/sundials_band.h
index e6593c0..3a27186 100644
--- a/include/sundials/sundials_band.h
+++ b/include/sundials/sundials_band.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4780 $
- * $Date: 2016-06-22 17:28:19 -0700 (Wed, 22 Jun 2016) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -81,9 +81,9 @@ extern "C" {
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int BandGBTRF(DlsMat A, long int *p);
-SUNDIALS_EXPORT long int bandGBTRF(realtype **a, long int n, long int mu, long int ml,
-                                   long int smu, long int *p);
+SUNDIALS_EXPORT sunindextype BandGBTRF(DlsMat A, sunindextype *p);
+SUNDIALS_EXPORT sunindextype bandGBTRF(realtype **a, sunindextype n, sunindextype mu, sunindextype ml,
+                                   sunindextype smu, sunindextype *p);
 
 /*
  * -----------------------------------------------------------------
@@ -102,9 +102,9 @@ SUNDIALS_EXPORT long int bandGBTRF(realtype **a, long int n, long int mu, long i
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT void BandGBTRS(DlsMat A, long int *p, realtype *b);
-SUNDIALS_EXPORT void bandGBTRS(realtype **a, long int n, long int smu,
-                               long int ml, long int *p, realtype *b);
+SUNDIALS_EXPORT void BandGBTRS(DlsMat A, sunindextype *p, realtype *b);
+SUNDIALS_EXPORT void bandGBTRS(realtype **a, sunindextype n, sunindextype smu,
+                               sunindextype ml, sunindextype *p, realtype *b);
 
 /*
  * -----------------------------------------------------------------
@@ -121,10 +121,10 @@ SUNDIALS_EXPORT void bandGBTRS(realtype **a, long int n, long int smu,
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT void BandCopy(DlsMat A, DlsMat B, long int copymu, long int copyml);
-SUNDIALS_EXPORT void bandCopy(realtype **a, realtype **b, long int n,
-                              long int a_smu, long int b_smu,
-			      long int copymu, long int copyml);
+SUNDIALS_EXPORT void BandCopy(DlsMat A, DlsMat B, sunindextype copymu, sunindextype copyml);
+SUNDIALS_EXPORT void bandCopy(realtype **a, realtype **b, sunindextype n,
+                              sunindextype a_smu, sunindextype b_smu,
+			      sunindextype copymu, sunindextype copyml);
 
 /*
  * -----------------------------------------------------------------
@@ -141,7 +141,7 @@ SUNDIALS_EXPORT void bandCopy(realtype **a, realtype **b, long int n,
  */
 
 SUNDIALS_EXPORT void BandScale(realtype c, DlsMat A);
-SUNDIALS_EXPORT void bandScale(realtype c, realtype **a, long int n, long int mu, long int ml, long int smu);
+SUNDIALS_EXPORT void bandScale(realtype c, realtype **a, sunindextype n, sunindextype mu, sunindextype ml, sunindextype smu);
 
 /*
  * -----------------------------------------------------------------
@@ -152,7 +152,7 @@ SUNDIALS_EXPORT void bandScale(realtype c, realtype **a, long int n, long int mu
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT void bandAddIdentity(realtype **a, long int n, long int smu);
+SUNDIALS_EXPORT void bandAddIdentity(realtype **a, sunindextype n, sunindextype smu);
 
 
 /*
@@ -170,8 +170,8 @@ SUNDIALS_EXPORT void bandAddIdentity(realtype **a, long int n, long int smu);
  */
 
 SUNDIALS_EXPORT void BandMatvec(DlsMat A, realtype *x, realtype *y);
-SUNDIALS_EXPORT void bandMatvec(realtype **a, realtype *x, realtype *y, long int n, 
-		long int mu, long int ml, long int smu);
+SUNDIALS_EXPORT void bandMatvec(realtype **a, realtype *x, realtype *y, sunindextype n, 
+		sunindextype mu, sunindextype ml, sunindextype smu);
 
 #ifdef __cplusplus
 }
diff --git a/include/sundials/sundials_config.in b/include/sundials/sundials_config.in
index 1e06ccd..82aee5f 100644
--- a/include/sundials/sundials_config.in
+++ b/include/sundials/sundials_config.in
@@ -1,21 +1,20 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4895 $
- * $Date: 2016-09-05 16:57:24 -0700 (Mon, 05 Sep 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Aaron Collier and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * Copyright (c) 2005, The Regents of the University of California.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
  * For details, see the LICENSE file.
- *------------------------------------------------------------------
+ * -----------------------------------------------------------------
  * SUNDIALS configuration header file
- *------------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
-/* Define SUNDIALS version number */
-#define SUNDIALS_PACKAGE_VERSION "@PACKAGE_VERSION@"
+/* Define SUNDIALS version numbers */
+#define SUNDIALS_VERSION "@PACKAGE_VERSION@"
+#define SUNDIALS_VERSION_MAJOR @PACKAGE_VERSION_MAJOR@
+#define SUNDIALS_VERSION_MINOR @PACKAGE_VERSION_MINOR@
+#define SUNDIALS_VERSION_PATCH @PACKAGE_VERSION_PATCH@
+#define SUNDIALS_VERSION_LABEL "@PACKAGE_VERSION_LABEL@"
 
 /* FCMIX: Define Fortran name-mangling macro for C identifiers.
  * Depending on the inferred scheme, one of the following six
@@ -43,6 +42,14 @@
  */
 @PRECISION_LEVEL@
 
+/* Define type of vector indices in SUNDIALS 'sunindextype'. 
+ * Depending on user choice of index type, one of the following 
+ * two macros will be defined:
+ *     #define SUNDIALS_INT64_T 1
+ *     #define SUNDIALS_INT32_T 1
+ */
+ at INDEX_TYPE@
+
 /* Use generic math functions 
  * If it was decided that generic math functions can be used, then
  *     #define SUNDIALS_USE_GENERIC_MATH
diff --git a/include/sundials/sundials_dense.h b/include/sundials/sundials_dense.h
index 30411a1..60088ad 100644
--- a/include/sundials/sundials_dense.h
+++ b/include/sundials/sundials_dense.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4780 $
- * $Date: 2016-06-22 17:28:19 -0700 (Wed, 22 Jun 2016) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer: Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -78,11 +78,11 @@ extern "C" {
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int DenseGETRF(DlsMat A, long int *p);
-SUNDIALS_EXPORT void DenseGETRS(DlsMat A, long int *p, realtype *b);
+SUNDIALS_EXPORT sunindextype DenseGETRF(DlsMat A, sunindextype *p);
+SUNDIALS_EXPORT void DenseGETRS(DlsMat A, sunindextype *p, realtype *b);
 
-SUNDIALS_EXPORT long int denseGETRF(realtype **a, long int m, long int n, long int *p);
-SUNDIALS_EXPORT void denseGETRS(realtype **a, long int n, long int *p, realtype *b);
+SUNDIALS_EXPORT sunindextype denseGETRF(realtype **a, sunindextype m, sunindextype n, sunindextype *p);
+SUNDIALS_EXPORT void denseGETRS(realtype **a, sunindextype n, sunindextype *p, realtype *b);
 
 /*
  * -----------------------------------------------------------------
@@ -102,11 +102,11 @@ SUNDIALS_EXPORT void denseGETRS(realtype **a, long int n, long int *p, realtype
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int DensePOTRF(DlsMat A);
+SUNDIALS_EXPORT sunindextype DensePOTRF(DlsMat A);
 SUNDIALS_EXPORT void DensePOTRS(DlsMat A, realtype *b);
 
-SUNDIALS_EXPORT long int densePOTRF(realtype **a, long int m);
-SUNDIALS_EXPORT void densePOTRS(realtype **a, long int m, realtype *b);
+SUNDIALS_EXPORT sunindextype densePOTRF(realtype **a, sunindextype m);
+SUNDIALS_EXPORT void densePOTRS(realtype **a, sunindextype m, realtype *b);
 
 /*
  * -----------------------------------------------------------------
@@ -138,9 +138,9 @@ SUNDIALS_EXPORT int DenseGEQRF(DlsMat A, realtype *beta, realtype *wrk);
 SUNDIALS_EXPORT int DenseORMQR(DlsMat A, realtype *beta, realtype *vn, realtype *vm, 
 			       realtype *wrk);
 
-SUNDIALS_EXPORT int denseGEQRF(realtype **a, long int m, long int n, realtype *beta,
+SUNDIALS_EXPORT int denseGEQRF(realtype **a, sunindextype m, sunindextype n, realtype *beta,
                                realtype *wrk);
-SUNDIALS_EXPORT int denseORMQR(realtype **a, long int m, long int n, realtype *beta,
+SUNDIALS_EXPORT int denseORMQR(realtype **a, sunindextype m, sunindextype n, realtype *beta,
 			       realtype *v, realtype *w, realtype *wrk);
 
 /*
@@ -156,7 +156,7 @@ SUNDIALS_EXPORT int denseORMQR(realtype **a, long int m, long int n, realtype *b
  */
 
 SUNDIALS_EXPORT void DenseCopy(DlsMat A, DlsMat B);
-SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, long int m, long int n);
+SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, sunindextype m, sunindextype n);
 
 /*
  * -----------------------------------------------------------------
@@ -171,7 +171,7 @@ SUNDIALS_EXPORT void denseCopy(realtype **a, realtype **b, long int m, long int
  */
 
 SUNDIALS_EXPORT void DenseScale(realtype c, DlsMat A);
-SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, long int m, long int n);
+SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, sunindextype m, sunindextype n);
 
 
 /*
@@ -183,7 +183,7 @@ SUNDIALS_EXPORT void denseScale(realtype c, realtype **a, long int m, long int n
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT void denseAddIdentity(realtype **a, long int n);
+SUNDIALS_EXPORT void denseAddIdentity(realtype **a, sunindextype n);
 
 
 /*
@@ -201,7 +201,7 @@ SUNDIALS_EXPORT void denseAddIdentity(realtype **a, long int n);
  */
 
 SUNDIALS_EXPORT void DenseMatvec(DlsMat A, realtype *x, realtype *y);
-SUNDIALS_EXPORT void denseMatvec(realtype **a, realtype *x, realtype *y, long int m, long int n);
+SUNDIALS_EXPORT void denseMatvec(realtype **a, realtype *x, realtype *y, sunindextype m, sunindextype n);
 
 
 #ifdef __cplusplus
diff --git a/include/sundials/sundials_direct.h b/include/sundials/sundials_direct.h
index 23984b4..8bcc089 100644
--- a/include/sundials/sundials_direct.h
+++ b/include/sundials/sundials_direct.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4780 $
- * $Date: 2016-06-22 17:28:19 -0700 (Wed, 22 Jun 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer: Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -18,8 +14,7 @@
  * This header file contains definitions and declarations for use by
  * generic direct linear solvers for Ax = b. It defines types for
  * dense and banded matrices and corresponding accessor macros.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _SUNDIALS_DIRECT_H
 #define _SUNDIALS_DIRECT_H
@@ -118,14 +113,14 @@ extern "C" {
 
 typedef struct _DlsMat {
   int type;
-  long int M;
-  long int N;
-  long int ldim;
-  long int mu;
-  long int ml;
-  long int s_mu;
+  sunindextype M;
+  sunindextype N;
+  sunindextype ldim;
+  sunindextype mu;
+  sunindextype ml;
+  sunindextype s_mu;
   realtype *data;
-  long int ldata;
+  sunindextype ldata;
   realtype **cols;
 } *DlsMat;
 
@@ -199,7 +194,7 @@ typedef struct _DlsMat {
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT DlsMat NewDenseMat(long int M, long int N);
+SUNDIALS_EXPORT DlsMat NewDenseMat(sunindextype M, sunindextype N);
 
 /*
  * -----------------------------------------------------------------
@@ -221,7 +216,7 @@ SUNDIALS_EXPORT DlsMat NewDenseMat(long int M, long int N);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT DlsMat NewBandMat(long int N, long int mu, long int ml, long int smu);
+SUNDIALS_EXPORT DlsMat NewBandMat(sunindextype N, sunindextype mu, sunindextype ml, sunindextype smu);
 
 /*
  * -----------------------------------------------------------------
@@ -247,15 +242,15 @@ SUNDIALS_EXPORT int *NewIntArray(int N);
 
 /*
  * -----------------------------------------------------------------
- * Function: NewLintArray
+ * Function: NewIndexArray
  * -----------------------------------------------------------------
- * NewLintArray allocates memory an array of N long int's and returns
- * the pointer to the memory it allocates. If the request for
- * memory storage cannot be satisfied, it returns NULL.
+ * NewIndexArray allocates memory an array of N sunindextype's and
+ * returns the pointer to the memory it allocates. If the request
+ * for memory storage cannot be satisfied, it returns NULL.
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT long int *NewLintArray(long int N);
+SUNDIALS_EXPORT sunindextype *NewIndexArray(sunindextype N);
 
 /*
  * -----------------------------------------------------------------
@@ -267,13 +262,13 @@ SUNDIALS_EXPORT long int *NewLintArray(long int N);
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT realtype *NewRealArray(long int N);
+SUNDIALS_EXPORT realtype *NewRealArray(sunindextype N);
 
 /*
  * -----------------------------------------------------------------
  * Function: DestroyArray
  * -----------------------------------------------------------------
- * DestroyArray frees memory allocated by NewIntArray, NewLintArray,
+ * DestroyArray frees memory allocated by NewIntArray, NewIndexArray,
  * or NewRealArray.
  * -----------------------------------------------------------------
  */
@@ -309,14 +304,14 @@ SUNDIALS_EXPORT void SetToZero(DlsMat A);
  * Functions: PrintMat
  * -----------------------------------------------------------------
  * This function prints the M-by-N (dense or band) matrix A to
- * standard output as it would normally appear on paper.
+ * outfile as it would normally appear on paper.
  * It is intended as debugging tools with small values of M and N.
  * The elements are printed using the %g/%lg/%Lg option. 
  * A blank line is printed before and after the matrix.
  * -----------------------------------------------------------------
  */
 
-SUNDIALS_EXPORT void PrintMat(DlsMat A);
+SUNDIALS_EXPORT void PrintMat(DlsMat A, FILE *outfile);
 
 
 /*
@@ -325,12 +320,12 @@ SUNDIALS_EXPORT void PrintMat(DlsMat A);
  * ==================================================================
  */
 
-SUNDIALS_EXPORT realtype **newDenseMat(long int m, long int n);
-SUNDIALS_EXPORT realtype **newBandMat(long int n, long int smu, long int ml);
+SUNDIALS_EXPORT realtype **newDenseMat(sunindextype m, sunindextype n);
+SUNDIALS_EXPORT realtype **newBandMat(sunindextype n, sunindextype smu, sunindextype ml);
 SUNDIALS_EXPORT void destroyMat(realtype **a);
 SUNDIALS_EXPORT int *newIntArray(int n);
-SUNDIALS_EXPORT long int *newLintArray(long int n);
-SUNDIALS_EXPORT realtype *newRealArray(long int m);
+SUNDIALS_EXPORT sunindextype *newIndexArray(sunindextype n);
+SUNDIALS_EXPORT realtype *newRealArray(sunindextype m);
 SUNDIALS_EXPORT void destroyArray(void *v);
 
 
diff --git a/include/sundials/sundials_fconfig.in b/include/sundials/sundials_fconfig.in
new file mode 100644
index 0000000..f699461
--- /dev/null
+++ b/include/sundials/sundials_fconfig.in
@@ -0,0 +1,56 @@
+!
+! ----------------------------------------------------------------- 
+! Programmer(s): Daniel R. Reynolds @ SMU
+!-----------------------------------------------------------------
+! LLNS/SMU Copyright Start
+! Copyright (c) 2015, Southern Methodist University and 
+! Lawrence Livermore National Security
+!
+! This work was performed under the auspices of the U.S. Department 
+! of Energy by Southern Methodist University and Lawrence Livermore 
+! National Laboratory under Contract DE-AC52-07NA27344.
+! Produced at Southern Methodist University and the Lawrence 
+! Livermore National Laboratory.
+!
+! All rights reserved.
+! For details, see the LICENSE file.
+! LLNS/SMU Copyright End
+! Copyright (c) 2013, Southern Methodist University.
+! All rights reserved.
+! For details, see the LICENSE file.
+! ------------------------------------------------------------------
+! SUNDIALS fortran configuration input
+! ------------------------------------------------------------------
+
+!     Define precision of SUNDIALS data type 'realtype' as Fortran 
+!     parameter "REALTYPE"
+!
+!     Depending on the precision level, this value will be one of
+!          4  (SUNDIALS_SINGLE_PRECISION)
+!          8  (SUNDIALS_DOUBLE_PRECISION)
+!         16  (SUNDIALS_EXTENDED_PRECISION)
+!
+integer REALTYPE
+parameter (REALTYPE=@FPRECISION_LEVEL@)
+
+!     Define type of vector indices in SUNDIALS 'sunindextype' as 
+!     the Fortran parameter "SUNINDEXTYPE"
+!
+!     Depending on the user choice of indextype, this will be one of
+!          4  (32BIT)
+!          8  (64BIT)
+!
+integer SUNINDEXTYPE
+parameter (SUNINDEXTYPE=@FINDEX_TYPE@)
+
+!     If building with MPI enabled, define the logical flag 
+!     "SUNDIALS_MPI_COMM_F2C" indicating whether the user can specify
+!     a different MPI communicator than MPI_COMM_WORLD to FNVInitP
+!
+!          .true.   (communicator can differ from MPI_COMM_WORLD)
+!          .false.  (communicator must be MPI_COMM_WORLD)
+!
+!      logical SUNDIALS_MPI_COMM_F2C
+!      parameter (SUNDIALS_MPI_COMM_F2C=)
+ at FMPI_COMM_F2C_1@
+ at FMPI_COMM_F2C_2@
\ No newline at end of file
diff --git a/include/sundials/sundials_fnvector.h b/include/sundials/sundials_fnvector.h
index 0128266..b64b7da 100644
--- a/include/sundials/sundials_fnvector.h
+++ b/include/sundials/sundials_fnvector.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
diff --git a/include/sundials/sundials_iterative.h b/include/sundials/sundials_iterative.h
index fe4118a..6312bdd 100644
--- a/include/sundials/sundials_iterative.h
+++ b/include/sundials/sundials_iterative.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen and Alan C. Hindmarsh @ LLNL
  * -----------------------------------------------------------------
@@ -21,7 +21,8 @@
  * The function type declarations give the prototypes for the
  * functions to be called within an iterative linear solver, that
  * are responsible for
- *    multiplying A by a given vector v (ATimesFn), and
+ *    multiplying A by a given vector v (ATimesFn), 
+ *    setting up a preconditioner P (PSetupFn), and
  *    solving the preconditioner equation Pz = r (PSolveFn).
  * -----------------------------------------------------------------
  */
@@ -87,6 +88,19 @@ enum { MODIFIED_GS = 1, CLASSICAL_GS = 2 };
 
 typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z);
 
+/* 
+ * -----------------------------------------------------------------
+ * Type: PSetupFn
+ * -----------------------------------------------------------------
+ * A PSetupFn is an integrator-supplied routine that accesses data
+ * stored in the integrator memory structure (P_data), and calls 
+ * the user-supplied, integrator-specific preconditioner setup 
+ * routine. 
+ * -----------------------------------------------------------------
+ */
+ 
+typedef int (*PSetupFn)(void *P_data);
+
 /*
  * -----------------------------------------------------------------
  * Type: PSolveFn                                                 
@@ -99,7 +113,12 @@ typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z);
  * is to be taken as the left preconditioner or the right         
  * preconditioner: lr = 1 for left and lr = 2 for right.          
  * If preconditioning is on one side only, lr can be ignored.     
- * The vector r is unchanged.                                     
+ * If the preconditioner is iterative, then it should strive to 
+ * solve the preconditioner equation so that
+ *     || Pz - r ||_wrms < tol
+ * where the weight vector for the WRMS norm may be accessed from 
+ * the main integrator memory structure.
+ * The vector r should not be modified by the PSolveFn.
  * A PSolveFn returns 0 if successful and a non-zero value if     
  * unsuccessful.  On a failure, a negative return value indicates 
  * an unrecoverable condition, while a positive value indicates   
@@ -108,7 +127,8 @@ typedef int (*ATimesFn)(void *A_data, N_Vector v, N_Vector z);
  * -----------------------------------------------------------------
  */
 
-typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z, int lr);
+typedef int (*PSolveFn)(void *P_data, N_Vector r, N_Vector z,
+                        realtype tol, int lr);
 
 /*
  * -----------------------------------------------------------------
diff --git a/include/sundials/sundials_klu_impl.h b/include/sundials/sundials_klu_impl.h
index 3271bc5..2b2463b 100644
--- a/include/sundials/sundials_klu_impl.h
+++ b/include/sundials/sundials_klu_impl.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Carol S. Woodward @ LLNL
  * -----------------------------------------------------------------
diff --git a/include/sundials/sundials_lapack.h b/include/sundials/sundials_lapack.h
index 08fcdaf..9a2b73c 100644
--- a/include/sundials/sundials_lapack.h
+++ b/include/sundials/sundials_lapack.h
@@ -1,9 +1,10 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer: Radu Serban @ LLNL
+ *             Daniel Reynolds @ SMU
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -51,6 +52,22 @@ extern "C" {
 #define dpotrf_f77      SUNDIALS_F77_FUNC(dpotrf, DPOTRF)
 #define dpotrs_f77      SUNDIALS_F77_FUNC(dpotrs, DPOTRS)
 
+#define scopy_f77       SUNDIALS_F77_FUNC(scopy, SCOPY)
+#define sscal_f77       SUNDIALS_F77_FUNC(sscal, SSCAL)
+#define sgemv_f77       SUNDIALS_F77_FUNC(sgemv, SGEMV)
+#define strsv_f77       SUNDIALS_F77_FUNC(strsv, STRSV)
+#define ssyrk_f77       SUNDIALS_F77_FUNC(ssyrk, SSKYR)
+
+#define sgbtrf_f77      SUNDIALS_F77_FUNC(sgbtrf, SGBTRF)
+#define sgbtrs_f77      SUNDIALS_F77_FUNC(sgbtrs, SGBTRS)
+#define sgetrf_f77      SUNDIALS_F77_FUNC(sgetrf, SGETRF)
+#define sgetrs_f77      SUNDIALS_F77_FUNC(sgetrs, SGETRS)
+#define sgeqp3_f77      SUNDIALS_F77_FUNC(sgeqp3, SGEQP3)
+#define sgeqrf_f77      SUNDIALS_F77_FUNC(sgeqrf, SGEQRF)
+#define sormqr_f77      SUNDIALS_F77_FUNC(sormqr, SORMQR)
+#define spotrf_f77      SUNDIALS_F77_FUNC(spotrf, SPOTRF)
+#define spotrs_f77      SUNDIALS_F77_FUNC(spotrs, SPOTRS)
+
 #else
 
 #define dcopy_f77       dcopy_
@@ -69,6 +86,22 @@ extern "C" {
 #define dpotrf_f77      dpotrf_
 #define dpotrs_f77      dpotrs_
 
+#define scopy_f77       scopy_
+#define sscal_f77       sscal_
+#define sgemv_f77       sgemv_
+#define strsv_f77       strsv_
+#define ssyrk_f77       ssyrk_
+
+#define sgbtrf_f77      sgbtrf_
+#define sgbtrs_f77      sgbtrs_
+#define sgeqp3_f77      sgeqp3_
+#define sgeqrf_f77      sgeqrf_
+#define sgetrf_f77      sgetrf_
+#define sgetrs_f77      sgetrs_
+#define sormqr_f77      sormqr_
+#define spotrf_f77      spotrf_
+#define spotrs_f77      spotrs_
+  
 #endif
 
 /* Level-1 BLAS */
@@ -76,6 +109,9 @@ extern "C" {
 extern void dcopy_f77(int *n, const double *x, const int *inc_x, double *y, const int *inc_y);
 extern void dscal_f77(int *n, const double *alpha, double *x, const int *inc_x);
 
+extern void scopy_f77(int *n, const float *x, const int *inc_x, float *y, const int *inc_y);
+extern void sscal_f77(int *n, const float *alpha, float *x, const int *inc_x);
+  
 /* Level-2 BLAS */
 
 extern void dgemv_f77(const char *trans, int *m, int *n, const double *alpha, const double *a, 
@@ -86,11 +122,23 @@ extern void dtrsv_f77(const char *uplo, const char *trans, const char *diag, con
 		      const double *a, const int *lda, double *x, const int *inc_x, 
 		      int len_uplo, int len_trans, int len_diag);
 
+extern void sgemv_f77(const char *trans, int *m, int *n, const float *alpha, const float *a, 
+		      int *lda, const float *x, int *inc_x, const float *beta, float *y, int *inc_y, 
+		      int len_trans);
+
+extern void strsv_f77(const char *uplo, const char *trans, const char *diag, const int *n, 
+		      const float *a, const int *lda, float *x, const int *inc_x, 
+		      int len_uplo, int len_trans, int len_diag);
+  
 /* Level-3 BLAS */
 
 extern void dsyrk_f77(const char *uplo, const char *trans, const int *n, const int *k, 
 		      const double *alpha, const double *a, const int *lda, const double *beta, 
 		      const double *c, const int *ldc, int len_uplo, int len_trans);
+
+extern void ssyrk_f77(const char *uplo, const char *trans, const int *n, const int *k, 
+		      const float *alpha, const float *a, const int *lda, const float *beta, 
+		      const float *c, const int *ldc, int len_uplo, int len_trans);
   
 /* LAPACK */
 
@@ -124,6 +172,36 @@ extern void dpotrs_f77(const char *uplo, const int *n, const int *nrhs, double *
 		       double *b, const int *ldb, int * info, int len_uplo);
 
 
+extern void sgbtrf_f77(const int *m, const int *n, const int *kl, const int *ku, 
+		       float *ab, int *ldab, int *ipiv, int *info);
+
+extern void sgbtrs_f77(const char *trans, const int *n, const int *kl, const int *ku, const int *nrhs, 
+		       float *ab, const int *ldab, int *ipiv, float *b, const int *ldb, 
+		       int *info, int len_trans);
+
+
+extern void sgeqp3_f77(const int *m, const int *n, float *a, const int *lda, int *jpvt, float *tau, 
+		       float *work, const int *lwork, int *info);
+
+extern void sgeqrf_f77(const int *m, const int *n, float *a, const int *lda, float *tau, float *work, 
+		       const int *lwork, int *info);
+
+extern void sgetrf_f77(const int *m, const int *n, float *a, int *lda, int *ipiv, int *info);
+
+extern void sgetrs_f77(const char *trans, const int *n, const int *nrhs, float *a, const int *lda, 
+		       int *ipiv, float *b, const int *ldb, int *info, int len_trans);
+
+
+extern void sormqr_f77(const char *side, const char *trans, const int *m, const int *n, const int *k, 
+		       float *a, const int *lda, float *tau, float *c, const int *ldc, 
+		       float *work, const int *lwork, int *info, int len_side, int len_trans);
+
+extern void spotrf_f77(const char *uplo, const int *n, float *a, int *lda, int *info, int len_uplo);
+
+extern void spotrs_f77(const char *uplo, const int *n, const int *nrhs, float *a, const int *lda, 
+		       float *b, const int *ldb, int * info, int len_uplo);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sundials/sundials_linearsolver.h b/include/sundials/sundials_linearsolver.h
new file mode 100644
index 0000000..1de3c05
--- /dev/null
+++ b/include/sundials/sundials_linearsolver.h
@@ -0,0 +1,364 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner, Carol Woodward, Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for a generic linear solver package.
+ * It defines the SUNLinearSolver structure (_generic_SUNLinearSolver)
+ * which contains the following fields:
+ *   - an implementation-dependent 'content' field which contains
+ *     any internal data required by the solver
+ *   - an 'ops' filed which contains a structure listing operations
+ *     acting on/by such solvers
+ *
+ * We consider both direct linear solvers and iterative linear solvers
+ * as available implementations of this package; as a result some of 
+ * the routines are applicable only to one type of linear solver (as 
+ * noted in the comments below).
+ *
+ * For most of the iterative linear solvers, instead of solving the 
+ * linear system A x = b directly, we apply the underlying iterative 
+ * algorithm to the transformed system 
+ *
+ *        Abar xbar = bbar
+ *
+ * where
+ *
+ *        Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse),
+ *        bbar = S1 (P1-inverse) b,
+ *        xbar = S2 P2 x,
+ * 
+ * and where 
+ *
+ *        P1 = left preconditioner
+ *        P2 = right preconditioner
+ *        S1 = diagonal matrix of scale factors for P1-inverse b
+ *        S2 = diagonal matrix of scale factors for P2 x.
+ * 
+ * The stopping tolerance on iterative linear solvers is on the  
+ * 2-norm of the scaled preconditioned residual:
+ *      || bbar - Abar xbar ||_2  <  tol.
+ * 
+ * We note that the Preconditioned Conjugate Gradient (PCG) solver 
+ * considers S1=S2 and P1=P2 (where each is approximately A^{1/2}), and 
+ * both scaling and preconditioning are applied symmetrically and 
+ * simultaneously, so that the user-supplied S and P are in fact 
+ * S1^2 and P1^2, i.e. P is approximately A and S is the corresponding 
+ * diagonal matrix of scale factors for P.  As such, in the PCG solver the 
+ * second scaling vector and the left/right "type" of P are ignored.
+ *
+ * -----------------------------------------------------------------
+ *
+ * Part I of this file contains enumeration constants for all 
+ * SUNDIALS-defined linear solver types, as well as a generic type for 
+ * user-supplied linear solver types.
+ *
+ * Part II of this file contains type declarations for the
+ * _generic_SUNLinearSolver and _generic_SUNLinearSolver_Ops structures, 
+ * as well as references to pointers to such structures 
+ * (SUNLinearSolver).
+ *
+ * Part III of this file contains the prototypes for the linear solver
+ * functions which operate on/by SUNLinearSolver objects.
+ *
+ * At a minimum, a particular implementation of a SUNLinearSolver must
+ * do the following:
+ *  - specify the 'content' field of SUNLinearSolver,
+ *  - implement the operations on/by those SUNLinearSolver,
+ *  - provide a constructor routine for new SUNLinearSolver objects
+ *
+ * Additionally, a SUNLinearSolver implementation may provide the 
+ * following:
+ *  - "Set" routines to control solver-specific parameters/options
+ *  - "Get" routines to access solver-specific performance metrics
+ *
+ * Part IV of this file contains error codes that may be returned by
+ * SUNLinearSolver objects.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINEARSOLVER_H
+#define _SUNLINEARSOLVER_H
+ 
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_iterative.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+ 
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+ 
+  
+/*
+ * -----------------------------------------------------------------
+ * I. Implemented SUNLinearSolver types: 
+ *
+ * These type names may be modified, but a at a minimum a client 
+ * nonlinear solver and/or time integrator will want to know whether 
+ * matrix/factorization information can be reused (hence the DIRECT 
+ * and ITERATIVE types).
+ * -----------------------------------------------------------------
+ */
+ 
+typedef enum {
+  SUNLINEARSOLVER_DIRECT,
+  SUNLINEARSOLVER_ITERATIVE,
+  SUNLINEARSOLVER_CUSTOM
+} SUNLinearSolver_Type;
+
+  
+/* 
+ * -----------------------------------------------------------------
+ * II. Generic definition of SUNLinearSolver 
+ * -----------------------------------------------------------------
+ */
+ 
+/* Forward reference for pointer to SUNLinearSolver_Ops object */
+typedef struct _generic_SUNLinearSolver_Ops *SUNLinearSolver_Ops;
+ 
+/* Forward reference for pointer to SUNLinearSolver object */
+typedef struct _generic_SUNLinearSolver *SUNLinearSolver;
+ 
+/* Structure containing function pointers to linear solver operations */  
+struct _generic_SUNLinearSolver_Ops {
+  SUNLinearSolver_Type (*gettype)(SUNLinearSolver);
+  int                  (*setatimes)(SUNLinearSolver, void*, ATimesFn);
+  int                  (*setpreconditioner)(SUNLinearSolver, void*, 
+                                            PSetupFn, PSolveFn);
+  int                  (*setscalingvectors)(SUNLinearSolver,
+                                            N_Vector, N_Vector);
+  int                  (*initialize)(SUNLinearSolver);
+  int                  (*setup)(SUNLinearSolver, SUNMatrix);
+  int                  (*solve)(SUNLinearSolver, SUNMatrix, N_Vector, 
+                                N_Vector, realtype);
+  int                  (*numiters)(SUNLinearSolver);
+  realtype             (*resnorm)(SUNLinearSolver);
+  long int             (*lastflag)(SUNLinearSolver);
+  int                  (*space)(SUNLinearSolver, long int*, long int*);
+  N_Vector             (*resid)(SUNLinearSolver);
+  int                  (*free)(SUNLinearSolver);
+};
+ 
+/* A linear solver is a structure with an implementation-dependent
+   'content' field, and a pointer to a structure of linear solver
+   operations corresponding to that implementation. */
+struct _generic_SUNLinearSolver {
+  void *content;
+  struct _generic_SUNLinearSolver_Ops *ops;
+};
+
+  
+/*
+ * -----------------------------------------------------------------
+ * III. Functions exported by SUNLinearSolver module
+ * 
+ * SUNLinSolGetType
+ *   Returns an identifier for the linear solver type from 
+ *   enumeration SUNLinearSolver_Type.
+ *
+ * SUNLinSolSetATimes (iterative methods only)
+ *   Sets the function pointer for ATimes inside of an iterative 
+ *   linear solver object.  This function should only be called by a 
+ *   main integrator, who will either provide this via 
+ *   difference-quotients and vector operations, or by translating 
+ *   between the generic ATimes call and the integrator-specific, 
+ *   user-supplied routines.  This should return zero for a 
+ *   successful call, and a negative value for a failure.  Ideally, 
+ *   this should return one of the generic SUNLS_* error codes 
+ *   listed at the bottom of this file.
+ *
+ * SUNLinSolSetPreconditioner (iterative methods only)
+ *   Sets function pointers for PSetup and PSolve routines inside 
+ *   of iterative linear solver objects.  This function should only 
+ *   be called by a main integrator, who will provide translation 
+ *   between the generic PSetup and PSolve calls and the integrator-
+ *   specific user-supplied routines.  This should return
+ *   zero for a successful call, and a negative value for a failure.
+ *   Ideally, this should return one of the generic SUNLS_* error 
+ *   codes listed at the bottom of this file.
+ *
+ * SUNLinSolSetScalingVectors (iterative methods only)
+ *   Sets pointers to left/right scaling vectors for the linear
+ *   system solve.  Here, s1 is an N_Vector of positive scale factors
+ *   for P1-inv b, where P1 is the left preconditioner (the vector is 
+ *   not tested for positivity).  Pass NULL if no scaling on P1-inv b
+ *   is required.  Similarly, s2 is an N_Vector of positive scale 
+ *   factors for P2 x, where P2 is the right preconditioner (again 
+ *   not tested for positivity). Pass NULL if no scaling on P2 x is 
+ *   required.  This should return zero for a successful call, and a 
+ *   negative value for a failure.  Ideally, this should return one of
+ *   the generic SUNLS_* error codes listed at the bottom of this file.
+ *
+ * SUNLinSolInitialize
+ *   Performs linear solver initialization (assumes that all 
+ *   solver-specific options have been set).  This should return
+ *   zero for a successful call, and a negative value for a failure.  
+ *   Ideally, this should return one of the generic SUNLS_* error 
+ *   codes listed at the bottom of this file.
+ *
+ * SUNLinSolSetup
+ *   Performs any linear solver setup needed, based on an updated
+ *   system matrix A.  This may be called frequently (e.g. with a
+ *   full Newton method) or infrequently (for a modified Newton 
+ *   method), based on the type of integrator and/or nonlinear 
+ *   solver requesting the solves.  This should return
+ *   zero for a successful call, a positive value for a recoverable 
+ *   failure and a negative value for an unrecoverable failure.  
+ *   Ideally, this should return one of the generic SUNLS_* error 
+ *   codes listed at the bottom of this file.
+ *
+ * SUNLinSolSolve
+ *   Solves a linear system A*x = b.  If the solver is scaled, it 
+ *   uses the supplied scaling vectors.  If the solver is iterative, 
+ *   it attempts to solve to the specified tolerance (weighted 
+ *   2-norm).  If the solver is direct it ignores the input tolerance 
+ *   and scaling vectors, and if the solver does not support scaling 
+ *   then it should just use a 2-norm.  This should return zero for a
+ *   successful call, a positive value for a recoverable failure and 
+ *   a negative value for an unrecoverable failure.  Ideally, this 
+ *   should return one of the generic SUNLS_* error codes listed at 
+ *   the bottom of this file.
+ *
+ * SUNLinSolNumIters (iterative methods only)
+ *   Returns the number of linear iterations performed in the last 
+ *   'Solve' call.  
+ *
+ * SUNLinSolResNorm (iterative methods only)
+ *   Returns the final residual norm from the last 'Solve' call.
+ *
+ * SUNLinSolResid (iterative methods only)
+ *   If an iterative method computes the preconditioned initial 
+ *   residual and returns with a successful solve without performing 
+ *   any iterations (i.e. either the initial guess or the 
+ *   preconditioner is sufficiently accurate), then this 
+ *   function may be called.  It should return the N_Vector 
+ *   containing the preconditioned initial residual.
+ *
+ * SUNLinSolLastFlag (optional)
+ *   Returns the last error flag encountered within the linear solver,
+ *   allowing the user to investigate linear solver issues after 
+ *   failed solves.
+ *
+ * SUNLinSolSpace (optional)
+ *   Returns the integer and real workspace sizes for the linear
+ *   solver.
+ *
+ * SUNLinSolFree
+ *   Frees memory allocated by the linear solver.  This should return
+ *   zero for a successful call, and a negative value for a failure.
+ *
+ * ---------------------------------------------------------------
+ *
+ * The following table lists the linear solver functions used by 
+ * different modules in SUNDIALS.  The symbols in the table have 
+ * The following meaning:
+ * M - called by the modified Newton nonlinear solver
+ * I - called by the inexact Newton nonlinear solver
+ * P - called by the Picard nonlinear solver
+ * S - called by the integrator directly (and non-identity mass matrix)
+ *
+ *  LinearSolver
+ *  Functions           CVODE(S)  ARKode     IDA(S)      KINSOL
+ *  ------------------------------------------------------------
+ *  GetType             M I P#    M I P#     M I P#      M I P
+ *  SetATimes           I         I S+       I           I
+ *  SetPreconditioner   I*        I* S*      I*          I*
+ *  SetScalingVectors   I         I S+       I           I 
+ *  Initialize          M I P#    M I P# S   M I P#      M I P
+ *  Setup               M I P#    M I P# S   M I P#      M I P      
+ *  Solve               M I P#    M I P# S   M I P#      M I P
+ *  NumIters            I         I S+       I           I
+ *  ResNorm             I         I S+       I           I
+ *  Resid                                    I
+ *  LastFlag^
+ *  Space               M I P#    M I P# S   M I P#      M I P
+ *  Free                M I P#    M I P# S   M I P#      M I P
+ *  ------------------------------------------------------------
+ * Notes: * -- only if user calls integrator-specific 
+ *             preconditioner "set" routine
+ *        + -- only called when using a non-identity mass matrix
+ *             with an iterative linear solver
+ *        # -- planned (currently only available for KINSOL)         
+ *        ^ -- available for users to diagnose solver failures
+ * ---------------------------------------------------------------
+ */
+  
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType(SUNLinearSolver S);
+
+SUNDIALS_EXPORT int SUNLinSolSetATimes(SUNLinearSolver S, void* A_data,
+                                       ATimesFn ATimes);
+  
+SUNDIALS_EXPORT int SUNLinSolSetPreconditioner(SUNLinearSolver S, void* P_data,
+                                               PSetupFn Pset, PSolveFn Psol);
+  
+SUNDIALS_EXPORT int SUNLinSolSetScalingVectors(SUNLinearSolver S, N_Vector s1,
+                                               N_Vector s2);
+  
+SUNDIALS_EXPORT int SUNLinSolInitialize(SUNLinearSolver S);
+  
+SUNDIALS_EXPORT int SUNLinSolSetup(SUNLinearSolver S, SUNMatrix A);
+  
+SUNDIALS_EXPORT int SUNLinSolSolve(SUNLinearSolver S, SUNMatrix A, N_Vector x,
+                                   N_Vector b, realtype tol);
+  
+SUNDIALS_EXPORT int SUNLinSolNumIters(SUNLinearSolver S);
+  
+SUNDIALS_EXPORT realtype SUNLinSolResNorm(SUNLinearSolver S);
+  
+SUNDIALS_EXPORT N_Vector SUNLinSolResid(SUNLinearSolver S);
+  
+SUNDIALS_EXPORT long int SUNLinSolLastFlag(SUNLinearSolver S);
+  
+SUNDIALS_EXPORT int SUNLinSolSpace(SUNLinearSolver S, long int *lenrwLS,
+                                   long int *leniwLS);
+  
+SUNDIALS_EXPORT int SUNLinSolFree(SUNLinearSolver S);
+
+
+/*
+ * -----------------------------------------------------------------
+ * IV. SUNLinearSolver error codes
+ * ---------------------------------------------------------------
+ */
+
+#define SUNLS_SUCCESS             0  /* successful/converged          */
+
+#define SUNLS_MEM_NULL           -1  /* mem argument is NULL          */
+#define SUNLS_ILL_INPUT          -2  /* illegal function input        */
+#define SUNLS_MEM_FAIL           -3  /* failed memory access          */
+#define SUNLS_ATIMES_FAIL_UNREC  -4  /* atimes unrecoverable failure  */
+#define SUNLS_PSET_FAIL_UNREC    -5  /* pset unrecoverable failure    */
+#define SUNLS_PSOLVE_FAIL_UNREC  -6  /* psolve unrecoverable failure  */
+#define SUNLS_PACKAGE_FAIL_UNREC -7  /* external package unrec. fail  */
+#define SUNLS_GS_FAIL            -8  /* Gram-Schmidt failure          */        
+#define SUNLS_QRSOL_FAIL         -9  /* QRsol found singular R        */
+
+#define SUNLS_RES_REDUCED         1  /* nonconv. solve, resid reduced */
+#define SUNLS_CONV_FAIL           2  /* nonconvergent solve           */
+#define SUNLS_ATIMES_FAIL_REC     3  /* atimes failed recoverably     */
+#define SUNLS_PSET_FAIL_REC       4  /* pset failed recoverably       */
+#define SUNLS_PSOLVE_FAIL_REC     5  /* psolve failed recoverably     */
+#define SUNLS_PACKAGE_FAIL_REC    6  /* external package recov. fail  */
+#define SUNLS_QRFACT_FAIL         7  /* QRfact found singular matrix  */
+#define SUNLS_LUFACT_FAIL         8  /* LUfact found singular matrix  */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sundials/sundials_math.h b/include/sundials/sundials_math.h
index 7e25d3e..62320be 100644
--- a/include/sundials/sundials_math.h
+++ b/include/sundials/sundials_math.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Aaron Collier @ LLNL
diff --git a/include/sundials/sundials_matrix.h b/include/sundials/sundials_matrix.h
new file mode 100644
index 0000000..ad8b571
--- /dev/null
+++ b/include/sundials/sundials_matrix.h
@@ -0,0 +1,196 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner, Carol Woodward, Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for a generic matrix package.
+ * It defines the SUNMatrix structure (_generic_SUNMatrix) which
+ * contains the following fields:
+ *   - an implementation-dependent 'content' field which contains
+ *     the description and actual data of the matrix
+ *   - an 'ops' filed which contains a structure listing operations
+ *     acting on such matrices
+ *
+ * Part I of this file contains enumeration constants for all 
+ * SUNDIALS-defined matrix types, as well as a generic type for 
+ * user-supplied matrix types.
+ *
+ * Part II of this file contains type declarations for the
+ * _generic_SUNMatrix and _generic_SUNMatrix_Ops structures, as well
+ * as references to pointers to such structures (SUNMatrix).
+ *
+ * Part III of this file contains the prototypes for the matrix
+ * functions which operate on SUNMatrix.
+ *
+ * At a minimum, a particular implementation of a SUNMatrix must
+ * do the following:
+ *  - specify the 'content' field of SUNMatrix,
+ *  - implement the operations on those SUNMatrix,
+ *  - provide a constructor routine for new SUNMatrix objects
+ *
+ * Additionally, a SUNMatrix implementation may provide the following:
+ *  - macros to access the underlying SUNMatrix data
+ *  - a routine to print the content of a SUNMatrix
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNMATRIX_H
+#define _SUNMATRIX_H
+ 
+#include <sundials/sundials_types.h>
+#include <sundials/sundials_nvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+ 
+  
+/*
+ * -----------------------------------------------------------------
+ * I. Implemented SUNMatrix types
+ * -----------------------------------------------------------------
+ */
+ 
+typedef enum {
+  SUNMATRIX_DENSE, 
+  SUNMATRIX_BAND, 
+  SUNMATRIX_SPARSE, 
+  SUNMATRIX_CUSTOM
+} SUNMatrix_ID;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * II. Generic definition of SUNMatrix 
+ * -----------------------------------------------------------------
+ */
+ 
+/* Forward reference for pointer to SUNMatrix_Ops object */
+typedef struct _generic_SUNMatrix_Ops *SUNMatrix_Ops;
+ 
+/* Forward reference for pointer to SUNMatrix object */
+typedef struct _generic_SUNMatrix *SUNMatrix;
+ 
+/* Structure containing function pointers to matrix operations  */  
+struct _generic_SUNMatrix_Ops {
+  SUNMatrix_ID (*getid)(SUNMatrix);
+  SUNMatrix    (*clone)(SUNMatrix);
+  void         (*destroy)(SUNMatrix);
+  int          (*zero)(SUNMatrix);
+  int          (*copy)(SUNMatrix, SUNMatrix);
+  int          (*scaleadd)(realtype, SUNMatrix, SUNMatrix);
+  int          (*scaleaddi)(realtype, SUNMatrix);
+  int          (*matvec)(SUNMatrix, N_Vector, N_Vector);
+  int          (*space)(SUNMatrix, long int*, long int*);
+};
+ 
+/* A matrix is a structure with an implementation-dependent
+   'content' field, and a pointer to a structure of matrix
+   operations corresponding to that implementation.  */
+struct _generic_SUNMatrix {
+  void *content;
+  struct _generic_SUNMatrix_Ops *ops;
+};
+
+  
+/*
+ * -----------------------------------------------------------------
+ * III. Functions exported by SUNMatrix module
+ *
+ * SUNMatGetID
+ *   Returns an identifier for the matrix type from the enumeration 
+ *   SUNMatrix_ID.  This will be queried by a given linear solver to 
+ *   assess compatibility.
+ *
+ * SUNMatClone
+ *   Creates a new matrix of the same type as an existing matrix.
+ *   It does not copy the matrix, but rather allocates storage for
+ *   the new matrix.
+ *
+ * SUNMatDestroy
+ *   Destroys a matrix created with SUNMatClone.
+ *
+ * SUNMatZero
+ *   Sets all matrix entries to zero
+ *
+ * SUNMatScaleAdd
+ *   Performs the operation A = c*A + B.  Returns an error if A 
+ *   and B have different types and/or dimensions.
+ *
+ * SUNMatCopy
+ *   Performs the operation B = A.  Should return an error if A and 
+ *   B have different types and/or dimensions.
+ *
+ * SUNMatScaleAddI
+ *   Performs the operation A = c*A + I.  Returns an error if A is 
+ *   not a square matrix.
+ *
+ * SUNMatMatvec
+ *   Performs the matrix-vector product y = A*x.  Returns an error if 
+ *   A, x and/or y have incompatible types and/or dimensions, or if 
+ *   x and y are the same vector.
+ *
+ * SUNMatSpace
+ *   Returns the real and integer workspace requirement for the 
+ *   SUNMatrix object.
+ *
+ * -----------------------------------------------------------------
+ *
+ * The following table lists the matrix functions used by
+ * different modules in SUNDIALS. The symbols in the table
+ * have the following meaning:
+ *   D  -  called by dense linear solver modules
+ *   B  -  called by band linear solver modules
+ *   I  -  called by iterative linear solver modules
+ *   S  -  called by sparse linear solver modules
+ *   BP -  called by band preconditioner module
+ *   DP -  called by band-block diagonal preconditioner module
+ *
+ *                                MODULES                  
+ * MATRIX        -----------------------------------------------
+ * FUNCTIONS     CVODE(S)      ARKode      IDA(S)       KINSOL    
+ * ----------------------------------------------------------------
+ *  GetID        D B S BP DP  D B S BP DP  D B S BP DP  D B S BP DP
+ *  Clone        D B S BP DP  D B S BP DP  BP DP
+ *  Destroy      D B S BP DP  D B S BP DP  BP DP
+ *  Zero         D B S BP DP  D B S BP DP  D B S BP DP  D B BP DP
+ *  Copy         D B S BP DP  D B S BP DP
+ *  ScaleAddI    D B S BP DP  D B S BP DP
+ *  ScaleAdd                  D B S BP DP
+ *  Matvec*                   D B S
+ *  Space        D B S BP DP  D B S BP DP  D B S BP DP  D B S BP DP
+ * -----------------------------------------------------------------
+ *  Note: MatrixMatvec is only called by ARKode when solving 
+ *        problems having non-identity mass matrix
+ * -----------------------------------------------------------------
+ */
+  
+SUNDIALS_EXPORT SUNMatrix_ID SUNMatGetID(SUNMatrix A);
+SUNDIALS_EXPORT SUNMatrix SUNMatClone(SUNMatrix A);
+SUNDIALS_EXPORT void SUNMatDestroy(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatZero(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatCopy(SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAdd(realtype c, SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAddI(realtype c, SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatMatvec(SUNMatrix A, N_Vector x, N_Vector y);
+SUNDIALS_EXPORT int SUNMatSpace(SUNMatrix A, long int *lenrw,
+                                long int *leniw);
+ 
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/sundials/sundials_mpi_types.h b/include/sundials/sundials_mpi_types.h
new file mode 100644
index 0000000..974aca0
--- /dev/null
+++ b/include/sundials/sundials_mpi_types.h
@@ -0,0 +1,36 @@
+/* -----------------------------------------------------------------
+ * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban,
+ *                Aaron Collier, and Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This header file contains definitions of MPI data types, which 
+ * are used by MPI parallel vector implementations.
+ * -----------------------------------------------------------------*/
+
+#include <sundials/sundials_types.h>
+
+/* define MPI data types */
+
+#if defined(SUNDIALS_SINGLE_PRECISION)
+  #define PVEC_REAL_MPI_TYPE MPI_FLOAT
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+  #define PVEC_REAL_MPI_TYPE MPI_DOUBLE
+#elif defined(SUNDIALS_EXTENDED_PRECISION)
+  #define PVEC_REAL_MPI_TYPE MPI_LONG_DOUBLE
+#endif
+
+#if defined(SUNDIALS_INT64_T)
+  #define PVEC_INTEGER_MPI_TYPE MPI_INT64_T
+#elif defined(SUNDIALS_INT32_T)
+  #define PVEC_INTEGER_MPI_TYPE MPI_INT32_T
+#endif
+
diff --git a/include/sundials/sundials_nvector.h b/include/sundials/sundials_nvector.h
index 7fe88e1..181aaca 100644
--- a/include/sundials/sundials_nvector.h
+++ b/include/sundials/sundials_nvector.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4803 $
- * $Date: 2016-07-08 14:01:04 -0700 (Fri, 08 Jul 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -68,6 +68,8 @@ typedef enum {
   SUNDIALS_NVEC_PTHREADS, 
   SUNDIALS_NVEC_PARHYP, 
   SUNDIALS_NVEC_PETSC,
+  SUNDIALS_NVEC_CUDA,
+  SUNDIALS_NVEC_RAJA,
   SUNDIALS_NVEC_CUSTOM
 } N_Vector_ID;
   
@@ -92,7 +94,7 @@ struct _generic_N_Vector_Ops {
   N_Vector    (*nvclone)(N_Vector);
   N_Vector    (*nvcloneempty)(N_Vector);
   void        (*nvdestroy)(N_Vector);
-  void        (*nvspace)(N_Vector, long int *, long int *);
+  void        (*nvspace)(N_Vector, sunindextype *, sunindextype *);
   realtype*   (*nvgetarraypointer)(N_Vector);
   void        (*nvsetarraypointer)(realtype *, N_Vector);
   void        (*nvlinearsum)(realtype, N_Vector, realtype, N_Vector, N_Vector); 
@@ -155,7 +157,7 @@ struct _generic_N_Vector {
  *
  * N_VSpace
  *   Returns space requirements for one N_Vector (type 'realtype' in
- *   lrw and type 'long int' in liw).
+ *   lrw and type 'sunindextype' in liw).
  *
  * N_VGetArrayPointer
  *   Returns a pointer to the data component of the given N_Vector.
@@ -240,8 +242,8 @@ struct _generic_N_Vector {
  * N_VInvTest
  *   Performs the operation z[i] = 1/x[i] with a test for 
  *   x[i] == 0.0 before inverting x[i].
- *   This routine returns TRUE if all components of x are non-zero 
- *   (successful inversion) and returns FALSE otherwise.
+ *   This routine returns SUNTRUE if all components of x are non-zero 
+ *   (successful inversion) and returns SUNFALSE otherwise.
  *
  * N_VConstrMask
  *   Performs the operation : 
@@ -252,8 +254,8 @@ struct _generic_N_Vector {
  *      If c[i] = +1.0, then x[i] must be >= 0.0.
  *      If c[i] = -1.0, then x[i] must be <= 0.0.
  *      If c[i] = -2.0, then x[i] must be <  0.0.
- *   This routine returns a boolean FALSE if any element failed
- *   the constraint test, TRUE if all passed. It also sets a
+ *   This routine returns a boolean SUNFALSE if any element failed
+ *   the constraint test, SUNTRUE if all passed. It also sets a
  *   mask vector m, with elements equal to 1.0 where the
  *   corresponding constraint test failed, and equal to 0.0
  *   where the constraint test passed.
@@ -346,7 +348,7 @@ SUNDIALS_EXPORT N_Vector_ID N_VGetVectorID(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VClone(N_Vector w);
 SUNDIALS_EXPORT N_Vector N_VCloneEmpty(N_Vector w);
 SUNDIALS_EXPORT void N_VDestroy(N_Vector v);
-SUNDIALS_EXPORT void N_VSpace(N_Vector v, long int *lrw, long int *liw);
+SUNDIALS_EXPORT void N_VSpace(N_Vector v, sunindextype *lrw, sunindextype *liw);
 SUNDIALS_EXPORT realtype *N_VGetArrayPointer(N_Vector v);
 SUNDIALS_EXPORT void N_VSetArrayPointer(realtype *v_data, N_Vector v);
 SUNDIALS_EXPORT void N_VLinearSum(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z);
diff --git a/include/sundials/sundials_sparse.h b/include/sundials/sundials_sparse.h
index 358f273..724f29e 100644
--- a/include/sundials/sundials_sparse.h
+++ b/include/sundials/sundials_sparse.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4771 $
- * $Date: 2016-06-03 13:21:57 -0700 (Fri, 03 Jun 2016) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer: Carol Woodward, Slaven Peles @ LLNL,
  *             Daniel R. Reynolds @ SMU.
diff --git a/include/sundials/sundials_spbcgs.h b/include/sundials/sundials_spbcgs.h
index 9c6b6a6..3976236 100644
--- a/include/sundials/sundials_spbcgs.h
+++ b/include/sundials/sundials_spbcgs.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Peter Brown and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
diff --git a/include/sundials/sundials_spgmr.h b/include/sundials/sundials_spgmr.h
index 07b0910..1d48928 100644
--- a/include/sundials/sundials_spgmr.h
+++ b/include/sundials/sundials_spgmr.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
diff --git a/include/sundials/sundials_sptfqmr.h b/include/sundials/sundials_sptfqmr.h
index 3dc2dfb..de80882 100644
--- a/include/sundials/sundials_sptfqmr.h
+++ b/include/sundials/sundials_sptfqmr.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Aaron Collier @ LLNL
  * -----------------------------------------------------------------
diff --git a/include/sundials/sundials_superlumt_impl.h b/include/sundials/sundials_superlumt_impl.h
index d823baa..282d7d1 100644
--- a/include/sundials/sundials_superlumt_impl.h
+++ b/include/sundials/sundials_superlumt_impl.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4741 $
- * $Date: 2016-04-20 11:36:18 -0700 (Wed, 20 Apr 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Carol S. Woodward @ LLNL
  * -----------------------------------------------------------------
diff --git a/include/sundials/sundials_types.h b/include/sundials/sundials_types.h
index 844d5f9..50d41fb 100644
--- a/include/sundials/sundials_types.h
+++ b/include/sundials/sundials_types.h
@@ -1,18 +1,19 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban, and
- *                Aaron Collier @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban,
+ *                Aaron Collier, and Slaven Peles @ LLNL
  * -----------------------------------------------------------------
- * Copyright (c) 2002, The Regents of the University of California.
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
  * For details, see the LICENSE file.
- *------------------------------------------------------------------
- * This header file exports two types: realtype and booleantype,
- * as well as the constants TRUE and FALSE.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This header file exports three types: realtype, sunindextype and 
+ * booleantype, as well as the constants SUNTRUE and SUNFALSE.
  *
  * Users should include the header file sundials_types.h in every
  * program file and use the exported name realtype instead of
@@ -20,12 +21,18 @@
  *
  * The constants SUNDIALS_SINGLE_PRECISION, SUNDIALS_DOUBLE_PRECISION
  * and SUNDIALS_LONG_DOUBLE_PRECISION indicate the underlying data
- * type of realtype. It is set at the configuration stage.
- *
+ * type of realtype. 
+ * 
  * The legal types for realtype are float, double and long double.
  *
+ * The constants SUNDIALS_INT64_T and SUNDIALS_INT32_T indicate 
+ * the underlying data type of sunindextype -- the integer data type
+ * used for vector and matrix indices. 
+ * 
+ * Data types are set at the configuration stage.
+ *
  * The macro RCONST gives the user a convenient way to define
- * real-valued constants. To use the constant 1.0, for example,
+ * real-valued literal constants. To use the constant 1.0, for example,
  * the user should write the following:
  *
  *   #define ONE RCONST(1.0)
@@ -34,9 +41,9 @@
  * to 1.0. If realtype is defined as a float, then RCONST(1.0)
  * expands to 1.0F. If realtype is defined as a long double,
  * then RCONST(1.0) expands to 1.0L. There is never a need to
- * explicitly cast 1.0 to (realtype).
- *------------------------------------------------------------------
- */
+ * explicitly cast 1.0 to (realtype). The macro can be used for 
+ * literal constants only. It cannot be used for expressions. 
+ * -----------------------------------------------------------------*/
   
 #ifndef _SUNDIALSTYPES_H
 #define _SUNDIALSTYPES_H
@@ -47,6 +54,7 @@
 #endif
 
 #include <float.h>
+#include <stdint.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -86,19 +94,51 @@ typedef long double realtype;
 
 #endif
 
+
+/*
+ *------------------------------------------------------------------
+ * Type : sunindextype
+ *------------------------------------------------------------------
+ * Defines integer type to be used for vector and matrix indices.
+ * User can build sundials to use 32- or 64-bit signed integers.
+ * If compiler does not support portable data types, 'int' is used
+ * in place of 32- and 'long int' is used in place of 64-bit 
+ * integer.
+ *------------------------------------------------------------------
+ */
+
+#if defined(SUNDIALS_INT64_T)
+
+#if __STDC_VERSION__ >= 199901L
+typedef int64_t sunindextype;
+#else
+typedef long int sunindextype;
+#endif
+
+#elif defined(SUNDIALS_INT32_T)
+
+#if __STDC_VERSION__ >= 199901L
+typedef int32_t sunindextype;
+#else
+typedef int sunindextype;
+#endif
+
+#endif
+
+
 /*
  *------------------------------------------------------------------
  * Type : booleantype
  *------------------------------------------------------------------
- * Constants : FALSE and TRUE
+ * Constants : SUNFALSE and SUNTRUE
  *------------------------------------------------------------------
  * ANSI C does not have a built-in boolean data type. Below is the
  * definition for a new type called booleantype. The advantage of
  * using the name booleantype (instead of int) is an increase in
  * code readability. It also allows the programmer to make a
  * distinction between int and boolean data. Variables of type
- * booleantype are intended to have only the two values FALSE and
- * TRUE which are defined below to be equal to 0 and 1,
+ * booleantype are intended to have only the two values SUNFALSE and
+ * SUNTRUE which are defined below to be equal to 0 and 1,
  * respectively.
  *------------------------------------------------------------------
  */
@@ -107,16 +147,19 @@ typedef long double realtype;
 #define booleantype int
 #endif
 
-#ifndef FALSE
-#define FALSE 0
+#ifndef SUNFALSE
+#define SUNFALSE 0
 #endif
 
-#ifndef TRUE
-#define TRUE 1
+#ifndef SUNTRUE
+#define SUNTRUE 1
 #endif
 
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif
+#endif  /* _SUNDIALSTYPES_H */
+
+
diff --git a/include/sundials/sundials_version.h b/include/sundials/sundials_version.h
new file mode 100644
index 0000000..e3ab9ae
--- /dev/null
+++ b/include/sundials/sundials_version.h
@@ -0,0 +1,66 @@
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This header file is for routines to get SUNDIALS version info
+ * -----------------------------------------------------------------*/
+
+#ifndef _SUNDIALS_VERSION_H
+#define _SUNDIALS_VERSION_H
+
+#include <sundials/sundials_config.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* -----------------------------------------------------------------
+ * Function: SUNDIALSGetVersion
+ * -----------------------------------------------------------------
+ * SUNDIALSGetVersion fills a string with SUNDIALS version
+ * information using the format major.minor.patch-label
+ * 
+ * Inputs:
+ *   version = string to fill with version information
+ *   len     = length of the input string version
+ *
+ * SUNDIALSGetVersion returns 0 if successful and -1 if the input
+ * string is too short to store the SUNDIALS version.
+ * -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int SUNDIALSGetVersion(char *version, int len);
+
+
+/* -----------------------------------------------------------------
+ * Function: SUNDIALSGetVersionNumber
+ * -----------------------------------------------------------------
+ * SUNDIALSGetVersionNumber fills separate integers with the 
+ * SUNDIALS major, minor, and patch release version numbers and a
+ * fills a string with the release label.
+ * 
+ * Inputs:
+ *   major = integer for major version number
+ *   minor = integer for minor version number
+ *   patch = integer for patch version number
+ *   label = string for version label
+ *   len   = length of the input string label
+ *
+ * SUNDIALSGetVersionNumber returns 0 if successful and -1 if the
+ * input string is too short to store the SUNDIALS version.
+ * -----------------------------------------------------------------*/
+SUNDIALS_EXPORT int SUNDIALSGetVersionNumber(int *major, int *minor, int *patch, 
+                                             char *label, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_band.h b/include/sunlinsol/sunlinsol_band.h
new file mode 100644
index 0000000..1a06e5d
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_band.h
@@ -0,0 +1,105 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the band implementation of the 
+ * SUNLINSOL module.
+ * 
+ * Part I contains declarations specific to the band implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNBandLinearSolver as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_BAND_H
+#define _SUNLINSOL_BAND_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_band.h>
+#include <sunmatrix/sunmatrix_band.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: Band implementation of SUNLinearSolver
+ *
+ * The band implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     N -- size of the linear system
+ *     pivots -- index array for partial pivoting in LU factorization
+ *     last_flag -- last error return flag from internal setup/solve
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_Band {
+  sunindextype  N;
+  sunindextype *pivots;
+  long int last_flag;
+};
+
+typedef struct _SUNLinearSolverContent_Band *SUNLinearSolverContent_Band;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_band
+ * 
+ * CONSTRUCTOR:
+ *    SUNBandLinearSolver creates and allocates memory for a banded
+ *    matrix solver
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNBandLinearSolver(N_Vector y,
+                                                    SUNMatrix A);
+
+/*
+ * -----------------------------------------------------------------
+ * band implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_Band(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_Band(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetup_Band(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_Band(SUNLinearSolver S, SUNMatrix A,
+                                        N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_Band(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_Band(SUNLinearSolver S,
+                                        long int *lenrwLS,
+                                        long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_Band(SUNLinearSolver S);
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_dense.h b/include/sunlinsol/sunlinsol_dense.h
new file mode 100644
index 0000000..b83f466
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_dense.h
@@ -0,0 +1,111 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the dense implementation of the 
+ * SUNLINSOL module.
+ * 
+ * Part I contains declarations specific to the dense implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNDenseLinearSolver as well as implementation-specific 
+ * prototypes for various useful matrix operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ *   - The definition of the type 'realtype' can be found in the
+ *     header file sundials_types.h, and it may be changed (at the 
+ *     configuration stage) according to the user's needs. 
+ *     The sundials_types.h file also contains the definition
+ *     for the type 'booleantype' and 'indextype'.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_DENSE_H
+#define _SUNLINSOL_DENSE_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_dense.h>
+#include <sunmatrix/sunmatrix_dense.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: Dense implementation of SUNLinearSolver
+ *
+ * The dense implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *       N -- size of the linear system
+ *	 pivots -- index array for partial pivoting in LU factorization
+ *       last_flag -- last error return flag from internal setup/solve
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_Dense {
+  sunindextype N;
+  sunindextype *pivots;
+  long int last_flag;
+};
+
+typedef struct _SUNLinearSolverContent_Dense *SUNLinearSolverContent_Dense;
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_dense
+ * 
+ * CONSTRUCTORS:
+ *    SUNDenseLinearSolver creates and allocates memory for a 
+ * 	 dense matrix solver
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNDenseLinearSolver(N_Vector y,
+                                                     SUNMatrix A);
+
+/*
+ * -----------------------------------------------------------------
+ * dense implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_Dense(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_Dense(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetup_Dense(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_Dense(SUNLinearSolver S, SUNMatrix A,
+                                         N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_Dense(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_Dense(SUNLinearSolver S,
+                                         long int *lenrwLS,
+                                         long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_Dense(SUNLinearSolver S);
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/sunlinsol/sunlinsol_klu.h b/include/sunlinsol/sunlinsol_klu.h
new file mode 100644
index 0000000..2e96956
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_klu.h
@@ -0,0 +1,197 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on sundials_klu_impl.h and arkode_klu.h/cvode_klu.h/... 
+ *     code, written by Carol S. Woodward @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the KLU implementation of the 
+ * SUNLINSOL module.
+ * 
+ * Part I contains declarations specific to the KLU implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNKLU as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_KLU_H
+#define _SUNLINSOL_KLU_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+#include "klu.h"
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Default KLU solver parameters */
+#define SUNKLU_ORDERING_DEFAULT  1    /* COLAMD */
+
+/* Interfaces to match 'sunindextype' with the correct KLU types/functions */
+#if defined(SUNDIALS_INT64_T)
+#define sun_klu_symbolic      klu_l_symbolic
+#define sun_klu_numeric       klu_l_numeric
+#define sun_klu_common        klu_l_common
+#define sun_klu_analyze       klu_l_analyze
+#define sun_klu_factor        klu_l_factor
+#define sun_klu_refactor      klu_l_refactor
+#define sun_klu_rcond         klu_l_rcond
+#define sun_klu_condest       klu_l_condest
+#define sun_klu_defaults      klu_l_defaults
+#define sun_klu_free_symbolic klu_l_free_symbolic
+#define sun_klu_free_numeric  klu_l_free_numeric
+#elif defined(SUNDIALS_INT32_T)
+#define sun_klu_symbolic      klu_symbolic
+#define sun_klu_numeric       klu_numeric
+#define sun_klu_common        klu_common
+#define sun_klu_analyze       klu_analyze
+#define sun_klu_factor        klu_factor
+#define sun_klu_refactor      klu_refactor
+#define sun_klu_rcond         klu_rcond
+#define sun_klu_condest       klu_condest
+#define sun_klu_defaults      klu_defaults
+#define sun_klu_free_symbolic klu_free_symbolic
+#define sun_klu_free_numeric  klu_free_numeric
+#else  /* incompatible sunindextype for KLU */
+#error  Incompatible sunindextype for KLU
+#endif
+
+#if defined(SUNDIALS_DOUBLE_PRECISION)
+#else
+#error  Incompatible realtype for KLU
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: KLU implementation of SUNLinearSolver
+ *
+ * The KLU implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     last_flag -- last error return flag from internal setup/solve
+ *     first_factorize -- flag indicating whether the factorization 
+ *       has ever been performed
+ *     Symbolic -- KLU storage structure for symbolic 
+ *       factorization components
+ *     Numeric -- KLU storage structure for numeric factorization
+ *        components
+ *     Common -- storage structure for common KLU solver 
+ *        components
+ *     klu_solver -- ptr to KLU function to handle CSR/CSC
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_KLU {
+  long int         last_flag;
+  int              first_factorize;
+  sun_klu_symbolic *symbolic;
+  sun_klu_numeric  *numeric;
+  sun_klu_common   common;
+  sunindextype     (*klu_solver)(sun_klu_symbolic*, sun_klu_numeric*,
+                                 sunindextype, sunindextype,
+                                 double*, sun_klu_common*);
+};
+
+typedef struct _SUNLinearSolverContent_KLU *SUNLinearSolverContent_KLU;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_klu
+ * 
+ * CONSTRUCTOR:
+ *    SUNKLU creates and allocates memory for a KLU sparse-direct 
+ *      linear solver
+ *
+ * OTHER:
+ *    SUNKLUReInit reinitializes memory and flags for a new 
+ *      factorization (symbolic and numeric) to be conducted at the 
+ *      next solver setup call.  This routine is useful in the 
+ *      cases where the number of nonzeroes has changed or if the 
+ *      structure of the linear system has changed which would 
+ *      require a new symbolic (and numeric factorization).
+ *
+ *      The reinit_type argument governs the level of 
+ *      reinitialization:
+ *
+ *      reinit_type = 1: The Jacobian matrix will be destroyed and 
+ *                       a new one will be allocated based on the 
+ *                       nnz value passed to this call. New 
+ *                       symbolic and numeric factorizations will 
+ *                       be completed at the next solver setup.
+ *
+ *      reinit_type = 2: Only symbolic and numeric factorizations 
+ *                       will be completed.  It is assumed that the 
+ *                       Jacobian size has not exceeded the size of 
+ *                       nnz given in the sparse matrix provided to
+ *                       the original constructor routine (or the 
+ *                       previous SUNKLUReInit call) 
+ *
+ *      This routine assumes no other changes to solver use are 
+ *      necessary.
+ *
+ *    SUNKLUSetOrdering sets the ordering used by KLU for reducing 
+ *      fill in the linear solve.  Options for ordering_choice are: 
+ *          0 for AMD, 
+ *          1 for COLAMD, and 
+ *          2 for the natural ordering.
+ *      The default is 1 for COLAMD.
+ *
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNKLU(N_Vector y, SUNMatrix A);
+
+SUNDIALS_EXPORT int SUNKLUReInit(SUNLinearSolver S, SUNMatrix A,
+                                 sunindextype nnz, int reinit_type);
+
+SUNDIALS_EXPORT int SUNKLUSetOrdering(SUNLinearSolver S,
+                                      int ordering_choice);
+
+/*
+ * -----------------------------------------------------------------
+ * KLU implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_KLU(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_KLU(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetup_KLU(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_KLU(SUNLinearSolver S, SUNMatrix A,
+                                       N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_KLU(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_KLU(SUNLinearSolver S,
+                                       long int *lenrwLS,
+                                       long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_KLU(SUNLinearSolver S);
+  
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_lapackband.h b/include/sunlinsol/sunlinsol_lapackband.h
new file mode 100644
index 0000000..a6251eb
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_lapackband.h
@@ -0,0 +1,123 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the LAPACK band implementation of the 
+ * SUNLINSOL module.
+ * 
+ * Part I contains declarations specific to the LAPACK band 
+ * implementation of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNLapackBand as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_LAPBAND_H
+#define _SUNLINSOL_LAPBAND_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_lapack.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sunmatrix/sunmatrix_band.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Interfaces to match 'realtype' with the correct LAPACK functions */
+#if defined(SUNDIALS_DOUBLE_PRECISION)
+#define xgbtrf_f77    dgbtrf_f77
+#define xgbtrs_f77    dgbtrs_f77
+#elif defined(SUNDIALS_SINGLE_PRECISION)
+#define xgbtrf_f77    sgbtrf_f77
+#define xgbtrs_f77    sgbtrs_f77
+#else
+#error  Incompatible realtype for LAPACK; disable LAPACK and rebuild
+#endif
+
+/* Catch to disable LAPACK linear solvers with incompatible sunindextype */
+#if defined(SUNDIALS_INT32_T)
+#else  /* incompatible sunindextype for LAPACK */
+#error  Incompatible sunindextype for LAPACK; disable LAPACK and rebuild
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: LAPACK band implementation of SUNLinearSolver
+ *
+ * The LAPACK band implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     N -- size of the linear system
+ *     pivots -- index array for partial pivoting in LU factorization
+ *     last_flag -- last error return flag from internal setup/solve
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_LapackBand {
+  sunindextype N;
+  sunindextype *pivots;
+  long int last_flag;
+};
+
+typedef struct _SUNLinearSolverContent_LapackBand *SUNLinearSolverContent_LapackBand;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_lapackband
+ * 
+ * CONSTRUCTOR:
+ *    SUNLapackBand creates and allocates memory for a LAPACK banded 
+ *      matrix solver
+ *
+ * OTHER:
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNLapackBand(N_Vector y, SUNMatrix A);
+
+/*
+ * -----------------------------------------------------------------
+ * LAPACK band implementations of required linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_LapackBand(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_LapackBand(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetup_LapackBand(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_LapackBand(SUNLinearSolver S, SUNMatrix A,
+                                              N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_LapackBand(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_LapackBand(SUNLinearSolver S,
+                                              long int *lenrwLS,
+                                              long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_LapackBand(SUNLinearSolver S);
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_lapackdense.h b/include/sunlinsol/sunlinsol_lapackdense.h
new file mode 100644
index 0000000..0db50e4
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_lapackdense.h
@@ -0,0 +1,123 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the LAPACK dense implementation of the 
+ * SUNLINSOL module.
+ * 
+ * Part I contains declarations specific to the LAPACK dense 
+ * implementation of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNLapackDense as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_LAPDENSE_H
+#define _SUNLINSOL_LAPDENSE_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_lapack.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sunmatrix/sunmatrix_dense.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Interfaces to match 'realtype' with the correct LAPACK functions */
+#if defined(SUNDIALS_DOUBLE_PRECISION)
+#define xgetrf_f77    dgetrf_f77
+#define xgetrs_f77    dgetrs_f77
+#elif defined(SUNDIALS_SINGLE_PRECISION)
+#define xgetrf_f77    sgetrf_f77
+#define xgetrs_f77    sgetrs_f77
+#else
+#error  Incompatible realtype for LAPACK; disable LAPACK and rebuild
+#endif
+
+/* Catch to disable LAPACK linear solvers with incompatible sunindextype */
+#if defined(SUNDIALS_INT32_T)
+#else  /* incompatible sunindextype for LAPACK */
+#error  Incompatible sunindextype for LAPACK; disable LAPACK and rebuild
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: LAPACK dense implementation of SUNLinearSolver
+ *
+ * The LAPACK dense implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     N -- size of the linear system
+ *     pivots -- index array for partial pivoting in LU factorization
+ *     last_flag -- last error return flag from internal setup/solve
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_LapackDense {
+  sunindextype N;
+  sunindextype *pivots;
+  long int last_flag;
+};
+
+typedef struct _SUNLinearSolverContent_LapackDense *SUNLinearSolverContent_LapackDense;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_lapackdense
+ * 
+ * CONSTRUCTOR:
+ *    SUNLapackDense creates and allocates memory for a LAPACK dense
+ *      matrix solver
+ *
+ * OTHER:
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNLapackDense(N_Vector y, SUNMatrix A);
+
+/*
+ * -----------------------------------------------------------------
+ * LAPACK dense implementations of required linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_LapackDense(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_LapackDense(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetup_LapackDense(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_LapackDense(SUNLinearSolver S, SUNMatrix A,
+                                               N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_LapackDense(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_LapackDense(SUNLinearSolver S,
+                                               long int *lenrwLS,
+                                               long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_LapackDense(SUNLinearSolver S);
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_pcg.h b/include/sunlinsol/sunlinsol_pcg.h
new file mode 100644
index 0000000..dc7a5d0
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_pcg.h
@@ -0,0 +1,218 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the PCG implementation of the 
+ * SUNLINSOL module.  The PCG algorithm is based on the
+ * Preconditioned Conjugate Gradient.
+ *
+ * The PCG algorithm solves a linear system A x = b where 
+ * A is a symmetric, real-valued matrix, i.e. A = A' (Matlab 
+ * notation for the transpose of A).  Preconditioning is allowed, 
+ * and is applied in a symmetric fashion on both the right and left.  
+ * Scaling is also allowed and is applied symmetrically.  We denote
+ * the preconditioner and scaling matrices as follows:
+ *   P = preconditioner (assumed symmetric)
+ *   S = diagonal matrix of scale factors 
+ * The matrices A and P are not required explicitly; only routines 
+ * that provide A and P-inverse as operators are required.  The 
+ * diagonal of the matrix S is held in a single N_Vector, supplied
+ * by the user of this module.
+ *
+ * In this notation, PCG applies the underlying algorithm to
+ * the equivalent transformed system
+ *   Abar xbar = bbar , where
+ *   Abar = S (P-inverse) A (P-inverse) S ,
+ *   bbar = S (P-inverse) b , and   xbar = (S-inverse) P x .
+ *
+ * The scaling matrix must be chosen so that the vectors
+ * (S P-inverse b) and (S-inverse P x) have dimensionless 
+ * components.
+ *
+ * The stopping test for the PCG iterations is on the L2 norm of
+ * the scaled preconditioned residual:
+ *      || bbar - Abar xbar ||_2  <  delta
+ *  <=>
+ *      || S (P-inverse) b - S (P-inverse) A x ||_2  <  delta
+ *  <=>
+ *      || P-inverse b - (P-inverse) A x ||_S  <  delta
+ * where || v ||_S =  sqrt(v' S' S v) with an input test constant 
+ * delta.
+ *
+ * The usage of this PCG solver involves supplying up to three
+ * routines and making a variety of calls.  The user-supplied 
+ * routines are
+ *    atimes (A_data, x, y) to compute y = A x, given x,
+ *    psolve (P_data, y, x, lr) to solve P1 x = y or P2 x = y for 
+ *           x, given y,
+ *    psetup (P_data) to perform any 'setup' operations in 
+ *           preparation for calling psolve.
+ * The user calls are:
+ *    SUNLinearSolver LS = SUNPCG(y, pretype, maxl);
+ *           to create the linear solver structure,
+ *    flag = SUNLinSolSetATimes(LS, A_data, atimes);
+ *           to set the matrix-vector product setup/apply routines,
+ *    flag = SUNLinSolSetPreconditioner(LS, P_data, psetup, psolve);
+ *           to *optionally* set the preconditioner setup/apply routines,
+ *    flag = SUNLinSolSetScalingVectors(LS, s, NULL);
+ *           to *optionally* set the diagonal of the scaling matrix 
+ *           (for PCG, only the first of the two scaling vectors is used)
+ *    flag = SUNLinSolInitialize(LS);
+ *           to perform internal solver memory allocations,
+ *    flag = SUNLinSolSetup(LS, NULL);
+ *           to call the psetup routine (if non-NULL);
+ *    flag = SUNLinSolSolve(LS, NULL, x, b, w, tol);
+ *           to solve the linear system to the tolerance 'tol'
+ *    long int nli = SUNLinSolNumIters(LS);
+ *           to *optionally* retrieve the number of linear iterations 
+ *           performed by the solver,
+ *    long int lastflag = SUNLinSolLastFlag(LS);
+ *           to *optionally* retrieve the last internal solver error flag,
+ *    realtype resnorm = SUNLinSolResNorm(LS);
+ *           to *optionally* retrieve the final linear residual norm,
+ *    flag = SUNLinSolFree(LS);
+ *           to free the solver memory.
+ * Complete details for specifying atimes, psetup and psolve 
+ * and for the usage calls are given below.
+ *
+ * -----------------------------------------------------------------
+ * 
+ * Part I contains declarations specific to the PCG implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor SUNPCG as well
+ * as implementation-specific prototypes for various useful solver
+ * operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_PCG_H
+#define _SUNLINSOL_PCG_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_pcg.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Default PCG solver parameters */
+#define SUNPCG_MAXL_DEFAULT    5
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: PCG implementation of SUNLinearSolver
+ *
+ * The PCG implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     maxl -- number of PCG iterations to use
+ *     pretype -- flag for use of preconditioning
+ *     numiters -- number of iterations from most-recent solve
+ *     resnorm -- final linear residual norm from most-recent solve
+ *     last_flag -- last error return flag from internal setup/solve
+ *     ATimes -- function pointer to ATimes routine
+ *     ATData -- pointer to structure for ATimes
+ *     Psetup -- function pointer to preconditioner setup routine
+ *     Psolve -- function pointer to preconditioner solve routine
+ *     PData -- pointer to structure for Psetup/Psolve
+ *     s -- vector (type N_Vector) which holds the diagonal of the 
+ *         scaling matrix S
+ *     r -- vector (type N_Vector) which holds the preconditioned 
+ *         linear system residual
+ *     p, z and Ap -- vectors (type N_Vector) used for workspace by
+ *         the PCG algorithm
+ * -----------------------------------------------------------------
+ */
+ 
+struct _SUNLinearSolverContent_PCG {
+  int maxl;
+  int pretype;
+  int numiters;
+  realtype resnorm;
+  long int last_flag;
+
+  ATimesFn ATimes;
+  void* ATData;
+  PSetupFn Psetup;
+  PSolveFn Psolve;
+  void* PData;
+
+  N_Vector s;
+  N_Vector r;
+  N_Vector p;
+  N_Vector z;
+  N_Vector Ap;
+};
+
+typedef struct _SUNLinearSolverContent_PCG *SUNLinearSolverContent_PCG;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART III: functions exported by sunlinsol_pcg
+ * 
+ * CONSTRUCTOR:
+ *    SUNPCG creates and allocates memory for a PCG solver
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNPCG(N_Vector y, int pretype, int maxl);
+SUNDIALS_EXPORT int SUNPCGSetPrecType(SUNLinearSolver S, int pretype);
+SUNDIALS_EXPORT int SUNPCGSetMaxl(SUNLinearSolver S, int maxl);
+
+/*
+ * -----------------------------------------------------------------
+ * PCG implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_PCG(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_PCG(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetATimes_PCG(SUNLinearSolver S, void* A_data,
+                                           ATimesFn ATimes);
+SUNDIALS_EXPORT int SUNLinSolSetPreconditioner_PCG(SUNLinearSolver S,
+                                                   void* P_data,
+                                                   PSetupFn Pset,
+                                                   PSolveFn Psol);
+SUNDIALS_EXPORT int SUNLinSolSetScalingVectors_PCG(SUNLinearSolver S,
+                                                   N_Vector s,
+                                                   N_Vector nul);
+SUNDIALS_EXPORT int SUNLinSolSetup_PCG(SUNLinearSolver S, SUNMatrix nul);
+SUNDIALS_EXPORT int SUNLinSolSolve_PCG(SUNLinearSolver S, SUNMatrix nul,
+                                       N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT int SUNLinSolNumIters_PCG(SUNLinearSolver S);
+SUNDIALS_EXPORT realtype SUNLinSolResNorm_PCG(SUNLinearSolver S);
+SUNDIALS_EXPORT N_Vector SUNLinSolResid_PCG(SUNLinearSolver S);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_PCG(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_PCG(SUNLinearSolver S, 
+                                       long int *lenrwLS, 
+                                       long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_PCG(SUNLinearSolver S);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_spbcgs.h b/include/sunlinsol/sunlinsol_spbcgs.h
new file mode 100644
index 0000000..b821aad
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_spbcgs.h
@@ -0,0 +1,234 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on code sundials_spbcgs.h by: Peter Brown and 
+ *     Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the SPBCGS implementation of the 
+ * SUNLINSOL module.  The SPBCGS algorithm is based on the
+ * Scaled Preconditioned Bi-CG-Stabilized method.
+ *
+ * The SPBCGS algorithm solves a linear system A x = b.
+ * Preconditioning is allowed on the left, right, or both.
+ * Scaling is allowed on both sides.  We denote the preconditioner 
+ * and scaling matrices as follows:
+ *   P1 = left preconditioner
+ *   P2 = right preconditioner
+ *   S1 = diagonal matrix of scale factors for P1-inverse b
+ *   S2 = diagonal matrix of scale factors for P2 x
+ * The matrices A, P1, and P2 are not required explicitly; only
+ * routines that provide A, P1-inverse, and P2-inverse as
+ * operators are required.
+ *
+ * In this notation, SPBCGS applies the underlying GMRES method to
+ * the equivalent transformed system
+ *   Abar xbar = bbar , where
+ *   Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) ,
+ *   bbar = S1 (P1-inverse) b , and   xbar = S2 P2 x .
+ *
+ * The scaling matrices must be chosen so that vectors S1
+ * P1-inverse b and S2 P2 x have dimensionless components.
+ * If preconditioning is done on the left only (P2 = I), by a
+ * matrix P, then S2 must be a scaling for x, while S1 is a
+ * scaling for P-inverse b, and so may also be taken as a scaling
+ * for x.  Similarly, if preconditioning is done on the right only
+ * (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 is
+ * a scaling for P x, and may also be taken as a scaling for b.
+ *
+ * The stopping test for the SPBCGS iterations is on the L2 norm of
+ * the scaled preconditioned residual:
+ *      || bbar - Abar xbar ||_2  <  delta
+ * with an input test constant delta.
+ *
+ * The usage of this SPBCGS solver involves supplying up to three
+ * routines and making a variety of calls.  The user-supplied 
+ * routines are
+ *    atimes (A_data, x, y) to compute y = A x, given x,
+ *    psolve (P_data, y, x, lr) to solve P1 x = y or P2 x = y for 
+ *           x, given y,
+ *    psetup (P_data) to perform any 'setup' operations in 
+ *           preparation for calling psolve.
+ * The user calls are:
+ *    SUNLinearSolver LS = SUNSPBCGS(y, pretype, maxl);
+ *           to create the linear solver structure,
+ *    flag = SUNLinSolSetATimes(LS, A_data, atimes);
+ *           to set the matrix-vector product setup/apply routines,
+ *    flag = SUNLinSolSetPreconditioner(LS, P_data, psetup, psolve);
+ *           to *optionally* set the preconditioner setup/apply routines,
+ *    flag = SUNLinSolSetScalingVectors(LS, s1, s2);
+ *           to *optionally* set the diagonals of the scaling matrices.
+ *    flag = SUNLinSolInitialize(LS);
+ *           to perform internal solver memory allocations,
+ *    flag = SUNLinSolSetup(LS, NULL);
+ *           to call the psetup routine (if non-NULL);
+ *    flag = SUNLinSolSolve(LS, NULL, x, b, w, tol);
+ *           to solve the linear system to the tolerance 'tol'
+ *    long int nli = SUNLinSolNumIters(LS);
+ *           to *optionally* retrieve the number of linear iterations 
+ *           performed by the solver,
+ *    long int lastflag = SUNLinSolLastFlag(LS);
+ *           to *optionally* retrieve the last internal solver error flag,
+ *    realtype resnorm = SUNLinSolResNorm(LS);
+ *           to *optionally* retrieve the final linear residual norm,
+ *    flag = SUNLinSolFree(LS);
+ *           to free the solver memory.
+ * Complete details for specifying atimes, psetup and psolve 
+ * and for the usage calls are given below.
+ *
+ * -----------------------------------------------------------------
+ * 
+ * Part I contains declarations specific to the SPBCGS implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNSPBCGS as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_SPBCGS_H
+#define _SUNLINSOL_SPBCGS_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_spbcgs.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Default SPBCGS solver parameters */
+#define SUNSPBCGS_MAXL_DEFAULT 5
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: SPBCGS implementation of SUNLinearSolver
+ *
+ * The SPBCGS implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     maxl -- number of BiCGStab iterations to allow
+ *     pretype -- flag for type of preconditioning to employ
+ *     numiters -- number of iterations from most-recent solve
+ *     resnorm -- final linear residual norm from most-recent solve
+ *     last_flag -- last error return flag from internal setup/solve
+ *     ATimes -- function pointer to ATimes routine
+ *     ATData -- pointer to structure for ATimes
+ *     Psetup -- function pointer to preconditioner setup routine
+ *     Psolve -- function pointer to preconditioner solve routine
+ *     PData -- pointer to structure for Psetup/Psolve
+ *     s1,s2 -- vectors (type N_Vector) which holds the diagonals
+ *         of the scaling matrices S1 and S2, respectively
+ *     r -- a vector (type N_Vector) which holds the scaled,
+ *         preconditioned linear system residual
+ *     r_star -- a vector (type N_Vector) which holds the initial 
+ *         scaled, preconditioned linear system residual
+ *     p, q, u and Ap -- vectors (type N_Vector) used for workspace
+ *         by the SPBCG algorithm.
+ *     vtemp -- a vector (type N_Vector) used as temporary vector
+ *         storage during calculations.
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_SPBCGS {
+  int maxl;
+  int pretype;
+  int numiters;
+  realtype resnorm;
+  long int last_flag;
+
+  ATimesFn ATimes;
+  void* ATData;
+  PSetupFn Psetup;
+  PSolveFn Psolve;
+  void* PData;
+
+  N_Vector s1;
+  N_Vector s2;
+  N_Vector r;
+  N_Vector r_star;
+  N_Vector p;
+  N_Vector q;
+  N_Vector u;
+  N_Vector Ap;
+  N_Vector vtemp;
+};
+
+typedef struct _SUNLinearSolverContent_SPBCGS *SUNLinearSolverContent_SPBCGS;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_spbcgs
+ * 
+ * CONSTRUCTOR:
+ *    SUNSPBCGS creates and allocates memory for a SPBCGS solver
+ *
+ * "SET" ROUTINES:
+ *    SUNSPBCGSSetPrecType updates the type of preconditioning to 
+ *       use.  Supported values are PREC_NONE, PREC_LEFT, PREC_RIGHT 
+ *       and PREC_BOTH.
+ *    SUNSPBCGSSetMaxl updates the maximum number of iterations to 
+ *       allow in the solver.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNSPBCGS(N_Vector y, int pretype, int maxl);
+SUNDIALS_EXPORT int SUNSPBCGSSetPrecType(SUNLinearSolver S, int pretype);
+SUNDIALS_EXPORT int SUNSPBCGSSetMaxl(SUNLinearSolver S, int maxl);
+
+/*
+ * -----------------------------------------------------------------
+ * SPBCGS implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_SPBCGS(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_SPBCGS(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetATimes_SPBCGS(SUNLinearSolver S, void* A_data,
+                                              ATimesFn ATimes);
+SUNDIALS_EXPORT int SUNLinSolSetPreconditioner_SPBCGS(SUNLinearSolver S,
+                                                      void* P_data,
+                                                      PSetupFn Pset,
+                                                      PSolveFn Psol);
+SUNDIALS_EXPORT int SUNLinSolSetScalingVectors_SPBCGS(SUNLinearSolver S,
+                                                      N_Vector s1,
+                                                      N_Vector s2);
+SUNDIALS_EXPORT int SUNLinSolSetup_SPBCGS(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_SPBCGS(SUNLinearSolver S, SUNMatrix A,
+                                          N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT int SUNLinSolNumIters_SPBCGS(SUNLinearSolver S);
+SUNDIALS_EXPORT realtype SUNLinSolResNorm_SPBCGS(SUNLinearSolver S);
+SUNDIALS_EXPORT N_Vector SUNLinSolResid_SPBCGS(SUNLinearSolver S);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_SPBCGS(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_SPBCGS(SUNLinearSolver S, 
+                                          long int *lenrwLS, 
+                                          long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_SPBCGS(SUNLinearSolver S);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_spfgmr.h b/include/sunlinsol/sunlinsol_spfgmr.h
new file mode 100644
index 0000000..24b2c42
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_spfgmr.h
@@ -0,0 +1,253 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on code sundials_spfgmr.h by: Daniel R. Reynolds and 
+ *    Hilari C. Tiedeman @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the SPFGMR implementation of the 
+ * SUNLINSOL module.  The SPFGMR algorithm is based on the
+ * Scaled Preconditioned FGMRES (Flexible Generalized Minimal 
+ * Residual) method [Y. Saad, SIAM J. Sci. Comput., 1993].
+ *
+ * The SPFGMR algorithm solves a linear system A x = b.
+ * Preconditioning is only allowed on the right.  Scaling is allowed 
+ * on both sides, and restarts are also allowed. We denote the
+ * preconditioner and scaling matrices as follows:
+ *   P = right preconditioner
+ *   S1 = diagonal matrix of scale factors for P-inverse b
+ *   S2 = diagonal matrix of scale factors for x
+ * The matrices A and P are not required explicitly; only routines 
+ * that provide A and P-inverse as operators are required.
+ *
+ * In this notation, SPFGMR applies the underlying GMRES method to
+ * the equivalent transformed system
+ *   Abar xbar = bbar , where
+ *   Abar = S1 A (P-inverse) (S2-inverse) ,
+ *   bbar = S1 b , and   xbar = S2 P x .
+ *
+ * The scaling matrices must be chosen so that vectors S1 b and 
+ * S2 P x have dimensionless components. If preconditioning is not 
+ * performed (P = I), then S2 must be a scaling for x, while S1 is a
+ * scaling for b.  Similarly, if preconditioning is performed, then
+ * S1 must be a scaling for b, while S2 is a scaling for P x, and may
+ * also be taken as a scaling for b.
+ *
+ * The stopping test for the SPFGMR iterations is on the L2 norm of
+ * the scaled preconditioned residual:
+ *      || bbar - Abar xbar ||_2  <  delta
+ * with an input test constant delta.
+ *
+ * The usage of this SPFGMR solver involves supplying up to three 
+ * routines and making a variety of calls.  The user-supplied routines are
+ *    atimes (A_data, x, y) to compute y = A x, given x,
+ *    psolve (P_data, y, x, lr) to solve P1 x = y or P2 x = y for 
+ *           x, given y,
+ *    psetup (P_data) to perform any 'setup' operations in 
+ *           preparation for calling psolve.
+ * The three user calls are:
+ *    SUNLinearSolver LS = SUNSPFGMR(y, pretype, maxl);
+ *           to create the linear solver structure,
+ *    flag = SUNLinSolSetATimes(LS, A_data, atimes);
+ *           to set the matrix-vector product setup/apply routines,
+ *    flag = SUNLinSolSetPreconditioner(LS, P_data, psetup, psolve);
+ *           to *optionally* set the preconditioner setup/apply routines,
+ *    flag = SUNLinSolInitialize(LS);
+ *           to perform internal solver memory allocations,
+ *    flag = SUNLinSolSetup(LS, NULL);
+ *           to call the psetup routine (if non-NULL);
+ *    flag = SUNLinSolSolve(LS, NULL, x, b, w, tol);
+ *           to solve the linear system to the tolerance 'tol'
+ *    long int nli = SUNLinSolNumIters(LS);
+ *           to *optionally* retrieve the number of linear iterations 
+ *           performed by the solver,
+ *    long int lastflag = SUNLinSolLastFlag(LS);
+ *           to *optionally* retrieve the last internal solver error flag,
+ *    flag = SUNLinSolFree(LS);
+ *           to free the solver memory.
+ * Complete details for specifying atimes, psetup and psolve 
+ * and for the usage calls are given below.
+ *
+ * -----------------------------------------------------------------
+ * 
+ * Part I contains declarations specific to the SPFGMR implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNSPFGMR as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_SPFGMR_H
+#define _SUNLINSOL_SPFGMR_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_spfgmr.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Default SPFGMR solver parameters */
+#define SUNSPFGMR_MAXL_DEFAULT    5
+#define SUNSPFGMR_MAXRS_DEFAULT   0
+#define SUNSPFGMR_GSTYPE_DEFAULT  MODIFIED_GS
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: SPFGMR implementation of SUNLinearSolver
+ *
+ * The SPFGMR implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     maxl -- number of GMRES basis vectors to use
+ *     pretype -- flag for type of preconditioning to employ
+ *     gstype -- flag for type of Gram-Schmidt orthogonalization
+ *     max_restarts -- number of GMRES restarts to allow
+ *     last_flag -- last error return flag from internal setup/solve
+ *     ATimes -- function pointer to ATimes routine
+ *     ATData -- pointer to structure for ATimes
+ *     Psetup -- function pointer to preconditioner setup routine
+ *     Psolve -- function pointer to preconditioner solve routine
+ *     PData -- pointer to structure for Psetup/Psolve
+ *     V -- the array of Krylov basis vectors v_1, ..., v_(maxl+1),
+ *         stored in V[0], ..., V[l_max]. Each v_i is a vector of 
+ *         type N_Vector.
+ *     Z -- the array of preconditioned basis vectors z_1, ..., 
+ *         z_(maxl+1), stored in Z[0], ..., Z[l_max]. Each z_i 
+ *         is a vector of type N_Vector.
+ *     Hes -- the (maxl+1) x maxl Hessenberg matrix. It is stored
+ *         row-wise so that the (i,j)th element is given by Hes[i][j].
+ *     givens -- a length 2*max array which represents the Givens 
+ *         rotation matrices that arise in the algorithm. The Givens 
+ *         rotation matrices F_0, F_1, ..., F_j, where F_i is
+ *
+ *             1
+ *               1
+ *                 c_i  -s_i      <--- row i
+ *                 s_i   c_i
+ *                           1
+ *                             1
+ *
+ *         are represented in the givens vector as
+ *         givens[0]=c_0, givens[1]=s_0, givens[2]=c_1, givens[3]=s_1,
+ *         ..., givens[2j]=c_j, givens[2j+1]=s_j.
+ *     xcor -- a vector (type N_Vector) which holds the scaled,
+ *         preconditioned correction to the initial guess
+ *     yg -- a length (maxl+1) array of realtype used to hold "short"
+ *         vectors (e.g. y and g).
+ *     vtemp -- a vector (type N_Vector) used as temporary vector
+ *         storage during calculations.
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_SPFGMR {
+  int maxl;
+  int pretype;
+  int gstype;
+  int max_restarts;
+  int numiters;
+  realtype resnorm;
+  long int last_flag;
+
+  ATimesFn ATimes;
+  void* ATData;
+  PSetupFn Psetup;
+  PSolveFn Psolve;
+  void* PData;
+
+  N_Vector s1;
+  N_Vector s2;
+  N_Vector *V;
+  N_Vector *Z;
+  realtype **Hes;
+  realtype *givens;
+  N_Vector xcor;
+  realtype *yg;
+  N_Vector vtemp;
+};
+
+typedef struct _SUNLinearSolverContent_SPFGMR *SUNLinearSolverContent_SPFGMR;
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_spfgmr
+ * 
+ * CONSTRUCTOR:
+ *    SUNSPFGMR creates and allocates memory for a SPFGMR solver
+ *
+ * "SET" ROUTINES:
+ *    SUNSPFGMRSetPrecType updates whether to use preconditioning.  
+ *       Since only right preconditioning is supported, the inputs 
+ *       PREC_LEFT, PREC_RIGHT and PREC_BOTH all result in 
+ *       PREC_RIGHT.  All other input values default to PREC_NONE.
+ *    SUNSPFGMRSetGSType sets the type of Gram-Schmidt 
+ *       orthogonalization to use.  Supported values are MODIFIED_GS 
+ *       and CLASSICAL_GS.
+ *    SUNSPFGMRSetMaxRestarts sets the number of FGMRES restarts to 
+ *       allow.  A negative input will result in the default of 0.
+ *
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNSPFGMR(N_Vector y, int pretype, int maxl);
+SUNDIALS_EXPORT int SUNSPFGMRSetPrecType(SUNLinearSolver S, int pretype);
+SUNDIALS_EXPORT int SUNSPFGMRSetGSType(SUNLinearSolver S, int gstype);
+SUNDIALS_EXPORT int SUNSPFGMRSetMaxRestarts(SUNLinearSolver S, int maxrs);
+
+/*
+ * -----------------------------------------------------------------
+ * SPFGMR implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_SPFGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_SPFGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetATimes_SPFGMR(SUNLinearSolver S, void* A_data,
+                                              ATimesFn ATimes);
+SUNDIALS_EXPORT int SUNLinSolSetPreconditioner_SPFGMR(SUNLinearSolver S,
+                                                      void* P_data,
+                                                      PSetupFn Pset,
+                                                      PSolveFn Psol);
+SUNDIALS_EXPORT int SUNLinSolSetScalingVectors_SPFGMR(SUNLinearSolver S,
+                                                      N_Vector s1,
+                                                      N_Vector s2);
+SUNDIALS_EXPORT int SUNLinSolSetup_SPFGMR(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_SPFGMR(SUNLinearSolver S, SUNMatrix A,
+                                          N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT int SUNLinSolNumIters_SPFGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT realtype SUNLinSolResNorm_SPFGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT N_Vector SUNLinSolResid_SPFGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_SPFGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_SPFGMR(SUNLinearSolver S, 
+                                          long int *lenrwLS, 
+                                          long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_SPFGMR(SUNLinearSolver S);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_spgmr.h b/include/sunlinsol/sunlinsol_spgmr.h
new file mode 100644
index 0000000..b8cb5e9
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_spgmr.h
@@ -0,0 +1,254 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on code sundials_spgmr.h by: Scott D. Cohen, 
+ *      Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the SPGMR implementation of the 
+ * SUNLINSOL module.  The SPGMR algorithm is based on the
+ * Scaled Preconditioned GMRES (Generalized Minimal Residual)
+ * method.
+ *
+ * The SPGMR algorithm solves a linear system A x = b.
+ * Preconditioning is allowed on the left, right, or both.
+ * Scaling is allowed on both sides, and restarts are also allowed.
+ * We denote the preconditioner and scaling matrices as follows:
+ *   P1 = left preconditioner
+ *   P2 = right preconditioner
+ *   S1 = diagonal matrix of scale factors for P1-inverse b
+ *   S2 = diagonal matrix of scale factors for P2 x
+ * The matrices A, P1, and P2 are not required explicitly; only
+ * routines that provide A, P1-inverse, and P2-inverse as
+ * operators are required.
+ *
+ * In this notation, SPGMR applies the underlying GMRES method to
+ * the equivalent transformed system
+ *   Abar xbar = bbar , where
+ *   Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) ,
+ *   bbar = S1 (P1-inverse) b , and   xbar = S2 P2 x .
+ *
+ * The scaling matrices must be chosen so that vectors S1
+ * P1-inverse b and S2 P2 x have dimensionless components.
+ * If preconditioning is done on the left only (P2 = I), by a
+ * matrix P, then S2 must be a scaling for x, while S1 is a
+ * scaling for P-inverse b, and so may also be taken as a scaling
+ * for x.  Similarly, if preconditioning is done on the right only
+ * (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 is
+ * a scaling for P x, and may also be taken as a scaling for b.
+ *
+ * The stopping test for the SPGMR iterations is on the L2 norm of
+ * the scaled preconditioned residual:
+ *      || bbar - Abar xbar ||_2  <  delta
+ * with an input test constant delta.
+ *
+ * The usage of this SPGMR solver involves supplying three routines
+ * and making a variety of calls.  The user-supplied routines are
+ *    atimes (A_data, x, y) to compute y = A x, given x,
+ *    psolve (P_data, y, x, lr) to solve P1 x = y or P2 x = y for 
+ *           x, given y,
+ *    psetup (P_data) to perform any 'setup' operations in 
+ *           preparation for calling psolve.
+ * The user calls are:
+ *    SUNLinearSolver LS = SUNSPGMR(y, pretype, maxl);
+ *           to create the linear solver structure,
+ *    flag = SUNLinSolSetATimes(LS, A_data, atimes);
+ *           to set the matrix-vector product setup/apply routines,
+ *    flag = SUNLinSolSetPreconditioner(LS, P_data, psetup, psolve);
+ *           to *optionally* set the preconditioner setup/apply routines,
+ *    flag = SUNLinSolInitialize(LS);
+ *           to perform internal solver memory allocations,
+ *    flag = SUNLinSolSetup(LS, NULL);
+ *           to call the psetup routine (if non-NULL);
+ *    flag = SUNLinSolSolve(LS, NULL, x, b, w, tol);
+ *           to solve the linear system to the tolerance 'tol'
+ *    long int nli = SUNLinSolNumIters(LS);
+ *           to *optionally* retrieve the number of linear iterations 
+ *           performed by the solver,
+ *    long int lastflag = SUNLinSolLastFlag(LS);
+ *           to *optionally* retrieve the last internal solver error flag,
+ *    flag = SUNLinSolFree(LS);
+ *           to free the solver memory.
+ * Complete details for specifying atimes, psetup and psolve 
+ * and for the usage calls are given below.
+ *
+ * -----------------------------------------------------------------
+ * 
+ * Part I contains declarations specific to the SPGMR implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNSPGMR as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_SPGMR_H
+#define _SUNLINSOL_SPGMR_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_spgmr.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Default SPGMR solver parameters */
+#define SUNSPGMR_MAXL_DEFAULT    5
+#define SUNSPGMR_MAXRS_DEFAULT   0
+#define SUNSPGMR_GSTYPE_DEFAULT  MODIFIED_GS
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: SPGMR implementation of SUNLinearSolver
+ *
+ * The SPGMR implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     maxl -- number of GMRES basis vectors to use
+ *     pretype -- flag for type of preconditioning to employ
+ *     gstype -- flag for type of Gram-Schmidt orthogonalization
+ *     max_restarts -- number of GMRES restarts to allow
+ *     numiters -- number of iterations from most-recent solve
+ *     resnorm -- final linear residual norm from most-recent solve
+ *     last_flag -- last error return flag from internal setup/solve
+ *     ATimes -- function pointer to ATimes routine
+ *     ATData -- pointer to structure for ATimes
+ *     Psetup -- function pointer to preconditioner setup routine
+ *     Psolve -- function pointer to preconditioner solve routine
+ *     PData -- pointer to structure for Psetup/Psolve
+ *     s1, s2 -- vector pointers for supplied scaling matrices
+ *     V -- the array of Krylov basis vectors v_1, ..., v_(maxl+1),
+ *         stored in V[0], ..., V[maxl]. Each v_i is a vector of 
+ *         type N_Vector.
+ *     Hes -- the (maxl+1) x maxl Hessenberg matrix. It is stored
+ *         row-wise so that the (i,j)th element is given by Hes[i][j].
+ *     givens -- a length 2*max array which represents the Givens 
+ *         rotation matrices that arise in the algorithm. The Givens 
+ *         rotation matrices F_0, F_1, ..., F_j, where F_i is
+ *
+ *             1
+ *               1
+ *                 c_i  -s_i      <--- row i
+ *                 s_i   c_i
+ *                           1
+ *                             1
+ *
+ *         are represented in the givens vector as
+ *         givens[0]=c_0, givens[1]=s_0, givens[2]=c_1, givens[3]=s_1,
+ *         ..., givens[2j]=c_j, givens[2j+1]=s_j.
+ *     xcor -- a vector (type N_Vector) which holds the scaled,
+ *         preconditioned correction to the initial guess
+ *     yg -- a length (maxl+1) array of realtype used to hold "short"
+ *         vectors (e.g. y and g).
+ *     vtemp -- a vector used as temporary vector storage
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_SPGMR {
+  int maxl;
+  int pretype;
+  int gstype;
+  int max_restarts;
+  int numiters;
+  realtype resnorm;
+  long int last_flag;
+
+  ATimesFn ATimes;
+  void* ATData;
+  PSetupFn Psetup;
+  PSolveFn Psolve;
+  void* PData;
+
+  N_Vector s1;
+  N_Vector s2;
+  N_Vector *V;
+  realtype **Hes;
+  realtype *givens;
+  N_Vector xcor;
+  realtype *yg;
+  N_Vector vtemp;
+};
+
+typedef struct _SUNLinearSolverContent_SPGMR *SUNLinearSolverContent_SPGMR;
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_spgmr
+ * 
+ * CONSTRUCTOR:
+ *    SUNSPGMR creates and allocates memory for a SPGMR solver
+ *
+ * "SET" ROUTINES:
+ *    SUNSPGMRSetPrecType updates the type of preconditioning to 
+ *       use.  Supported values are PREC_NONE, PREC_LEFT, PREC_RIGHT 
+ *       and PREC_BOTH.
+ *    SUNSPGMRSetGSType sets the type of Gram-Schmidt 
+ *       orthogonalization to use.  Supported values are MODIFIED_GS 
+ *       and CLASSICAL_GS.
+ *    SUNSPGMRSetMaxRestarts sets the number of GMRES restarts to 
+ *       allow.  A negative input will result in the default of 0.
+ * 
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNSPGMR(N_Vector y, int pretype, int maxl);
+SUNDIALS_EXPORT int SUNSPGMRSetPrecType(SUNLinearSolver S, int pretype);
+SUNDIALS_EXPORT int SUNSPGMRSetGSType(SUNLinearSolver S, int gstype);
+SUNDIALS_EXPORT int SUNSPGMRSetMaxRestarts(SUNLinearSolver S, int maxrs);
+
+/*
+ * -----------------------------------------------------------------
+ * SPGMR implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_SPGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_SPGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetATimes_SPGMR(SUNLinearSolver S, void* A_data,
+                                             ATimesFn ATimes);
+SUNDIALS_EXPORT int SUNLinSolSetPreconditioner_SPGMR(SUNLinearSolver S,
+                                                     void* P_data,
+                                                     PSetupFn Pset,
+                                                     PSolveFn Psol);
+SUNDIALS_EXPORT int SUNLinSolSetScalingVectors_SPGMR(SUNLinearSolver S,
+                                                     N_Vector s1,
+                                                     N_Vector s2);
+SUNDIALS_EXPORT int SUNLinSolSetup_SPGMR(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_SPGMR(SUNLinearSolver S, SUNMatrix A,
+                                         N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT int SUNLinSolNumIters_SPGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT realtype SUNLinSolResNorm_SPGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT N_Vector SUNLinSolResid_SPGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_SPGMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_SPGMR(SUNLinearSolver S, 
+                                         long int *lenrwLS, 
+                                         long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_SPGMR(SUNLinearSolver S);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_sptfqmr.h b/include/sunlinsol/sunlinsol_sptfqmr.h
new file mode 100644
index 0000000..1260cbb
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_sptfqmr.h
@@ -0,0 +1,229 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on code sundials_sptfqmr.h by: Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the SPTFQMR implementation of the 
+ * SUNLINSOL module.  The SPTFQMR algorithm is based on the
+ * Scaled Preconditioned Transpose-free Quasi-Minimum Residual method.
+ *
+ * The SPTFQMR algorithm solves a linear system A x = b.
+ * Preconditioning is allowed on the left, right, or both.
+ * Scaling is allowed on both sides.
+ * We denote the preconditioner and scaling matrices as follows:
+ *   P1 = left preconditioner
+ *   P2 = right preconditioner
+ *   S1 = diagonal matrix of scale factors for P1-inverse b
+ *   S2 = diagonal matrix of scale factors for P2 x
+ * The matrices A, P1, and P2 are not required explicitly; only
+ * routines that provide A, P1-inverse, and P2-inverse as
+ * operators are required.
+ *
+ * In this notation, SPTFQMR applies the underlying TFQMR method to
+ * the equivalent transformed system
+ *   Abar xbar = bbar , where
+ *   Abar = S1 (P1-inverse) A (P2-inverse) (S2-inverse) ,
+ *   bbar = S1 (P1-inverse) b , and   xbar = S2 P2 x .
+ *
+ * The scaling matrices must be chosen so that vectors S1
+ * P1-inverse b and S2 P2 x have dimensionless components.
+ * If preconditioning is done on the left only (P2 = I), by a
+ * matrix P, then S2 must be a scaling for x, while S1 is a
+ * scaling for P-inverse b, and so may also be taken as a scaling
+ * for x.  Similarly, if preconditioning is done on the right only
+ * (P1 = I, P2 = P), then S1 must be a scaling for b, while S2 is
+ * a scaling for P x, and may also be taken as a scaling for b.
+ *
+ * The stopping test for the SPTFQMR iterations is on the L2 norm of
+ * the scaled preconditioned residual:
+ *      || bbar - Abar xbar ||_2  <  delta
+ * with an input test constant delta.
+ *
+ * The usage of this SPTFQMR solver involves supplying up to three 
+ * routines and making a variety of calls.  The user-supplied routines are
+ *    atimes (A_data, x, y) to compute y = A x, given x,
+ *    psolve (P_data, y, x, lr) to solve P1 x = y or P2 x = y for 
+ *           x, given y,
+ *    psetup (P_data) to perform any 'setup' operations in 
+ *           preparation for calling psolve.
+ * The three user calls are:
+ *    SUNLinearSolver LS = SUNSPTFQMR(y, pretype, maxl);
+ *           to create the linear solver structure,
+ *    flag = SUNLinSolSetATimes(LS, A_data, atimes);
+ *           to set the matrix-vector product setup/apply routines,
+ *    flag = SUNLinSolSetPreconditioner(LS, P_data, psetup, psolve);
+ *           to *optionally* set the preconditioner setup/apply routines,
+ *    flag = SUNLinSolInitialize(LS);
+ *           to perform internal solver memory allocations,
+ *    flag = SUNLinSolSetup(LS, NULL);
+ *           to call the psetup routine (if non-NULL);
+ *    flag = SUNLinSolSolve(LS, NULL, x, b, w, tol);
+ *           to solve the linear system to the tolerance 'tol'
+ *    long int nli = SUNLinSolNumIters(LS);
+ *           to *optionally* retrieve the number of linear iterations 
+ *           performed by the solver,
+ *    long int lastflag = SUNLinSolLastFlag(LS);
+ *           to *optionally* retrieve the last internal solver error flag,
+ *    flag = SUNLinSolFree(LS);
+ *           to free the solver memory.
+ * Complete details for specifying atimes, psetup and psolve 
+ * and for the usage calls are given below.
+ *
+ * -----------------------------------------------------------------
+ * 
+ * Part I contains declarations specific to the SPTFQMR implementation
+ * of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNSPTFQMR as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_SPTFQMR_H
+#define _SUNLINSOL_SPTFQMR_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_sptfqmr.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Default SPTFQMR solver parameters */
+#define SUNSPTFQMR_MAXL_DEFAULT    5
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: SPTFQMR implementation of SUNLinearSolver
+ *
+ * The SPTFQMR implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     maxl -- number of BiCGStab iterations to allow
+ *     pretype -- flag for type of preconditioning to employ
+ *     numiters -- number of iterations from most-recent solve
+ *     resnorm -- final linear residual norm from most-recent solve
+ *     last_flag -- last error return flag from internal setup/solve
+ *     ATimes -- function pointer to ATimes routine
+ *     ATData -- pointer to structure for ATimes
+ *     Psetup -- function pointer to preconditioner setup routine
+ *     Psolve -- function pointer to preconditioner solve routine
+ *     PData -- pointer to structure for Psetup/Psolve
+ *     s1, s2 -- vector pointers for supplied scaling matrices
+ *     r_star -- a vector (type N_Vector) which holds the initial 
+ *         scaled, preconditioned linear system residual
+ *     q, d, v, p and u -- vectors (type N_Vector) used for 
+ *         workspace by the SPTFQMR algorithm
+ *     r -- array of vectors (type N_Vector) used for workspace 
+ *         within the SPTFQMR algorithm
+ *     vtemp1/vtemp2/vtemp3 -- scratch vectors (type N_Vector) used
+ *         as temporary vector storage during calculations.
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_SPTFQMR {
+  int maxl;
+  int pretype;
+  int numiters;
+  realtype resnorm;
+  long int last_flag;
+
+  ATimesFn ATimes;
+  void* ATData;
+  PSetupFn Psetup;
+  PSolveFn Psolve;
+  void* PData;
+
+  N_Vector s1;
+  N_Vector s2;
+  N_Vector r_star;
+  N_Vector q;
+  N_Vector d;
+  N_Vector v;
+  N_Vector p;
+  N_Vector *r;
+  N_Vector u;
+  N_Vector vtemp1;
+  N_Vector vtemp2;
+  N_Vector vtemp3;
+};
+
+typedef struct _SUNLinearSolverContent_SPTFQMR *SUNLinearSolverContent_SPTFQMR;
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_sptfqmr
+ * 
+ * CONSTRUCTOR:
+ *    SUNSPTFQMR creates and allocates memory for a SPTFQMR solver
+ *
+ * "SET" ROUTINES:
+ *    SUNSPTFQMRSSetPrecType updates the type of preconditioning to 
+ *       use.  Supported values are PREC_NONE, PREC_LEFT, PREC_RIGHT 
+ *       and PREC_BOTH.
+ *    SUNSPTFQMRSetMaxl updates the maximum number of iterations to 
+ *       allow in the solver.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNSPTFQMR(N_Vector y, int pretype, int maxl);
+SUNDIALS_EXPORT int SUNSPTFQMRSetPrecType(SUNLinearSolver S, int pretype);
+SUNDIALS_EXPORT int SUNSPTFQMRSetMaxl(SUNLinearSolver S, int maxl);
+
+/*
+ * -----------------------------------------------------------------
+ * SPTFQMR implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_SPTFQMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_SPTFQMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetATimes_SPTFQMR(SUNLinearSolver S, void* A_data,
+                                               ATimesFn ATimes);
+SUNDIALS_EXPORT int SUNLinSolSetPreconditioner_SPTFQMR(SUNLinearSolver S,
+                                                       void* P_data,
+                                                       PSetupFn Pset,
+                                                       PSolveFn Psol);
+SUNDIALS_EXPORT int SUNLinSolSetScalingVectors_SPTFQMR(SUNLinearSolver S,
+                                                       N_Vector s1,
+                                                       N_Vector s2);
+SUNDIALS_EXPORT int SUNLinSolSetup_SPTFQMR(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_SPTFQMR(SUNLinearSolver S, SUNMatrix A,
+                                           N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT int SUNLinSolNumIters_SPTFQMR(SUNLinearSolver S);
+SUNDIALS_EXPORT realtype SUNLinSolResNorm_SPTFQMR(SUNLinearSolver S);
+SUNDIALS_EXPORT N_Vector SUNLinSolResid_SPTFQMR(SUNLinearSolver S);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_SPTFQMR(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_SPTFQMR(SUNLinearSolver S, 
+                                           long int *lenrwLS, 
+                                           long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_SPTFQMR(SUNLinearSolver S);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunlinsol/sunlinsol_superlumt.h b/include/sunlinsol/sunlinsol_superlumt.h
new file mode 100644
index 0000000..177e914
--- /dev/null
+++ b/include/sunlinsol/sunlinsol_superlumt.h
@@ -0,0 +1,169 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on codes sundials_superlumt_impl.h and <solver>_superlumt.h
+ *     written by Carol S. Woodward @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the SuperLUMT implementation of the 
+ * SUNLINSOL module.
+ * 
+ * Part I contains declarations specific to the SuperLUMT 
+ * implementation of the supplied SUNLINSOL module.
+ * 
+ * Part II contains the prototype for the constructor 
+ * SUNSuperLUMT as well as implementation-specific prototypes 
+ * for various useful solver operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNLinearSolver structure can 
+ *     be found in the header file sundials_linearsolver.h.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNLINSOL_SLUMT_H
+#define _SUNLINSOL_SLUMT_H
+
+#include <sundials/sundials_linearsolver.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+
+/* assume SuperLU_MT library was built with compatible index type */  
+#if defined(SUNDIALS_INT64_T)
+#define _LONGINT
+#endif
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/* Default SuperLU_MT solver parameters */
+#define SUNSLUMT_ORDERING_DEFAULT  3     /* COLAMD */
+
+/* Interfaces to match 'realtype' with the correct SuperLUMT functions */
+#if defined(SUNDIALS_DOUBLE_PRECISION)
+#ifndef _SLUMT_H
+#define _SLUMT_H
+#include "slu_mt_ddefs.h"
+#endif
+#define xgstrs                  dgstrs
+#define pxgstrf                 pdgstrf
+#define pxgstrf_init            pdgstrf_init
+#define xCreate_Dense_Matrix    dCreate_Dense_Matrix
+#define xCreate_CompCol_Matrix  dCreate_CompCol_Matrix
+#elif defined(SUNDIALS_SINGLE_PRECISION)
+#ifndef _SLUMT_H
+#define _SLUMT_H
+#include "slu_mt_sdefs.h"
+#endif
+#define xgstrs                  sgstrs
+#define pxgstrf                 psgstrf
+#define pxgstrf_init            psgstrf_init
+#define xCreate_Dense_Matrix    sCreate_Dense_Matrix
+#define xCreate_CompCol_Matrix  sCreate_CompCol_Matrix
+#else  /* incompatible sunindextype for SuperLUMT */
+#error  Incompatible realtype for SuperLUMT
+#endif
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART I: SuperLUMT implementation of SUNLinearSolver
+ *
+ * The SuperLUMT implementation of the SUNLinearSolver 'content' 
+ * structure contains:
+ *     last_flag -- last error return flag from internal setup/solve
+ *     first_factorize -- flag indicating whether the factorization 
+ *       has ever been performed
+ *     A, AC, L, U, B -- SuperMatrix pointers used in solve
+ *     Gstat -- GStat_t object used in solve
+ *     perm_r, perm_c -- permutation arrays used in solve
+ *     N -- size of the linear system
+ *     num_threads -- number of OpenMP/Pthreads threads to use
+ *     diag_pivot_thresh -- threshold on diagonal pivoting
+ *     ordering -- flag for reordering algorithm to use
+ *     options -- pointer to SuperLUMT options structure
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNLinearSolverContent_SuperLUMT {
+  long int     last_flag;
+  int          first_factorize;
+  SuperMatrix  *A, *AC, *L, *U, *B;
+  Gstat_t      *Gstat;
+  sunindextype *perm_r, *perm_c;
+  sunindextype N;
+  int          num_threads;
+  realtype     diag_pivot_thresh; 
+  int          ordering;
+  superlumt_options_t *options;
+};
+
+typedef struct _SUNLinearSolverContent_SuperLUMT *SUNLinearSolverContent_SuperLUMT;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART II: functions exported by sunlinsol_slumt
+ * 
+ * CONSTRUCTOR:
+ *    SUNSuperLUMT creates and allocates memory for a SuperLUMT sparse-direct 
+ *      linear solver
+ *
+ * OTHER:
+ *    SUNSuperLUMTSetOrdering sets the ordering used by SuperLUMT for reducing 
+ *      fill in the linear solve.  Options for ordering_choice are: 
+ *         0 for natural ordering
+ *         1 for minimal degree ordering on A'*A
+ *         2 for minimal degree ordering on A'+A
+ *         3 for AMD ordering for unsymmetric matrices
+ *      The default used in SUNDIALS is 3 for COLAMD.
+ *
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver SUNSuperLUMT(N_Vector y, SUNMatrix A,
+                                             int num_threads);
+
+SUNDIALS_EXPORT int SUNSuperLUMTSetOrdering(SUNLinearSolver S,
+                                            int ordering_choice);
+
+/*
+ * -----------------------------------------------------------------
+ * SuperLUMT implementations of various useful linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNLinearSolver_Type SUNLinSolGetType_SuperLUMT(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolInitialize_SuperLUMT(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSetup_SuperLUMT(SUNLinearSolver S, SUNMatrix A);
+SUNDIALS_EXPORT int SUNLinSolSolve_SuperLUMT(SUNLinearSolver S, SUNMatrix A,
+                                       N_Vector x, N_Vector b, realtype tol);
+SUNDIALS_EXPORT long int SUNLinSolLastFlag_SuperLUMT(SUNLinearSolver S);
+SUNDIALS_EXPORT int SUNLinSolSpace_SuperLUMT(SUNLinearSolver S, 
+                                             long int *lenrwLS, 
+                                             long int *leniwLS);
+SUNDIALS_EXPORT int SUNLinSolFree_SuperLUMT(SUNLinearSolver S);
+  
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunmatrix/sunmatrix_band.h b/include/sunmatrix/sunmatrix_band.h
new file mode 100644
index 0000000..54f440b
--- /dev/null
+++ b/include/sunmatrix/sunmatrix_band.h
@@ -0,0 +1,334 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * Based on code sundials_direct.h by: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the band implementation of the 
+ * SUNMATRIX module.
+ * 
+ * Part I contains declarations specific to the band implementation
+ * of the supplied SUNMATRIX module.
+ * 
+ * Part II defines accessor macros that allow the user to 
+ * efficiently use this SUNMatrix type without making explicit
+ * references to the underlying data structure.
+ *
+ * Part III contains the prototype for the constructor 
+ * SUNBandMatrix as well as implementation-specific prototypes 
+ * for various useful matrix operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNMatrix structure can be found
+ *     in the header file sundials_matrix.h.
+ *
+ *   - The definition of the type 'realtype' can be found in the
+ *     header file sundials_types.h, and it may be changed (at the 
+ *     configuration stage) according to the user's needs. 
+ *     The sundials_types.h file also contains the definition
+ *     for the type 'booleantype' and 'indextype'.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNMATRIX_BAND_H
+#define _SUNMATRIX_BAND_H
+
+#include <sundials/sundials_matrix.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: Band implementation of SUNMatrix
+ *
+ * The band implementation of the SUNMatrix 'content' structure
+ * contains:
+ *   M     - number of rows
+ *   N     - number of columns
+ *   mu    - upper bandwidth, 0 <= mu <= min(M,N)
+ *   ml    - lower bandwidth, 0 <= ml <= min(M,N)
+ *   s_mu  - storage upper bandwidth, mu <= s_mu <= N-1.
+ *           The dgbtrf routine writes the LU factors into the storage 
+ *           for A. The upper triangular factor U, however, may have 
+ *           an upper bandwidth as big as MIN(N-1,mu+ml) because of 
+ *           partial pivoting. The s_mu field holds the upper 
+ *           bandwidth allocated for A.
+ *   ldim  - leading dimension (ldim >= s_mu)
+ *   data  - pointer to a contiguous block of realtype variables
+ *   ldata - length of the data array = ldim*(s_mu+ml+1)
+ *   cols  - array of pointers. cols[j] points to the first element 
+ *           of the j-th column of the matrix in the array data.
+ * The elements of a band matrix are stored columnwise (i.e. columns 
+ * are stored one on top of the other in memory); i.e. if A is a 
+ * SUNMatrix_Band object, then the (i,j)th element of A (with 
+ * 0 <= i < M and 0 <= j < N) is given by ???
+ *
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNMatrixContent_Band {
+  sunindextype M;
+  sunindextype N;
+  sunindextype ldim;
+  sunindextype mu;
+  sunindextype ml;
+  sunindextype s_mu;
+  realtype *data;
+  sunindextype ldata;
+  realtype **cols;
+};
+
+typedef struct _SUNMatrixContent_Band *SUNMatrixContent_Band;
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART II: macros SM_CONTENT_B, SM_DATA_B, SM_ROWS_B, SM_COLUMNS_B, 
+ *          SM_UBAND_B, SM_LBAND_B, SM_SUBAND_B, SM_LDIM_B, SM_COLS_B, 
+ *          SM_COLUMN_B, SM_COLUMN_ELEMENT_B, and SM_ELEMENT_B
+ * -----------------------------------------------------------------
+ * In the descriptions below, the following user declarations
+ * are assumed:
+ *
+ * SUNMatrix A;
+ * SUNMatrixContent_Band A_cont;
+ * realtype *A_col_j, *A_data, **A_cols, A_ij;
+ * sunindextype i, j, A_rows, A_columns, A_ldata, A_ldim;
+ *
+ * (1) SM_CONTENT_B
+ *
+ *     This macro gives access to the contents of the band
+ *     SUNMatrix
+ *
+ *     The assignment A_cont = SM_CONTENT_B(A) sets A_cont to be
+ *     a pointer to the band SUNMatrix content structure.
+ *
+ * (2) SM_DATA_B, SM_ROWS_B, SM_COLUMNS_B, SM_LDATA_B, SM_LDIM_B, 
+ *     SM_UBAND_B, SM_LBAND_B and SM_SUBAND_B
+ *
+ *     These macros give access to the individual parts of
+ *     the content structure of a band SUNMatrix.
+ *
+ *     The assignment A_data = SM_DATA_B(A) sets A_data to be
+ *     a pointer to the first component of A. 
+ *
+ *     The assignment A_cols = SM_COLS_B(A) sets A_cols to be
+ *     a pointer to the content's 'cols' entry.
+ *
+ *     The assignment A_rows = SM_ROWS_B(A) sets A_rows to be
+ *     the number of rows in A.
+ *
+ *     The assignment A_columns = SM_COLUMNS_B(A) sets A_columns 
+ *     to be the number of columns in A.
+ *
+ *     The assignment A_ldata = SM_LDATA_B(A) sets A_ldata to be
+ *     the length of the data array for A.
+ *
+ *     The assignment A_mu = SM_UBAND_B(A) sets A_mu to be
+ *     the upper bandwidth of A.
+ *
+ *     The assignment A_ml = SM_LBAND_B(A) sets A_lu to be
+ *     the lower bandwidth of A.
+ *
+ *     The assignment A_smu = SM_SUBAND_B(A) sets A_smu to be
+ *     the storage upper bandwidth of A.
+ *
+ *     The assignment A_ldim = SM_LDIM_B(A) sets A_ldim to be
+ *     the length of the leading dimension of A.
+ *
+ * (3) SM_COLUMN_B, SM_COLUMN_ELEMENT_B and SM_ELEMENT_B
+ *
+ *     These macros give access to the individual columns and 
+ *     elements of a band SUNMatrix, respectively.  In the 
+ *     following, the entries of a SUNMatrix are indexed (i,j) 
+ *     where i=0,...,M-1 and j=0,...,N-1.
+ *     
+ *     The assignment A_col_j = SM_COLUMN_B(A,j) sets A_col_j to 
+ *     be a pointer to the jth column of the M-by-N band
+ *     matrix A, 0 <= j < N.  After the assignment, A_col_j may 
+ *     be treated as an array indexed from -mu to ml.
+ *     The (i,j)-th element of A is thus referenced by col_j[i-j].
+ *
+ *     The assignment A_ij = SM_COLUMN_ELEMENT_B(SM_COLUMN_B(A),i,j) 
+ *     sets A_ij to the value of the (i,j)th element of the band 
+ *     M-by-N matrix A, when used in conjunction with SM_COLUMN_B.  
+ *     The index (i,j) should satisfy j-mu <= i <= j+ml, with 
+ *     0 <= i < M and 0 <= j < N.  Similarly, the assignment  
+ *     SM_COLUMN_ELEMENT_B(SM_COLUMN_B(A),i,j) = A_ij sets the value 
+ *     of A_ij into the (i,j) location of the matrix A.
+ *
+ *     The assignment A_ij = SM_ELEMENT_B(A,i,j) sets A_ij to 
+ *     the value of the (i,j)th element of the band M-by-N matrix
+ *     A.  The location (i,j) should satisfy j-mu <= i <= j+ml, 
+ *     with 0 <= i < M ; 0 <= j < N.  Similarly, the assignment 
+ *     SM_ELEMENT_B(A,i,j) = A_ij sets the value of A_ij into the 
+ *     (i,j) location of the matrix A.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#define SM_CONTENT_B(A)     ( (SUNMatrixContent_Band)(A->content) )
+
+#define SM_ROWS_B(A)        ( SM_CONTENT_B(A)->M )
+
+#define SM_COLUMNS_B(A)     ( SM_CONTENT_B(A)->N )
+
+#define SM_LDATA_B(A)       ( SM_CONTENT_B(A)->ldata )
+
+#define SM_UBAND_B(A)       ( SM_CONTENT_B(A)->mu )
+
+#define SM_LBAND_B(A)       ( SM_CONTENT_B(A)->ml )
+
+#define SM_SUBAND_B(A)      ( SM_CONTENT_B(A)->s_mu )
+
+#define SM_LDIM_B(A)        ( SM_CONTENT_B(A)->ldim )
+
+#define SM_DATA_B(A)        ( SM_CONTENT_B(A)->data )
+
+#define SM_COLS_B(A)        ( SM_CONTENT_B(A)->cols )
+
+#define SM_COLUMN_B(A,j)    ( ((SM_CONTENT_B(A)->cols)[j])+SM_SUBAND_B(A) )
+
+#define SM_COLUMN_ELEMENT_B(col_j,i,j) (col_j[(i)-(j)])
+
+#define SM_ELEMENT_B(A,i,j) ( (SM_CONTENT_B(A)->cols)[j][(i)-(j)+SM_SUBAND_B(A)] )
+
+
+/*
+ * -----------------------------------------------------------------
+ * PART III: functions exported by sunmatrix_band
+ * 
+ * CONSTRUCTORS:
+ *    SUNBandMatrix
+ * OTHER:
+ *    SUNBandMatrix_Print
+ *    SUNBandMatrix_Rows
+ *    SUNBandMatrix_Columns
+ *    SUNBandMatrix_LowerBandwidth
+ *    SUNBandMatrix_UpperBandwidth
+ *    SUNBandMatrix_StoredUpperBandwidth
+ *    SUNBandMatrix_LDim
+ *    SUNBandMatrix_Data
+ *    SUNBandMatrix_Cols
+ *    SUNBandMatrix_Column
+ * -----------------------------------------------------------------
+ */
+
+
+/*
+ * -----------------------------------------------------------------
+ * Function: SUNBandMatrix
+ * -----------------------------------------------------------------
+ * SUNBandMatrix creates and allocates memory for an M-by-N 
+ * band matrix with upper bandwidth mu, lower bandwidth ml, and 
+ * storage upper bandwidth smu. Pass smu as follows depending on 
+ * whether A will be LU factored:
+ *
+ * (1) Pass smu = mu if A will not be factored.
+ *
+ * (2) Pass smu = MIN(N-1,mu+ml) if A will be factored.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix SUNBandMatrix(sunindextype N, sunindextype mu,
+                                        sunindextype ml, sunindextype smu);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: SUNBandMatrix_Print
+ * -----------------------------------------------------------------
+ * This function prints the content of a M-by-N band matrix A to
+ * a file pointer as it would normally appear on paper.
+ * It is intended as debugging tools with small values of M and N.
+ * The elements are printed using the %g/%lg/%Lg option. 
+ * A blank line is printed before and after the matrix.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void SUNBandMatrix_Print(SUNMatrix A, FILE* outfile);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Accessor Functions: 
+ *
+ * SUNBandMatrix_Rows
+ *    Returns the number of rows in the banded matrix
+ *
+ * SUNBandMatrix_Columns
+ *    Returns the number of columns in the banded matrix
+ *
+ * SUNBandMatrix_LowerBandwidth
+ *    Returns the number of lower bands in the banded matrix
+ *
+ * SUNBandMatrix_UpperBandwidth
+ *    Returns the number of upper bands in the banded matrix
+ *
+ * SUNBandMatrix_StoredUpperBandwidth
+ *    Returns the number of stored upper bands in the banded matrix
+ *
+ * SUNBandMatrix_LDim
+ *    Returns the length of the leading dimension of A.
+ *
+ * SUNBandMatrix_Data
+ *    Returns a pointer to the data array for the banded matrix
+ *
+ * SUNBandMatrix_Cols
+ *    Returns a pointer to the cols array for the banded matrix
+ *
+ * SUNBandMatrix_Column
+ *    Returns a pointer to the diagonal entry of jth column of the
+ *    banded matrix.  The resulting pointer should be indexed over 
+ *    the range -mu to ml.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT sunindextype SUNBandMatrix_Rows(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNBandMatrix_Columns(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNBandMatrix_LowerBandwidth(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNBandMatrix_UpperBandwidth(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNBandMatrix_StoredUpperBandwidth(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNBandMatrix_LDim(SUNMatrix A);
+SUNDIALS_EXPORT realtype* SUNBandMatrix_Data(SUNMatrix A);
+SUNDIALS_EXPORT realtype** SUNBandMatrix_Cols(SUNMatrix A);
+SUNDIALS_EXPORT realtype* SUNBandMatrix_Column(SUNMatrix A, sunindextype j);
+
+/*
+ * -----------------------------------------------------------------
+ * band implementations of various useful matrix operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix_ID SUNMatGetID_Band(SUNMatrix A);
+SUNDIALS_EXPORT SUNMatrix SUNMatClone_Band(SUNMatrix A);
+SUNDIALS_EXPORT void SUNMatDestroy_Band(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatZero_Band(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatCopy_Band(SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAdd_Band(realtype c, SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAddI_Band(realtype c, SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatMatvec_Band(SUNMatrix A, N_Vector x, N_Vector y);
+SUNDIALS_EXPORT int SUNMatSpace_Band(SUNMatrix A, long int *lenrw, long int *leniw);
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunmatrix/sunmatrix_dense.h b/include/sunmatrix/sunmatrix_dense.h
new file mode 100644
index 0000000..c0e7a8a
--- /dev/null
+++ b/include/sunmatrix/sunmatrix_dense.h
@@ -0,0 +1,263 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * Based on code sundials_direct.h by: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the dense implementation of the 
+ * SUNMATRIX module.
+ * 
+ * Part I contains declarations specific to the dense implementation
+ * of the supplied SUNMATRIX module.
+ * 
+ * Part II defines accessor macros that allow the user to 
+ * efficiently use this SUNMatrix type without making explicit
+ * references to the underlying data structure.
+ *
+ * Part III contains the prototype for the constructor 
+ * SUNDenseMatrix as well as implementation-specific prototypes 
+ * for various useful matrix operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNMatrix structure can be found
+ *     in the header file sundials_matrix.h.
+ *
+ *   - The definition of the type 'realtype' can be found in the
+ *     header file sundials_types.h, and it may be changed (at the 
+ *     configuration stage) according to the user's needs. 
+ *     The sundials_types.h file also contains the definition
+ *     for the type 'booleantype' and 'indextype'.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNMATRIX_DENSE_H
+#define _SUNMATRIX_DENSE_H
+
+#include <sundials/sundials_matrix.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * -----------------------------------------------------------------
+ * PART I: Dense implementation of SUNMatrix
+ *
+ * The dense implementation of the SUNMatrix 'content' structure
+ * contains:
+ *   M     - number of rows
+ *   N     - number of columns
+ *   data  - pointer to a contiguous block of realtype variables
+ *   ldata - length of the data array = M*N
+ *   cols  - array of pointers. cols[j] points to the first element 
+ *           of the j-th column of the matrix in the array data.
+ * The elements of a dense matrix are stored columnwise (i.e. columns 
+ * are stored one on top of the other in memory); i.e. if A is a 
+ * SUNMatrix_Dense object, then the (i,j)th element of A (with 
+ * 0 <= i < M and 0 <= j < N) is given by (A->data)[j*M+i].
+ *
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNMatrixContent_Dense {
+  sunindextype M;
+  sunindextype N;
+  realtype *data;
+  sunindextype ldata;
+  realtype **cols;
+};
+
+typedef struct _SUNMatrixContent_Dense *SUNMatrixContent_Dense;
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: macros SM_CONTENT_D, SM_DATA_D, SM_ROWS_D, SM_COLUMNS_D, 
+ *          SM_COLUMN_D, and SM_ELEMENT_D
+ * -----------------------------------------------------------------
+ * In the descriptions below, the following user declarations
+ * are assumed:
+ *
+ * SUNMatrix A;
+ * SUNMatrixContent_Dense A_cont;
+ * realtype *A_col_j, *A_data, **A_cols, A_ij;
+ * sunindextype i, j, A_rows, A_columns, A_ldata;
+ *
+ * (1) SM_CONTENT_D
+ *
+ *     This macro gives access to the contents of the dense
+ *     SUNMatrix
+ *
+ *     The assignment A_cont = SM_CONTENT_D(A) sets A_cont to be
+ *     a pointer to the dense SUNMatrix content structure.
+ *
+ * (2) SM_DATA_D, SM_COLS_D, SM_LDATA_D, SM_ROWS_D, SM_COLUMNS_D
+ *
+ *     These macros give access to the individual parts of
+ *     the content structure of a dense SUNMatrix.
+ *
+ *     The assignment A_data = SM_DATA_D(A) sets A_data to be
+ *     a pointer to the first component of A. 
+ *
+ *     The assignment A_cols = SM_COLS_D(A) sets A_cols to be
+ *     a pointer to the content's 'cols' entry.
+ *
+ *     The assignment A_ldata = SM_LDATA_D(A) sets A_ldata to be
+ *     the length of the data array for A. 
+ *
+ *     The assignment A_rows = SM_ROWS_D(A) sets A_rows to be
+ *     the number of rows in A.
+ *
+ *     The assignment A_columns = SM_COLUMNS_D(A) sets A_columns 
+ *     to be the number of columns in A.
+ *
+ * (3) SM_COLUMN_D and SM_ELEMENT_D
+ *
+ *     These macros give access to the individual columns and 
+ *     elements of a dense SUNMatrix, respectively.  In the 
+ *     following, the entries of a SUNMatrix are indexed (i,j) 
+ *     where i=0,...,M-1 and j=0,...,N-1.
+ *     
+ *     The assignment A_col_j = SM_COLUMN_D(A,j) sets A_col_j to 
+ *     be a pointer to the jth column of the M-by-N dense
+ *     matrix A, 0 <= j < N.  After the assignment, A_col_j may 
+ *     be treated as an array indexed from 0 to M-1.
+ *     The (i,j)-th element of A is thus referenced by col_j[i].
+ *
+ *     The assignment A_ij = SM_ELEMENT_D(A,i,j) sets A_ij to 
+ *     the value of the (i,j)th element of the dense M-by-N matrix
+ *     A, 0 <= i < M ; 0 <= j < N.  Similarly, the assignment 
+ *     SM_ELEMENT_D(A,i,j) = A_ij sets the value of A_ij into the 
+ *     (i,j) location of the matrix A.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#define SM_CONTENT_D(A)     ( (SUNMatrixContent_Dense)(A->content) )
+
+#define SM_ROWS_D(A)        ( SM_CONTENT_D(A)->M )
+
+#define SM_COLUMNS_D(A)     ( SM_CONTENT_D(A)->N )
+
+#define SM_LDATA_D(A)       ( SM_CONTENT_D(A)->ldata )
+
+#define SM_DATA_D(A)        ( SM_CONTENT_D(A)->data )
+
+#define SM_COLS_D(A)        ( SM_CONTENT_D(A)->cols )
+
+#define SM_COLUMN_D(A,j)    ( (SM_CONTENT_D(A)->cols)[j] )
+
+#define SM_ELEMENT_D(A,i,j) ( (SM_CONTENT_D(A)->cols)[j][i] )
+
+/*
+ * -----------------------------------------------------------------
+ * PART III: functions exported by sunmatrix_dense
+ * 
+ * CONSTRUCTORS:
+ *    SUNDenseMatrix
+ * OTHER:
+ *    SUNDenseMatrix_Print
+ *    SUNDenseMatrix_Rows
+ *    SUNDenseMatrix_Columns
+ *    SUNDenseMatrix_LData
+ *    SUNDenseMatrix_Data 
+ *    SUNDenseMatrix_Cols
+ *    SUNDenseMatrix_Column
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function: SUNDenseMatrix
+ * -----------------------------------------------------------------
+ * Creates and allocates memory for an M-by-N dense SUNMatrix.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix SUNDenseMatrix(sunindextype M, sunindextype N);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: SUNDenseMatrix_Print
+ * -----------------------------------------------------------------
+ * This function prints the content of a M-by-N dense matrix A to
+ * file pointer as it would normally appear on paper.
+ * It is intended as debugging tools with small values of M and N.
+ * The elements are printed using the %g/%lg/%Lg option. 
+ * A blank line is printed before and after the matrix.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void SUNDenseMatrix_Print(SUNMatrix A, FILE* outfile);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Accessor Functions: 
+ *
+ * SUNDenseMatrix_Rows 
+ *    Returns the number of rows in the dense matrix
+ *
+ * SUNDenseMatrix_Columns
+ *    Returns the number of columns in the dense matrix
+ *
+ * SUNDenseMatrix_LData
+ *    Returns the total allocated data length for the dense matrix
+ *
+ * SUNDenseMatrix_Data
+ *    Returns a pointer to the data array for the dense matrix
+ *
+ * SUNDenseMatrix_Cols
+ *    Returns a pointer to the cols array for the dense matrix
+ *
+ * SUNDenseMatrix_Column
+ *    Returns a pointer to the jth column of the dense matrix
+ *
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT sunindextype SUNDenseMatrix_Rows(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNDenseMatrix_Columns(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNDenseMatrix_LData(SUNMatrix A);
+SUNDIALS_EXPORT realtype* SUNDenseMatrix_Data(SUNMatrix A);
+SUNDIALS_EXPORT realtype** SUNDenseMatrix_Cols(SUNMatrix A);
+SUNDIALS_EXPORT realtype* SUNDenseMatrix_Column(SUNMatrix A, sunindextype j);
+
+/*
+ * -----------------------------------------------------------------
+ * dense implementations of various useful matrix operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix_ID SUNMatGetID_Dense(SUNMatrix A);
+SUNDIALS_EXPORT SUNMatrix SUNMatClone_Dense(SUNMatrix A);
+SUNDIALS_EXPORT void SUNMatDestroy_Dense(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatZero_Dense(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatCopy_Dense(SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAdd_Dense(realtype c, SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAddI_Dense(realtype c, SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatMatvec_Dense(SUNMatrix A, N_Vector x, N_Vector y);
+SUNDIALS_EXPORT int SUNMatSpace_Dense(SUNMatrix A, long int *lenrw,
+                                      long int *leniw);
+
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/sunmatrix/sunmatrix_sparse.h b/include/sunmatrix/sunmatrix_sparse.h
new file mode 100644
index 0000000..2344e02
--- /dev/null
+++ b/include/sunmatrix/sunmatrix_sparse.h
@@ -0,0 +1,355 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * Based on code sundials_sparse.h by: Carol Woodward and 
+ *     Slaven Peles @ LLNL, and Daniel R. Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the header file for the sparse implementation of the 
+ * SUNMATRIX module.
+ * 
+ * Part I contains declarations specific to the sparse implementation
+ * of the supplied SUNMATRIX module.
+ * 
+ * Part II defines accessor macros that allow the user to 
+ * efficiently use this SUNMatrix type without making explicit
+ * references to the underlying data structure.
+ *
+ * Part III contains the prototype for the constructor 
+ * SUNMatrixNew_Sparse as well as implementation-specific prototypes 
+ * for various useful matrix operations.
+ *
+ * Notes:
+ *
+ *   - The definition of the generic SUNMatrix structure can be found
+ *     in the header file sundials_matrix.h.
+ *
+ *   - The definition of the type 'realtype' can be found in the
+ *     header file sundials_types.h, and it may be changed (at the 
+ *     configuration stage) according to the user's needs. 
+ *     The sundials_types.h file also contains the definition
+ *     for the type 'booleantype' and 'indextype'.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _SUNMATRIX_SPARSE_H
+#define _SUNMATRIX_SPARSE_H
+
+#include <sundials/sundials_matrix.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_band.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+/*
+ * ==================================================================
+ * Type definitions
+ * ==================================================================
+ */
+
+#define CSC_MAT 0
+#define CSR_MAT 1
+
+  
+/*
+ * -----------------------------------------------------------------
+ * PART I: Sparse implementation of SUNMatrix
+ *
+ * The sparse implementation of the SUNMatrix 'content' structure
+ * contains:
+ *   M     - number of rows
+ *   N     - number of columns
+ *   NNZ   - the number of nonzero entries in the matrix
+ *   NP    - number of index pointers
+ *   data  - pointer to a contiguous block of realtype variables
+ *   sparsetype - type of sparse matrix: compressed sparse column or row
+ *   indexvals  - indices of each nonzero entry (columns or rows)
+ *   indexptrs  - starting index of the first entry in data for each slice
+ *   rowvals - pointer to row indices of each nonzero entry
+ *   colptrs - pointer to starting indices in data array for each column
+ *   colvals - pointer to column indices of each nonzero entry
+ *   rowptrs - pointer to starting indices in data array for each row
+ * -----------------------------------------------------------------
+ */
+  
+struct _SUNMatrixContent_Sparse {
+  sunindextype M;
+  sunindextype N;
+  sunindextype NNZ;
+  sunindextype NP;
+  realtype *data;
+  int sparsetype;
+  sunindextype *indexvals;
+  sunindextype *indexptrs;
+  /* CSC indices */
+  sunindextype **rowvals;
+  sunindextype **colptrs;
+  /* CSR indices */
+  sunindextype **colvals;
+  sunindextype **rowptrs;
+};
+
+typedef struct _SUNMatrixContent_Sparse *SUNMatrixContent_Sparse;
+
+
+/*
+ * -----------------------------------------------------------------
+ * PART II: macros SM_CONTENT_S, SM_ROWS_S, SM_COLUMNS_S, SM_NNZ_S, 
+ *          SM_NP_S, SM_SPARSETYPE_S, SM_DATA_S, SM_INDEXVALS_S, and
+ *          SM_INDEXPTRS_S
+ * -----------------------------------------------------------------
+ * In the descriptions below, the following user declarations
+ * are assumed:
+ *
+ * SUNMatrix A;
+ * SUNMatrixContent_Sparse A_cont;
+ * realtype *A_data;
+ * int A_type;
+ * sunindextype A_nnz, A_np, *A_ivals, *A_iptrs;
+ *
+ * (1) SM_CONTENT_S
+ *
+ *     This macro gives access to the contents of the sparse
+ *     SUNMatrix
+ *
+ *     The assignment A_cont = SM_CONTENT_S(A) sets A_cont to be
+ *     a pointer to the sparse SUNMatrix content structure.
+ *
+ * (2) SM_ROWS_D, SM_COLUMNS_D, SM_NNZ_S, SM_NP_S, SM_SPARSETYPE_S, 
+ *     SM_DATA_S, SM_INDEXVALS_S and SM_INDEXPTRS_S
+ *
+ *     These macros give access to the individual parts of
+ *     the content structure of a sparse SUNMatrix.
+ *
+ *     The assignment A_rows = SM_ROWS_S(A) sets A_rows to be
+ *     the number of rows in A.
+ *
+ *     The assignment A_cols = SM_COLUMNS_S(A) sets A_cols to be
+ *     the number of columns in A.
+ *
+ *     The assignment A_nnz = SM_NNZ_S(A) sets A_nnz to be
+ *     the number of nonzero entries in A.
+ *
+ *     The assignment A_np = SM_NP_S(A) sets A_np to be
+ *     the number of index pointers in A.
+ *
+ *     The assignment A_type = SM_SPARSETYPE_S(A) sets A_type to be
+ *     the type of sparse matrix that A is (CSC_MAT or CSR_MAT).
+ *
+ *     The assignment A_data = SM_DATA_S(A) sets A_data to be
+ *     a pointer to the first component of the data array for A. 
+ *
+ *     The assignment A_ivals = SM_INDEXVALS_S(A) sets A_ivals to be
+ *     a pointer to the array of index values of each nonzero entry in A. 
+ *
+ *     The assignment A_iptrs = SM_INDEXPTRS_S(A) sets A_iptrs to be
+ *     a pointer to the array of starting indices for the first entry
+ *     of each row/column in the data/indexvals arrays.
+ *
+ * -----------------------------------------------------------------
+ */
+
+#define SM_CONTENT_S(A)     ( (SUNMatrixContent_Sparse)(A->content) )
+
+#define SM_ROWS_S(A)        ( SM_CONTENT_S(A)->M )
+
+#define SM_COLUMNS_S(A)     ( SM_CONTENT_S(A)->N )
+
+#define SM_NNZ_S(A)         ( SM_CONTENT_S(A)->NNZ )
+
+#define SM_NP_S(A)          ( SM_CONTENT_S(A)->NP )
+
+#define SM_SPARSETYPE_S(A)  ( SM_CONTENT_S(A)->sparsetype )
+
+#define SM_DATA_S(A)        ( SM_CONTENT_S(A)->data )
+
+#define SM_INDEXVALS_S(A)   ( SM_CONTENT_S(A)->indexvals )
+
+#define SM_INDEXPTRS_S(A)   ( SM_CONTENT_S(A)->indexptrs )
+
+/*
+ * -----------------------------------------------------------------
+ * PART III: functions exported by sunmatrix_sparse
+ * 
+ * CONSTRUCTORS:
+ *    SUNSparseMatrix
+ *    SUNSparseFromDenseMatrix
+ *    SUNSparseFromBandMatrix
+ * OTHER:
+ *    SUNSparseMatrix_Print
+ *    SUNSparseMatrix_Realloc
+ *    SUNSparseMatrix_Rows
+ *    SUNSparseMatrix_Columns 
+ *    SUNSparseMatrix_NNZ
+ *    SUNSparseMatrix_NP
+ *    SUNSparseMatrix_SparseType
+ *    SUNSparseMatrix_Data 
+ *    SUNSparseMatrix_IndexValues
+ *    SUNSparseMatrix_IndexPointers
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * -----------------------------------------------------------------
+ * Function: SUNSparseMatrix
+ * -----------------------------------------------------------------
+ * Creates and allocates memory for an M-by-N sparse SUNMatrix of 
+ * type sparsetype.
+ * Requirements: M and N must be strictly positive; NNZ must be 
+ * non-negative; sparsetype must be either CSC_MAT or CSR_MAT;
+ * Returns NULL if any requirements are violated, or if the matrix 
+ * storage request cannot be satisfied.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix SUNSparseMatrix(sunindextype M, sunindextype N,
+                                          sunindextype NNZ, int sparsetype);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: SUNSparseFromDenseMatrix
+ * -----------------------------------------------------------------
+ * Creates a new sparse matrix from an existing dense matrix 
+ * by copying all values with magnitude larger than droptol into 
+ * the sparse matrix structure.  
+ * Requirements: A must have type SUNMATRIX_DENSE; 
+ * droptol must be non-negative; sparsetype must be either 
+ * CSC_MAT or CSR_MAT.
+ * Returns NULL if any requirements are violated, or if the matrix
+ * storage request cannot be satisfied. 
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix SUNSparseFromDenseMatrix(SUNMatrix A,
+                                                   realtype droptol,
+                                                   int sparsetype);
+
+/*
+ * -----------------------------------------------------------------
+ * Function: SUNSparseFromBandMatrix
+ * -----------------------------------------------------------------
+ * Creates a new sparse matrix from an existing band matrix 
+ * by copying all values with magnitude larger than or equal to 
+ * droptol into the sparse matrix structure.  
+ * Requirements: A must have type SUNMATRIX_BAND; 
+ * droptol must be non-negative; sparsetype must be either 
+ * CSC_MAT or CSR_MAT.
+ * Returns NULL if any requirements are violated, or if the matrix
+ * storage request cannot be satisfied. 
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix SUNSparseFromBandMatrix(SUNMatrix A,
+                                                  realtype droptol,
+                                                  int sparsetype);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: SUNSparseMatrix_Realloc
+ * -----------------------------------------------------------------
+ * This function reallocates internal arrays so that the resulting 
+ * sparse matrix holds colptrs[N] nonzeros.  Returns 0 on success and 
+ * 1 on failure (e.g. if A does not have sparse type)
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT int SUNSparseMatrix_Realloc(SUNMatrix A);
+
+/*
+ * -----------------------------------------------------------------
+ * Functions: SUNSparseMatrix_Print
+ * -----------------------------------------------------------------
+ * This function prints the sparse matrix information to a file 
+ * pointer.  It is intended as a debugging tool with small values 
+ * of NNZ.  The elements are printed using the %g/%lg/%Lg option. 
+ * A blank line is printed before and after the matrix.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT void SUNSparseMatrix_Print(SUNMatrix A, FILE* outfile);
+
+
+/*
+ * -----------------------------------------------------------------
+ * Accessor Functions: 
+ *
+ * SUNSparseMatrix_Rows 
+ *    Returns the number of rows in the sparse matrix
+ *
+ * SUNSparseMatrix_Columns
+ *    Returns the number of columns in the sparse matrix
+ *
+ * SUNSparseMatrix_NNZ
+ *    Returns the allocated number of nonzeros in the sparse matrix
+ *
+ * SUNSparseMatrix_NP
+ *    Returns the number of columns/rows depending on whether the 
+ *    matrix uses CSC/CSR format, respectively
+ *
+ * SUNSparseMatrix_SparseType
+ *    Returns the storage type for this matrix (CSR_MAT or CSC_MAT)
+ *
+ * SUNSparseMatrix_Data
+ *    Returns a pointer to the data array for the sparse matrix
+ *
+ * SUNSparseMatrix_IndexValues
+ *    Returns a ptr to the index value array for the sparse matrix:
+ *    for CSR this is the column index for each nonzero,
+ *    for CSC this is the row index for each nonzero.
+ *
+ * SUNSparseMatrix_IndexPointers
+ *    Returns a ptr to the index pointer array for the sparse matrix:
+ *    for CSR this is the location of the first entry of each row,
+ *    for CSC this is the location of the first entry of each column.
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT sunindextype SUNSparseMatrix_Rows(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNSparseMatrix_Columns(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNSparseMatrix_NNZ(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype SUNSparseMatrix_NP(SUNMatrix A);
+SUNDIALS_EXPORT int SUNSparseMatrix_SparseType(SUNMatrix A);
+SUNDIALS_EXPORT realtype* SUNSparseMatrix_Data(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype* SUNSparseMatrix_IndexValues(SUNMatrix A);
+SUNDIALS_EXPORT sunindextype* SUNSparseMatrix_IndexPointers(SUNMatrix A);
+
+/*
+ * -----------------------------------------------------------------
+ * sparse implementations of various useful matrix operations
+ * -----------------------------------------------------------------
+ */
+
+SUNDIALS_EXPORT SUNMatrix_ID SUNMatGetID_Sparse(SUNMatrix A);
+SUNDIALS_EXPORT SUNMatrix SUNMatClone_Sparse(SUNMatrix A);
+SUNDIALS_EXPORT void SUNMatDestroy_Sparse(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatZero_Sparse(SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatCopy_Sparse(SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAdd_Sparse(realtype c, SUNMatrix A, SUNMatrix B);
+SUNDIALS_EXPORT int SUNMatScaleAddI_Sparse(realtype c, SUNMatrix A);
+SUNDIALS_EXPORT int SUNMatMatvec_Sparse(SUNMatrix A, N_Vector x, N_Vector y);
+SUNDIALS_EXPORT int SUNMatSpace_Sparse(SUNMatrix A, long int *lenrw,
+                                       long int *leniw);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/arkode/CMakeLists.txt b/src/arkode/CMakeLists.txt
index cfed8e6..493f9e5 100644
--- a/src/arkode/CMakeLists.txt
+++ b/src/arkode/CMakeLists.txt
@@ -2,7 +2,7 @@
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
 # LLNS/SMU Copyright Start
-# Copyright (c) 2015, Southern Methodist University and 
+# Copyright (c) 2017, Southern Methodist University and 
 # Lawrence Livermore National Security
 #
 # This work was performed under the auspices of the U.S. Department 
@@ -14,9 +14,6 @@
 # All rights reserved.
 # For details, see the LICENSE file.
 # LLNS/SMU Copyright End
-# Copyright (c) 2013, Southern Methodist University.
-# All rights reserved.
-# For details, see the LICENSE file.
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the ARKODE library
 
@@ -25,88 +22,61 @@ INSTALL(CODE "MESSAGE(\"\nInstall ARKODE\n\")")
 # Add variable arkode_SOURCES with the sources for the ARKODE library
 SET(arkode_SOURCES
   arkode.c
-  arkode_band.c
   arkode_bandpre.c
   arkode_bbdpre.c
   arkode_butcher.c
-  arkode_dense.c
   arkode_direct.c        
   arkode_io.c
-  arkode_pcg.c
-  arkode_spbcgs.c
-  arkode_spfgmr.c
-  arkode_spgmr.c
   arkode_spils.c
-  arkode_sptfqmr.c
-  arkode_sparse.c
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND arkode_SOURCES arkode_klu.c)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND arkode_SOURCES arkode_superlumt.c)
-ENDIF()
-
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the ARKODE library
 SET(shared_SOURCES
-  sundials_nvector.c
-  sundials_math.c
-  sundials_direct.c
-  sundials_band.c
-  sundials_dense.c
-  sundials_iterative.c
-  sundials_pcg.c
-  sundials_spbcgs.c
-  sundials_spfgmr.c
-  sundials_spgmr.c
-  sundials_sptfqmr.c
-  sundials_sparse.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_band.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_dense.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_direct.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_version.c
+  ${sundials_SOURCE_DIR}/src/nvec_ser/nvector_serial.c
   )
 
-# Add prefix with complete path to the common SUNDIALS sources
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the ARKODE library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/sunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/sunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/sunmatrix_sparse.c
+  )
+
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the ARKODE library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/sunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/sunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/sunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/sunlinsol_pcg.c
+  )
 
 # Add variable arkode_HEADERS with the exported ARKODE header files
 SET(arkode_HEADERS
   arkode.h
-  arkode_band.h
   arkode_bandpre.h
   arkode_bbdpre.h
-  arkode_dense.h
   arkode_direct.h
-  arkode_pcg.h
-  arkode_spbcgs.h
-  arkode_spfgmr.h
-  arkode_spgmr.h
   arkode_spils.h
-  arkode_sptfqmr.h
-  arkode_sparse.h
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND arkode_HEADERS arkode_klu.h)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND arkode_HEADERS arkode_superlumt.h)
-ENDIF()
-
 # Add prefix with complete path to the ARKODE header files
 ADD_PREFIX(${sundials_SOURCE_DIR}/include/arkode/ arkode_HEADERS)
 
-# If Blas/Lapack support was enabled, set-up additional file lists
-IF(LAPACK_FOUND)
-  SET(arkode_BL_SOURCES arkode_lapack.c)
-  SET(arkode_BL_HEADERS arkode_lapack.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/arkode/ arkode_BL_HEADERS)
-ELSE(LAPACK_FOUND)
-  SET(arkode_BL_SOURCES "")
-  SET(arkode_BL_HEADERS "")
-ENDIF(LAPACK_FOUND)
-
 # Add source directories to include directories for access to
 # implementation only header files.
 INCLUDE_DIRECTORIES(.)
@@ -120,7 +90,7 @@ IF(BUILD_STATIC_LIBS)
 
   # Add the build target for the static ARKODE library
   ADD_LIBRARY(sundials_arkode_static STATIC 
-    ${arkode_SOURCES}  ${arkode_BL_SOURCES} ${shared_SOURCES})
+    ${arkode_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_arkode_static
@@ -136,7 +106,11 @@ IF(BUILD_SHARED_LIBS)
 
   # Add the build target for the ARKODE library
   ADD_LIBRARY(sundials_arkode_shared SHARED 
-    ${arkode_SOURCES}  ${arkode_BL_SOURCES}  ${shared_SOURCES})
+    ${arkode_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_arkode_shared m)
+  ENDIF()
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_arkode_shared
@@ -152,7 +126,7 @@ IF(BUILD_SHARED_LIBS)
 ENDIF(BUILD_SHARED_LIBS)
 
 # Install the ARKODE header files
-INSTALL(FILES ${arkode_HEADERS} ${arkode_BL_HEADERS} DESTINATION include/arkode)
+INSTALL(FILES ${arkode_HEADERS} DESTINATION include/arkode)
 
 # Install the ARKODE implementation header file
 INSTALL(FILES arkode_impl.h DESTINATION include/arkode)
diff --git a/src/arkode/README b/src/arkode/README
index e56be67..c9a5d51 100644
--- a/src/arkode/README
+++ b/src/arkode/README
@@ -1,5 +1,5 @@
                              ARKODE
-                   Release 1.1.0, September, 2016
+                   Release 2.1.0, November 2017
                        Daniel R. Reynolds
                   Department of Mathematics, SMU
 
@@ -20,7 +20,6 @@ scaled preconditioned Flexible GMRES (SPFGMR), scaled preconditioned
 conjugate gradient, scaled preconditioned BiCGStab (SPBCG), 
 and scaled preconditioned TFQMR (SPTFQMR). When ARKODE is used with 
 the parallel NVECTOR module, only the Krylov linear solvers are available. 
-(An approximate diagonal Jacobian option is available with both versions.)  
 For the serial version, there is a banded preconditioner module called 
 ARKBANDPRE available for use with the Krylov solvers, while for the 
 parallel version there is a preconditioner module called ARKBBDPRE 
@@ -65,6 +64,8 @@ C. References
 D. Releases
 -----------
 
+v. 2.1.0 - Nov. 2017
+v. 2.0.0 - Sep. 2017
 v. 1.1.0 - Sep. 2016
 v. 1.0.2 - Aug. 2015
 v. 1.0.1 - Mar. 2015
diff --git a/src/arkode/arkode.c b/src/arkode/arkode.c
index cf4a7f3..95d36c3 100644
--- a/src/arkode/arkode.c
+++ b/src/arkode/arkode.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -36,6 +36,12 @@
 #include <nvector/nvector_serial.h>
 #endif
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define RSYM ".32Lg"
+#else
+#define RSYM ".16g"
+#endif
+
 #define FIXED_LIN_TOL
 
 #ifdef __GNUC__
@@ -47,7 +53,7 @@
 /*===============================================================
              Private Functions Prototypes
 ===============================================================*/
-static void arkPrintMem(ARKodeMem ark_mem) SUNDIALS_UNUSED;
+static void arkPrintMem(ARKodeMem ark_mem, FILE *outfile) SUNDIALS_UNUSED;
 static booleantype arkCheckNvector(N_Vector tmpl);
 static booleantype arkAllocVectors(ARKodeMem ark_mem, 
 				   N_Vector tmpl);
@@ -58,8 +64,8 @@ static int arkAllocFPData(ARKodeMem ark_mem);
 static int arkResizeFPData(ARKodeMem ark_mem, 
 			   ARKVecResizeFn resize,
 			   void *resize_data,
-			   long int lrw_diff,
-			   long int liw_diff);
+			   sunindextype lrw_diff,
+			   sunindextype liw_diff);
 static void arkFreeFPData(ARKodeMem ark_mem);
 
 static int arkInitialSetup(ARKodeMem ark_mem);
@@ -198,7 +204,7 @@ void *ARKodeCreate()
 
   /* Set default nonlinear solver choice to Newton,
      initialize fixed-point solver variables */
-  ark_mem->ark_use_fp   = FALSE;
+  ark_mem->ark_use_fp   = SUNFALSE;
   ark_mem->ark_fp_R     = NULL;
   ark_mem->ark_fp_gamma = NULL;
   ark_mem->ark_fp_df    = NULL;
@@ -209,7 +215,7 @@ void *ARKodeCreate()
   ark_mem->ark_fp_gold  = NULL;
 
   /* Initialize diagnostics reporting variables */
-  ark_mem->ark_report  = FALSE;
+  ark_mem->ark_report  = SUNFALSE;
   ark_mem->ark_diagfp  = NULL;
 
   /* Initialize lrw and liw */
@@ -217,9 +223,9 @@ void *ARKodeCreate()
   ark_mem->ark_liw = 40;   /* to be updated */
 
   /* No mallocs have been done yet */
-  ark_mem->ark_VabstolMallocDone  = FALSE;
-  ark_mem->ark_VRabstolMallocDone = FALSE;
-  ark_mem->ark_MallocDone         = FALSE;
+  ark_mem->ark_VabstolMallocDone  = SUNFALSE;
+  ark_mem->ark_VRabstolMallocDone = SUNFALSE;
+  ark_mem->ark_MallocDone         = SUNFALSE;
 
   /* No user-supplied step postprocessing function yet */
   ark_mem->ark_ProcessStep = NULL;
@@ -244,7 +250,7 @@ int ARKodeInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
 {
   ARKodeMem ark_mem;
   booleantype nvectorOK, allocOK;
-  long int lrw1, liw1;
+  sunindextype lrw1, liw1;
 
   /* Check arkode_mem */
   if (arkode_mem==NULL) {
@@ -262,8 +268,8 @@ int ARKodeInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
   }
 
   /* Set implicit/explicit problem based on function pointers */
-  if (fe == NULL) ark_mem->ark_implicit = TRUE;
-  if (fi == NULL) ark_mem->ark_explicit = TRUE;
+  if (fe == NULL) ark_mem->ark_implicit = SUNTRUE;
+  if (fi == NULL) ark_mem->ark_explicit = SUNTRUE;
 
   /* Check that at least one of fe,fi is supplied and is to be used */
   if (ark_mem->ark_implicit && ark_mem->ark_explicit) {
@@ -322,13 +328,12 @@ int ARKodeInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
 
   /* Set the mass matrix to identity, and mass matrix solver 
      addresses to NULL. (We check != NULL later, in ARKode.) */
-  ark_mem->ark_mass_matrix = FALSE;
+  ark_mem->ark_mass_matrix = SUNFALSE;
   ark_mem->ark_minit       = NULL;
   ark_mem->ark_msetup      = NULL;
+  ark_mem->ark_mmult       = NULL;
   ark_mem->ark_msolve      = NULL;
   ark_mem->ark_mfree       = NULL;
-  ark_mem->ark_mtimes      = NULL;
-  ark_mem->ark_mtimes_data = NULL;
   ark_mem->ark_mass_mem    = NULL;
   ark_mem->ark_msolve_type = -1;
 
@@ -354,7 +359,6 @@ int ARKodeInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
   ark_mem->ark_nfe          = 0;
   ark_mem->ark_nfi          = 0;
   ark_mem->ark_ncfn         = 0;
-  ark_mem->ark_nmassfails   = 0;
   ark_mem->ark_netf         = 0;
   ark_mem->ark_nni          = 0;
   ark_mem->ark_nsetups      = 0;
@@ -362,22 +366,20 @@ int ARKodeInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
   ark_mem->ark_nstlp        = 0;
   ark_mem->ark_nge          = 0;
   ark_mem->ark_irfnd        = 0;
-  ark_mem->ark_mass_solves  = 0;
-  ark_mem->ark_mass_mult    = 0;
 
   /* Initialize other integrator optional outputs */
   ark_mem->ark_h0u    = ZERO;
   ark_mem->ark_next_h = ZERO;
 
   /* Initially, rwt should point to ewt */
-  ark_mem->ark_rwt_is_ewt = TRUE;
+  ark_mem->ark_rwt_is_ewt = SUNTRUE;
 
   /* Indicate that problem size is new */
-  ark_mem->ark_resized = TRUE;
-  ark_mem->ark_firststage = TRUE;
+  ark_mem->ark_resized = SUNTRUE;
+  ark_mem->ark_firststage = SUNTRUE;
 
   /* Problem has been successfully initialized */
-  ark_mem->ark_MallocDone = TRUE;
+  ark_mem->ark_MallocDone = SUNTRUE;
 
   return(ARK_SUCCESS);
 }
@@ -412,7 +414,7 @@ int ARKodeReInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
   ark_mem = (ARKodeMem) arkode_mem;
 
   /* Check if arkode_mem was allocated */
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeReInit", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -426,9 +428,9 @@ int ARKodeReInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
   }
   
   /* Set implicit/explicit problem based on function pointers */
-  ark_mem->ark_implicit = ark_mem->ark_explicit = FALSE;
-  if (fe == NULL) ark_mem->ark_implicit = TRUE;
-  if (fi == NULL) ark_mem->ark_explicit = TRUE;
+  ark_mem->ark_implicit = ark_mem->ark_explicit = SUNFALSE;
+  if (fe == NULL) ark_mem->ark_implicit = SUNTRUE;
+  if (fi == NULL) ark_mem->ark_explicit = SUNTRUE;
 
   /* Check that at least one of fe,fi is supplied and is to be used */
   if (ark_mem->ark_implicit && ark_mem->ark_explicit) {
@@ -473,7 +475,6 @@ int ARKodeReInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
   ark_mem->ark_nfe          = 0;
   ark_mem->ark_nfi          = 0;
   ark_mem->ark_ncfn         = 0;
-  ark_mem->ark_nmassfails   = 0;
   ark_mem->ark_netf         = 0;
   ark_mem->ark_nni          = 0;
   ark_mem->ark_nsetups      = 0;
@@ -481,12 +482,10 @@ int ARKodeReInit(void *arkode_mem, ARKRhsFn fe, ARKRhsFn fi,
   ark_mem->ark_nstlp        = 0;
   ark_mem->ark_nge          = 0;
   ark_mem->ark_irfnd        = 0;
-  ark_mem->ark_mass_solves  = 0;
-  ark_mem->ark_mass_mult    = 0;
 
   /* Indicate that problem size is new */
-  ark_mem->ark_resized = TRUE;
-  ark_mem->ark_firststage = TRUE;
+  ark_mem->ark_resized = SUNTRUE;
+  ark_mem->ark_firststage = SUNTRUE;
 
   /* Initialize other integrator optional outputs */
   ark_mem->ark_h0u    = ZERO;
@@ -539,8 +538,8 @@ int ARKodeResize(void *arkode_mem, N_Vector y0,
 		 ARKVecResizeFn resize, void *resize_data)
 {
   ARKodeMem ark_mem;
-  long int lrw1=0, liw1=0;
-  long int lrw_diff, liw_diff;
+  sunindextype lrw1=0, liw1=0;
+  sunindextype lrw_diff, liw_diff;
   int ier, i;
  
   /* Check arkode_mem */
@@ -552,7 +551,7 @@ int ARKodeResize(void *arkode_mem, N_Vector y0,
   ark_mem = (ARKodeMem) arkode_mem;
 
   /* Check if arkode_mem was allocated */
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeResize", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -847,8 +846,8 @@ int ARKodeResize(void *arkode_mem, N_Vector y0,
   N_VScale(ONE, y0, ark_mem->ark_ycur);
 
   /* Indicate that problem size is new */
-  ark_mem->ark_resized = TRUE;
-  ark_mem->ark_firststage = TRUE;
+  ark_mem->ark_resized = SUNTRUE;
+  ark_mem->ark_firststage = SUNTRUE;
   
   /* Problem has been successfully re-sized */
   return(ARK_SUCCESS);
@@ -887,7 +886,7 @@ int ARKodeSStolerances(void *arkode_mem, realtype reltol,
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeSStolerances", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -911,7 +910,7 @@ int ARKodeSStolerances(void *arkode_mem, realtype reltol,
   ark_mem->ark_itol    = ARK_SS;
 
   /* enforce use of arkEwtSet */
-  ark_mem->ark_user_efun = FALSE;
+  ark_mem->ark_user_efun = SUNFALSE;
   ark_mem->ark_efun      = arkEwtSet;
   ark_mem->ark_e_data    = ark_mem;
 
@@ -930,7 +929,7 @@ int ARKodeSVtolerances(void *arkode_mem, realtype reltol,
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeSVtolerances", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -953,14 +952,14 @@ int ARKodeSVtolerances(void *arkode_mem, realtype reltol,
     ark_mem->ark_Vabstol = N_VClone(ark_mem->ark_ewt);
     ark_mem->ark_lrw += ark_mem->ark_lrw1;
     ark_mem->ark_liw += ark_mem->ark_liw1;
-    ark_mem->ark_VabstolMallocDone = TRUE;
+    ark_mem->ark_VabstolMallocDone = SUNTRUE;
   }
   N_VScale(ONE, abstol, ark_mem->ark_Vabstol);
   ark_mem->ark_reltol = reltol;
   ark_mem->ark_itol   = ARK_SV;
 
   /* enforce use of arkEwtSet */
-  ark_mem->ark_user_efun = FALSE;
+  ark_mem->ark_user_efun = SUNFALSE;
   ark_mem->ark_efun      = arkEwtSet;
   ark_mem->ark_e_data    = ark_mem;
 
@@ -978,7 +977,7 @@ int ARKodeWFtolerances(void *arkode_mem, ARKEwtFn efun)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeWFtolerances", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -986,7 +985,7 @@ int ARKodeWFtolerances(void *arkode_mem, ARKEwtFn efun)
 
   /* Copy tolerance data into memory */
   ark_mem->ark_itol      = ARK_WF;
-  ark_mem->ark_user_efun = TRUE;
+  ark_mem->ark_user_efun = SUNTRUE;
   ark_mem->ark_efun      = efun;
   ark_mem->ark_e_data    = NULL; /* set to user_data in InitialSetup */
 
@@ -1029,7 +1028,7 @@ int ARKodeResStolerance(void *arkode_mem, realtype rabstol)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeResStolerances", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -1044,7 +1043,7 @@ int ARKodeResStolerance(void *arkode_mem, realtype rabstol)
 
   /* Allocate space for rwt if necessary */
   if (ark_mem->ark_rwt_is_ewt) {
-    ark_mem->ark_rwt_is_ewt = FALSE;
+    ark_mem->ark_rwt_is_ewt = SUNFALSE;
     ark_mem->ark_rwt = N_VClone(ark_mem->ark_ewt);
     ark_mem->ark_lrw += ark_mem->ark_lrw1;
     ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -1055,7 +1054,7 @@ int ARKodeResStolerance(void *arkode_mem, realtype rabstol)
   ark_mem->ark_ritol    = ARK_SS;
 
   /* enforce use of arkRwtSet */
-  ark_mem->ark_user_efun = FALSE;
+  ark_mem->ark_user_efun = SUNFALSE;
   ark_mem->ark_rfun      = arkRwtSet;
   ark_mem->ark_r_data    = ark_mem;
 
@@ -1073,7 +1072,7 @@ int ARKodeResVtolerance(void *arkode_mem, N_Vector rabstol)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeResVtolerances", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -1088,7 +1087,7 @@ int ARKodeResVtolerance(void *arkode_mem, N_Vector rabstol)
 
   /* Allocate space for rwt if necessary */
   if (ark_mem->ark_rwt_is_ewt) {
-    ark_mem->ark_rwt_is_ewt = FALSE;
+    ark_mem->ark_rwt_is_ewt = SUNFALSE;
     ark_mem->ark_rwt = N_VClone(ark_mem->ark_ewt);
     ark_mem->ark_lrw += ark_mem->ark_lrw1;
     ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -1099,14 +1098,14 @@ int ARKodeResVtolerance(void *arkode_mem, N_Vector rabstol)
     ark_mem->ark_VRabstol = N_VClone(ark_mem->ark_rwt);
     ark_mem->ark_lrw += ark_mem->ark_lrw1;
     ark_mem->ark_liw += ark_mem->ark_liw1;
-    ark_mem->ark_VRabstolMallocDone = TRUE;
+    ark_mem->ark_VRabstolMallocDone = SUNTRUE;
   }
   N_VScale(ONE, rabstol, ark_mem->ark_VRabstol);
   ark_mem->ark_ritol = ARK_SV;
 
 
   /* enforce use of arkRwtSet */
-  ark_mem->ark_user_efun = FALSE;
+  ark_mem->ark_user_efun = SUNFALSE;
   ark_mem->ark_rfun      = arkRwtSet;
   ark_mem->ark_r_data    = ark_mem;
 
@@ -1124,7 +1123,7 @@ int ARKodeResFtolerance(void *arkode_mem, ARKRwtFn rfun)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", 
 		    "ARKodeResFtolerances", MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -1132,7 +1131,7 @@ int ARKodeResFtolerance(void *arkode_mem, ARKRwtFn rfun)
 
   /* Allocate space for rwt if necessary */
   if (ark_mem->ark_rwt_is_ewt) {
-    ark_mem->ark_rwt_is_ewt = FALSE;
+    ark_mem->ark_rwt_is_ewt = SUNFALSE;
     ark_mem->ark_rwt = N_VClone(ark_mem->ark_ewt);
     ark_mem->ark_lrw += ark_mem->ark_lrw1;
     ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -1140,7 +1139,7 @@ int ARKodeResFtolerance(void *arkode_mem, ARKRwtFn rfun)
 
   /* Copy tolerance data into memory */
   ark_mem->ark_ritol     = ARK_WF;
-  ark_mem->ark_user_rfun = TRUE;
+  ark_mem->ark_user_rfun = SUNTRUE;
   ark_mem->ark_rfun      = rfun;
   ark_mem->ark_r_data    = NULL; /* set to user_data in InitialSetup */
 
@@ -1194,7 +1193,7 @@ int ARKode(void *arkode_mem, realtype tout, N_Vector yout,
   ark_mem = (ARKodeMem) arkode_mem;
 
   /* Check if arkode_mem was allocated */
-  if (ark_mem->ark_MallocDone == FALSE) {
+  if (ark_mem->ark_MallocDone == SUNFALSE) {
     arkProcessError(ark_mem, ARK_NO_MALLOC, "ARKODE", "ARKode", 
 		    MSGARK_NO_MALLOC);
     return(ARK_NO_MALLOC);
@@ -1383,12 +1382,9 @@ int ARKode(void *arkode_mem, realtype tout, N_Vector yout,
     /* if the problem involves a non-identity mass matrix, update fnew here */
     if (ark_mem->ark_mass_matrix) {
       N_VScale(ark_mem->ark_h, ark_mem->ark_fnew, ark_mem->ark_fnew);   /* scale RHS */
-      retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_fnew, ark_mem->ark_rwt); 
-      /* retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_fnew, ark_mem->ark_ewt);  */
+      retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_fnew); 
       N_VScale(ONE/ark_mem->ark_h, ark_mem->ark_fnew, ark_mem->ark_fnew);   /* scale result */
-      ark_mem->ark_mass_solves++;
       if (retval != ARK_SUCCESS) {
-	ark_mem->ark_nmassfails++;
 	arkProcessError(ark_mem, ARK_MASSSOLVE_FAIL, "ARKODE", 
 			"ARKode", "Mass matrix solver failure");
 	return(ARK_MASSSOLVE_FAIL);
@@ -1520,7 +1516,7 @@ int ARKode(void *arkode_mem, realtype tout, N_Vector yout,
           return(ARK_ILL_INPUT);
         }
         ark_mem->ark_tretlast = *tret = ark_mem->ark_tstop;
-        ark_mem->ark_tstopset = FALSE;
+        ark_mem->ark_tstopset = SUNFALSE;
         return(ARK_TSTOP_RETURN);
       }
       
@@ -1673,10 +1669,10 @@ int ARKode(void *arkode_mem, realtype tout, N_Vector yout,
        * as this may indicate a user error in the implementation
        * of the root function. */
       if (ark_mem->ark_nst==1) {
-        inactive_roots = FALSE;
+        inactive_roots = SUNFALSE;
         for (ir=0; ir<ark_mem->ark_nrtfn; ir++) { 
           if (!ark_mem->ark_gactive[ir]) {
-            inactive_roots = TRUE;
+            inactive_roots = SUNTRUE;
             break;
           }
         }
@@ -1704,7 +1700,7 @@ int ARKode(void *arkode_mem, realtype tout, N_Vector yout,
       if ( SUNRabs(ark_mem->ark_tn - ark_mem->ark_tstop) <= troundoff) {
         (void) ARKodeGetDky(ark_mem, ark_mem->ark_tstop, 0, yout);
         ark_mem->ark_tretlast = *tret = ark_mem->ark_tstop;
-        ark_mem->ark_tstopset = FALSE;
+        ark_mem->ark_tstopset = SUNFALSE;
         istate = ARK_TSTOP_RETURN;
         break;
       }
@@ -1984,7 +1980,7 @@ int ARKodeRootInit(void *arkode_mem, int nrtfn, ARKRootFn g)
   for(i=0; i<nrt; i++) ark_mem->ark_rootdir[i] = 0;
 
   /* Set default values for gactive (all active) */
-  for(i=0; i<nrt; i++) ark_mem->ark_gactive[i] = TRUE;
+  for(i=0; i<nrt; i++) ark_mem->ark_gactive[i] = SUNTRUE;
 
   ark_mem->ark_lrw += 3*nrt;
   ark_mem->ark_liw += 3*nrt;
@@ -2069,9 +2065,7 @@ int arkRwtSet(N_Vector y, N_Vector weight, void *data)
   /* put M*y into ark_ftemp */
   My = ark_mem->ark_ftemp;
   if (ark_mem->ark_mass_matrix) {
-    flag = ark_mem->ark_mtimes(y, My, ark_mem->ark_tn, 
-			       ark_mem->ark_mtimes_data);
-    ark_mem->ark_mass_mult++;
+    flag = ark_mem->ark_mmult(ark_mem, y, My);
     if (flag != ARK_SUCCESS)  return (ARK_MASSMULT_FAIL);
   } else {  /* this condition should not apply, but just in case */
     N_VScale(ONE, y, My);
@@ -2130,291 +2124,286 @@ void arkErrHandler(int error_code, const char *module,
 
  This routine outputs the ark_mem structure to stdout.
 ---------------------------------------------------------------*/
-static void arkPrintMem(ARKodeMem ark_mem)
+static void arkPrintMem(ARKodeMem ark_mem, FILE *outfile)
 {
   int i, j;
 
   /* output integer quantities */
-  printf("ark_itol = %i\n", ark_mem->ark_itol);
-  printf("ark_ritol = %i\n", ark_mem->ark_ritol);
-  printf("ark_q = %i\n", ark_mem->ark_q);
-  printf("ark_p = %i\n", ark_mem->ark_p);
-  printf("ark_istage = %i\n", ark_mem->ark_istage);
-  printf("ark_stages = %i\n", ark_mem->ark_stages);
-  printf("ark_dense_q = %i\n", ark_mem->ark_dense_q);
-  printf("ark_mnewt = %i\n", ark_mem->ark_mnewt);
-  printf("ark_hadapt_imethod = %i\n", ark_mem->ark_hadapt_imethod);
-  printf("ark_maxcor = %i\n", ark_mem->ark_maxcor);
-  printf("ark_mxhnil = %i\n", ark_mem->ark_mxhnil);
-  printf("ark_maxnef = %i\n", ark_mem->ark_maxnef);
-  printf("ark_maxncf = %i\n", ark_mem->ark_maxncf);
-  printf("ark_small_nef = %i\n", ark_mem->ark_small_nef);
-  printf("ark_msbp = %i\n", ark_mem->ark_msbp);
-  printf("ark_predictor = %i\n", ark_mem->ark_predictor);
-  printf("ark_nhnil = %i\n", ark_mem->ark_nhnil);
-  printf("ark_lsolve_type = %i\n", ark_mem->ark_lsolve_type);
-  printf("ark_msolve_type = %i\n", ark_mem->ark_msolve_type);
-  printf("ark_nrtfn = %i\n", ark_mem->ark_nrtfn);
+  fprintf(outfile, "ark_itol = %i\n", ark_mem->ark_itol);
+  fprintf(outfile, "ark_ritol = %i\n", ark_mem->ark_ritol);
+  fprintf(outfile, "ark_q = %i\n", ark_mem->ark_q);
+  fprintf(outfile, "ark_p = %i\n", ark_mem->ark_p);
+  fprintf(outfile, "ark_istage = %i\n", ark_mem->ark_istage);
+  fprintf(outfile, "ark_stages = %i\n", ark_mem->ark_stages);
+  fprintf(outfile, "ark_dense_q = %i\n", ark_mem->ark_dense_q);
+  fprintf(outfile, "ark_mnewt = %i\n", ark_mem->ark_mnewt);
+  fprintf(outfile, "ark_hadapt_imethod = %i\n", ark_mem->ark_hadapt_imethod);
+  fprintf(outfile, "ark_maxcor = %i\n", ark_mem->ark_maxcor);
+  fprintf(outfile, "ark_mxhnil = %i\n", ark_mem->ark_mxhnil);
+  fprintf(outfile, "ark_maxnef = %i\n", ark_mem->ark_maxnef);
+  fprintf(outfile, "ark_maxncf = %i\n", ark_mem->ark_maxncf);
+  fprintf(outfile, "ark_small_nef = %i\n", ark_mem->ark_small_nef);
+  fprintf(outfile, "ark_msbp = %i\n", ark_mem->ark_msbp);
+  fprintf(outfile, "ark_predictor = %i\n", ark_mem->ark_predictor);
+  fprintf(outfile, "ark_nhnil = %i\n", ark_mem->ark_nhnil);
+  fprintf(outfile, "ark_lsolve_type = %i\n", ark_mem->ark_lsolve_type);
+  fprintf(outfile, "ark_msolve_type = %i\n", ark_mem->ark_msolve_type);
+  fprintf(outfile, "ark_nrtfn = %i\n", ark_mem->ark_nrtfn);
   if (ark_mem->ark_iroots != NULL) 
     for (i=0; i<ark_mem->ark_nrtfn; i++)
-      printf("ark_iroots[%i] = %i\n", i, ark_mem->ark_iroots[i]);
+      fprintf(outfile, "ark_iroots[%i] = %i\n", i, ark_mem->ark_iroots[i]);
   if (ark_mem->ark_rootdir != NULL) 
     for (i=0; i<ark_mem->ark_nrtfn; i++)
-      printf("ark_rootdir[%i] = %i\n", i, ark_mem->ark_rootdir[i]);
-  printf("ark_taskc = %i\n", ark_mem->ark_taskc);
-  printf("ark_irfnd = %i\n", ark_mem->ark_irfnd);
-  printf("ark_mxgnull = %i\n", ark_mem->ark_mxgnull);
+      fprintf(outfile, "ark_rootdir[%i] = %i\n", i, ark_mem->ark_rootdir[i]);
+  fprintf(outfile, "ark_taskc = %i\n", ark_mem->ark_taskc);
+  fprintf(outfile, "ark_irfnd = %i\n", ark_mem->ark_irfnd);
+  fprintf(outfile, "ark_mxgnull = %i\n", ark_mem->ark_mxgnull);
 
   /* output long integer quantities */
-  printf("ark_mxstep = %li\n", ark_mem->ark_mxstep);
-  printf("ark_nst = %li\n", ark_mem->ark_nst);
-  printf("ark_nst_acc = %li\n", ark_mem->ark_nst_acc);
-  printf("ark_nst_exp = %li\n", ark_mem->ark_nst_exp);
-  printf("ark_nst_attempts = %li\n", ark_mem->ark_nst_attempts);
-  printf("ark_nfe = %li\n", ark_mem->ark_nfe);
-  printf("ark_nfi = %li\n", ark_mem->ark_nfi);
-  printf("ark_ncfn = %li\n", ark_mem->ark_ncfn);
-  printf("ark_nmassfails = %li\n", ark_mem->ark_nmassfails);
-  printf("ark_netf = %li\n", ark_mem->ark_netf);
-  printf("ark_nni = %li\n", ark_mem->ark_nni);
-  printf("ark_nsetups = %li\n", ark_mem->ark_nsetups);
-  printf("ark_lrw1 = %li\n", ark_mem->ark_lrw1);
-  printf("ark_liw1 = %li\n", ark_mem->ark_liw1);
-  printf("ark_lrw = %li\n", ark_mem->ark_lrw);
-  printf("ark_liw = %li\n", ark_mem->ark_liw);
-  printf("ark_fp_m = %li\n", ark_mem->ark_fp_m);
+  fprintf(outfile, "ark_mxstep = %li\n", ark_mem->ark_mxstep);
+  fprintf(outfile, "ark_nst = %li\n", ark_mem->ark_nst);
+  fprintf(outfile, "ark_nst_acc = %li\n", ark_mem->ark_nst_acc);
+  fprintf(outfile, "ark_nst_exp = %li\n", ark_mem->ark_nst_exp);
+  fprintf(outfile, "ark_nst_attempts = %li\n", ark_mem->ark_nst_attempts);
+  fprintf(outfile, "ark_nfe = %li\n", ark_mem->ark_nfe);
+  fprintf(outfile, "ark_nfi = %li\n", ark_mem->ark_nfi);
+  fprintf(outfile, "ark_ncfn = %li\n", ark_mem->ark_ncfn);
+  fprintf(outfile, "ark_netf = %li\n", ark_mem->ark_netf);
+  fprintf(outfile, "ark_nni = %li\n", ark_mem->ark_nni);
+  fprintf(outfile, "ark_nsetups = %li\n", ark_mem->ark_nsetups);
+  fprintf(outfile, "ark_lrw1 = %li\n", (long int) ark_mem->ark_lrw1);
+  fprintf(outfile, "ark_liw1 = %li\n", (long int) ark_mem->ark_liw1);
+  fprintf(outfile, "ark_lrw = %li\n", (long int) ark_mem->ark_lrw);
+  fprintf(outfile, "ark_liw = %li\n", (long int) ark_mem->ark_liw);
+  fprintf(outfile, "ark_fp_m = %li\n", ark_mem->ark_fp_m);
   if (ark_mem->ark_fp_imap != NULL)
     for (i=0; i<ark_mem->ark_fp_m; i++)
-      printf("ark_fp_imap[%i] = %li\n", i, ark_mem->ark_fp_imap[i]);
-  printf("ark_mass_solves = %li\n", ark_mem->ark_mass_solves);
-  printf("ark_mass_mult = %li\n", ark_mem->ark_mass_mult);
-  printf("ark_nstlp = %li\n", ark_mem->ark_nstlp);
-  printf("ark_nge = %li\n", ark_mem->ark_nge);
+      fprintf(outfile, "ark_fp_imap[%i] = %li\n", i, ark_mem->ark_fp_imap[i]);
+  fprintf(outfile, "ark_nstlp = %li\n", ark_mem->ark_nstlp);
+  fprintf(outfile, "ark_nge = %li\n", ark_mem->ark_nge);
 
   /* output boolean quantities */
-  printf("ark_user_efun = %i\n", ark_mem->ark_user_efun);
-  printf("ark_user_linear = %i\n", ark_mem->ark_linear);
-  printf("ark_user_linear_timedep = %i\n", ark_mem->ark_linear_timedep);
-  printf("ark_user_explicit = %i\n", ark_mem->ark_explicit);
-  printf("ark_user_implicit = %i\n", ark_mem->ark_implicit);
-  printf("ark_tstopset = %i\n", ark_mem->ark_tstopset);
-  printf("ark_hadapt_pq = %i\n", ark_mem->ark_hadapt_pq);
-  printf("ark_report = %i\n", ark_mem->ark_report);
-  printf("ark_use_fp = %i\n", ark_mem->ark_use_fp);
-  printf("ark_mass_matrix = %i\n", ark_mem->ark_mass_matrix);
-  printf("ark_jcur = %i\n", ark_mem->ark_jcur);
-  printf("ark_setupNonNull = %i\n", ark_mem->ark_setupNonNull);
-  printf("ark_MassSetupNonNull = %i\n", ark_mem->ark_MassSetupNonNull);
-  printf("ark_VabstolMallocDone = %i\n", ark_mem->ark_VabstolMallocDone);
-  printf("ark_MallocDone = %i\n", ark_mem->ark_MallocDone);
-  printf("ark_resized = %i\n", ark_mem->ark_resized);
-  printf("ark_firststage = %i\n", ark_mem->ark_firststage);
+  fprintf(outfile, "ark_user_efun = %i\n", ark_mem->ark_user_efun);
+  fprintf(outfile, "ark_user_linear = %i\n", ark_mem->ark_linear);
+  fprintf(outfile, "ark_user_linear_timedep = %i\n", ark_mem->ark_linear_timedep);
+  fprintf(outfile, "ark_user_explicit = %i\n", ark_mem->ark_explicit);
+  fprintf(outfile, "ark_user_implicit = %i\n", ark_mem->ark_implicit);
+  fprintf(outfile, "ark_tstopset = %i\n", ark_mem->ark_tstopset);
+  fprintf(outfile, "ark_hadapt_pq = %i\n", ark_mem->ark_hadapt_pq);
+  fprintf(outfile, "ark_report = %i\n", ark_mem->ark_report);
+  fprintf(outfile, "ark_use_fp = %i\n", ark_mem->ark_use_fp);
+  fprintf(outfile, "ark_mass_matrix = %i\n", ark_mem->ark_mass_matrix);
+  fprintf(outfile, "ark_jcur = %i\n", ark_mem->ark_jcur);
+  fprintf(outfile, "ark_VabstolMallocDone = %i\n", ark_mem->ark_VabstolMallocDone);
+  fprintf(outfile, "ark_MallocDone = %i\n", ark_mem->ark_MallocDone);
+  fprintf(outfile, "ark_resized = %i\n", ark_mem->ark_resized);
+  fprintf(outfile, "ark_firststage = %i\n", ark_mem->ark_firststage);
   if (ark_mem->ark_gactive != NULL)
     for (i=0; i<ark_mem->ark_nrtfn; i++)
-      printf("ark_gactive[%i] = %i\n", i, ark_mem->ark_gactive[i]);
+      fprintf(outfile, "ark_gactive[%i] = %i\n", i, ark_mem->ark_gactive[i]);
 
   /* output realtype quantities */
-  printf("ark_uround = %.16g\n", ark_mem->ark_uround);
-  printf("ark_reltol = %.16g\n", ark_mem->ark_reltol);
-  printf("ark_Sabstol = %.16g\n", ark_mem->ark_Sabstol);
-  printf("ark_tstop = %.16g\n", ark_mem->ark_tstop);
-  printf("ark_Ae = \n");
+  fprintf(outfile, "ark_uround = %"RSYM"\n", ark_mem->ark_uround);
+  fprintf(outfile, "ark_reltol = %"RSYM"\n", ark_mem->ark_reltol);
+  fprintf(outfile, "ark_Sabstol = %"RSYM"\n", ark_mem->ark_Sabstol);
+  fprintf(outfile, "ark_tstop = %"RSYM"\n", ark_mem->ark_tstop);
+  fprintf(outfile, "ark_Ae = \n");
   for (i=0; i<ARK_S_MAX; i++) {
-    printf("    ");
+    fprintf(outfile, "    ");
     for (j=0; j<ARK_S_MAX; j++)
-      printf("%.16g  ", ARK_A(ark_mem->ark_Ae,i,j));
-    printf("\n");
+      fprintf(outfile, "%"RSYM"  ", ARK_A(ark_mem->ark_Ae,i,j));
+    fprintf(outfile, "\n");
   }
-  printf("ark_Ai = \n");
+  fprintf(outfile, "ark_Ai = \n");
   for (i=0; i<ARK_S_MAX; i++) {
-    printf("    ");
+    fprintf(outfile, "    ");
     for (j=0; j<ARK_S_MAX; j++)
-      printf("%.16g  ", ARK_A(ark_mem->ark_Ai,i,j));
-    printf("\n");
+      fprintf(outfile, "%"RSYM"  ", ARK_A(ark_mem->ark_Ai,i,j));
+    fprintf(outfile, "\n");
   }
-  printf("ark_ce = ");
+  fprintf(outfile, "ark_ce = ");
   for (i=0; i<ARK_S_MAX; i++) 
-    printf("%.16g  ", ark_mem->ark_ce[i]);
-  printf("\n");
-  printf("ark_ci = ");
+    fprintf(outfile, "%"RSYM"  ", ark_mem->ark_ce[i]);
+  fprintf(outfile, "\n");
+  fprintf(outfile, "ark_ci = ");
   for (i=0; i<ARK_S_MAX; i++) 
-    printf("%.16g  ", ark_mem->ark_ci[i]);
-  printf("\n");
-  printf("ark_be = ");
+    fprintf(outfile, "%"RSYM"  ", ark_mem->ark_ci[i]);
+  fprintf(outfile, "\n");
+  fprintf(outfile, "ark_be = ");
   for (i=0; i<ARK_S_MAX; i++) 
-    printf("%.16g  ", ark_mem->ark_be[i]);
-  printf("\n");
-  printf("ark_bi = ");
+    fprintf(outfile, "%"RSYM"  ", ark_mem->ark_be[i]);
+  fprintf(outfile, "\n");
+  fprintf(outfile, "ark_bi = ");
   for (i=0; i<ARK_S_MAX; i++) 
-    printf("%.16g  ", ark_mem->ark_bi[i]);
-  printf("\n");
-  printf("ark_b2e = ");
+    fprintf(outfile, "%"RSYM"  ", ark_mem->ark_bi[i]);
+  fprintf(outfile, "\n");
+  fprintf(outfile, "ark_b2e = ");
   for (i=0; i<ARK_S_MAX; i++) 
-    printf("%.16g  ", ark_mem->ark_b2e[i]);
-  printf("\n");
-  printf("ark_b2i = ");
+    fprintf(outfile, "%"RSYM"  ", ark_mem->ark_b2e[i]);
+  fprintf(outfile, "\n");
+  fprintf(outfile, "ark_b2i = ");
   for (i=0; i<ARK_S_MAX; i++) 
-    printf("%.16g  ", ark_mem->ark_b2i[i]);
-  printf("\n");
-  printf("ark_hin = %.16g\n", ark_mem->ark_hin);
-  printf("ark_h = %.16g\n", ark_mem->ark_h);
-  printf("ark_hprime = %.16g\n", ark_mem->ark_hprime);
-  printf("ark_next_h = %.16g\n", ark_mem->ark_next_h);
-  printf("ark_eta = %.16g\n", ark_mem->ark_eta);
-  printf("ark_tn = %.16g\n", ark_mem->ark_tn);
-  printf("ark_tretlast = %.16g\n", ark_mem->ark_tretlast);
-  printf("ark_gamma = %.16g\n", ark_mem->ark_gamma);
-  printf("ark_gammap = %.16g\n", ark_mem->ark_gammap);
-  printf("ark_gamrat = %.16g\n", ark_mem->ark_gamrat);
-  printf("ark_crate = %.16g\n", ark_mem->ark_crate);
-  printf("ark_eRNrm = %.16g\n", ark_mem->ark_eRNrm);
-  printf("ark_nlscoef = %.16g\n", ark_mem->ark_nlscoef);
-  printf("ark_fixedstep = %i\n", ark_mem->ark_fixedstep);
-  printf("ark_hadapt_ehist =  %.16g  %.16g  %.16g\n",
+    fprintf(outfile, "%"RSYM"  ", ark_mem->ark_b2i[i]);
+  fprintf(outfile, "\n");
+  fprintf(outfile, "ark_hin = %"RSYM"\n", ark_mem->ark_hin);
+  fprintf(outfile, "ark_h = %"RSYM"\n", ark_mem->ark_h);
+  fprintf(outfile, "ark_hprime = %"RSYM"\n", ark_mem->ark_hprime);
+  fprintf(outfile, "ark_next_h = %"RSYM"\n", ark_mem->ark_next_h);
+  fprintf(outfile, "ark_eta = %"RSYM"\n", ark_mem->ark_eta);
+  fprintf(outfile, "ark_tn = %"RSYM"\n", ark_mem->ark_tn);
+  fprintf(outfile, "ark_tretlast = %"RSYM"\n", ark_mem->ark_tretlast);
+  fprintf(outfile, "ark_gamma = %"RSYM"\n", ark_mem->ark_gamma);
+  fprintf(outfile, "ark_gammap = %"RSYM"\n", ark_mem->ark_gammap);
+  fprintf(outfile, "ark_gamrat = %"RSYM"\n", ark_mem->ark_gamrat);
+  fprintf(outfile, "ark_crate = %"RSYM"\n", ark_mem->ark_crate);
+  fprintf(outfile, "ark_eRNrm = %"RSYM"\n", ark_mem->ark_eRNrm);
+  fprintf(outfile, "ark_nlscoef = %"RSYM"\n", ark_mem->ark_nlscoef);
+  fprintf(outfile, "ark_fixedstep = %i\n", ark_mem->ark_fixedstep);
+  fprintf(outfile, "ark_hadapt_ehist =  %"RSYM"  %"RSYM"  %"RSYM"\n",
 	 ark_mem->ark_hadapt_ehist[0], ark_mem->ark_hadapt_ehist[1], ark_mem->ark_hadapt_ehist[2]);
-  printf("ark_hadapt_hhist =  %.16g  %.16g  %.16g\n",
+  fprintf(outfile, "ark_hadapt_hhist =  %"RSYM"  %"RSYM"  %"RSYM"\n",
 	 ark_mem->ark_hadapt_hhist[0], ark_mem->ark_hadapt_hhist[1], ark_mem->ark_hadapt_hhist[2]);
-  printf("ark_hadapt_cfl = %.16g\n", ark_mem->ark_hadapt_cfl);
-  printf("ark_hadapt_safety = %.16g\n", ark_mem->ark_hadapt_safety);
-  printf("ark_hadapt_bias = %.16g\n", ark_mem->ark_hadapt_bias);
-  printf("ark_hadapt_growth = %.16g\n", ark_mem->ark_hadapt_growth);
-  printf("ark_hadapt_lbound = %.16g\n", ark_mem->ark_hadapt_lbound);
-  printf("ark_hadapt_ubound = %.16g\n", ark_mem->ark_hadapt_ubound);
-  printf("ark_hadapt_k1 = %.16g\n", ark_mem->ark_hadapt_k1);
-  printf("ark_hadapt_k2 = %.16g\n", ark_mem->ark_hadapt_k2);
-  printf("ark_hadapt_k3 = %.16g\n", ark_mem->ark_hadapt_k3);
-  printf("ark_hmin = %.16g\n", ark_mem->ark_hmin);
-  printf("ark_hmax_inv = %.16g\n", ark_mem->ark_hmax_inv);
-  printf("ark_etamax = %.16g\n", ark_mem->ark_etamax);
-  printf("ark_etamx1 = %.16g\n", ark_mem->ark_etamx1);
-  printf("ark_etamxf = %.16g\n", ark_mem->ark_etamxf);
-  printf("ark_etacf = %.16g\n", ark_mem->ark_etacf);
-  printf("ark_crdown = %.16g\n", ark_mem->ark_crdown);
-  printf("ark_rdiv = %.16g\n", ark_mem->ark_rdiv);
-  printf("ark_dgmax = %.16g\n", ark_mem->ark_dgmax);
+  fprintf(outfile, "ark_hadapt_cfl = %"RSYM"\n", ark_mem->ark_hadapt_cfl);
+  fprintf(outfile, "ark_hadapt_safety = %"RSYM"\n", ark_mem->ark_hadapt_safety);
+  fprintf(outfile, "ark_hadapt_bias = %"RSYM"\n", ark_mem->ark_hadapt_bias);
+  fprintf(outfile, "ark_hadapt_growth = %"RSYM"\n", ark_mem->ark_hadapt_growth);
+  fprintf(outfile, "ark_hadapt_lbound = %"RSYM"\n", ark_mem->ark_hadapt_lbound);
+  fprintf(outfile, "ark_hadapt_ubound = %"RSYM"\n", ark_mem->ark_hadapt_ubound);
+  fprintf(outfile, "ark_hadapt_k1 = %"RSYM"\n", ark_mem->ark_hadapt_k1);
+  fprintf(outfile, "ark_hadapt_k2 = %"RSYM"\n", ark_mem->ark_hadapt_k2);
+  fprintf(outfile, "ark_hadapt_k3 = %"RSYM"\n", ark_mem->ark_hadapt_k3);
+  fprintf(outfile, "ark_hmin = %"RSYM"\n", ark_mem->ark_hmin);
+  fprintf(outfile, "ark_hmax_inv = %"RSYM"\n", ark_mem->ark_hmax_inv);
+  fprintf(outfile, "ark_etamax = %"RSYM"\n", ark_mem->ark_etamax);
+  fprintf(outfile, "ark_etamx1 = %"RSYM"\n", ark_mem->ark_etamx1);
+  fprintf(outfile, "ark_etamxf = %"RSYM"\n", ark_mem->ark_etamxf);
+  fprintf(outfile, "ark_etacf = %"RSYM"\n", ark_mem->ark_etacf);
+  fprintf(outfile, "ark_crdown = %"RSYM"\n", ark_mem->ark_crdown);
+  fprintf(outfile, "ark_rdiv = %"RSYM"\n", ark_mem->ark_rdiv);
+  fprintf(outfile, "ark_dgmax = %"RSYM"\n", ark_mem->ark_dgmax);
   if (ark_mem->ark_fp_R != NULL) {
-    printf("ark_fp_R =  ");
+    fprintf(outfile, "ark_fp_R =  ");
     for (i=0; i<ark_mem->ark_fp_m*ark_mem->ark_fp_m; i++)
-      printf("%.16g  ", ark_mem->ark_fp_R[i]);
-    printf("\n");
+      fprintf(outfile, "%"RSYM"  ", ark_mem->ark_fp_R[i]);
+    fprintf(outfile, "\n");
   }
   if (ark_mem->ark_fp_gamma != NULL) {
-    printf("ark_fp_gamma =  ");
+    fprintf(outfile, "ark_fp_gamma =  ");
     for (i=0; i<ark_mem->ark_fp_m; i++)
-      printf("%.16g  ", ark_mem->ark_fp_gamma[i]);
-    printf("\n");
-  }
-  printf("ark_h0u = %.16g\n", ark_mem->ark_h0u);
-  printf("ark_tnew = %.16g\n", ark_mem->ark_tnew);
-  printf("ark_hold = %.16g\n", ark_mem->ark_hold);
-  printf("ark_tolsf = %.16g\n", ark_mem->ark_tolsf);
-  printf("ark_tlo = %.16g\n", ark_mem->ark_tlo);
-  printf("ark_thi = %.16g\n", ark_mem->ark_thi);
-  printf("ark_trout = %.16g\n", ark_mem->ark_trout);
+      fprintf(outfile, "%"RSYM"  ", ark_mem->ark_fp_gamma[i]);
+    fprintf(outfile, "\n");
+  }
+  fprintf(outfile, "ark_h0u = %"RSYM"\n", ark_mem->ark_h0u);
+  fprintf(outfile, "ark_tnew = %"RSYM"\n", ark_mem->ark_tnew);
+  fprintf(outfile, "ark_hold = %"RSYM"\n", ark_mem->ark_hold);
+  fprintf(outfile, "ark_tolsf = %"RSYM"\n", ark_mem->ark_tolsf);
+  fprintf(outfile, "ark_tlo = %"RSYM"\n", ark_mem->ark_tlo);
+  fprintf(outfile, "ark_thi = %"RSYM"\n", ark_mem->ark_thi);
+  fprintf(outfile, "ark_trout = %"RSYM"\n", ark_mem->ark_trout);
   if (ark_mem->ark_glo != NULL) 
     for (i=0; i<ark_mem->ark_nrtfn; i++)
-      printf("ark_glo[%i] = %.16g\n", i, ark_mem->ark_glo[i]);
+      fprintf(outfile, "ark_glo[%i] = %"RSYM"\n", i, ark_mem->ark_glo[i]);
   if (ark_mem->ark_ghi != NULL) 
     for (i=0; i<ark_mem->ark_nrtfn; i++)
-      printf("ark_ghi[%i] = %.16g\n", i, ark_mem->ark_ghi[i]);
+      fprintf(outfile, "ark_ghi[%i] = %"RSYM"\n", i, ark_mem->ark_ghi[i]);
   if (ark_mem->ark_grout != NULL) 
     for (i=0; i<ark_mem->ark_nrtfn; i++)
-      printf("ark_grout[%i] = %.16g\n", i, ark_mem->ark_grout[i]);
-  printf("ark_toutc = %.16g\n", ark_mem->ark_toutc);
-  printf("ark_ttol = %.16g\n", ark_mem->ark_ttol);
+      fprintf(outfile, "ark_grout[%i] = %"RSYM"\n", i, ark_mem->ark_grout[i]);
+  fprintf(outfile, "ark_toutc = %"RSYM"\n", ark_mem->ark_toutc);
+  fprintf(outfile, "ark_ttol = %"RSYM"\n", ark_mem->ark_ttol);
 
 #ifdef DEBUG_OUTPUT
   /* output vector quantities */  
   if (ark_mem->ark_Vabstol != NULL) {
-    printf("ark_Vapbsol:\n");
+    fprintf(outfile, "ark_Vapbsol:\n");
     N_VPrint_Serial(ark_mem->ark_Vabstol);
   }
   for (i=0; i<ARK_S_MAX; i++) 
     if (ark_mem->ark_Fe[i] != NULL) {
-      printf("ark_Fe[%i]:\n", i);
+      fprintf(outfile, "ark_Fe[%i]:\n", i);
       N_VPrint_Serial(ark_mem->ark_Fe[i]);
     }
   for (i=0; i<ARK_S_MAX; i++) 
     if (ark_mem->ark_Fi[i] != NULL) {
-      printf("ark_Fi[%i]:\n", i);
+      fprintf(outfile, "ark_Fi[%i]:\n", i);
       N_VPrint_Serial(ark_mem->ark_Fi[i]);
     }
   if (ark_mem->ark_ewt != NULL) {
-    printf("ark_ewt:\n");
+    fprintf(outfile, "ark_ewt:\n");
     N_VPrint_Serial(ark_mem->ark_ewt);
   }
   if (!ark_mem->ark_rwt_is_ewt && ark_mem->ark_rwt != NULL) {
-    printf("ark_rwt:\n");
+    fprintf(outfile, "ark_rwt:\n");
     N_VPrint_Serial(ark_mem->ark_rwt);
   }
   if (ark_mem->ark_y != NULL) {
-    printf("ark_y:\n");
+    fprintf(outfile, "ark_y:\n");
     N_VPrint_Serial(ark_mem->ark_y);
   }
   if (ark_mem->ark_ycur != NULL) {
-    printf("ark_ycur:\n");
+    fprintf(outfile, "ark_ycur:\n");
     N_VPrint_Serial(ark_mem->ark_ycur);
   }
   if (ark_mem->ark_sdata != NULL) {
-    printf("ark_sdata:\n");
+    fprintf(outfile, "ark_sdata:\n");
     N_VPrint_Serial(ark_mem->ark_sdata);
   }
   if (ark_mem->ark_tempv != NULL) {
-    printf("ark_tempv:\n");
+    fprintf(outfile, "ark_tempv:\n");
     N_VPrint_Serial(ark_mem->ark_tempv);
   }
   if (ark_mem->ark_acor != NULL) {
-    printf("ark_acor:\n");
+    fprintf(outfile, "ark_acor:\n");
     N_VPrint_Serial(ark_mem->ark_acor);
   }
   if (ark_mem->ark_ftemp != NULL) {
-    printf("ark_ftemp:\n");
+    fprintf(outfile, "ark_ftemp:\n");
     N_VPrint_Serial(ark_mem->ark_ftemp);
   }
   if (ark_mem->ark_fold != NULL) {
-    printf("ark_fold:\n");
+    fprintf(outfile, "ark_fold:\n");
     N_VPrint_Serial(ark_mem->ark_fold);
   }
   if (ark_mem->ark_fnew != NULL) {
-    printf("ark_fnew:\n");
+    fprintf(outfile, "ark_fnew:\n");
     N_VPrint_Serial(ark_mem->ark_fnew);
   }
   if (ark_mem->ark_yold != NULL) {
-    printf("ark_yold:\n");
+    fprintf(outfile, "ark_yold:\n");
     N_VPrint_Serial(ark_mem->ark_yold);
   }
   if (ark_mem->ark_ynew != NULL) {
-    printf("ark_ynew:\n");
+    fprintf(outfile, "ark_ynew:\n");
     N_VPrint_Serial(ark_mem->ark_ynew);
   }
   if (ark_mem->ark_fp_df != NULL) 
     for (i=0; i<ark_mem->ark_fp_m; i++)
       if (ark_mem->ark_fp_df[i] != NULL) {
-	printf("ark_fp_df[%i]:\n", i);
+	fprintf(outfile, "ark_fp_df[%i]:\n", i);
 	N_VPrint_Serial(ark_mem->ark_fp_df[i]);
       }
   if (ark_mem->ark_fp_dg != NULL) 
     for (i=0; i<ark_mem->ark_fp_m; i++)
       if (ark_mem->ark_fp_dg[i] != NULL) {
-	printf("ark_fp_dg[%i]:\n", i);
+	fprintf(outfile, "ark_fp_dg[%i]:\n", i);
 	N_VPrint_Serial(ark_mem->ark_fp_dg[i]);
       }
   if (ark_mem->ark_fp_q != NULL) 
     for (i=0; i<ark_mem->ark_fp_m; i++)
       if (ark_mem->ark_fp_q[i] != NULL) {
-	printf("ark_fp_q[%i]:\n", i);
+	fprintf(outfile, "ark_fp_q[%i]:\n", i);
 	N_VPrint_Serial(ark_mem->ark_fp_q[i]);
       }
   if (ark_mem->ark_fp_fval != NULL) {
-    printf("ark_fp_fval:\n");
+    fprintf(outfile, "ark_fp_fval:\n");
     N_VPrint_Serial(ark_mem->ark_fp_fval);
   }
   if (ark_mem->ark_fp_fold != NULL) {
-    printf("ark_fp_fold:\n");
+    fprintf(outfile, "ark_fp_fold:\n");
     N_VPrint_Serial(ark_mem->ark_fp_fold);
   }
   if (ark_mem->ark_fp_gold != NULL) {
-    printf("ark_fp_gold:\n");
+    fprintf(outfile, "ark_fp_gold:\n");
     N_VPrint_Serial(ark_mem->ark_fp_gold);
   }
 #endif
@@ -2426,7 +2415,7 @@ static void arkPrintMem(ARKodeMem ark_mem)
  arkCheckNvector:
 
  This routine checks if all required vector operations are 
- present.  If any of them is missing it returns FALSE.
+ present.  If any of them is missing it returns SUNFALSE.
 ---------------------------------------------------------------*/
 static booleantype arkCheckNvector(N_Vector tmpl)  /* to be updated?? */
 {
@@ -2442,9 +2431,9 @@ static booleantype arkCheckNvector(N_Vector tmpl)  /* to be updated?? */
       (tmpl->ops->nvmaxnorm   == NULL) ||
       (tmpl->ops->nvwrmsnorm  == NULL) ||
       (tmpl->ops->nvmin       == NULL))
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 
@@ -2455,9 +2444,9 @@ static booleantype arkCheckNvector(N_Vector tmpl)  /* to be updated?? */
  sdata, tempv, ftemp, fold, fnew, yold, and ynew.  If any of 
  these vectors already exist, they are left alone.  Otherwise, it
  will allocate each vector by cloning the input vector. If all 
- memory allocations are successful, arkAllocVectors returns TRUE. 
+ memory allocations are successful, arkAllocVectors returns SUNTRUE. 
  Otherwise all vector memory is freed and arkAllocVectors 
- returns FALSE. This routine also updates the optional outputs 
+ returns SUNFALSE. This routine also updates the optional outputs 
  lrw and liw, which are (respectively) the lengths of the real 
  and integer work spaces.
 ---------------------------------------------------------------*/
@@ -2468,7 +2457,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_ewt = N_VClone(tmpl);
     if (ark_mem->ark_ewt == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2484,7 +2473,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_acor = N_VClone(tmpl);
     if (ark_mem->ark_acor == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2496,7 +2485,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_ycur = N_VClone(tmpl);
     if (ark_mem->ark_ycur == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2508,7 +2497,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_sdata = N_VClone(tmpl);
     if (ark_mem->ark_sdata == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2520,7 +2509,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_tempv = N_VClone(tmpl);
     if (ark_mem->ark_tempv == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2532,7 +2521,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_ftemp = N_VClone(tmpl);
     if (ark_mem->ark_ftemp == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2544,7 +2533,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_fold = N_VClone(tmpl);
     if (ark_mem->ark_fold == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2556,7 +2545,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_fnew = N_VClone(tmpl);
     if (ark_mem->ark_fnew == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2568,7 +2557,7 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_yold = N_VClone(tmpl);
     if (ark_mem->ark_yold == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
@@ -2580,14 +2569,14 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
     ark_mem->ark_ynew = N_VClone(tmpl);
     if (ark_mem->ark_ynew == NULL) {
       arkFreeVectors(ark_mem);
-      return(FALSE);
+      return(SUNFALSE);
     } else {
       ark_mem->ark_lrw += ark_mem->ark_lrw1;
       ark_mem->ark_liw += ark_mem->ark_liw1;
     }
   }
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 
@@ -2601,8 +2590,8 @@ static booleantype arkAllocVectors(ARKodeMem ark_mem, N_Vector tmpl)
  If any of these vectors already exist, they are left alone.  
  Otherwise, it will allocate each vector by cloning the input 
  vector. If all memory allocations are successful, 
- arkAllocRKVectors returns TRUE.  Otherwise all vector memory is 
- freed and arkAllocRKVectors returns FALSE. This routine also 
+ arkAllocRKVectors returns SUNTRUE.  Otherwise all vector memory is 
+ freed and arkAllocRKVectors returns SUNFALSE. This routine also 
  updates the optional outputs lrw and liw, which are 
  (respectively) the lengths of the real and integer work spaces.
 
@@ -2895,8 +2884,8 @@ static int arkAllocFPData(ARKodeMem ark_mem)
  fixed-point solver (called from ARKodeResize()).
 ---------------------------------------------------------------*/
 static int arkResizeFPData(ARKodeMem ark_mem, ARKVecResizeFn resize,
-			   void *resize_data, long int lrw_diff, 
-			   long int liw_diff)
+			   void *resize_data, sunindextype lrw_diff, 
+			   sunindextype liw_diff)
 {
   long int i;
   long int maa = ark_mem->ark_fp_m;
@@ -3165,6 +3154,27 @@ static int arkInitialSetup(ARKodeMem ark_mem)
     return(ARK_ILL_INPUT);
   }
 
+  /* Call minit (if it exists) */
+  if (ark_mem->ark_minit) {
+    ier = ark_mem->ark_minit(ark_mem);
+    if (ier != 0) {
+      arkProcessError(ark_mem, ARK_MASSINIT_FAIL, "ARKODE", 
+                      "arkInitialSetup", MSGARK_MASSINIT_FAIL);
+      return(ARK_MASSINIT_FAIL);
+    }
+  }
+
+  /* Call msetup (if it exists) -- use ewt, acor and sdata as temp vectors */
+  if (ark_mem->ark_msetup) {
+    ier = ark_mem->ark_msetup(ark_mem, ark_mem->ark_ewt,
+                              ark_mem->ark_acor, ark_mem->ark_sdata);
+    if (ier != 0) {
+      arkProcessError(ark_mem, ARK_MASSSETUP_FAIL, "ARKODE", 
+                      "arkInitialSetup", MSGARK_MASSSETUP_FAIL);
+      return(ARK_MASSSETUP_FAIL);
+    }
+  }
+  
   /* Set data for rfun (if left unspecified) */
   if (ark_mem->ark_user_rfun) 
     ark_mem->ark_r_data = ark_mem->ark_user_data;
@@ -3196,37 +3206,16 @@ static int arkInitialSetup(ARKodeMem ark_mem)
 		      "arkInitialSetup", MSGARK_LSOLVE_NULL);
       return(ARK_ILL_INPUT);
     }
-    if (ark_mem->ark_linit != NULL) {
+    if (ark_mem->ark_linit) {
       ier = ark_mem->ark_linit(ark_mem);
       if (ier != 0) {
-	arkProcessError(ark_mem, ARK_LINIT_FAIL, "ARKODE", 
-			"arkInitialSetup", MSGARK_LINIT_FAIL);
-	return(ARK_LINIT_FAIL);
+        arkProcessError(ark_mem, ARK_LINIT_FAIL, "ARKODE", 
+                        "arkInitialSetup", MSGARK_LINIT_FAIL);
+        return(ARK_LINIT_FAIL);
       }
     }
   }
 
-  /* Call minit (if it exists) */
-  if (ark_mem->ark_minit != NULL) {
-    ier = ark_mem->ark_minit(ark_mem);
-    if (ier != 0) {
-      arkProcessError(ark_mem, ARK_MASSINIT_FAIL, "ARKODE", 
-		      "arkInitialSetup", MSGARK_MASSINIT_FAIL);
-      return(ARK_MASSINIT_FAIL);
-    }
-  }
-  
-  /* Call msetup (if necessary) */
-  if (ark_mem->ark_mass_matrix && ark_mem->ark_MassSetupNonNull) {
-    ier = ark_mem->ark_msetup(ark_mem, ark_mem->ark_ewt, 
-			      ark_mem->ark_acor, ark_mem->ark_sdata);
-    if (ier != 0) {
-      arkProcessError(ark_mem, ARK_MASSSETUP_FAIL, "ARKODE", 
-		      "arkInitialSetup", MSGARK_MASSSETUP_FAIL);
-      return(ARK_MASSSETUP_FAIL);
-    }
-  }
-
   /* Allocate fixed-point solver memory */
   if (ark_mem->ark_use_fp) {
     ier = arkAllocFPData(ark_mem);
@@ -3246,11 +3235,9 @@ static int arkInitialSetup(ARKodeMem ark_mem)
   /* if the problem involves a non-identity mass matrix, update fnew here */
   if (ark_mem->ark_mass_matrix) {
     N_VScale(ark_mem->ark_h, ark_mem->ark_fnew, ark_mem->ark_fnew);   /* scale RHS */
-    ier = ark_mem->ark_msolve(ark_mem, ark_mem->ark_fnew, ark_mem->ark_rwt); 
+    ier = ark_mem->ark_msolve(ark_mem, ark_mem->ark_fnew); 
     N_VScale(ONE/ark_mem->ark_h, ark_mem->ark_fnew, ark_mem->ark_fnew);   /* scale result */
-    ark_mem->ark_mass_solves++;
     if (ier != ARK_SUCCESS) {
-      ark_mem->ark_nmassfails++;
       arkProcessError(ark_mem, ARK_MASSSOLVE_FAIL, "ARKODE", 
 		      "arkInitialSetup", "Mass matrix solver failure");
       return(ARK_MASSSOLVE_FAIL);
@@ -3333,12 +3320,12 @@ static int arkHin(ARKodeMem ark_mem, realtype tout)
   }
   
   /* Outer loop */
-  hnewOK = FALSE;
+  hnewOK = SUNFALSE;
   hs = hg;     /* safeguard against 'uninitialized variable' warning */
   for(count1 = 1; count1 <= H0_ITERS; count1++) {
 
     /* Attempts to estimate ydd */
-    hgOK = FALSE;
+    hgOK = SUNFALSE;
 
     for (count2 = 1; count2 <= H0_ITERS; count2++) {
       hgs = hg*sign;
@@ -3346,7 +3333,7 @@ static int arkHin(ARKodeMem ark_mem, realtype tout)
       /* If f() failed unrecoverably, give up */
       if (retval < 0) return(ARK_RHSFUNC_FAIL);
       /* If successful, we can use ydd */
-      if (retval == ARK_SUCCESS) {hgOK = TRUE; break;}
+      if (retval == ARK_SUCCESS) {hgOK = SUNTRUE; break;}
       /* f() failed recoverably; cut step size and test it again */
       hg *= POINT2;
     }
@@ -3372,12 +3359,12 @@ static int arkHin(ARKodeMem ark_mem, realtype tout)
     hrat = hnew/hg;
     
     /* Accept hnew if it does not differ from hg by more than a factor of 2 */
-    if ((hrat > HALF) && (hrat < TWO))  hnewOK = TRUE;
+    if ((hrat > HALF) && (hrat < TWO))  hnewOK = SUNTRUE;
 
     /* After one pass, if ydd seems to be bad, use fall-back value. */
     if ((count1 > 1) && (hrat > TWO)) {
       hnew = hg;
-      hnewOK = TRUE;
+      hnewOK = SUNTRUE;
     }
 
     /* Send this value back through f() */
@@ -3455,12 +3442,9 @@ static int arkYddNorm(ARKodeMem ark_mem, realtype hg, realtype *yddnrm)
   /* if using a non-identity mass matrix, update fnew here to get y' */
   if (ark_mem->ark_mass_matrix) {
     N_VScale(ark_mem->ark_h, ark_mem->ark_tempv, ark_mem->ark_tempv);
-    retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_tempv, ark_mem->ark_rwt); 
-    /* retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_tempv, ark_mem->ark_ewt);  */
+    retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_tempv); 
     N_VScale(ONE/ark_mem->ark_h, ark_mem->ark_tempv, ark_mem->ark_tempv);
-    ark_mem->ark_mass_solves++;
     if (retval != ARK_SUCCESS) {
-      ark_mem->ark_nmassfails++;
       arkProcessError(ark_mem, ARK_MASSSOLVE_FAIL, "ARKODE", 
 		      "arkYddNorm", "Mass matrix solver failure");
       return(ARK_MASSSOLVE_FAIL);
@@ -3491,16 +3475,16 @@ static int arkSetButcherTables(ARKodeMem ark_mem)
 
   /* if tables have already been specified, just return */
   int i,j,q, etable=-1, itable=-1;
-  booleantype A_set = FALSE;
+  booleantype A_set = SUNFALSE;
   for (i=0; i<ARK_S_MAX; i++) {
     for (j=0; j<ARK_S_MAX; j++) {
-      if (SUNRabs(ARK_A(ark_mem->ark_Ae,i,j)) > TINY)  A_set = TRUE;
-      if (SUNRabs(ARK_A(ark_mem->ark_Ai,i,j)) > TINY)  A_set = TRUE;
+      if (SUNRabs(ARK_A(ark_mem->ark_Ae,i,j)) > TINY)  A_set = SUNTRUE;
+      if (SUNRabs(ARK_A(ark_mem->ark_Ai,i,j)) > TINY)  A_set = SUNTRUE;
     }
-    if (SUNRabs(ark_mem->ark_be[i]) > TINY)  A_set = TRUE;
-    if (SUNRabs(ark_mem->ark_bi[i]) > TINY)  A_set = TRUE;
-    if (SUNRabs(ark_mem->ark_ce[i]) > TINY)  A_set = TRUE;
-    if (SUNRabs(ark_mem->ark_ci[i]) > TINY)  A_set = TRUE;
+    if (SUNRabs(ark_mem->ark_be[i]) > TINY)  A_set = SUNTRUE;
+    if (SUNRabs(ark_mem->ark_bi[i]) > TINY)  A_set = SUNTRUE;
+    if (SUNRabs(ark_mem->ark_ce[i]) > TINY)  A_set = SUNTRUE;
+    if (SUNRabs(ark_mem->ark_ci[i]) > TINY)  A_set = SUNTRUE;
   }
   if (A_set)  return (ARK_SUCCESS);
 
@@ -3635,11 +3619,11 @@ static int arkCheckButcherTables(ARKodeMem ark_mem)
 
   /* check that ERK table is strictly lower triangular */
   if (!ark_mem->ark_implicit) {
-    okay = TRUE;
+    okay = SUNTRUE;
     for (i=0; i<ark_mem->ark_stages; i++)
       for (j=i; j<ark_mem->ark_stages; j++)
 	if (SUNRabs(ARK_A(ark_mem->ark_Ae,i,j)) > tol)
-	  okay = FALSE;
+	  okay = SUNFALSE;
     if (!okay) {
       arkProcessError(NULL, ARK_ILL_INPUT, "ARKODE", 
 		      "arkCheckButcherTables",
@@ -3650,10 +3634,10 @@ static int arkCheckButcherTables(ARKodeMem ark_mem)
 
   /* check that IRK table is implicit */
   if (!ark_mem->ark_explicit) {
-    okay = FALSE;
+    okay = SUNFALSE;
     for (i=0; i<ark_mem->ark_stages; i++)
       if (SUNRabs(ARK_A(ark_mem->ark_Ai,i,i)) > tol)
-	okay = TRUE;
+	okay = SUNTRUE;
     if (!okay) {
       arkProcessError(NULL, ARK_ILL_INPUT, "ARKODE", 
 		      "arkCheckButcherTables",
@@ -3664,11 +3648,11 @@ static int arkCheckButcherTables(ARKodeMem ark_mem)
 
   /* check that IRK table is lower triangular */
   if (!ark_mem->ark_explicit) {
-    okay = TRUE;
+    okay = SUNTRUE;
     for (i=0; i<ark_mem->ark_stages; i++)
       for (j=i+1; j<ark_mem->ark_stages; j++)
 	if (SUNRabs(ARK_A(ark_mem->ark_Ai,i,j)) > tol)
-	  okay = FALSE;
+	  okay = SUNFALSE;
     if (!okay) {
       arkProcessError(NULL, ARK_ILL_INPUT, "ARKODE", 
 		      "arkCheckButcherTables",
@@ -3756,7 +3740,7 @@ static int arkStep(ARKodeMem ark_mem)
       /* } */
 
 #ifdef DEBUG_OUTPUT
- printf("step %li,  stage %i,  h = %19.16g,  t_n = %19.16g\n", 
+ printf("step %li,  stage %i,  h = %"RSYM",  t_n = %"RSYM"\n", 
 	 ark_mem->ark_nst, is, ark_mem->ark_h, ark_mem->ark_tn);
 #endif
       
@@ -3780,7 +3764,7 @@ static int arkStep(ARKodeMem ark_mem)
 
       /* Solver diagnostics reporting */
       if (ark_mem->ark_report) 	
-	fprintf(ark_mem->ark_diagfp, "step  %li  %19.16g  %i  %19.16g\n",
+	fprintf(ark_mem->ark_diagfp, "step  %li  %"RSYM"  %i  %"RSYM"\n",
 		ark_mem->ark_nst, ark_mem->ark_h, is, ark_mem->ark_tn);
 
       /* solve implicit problem (if required) */
@@ -3815,19 +3799,11 @@ static int arkStep(ARKodeMem ark_mem)
 	if (ark_mem->ark_mass_matrix) {
 
 	  /* perform mass matrix solve */
-	  /* nflag = ark_mem->ark_msolve(ark_mem, ark_mem->ark_sdata,  */
-	  /* 			      ark_mem->ark_ewt);  */
-	  nflag = ark_mem->ark_msolve(ark_mem, ark_mem->ark_sdata, 
-				      ark_mem->ark_rwt); 
-	  ark_mem->ark_mass_solves++;
+	  nflag = ark_mem->ark_msolve(ark_mem, ark_mem->ark_sdata); 
 	  
 	  /* check for convergence (on failure, h will have been modified) */
 	  kflag = arkHandleNFlag(ark_mem, &nflag, saved_t, &ncf);
 
-	  /* increment failure counter if necessary */
-	  if (kflag != SOLVE_SUCCESS)
-	    ark_mem->ark_nmassfails++;
-
 	  /* If fixed time-stepping is used, then anything other than a 
 	     successful solve must result in an error */
 	  if (ark_mem->ark_fixedstep && (kflag != SOLVE_SUCCESS)) 
@@ -3880,12 +3856,12 @@ static int arkStep(ARKodeMem ark_mem)
     if (retval < 0)  return(retval);    /* msetup failure */
 
 #ifdef DEBUG_OUTPUT
- printf("error estimate = %19.16g\n", dsm);
+ printf("error estimate = %"RSYM"\n", dsm);
 #endif
 
     /* Solver diagnostics reporting */
     if (ark_mem->ark_report) 
-      fprintf(ark_mem->ark_diagfp, "  etest  %li  %19.16g  %19.16g\n", 
+      fprintf(ark_mem->ark_diagfp, "  etest  %li  %"RSYM"  %"RSYM"\n", 
 	      ark_mem->ark_nst, ark_mem->ark_h, dsm);
 
     /* Perform time accuracy error test (if failure, updates h for next try) */
@@ -4096,9 +4072,7 @@ static int arkSet(ARKodeMem ark_mem)
     /* If M!=I, replace sdata with M*sdata, so that sdata = M*(yn-ycur) */
     if (ark_mem->ark_mass_matrix) {
       N_VScale(ONE, ark_mem->ark_sdata, tmp);
-      retval = ark_mem->ark_mtimes(tmp, ark_mem->ark_sdata, ark_mem->ark_tn, 
-                                   ark_mem->ark_mtimes_data);
-      ark_mem->ark_mass_mult++;
+      retval = ark_mem->ark_mmult(ark_mem, tmp, ark_mem->ark_sdata);
       if (retval != ARK_SUCCESS)  return (ARK_MASSMULT_FAIL);
     }
 
@@ -4162,7 +4136,7 @@ static int arkComputeSolutions(ARKodeMem ark_mem, realtype *dsm)
   if (ark_mem->ark_mass_matrix) {   /* M != I */
 
     /* setup mass matrix, using y, tmp1, tmp2 as temporaries */
-    if (ark_mem->ark_MassSetupNonNull) {
+    if (ark_mem->ark_msetup) {
       ier = ark_mem->ark_msetup(ark_mem, y, tmp1, tmp2);
       if (ier != ARK_SUCCESS)  return(ARK_MASSSETUP_FAIL);
     }
@@ -4181,11 +4155,8 @@ static int arkComputeSolutions(ARKodeMem ark_mem, realtype *dsm)
     }
     
     /* solve for y update (stored in y) */
-    /* ier = ark_mem->ark_msolve(ark_mem, y, ark_mem->ark_ewt);  */
-    ier = ark_mem->ark_msolve(ark_mem, y, ark_mem->ark_rwt); 
-    ark_mem->ark_mass_solves++;
+    ier = ark_mem->ark_msolve(ark_mem, y); 
     if (ier < 0) {
-      ark_mem->ark_nmassfails++;
       *dsm = 2.0;         /* indicate too much error, step with smaller step */
       N_VScale(ONE, ark_mem->ark_ynew, y);      /* place old solution into y */
       return(CONV_FAIL);
@@ -4212,11 +4183,8 @@ static int arkComputeSolutions(ARKodeMem ark_mem, realtype *dsm)
       }
 
       /* solve for yerr */
-      /* ier = ark_mem->ark_msolve(ark_mem, yerr, ark_mem->ark_ewt);  */
-      ier = ark_mem->ark_msolve(ark_mem, yerr, ark_mem->ark_rwt); 
-      ark_mem->ark_mass_solves++;
+      ier = ark_mem->ark_msolve(ark_mem, yerr); 
       if (ier < 0) {
-	ark_mem->ark_nmassfails++;
 	*dsm = 2.0;         /* indicate too much error, step with smaller step */
 	return(CONV_FAIL);
       }
@@ -4372,7 +4340,7 @@ static int arkCompleteStep(ARKodeMem ark_mem, realtype dsm)
   ark_mem->ark_tnew = ark_mem->ark_tn;
 
   /* turn off flag regarding resized problem */
-  ark_mem->ark_resized = FALSE;
+  ark_mem->ark_resized = SUNFALSE;
 
   /* update error history array */
   ark_mem->ark_hadapt_ehist[2] = ark_mem->ark_hadapt_ehist[1];
@@ -4410,13 +4378,13 @@ static int arkCompleteStep(ARKodeMem ark_mem, realtype dsm)
      if ce[s-1] = 1.0 and ci[s-1] = 1.0 and no post-processing, use already-computed 
      RHS values, otherwise compute from scratch */
   N_VConst(ZERO, ark_mem->ark_fnew);
-  recomputeRHS = FALSE;
+  recomputeRHS = SUNFALSE;
   if (ark_mem->ark_ProcessStep != NULL) 
-    recomputeRHS = TRUE;
+    recomputeRHS = SUNTRUE;
   if ((!ark_mem->ark_implicit) && (SUNRabs(ark_mem->ark_ce[ark_mem->ark_stages-1]-ONE)>TINY))
-    recomputeRHS = TRUE;
+    recomputeRHS = SUNTRUE;
   if ((!ark_mem->ark_explicit) && (SUNRabs(ark_mem->ark_ci[ark_mem->ark_stages-1]-ONE)>TINY))
-    recomputeRHS = TRUE;
+    recomputeRHS = SUNTRUE;
   if (recomputeRHS) {
     retval = arkFullRHS(ark_mem, ark_mem->ark_tn, ark_mem->ark_y, 
 			ark_mem->ark_ftemp, ark_mem->ark_fnew);
@@ -4433,11 +4401,9 @@ static int arkCompleteStep(ARKodeMem ark_mem, realtype dsm)
   /* if M!=I, update fnew with M^{-1}*fnew (note, mass matrix already current) */
   if (ark_mem->ark_mass_matrix) {   /* M != I */
     N_VScale(ark_mem->ark_h, ark_mem->ark_fnew, ark_mem->ark_fnew);      /* scale RHS */
-    retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_fnew, ark_mem->ark_rwt); 
+    retval = ark_mem->ark_msolve(ark_mem, ark_mem->ark_fnew); 
     N_VScale(ONE/ark_mem->ark_h, ark_mem->ark_fnew, ark_mem->ark_fnew);  /* scale result */
-    ark_mem->ark_mass_solves++;
     if (retval != ARK_SUCCESS) {
-      ark_mem->ark_nmassfails++;
       arkProcessError(ark_mem, ARK_MASSSOLVE_FAIL, "ARKODE", 
 		      "arkCompleteStep", "Mass matrix solver failure");
       return(ARK_MASSSOLVE_FAIL);
@@ -4543,9 +4509,7 @@ static int arkNlsResid(ARKodeMem ark_mem, N_Vector y,
 
   /* put M*y in r */
   if (ark_mem->ark_mass_matrix) {
-    retval = ark_mem->ark_mtimes(y, r, ark_mem->ark_tn, 
-				 ark_mem->ark_mtimes_data);
-    ark_mem->ark_mass_mult++;
+    retval = ark_mem->ark_mmult(ark_mem, y, r);
     if (retval != ARK_SUCCESS)  
       return (ARK_MASSMULT_FAIL);
   } else {
@@ -4607,24 +4571,24 @@ static int arkNlsNewton(ARKodeMem ark_mem, int nflag)
     ARK_NO_FAILURES : ARK_FAIL_OTHER;
 
   /* Decide whether or not to call setup routine (if one exists) */
-  if (ark_mem->ark_setupNonNull) {      
+  if (ark_mem->ark_lsetup) {      
     callSetup = (nflag == PREV_CONV_FAIL) || (nflag == PREV_ERR_FAIL) ||
       (ark_mem->ark_firststage) || (ark_mem->ark_msbp < 0) ||
       (ark_mem->ark_nst >= ark_mem->ark_nstlp + abs(ark_mem->ark_msbp)) || 
       (SUNRabs(ark_mem->ark_gamrat-ONE) > ark_mem->ark_dgmax);
   } else {  
     ark_mem->ark_crate = ONE;
-    callSetup = FALSE;
+    callSetup = SUNFALSE;
   }
   
   /* Looping point for attempts at solution of the nonlinear system:
-       Evaluate f at predicted y, store result in ark_mem->ark_ftemp.
-       Call lsetup if indicated, setting statistics and gamma factors.
-       Zero out the correction array (ark_mem->ark_acor).
-       Copy the predicted y (ycur) into the output (ark_mem->ark_y).
-       Performs the modified Newton iteration using the existing lsetup.
-       Repeat process if a recoverable failure occurred (convergence
-	  failure with stale Jacobian). */
+     Evaluate f at predicted y, store result in ark_mem->ark_ftemp.
+     Call lsetup if indicated, setting statistics and gamma factors.
+     Zero out the correction array (ark_mem->ark_acor).
+     Copy the predicted y (ycur) into the output (ark_mem->ark_y).
+     Performs the modified Newton iteration using the existing lsetup.
+     Repeat process if a recoverable failure occurred (convergence
+     failure with stale Jacobian). */
   for(;;) {
 
     if (!ark_mem->ark_explicit) {
@@ -4635,6 +4599,7 @@ static int arkNlsNewton(ARKodeMem ark_mem, int nflag)
       if (retval > 0) return(RHSFUNC_RECVR);
     }
     
+    /* update system matrix/factorization if necessary */
     if (callSetup) {
 
       /* Solver diagnostics reporting */
@@ -4644,8 +4609,8 @@ static int arkNlsNewton(ARKodeMem ark_mem, int nflag)
 				ark_mem->ark_ftemp, &ark_mem->ark_jcur, 
 				vtemp1, vtemp2, vtemp3);
       ark_mem->ark_nsetups++;
-      callSetup = FALSE;
-      ark_mem->ark_firststage = FALSE;
+      callSetup = SUNFALSE;
+      ark_mem->ark_firststage = SUNFALSE;
       ark_mem->ark_gamrat = ark_mem->ark_crate = ONE; 
       ark_mem->ark_gammap = ark_mem->ark_gamma;
       ark_mem->ark_nstlp  = ark_mem->ark_nst;
@@ -4681,30 +4646,29 @@ static int arkNlsNewton(ARKodeMem ark_mem, int nflag)
 
       /* Evaluate the nonlinear system residual, put result into b */
       retval = arkNlsResid(ark_mem, ark_mem->ark_acor, 
-			   ark_mem->ark_ftemp, b);
+                           ark_mem->ark_ftemp, b);
       if (retval != ARK_SUCCESS) {
-	ier = ARK_RHSFUNC_FAIL;
-	break;
+        ier = ARK_RHSFUNC_FAIL;
+        break;
       }
 
       /* Call the lsolve function */
-      retval = ark_mem->ark_lsolve(ark_mem, b, ark_mem->ark_rwt, 
-				   ark_mem->ark_y, ark_mem->ark_ftemp); 
+      retval = ark_mem->ark_lsolve(ark_mem, b, ark_mem->ark_y, ark_mem->ark_ftemp); 
       ark_mem->ark_nni++;
     
       if (retval < 0) {
-	ier = ARK_LSOLVE_FAIL;
-	break;
+        ier = ARK_LSOLVE_FAIL;
+        break;
       }
     
       /* If lsolve had a recoverable failure and Jacobian data is
 	 not current, signal to try the solution again */
       if (retval > 0) { 
-	if ((!ark_mem->ark_jcur) && (ark_mem->ark_setupNonNull)) 
-	  ier = TRY_AGAIN;
-	else 
-	  ier = CONV_FAIL;
-	break;
+        if ((!ark_mem->ark_jcur) && (ark_mem->ark_lsetup)) 
+          ier = TRY_AGAIN;
+        else 
+          ier = CONV_FAIL;
+        break;
       }
 
       /* Get WRMS norm of correction; add correction to acor and y */
@@ -4713,68 +4677,68 @@ static int arkNlsNewton(ARKodeMem ark_mem, int nflag)
       N_VLinearSum(ONE, ark_mem->ark_ycur, ONE, ark_mem->ark_acor, ark_mem->ark_y);
 
       /* Compute the nonlinear error estimate.  If m > 0, an estimate of the convergence
-	 rate constant is stored in crate, and used in the subsequent estimates */
+         rate constant is stored in crate, and used in the subsequent estimates */
       if (m > 0) 
-	ark_mem->ark_crate = SUNMAX(ark_mem->ark_crdown*ark_mem->ark_crate, del/delp);
+        ark_mem->ark_crate = SUNMAX(ark_mem->ark_crdown*ark_mem->ark_crate, del/delp);
       dcon = SUNMIN(ark_mem->ark_crate, ONE) * del / ark_mem->ark_nlscoef;
 
       /* compute the forcing term for linear solver tolerance */
       ark_mem->ark_eRNrm = SUNMIN(ark_mem->ark_crate, ONE) * del
-	                 * RCONST(0.1) * ark_mem->ark_nlscoef;
+                         * RCONST(0.1) * ark_mem->ark_nlscoef;
 #ifdef FIXED_LIN_TOL
       /* reset if a fixed linear solver tolerance is desired */
       ark_mem->ark_eRNrm = RCONST(0.1) * ark_mem->ark_nlscoef;
 #endif
 
 #ifdef DEBUG_OUTPUT
- printf("Newton iter %i,  del = %19.16g,  crate = %19.16g\n", m, del, ark_mem->ark_crate);
- printf("   dcon = %19.16g\n", dcon);
+ printf("Newton iter %i,  del = %"RSYM",  crate = %"RSYM"\n", m, del, ark_mem->ark_crate);
+ printf("   dcon = %"RSYM"\n", dcon);
  printf("Newton correction:\n");
  N_VPrint_Serial(ark_mem->ark_acor);
 #endif
 
       /* Solver diagnostics reporting */
       if (ark_mem->ark_report) 
-	fprintf(ark_mem->ark_diagfp, "    newt  %i  %19.16g  %19.16g\n", m, del, dcon);
+        fprintf(ark_mem->ark_diagfp, "    newt  %i  %"RSYM"  %"RSYM"\n", m, del, dcon);
     
       if (dcon <= ONE) {
-	ark_mem->ark_jcur = FALSE;
-	ier = ARK_SUCCESS;
-	break;
+        ark_mem->ark_jcur = SUNFALSE;
+        ier = ARK_SUCCESS;
+        break;
       }
 
       /* update Newton iteration counter */
       ark_mem->ark_mnewt = ++m;
     
       /* Stop at maxcor iterations or if iteration seems to be diverging.
-	 If still not converged and Jacobian data is not current, signal 
-	 to try the solution again */
-      if ((m == ark_mem->ark_maxcor) || 
-	  ((m >= 2) && (del > ark_mem->ark_rdiv*delp))) {
-	if ((!ark_mem->ark_jcur) && (ark_mem->ark_setupNonNull)) 
-	  ier = TRY_AGAIN;
-	else
-	  ier = CONV_FAIL;
-	break;
+         If still not converged and Jacobian data is not current, signal 
+         to try the solution again */
+      if ( (m == ark_mem->ark_maxcor) || 
+           ((m >= 2) && (del > ark_mem->ark_rdiv*delp)) ) {
+        if ((!ark_mem->ark_jcur) && (ark_mem->ark_lsetup)) 
+          ier = TRY_AGAIN;
+        else
+          ier = CONV_FAIL;
+        break;
       }
     
       /* Save norm of correction, evaluate fi, and loop again */
       delp = del;
       if (!ark_mem->ark_explicit) {
-	retval = ark_mem->ark_fi(ark_mem->ark_tn, ark_mem->ark_y, 
-				 ark_mem->ark_ftemp, ark_mem->ark_user_data);
-	ark_mem->ark_nfi++;
-	if (retval < 0) {
-	  ier = ARK_RHSFUNC_FAIL;
-	  break;
-	}
-	if (retval > 0) {
-	  if ((!ark_mem->ark_jcur) && (ark_mem->ark_setupNonNull)) 
-	    ier = TRY_AGAIN;
-	  else
-	    ier = RHSFUNC_RECVR;
-	  break;
-	}
+        retval = ark_mem->ark_fi(ark_mem->ark_tn, ark_mem->ark_y, 
+                                 ark_mem->ark_ftemp, ark_mem->ark_user_data);
+        ark_mem->ark_nfi++;
+        if (retval < 0) {
+          ier = ARK_RHSFUNC_FAIL;
+          break;
+        }
+        if (retval > 0) {
+          if ((!ark_mem->ark_jcur) && (ark_mem->ark_lsetup)) 
+            ier = TRY_AGAIN;
+          else
+            ier = RHSFUNC_RECVR;
+          break;
+        }
       }
     } 
     /* end modified Newton iteration */
@@ -4785,7 +4749,7 @@ static int arkNlsNewton(ARKodeMem ark_mem, int nflag)
        in which convfail=ARK_FAIL_BAD_J.  Otherwise return. */
     if (ier != TRY_AGAIN) return(ier);
     
-    callSetup = TRUE;
+    callSetup = SUNTRUE;
     convfail = ARK_FAIL_BAD_J;
   }
 }
@@ -4865,6 +4829,7 @@ static int arkNlsAccelFP(ARKodeMem ark_mem, int nflag)
     if (retval != ARK_SUCCESS) return(ARK_RHSFUNC_FAIL);
 
     /* convert nonlinear residual result to a fixed-point function result */
+    /* NOTE: AS IMPLEMENTED, DOES NOT WORK WITH NON-IDENTITY MASS MATRIX */
     N_VLinearSum(ONE, y, ONE, fval, fval);
 
     /* perform fixed point update */
@@ -4888,15 +4853,15 @@ static int arkNlsAccelFP(ARKodeMem ark_mem, int nflag)
     dcon = SUNMIN(ark_mem->ark_crate, ONE) * del / ark_mem->ark_nlscoef;
 
 #ifdef DEBUG_OUTPUT
- printf("FP iter %i,  del = %19.16g,  crate = %19.16g\n", ark_mem->ark_mnewt, del, ark_mem->ark_crate);
- printf("   dcon = %19.16g\n", dcon);
+ printf("FP iter %i,  del = %"RSYM",  crate = %"RSYM"\n", ark_mem->ark_mnewt, del, ark_mem->ark_crate);
+ printf("   dcon = %"RSYM"\n", dcon);
  printf("Fixed-point correction:\n");
  N_VPrint_Serial(tempv);
 #endif
 
     /* Solver diagnostics reporting */
     if (ark_mem->ark_report)
-      fprintf(ark_mem->ark_diagfp, "    fp  %i  %19.16g  %19.16g\n", ark_mem->ark_mnewt, del, dcon);
+      fprintf(ark_mem->ark_diagfp, "    fp  %i  %"RSYM"  %"RSYM"\n", ark_mem->ark_mnewt, del, dcon);
 
     /* update iteration counter */
     ark_mem->ark_mnewt++;
@@ -5099,12 +5064,12 @@ static int arkLs(ARKodeMem ark_mem, int nflag)
   convfail = (nflag == FIRST_CALL) ? ARK_NO_FAILURES : ARK_FAIL_OTHER;
 
   /* Decide whether or not to call setup routine (if one exists) */
-  if (ark_mem->ark_setupNonNull) {      
+  if (ark_mem->ark_lsetup) {    
     callSetup = (ark_mem->ark_firststage) || 
       (ark_mem->ark_linear_timedep) || (ark_mem->ark_msbp < 0) ||
       (SUNRabs(ark_mem->ark_gamrat-ONE) > ark_mem->ark_dgmax);
   } else {  
-    callSetup = FALSE;
+    callSetup = SUNFALSE;
   }
   
   /* update implicit RHS, store in ark_mem->ark_ftemp */
@@ -5116,7 +5081,7 @@ static int arkLs(ARKodeMem ark_mem, int nflag)
     if (retval > 0) return(RHSFUNC_RECVR);
   }
   
-  /* update system matrix if necessary */
+  /* update system matrix/factorization if necessary */
   if (callSetup) {
 
     /* Solver diagnostics reporting */
@@ -5126,8 +5091,8 @@ static int arkLs(ARKodeMem ark_mem, int nflag)
 			      ark_mem->ark_ftemp, &ark_mem->ark_jcur, 
 			      vtemp1, vtemp2, vtemp3);
     ark_mem->ark_nsetups++;
-    callSetup = FALSE;
-    ark_mem->ark_firststage = FALSE;
+    callSetup = SUNFALSE;
+    ark_mem->ark_firststage = SUNFALSE;
     ark_mem->ark_gamrat = ark_mem->ark_crate = ONE; 
     ark_mem->ark_gammap = ark_mem->ark_gamma;
     ark_mem->ark_nstlp  = ark_mem->ark_nst;
@@ -5156,8 +5121,7 @@ static int arkLs(ARKodeMem ark_mem, int nflag)
   if (retval != ARK_SUCCESS)  return (ARK_RHSFUNC_FAIL);
 
   /*   Call the lsolve function */
-  retval = ark_mem->ark_lsolve(ark_mem, b, ark_mem->ark_rwt, 
-			       ark_mem->ark_y, ark_mem->ark_ftemp); 
+  retval = ark_mem->ark_lsolve(ark_mem, b, ark_mem->ark_y, ark_mem->ark_ftemp); 
   ark_mem->ark_nni++;
   if (retval != 0)  return (ARK_LSOLVE_FAIL);
     
@@ -5168,10 +5132,10 @@ static int arkLs(ARKodeMem ark_mem, int nflag)
 
   /*   Solver diagnostics reporting */
   if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "    newt  %i  %19.16g  %19.16g\n", 0, del, 0.0);
+    fprintf(ark_mem->ark_diagfp, "    newt  %i  %"RSYM"  %g\n", 0, del, 0.0);
 
   /* clean up and return */ 
-  ark_mem->ark_jcur = FALSE;
+  ark_mem->ark_jcur = SUNFALSE;
   return (ARK_SUCCESS);
 }
 
@@ -5452,7 +5416,7 @@ static int arkFullRHS(ARKodeMem ark_mem, realtype t,
 
   /* if the problem involves a non-identity mass matrix and setup is
      required, do so here (use f, tmp and ark_sdata as a temporaries) */
-  if (ark_mem->ark_mass_matrix && ark_mem->ark_MassSetupNonNull) {
+  if (ark_mem->ark_mass_matrix && ark_mem->ark_msetup) {
     retval = ark_mem->ark_msetup(ark_mem, f, tmp, ark_mem->ark_sdata);
     if (retval != ARK_SUCCESS)  return(ARK_MASSSETUP_FAIL);
   }
@@ -5655,7 +5619,7 @@ static int arkAdapt(ARKodeMem ark_mem)
 
   /* Solver diagnostics reporting */
   if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "  adapt  %19.16g  %19.16g  %19.16g  %19.16g  %19.16g  %19.16g  %19.16g  %19.16g  ",
+    fprintf(ark_mem->ark_diagfp, "  adapt  %"RSYM"  %"RSYM"  %"RSYM"  %"RSYM"  %"RSYM"  %"RSYM"  %"RSYM"  %"RSYM"  ",
 	    ark_mem->ark_hadapt_ehist[0], ark_mem->ark_hadapt_ehist[1], 
 	    ark_mem->ark_hadapt_ehist[2], ark_mem->ark_hadapt_hhist[0], 
 	    ark_mem->ark_hadapt_hhist[1], ark_mem->ark_hadapt_hhist[2], h_acc, h_cfl);
@@ -5672,7 +5636,7 @@ static int arkAdapt(ARKodeMem ark_mem)
 
   /* Solver diagnostics reporting */
   if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "%19.16g  %19.16g  ", h_acc, h_cfl);
+    fprintf(ark_mem->ark_diagfp, "%"RSYM"  %"RSYM"  ", h_acc, h_cfl);
 
   /* increment the relevant step counter, set desired step */
   if (SUNRabs(h_acc) < SUNRabs(h_cfl))
@@ -5699,7 +5663,7 @@ static int arkAdapt(ARKodeMem ark_mem)
 
   /* Solver diagnostics reporting */
   if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "%19.16g\n", ark_mem->ark_eta);
+    fprintf(ark_mem->ark_diagfp, "%"RSYM"\n", ark_mem->ark_eta);
 
   return(ier);
 }
@@ -5963,11 +5927,11 @@ static int arkRootCheck1(ARKodeMem ark_mem)
   ark_mem->ark_nge = 1;
   if (retval != 0) return(ARK_RTFUNC_FAIL);
 
-  zroot = FALSE;
+  zroot = SUNFALSE;
   for (i = 0; i < ark_mem->ark_nrtfn; i++) {
     if (SUNRabs(ark_mem->ark_glo[i]) == ZERO) {
-      zroot = TRUE;
-      ark_mem->ark_gactive[i] = FALSE;
+      zroot = SUNTRUE;
+      ark_mem->ark_gactive[i] = SUNFALSE;
     }
   }
   if (!zroot) return(ARK_SUCCESS);
@@ -5987,7 +5951,7 @@ static int arkRootCheck1(ARKodeMem ark_mem)
    * to see if we can 'activate' them. */
   for (i = 0; i < ark_mem->ark_nrtfn; i++) {
     if (!ark_mem->ark_gactive[i] && SUNRabs(ark_mem->ark_ghi[i]) != ZERO) {
-      ark_mem->ark_gactive[i] = TRUE;
+      ark_mem->ark_gactive[i] = SUNTRUE;
       ark_mem->ark_glo[i] = ark_mem->ark_ghi[i];
     }
   }
@@ -6035,7 +5999,7 @@ static int arkRootCheck2(ARKodeMem ark_mem)
   if (retval != 0) return(ARK_RTFUNC_FAIL);
 
   /* reset root-finding flags (overall, and for specific eqns) */
-  zroot = FALSE;
+  zroot = SUNFALSE;
   for (i = 0; i < ark_mem->ark_nrtfn; i++) 
     ark_mem->ark_iroots[i] = 0;
 
@@ -6043,7 +6007,7 @@ static int arkRootCheck2(ARKodeMem ark_mem)
   for (i = 0; i < ark_mem->ark_nrtfn; i++) {
     if (!ark_mem->ark_gactive[i]) continue;
     if (SUNRabs(ark_mem->ark_glo[i]) == ZERO) {
-      zroot = TRUE;
+      zroot = SUNTRUE;
       ark_mem->ark_iroots[i] = 1;
     }
   }
@@ -6073,12 +6037,12 @@ static int arkRootCheck2(ARKodeMem ark_mem)
 
   /* Check for close roots (error return), for a new zero at tlo+smallh,
   and for a g_i that changed from zero to nonzero. */
-  zroot = FALSE;
+  zroot = SUNFALSE;
   for (i = 0; i < ark_mem->ark_nrtfn; i++) {
     if (!ark_mem->ark_gactive[i]) continue;
     if (SUNRabs(ark_mem->ark_ghi[i]) == ZERO) {
       if (ark_mem->ark_iroots[i] == 1) return(CLOSERT);
-      zroot = TRUE;
+      zroot = SUNTRUE;
       ark_mem->ark_iroots[i] = 1;
     } else {
       if (ark_mem->ark_iroots[i] == 1) 
@@ -6133,7 +6097,7 @@ static int arkRootCheck3(ARKodeMem ark_mem)
   if (ier == ARK_RTFUNC_FAIL) return(ARK_RTFUNC_FAIL);
   for(i=0; i<ark_mem->ark_nrtfn; i++) {
     if (!ark_mem->ark_gactive[i] && ark_mem->ark_grout[i] != ZERO) 
-      ark_mem->ark_gactive[i] = TRUE;
+      ark_mem->ark_gactive[i] = SUNTRUE;
   }
   ark_mem->ark_tlo = ark_mem->ark_trout;
   for (i = 0; i < ark_mem->ark_nrtfn; i++) 
@@ -6179,10 +6143,10 @@ static int arkRootCheck3(ARKodeMem ark_mem)
 
  gactive  = array specifying whether a component of g should
             or should not be monitored. gactive[i] is initially
-            set to TRUE for all i=0,...,nrtfn-1, but it may be
-            reset to FALSE if at the first step g[i] is 0.0
+            set to SUNTRUE for all i=0,...,nrtfn-1, but it may be
+            reset to SUNFALSE if at the first step g[i] is 0.0
             both at the I.C. and at a small perturbation of them.
-            gactive[i] is then set back on TRUE only after the 
+            gactive[i] is then set back on SUNTRUE only after the 
             corresponding g function moves away from 0.0.
 
  nge      = cumulative counter for gfun calls.
@@ -6235,20 +6199,20 @@ static int arkRootfind(ARKodeMem ark_mem)
 
   /* First check for change in sign in ghi or for a zero in ghi. */
   maxfrac = ZERO;
-  zroot = FALSE;
-  sgnchg = FALSE;
+  zroot = SUNFALSE;
+  sgnchg = SUNFALSE;
   for (i = 0;  i < ark_mem->ark_nrtfn; i++) {
     if (!ark_mem->ark_gactive[i]) continue;
     if (SUNRabs(ark_mem->ark_ghi[i]) == ZERO) {
       if (ark_mem->ark_rootdir[i]*ark_mem->ark_glo[i] <= ZERO) {
-        zroot = TRUE;
+        zroot = SUNTRUE;
       }
     } else {
       if ( (ark_mem->ark_glo[i]*ark_mem->ark_ghi[i] < ZERO) && 
 	   (ark_mem->ark_rootdir[i]*ark_mem->ark_glo[i] <= ZERO) ) {
         gfrac = SUNRabs(ark_mem->ark_ghi[i]/(ark_mem->ark_ghi[i] - ark_mem->ark_glo[i]));
         if (gfrac > maxfrac) {
-          sgnchg = TRUE;
+          sgnchg = SUNTRUE;
           maxfrac = gfrac;
           imax = i;
         }
@@ -6322,21 +6286,21 @@ static int arkRootfind(ARKodeMem ark_mem)
     /* Check to see in which subinterval g changes sign, and reset imax.
        Set side = 1 if sign change is on low side, or 2 if on high side.  */  
     maxfrac = ZERO;
-    zroot = FALSE;
-    sgnchg = FALSE;
+    zroot = SUNFALSE;
+    sgnchg = SUNFALSE;
     sideprev = side;
     for (i = 0;  i < ark_mem->ark_nrtfn; i++) {
       if (!ark_mem->ark_gactive[i]) continue;
       if (SUNRabs(ark_mem->ark_grout[i]) == ZERO) {
         if (ark_mem->ark_rootdir[i]*ark_mem->ark_glo[i] <= ZERO) {
-          zroot = TRUE;
+          zroot = SUNTRUE;
         }
       } else {
         if ( (ark_mem->ark_glo[i]*ark_mem->ark_grout[i] < ZERO) && 
 	     (ark_mem->ark_rootdir[i]*ark_mem->ark_glo[i] <= ZERO) ) {
           gfrac = SUNRabs(ark_mem->ark_grout[i]/(ark_mem->ark_grout[i] - ark_mem->ark_glo[i]));
           if (gfrac > maxfrac) {
-            sgnchg = TRUE;
+            sgnchg = SUNTRUE;
             maxfrac = gfrac;
             imax = i;
           }
diff --git a/src/arkode/arkode_band.c b/src/arkode/arkode_band.c
deleted file mode 100644
index 603a66a..0000000
--- a/src/arkode/arkode_band.c
+++ /dev/null
@@ -1,637 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the implementation file for the ARKBAND linear solver.
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_band.h>
-#include "arkode_direct_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* ARKBAND linit, lsetup, lsolve, and lfree routines */
-static int arkBandInit(ARKodeMem ark_mem);
-static int arkBandSetup(ARKodeMem ark_mem, int convfail, N_Vector ypred,
-                       N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                       N_Vector vtemp2, N_Vector vtemp3);
-static int arkBandSolve(ARKodeMem ark_mem, N_Vector b, N_Vector weight,
-                       N_Vector ycur, N_Vector fcur);
-static int arkBandFree(ARKodeMem ark_mem);
-
-/* ARKBAND minit, msetup, msolve, mfree and mtimes routines */
-static int arkMassBandInit(ARKodeMem ark_mem);
-static int arkMassBandSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			    N_Vector vtemp2, N_Vector vtemp3);
-static int arkMassBandSolve(ARKodeMem ark_mem, N_Vector b, N_Vector weight);
-static int arkMassBandFree(ARKodeMem ark_mem);
-static int arkMassBandMultiply(N_Vector v, N_Vector Mv, 
-			       realtype t, void *user_data);
-
-
-/*---------------------------------------------------------------
- ARKBand:
-
- This routine initializes the memory record and sets various function
- fields specific to the band linear solver module.  ARKBand first calls
- the existing lfree routine if this is not NULL.  It then sets the
- ark_linit, ark_lsetup, ark_lsolve, and ark_lfree fields in (*arkode_mem)
- to be arkBandInit, arkBandSetup, arkBandSolve, and arkBandFree,
- respectively.  It allocates memory for a structure of type
- ARKDlsMemRec and sets the ark_lmem field in (*arkode_mem) to the
- address of this structure.  It sets setupNonNull in (*arkode_mem) to be
- TRUE, d_mu to be mupper, d_ml to be mlower, and the d_jac field to be 
- arkDlsBandDQJac.  Finally, it allocates memory for M, savedJ, and pivot.  
- The ARKBand return value is SUCCESS = 0, LMEM_FAIL = -1, or 
- LIN_ILL_INPUT = -2.
-
- NOTE: The band linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKBand will first 
-       test for compatible a compatible N_Vector internal
-       representation by checking that the function 
-       N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-int ARKBand(void *arkode_mem, long int N, long int mupper, long int mlower)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKBAND", "ARKBand", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKBAND", "ARKBand", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */  
-  ark_mem->ark_linit  = arkBandInit;
-  ark_mem->ark_lsetup = arkBandSetup;
-  ark_mem->ark_lsolve = arkBandSolve;
-  ark_mem->ark_lfree  = arkBandFree;
-  ark_mem->ark_lsolve_type = 2;
-  
-  /* Get memory for ARKDlsMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMem) malloc(sizeof(struct ARKDlsMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKBand", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_BAND;
-  
-  /* Initialize Jacobian-related data */
-  arkdls_mem->d_jacDQ = TRUE;
-  arkdls_mem->d_bjac = NULL;
-  arkdls_mem->d_J_data = NULL;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_setupNonNull = TRUE;
-
-  /* Initialize counters */
-  arkDlsInitializeCounters(arkdls_mem);
-  
-  /* Load problem dimension */
-  arkdls_mem->d_n = N;
-
-  /* Load half-bandwiths in arkdls_mem */
-  arkdls_mem->d_ml = mlower;
-  arkdls_mem->d_mu = mupper;
-
-  /* Test ml and mu for legality */
-  if ((arkdls_mem->d_ml < 0) || (arkdls_mem->d_mu < 0) || (arkdls_mem->d_ml >= N) || (arkdls_mem->d_mu >= N)) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKBAND", "ARKBand", MSGD_BAD_SIZES);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  arkdls_mem->d_smu = SUNMIN(N-1, arkdls_mem->d_mu + arkdls_mem->d_ml);
-
-  /* Allocate memory for M, savedJ, and pivot arrays */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_M = NewBandMat(N, arkdls_mem->d_mu, arkdls_mem->d_ml, arkdls_mem->d_smu);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKBand", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_savedJ = NULL;
-  arkdls_mem->d_savedJ = NewBandMat(N, arkdls_mem->d_mu, arkdls_mem->d_ml, arkdls_mem->d_mu);
-  if (arkdls_mem->d_savedJ == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKBand", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_lpivots = NULL;
-  arkdls_mem->d_lpivots = NewLintArray(N);
-  if (arkdls_mem->d_lpivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKBand", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    DestroyMat(arkdls_mem->d_savedJ);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkBandInit:
-
- This routine does remaining initializations specific to the band
- linear solver.
----------------------------------------------------------------*/
-static int arkBandInit(ARKodeMem ark_mem)
-{
-  ARKDlsMem arkdls_mem;
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-
-  arkDlsInitializeCounters(arkdls_mem);
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (arkdls_mem->d_jacDQ) {
-    arkdls_mem->d_bjac = arkDlsBandDQJac;
-    arkdls_mem->d_J_data = ark_mem;
-  } else {
-    arkdls_mem->d_J_data = ark_mem->ark_user_data;
-  }
-
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkBandSetup:
-
- This routine does the setup operations for the band linear 
- solver. It makes a decision whether or not to call the Jacobian 
- evaluation routine based on various state variables, and if not 
- it uses the saved copy.  In any case, it constructs the Newton 
- matrix  A = M - gamma*J, updates counters, and calls the band 
- LU factorization routine.
----------------------------------------------------------------*/
-static int arkBandSetup(ARKodeMem ark_mem, int convfail, 
-			N_Vector ypred, N_Vector fpred, 
-			booleantype *jcurPtr, N_Vector vtemp1,
-			N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  long int i, j, ier, ml, mu, N, M, is, ie;
-  DlsMat A, Mass;
-  ARKDlsMem arkdls_mem;
-  ARKDlsMassMem arkdls_mass_mem;
-  int retval;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkdls_mem->d_nstlj + ARKD_MSBJ) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKD_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    BandCopy(arkdls_mem->d_savedJ, arkdls_mem->d_M, arkdls_mem->d_mu, arkdls_mem->d_ml);
-
-  } else {
-
-    /* If jok = FALSE, call jac routine for new J value */
-    arkdls_mem->d_nje++;
-    arkdls_mem->d_nstlj = ark_mem->ark_nst;
-    *jcurPtr = TRUE;
-    SetToZero(arkdls_mem->d_M); 
-
-    retval = arkdls_mem->d_bjac(arkdls_mem->d_n, arkdls_mem->d_mu, arkdls_mem->d_ml, 
-				ark_mem->ark_tn, ypred, fpred, arkdls_mem->d_M, 
-				arkdls_mem->d_J_data, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_JACFUNC_UNRECVR, "ARKBAND", "arkBandSetup", MSGD_JACFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    BandCopy(arkdls_mem->d_M, arkdls_mem->d_savedJ, arkdls_mem->d_mu, arkdls_mem->d_ml);
-
-  }
-
-  /* Scale J by -gamma */
-  BandScale(-ark_mem->ark_gamma, arkdls_mem->d_M);
-
-  /* Add mass matrix to get A = M-gamma*J*/
-  if (ark_mem->ark_mass_matrix) {
-
-    /* Compute mass matrix */
-    arkdls_mass_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-    SetToZero(arkdls_mass_mem->d_M);
-    retval = arkdls_mass_mem->d_bmass(arkdls_mass_mem->d_n, arkdls_mass_mem->d_mu, 
-				      arkdls_mass_mem->d_ml, ark_mem->ark_tn, 
-				      arkdls_mass_mem->d_M, arkdls_mass_mem->d_M_data, 
-				      vtemp1, vtemp2, vtemp3);
-    arkdls_mass_mem->d_nme++;
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKBAND", 
-		      "arkBandSetup",  MSGD_MASSFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-      return(1);
-    }
-
-    /* perform matrix sum */
-    ml = arkdls_mem->d_M->ml;
-    mu = arkdls_mem->d_M->mu;
-    N = arkdls_mem->d_M->N;
-    M = arkdls_mem->d_M->M;
-    A = arkdls_mem->d_M;
-    Mass = arkdls_mass_mem->d_M;
-    for (j=0; j<N; j++) {                /* loop over columns */
-      is = (0 > j-mu) ? 0 : j-mu;        /* colum nonzero bounds */
-      ie = (M-1 < j+ml) ? M-1 : j+ml;
-      for (i=is; i<=ie; i++) {           /* loop over rows */
-	BAND_ELEM(A,i,j) += BAND_ELEM(Mass,i,j);
-      }
-    }
-
-  } else {
-    AddIdentity(arkdls_mem->d_M);
-  }
-
-  /* Do LU factorization of M */
-  ier = BandGBTRF(arkdls_mem->d_M, arkdls_mem->d_lpivots);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  if (ier > 0) {
-    arkdls_mem->d_last_flag = ier;
-    return(1);
-  }
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkBandSolve:
-
- This routine handles the solve operation for the band linear solver
- by calling the band backsolve routine.  The return value is 0.
----------------------------------------------------------------*/
-static int arkBandSolve(ARKodeMem ark_mem, N_Vector b, N_Vector weight,
-                       N_Vector ycur, N_Vector fcur)
-{
-  ARKDlsMem arkdls_mem;
-  realtype *bd;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-
-  bd = N_VGetArrayPointer(b);
-
-  BandGBTRS(arkdls_mem->d_M, arkdls_mem->d_lpivots, bd);
-
-  /* scale the correction to account for change in gamma */
-  if (ark_mem->ark_gamrat != ONE) 
-    N_VScale(TWO/(ONE + ark_mem->ark_gamrat), b, b);
-
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkBandFree:
-
- This routine frees memory specific to the band linear solver.
----------------------------------------------------------------*/
-static int arkBandFree(ARKodeMem ark_mem)
-{
-  ARKDlsMem arkdls_mem;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-
-  DestroyMat(arkdls_mem->d_M);
-  DestroyMat(arkdls_mem->d_savedJ);
-  DestroyArray(arkdls_mem->d_lpivots);
-  free(arkdls_mem);
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-
-/*---------------------------------------------------------------
- ARKMassBand:
-
- This routine initializes the memory record and sets various 
- function fields specific to the band mass matrix linear solver 
- module.  ARKMassBand first calls the existing mfree routine if 
- this is not NULL.  It then sets the ark_minit, ark_msetup, 
- ark_msolve, and ark_mfree fields in (*arkode_mem) to be 
- arkMassBandInit, arkMassBandSetup, arkMassBandSolve, and 
- arkMassBandFree, respectively.  It allocates memory for a 
- structure of type ARKDlsMassMemRec and sets the ark_mass_mem 
- field in (*arkode_mem) to the address of this structure.  It 
- sets MassSetupNonNull in (*arkode_mem) to be TRUE, d_mu to be 
- mupper and d_ml to be mlower. Finally, it allocates memory for 
- M and pivot.  The ARKMassBand return value is SUCCESS = 0, 
- LMEM_FAIL = -1, or LIN_ILL_INPUT = -2.
-
- NOTE: The band linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKMassBand will first 
-       test for compatible a compatible N_Vector internal
-       representation by checking that the function 
-       N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-int ARKMassBand(void *arkode_mem, long int N, long int mupper, 
-		long int mlower, ARKDlsBandMassFn bmass)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKBAND", "ARKMassBand", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKBAND", "ARKMassBand", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = arkMassBandInit;
-  ark_mem->ark_msetup = arkMassBandSetup;
-  ark_mem->ark_msolve = arkMassBandSolve;
-  ark_mem->ark_mfree  = arkMassBandFree;
-  ark_mem->ark_mtimes = arkMassBandMultiply;
-  ark_mem->ark_mtimes_data = (void *) ark_mem;
-  ark_mem->ark_msolve_type = 2;
-  
-  /* Get memory for ARKDlsMassMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMassMem) malloc(sizeof(struct ARKDlsMassMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKMassBand", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_BAND;
-  
-  /* Initialize mass-matrix-related data */
-  arkdls_mem->d_nme = 0;
-  arkdls_mem->d_bmass = bmass;
-  arkdls_mem->d_M_data = NULL;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = TRUE;
-
-  /* Load problem dimension */
-  arkdls_mem->d_n = N;
-
-  /* Load half-bandwiths in arkdls_mem */
-  arkdls_mem->d_ml = mlower;
-  arkdls_mem->d_mu = mupper;
-
-  /* Test ml and mu for legality */
-  if ((arkdls_mem->d_ml < 0) || (arkdls_mem->d_mu < 0) || (arkdls_mem->d_ml >= N) || (arkdls_mem->d_mu >= N)) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKBAND", "ARKMassBand", MSGD_BAD_SIZES);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  arkdls_mem->d_smu = SUNMIN(N-1, arkdls_mem->d_mu + arkdls_mem->d_ml);
-
-  /* Allocate memory for M, M_lu, and pivot arrays */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_M = NewBandMat(N, arkdls_mem->d_mu, arkdls_mem->d_ml, arkdls_mem->d_mu);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKMassBand", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_M_lu = NULL;
-  arkdls_mem->d_M_lu = NewBandMat(N, arkdls_mem->d_mu, arkdls_mem->d_ml, arkdls_mem->d_smu);
-  if (arkdls_mem->d_M_lu == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKMassBand", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_lpivots = NULL;
-  arkdls_mem->d_lpivots = NewLintArray(N);
-  if (arkdls_mem->d_lpivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKBAND", "ARKMassBand", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    DestroyMat(arkdls_mem->d_M_lu);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkMassBandInit:
-
- This routine does remaining initializations specific to the band
- mass matrix linear solver.
----------------------------------------------------------------*/
-static int arkMassBandInit(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem arkdls_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  arkdls_mem->d_nme = 0;
-
-  /* Set mass matrix data */
-  arkdls_mem->d_M_data = ark_mem->ark_user_data;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassBandSetup:
-
- This routine does the setup operations for the band mass matrix
- solver. It constructs the mass matrix, M, updates counters, 
- and calls the band LU factorization routine.
----------------------------------------------------------------*/
-static int arkMassBandSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			    N_Vector vtemp2, N_Vector vtemp3)
-{
-  long int ier;
-  ARKDlsMassMem arkdls_mem;
-  int retval;
-
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-
-  SetToZero(arkdls_mem->d_M); 
-  retval = arkdls_mem->d_bmass(arkdls_mem->d_n, arkdls_mem->d_mu, 
-			       arkdls_mem->d_ml, ark_mem->ark_tn, 
-			       arkdls_mem->d_M, arkdls_mem->d_M_data, 
-			       vtemp1, vtemp2, vtemp3);
-  arkdls_mem->d_nme++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKBAND", "arkMassBandSetup", 
-		    MSGD_MASSFUNC_FAILED);
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-    return(-1);
-  }
-  if (retval > 0) {
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-    return(1);
-  }
-
-  /* Copy M into M_lu for LU decomposition */
-  BandCopy(arkdls_mem->d_M, arkdls_mem->d_M_lu, arkdls_mem->d_mu, arkdls_mem->d_ml);
-
-  /* Do LU factorization of M */
-  ier = BandGBTRF(arkdls_mem->d_M_lu, arkdls_mem->d_lpivots);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  if (ier > 0) {
-    arkdls_mem->d_last_flag = ier;
-    return(1);
-  }
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassBandSolve:
-
- This routine handles the solve operation for the band mass 
- matrix solver by calling the band backsolve routine.  The 
- return value is 0.
----------------------------------------------------------------*/
-static int arkMassBandSolve(ARKodeMem ark_mem, N_Vector b, 
-			    N_Vector weight)
-{
-  ARKDlsMassMem arkdls_mem;
-  realtype *bd;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  bd = N_VGetArrayPointer(b);
-  BandGBTRS(arkdls_mem->d_M_lu, arkdls_mem->d_lpivots, bd);
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassBandFree:
-
- This routine frees memory specific to the band linear solver.
----------------------------------------------------------------*/
-static int arkMassBandFree(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem arkdls_mem;
-
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-
-  DestroyMat(arkdls_mem->d_M);
-  DestroyMat(arkdls_mem->d_M_lu);
-  DestroyArray(arkdls_mem->d_lpivots);
-  free(arkdls_mem);
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassBandMultiply performs a matrix-vector product, 
- multiplying the current mass matrix by a given vector.
----------------------------------------------------------------*/                  
-static int arkMassBandMultiply(N_Vector v, N_Vector Mv, 
-			       realtype t, void *arkode_mem)
-{
-  /* extract the DlsMassMem structure from the user_data pointer */
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-  realtype *vdata=NULL, *Mvdata=NULL;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKBAND", 
-		    "arkMassBandMultiply", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-
-  /* access the vector arrays (since they must be serial vectors) */
-  vdata = N_VGetArrayPointer(v);
-  Mvdata = N_VGetArrayPointer(Mv);
-  if (vdata == NULL || Mvdata == NULL)
-    return(1);
-
-  /* perform matrix-vector product and return */
-  BandMatvec(arkdls_mem->d_M, vdata, Mvdata);
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
-    EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_bandpre.c b/src/arkode/arkode_bandpre.c
index 5757f17..634bc93 100644
--- a/src/arkode/arkode_bandpre.c
+++ b/src/arkode/arkode_bandpre.c
@@ -1,8 +1,10 @@
 /*---------------------------------------------------------------
  * Programmer(s): Daniel R. Reynolds @ SMU
+ * Based off of cvode_bandpre.c by Scott D. Cohen, 
+ *      Alan C. Hindmarsh, Radu Serban, and Aaron Collier @ LLNL
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -17,7 +19,7 @@
  *---------------------------------------------------------------
  * This file contains implementations of the banded difference
  * quotient Jacobian-based preconditioner and solver routines for
- * use with the ARKSPILS linear solvers..
+ * use with the ARKSPILS linear solver interface.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -36,12 +38,11 @@
 /* Prototypes of ARKBandPrecSetup and ARKBandPrecSolve */
 static int ARKBandPrecSetup(realtype t, N_Vector y, N_Vector fy, 
 			    booleantype jok, booleantype *jcurPtr, 
-			    realtype gamma, void *bp_data,
-			    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+			    realtype gamma, void *bp_data);
 static int ARKBandPrecSolve(realtype t, N_Vector y, N_Vector fy, 
 			    N_Vector r, N_Vector z, 
 			    realtype gamma, realtype delta,
-			    int lr, void *bp_data, N_Vector tmp);
+			    int lr, void *bp_data);
 
 /* Prototype for ARKBandPrecFree */
 static int ARKBandPrecFree(ARKodeMem ark_mem);
@@ -60,38 +61,43 @@ static int ARKBandPDQJac(ARKBandPrecData pdata,
        representation by checking that the function 
        N_VGetArrayPointer exists.
 ---------------------------------------------------------------*/
-int ARKBandPrecInit(void *arkode_mem, long int N, 
-		    long int mu, long int ml)
+int ARKBandPrecInit(void *arkode_mem, sunindextype N, 
+		    sunindextype mu, sunindextype ml)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
   ARKBandPrecData pdata;
-  long int mup, mlp, storagemu;
+  sunindextype mup, mlp, storagemu;
   int flag;
 
   if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBANDPRE", "ARKBandPrecInit", MSGBP_MEM_NULL);
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_MEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBANDPRE", "ARKBandPrecInit", MSGBP_LMEM_NULL);
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  /* Test if the NVECTOR package is compatible with the BAND preconditioner */
+  /* Test compatibility of NVECTOR package with the BAND preconditioner */
   if(ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKBANDPRE", "ARKBandPrecInit", MSGBP_BAD_NVECTOR);
+    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_BAD_NVECTOR);
     return(ARKSPILS_ILL_INPUT);
   }
 
+  /* Allocate data memory */
   pdata = NULL;
-  pdata = (ARKBandPrecData) malloc(sizeof *pdata);  /* Allocate data memory */
+  pdata = (ARKBandPrecData) malloc(sizeof *pdata);
   if (pdata == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", "ARKBandPrecInit", MSGBP_MEM_FAIL);
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL);
   }
 
@@ -106,86 +112,149 @@ int ARKBandPrecInit(void *arkode_mem, long int N,
 
   /* Allocate memory for saved banded Jacobian approximation. */
   pdata->savedJ = NULL;
-  pdata->savedJ = NewBandMat(N, mup, mlp, mup);
+  pdata->savedJ = SUNBandMatrix(N, mup, mlp, mup);
   if (pdata->savedJ == NULL) {
     free(pdata); pdata = NULL;
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", "ARKBandPrecInit", MSGBP_MEM_FAIL);
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL);
   }
 
   /* Allocate memory for banded preconditioner. */
   storagemu = SUNMIN(N-1, mup+mlp);
   pdata->savedP = NULL;
-  pdata->savedP = NewBandMat(N, mup, mlp, storagemu);
+  pdata->savedP = SUNBandMatrix(N, mup, mlp, storagemu);
   if (pdata->savedP == NULL) {
-    DestroyMat(pdata->savedJ);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", "ARKBandPrecInit", MSGBP_MEM_FAIL);
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL);
   }
 
-  /* Allocate memory for pivot array. */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(N);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->savedP);
-    DestroyMat(pdata->savedJ);
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(ark_mem->ark_tempv, pdata->savedP);
+  if (pdata->LS == NULL) {
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", "ARKBandPrecInit", MSGBP_MEM_FAIL);
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL);
   }
   
-  /* make sure s_P_data is free from any previous allocations */
-  if (arkspils_mem->s_pfree != NULL) {
-    arkspils_mem->s_pfree(ark_mem);
+  /* allocate memory for temporary N_Vectors */
+  pdata->tmp1 = NULL;
+  pdata->tmp1 = N_VClone(ark_mem->ark_tempv);
+  if (pdata->tmp1 == NULL) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+  pdata->tmp2 = NULL;
+  pdata->tmp2 = N_VClone(ark_mem->ark_tempv);
+  if (pdata->tmp2 == NULL) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    N_VDestroy(pdata->tmp1);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
   }
 
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKBANDPRE", 
+                    "ARKBandPrecInit", MSGBP_SUNLS_FAIL);
+    return(ARKSPILS_SUNLS_FAIL);
+  }
+  
+  /* make sure s_P_data is free from any previous allocations */
+  if (arkspils_mem->pfree)
+    arkspils_mem->pfree(ark_mem);
+
   /* Point to the new P_data field in the SPILS memory */
-  arkspils_mem->s_P_data = pdata;
+  arkspils_mem->P_data = pdata;
 
   /* Attach the pfree function */
-  arkspils_mem->s_pfree = ARKBandPrecFree;
+  arkspils_mem->pfree = ARKBandPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = ARKSpilsSetPreconditioner(arkode_mem, ARKBandPrecSetup, ARKBandPrecSolve);
-
+  flag = ARKSpilsSetPreconditioner(arkode_mem, 
+                                   ARKBandPrecSetup, 
+                                   ARKBandPrecSolve);
   return(flag);
 }
 
 
-int ARKBandPrecGetWorkSpace(void *arkode_mem, long int *lenrwBP, long int *leniwBP)
+int ARKBandPrecGetWorkSpace(void *arkode_mem, long int *lenrwBP, 
+                            long int *leniwBP)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
   ARKBandPrecData pdata;
-  long int N, ml, mu, smu;
-
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
   
   if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBANDPRE", "ARKBandPrecGetWorkSpace", MSGBP_MEM_NULL);
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecGetWorkSpace", MSGBP_MEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
   if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBANDPRE", "ARKBandPrecGetWorkSpace", MSGBP_LMEM_NULL);
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecGetWorkSpace", MSGBP_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if (arkspils_mem->s_P_data == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_PMEM_NULL, "ARKBANDPRE", "ARKBandPrecGetWorkSpace", MSGBP_PMEM_NULL);
+  if (arkspils_mem->P_data == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_PMEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecGetWorkSpace", MSGBP_PMEM_NULL);
     return(ARKSPILS_PMEM_NULL);
   } 
-  pdata = (ARKBandPrecData) arkspils_mem->s_P_data;
-
-  N   = pdata->N;
-  mu  = pdata->mu;
-  ml  = pdata->ml;
-  smu = SUNMIN( N-1, mu + ml);
-
-  *leniwBP = pdata->N;
-  *lenrwBP = N * ( 2*ml + smu + mu + 2 );
+  pdata = (ARKBandPrecData) arkspils_mem->P_data;
+
+  /* sum space requirements for all objects in pdata */
+  *leniwBP = 4;
+  *lenrwBP = 0;
+  if (ark_mem->ark_tempv->ops->nvspace) {
+    N_VSpace(ark_mem->ark_tempv, &lrw1, &liw1);
+    *leniwBP += 2*liw1;
+    *lenrwBP += 2*lrw1;
+  }
+  if (pdata->savedJ->ops->space) {
+    flag = SUNMatSpace(pdata->savedJ, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
+  if (pdata->savedP->ops->space) {
+    flag = SUNMatSpace(pdata->savedP, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
 
   return(ARKSPILS_SUCCESS);
 }
@@ -198,22 +267,25 @@ int ARKBandPrecGetNumRhsEvals(void *arkode_mem, long int *nfevalsBP)
   ARKBandPrecData pdata;
 
   if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBANDPRE", "ARKBandPrecGetNumRhsEvals", MSGBP_MEM_NULL);
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecGetNumRhsEvals", MSGBP_MEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
   if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBANDPRE", "ARKBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL);
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if (arkspils_mem->s_P_data == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_PMEM_NULL, "ARKBANDPRE", "ARKBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL);
+  if (arkspils_mem->P_data == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_PMEM_NULL, "ARKBANDPRE", 
+                    "ARKBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL);
     return(ARKSPILS_PMEM_NULL);
   } 
-  pdata = (ARKBandPrecData) arkspils_mem->s_P_data;
+  pdata = (ARKBandPrecData) arkspils_mem->P_data;
 
   *nfevalsBP = pdata->nfeBP;
 
@@ -240,41 +312,36 @@ int ARKBandPrecGetNumRhsEvals(void *arkode_mem, long int *nfevalsBP)
 
  jok     is an input flag indicating whether Jacobian-related
          data needs to be recomputed, as follows:
-           jok == FALSE means recompute Jacobian-related data
+           jok == SUNFALSE means recompute Jacobian-related data
                   from scratch.
-           jok == TRUE means that Jacobian data from the
+           jok == SUNTRUE means that Jacobian data from the
                   previous PrecSetup call will be reused
                   (with the current value of gamma).
-         A ARKBandPrecSetup call with jok == TRUE should only
-         occur after a call with jok == FALSE.
+         A ARKBandPrecSetup call with jok == SUNTRUE should only
+         occur after a call with jok == SUNFALSE.
 
  *jcurPtr is a pointer to an output integer flag which is
           set by ARKBandPrecond as follows:
-            *jcurPtr = TRUE if Jacobian data was recomputed.
-            *jcurPtr = FALSE if Jacobian data was not recomputed,
+            *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+            *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
                        but saved data was reused.
 
  gamma   is the scalar appearing in the Newton matrix.
 
  bp_data is a pointer to preconditoner data (set by ARKBandPrecInit)
 
- tmp1, tmp2, and tmp3 are pointers to memory allocated
-           for vectors of length N for work space. This
-           routine uses only tmp1 and tmp2.
-
  The value to be returned by the ARKBandPrecSetup function is
    0  if successful, or
    1  if the band factorization failed.
 ---------------------------------------------------------------*/
 static int ARKBandPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                            booleantype jok, booleantype *jcurPtr, 
-                           realtype gamma, void *bp_data,
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+                           realtype gamma, void *bp_data)
 {
   ARKBandPrecData pdata;
   ARKodeMem ark_mem;
   int retval;
-  long int ier;
+  sunindextype ier;
 
   /* Assume matrix and lpivots have already been allocated. */
   pdata = (ARKBandPrecData) bp_data;
@@ -283,39 +350,66 @@ static int ARKBandPrecSetup(realtype t, N_Vector y, N_Vector fy,
 
   if (jok) {
 
-    /* If jok = TRUE, use saved copy of J. */
-    *jcurPtr = FALSE;
-    BandCopy(pdata->savedJ, pdata->savedP, pdata->mu, pdata->ml);
+    /* If jok = SUNTRUE, use saved copy of J. */
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      arkProcessError(ark_mem, -1, "ARKBANDPRE", 
+                      "ARKBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   } else {
 
-    /* If jok = FALSE, call ARKBandPDQJac for new J value. */
-    *jcurPtr = TRUE;
-    SetToZero(pdata->savedJ);
+    /* If jok = SUNFALSE, call ARKBandPDQJac for new J value. */
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(pdata->savedJ);
+    if (retval < 0) {
+      arkProcessError(ark_mem, -1, "ARKBANDPRE", 
+                      "ARKBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    retval = ARKBandPDQJac(pdata, t, y, fy, tmp1, tmp2);
+    retval = ARKBandPDQJac(pdata, t, y, fy, 
+                           pdata->tmp1, pdata->tmp2);
     if (retval < 0) {
-      arkProcessError(ark_mem, -1, "ARKBANDPRE", "ARKBandPrecSetup", MSGBP_RHSFUNC_FAILED);
+      arkProcessError(ark_mem, -1, "ARKBANDPRE", 
+                      "ARKBandPrecSetup", MSGBP_RHSFUNC_FAILED);
       return(-1);
     }
     if (retval > 0) {
       return(1);
     }
 
-    BandCopy(pdata->savedJ, pdata->savedP, pdata->mu, pdata->ml);
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      arkProcessError(ark_mem, -1, "ARKBANDPRE", 
+                      "ARKBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   }
   
-  /* Scale and add I to get savedP = I - gamma*J. */
-  BandScale(-gamma, pdata->savedP);
-  AddIdentity(pdata->savedP);
- 
-  /* Do LU factorization of matrix. */
-  ier = BandGBTRF(pdata->savedP, pdata->lpivots);
- 
-  /* Return 0 if the LU was complete; otherwise return 1. */
-  if (ier > 0) return(1);
-  return(0);
+  /* Scale and add identity to get savedP = I - gamma*J. */
+  retval = SUNMatScaleAddI(-gamma, pdata->savedP);
+  if (retval) {
+    arkProcessError(ark_mem, -1, "ARKBANDPRE", 
+                    "ARKBandPrecSetup", MSGBP_SUNMAT_FAIL);
+    return(-1);
+  }
+
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->savedP);
+  return(ier);
 }
 
 
@@ -337,25 +431,19 @@ static int ARKBandPrecSetup(realtype t, N_Vector y, N_Vector fy,
  indicating success.
 ---------------------------------------------------------------*/ 
 static int ARKBandPrecSolve(realtype t, N_Vector y, N_Vector fy, 
-                           N_Vector r, N_Vector z, 
-                           realtype gamma, realtype delta,
-                           int lr, void *bp_data, N_Vector tmp)
+                            N_Vector r, N_Vector z, 
+                            realtype gamma, realtype delta,
+                            int lr, void *bp_data)
 {
   ARKBandPrecData pdata;
-  realtype *zd;
+  int retval;
 
-  /* Assume matrix and lpivots have already been allocated. */
+  /* Assume matrix and linear solver have already been allocated. */
   pdata = (ARKBandPrecData) bp_data;
 
-  /* Copy r to z. */
-  N_VScale(ONE, r, z);
-
-  /* Do band backsolve on the vector z. */
-  zd = N_VGetArrayPointer(z);
-
-  BandGBTRS(pdata->savedP, pdata->lpivots, zd);
-
-  return(0);
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->savedP, z, r, ZERO);
+  return(retval);
 }
 
 
@@ -372,12 +460,14 @@ static int ARKBandPrecFree(ARKodeMem ark_mem)
   if (ark_mem->ark_lmem == NULL) return(0);
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
   
-  if (arkspils_mem->s_P_data == NULL) return(0);
-  pdata = (ARKBandPrecData) arkspils_mem->s_P_data;
+  if (arkspils_mem->P_data == NULL) return(0);
+  pdata = (ARKBandPrecData) arkspils_mem->P_data;
 
-  DestroyMat(pdata->savedJ);
-  DestroyMat(pdata->savedP);
-  DestroyArray(pdata->lpivots);
+  SUNLinSolFree(pdata->LS);
+  SUNMatDestroy(pdata->savedP);
+  SUNMatDestroy(pdata->savedJ);
+  N_VDestroy(pdata->tmp1);
+  N_VDestroy(pdata->tmp2);
 
   free(pdata);
   pdata = NULL;
@@ -402,7 +492,7 @@ static int ARKBandPDQJac(ARKBandPrecData pdata,
 {
   ARKodeMem ark_mem;
   realtype fnorm, minInc, inc, inc_inv, srur;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
   int retval;
 
@@ -420,10 +510,10 @@ static int ARKBandPDQJac(ARKBandPrecData pdata,
 
   /* Set minimum increment based on uround and norm of f. */
   srur = SUNRsqrt(ark_mem->ark_uround);
-  /* fnorm = N_VWrmsNorm(fy, ark_mem->ark_ewt); */
   fnorm = N_VWrmsNorm(fy, ark_mem->ark_rwt);
   minInc = (fnorm != ZERO) ?
-    (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) * ark_mem->ark_uround * pdata->N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) * 
+     ark_mem->ark_uround * pdata->N * fnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing. */
   width = pdata->ml + pdata->mu + 1;
@@ -445,13 +535,13 @@ static int ARKBandPDQJac(ARKBandPrecData pdata,
     /* Restore ytemp, then form and load difference quotients. */
     for (j = group-1; j < pdata->N; j += width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(pdata->savedJ,j);
+      col_j = SUNBandMatrix_Column(pdata->savedJ,j);
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-pdata->mu);
       i2 = SUNMIN(j+pdata->ml, pdata->N-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) =
+        SM_COLUMN_ELEMENT_B(col_j,i,j) =
           inc_inv * (ftemp_data[i] - fy_data[i]);
     }
   }
diff --git a/src/arkode/arkode_bandpre_impl.h b/src/arkode/arkode_bandpre_impl.h
index 6c65b69..efb0cac 100644
--- a/src/arkode/arkode_bandpre_impl.h
+++ b/src/arkode/arkode_bandpre_impl.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -22,8 +22,8 @@
 #define _ARKBANDPRE_IMPL_H
 
 #include <arkode/arkode_bandpre.h>
-#include <sundials/sundials_band.h>
-#include <sundials/sundials_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -36,13 +36,15 @@ extern "C" {
 typedef struct ARKBandPrecDataRec {
 
   /* Data set by user in ARKBandPrecInit */
-  long int N;
-  long int ml, mu;
+  sunindextype N;
+  sunindextype ml, mu;
 
   /* Data set by ARKBandPrecSetup */
-  DlsMat savedJ;
-  DlsMat savedP;
-  long int *lpivots;
+  SUNMatrix savedJ;
+  SUNMatrix savedP;
+  SUNLinearSolver LS;
+  N_Vector tmp1;
+  N_Vector tmp2;
 
   /* Rhs calls */
   long int nfeBP;
@@ -58,9 +60,11 @@ typedef struct ARKBandPrecDataRec {
 ---------------------------------------------------------------*/
 
 #define MSGBP_MEM_NULL       "Integrator memory is NULL."
-#define MSGBP_LMEM_NULL      "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
+#define MSGBP_LMEM_NULL      "Linear solver memory is NULL. The SPILS interface must be attached."
 #define MSGBP_MEM_FAIL       "A memory request failed."
 #define MSGBP_BAD_NVECTOR    "A required vector operation is not implemented."
+#define MSGBP_SUNMAT_FAIL    "An error arose from a SUNBandMatrix routine."
+#define MSGBP_SUNLS_FAIL     "An error arose from a SUNBandLinearSolver routine."
 #define MSGBP_PMEM_NULL      "Band preconditioner memory is NULL. ARKBandPrecInit must be called."
 #define MSGBP_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner."
 
diff --git a/src/arkode/arkode_bbdpre.c b/src/arkode/arkode_bbdpre.c
index 8bdb603..23408b1 100644
--- a/src/arkode/arkode_bbdpre.c
+++ b/src/arkode/arkode_bbdpre.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -17,8 +17,9 @@
  *---------------------------------------------------------------
  * This file contains implementations of routines for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with ARKODE, a ARKSPILS 
- * linear solver, and the parallel implementation of NVECTOR.
+ * matrix with banded blocks, for use with ARKODE, the ARKSPILS 
+ * linear solver interface, and the MPI-parallel implementation 
+ * of NVECTOR.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -28,6 +29,7 @@
 #include "arkode_bbdpre_impl.h"
 #include "arkode_spils_impl.h"
 #include <sundials/sundials_math.h>
+#include <nvector/nvector_serial.h>
 
 
 #define MIN_INC_MULT RCONST(1000.0)
@@ -38,12 +40,11 @@
 /* Prototypes of functions ARKBBDPrecSetup and ARKBBDPrecSolve */
 static int ARKBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, 
 			   booleantype jok, booleantype *jcurPtr, 
-			   realtype gamma, void *bbd_data, 
-			   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+			   realtype gamma, void *bbd_data);
 static int ARKBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, 
 			   N_Vector r, N_Vector z, 
 			   realtype gamma, realtype delta,
-			   int lr, void *bbd_data, N_Vector tmp);
+			   int lr, void *bbd_data);
 
 /* Prototype for ARKBBDPrecFree */
 static int ARKBBDPrecFree(ARKodeMem ark_mem);
@@ -57,38 +58,38 @@ static int ARKBBDDQJac(ARKBBDPrecData pdata, realtype t,
 /*---------------------------------------------------------------
  User-Callable Functions: initialization, reinit and free
 ---------------------------------------------------------------*/
-int ARKBBDPrecInit(void *arkode_mem, long int Nlocal, 
-                   long int mudq, long int mldq,
-                   long int mukeep, long int mlkeep, 
+int ARKBBDPrecInit(void *arkode_mem, sunindextype Nlocal, 
+                   sunindextype mudq, sunindextype mldq,
+                   sunindextype mukeep, sunindextype mlkeep, 
                    realtype dqrely, 
                    ARKLocalFn gloc, ARKCommFn cfn)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
   ARKBBDPrecData pdata;
-  long int muk, mlk, storage_mu;
+  sunindextype muk, mlk, storage_mu, lrw1, liw1;
+  long int lrw, liw;
   int flag;
 
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecInit", MSGBBD_MEM_NULL);
+                    "ARKBBDPrecInit", MSGBBD_MEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecInit", MSGBBD_LMEM_NULL);
+                    "ARKBBDPrecInit", MSGBBD_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  /* Test if the NVECTOR package is compatible with the BLOCK 
-     BAND preconditioner */
+  /* Test compatibility of NVECTOR package with the BBD preconditioner */
   if(ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
     arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKBBDPRE", 
-		    "ARKBBDPrecInit", MSGBBD_BAD_NVECTOR);
+                    "ARKBBDPrecInit", MSGBBD_BAD_NVECTOR);
     return(ARKSPILS_ILL_INPUT);
   }
 
@@ -97,7 +98,7 @@ int ARKBBDPrecInit(void *arkode_mem, long int Nlocal,
   pdata = (ARKBBDPrecData) malloc(sizeof *pdata);  
   if (pdata == NULL) {
     arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
-		    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL);
   }
 
@@ -113,61 +114,172 @@ int ARKBBDPrecInit(void *arkode_mem, long int Nlocal,
   pdata->mlkeep = mlk;
 
   /* Allocate memory for saved Jacobian */
-  pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk);
+  pdata->savedJ = SUNBandMatrix(Nlocal, muk, mlk, muk);
   if (pdata->savedJ == NULL) { 
     free(pdata); pdata = NULL; 
     arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
-		    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL); 
   }
 
   /* Allocate memory for preconditioner matrix */
   storage_mu = SUNMIN(Nlocal-1, muk + mlk);
   pdata->savedP = NULL;
-  pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+  pdata->savedP = SUNBandMatrix(Nlocal, muk, mlk, storage_mu);
   if (pdata->savedP == NULL) {
-    DestroyMat(pdata->savedJ);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
     arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
-		    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL);
   }
-  /* Allocate memory for lpivots */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(Nlocal);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->savedP);
-    DestroyMat(pdata->savedJ);
+
+  /* Allocate memory for temporary N_Vectors */
+  pdata->zlocal = NULL;
+  pdata->zlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->zlocal == NULL) {
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+  pdata->rlocal = NULL;
+  pdata->rlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->rlocal == NULL) {
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+  pdata->tmp1 = NULL;
+  pdata->tmp1 = N_VClone(ark_mem->ark_tempv);
+  if (pdata->tmp1 == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+  pdata->tmp2 = NULL;
+  pdata->tmp2 = N_VClone(ark_mem->ark_tempv);
+  if (pdata->tmp2 == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+  pdata->tmp3 = NULL;
+  pdata->tmp3 = N_VClone(ark_mem->ark_tempv);
+  if (pdata->tmp3 == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
     arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
-		    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
     return(ARKSPILS_MEM_FAIL);
   }
 
-  /* Set pdata->dqrely based on input dqrely (0 implies default). */
-  pdata->dqrely = (dqrely > ZERO) ? dqrely : SUNRsqrt(ark_mem->ark_uround);
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(pdata->rlocal, pdata->savedP);
+  if (pdata->LS == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->tmp3);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKBBDPRE", 
+                    "ARKBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (pdata->LS == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->tmp3);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    SUNLinSolFree(pdata->LS);
+    free(pdata); pdata = NULL;
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKBBDPRE", 
+                    "ARKBBDPrecInit", MSGBBD_SUNLS_FAIL);
+    return(ARKSPILS_SUNLS_FAIL);
+  }
+  
+  /* Set dqrely based on input dqrely (0 implies default). */
+  pdata->dqrely = (dqrely > ZERO) ? 
+    dqrely : SUNRsqrt(ark_mem->ark_uround);
 
   /* Store Nlocal to be used in ARKBBDPrecSetup */
   pdata->n_local = Nlocal;
 
   /* Set work space sizes and initialize nge */
-  pdata->rpwsize = Nlocal*(muk + 2*mlk + storage_mu + 2);
-  pdata->ipwsize = Nlocal;
+  pdata->rpwsize = 0;
+  pdata->ipwsize = 0;
+  if (ark_mem->ark_tempv->ops->nvspace) {
+    N_VSpace(ark_mem->ark_tempv, &lrw1, &liw1);
+    pdata->rpwsize += 3*lrw1;
+    pdata->ipwsize += 3*liw1;
+  }
+  if (pdata->rlocal->ops->nvspace) {
+    N_VSpace(pdata->rlocal, &lrw1, &liw1);
+    pdata->rpwsize += 2*lrw1;
+    pdata->ipwsize += 2*liw1;
+  }
+  if (pdata->savedJ->ops->space) {
+    flag = SUNMatSpace(pdata->savedJ, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->savedP->ops->space) {
+    flag = SUNMatSpace(pdata->savedP, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
   pdata->nge = 0;
 
-  /* make sure s_P_data is free from any previous allocations */
-  if (arkspils_mem->s_pfree != NULL) {
-    arkspils_mem->s_pfree(ark_mem);
-  }
+  /* make sure P_data is free from any previous allocations */
+  if (arkspils_mem->pfree) 
+    arkspils_mem->pfree(ark_mem);
 
   /* Point to the new P_data field in the SPILS memory */
-  arkspils_mem->s_P_data = pdata;
+  arkspils_mem->P_data = pdata;
 
   /* Attach the pfree function */
-  arkspils_mem->s_pfree = ARKBBDPrecFree;
+  arkspils_mem->pfree = ARKBBDPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = ARKSpilsSetPreconditioner(arkode_mem, ARKBBDPrecSetup, 
+  flag = ARKSpilsSetPreconditioner(arkode_mem, 
+                                   ARKBBDPrecSetup, 
 				   ARKBBDPrecSolve);
 
   return(flag);
@@ -175,44 +287,45 @@ int ARKBBDPrecInit(void *arkode_mem, long int Nlocal,
 
 
 /*-------------------------------------------------------------*/
-int ARKBBDPrecReInit(void *arkode_mem, long int mudq, 
-		     long int mldq, realtype dqrely)
+int ARKBBDPrecReInit(void *arkode_mem, sunindextype mudq, 
+		     sunindextype mldq, realtype dqrely)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
   ARKBBDPrecData pdata;
-  long int Nlocal;
+  sunindextype Nlocal;
 
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecReInit", MSGBBD_MEM_NULL);
+                    "ARKBBDPrecReInit", MSGBBD_MEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecReInit", MSGBBD_LMEM_NULL);
+                    "ARKBBDPrecReInit", MSGBBD_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
   /* Test if the preconditioner data is non-NULL */
-  if (arkspils_mem->s_P_data == NULL) {
+  if (arkspils_mem->P_data == NULL) {
     arkProcessError(ark_mem, ARKSPILS_PMEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecReInit", MSGBBD_PMEM_NULL);
+                    "ARKBBDPrecReInit", MSGBBD_PMEM_NULL);
     return(ARKSPILS_PMEM_NULL);
   } 
-  pdata = (ARKBBDPrecData) arkspils_mem->s_P_data;
+  pdata = (ARKBBDPrecData) arkspils_mem->P_data;
 
   /* Load half-bandwidths */
   Nlocal = pdata->n_local;
   pdata->mudq = SUNMIN(Nlocal-1, SUNMAX(0,mudq));
   pdata->mldq = SUNMIN(Nlocal-1, SUNMAX(0,mldq));
 
-  /* Set pdata->dqrely based on input dqrely (0 implies default). */
-  pdata->dqrely = (dqrely > ZERO) ? dqrely : SUNRsqrt(ark_mem->ark_uround);
+  /* Set dqrely based on input dqrely (0 implies default). */
+  pdata->dqrely = (dqrely > ZERO) ? 
+    dqrely : SUNRsqrt(ark_mem->ark_uround);
 
   /* Re-initialize nge */
   pdata->nge = 0;
@@ -222,7 +335,8 @@ int ARKBBDPrecReInit(void *arkode_mem, long int mudq,
 
 
 /*-------------------------------------------------------------*/
-int ARKBBDPrecGetWorkSpace(void *arkode_mem, long int *lenrwBBDP, 
+int ARKBBDPrecGetWorkSpace(void *arkode_mem, 
+                           long int *lenrwBBDP, 
 			   long int *leniwBBDP)
 {
   ARKodeMem ark_mem;
@@ -231,24 +345,24 @@ int ARKBBDPrecGetWorkSpace(void *arkode_mem, long int *lenrwBBDP,
 
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
+                    "ARKBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
+                    "ARKBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if (arkspils_mem->s_P_data == NULL) {
+  if (arkspils_mem->P_data == NULL) {
     arkProcessError(ark_mem, ARKSPILS_PMEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
+                    "ARKBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
     return(ARKSPILS_PMEM_NULL);
   } 
-  pdata = (ARKBBDPrecData) arkspils_mem->s_P_data;
+  pdata = (ARKBBDPrecData) arkspils_mem->P_data;
 
   *lenrwBBDP = pdata->rpwsize;
   *leniwBBDP = pdata->ipwsize;
@@ -258,7 +372,8 @@ int ARKBBDPrecGetWorkSpace(void *arkode_mem, long int *lenrwBBDP,
 
 
 /*-------------------------------------------------------------*/
-int ARKBBDPrecGetNumGfnEvals(void *arkode_mem, long int *ngevalsBBDP)
+int ARKBBDPrecGetNumGfnEvals(void *arkode_mem, 
+                             long int *ngevalsBBDP)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
@@ -266,24 +381,24 @@ int ARKBBDPrecGetNumGfnEvals(void *arkode_mem, long int *ngevalsBBDP)
 
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
+                    "ARKBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
+                    "ARKBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if (arkspils_mem->s_P_data == NULL) {
+  if (arkspils_mem->P_data == NULL) {
     arkProcessError(ark_mem, ARKSPILS_PMEM_NULL, "ARKBBDPRE", 
-		    "ARKBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
+                    "ARKBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
     return(ARKSPILS_PMEM_NULL);
   } 
-  pdata = (ARKBBDPrecData) arkspils_mem->s_P_data;
+  pdata = (ARKBBDPrecData) arkspils_mem->P_data;
 
   *ngevalsBBDP = pdata->nge;
 
@@ -299,8 +414,8 @@ int ARKBBDPrecGetNumGfnEvals(void *arkode_mem, long int *ngevalsBBDP)
  user-supplied gloc and cfn functions. It uses difference
  quotient approximations to the Jacobian elements.
 
- ARKBBDPrecSetup calculates a new J,if necessary, then calculates
- P = I - gamma*J, and does an LU factorization of P.
+ ARKBBDPrecSetup calculates a new J, if necessary, then 
+ calculates P = M - gamma*J, and does an LU factorization of P.
 
  The parameters of ARKBBDPrecSetup used here are as follows:
 
@@ -313,18 +428,18 @@ int ARKBBDPrecGetNumGfnEvals(void *arkode_mem, long int *ngevalsBBDP)
 
  jok     is an input flag indicating whether Jacobian-related
          data needs to be recomputed, as follows:
-           jok == FALSE means recompute Jacobian-related data
+           jok == SUNFALSE means recompute Jacobian-related data
                   from scratch.
-           jok == TRUE  means that Jacobian data from the
+           jok == SUNTRUE  means that Jacobian data from the
                   previous ARKBBDPrecon call can be reused
                   (with the current value of gamma).
-         A ARKBBDPrecon call with jok == TRUE should only occur
-         after a call with jok == FALSE.
+         A ARKBBDPrecon call with jok == SUNTRUE should only occur
+         after a call with jok == SUNFALSE.
 
  jcurPtr is a pointer to an output integer flag which is
          set by ARKBBDPrecon as follows:
-           *jcurPtr = TRUE if Jacobian data was recomputed.
-           *jcurPtr = FALSE if Jacobian data was not recomputed,
+           *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+           *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
                       but saved data was reused.
 
  gamma   is the scalar appearing in the Newton matrix.
@@ -332,10 +447,6 @@ int ARKBBDPrecGetNumGfnEvals(void *arkode_mem, long int *ngevalsBBDP)
  bbd_data is a pointer to the preconditioner data set by
           ARKBBDPrecInit
 
- tmp1, tmp2, and tmp3 are pointers to memory allocated
-           for NVectors which are be used by ARKBBDPrecSetup
-           as temporary storage or work space.
-
  Return value:
  The value returned by this ARKBBDPrecSetup function is the int
    0  if successful,
@@ -343,10 +454,9 @@ int ARKBBDPrecGetNumGfnEvals(void *arkode_mem, long int *ngevalsBBDP)
 ---------------------------------------------------------------*/
 static int ARKBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, 
 			   booleantype jok, booleantype *jcurPtr, 
-			   realtype gamma, void *bbd_data, 
-			   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+			   realtype gamma, void *bbd_data)
 {
-  long int ier;
+  sunindextype ier;
   ARKBBDPrecData pdata;
   ARKodeMem ark_mem;
   int retval;
@@ -355,39 +465,67 @@ static int ARKBBDPrecSetup(realtype t, N_Vector y, N_Vector fy,
 
   ark_mem = (ARKodeMem) pdata->arkode_mem;
 
-  /* If jok = TRUE, use saved copy of J */
+  /* If jok = SUNTRUE, use saved copy of J */
   if (jok) {
-    *jcurPtr = FALSE;
-    BandCopy(pdata->savedJ, pdata->savedP, pdata->mukeep, pdata->mlkeep);
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      arkProcessError(ark_mem, -1, "ARKBBDPRE", 
+                      "ARKBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   /* Otherwise call ARKBBDDQJac for new J value */
   } else {
-    *jcurPtr = TRUE;
-    SetToZero(pdata->savedJ);
+    
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(pdata->savedJ);
+    if (retval < 0) {
+      arkProcessError(ark_mem, -1, "ARKBBDPRE", 
+                      "ARKBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    retval = ARKBBDDQJac(pdata, t, y, tmp1, tmp2, tmp3);
+    retval = ARKBBDDQJac(pdata, t, y, pdata->tmp1, 
+                         pdata->tmp2, pdata->tmp3);
     if (retval < 0) {
       arkProcessError(ark_mem, -1, "ARKBBDPRE", "ARKBBDPrecSetup", 
-		      MSGBBD_FUNC_FAILED);
+                      MSGBBD_FUNC_FAILED);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
+
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      arkProcessError(ark_mem, -1, "ARKBBDPRE", 
+                      "ARKBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
       return(-1);
     }
     if (retval > 0) {
       return(1);
     }
-    BandCopy(pdata->savedJ, pdata->savedP, pdata->mukeep, pdata->mlkeep);
 
   }
   
   /* Scale and add I to get P = I - gamma*J */
-  BandScale(-gamma, pdata->savedP);
-  AddIdentity(pdata->savedP);
- 
-  /* Do LU factorization of P in place */
-  ier = BandGBTRF(pdata->savedP, pdata->lpivots);
+  retval = SUNMatScaleAddI(-gamma, pdata->savedP);
+  if (retval) {
+    arkProcessError(ark_mem, -1, "ARKBBDPRE", 
+                    "ARKBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+    return(-1);
+  }
  
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  if (ier > 0) return(1);
-  return(0);
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->savedP);
+  return(ier);
 }
 
 
@@ -407,25 +545,32 @@ static int ARKBBDPrecSetup(realtype t, N_Vector y, N_Vector fy,
 
  z is the output vector computed by ARKBBDPrecSolve.
 
- The value returned by the ARKBBDPrecSolve function is always 0,
- indicating success.
+ The value returned by the ARKBBDPrecSolve function is the same 
+ as the value returned from the linear solver object.
 ---------------------------------------------------------------*/
 static int ARKBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, 
 			   N_Vector r, N_Vector z, 
 			   realtype gamma, realtype delta,
-			   int lr, void *bbd_data, N_Vector tmp)
+			   int lr, void *bbd_data)
 {
+  int retval;
   ARKBBDPrecData pdata;
-  realtype *zd;
 
   pdata = (ARKBBDPrecData) bbd_data;
 
-  /* Copy r to z, then do backsolve and return */
-  N_VScale(ONE, r, z);
-  zd = N_VGetArrayPointer(z);
-  BandGBTRS(pdata->savedP, pdata->lpivots, zd);
+  /* Attach local data arrays for r and z to rlocal and zlocal */
+  N_VSetArrayPointer(N_VGetArrayPointer(r), pdata->rlocal);
+  N_VSetArrayPointer(N_VGetArrayPointer(z), pdata->zlocal);
+  
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->savedP, pdata->zlocal, 
+                          pdata->rlocal, ZERO);
 
-  return(0);
+  /* Detach local data arrays from rlocal and zlocal */
+  N_VSetArrayPointer(NULL, pdata->rlocal);
+  N_VSetArrayPointer(NULL, pdata->zlocal);
+
+  return(retval);
 }
 
 
@@ -438,12 +583,17 @@ static int ARKBBDPrecFree(ARKodeMem ark_mem)
   if (ark_mem->ark_lmem == NULL) return(0);
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
   
-  if (arkspils_mem->s_P_data == NULL) return(0);
-  pdata = (ARKBBDPrecData) arkspils_mem->s_P_data;
-
-  DestroyMat(pdata->savedJ);
-  DestroyMat(pdata->savedP);
-  DestroyArray(pdata->lpivots);
+  if (arkspils_mem->P_data == NULL) return(0);
+  pdata = (ARKBBDPrecData) arkspils_mem->P_data;
+
+  SUNLinSolFree(pdata->LS);
+  N_VDestroy(pdata->tmp1);
+  N_VDestroy(pdata->tmp2);
+  N_VDestroy(pdata->tmp3);
+  N_VDestroy(pdata->zlocal);
+  N_VDestroy(pdata->rlocal);
+  SUNMatDestroy(pdata->savedP);
+  SUNMatDestroy(pdata->savedJ);
 
   free(pdata);
   pdata = NULL;
@@ -457,11 +607,11 @@ static int ARKBBDPrecFree(ARKodeMem ark_mem)
 
  This routine generates a banded difference quotient approximation
  to the local block of the Jacobian of g(t,y). It assumes that a
- band matrix of type DlsMat is stored columnwise, and that elements
- within each column are contiguous. All matrix elements are generated
- as difference quotients, by way of calls to the user routine gloc.
- By virtue of the band structure, the number of these calls is
- bandwidth + 1, where bandwidth = mldq + mudq + 1.
+ band matrix of type SUNMatrix is stored columnwise, and that 
+ elements within each column are contiguous. All matrix elements 
+ are generated as difference quotients, by way of calls to the 
+ user routine gloc.  By virtue of the band structure, the number 
+ of these calls is bandwidth + 1, where bandwidth = mldq + mudq + 1.
  But the band matrix kept has bandwidth = mlkeep + mukeep + 1.
  This routine also assumes that the local elements of a vector are
  stored contiguously.
@@ -472,7 +622,7 @@ static int ARKBBDDQJac(ARKBBDPrecData pdata, realtype t,
 {
   ARKodeMem ark_mem;
   realtype gnorm, minInc, inc, inc_inv;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *y_data, *ewt_data, *gy_data, *gtemp_data, *ytemp_data, *col_j;
   int retval;
 
@@ -487,7 +637,8 @@ static int ARKBBDDQJac(ARKBBDPrecData pdata, realtype t,
     if (retval != 0) return(retval);
   }
 
-  retval = pdata->gloc(pdata->n_local, t, ytemp, gy, ark_mem->ark_user_data);
+  retval = pdata->gloc(pdata->n_local, t, ytemp, gy, 
+                       ark_mem->ark_user_data);
   pdata->nge++;
   if (retval != 0) return(retval);
 
@@ -499,10 +650,10 @@ static int ARKBBDDQJac(ARKBBDPrecData pdata, realtype t,
   gtemp_data =  N_VGetArrayPointer(gtemp);
 
   /* Set minimum increment based on uround and norm of g */
-  /* gnorm = N_VWrmsNorm(gy, ark_mem->ark_ewt); */
   gnorm = N_VWrmsNorm(gy, ark_mem->ark_rwt);
-  minInc = (gnorm != ZERO) ? (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) *
-			      ark_mem->ark_uround * pdata->n_local * gnorm) : ONE;
+  minInc = (gnorm != ZERO) ? 
+    (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) *
+     ark_mem->ark_uround * pdata->n_local * gnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing */
   width = pdata->mldq + pdata->mudq + 1;
@@ -526,13 +677,13 @@ static int ARKBBDDQJac(ARKBBDPrecData pdata, realtype t,
     /* Restore ytemp, then form and load difference quotients */
     for (j=group-1; j < pdata->n_local; j+=width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(pdata->savedJ,j);
+      col_j = SUNBandMatrix_Column(pdata->savedJ,j);
       inc = SUNMAX(pdata->dqrely*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-pdata->mukeep);
       i2 = SUNMIN(j+pdata->mlkeep, pdata->n_local-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) =
+        SM_COLUMN_ELEMENT_B(col_j,i,j) =
           inc_inv * (gtemp_data[i] - gy_data[i]);
     }
   }
diff --git a/src/arkode/arkode_bbdpre_impl.h b/src/arkode/arkode_bbdpre_impl.h
index d546867..3d6633c 100644
--- a/src/arkode/arkode_bbdpre_impl.h
+++ b/src/arkode/arkode_bbdpre_impl.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -22,7 +22,8 @@
 #define _ARKBBDPRE_IMPL_H
 
 #include <arkode/arkode_bbdpre.h>
-#include <sundials/sundials_band.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -35,18 +36,23 @@ extern "C" {
 typedef struct ARKBBDPrecDataRec {
 
   /* passed by user to ARKBBDPrecAlloc and used by PrecSetup/PrecSolve */
-  long int mudq, mldq, mukeep, mlkeep;
+  sunindextype mudq, mldq, mukeep, mlkeep;
   realtype dqrely;
   ARKLocalFn gloc;
   ARKCommFn cfn;
 
   /* set by ARKBBDPrecSetup and used by ARKBBDPrecSolve */
-  DlsMat savedJ;
-  DlsMat savedP;
-  long int *lpivots;
+  SUNMatrix savedJ;
+  SUNMatrix savedP;
+  SUNLinearSolver LS;
+  N_Vector tmp1;
+  N_Vector tmp2;
+  N_Vector tmp3;
+  N_Vector zlocal;
+  N_Vector rlocal;
 
   /* set by ARKBBDPrecAlloc and used by ARKBBDPrecSetup */
-  long int n_local;
+  sunindextype n_local;
 
   /* available for optional output */
   long int rpwsize;
@@ -67,6 +73,8 @@ typedef struct ARKBBDPrecDataRec {
 #define MSGBBD_LMEM_NULL   "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBBD_MEM_FAIL    "A memory request failed."
 #define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGBBD_SUNMAT_FAIL "An error arose from a SUNBandMatrix routine."
+#define MSGBBD_SUNLS_FAIL  "An error arose from a SUNBandLinearSolver routine."
 #define MSGBBD_PMEM_NULL   "BBD peconditioner memory is NULL. ARKBBDPrecInit must be called."
 #define MSGBBD_FUNC_FAILED "The gloc or cfn routine failed in an unrecoverable manner."
 
diff --git a/src/arkode/arkode_butcher.c b/src/arkode/arkode_butcher.c
index 065dabf..366d459 100644
--- a/src/arkode/arkode_butcher.c
+++ b/src/arkode/arkode_butcher.c
@@ -41,35 +41,43 @@
      b2[s] -- realtype embedding coefficients
 
  Allowed 'method' names and properties (those in an ARK pair are marked 
- with a *).  All method names are of the form <name>_s_p_q:
-
-   imeth                       type  A-stable  L-stable
-  ------------------------------------------------------
-   HEUN_EULER_2_1_2             ERK     N         N 
-   BOGACKI_SHAMPINE_4_2_3       ERK     N         N 
-   ARK324L2SA_ERK_4_2_3*        ERK     N         N 
-   ZONNEVELD_5_3_4              ERK     N         N 
-   ARK436L2SA_ERK_6_3_4*        ERK     N         N 
-   SAYFY_ABURUB_6_3_4           ERK     N         N 
-   CASH_KARP_6_4_5              ERK     N         N 
-   FEHLBERG_6_4_5               ERK     N         N 
-   DORMAND_PRINCE_7_4_5         ERK     N         N 
-   ARK548L2SA_ERK_8_4_5*        ERK     N         N 
-   VERNER_8_5_6                 ERK     N         N 
-   FEHLBERG_13_7_8              ERK     N         N 
-   SDIRK_2_1_2                SDIRK     Y         N 
-   BILLINGTON_3_3_2           SDIRK     N         N
-   TRBDF2_3_3_2              ESDIRK     N         N
-   KVAERNO_4_2_3             ESDIRK     Y         Y
-   ARK324L2SA_DIRK_4_2_3*    ESDIRK     Y         Y 
-   CASH_5_2_4                 SDIRK     Y         Y 
-   CASH_5_3_4                 SDIRK     Y         Y  
-   SDIRK_5_3_4                SDIRK     Y         Y  
-   KVAERNO_5_3_4             ESDIRK     Y         N 
-   ARK436L2SA_DIRK_6_3_4*    ESDIRK     Y         Y  
-   KVAERNO_7_4_5             ESDIRK     Y         Y  
-   ARK548L2SA_DIRK_8_4_5*    ESDIRK     Y         Y  
-  ------------------------------------------------------
+ with a *).  All method names are of the form <name>_s_p_q.  The method 
+ 'type' is one of 
+    ERK -- explicit Runge Kutta
+    SDIRK -- singly-diagonally implicit Runge Kutta
+    SDIRK -- explicit [1st stage] singly-diagonally implicit Runge Kutta
+ The 'A-stable' and 'L-stable' columns are based on numerical estimates 
+ of each property.  The 'QP' column denotes whether the coefficients 
+ of the method are known precisely enough for use in 'long double' 
+ (128-bit) calculations.
+
+   imeth                       type  A-stable  L-stable  QP 
+  ----------------------------------------------------------
+   HEUN_EULER_2_1_2             ERK     N         N       Y
+   BOGACKI_SHAMPINE_4_2_3       ERK     N         N       Y
+   ARK324L2SA_ERK_4_2_3*        ERK     N         N       N
+   ZONNEVELD_5_3_4              ERK     N         N       Y
+   ARK436L2SA_ERK_6_3_4*        ERK     N         N       N
+   SAYFY_ABURUB_6_3_4           ERK     N         N       N
+   CASH_KARP_6_4_5              ERK     N         N       Y
+   FEHLBERG_6_4_5               ERK     N         N       Y
+   DORMAND_PRINCE_7_4_5         ERK     N         N       Y
+   ARK548L2SA_ERK_8_4_5*        ERK     N         N       N
+   VERNER_8_5_6                 ERK     N         N       Y
+   FEHLBERG_13_7_8              ERK     N         N       Y
+   SDIRK_2_1_2                SDIRK     Y         N       Y
+   BILLINGTON_3_3_2           SDIRK     N         N       N
+   TRBDF2_3_3_2              ESDIRK     N         N       Y
+   KVAERNO_4_2_3             ESDIRK     Y         Y       N
+   ARK324L2SA_DIRK_4_2_3*    ESDIRK     Y         Y       N
+   CASH_5_2_4                 SDIRK     Y         Y       N
+   CASH_5_3_4                 SDIRK     Y         Y       N
+   SDIRK_5_3_4                SDIRK     Y         Y       Y
+   KVAERNO_5_3_4             ESDIRK     Y         N       N
+   ARK436L2SA_DIRK_6_3_4*    ESDIRK     Y         Y       N
+   KVAERNO_7_4_5             ESDIRK     Y         Y       N
+   ARK548L2SA_DIRK_8_4_5*    ESDIRK     Y         Y       N
+  ----------------------------------------------------------
 
 ---------------------------------------------------------------*/
 int ARKodeLoadButcherTable(int imethod, int *s, int *q, int *p, 
@@ -748,8 +756,8 @@ int ARKodeLoadButcherTable(int imethod, int *s, int *q, int *p,
     b[3] = RCONST(-0.266418670647);
     b[4] = RCONST(0.435866521508);
 
-    b2[0] = RCONST((-0.7-0.5))/RCONST((-0.7-0.435866521508));
-    b2[1] = RCONST((0.5-0.435866521508))/RCONST((-0.7-0.435866521508));
+    b2[0] = (RCONST(-0.7)-RCONST(0.5))/(RCONST(-0.7)-RCONST(0.435866521508));
+    b2[1] = (RCONST(0.5)-RCONST(0.435866521508))/(RCONST(-0.7)-RCONST(0.435866521508));
 
     c[0] = RCONST(0.435866521508);
     c[1] = RCONST(-0.7);
diff --git a/src/arkode/arkode_dense.c b/src/arkode/arkode_dense.c
deleted file mode 100644
index b472218..0000000
--- a/src/arkode/arkode_dense.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the impleentation file for the ARKDENSE linear solver.
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_dense.h>
-#include "arkode_direct_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* ARKDENSE linit, lsetup, lsolve, and lfree routines */
-static int arkDenseInit(ARKodeMem ark_mem);
-static int arkDenseSetup(ARKodeMem ark_mem, int convfail, N_Vector ypred,
-			 N_Vector fpred, booleantype *jcurPtr, 
-			 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-static int arkDenseSolve(ARKodeMem ark_mem, N_Vector b, N_Vector weight,
-			 N_Vector ycur, N_Vector fcur);
-static int arkDenseFree(ARKodeMem ark_mem);
-
-/* ARKDENSE minit, msetup, msolve, mfree and mtimes routines */
-static int arkMassDenseInit(ARKodeMem ark_mem);
-static int arkMassDenseSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			     N_Vector vtemp2, N_Vector vtemp3);
-static int arkMassDenseSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight);
-static int arkMassDenseFree(ARKodeMem ark_mem);
-static int arkMassDenseMultiply(N_Vector v, N_Vector Mv, 
-				realtype t, void *arkode_mem);
-                
-                
-/*---------------------------------------------------------------
- ARKDense:
-
- This routine initializes the memory record and sets various 
- function fields specific to the dense linear solver module.  
- ARKDense first calls the existing lfree routine if this is not 
- NULL.  Then it sets the ark_linit, ark_lsetup, ark_lsolve and
- ark_lfree fields in (*arkode_mem) to be arkDenseInit, 
- arkDenseSetup, arkDenseSolve, and arkDenseFree, respectively.  
- It allocates memory for a structure of type ARKDlsMemRec and 
- sets the ark_lmem field in (*arkode_mem) to the address of this 
- structure.  It sets setupNonNull in (*arkode_mem) to TRUE, and 
- the d_jac field to the default arkDlsDenseDQJac.  Finally, it
- allocates memory for M, savedJ, and lpivots. The return value 
- is SUCCESS = 0, or LMEM_FAIL = -1.
-
- NOTE: The dense linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKDense will first 
-       test for compatible a compatible N_Vector internal
-       representation by checking that N_VGetArrayPointer and
-       N_VSetArrayPointer exist.
----------------------------------------------------------------*/
-int ARKDense(void *arkode_mem, long int N)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDENSE", 
-                    "ARKDense", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL ||
-      ark_mem->ark_tempv->ops->nvsetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDENSE", 
-                    "ARKDense", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree !=NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */
-  ark_mem->ark_linit  = arkDenseInit;
-  ark_mem->ark_lsetup = arkDenseSetup;
-  ark_mem->ark_lsolve = arkDenseSolve;
-  ark_mem->ark_lfree  = arkDenseFree;
-  ark_mem->ark_lsolve_type = 1;
-
-  /* Get memory for ARKDlsMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMem) malloc(sizeof(struct ARKDlsMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-                    "ARKDense", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_DENSE;
-
-  /* Initialize Jacobian-related data */
-  arkdls_mem->d_jacDQ  = TRUE;
-  arkdls_mem->d_djac   = NULL;
-  arkdls_mem->d_J_data = NULL;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_setupNonNull = TRUE;
-
-  /* Initialize counters */
-  arkDlsInitializeCounters(arkdls_mem);
-
-  /* Set problem dimension */
-  arkdls_mem->d_n = N;
-
-  /* Allocate memory for M, savedJ, and pivot array */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_M = NewDenseMat(N, N);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-                    "ARKDense", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_savedJ = NULL;
-  arkdls_mem->d_savedJ = NewDenseMat(N, N);
-  if (arkdls_mem->d_savedJ == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-                    "ARKDense", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_lpivots = NULL;
-  arkdls_mem->d_lpivots = NewLintArray(N);
-  if (arkdls_mem->d_lpivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-                    "ARKDense", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    DestroyMat(arkdls_mem->d_savedJ);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkDenseInit:
-
- This routine does remaining initializations specific to the 
- dense linear solver.
----------------------------------------------------------------*/
-static int arkDenseInit(ARKodeMem ark_mem)
-{
-  ARKDlsMem arkdls_mem;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  
-  arkDlsInitializeCounters(arkdls_mem);
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (arkdls_mem->d_jacDQ) {
-    arkdls_mem->d_djac   = arkDlsDenseDQJac;
-    arkdls_mem->d_J_data = ark_mem;
-  } else {
-    arkdls_mem->d_J_data = ark_mem->ark_user_data;
-  }
-
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkDenseSetup:
-
- This routine does the setup operations for the dense linear solver.
- It makes a decision whether or not to call the Jacobian evaluation
- routine based on various state variables, and if not it uses the 
- saved copy.  In any case, it constructs the Newton matrix 
- A = M - gamma*J, updates counters, and calls the dense LU 
- factorization routine.
----------------------------------------------------------------*/
-static int arkDenseSetup(ARKodeMem ark_mem, int convfail, 
-			 N_Vector ypred, N_Vector fpred, 
-			 booleantype *jcurPtr, N_Vector vtemp1, 
-			 N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma, *Acol_j, *Mcol_j;
-  long int i, j, ier;
-  ARKDlsMem arkdls_mem;
-  ARKDlsMassMem arkdls_mass_mem;
-  int retval;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
- 
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkdls_mem->d_nstlj + ARKD_MSBJ) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKD_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  jok = !jbad;
- 
-  /* If jok = TRUE, use saved copy of J */
-  if (jok) {
-    *jcurPtr = FALSE;
-    DenseCopy(arkdls_mem->d_savedJ, arkdls_mem->d_M);
-
-  /* If jok = FALSE, call jac routine for new J value */
-  } else {
-    arkdls_mem->d_nje++;
-    arkdls_mem->d_nstlj = ark_mem->ark_nst;
-    *jcurPtr = TRUE;
-    SetToZero(arkdls_mem->d_M);
-
-    retval = arkdls_mem->d_djac(arkdls_mem->d_n, ark_mem->ark_tn, 
-				ypred, fpred, arkdls_mem->d_M, 
-				arkdls_mem->d_J_data, 
-				vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_JACFUNC_UNRECVR, "ARKDENSE", 
-		      "arkDenseSetup",  MSGD_JACFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    DenseCopy(arkdls_mem->d_M, arkdls_mem->d_savedJ);
-
-  }
-  
-  /* Scale J by -gamma */
-  DenseScale(-ark_mem->ark_gamma, arkdls_mem->d_M);
-  
-  /* Add mass matrix to get A = M-gamma*J*/
-  if (ark_mem->ark_mass_matrix) {
-
-    /* Compute mass matrix */
-    arkdls_mass_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-    SetToZero(arkdls_mass_mem->d_M);
-    retval = arkdls_mass_mem->d_dmass(arkdls_mass_mem->d_n, 
-				      ark_mem->ark_tn, 
-				      arkdls_mass_mem->d_M, 
-				      arkdls_mass_mem->d_M_data, 
-				      vtemp1, vtemp2, vtemp3);
-    arkdls_mass_mem->d_nme++;
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKDENSE", 
-		      "arkDenseSetup",  MSGD_MASSFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-      return(1);
-    }
-
-    /* Add to A */
-    for (j=0; j<arkdls_mem->d_M->N; j++) {
-      Acol_j = arkdls_mem->d_M->cols[j];
-      Mcol_j = arkdls_mass_mem->d_M->cols[j];
-      for (i=0; i<arkdls_mem->d_M->M; i++) 
-	Acol_j[i] += Mcol_j[i];
-    }
-  } else {
-    AddIdentity(arkdls_mem->d_M);
-  }
-
-  /* Do LU factorization of A */
-  ier = DenseGETRF(arkdls_mem->d_M, arkdls_mem->d_lpivots); 
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  arkdls_mem->d_last_flag = ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkDenseSolve:
-
- This routine handles the solve operation for the dense linear 
- solver by calling the dense backsolve routine.  The returned 
- value is 0.
----------------------------------------------------------------*/
-static int arkDenseSolve(ARKodeMem ark_mem, N_Vector b, 
-			 N_Vector weight, N_Vector ycur, 
-			 N_Vector fcur)
-{
-  ARKDlsMem arkdls_mem;
-  realtype *bd;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  
-  bd = N_VGetArrayPointer(b);
-
-  DenseGETRS(arkdls_mem->d_M, arkdls_mem->d_lpivots, bd);
-
-  /* scale the correction to account for change in gamma */
-  if (ark_mem->ark_gamrat != ONE) 
-    N_VScale(TWO/(ONE + ark_mem->ark_gamrat), b, b);
-  
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkDenseFree:
-
- This routine frees memory specific to the dense linear solver.
----------------------------------------------------------------*/
-static int arkDenseFree(ARKodeMem ark_mem)
-{
-  ARKDlsMem  arkdls_mem;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  
-  DestroyMat(arkdls_mem->d_M);
-  DestroyMat(arkdls_mem->d_savedJ);
-  DestroyArray(arkdls_mem->d_lpivots);
-  free(arkdls_mem);
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-
-/*---------------------------------------------------------------
- ARKMassDense:
-
- This routine initializes the memory record and sets various 
- function fields specific to the dense mass matrix linear solver
- module.  ARKMassDense first calls the existing mfree routine if 
- this is not NULL.  Then it sets the ark_minit, ark_msetup, 
- ark_msolve, ark_mfree fields in (*arkode_mem) to be 
- arkMassDenseInit, arkMassDenseSetup, arkMassDenseSolve, and 
- arkMassDenseFree, respectively.  It allocates memory for a 
- structure of type ARKDlsMassMemRec and sets the ark_mass_mem
- field in (*arkode_mem) to the address of this structure.  It 
- sets MassSetupNonNull in (*arkode_mem) to TRUE.  Finally, it 
- allocates memory for M and lpivots. The return value is 
- SUCCESS = 0, or LMEM_FAIL = -1.
-
- NOTE: The dense linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKMassDense will first 
-       test for compatible a compatible N_Vector internal
-       representation by checking that N_VGetArrayPointer and
-       N_VSetArrayPointer exist.
----------------------------------------------------------------*/
-int ARKMassDense(void *arkode_mem, long int N, ARKDlsDenseMassFn dmass)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDENSE", 
-		    "ARKMassDense", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL ||
-      ark_mem->ark_tempv->ops->nvsetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDENSE", 
-		    "ARKMassDense", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree !=NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = arkMassDenseInit;
-  ark_mem->ark_msetup = arkMassDenseSetup;
-  ark_mem->ark_msolve = arkMassDenseSolve;
-  ark_mem->ark_mfree  = arkMassDenseFree;
-  ark_mem->ark_mtimes = arkMassDenseMultiply;
-  ark_mem->ark_mtimes_data = (void *) ark_mem;
-  ark_mem->ark_msolve_type = 1;
-
-  /* Get memory for ARKDlsMassMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMassMem) malloc(sizeof(struct ARKDlsMassMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-		    "ARKMassDense", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_DENSE;
-
-  /* Initialize mass-matrix-related data */
-  arkdls_mem->d_nme = 0;
-  arkdls_mem->d_dmass = dmass;
-  arkdls_mem->d_M_data = NULL;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = TRUE;
-
-  /* Set problem dimension */
-  arkdls_mem->d_n = N;
-
-  /* Allocate memory for M, M_lu, and pivot array */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_M = NewDenseMat(N, N);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-		    "ARKMassDense", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_M_lu = NULL;
-  arkdls_mem->d_M_lu = NewDenseMat(N, N);
-  if (arkdls_mem->d_M_lu == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-		    "ARKMassDense", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_lpivots = NULL;
-  arkdls_mem->d_lpivots = NewLintArray(N);
-  if (arkdls_mem->d_lpivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDENSE", 
-		    "ARKMassDense", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    DestroyMat(arkdls_mem->d_M_lu);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkMassDenseInit:
-
- This routine does remaining initializations specific to the 
- dense linear solver.
----------------------------------------------------------------*/
-static int arkMassDenseInit(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem arkdls_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  arkdls_mem->d_nme = 0;
-
-  /* Set mass matrix function data */
-  arkdls_mem->d_M_data = ark_mem->ark_user_data;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassDenseSetup:
-
- This routine does the setup operations for the dense mass matrix 
- solver.  It calls the mass matrix evaluation, updates counters, 
- and calls the dense LU factorization routine.
----------------------------------------------------------------*/
-static int arkMassDenseSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			     N_Vector vtemp2, N_Vector vtemp3)
-{
-  long int ier;
-  ARKDlsMassMem arkdls_mem;
-  int retval;
-
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
- 
-  /* call Mass routine for new M matrix */
-  SetToZero(arkdls_mem->d_M);
-  retval = arkdls_mem->d_dmass(arkdls_mem->d_n, ark_mem->ark_tn, 
-			       arkdls_mem->d_M, 
-			       arkdls_mem->d_M_data, vtemp1, 
-			       vtemp2, vtemp3);
-  arkdls_mem->d_nme++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKDENSE", 
-		    "arkMassDenseSetup",  MSGD_MASSFUNC_FAILED);
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-    return(-1);
-  }
-  if (retval > 0) {
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-    return(1);
-  }
-
-  /* Copy M into M_lu for LU decomposition */
-  DenseCopy(arkdls_mem->d_M, arkdls_mem->d_M_lu);
-
-  /* Do LU factorization of M_lu */
-  ier = DenseGETRF(arkdls_mem->d_M_lu, arkdls_mem->d_lpivots); 
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  arkdls_mem->d_last_flag = ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassDenseSolve:
-
- This routine handles the solve operation for the dense mass 
- matrix solver by calling the dense backsolve routine.  The 
- returned value is 0.
----------------------------------------------------------------*/
-static int arkMassDenseSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight)
-{
-  ARKDlsMassMem arkdls_mem;
-  realtype *bd;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  bd = N_VGetArrayPointer(b);
-  DenseGETRS(arkdls_mem->d_M_lu, arkdls_mem->d_lpivots, bd);
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassDenseFree:
-
- This routine frees memory specific to the dense mass matrix
- solver.
----------------------------------------------------------------*/
-static int arkMassDenseFree(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem  arkdls_mem;
-
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  
-  DestroyMat(arkdls_mem->d_M);
-  DestroyMat(arkdls_mem->d_M_lu);
-  DestroyArray(arkdls_mem->d_lpivots);
-  free(arkdls_mem);
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassDenseMultiply performs a matrix-vector product, 
- multiplying the current mass matrix by a given vector.
----------------------------------------------------------------*/                  
-static int arkMassDenseMultiply(N_Vector v, N_Vector Mv, 
-				realtype t, void *arkode_mem)
-{
-  /* extract the DlsMassMem structure from the user_data pointer */
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-  realtype *vdata=NULL, *Mvdata=NULL;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDENSE", 
-		    "arkMassDenseMultiply", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-
-  /* access the vector arrays (since they must be serial vectors) */
-  vdata = N_VGetArrayPointer(v);
-  Mvdata = N_VGetArrayPointer(Mv);
-  if (vdata == NULL || Mvdata == NULL)
-    return(1);
-
-  /* perform matrix-vector product and return */
-  DenseMatvec(arkdls_mem->d_M, vdata, Mvdata);
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
-   EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_direct.c b/src/arkode/arkode_direct.c
index ad03b14..43b29f5 100644
--- a/src/arkode/arkode_direct.c
+++ b/src/arkode/arkode_direct.c
@@ -1,8 +1,8 @@
 /*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
+ * Programmer(s): Daniel R. Reynolds, Ashley L. Crawford @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,7 +15,8 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * This is the implementation file for the ARKDLS linear solvers
+ * This is the implementation file for the ARKDLS linear solver 
+ * interface
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -24,6 +25,9 @@
 #include "arkode_impl.h"
 #include "arkode_direct_impl.h"
 #include <sundials/sundials_math.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
 /*===============================================================
  FUNCTION SPECIFIC CONSTANTS
@@ -36,106 +40,239 @@
 
 
 /*===============================================================
- EXPORTED FUNCTIONS
+  ARKDLS Exported functions -- Required
 ===============================================================*/
-              
+
 /*---------------------------------------------------------------
- ARKDlsSetDenseJacFn specifies the dense Jacobian function.
+ ARKDlsSetLinearSolver specifies the direct linear solver.
 ---------------------------------------------------------------*/
-int ARKDlsSetDenseJacFn(void *arkode_mem, ARKDlsDenseJacFn jac)
+int ARKDlsSetLinearSolver(void *arkode_mem, SUNLinearSolver LS,
+                          SUNMatrix A)
 {
   ARKodeMem ark_mem;
   ARKDlsMem arkdls_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
-		    "ARKDlsSetDenseJacFn", MSGD_ARKMEM_NULL);
+                    "ARKDlsSetLinearSolver", MSGD_ARKMEM_NULL);
     return(ARKDLS_MEM_NULL);
   }
+  if ( (LS == NULL)  || (A == NULL) ) {
+    arkProcessError(NULL, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "ARKDlsSetLinearSolver",
+                    "Both LS and A must be non-NULL");
+    return(ARKDLS_ILL_INPUT);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
-		    "ARKDlsSetDenseJacFn", MSGD_LMEM_NULL);
-    return(ARKDLS_LMEM_NULL);
+  /* Test if solver and vector are compatible with DLS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
+    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "ARKDlsSetLinearSolver", 
+                    "Non-direct LS supplied to ARKDls interface");
+    return(ARKDLS_ILL_INPUT);
+  }
+  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL ||
+      ark_mem->ark_tempv->ops->nvsetarraypointer == NULL) {
+    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "ARKDlsSetLinearSolver", MSGD_BAD_NVECTOR);
+    return(ARKDLS_ILL_INPUT);
   }
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  if (jac != NULL) {
-    arkdls_mem->d_jacDQ = FALSE;
-    arkdls_mem->d_djac  = jac;
-  } else {
-    arkdls_mem->d_jacDQ = TRUE;
+  /* free any existing system solver attached to ARKode */
+  if (ark_mem->ark_lfree)  ark_mem->ark_lfree(ark_mem);
+
+  /* Set four main system linear solver function fields in ark_mem */
+  ark_mem->ark_linit  = arkDlsInitialize;
+  ark_mem->ark_lsetup = arkDlsSetup;
+  ark_mem->ark_lsolve = arkDlsSolve;
+  ark_mem->ark_lfree  = arkDlsFree;
+  ark_mem->ark_lsolve_type = 1;
+  
+  /* Get memory for ARKDlsMemRec */
+  arkdls_mem = NULL;
+  arkdls_mem = (ARKDlsMem) malloc(sizeof(struct ARKDlsMemRec));
+  if (arkdls_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDLS", 
+                    "ARKDlsSetLinearSolver", MSGD_MEM_FAIL);
+    return(ARKDLS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer */
+  arkdls_mem->LS = LS;
+  
+  /* Initialize Jacobian-related data */
+  arkdls_mem->jacDQ = SUNTRUE;
+  arkdls_mem->jac = arkDlsDQJac;
+  arkdls_mem->J_data = ark_mem;
+  arkdls_mem->last_flag = ARKDLS_SUCCESS;
+
+  /* Initialize counters */
+  arkDlsInitializeCounters(arkdls_mem);
+
+  /* Store pointer to A and create saved_J */
+  arkdls_mem->A = A;
+  arkdls_mem->savedJ = SUNMatClone(A);
+  if (arkdls_mem->savedJ == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDLS", 
+                    "ARKDlsSetLinearSolver", MSGD_MEM_FAIL);
+    free(arkdls_mem); arkdls_mem = NULL;
+    return(ARKDLS_MEM_FAIL);
+  }
+
+  /* Allocate memory for x */
+  arkdls_mem->x = N_VClone(ark_mem->ark_tempv);
+  if (arkdls_mem->x == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDLS", 
+                    "ARKDlsSetLinearSolver", MSGD_MEM_FAIL);
+    SUNMatDestroy(arkdls_mem->savedJ);
+    free(arkdls_mem); arkdls_mem = NULL;
+    return(ARKDLS_MEM_FAIL);
   }
+  /* Attach linear solver memory to integrator memory */
+  ark_mem->ark_lmem = arkdls_mem;
 
   return(ARKDLS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKDlsSetBandJacFn specifies the band Jacobian function.
+ ARKDlsSetMassLinearSolver specifies the direct mass-matrix
+ linear solver and user-supplied routine to fill the mass matrix
 ---------------------------------------------------------------*/
-int ARKDlsSetBandJacFn(void *arkode_mem, ARKDlsBandJacFn jac)
+int ARKDlsSetMassLinearSolver(void *arkode_mem, SUNLinearSolver LS,
+                              SUNMatrix M, booleantype time_dep)
 {
   ARKodeMem ark_mem;
-  ARKDlsMem arkdls_mem;
+  ARKDlsMassMem arkdls_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
-		    "ARKDlsSetBandJacFn", MSGD_ARKMEM_NULL);
+		    "ARKDlsSetMassLinearSolver", 
+                    MSGD_ARKMEM_NULL);
     return(ARKDLS_MEM_NULL);
   }
+  if ( (LS == NULL) || (M == NULL) ) {
+    arkProcessError(NULL, ARKDLS_ILL_INPUT, "ARKDLS", 
+		    "ARKDlsSetMassLinearSolver",
+                    "Both LS and M must be non-NULL");
+    return(ARKDLS_ILL_INPUT);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
-		    "ARKDlsSetBandJacFn", MSGD_LMEM_NULL);
-    return(ARKDLS_LMEM_NULL);
+  /* Test if solver and vector are compatible with DLS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
+    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "ARKDlsSetMassLinearSolver", 
+                    "Non-direct LS supplied to ARKDls interface");
+    return(ARKDLS_ILL_INPUT);
+  }
+  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL ||
+      ark_mem->ark_tempv->ops->nvsetarraypointer == NULL) {
+    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "ARKDlsSetMassLinearSolver", 
+                    MSGD_BAD_NVECTOR);
+    return(ARKDLS_ILL_INPUT);
   }
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  if (jac != NULL) {
-    arkdls_mem->d_jacDQ = FALSE;
-    arkdls_mem->d_bjac  = jac;
-  } else {
-    arkdls_mem->d_jacDQ = TRUE;
+  /* free any existing system solver attached to ARKode */
+  if (ark_mem->ark_mfree)  ark_mem->ark_mfree(ark_mem);
+
+  /* Set four main system linear solver function fields in ark_mem */
+  ark_mem->ark_minit  = arkDlsMassInitialize;
+  ark_mem->ark_msetup = arkDlsMassSetup;
+  ark_mem->ark_mmult  = arkDlsMassMult;
+  ark_mem->ark_msolve = arkDlsMassSolve;
+  ark_mem->ark_mfree  = arkDlsMassFree;
+  ark_mem->ark_msolve_type = 1;
+  
+  /* notify arkode of non-identity mass matrix */
+  ark_mem->ark_mass_matrix = SUNTRUE;
+
+  /* Get memory for ARKDlsMassMemRec */
+  arkdls_mem = NULL;
+  arkdls_mem = (ARKDlsMassMem) malloc(sizeof(struct ARKDlsMassMemRec));
+  if (arkdls_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDLS", 
+                    "ARKDlsSetMassLinearSolver", MSGD_MEM_FAIL);
+    return(ARKDLS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer; flag indicating time-dependence */
+  arkdls_mem->LS = LS;
+  arkdls_mem->time_dependent = time_dep;
+
+  /* Initialize mass-matrix-related data */
+  arkdls_mem->mass = NULL;
+  arkdls_mem->last_flag = ARKDLS_SUCCESS;
+
+  /* Initialize counters */
+  arkDlsInitializeMassCounters(arkdls_mem);
+
+  /* Store pointer to M and create M_lu */
+  arkdls_mem->M = M;
+  arkdls_mem->M_lu = SUNMatClone(M);
+  if (arkdls_mem->M_lu == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDLS", 
+                    "ARKDlsSetMassLinearSolver", MSGD_MEM_FAIL);
+    free(arkdls_mem); arkdls_mem = NULL;
+    return(ARKDLS_MEM_FAIL);
   }
 
+  /* Allocate memory for x */
+  arkdls_mem->x = N_VClone(ark_mem->ark_tempv);
+  if (arkdls_mem->x == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKDLS", 
+                    "ARKDlsSetMassLinearSolver", MSGD_MEM_FAIL);
+    SUNMatDestroy(arkdls_mem->M_lu);
+    free(arkdls_mem); arkdls_mem = NULL;
+    return(ARKDLS_MEM_FAIL);
+  }
+
+  /* Attach linear solver memory to integrator memory */
+  ark_mem->ark_mass_mem = arkdls_mem;
+
   return(ARKDLS_SUCCESS);
 }
 
 
+/*===============================================================
+  ARKDLS Exported functions -- Optional input/output
+===============================================================*/
+
 /*---------------------------------------------------------------
- ARKDlsSetDenseMassFn specifies the dense mass matrix function.
+ ARKDlsSetJacFn specifies the Jacobian function.
 ---------------------------------------------------------------*/
-int ARKDlsSetDenseMassFn(void *arkode_mem, ARKDlsDenseMassFn mass)
+int ARKDlsSetJacFn(void *arkode_mem, ARKDlsJacFn jac)
 {
   ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
+  ARKDlsMem arkdls_mem;
 
   /* Return immediately if arkode_mem is NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
-		    "ARKDlsSetDenseMassFn", MSGD_ARKMEM_NULL);
+		    "ARKDlsSetJacFn", MSGD_ARKMEM_NULL);
     return(ARKDLS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
-		    "ARKDlsSetDenseMassFn", MSGD_MASSMEM_NULL);
-    return(ARKDLS_MASSMEM_NULL);
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
+		    "ARKDlsSetJacFn", MSGD_LMEM_NULL);
+    return(ARKDLS_LMEM_NULL);
   }
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  if (mass != NULL) {
-    arkdls_mem->d_dmass = mass;
+  if (jac != NULL) {
+    arkdls_mem->jacDQ  = SUNFALSE;
+    arkdls_mem->jac    = jac;
+    arkdls_mem->J_data = ark_mem->ark_user_data;
   } else {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
-		    "ARKDlsSetDenseMassFn", "DenseMassFn must be non-NULL");
-    return(ARKDLS_ILL_INPUT);
+    arkdls_mem->jacDQ  = SUNTRUE;
+    arkdls_mem->jac    = arkDlsDQJac;
+    arkdls_mem->J_data = ark_mem;
   }
 
   return(ARKDLS_SUCCESS);
@@ -143,9 +280,9 @@ int ARKDlsSetDenseMassFn(void *arkode_mem, ARKDlsDenseMassFn mass)
 
 
 /*---------------------------------------------------------------
- ARKDlsSetBandMassFn specifies the band mass matrix function.
+ ARKDlsSetMassFn specifies the mass matrix function.
 ---------------------------------------------------------------*/
-int ARKDlsSetBandMassFn(void *arkode_mem, ARKDlsBandMassFn mass)
+int ARKDlsSetMassFn(void *arkode_mem, ARKDlsMassFn mass)
 {
   ARKodeMem ark_mem;
   ARKDlsMassMem arkdls_mem;
@@ -153,24 +290,24 @@ int ARKDlsSetBandMassFn(void *arkode_mem, ARKDlsBandMassFn mass)
   /* Return immediately if arkode_mem is NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
-		    "ARKDlsSetBandMassFn", MSGD_ARKMEM_NULL);
+		    "ARKDlsSetDenseMassFn", MSGD_ARKMEM_NULL);
     return(ARKDLS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
-		    "ARKDlsSetBandMassFn", MSGD_MASSMEM_NULL);
+		    "ARKDlsSetDenseMassFn", MSGD_MASSMEM_NULL);
     return(ARKDLS_MASSMEM_NULL);
   }
   arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
 
   if (mass != NULL) {
-    arkdls_mem->d_bmass = mass;
+    arkdls_mem->mass = mass;
   } else {
     arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
-		    "ARKDlsSetBandMassFn", "BandMassFn must be non-NULL");
-    return(ARKDLS_MASSMEM_NULL);
+		    "ARKDlsSetDenseMassFn", "MassFn must be non-NULL");
+    return(ARKDLS_ILL_INPUT);
   }
 
   return(ARKDLS_SUCCESS);
@@ -179,12 +316,16 @@ int ARKDlsSetBandMassFn(void *arkode_mem, ARKDlsBandMassFn mass)
 
 /*---------------------------------------------------------------
  ARKDlsGetWorkSpace returns the length of workspace allocated for 
- the ARKDLS linear solver.
+ the ARKDLS linear solver interface.
 ---------------------------------------------------------------*/
-int ARKDlsGetWorkSpace(void *arkode_mem, long int *lenrwLS, long int *leniwLS)
+int ARKDlsGetWorkSpace(void *arkode_mem, long int *lenrw, 
+                       long int *leniw)
 {
   ARKodeMem ark_mem;
   ARKDlsMem arkdls_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
   /* Return immediately if arkode_mem is NULL */
   if (arkode_mem == NULL) {
@@ -201,49 +342,29 @@ int ARKDlsGetWorkSpace(void *arkode_mem, long int *lenrwLS, long int *leniwLS)
   }
   arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  if (arkdls_mem->d_type == SUNDIALS_DENSE) {
-    *lenrwLS = 2*arkdls_mem->d_n*arkdls_mem->d_n;
-    *leniwLS = arkdls_mem->d_n;
-  } else if (arkdls_mem->d_type == SUNDIALS_BAND) {
-    *lenrwLS = arkdls_mem->d_n*(arkdls_mem->d_smu + arkdls_mem->d_mu + 2*arkdls_mem->d_ml + 2);
-    *leniwLS = arkdls_mem->d_n;
-  }
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKDlsGetMassWorkSpace returns the length of workspace allocated 
- for the ARKDLS mass matrix linear solver.
----------------------------------------------------------------*/
-int ARKDlsGetMassWorkSpace(void *arkode_mem, long int *lenrwMLS, 
-			   long int *leniwMLS)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
+  /* initialize outputs with requirements from ARKDlsMem structure */
+  *lenrw = 0;
+  *leniw = 4;
 
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
-		    "ARKDlsGetMassWorkSpace", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
+  /* add NVector sizes */
+  if (arkdls_mem->x->ops->nvspace) {
+    N_VSpace(arkdls_mem->x, &lrw1, &liw1);
+    *lenrw += lrw1;
+    *leniw += liw1;
   }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
-		    "ARKDlsGetMassWorkSpace", MSGD_MASSMEM_NULL);
-    return(ARKDLS_MASSMEM_NULL);
+  
+  /* add SUNMatrix size (only account for the one owned by Dls interface) */
+  if (arkdls_mem->savedJ->ops->space) {
+    flag = SUNMatSpace(arkdls_mem->savedJ, &lrw, &liw);
+    *lenrw += lrw;
+    *leniw += liw;
   }
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
 
-  if (arkdls_mem->d_type == SUNDIALS_DENSE) {
-    *lenrwMLS = 2*arkdls_mem->d_n*arkdls_mem->d_n;
-    *leniwMLS = arkdls_mem->d_n;
-  } else if (arkdls_mem->d_type == SUNDIALS_BAND) {
-    *lenrwMLS = arkdls_mem->d_n*(arkdls_mem->d_smu + arkdls_mem->d_mu + 2*arkdls_mem->d_ml + 2);
-    *leniwMLS = arkdls_mem->d_n;
+  /* add LS sizes */
+  if (arkdls_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(arkdls_mem->LS, &lrw, &liw);
+    *lenrw += lrw;
+    *leniw += liw;
   }
 
   return(ARKDLS_SUCCESS);
@@ -266,6 +387,7 @@ int ARKDlsGetNumJacEvals(void *arkode_mem, long int *njevals)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
+  /* Access the ARKDlsMem structure */
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
 		    "ARKDlsGetNumJacEvals", MSGD_LMEM_NULL);
@@ -273,36 +395,7 @@ int ARKDlsGetNumJacEvals(void *arkode_mem, long int *njevals)
   }
   arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  *njevals = arkdls_mem->d_nje;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKDlsGetNumMassEvals returns the number of mass matrix evaluations.
----------------------------------------------------------------*/
-int ARKDlsGetNumMassEvals(void *arkode_mem, long int *nmevals)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
-		    "ARKDlsGetNumMassEvals", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
-		    "ARKDlsGetNumMassEvals", MSGD_MASSMEM_NULL);
-    return(ARKDLS_MASSMEM_NULL);
-  }
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-
-  *nmevals = arkdls_mem->d_nme;
+  *njevals = arkdls_mem->nje;
 
   return(ARKDLS_SUCCESS);
 }
@@ -325,6 +418,7 @@ int ARKDlsGetNumRhsEvals(void *arkode_mem, long int *nfevalsLS)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
+  /* Access the ARKDlsMem structure */
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
 		    "ARKDlsGetNumRhsEvals", MSGD_LMEM_NULL);
@@ -332,7 +426,7 @@ int ARKDlsGetNumRhsEvals(void *arkode_mem, long int *nfevalsLS)
   }
   arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  *nfevalsLS = arkdls_mem->d_nfeDQ;
+  *nfevalsLS = arkdls_mem->nfeDQ;
 
   return(ARKDLS_SUCCESS);
 }
@@ -358,21 +452,30 @@ char *ARKDlsGetReturnFlagName(long int flag)
   case ARKDLS_LMEM_NULL:
     sprintf(name,"ARKDLS_LMEM_NULL");
     break;
-  case ARKDLS_MASSMEM_NULL:
-    sprintf(name,"ARKDLS_MASSMEM_NULL");
-    break;
   case ARKDLS_ILL_INPUT:
     sprintf(name,"ARKDLS_ILL_INPUT");
     break;
   case ARKDLS_MEM_FAIL:
     sprintf(name,"ARKDLS_MEM_FAIL");
     break;
+  case ARKDLS_MASSMEM_NULL:
+    sprintf(name,"ARKDLS_MASSMEM_NULL");
+    break;
   case ARKDLS_JACFUNC_UNRECVR:
     sprintf(name,"ARKDLS_JACFUNC_UNRECVR");
     break;
   case ARKDLS_JACFUNC_RECVR:
     sprintf(name,"ARKDLS_JACFUNC_RECVR");
     break;
+  case ARKDLS_MASSFUNC_UNRECVR:
+    sprintf(name,"ARKDLS_MASSFUNC_UNRECVR");
+    break;
+  case ARKDLS_MASSFUNC_RECVR:
+    sprintf(name,"ARKDLS_MASSFUNC_RECVR");
+    break;
+  case ARKDLS_SUNMAT_FAIL:
+    sprintf(name,"ARKDLS_SUNMAT_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -397,6 +500,7 @@ int ARKDlsGetLastFlag(void *arkode_mem, long int *flag)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
+  /* Access the ARKDlsMem structure */
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
 		    "ARKDlsGetLastFlag", MSGD_LMEM_NULL);
@@ -404,7 +508,157 @@ int ARKDlsGetLastFlag(void *arkode_mem, long int *flag)
   }
   arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  *flag = arkdls_mem->d_last_flag;
+  *flag = arkdls_mem->last_flag;
+
+  return(ARKDLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ ARKDlsGetMassWorkSpace returns the length of workspace allocated 
+ for the ARKDLS mass matrix linear solver.
+---------------------------------------------------------------*/
+int ARKDlsGetMassWorkSpace(void *arkode_mem, long int *lenrw, 
+                           long int *leniw)
+{
+  ARKodeMem ark_mem;
+  ARKDlsMassMem arkdls_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
+
+  /* Return immediately if arkode_mem is NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "ARKDlsGetMassWorkSpace", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "ARKDlsGetMassWorkSpace", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  /* initialize outputs with requirements from ARKDlsMem structure */
+  *lenrw = 0;
+  *leniw = 6;
+
+  /* add NVector sizes */
+  if (arkdls_mem->x->ops->nvspace) {
+    N_VSpace(arkdls_mem->x, &lrw1, &liw1);
+    *lenrw += lrw1;
+    *leniw += liw1;
+  }
+  
+  /* add SUNMatrix size (only account for the one owned by Dls interface) */
+  if (arkdls_mem->M_lu->ops->space) {
+    flag = SUNMatSpace(arkdls_mem->M_lu, &lrw, &liw);
+    *lenrw += lrw;
+    *leniw += liw;
+  }
+
+  /* add LS sizes */
+  if (arkdls_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(arkdls_mem->LS, &lrw, &liw);
+    *lenrw += lrw;
+    *leniw += liw;
+  }
+  
+  return(ARKDLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ ARKDlsGetNumMassSetups returns the number of mass matrix solver
+ 'setup' calls
+---------------------------------------------------------------*/
+int ARKDlsGetNumMassSetups(void *arkode_mem, long int *nmsetups)
+{
+  ARKodeMem ark_mem;
+  ARKDlsMassMem arkdls_mem;
+
+  /* Return immediately if arkode_mem is NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "ARKDlsGetNumMassSetups", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+
+  /* Access the ARKDlsMem structure */
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "ARKDlsGetNumMassSetups", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  *nmsetups = arkdls_mem->mass_setups;
+
+  return(ARKDLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ ARKDlsGetNumMassSolves returns the number of mass matrix solver
+ 'solve' calls
+---------------------------------------------------------------*/
+int ARKDlsGetNumMassSolves(void *arkode_mem, long int *nmsolves)
+{
+  ARKodeMem ark_mem;
+  ARKDlsMassMem arkdls_mem;
+
+  /* Return immediately if arkode_mem is NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "ARKDlsGetNumMassSolves", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+
+  /* Access the ARKDlsMem structure */
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "ARKDlsGetNumMassSolves", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  *nmsolves = arkdls_mem->mass_solves;
+
+  return(ARKDLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ ARKDlsGetNumMassMult returns the number of mass matrix-vector
+ products
+---------------------------------------------------------------*/
+int ARKDlsGetNumMassMult(void *arkode_mem, long int *nmmults)
+{
+  ARKodeMem ark_mem;
+  ARKDlsMassMem arkdls_mem;
+
+  /* Return immediately if arkode_mem is NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "ARKDlsGetNumMassMult", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+
+  /* Access the ARKDlsMem structure */
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "ARKDlsGetNumMassMult", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  *nmmults = arkdls_mem->mass_mults;
 
   return(ARKDLS_SUCCESS);
 }
@@ -427,6 +681,7 @@ int ARKDlsGetLastMassFlag(void *arkode_mem, long int *flag)
   }
   ark_mem = (ARKodeMem) arkode_mem;
 
+  /* Access the ARKDlsMem structure */
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
 		    "ARKDlsGetLastMassFlag", MSGD_MASSMEM_NULL);
@@ -434,51 +689,90 @@ int ARKDlsGetLastMassFlag(void *arkode_mem, long int *flag)
   }
   arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
 
-  *flag = arkdls_mem->d_last_flag;
+  *flag = arkdls_mem->last_flag;
 
   return(ARKDLS_SUCCESS);
 }
 
 
 /*===============================================================
- DQ JACOBIAN APPROXIMATIONS
+  ARKDLS Private functions
 ===============================================================*/
 
 /*---------------------------------------------------------------
+ arkDlsDQJac:
+
+ This routine is a wrapper for the Dense and Band
+ implementations of the difference quotient Jacobian 
+ approximation routines.
+---------------------------------------------------------------*/
+int arkDlsDQJac(realtype t, N_Vector y, N_Vector fy, 
+                SUNMatrix Jac, void *arkode_mem, N_Vector tmp1, 
+                N_Vector tmp2, N_Vector tmp3)
+{
+  int retval;
+  ARKodeMem ark_mem;
+  ark_mem = (ARKodeMem) arkode_mem;
+
+  /* verify that Jac is non-NULL */
+  if (Jac == NULL) {
+    arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
+		    "arkDlsDQJac", MSGD_LMEM_NULL);
+    return(ARKDLS_LMEM_NULL);
+  }
+
+  if (SUNMatGetID(Jac) == SUNMATRIX_DENSE) {
+    retval = arkDlsDenseDQJac(t, y, fy, Jac, ark_mem, tmp1);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_BAND) {
+    retval = arkDlsBandDQJac(t, y, fy, Jac, ark_mem, tmp1, tmp2);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_SPARSE) {
+    arkProcessError(ark_mem, ARK_ILL_INPUT, "ARKDLS", 
+		    "arkDlsDQJac", 
+                    "arkDlsDQJac not implemented for SUNMATRIX_SPARSE");
+    retval = ARK_ILL_INPUT;
+  } else {
+    arkProcessError(ark_mem, ARK_ILL_INPUT, "ARKDLS", 
+		    "arkDlsDQJac", 
+                    "unrecognized matrix type for arkDlsDQJac");
+    retval = ARK_ILL_INPUT;
+  }
+  return(retval);
+}
+
+/*---------------------------------------------------------------
  arkDlsDenseDQJac:
 
  This routine generates a dense difference quotient approximation 
- to the Jacobian of f(t,y). It assumes that a dense matrix of 
- type DlsMat is stored column-wise, and that elements within each 
- column are contiguous. The address of the jth column of J is 
- obtained via the macro DENSE_COL and this pointer is associated 
- with an N_Vector using the N_VGetArrayPointer/N_VSetArrayPointer 
- functions.  Finally, the actual computation of the jth column of
- the Jacobian is done with a call to N_VLinearSum.
+ to the Jacobian of f(t,y). It assumes a dense SUNMatrix input
+ (stored column-wise, and that elements within each column are
+ contiguous). The address of the jth column of J is obtained via 
+ the function SUNDenseMatrix_Column() and this pointer is 
+ associated with an N_Vector using the 
+ N_VGetArrayPointer/N_VSetArrayPointer functions.  Finally, the
+ actual computation of the jth column of the Jacobian is done 
+ with a call to N_VLinearSum.
 ---------------------------------------------------------------*/
-int arkDlsDenseDQJac(long int N, realtype t, N_Vector y, 
-		     N_Vector fy, DlsMat Jac, void *data,
-		     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+int arkDlsDenseDQJac(realtype t, N_Vector y, N_Vector fy, 
+                     SUNMatrix Jac, ARKodeMem ark_mem, N_Vector tmp1)
 {
   realtype fnorm, minInc, inc, inc_inv, yjsaved, srur;
-  realtype *tmp2_data, *y_data, *ewt_data;
+  realtype *y_data, *ewt_data;
   N_Vector ftemp, jthCol;
-  long int j;
+  sunindextype j, N;
   int retval = 0;
-
-  ARKodeMem ark_mem;
   ARKDlsMem arkdls_mem;
 
-  /* data points to arkode_mem */
-  ark_mem = (ARKodeMem) data;
+  /* access DlsMem interface structure */
   arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
-  /* Save pointer to the array in tmp2 */
-  tmp2_data = N_VGetArrayPointer(tmp2);
+  /* access matrix dimension */
+  N = SUNDenseMatrix_Rows(Jac);
+
+  /* Rename work vector for readibility */
+  ftemp = tmp1;
 
-  /* Rename work vectors for readibility */
-  ftemp = tmp1; 
-  jthCol = tmp2;
+  /* Create an empty vector for matrix column calculations */
+  jthCol = N_VCloneEmpty(tmp1);
 
   /* Obtain pointers to the data for ewt, y */
   ewt_data = N_VGetArrayPointer(ark_mem->ark_ewt);
@@ -486,22 +780,21 @@ int arkDlsDenseDQJac(long int N, realtype t, N_Vector y,
 
   /* Set minimum increment based on uround and norm of f */
   srur = SUNRsqrt(ark_mem->ark_uround);
-  /* fnorm = N_VWrmsNorm(fy, ark_mem->ark_ewt); */
   fnorm = N_VWrmsNorm(fy, ark_mem->ark_rwt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) * ark_mem->ark_uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) * ark_mem->ark_uround * N * fnorm) : ONE;
 
   for (j = 0; j < N; j++) {
 
     /* Generate the jth col of J(tn,y) */
-    N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol);
+    N_VSetArrayPointer(SUNDenseMatrix_Column(Jac,j), jthCol);
 
     yjsaved = y_data[j];
     inc = SUNMAX(srur*SUNRabs(yjsaved), minInc/ewt_data[j]);
     y_data[j] += inc;
 
     retval = ark_mem->ark_fi(t, y, ftemp, ark_mem->ark_user_data);
-    arkdls_mem->d_nfeDQ++;
+    arkdls_mem->nfeDQ++;
     if (retval != 0) break;
     
     y_data[j] = yjsaved;
@@ -509,11 +802,12 @@ int arkDlsDenseDQJac(long int N, realtype t, N_Vector y,
     inc_inv = ONE/inc;
     N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol);
 
-    DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);
+    /* DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol); */  /* UNNECESSARY?? */
   }
 
-  /* Restore original array pointer in tmp2 */
-  N_VSetArrayPointer(tmp2_data, tmp2);
+  /* Destroy jthCol vector */
+  N_VSetArrayPointer(NULL, jthCol);  /* SHOULDN'T BE NEEDED */
+  N_VDestroy(jthCol);
 
   return(retval);
 }
@@ -523,30 +817,33 @@ int arkDlsDenseDQJac(long int N, realtype t, N_Vector y,
  arkDlsBandDQJac:
 
  This routine generates a banded difference quotient approximation 
- to the Jacobian of f(t,y).  It assumes that a band matrix of type
- DlsMat is stored column-wise, and that elements within each 
- column are contiguous. This makes it possible to get the address 
- of a column of J via the macro BAND_COL and to write a simple for 
- loop to set each of the elements of a column in succession.
+ to the Jacobian of f(t,y).  It assumes a band SUNMatrix input 
+ (stored column-wise, and that elements within each column are 
+ contiguous). This makes it possible to get the address 
+ of a column of J via the function SUNBandMatrix_Column() and to
+ write a simple for loop to set each of the elements of a column 
+ in succession.
 ---------------------------------------------------------------*/
-int arkDlsBandDQJac(long int N, long int mupper, long int mlower,
-                   realtype t, N_Vector y, N_Vector fy, 
-                   DlsMat Jac, void *data,
-                   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+int arkDlsBandDQJac(realtype t, N_Vector y, N_Vector fy, 
+                    SUNMatrix Jac, ARKodeMem ark_mem,
+                    N_Vector tmp1, N_Vector tmp2)
 {
   N_Vector ftemp, ytemp;
   realtype fnorm, minInc, inc, inc_inv, srur;
   realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   int retval = 0;
-
-  ARKodeMem ark_mem;
+  sunindextype N, mupper, mlower;
   ARKDlsMem arkdls_mem;
 
-  /* data points to arkode_mem */
-  ark_mem = (ARKodeMem) data;
+  /* access DlsMem interface structure */
   arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
 
+  /* access matrix dimensions */
+  N = SUNBandMatrix_Columns(Jac);
+  mupper = SUNBandMatrix_UpperBandwidth(Jac);
+  mlower = SUNBandMatrix_LowerBandwidth(Jac);
+
   /* Rename work vectors for use as temporary values of y and f */
   ftemp = tmp1;
   ytemp = tmp2;
@@ -563,10 +860,9 @@ int arkDlsBandDQJac(long int N, long int mupper, long int mlower,
 
   /* Set minimum increment based on uround and norm of f */
   srur = SUNRsqrt(ark_mem->ark_uround);
-  /* fnorm = N_VWrmsNorm(fy, ark_mem->ark_ewt); */
   fnorm = N_VWrmsNorm(fy, ark_mem->ark_rwt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) * ark_mem->ark_uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(ark_mem->ark_h) * ark_mem->ark_uround * N * fnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing */
   width = mlower + mupper + 1;
@@ -584,19 +880,19 @@ int arkDlsBandDQJac(long int N, long int mupper, long int mlower,
     /* Evaluate f with incremented y */
     retval = ark_mem->ark_fi(ark_mem->ark_tn, ytemp, ftemp, 
                              ark_mem->ark_user_data);
-    arkdls_mem->d_nfeDQ++;
+    arkdls_mem->nfeDQ++;
     if (retval != 0) break;
 
     /* Restore ytemp, then form and load difference quotients */
     for (j=group-1; j < N; j+=width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(Jac,j);
+      col_j = SUNBandMatrix_Column(Jac, j);
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-mupper);
       i2 = SUNMIN(j+mlower, N-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
     }
   }
   
@@ -604,14 +900,513 @@ int arkDlsBandDQJac(long int N, long int mupper, long int mlower,
 }
 
 
+/*---------------------------------------------------------------
+ arkDlsInitialize performs remaining initializations specific
+ to the direct linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int arkDlsInitialize(ARKodeMem ark_mem)
+{
+  ARKDlsMem arkdls_mem;
+  ARKDlsMassMem arkdls_mass_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+                    "arkDlsInitialize", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
+		    "arkDlsInitialize", MSGD_LMEM_NULL);
+    return(ARKDLS_LMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
+  
+  arkDlsInitializeCounters(arkdls_mem);
+
+  /* Set Jacobian function and data, depending on jacDQ (in case 
+     it has changed based on user input) */
+  if (arkdls_mem->jacDQ) {
+    arkdls_mem->jac    = arkDlsDQJac;
+    arkdls_mem->J_data = ark_mem;
+  } else {
+    arkdls_mem->J_data = ark_mem->ark_user_data;
+  }
+
+  /* Ensure that if a mass matrix / solver are used, that system 
+     and mass matrix solvers and types match */
+  if (ark_mem->ark_mass_matrix) {
+
+    /* access mass matrix solver interface */
+    if (ark_mem->ark_mass_mem == NULL) {
+      arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+                      "arkDlsInitialize", MSGD_MASSMEM_NULL);
+      return(ARKDLS_MASSMEM_NULL);
+    }
+    arkdls_mass_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+    /* check that ark_msolve_type is compatible */
+    if (ark_mem->ark_msolve_type != 1) {
+      arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+		      "arkDlsInitialize",
+                      "Dls and Spils solvers cannot be combined");
+      arkdls_mem->last_flag = ARKDLS_ILL_INPUT;
+      return(-1);
+    }
+
+    /* check that system and mass matrix types are compatible */
+    if (SUNMatGetID(arkdls_mem->A) != SUNMatGetID(arkdls_mass_mem->M)) {
+      arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+		      "arkDlsInitialize",
+                      "System and mass matrices must have the same type");
+      arkdls_mem->last_flag = ARKDLS_ILL_INPUT;
+      return(-1);
+    }
+  }
+
+  /* Call LS initialize routine */
+  arkdls_mem->last_flag = SUNLinSolInitialize(arkdls_mem->LS);
+  return(arkdls_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsSetup determines whether to update a Jacobian matrix (or
+ use a stored version), based on heuristics regarding previous 
+ convergence issues, the number of time steps since it was last
+ updated, etc.; it then creates the system matrix from this, the
+ 'gamma' factor and the mass/identity matrix, 
+    A = M-gamma*J.
+ This routine then calls the LS 'setup' routine with A.
+---------------------------------------------------------------*/
+int arkDlsSetup(ARKodeMem ark_mem, int convfail, N_Vector ypred,
+                N_Vector fpred, booleantype *jcurPtr, 
+                N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+{
+  booleantype jbad, jok;
+  realtype dgamma;
+  ARKDlsMem arkdls_mem;
+  ARKDlsMassMem arkdls_mass_mem;
+  int retval;
+
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+                    "arkDlsSetup", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
+                    "arkDlsSetup", MSGD_LMEM_NULL);
+    return(ARKDLS_LMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
+
+  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
+  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
+  jbad = (ark_mem->ark_nst == 0) || 
+    (ark_mem->ark_nst > arkdls_mem->nstlj + ARKD_MSBJ) ||
+    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKD_DGMAX)) ||
+    (convfail == ARK_FAIL_OTHER);
+  jok = !jbad;
+ 
+  /* If jok = SUNTRUE, use saved copy of J */
+  if (jok) {
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(arkdls_mem->savedJ, arkdls_mem->A);
+    if (retval) {
+      arkProcessError(ark_mem, ARKDLS_SUNMAT_FAIL, "ARKDLS", 
+                      "arkDlsSetup",  MSGD_MATCOPY_FAILED);
+      arkdls_mem->last_flag = ARKDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+
+  /* If jok = SUNFALSE, call jac routine for new J value */
+  } else {
+    arkdls_mem->nje++;
+    arkdls_mem->nstlj = ark_mem->ark_nst;
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(arkdls_mem->A);
+    if (retval) {
+      arkProcessError(ark_mem, ARKDLS_SUNMAT_FAIL, "ARKDLS", 
+                      "arkDlsSetup",  MSGD_MATZERO_FAILED);
+      arkdls_mem->last_flag = ARKDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+
+    retval = arkdls_mem->jac(ark_mem->ark_tn, ypred, fpred, arkdls_mem->A, 
+                             arkdls_mem->J_data, vtemp1, vtemp2, vtemp3);
+    if (retval < 0) {
+      arkProcessError(ark_mem, ARKDLS_JACFUNC_UNRECVR, "ARKDLS", 
+                      "arkDlsSetup",  MSGD_JACFUNC_FAILED);
+      arkdls_mem->last_flag = ARKDLS_JACFUNC_UNRECVR;
+      return(-1);
+    }
+    if (retval > 0) {
+      arkdls_mem->last_flag = ARKDLS_JACFUNC_RECVR;
+      return(1);
+    }
+
+    retval = SUNMatCopy(arkdls_mem->A, arkdls_mem->savedJ);
+    if (retval) {
+      arkProcessError(ark_mem, ARKDLS_SUNMAT_FAIL, "ARKDLS", 
+                      "arkDlsSetup",  MSGD_MATCOPY_FAILED);
+      arkdls_mem->last_flag = ARKDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+
+  }
+  
+  /* Scale and add mass matrix to get A = M-gamma*J*/
+  if (ark_mem->ark_mass_matrix) {
+
+    /* Access mass matrix solver interface */
+    if (ark_mem->ark_mass_mem == NULL) {
+      arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+                      "arkDlsSetup", MSGD_MASSMEM_NULL);
+      return(ARKDLS_MASSMEM_NULL);
+    }
+    arkdls_mass_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+    /* Compute mass matrix */
+    retval = arkDlsMassSetup(ark_mem, vtemp1, vtemp2, vtemp3);
+
+    /* Perform linear combination A = M-gamma*A */
+    retval = SUNMatScaleAdd(-ark_mem->ark_gamma, arkdls_mem->A, 
+                            arkdls_mass_mem->M);
+    if (retval) {
+      arkProcessError(ark_mem, ARKDLS_SUNMAT_FAIL, "ARKDLS", 
+                      "arkDlsSetup",  MSGD_MATSCALEADD_FAILED);
+      arkdls_mem->last_flag = ARKDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+
+  } else {
+    retval = SUNMatScaleAddI(-ark_mem->ark_gamma, arkdls_mem->A);
+    if (retval) {
+      arkProcessError(ark_mem, ARKDLS_SUNMAT_FAIL, "ARKDLS", 
+                      "arkDlsSetup",  MSGD_MATSCALEADDI_FAILED);
+      arkdls_mem->last_flag = ARKDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+  }
+
+  /* Call generic linear solver 'setup' with this system matrix, and
+     return success/failure flag */
+  arkdls_mem->last_flag = SUNLinSolSetup(arkdls_mem->LS, arkdls_mem->A);
+  return(arkdls_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsSolve interfaces between ARKode and the generic 
+ SUNLinearSolver object LS, by calling the solver and scaling 
+ the solution appropriately when gamrat != 1.
+---------------------------------------------------------------*/
+int arkDlsSolve(ARKodeMem ark_mem, N_Vector b, N_Vector ycur, N_Vector fcur)
+{
+  int retval;
+  ARKDlsMem arkdls_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "arkDlsSolve", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_LMEM_NULL, "ARKDLS", 
+		    "arkDlsSolve", MSGD_LMEM_NULL);
+    return(ARKDLS_LMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
+
+  /* call the generic linear system solver, and copy b to x */
+  retval = SUNLinSolSolve(arkdls_mem->LS, arkdls_mem->A, arkdls_mem->x, b, ZERO);
+  N_VScale(ONE, arkdls_mem->x, b);
+  
+  /* scale the correction to account for change in gamma */
+  if (ark_mem->ark_gamrat != ONE) 
+    N_VScale(TWO/(ONE + ark_mem->ark_gamrat), b, b);
+  
+  /* store solver return value and return */
+  arkdls_mem->last_flag = retval;
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsFree frees memory associates with the ARKDls system
+ solver interface.
+---------------------------------------------------------------*/
+int arkDlsFree(ARKodeMem ark_mem)
+{
+  ARKDlsMem arkdls_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL)  return (ARKDLS_SUCCESS);
+  if (ark_mem->ark_lmem == NULL)  return(ARKDLS_SUCCESS);
+  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
+
+  /* Free x vector */
+  if (arkdls_mem->x) {
+    N_VDestroy(arkdls_mem->x);
+    arkdls_mem->x = NULL;
+  }
+
+  /* Free savedJ memory */
+  if (arkdls_mem->savedJ) {
+    SUNMatDestroy(arkdls_mem->savedJ);
+    arkdls_mem->savedJ = NULL;
+  }
+
+  /* Nullify other SUNMatrix pointer */
+  arkdls_mem->A = NULL;
+
+  /* free ARKDls interface structure */
+  free(ark_mem->ark_lmem);
+  
+  return(ARKDLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsMassInitialize performs remaining initializations specific
+ to the direct mass linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int arkDlsMassInitialize(ARKodeMem ark_mem)
+{
+  ARKDlsMassMem arkdls_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "arkDlsMassInitialize", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "arkDlsMassInitialize", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+  
+  arkDlsInitializeMassCounters(arkdls_mem);
+
+  /* Ensure that mass matrix routine, matrix and solver exist */
+  if (arkdls_mem->mass == NULL) {
+    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "arkDlsMassInitialize",
+                    "DlsMass solver cannot run without user-provided mass-matrix routine");
+    arkdls_mem->last_flag = ARKDLS_ILL_INPUT;
+    return(-1);
+  }
+  if (arkdls_mem->M == NULL) {
+    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "arkDlsMassInitialize",
+                    "DlsMass solver cannot run without SUNMatrix object");
+    arkdls_mem->last_flag = ARKDLS_ILL_INPUT;
+    return(-1);
+  }
+  if (arkdls_mem->LS == NULL) {
+    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKDLS", 
+                    "arkDlsMassInitialize",
+                    "DlsMass solver cannot run without SUNLinearSolver object");
+    arkdls_mem->last_flag = ARKDLS_ILL_INPUT;
+    return(-1);
+  }
+
+  /* Call LS initialize routine */
+  arkdls_mem->last_flag = SUNLinSolInitialize(arkdls_mem->LS);
+  return(arkdls_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsMassSetup updates the system mass matrix and calls the LS
+ 'setup' routine with M.
+---------------------------------------------------------------*/
+int arkDlsMassSetup(ARKodeMem ark_mem, N_Vector vtemp1,
+                    N_Vector vtemp2, N_Vector vtemp3)
+{
+  ARKDlsMassMem arkdls_mem;
+  int retval;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "arkDlsMassSetup", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "arkDlsMassSetup", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  /* If mass matrix is not time dependent, and if it has been set up 
+   previously, just reuse existing M and M_lu */
+  if (!arkdls_mem->time_dependent && arkdls_mem->mass_setups) {
+    arkdls_mem->last_flag = ARKDLS_SUCCESS;
+    return(arkdls_mem->last_flag);
+  }
+  
+  /* Compute mass matrix */
+  retval = SUNMatZero(arkdls_mem->M);
+  if (retval) {
+    arkProcessError(ark_mem, ARKDLS_SUNMAT_FAIL, "ARKDLS", 
+                    "arkDlsMassSetup",  MSGD_MATZERO_FAILED);
+    arkdls_mem->last_flag = ARKDLS_SUNMAT_FAIL;
+    return(-1);
+  }
+
+  retval = arkdls_mem->mass(ark_mem->ark_tn, 
+                            arkdls_mem->M, 
+                            ark_mem->ark_user_data, 
+                            vtemp1, vtemp2, vtemp3);
+  if (retval < 0) {
+    arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKDLS", 
+                    "arkDlsMassSetup",  MSGD_MASSFUNC_FAILED);
+    arkdls_mem->last_flag = ARKDLS_MASSFUNC_UNRECVR;
+    return(-1);
+  }
+  if (retval > 0) {
+    arkdls_mem->last_flag = ARKDLS_MASSFUNC_RECVR;
+    return(1);
+  }
+
+  /* Copy M into M_lu for factorization */
+  retval = SUNMatCopy(arkdls_mem->M, arkdls_mem->M_lu);
+  
+  /* Call generic linear solver 'setup' with this system matrix, and
+     return success/failure flag */
+  arkdls_mem->last_flag = SUNLinSolSetup(arkdls_mem->LS, arkdls_mem->M_lu);
+  arkdls_mem->mass_setups++;
+  return(arkdls_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsMassMult performs a mass-matrix-vector product using 
+ the current mass matrix stored in the DLS solver object.  This
+ is only used when updating the residual weight vector.
+---------------------------------------------------------------*/
+int arkDlsMassMult(ARKodeMem ark_mem, N_Vector v, N_Vector Mv)
+{
+  int retval;
+  ARKDlsMassMem arkdls_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "arkDlsMassMult", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "arkDlsMassMult", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  /* Use SUNMatrix routine to perform product */
+  retval = SUNMatMatvec(arkdls_mem->M, v, Mv);
+  arkdls_mem->mass_mults++;
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsMassSolve interfaces between ARKode and the generic 
+ SUNLinearSolver object LS.
+---------------------------------------------------------------*/
+int arkDlsMassSolve(ARKodeMem ark_mem, N_Vector b)
+{
+  int retval;
+  ARKDlsMassMem arkdls_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKDLS", 
+		    "arkDlsMassSolve", MSGD_ARKMEM_NULL);
+    return(ARKDLS_MEM_NULL);
+  }
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKDLS_MASSMEM_NULL, "ARKDLS", 
+		    "arkDlsMassSolve", MSGD_MASSMEM_NULL);
+    return(ARKDLS_MASSMEM_NULL);
+  }
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  /* call the generic linear system solver, and copy b to x */
+  retval = SUNLinSolSolve(arkdls_mem->LS, arkdls_mem->M_lu, arkdls_mem->x, b, ZERO);
+  N_VScale(ONE, arkdls_mem->x, b);
+  arkdls_mem->mass_solves++;
+  
+  /* store solver return value and return */
+  arkdls_mem->last_flag = retval;
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsMassFree frees memory associates with the ARKDls mass
+ matrix solver interface.
+---------------------------------------------------------------*/
+int arkDlsMassFree(ARKodeMem ark_mem)
+{
+  ARKDlsMassMem arkdls_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL)  return (ARKDLS_SUCCESS);
+  if (ark_mem->ark_mass_mem == NULL)  return(ARKDLS_SUCCESS);
+  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
+
+  /* Free x vector */
+  if (arkdls_mem->x) {
+    N_VDestroy(arkdls_mem->x);
+    arkdls_mem->x = NULL;
+  }
+
+  /* Free M_lu memory */
+  if (arkdls_mem->M_lu) {
+    SUNMatDestroy(arkdls_mem->M_lu);
+    arkdls_mem->M_lu = NULL;
+  }
+
+  /* Nullify other SUNMatrix pointer */
+  arkdls_mem->M = NULL;
+
+  /* free ARKDls interface structure */
+  free(ark_mem->ark_mass_mem);
+  
+  return(ARKDLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ arkDlsInitializeCounters and arkDlsInitializeMassCounters reset
+ the counters inside the ARKDlsMem and ARKDlsMassMem objects.
+---------------------------------------------------------------*/
 int arkDlsInitializeCounters(ARKDlsMem arkdls_mem)
 {
-  arkdls_mem->d_nje    = 0;
-  arkdls_mem->d_nfeDQ  = 0;
-  arkdls_mem->d_nstlj  = 0;
+  arkdls_mem->nje   = 0;
+  arkdls_mem->nfeDQ = 0;
+  arkdls_mem->nstlj = 0;
   return(0);
 }
 
+
+int arkDlsInitializeMassCounters(ARKDlsMassMem arkdls_mem)
+{
+  arkdls_mem->mass_setups = 0;
+  arkdls_mem->mass_solves = 0;
+  arkdls_mem->mass_mults  = 0;
+  return(0);
+}
+
+
 /*---------------------------------------------------------------
     EOF
 ---------------------------------------------------------------*/
diff --git a/src/arkode/arkode_direct_impl.h b/src/arkode/arkode_direct_impl.h
index 29b1906..19ad7ea 100644
--- a/src/arkode/arkode_direct_impl.h
+++ b/src/arkode/arkode_direct_impl.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,13 +15,15 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Common implementation header file for the ARKDLS linear solvers.
+ * Implementation header file for the ARKDLS linear solver 
+ * interface
  *--------------------------------------------------------------*/
 
 #ifndef _ARKDLS_IMPL_H
 #define _ARKDLS_IMPL_H
 
 #include <arkode/arkode_direct.h>
+#include "arkode_impl.h"
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -44,32 +46,24 @@ extern "C" {
 ---------------------------------------------------------------*/
 typedef struct ARKDlsMemRec {
 
-  int d_type;             /* SUNDIALS_DENSE or SUNDIALS_BAND              */
+  booleantype jacDQ;    /* SUNTRUE if using internal DQ Jacobian approx. */
+  ARKDlsJacFn jac;      /* Jacobian routine to be called                 */
+  void *J_data;         /* user data is passed to jac                    */
 
-  long int d_n;           /* problem dimension                            */
+  SUNLinearSolver LS;   /* generic direct linear solver object           */
 
-  long int d_ml;          /* lower bandwidth of Jacobian                  */
-  long int d_mu;          /* upper bandwidth of Jacobian                  */ 
-  long int d_smu;         /* upper bandwith of M = MIN(N-1,d_mu+d_ml)     */
+  SUNMatrix A;          /* A = M - gamma * df/dy                         */
+  SUNMatrix savedJ;     /* savedJ = old Jacobian                         */
 
-  booleantype d_jacDQ;    /* TRUE if using internal DQ Jacobian approx.   */
-  ARKDlsDenseJacFn d_djac; /* dense Jacobian routine to be called          */
-  ARKDlsBandJacFn d_bjac;  /* band Jacobian routine to be called           */
-  void *d_J_data;         /* user data is passed to djac or bjac          */
-
-  DlsMat d_M;             /* M = I - gamma * df/dy                        */
-  DlsMat d_savedJ;        /* savedJ = old Jacobian                        */
-
-  int *d_pivots;          /* pivots = int pivot array for PM = LU         */
-  long int *d_lpivots;    /* lpivots = long int pivot array for PM = LU   */
-
-  long int  d_nstlj;      /* nstlj = nst at last Jacobian eval.           */
+  N_Vector x;           /* solution vector used by SUNLinearSolver       */
+  
+  long int nstlj;       /* nstlj = nst at last Jacobian eval.            */
 
-  long int d_nje;         /* nje = no. of calls to jac                    */
+  long int nje;         /* nje = no. of calls to jac                     */
 
-  long int d_nfeDQ;       /* no. of calls to f due to DQ Jacobian approx. */
+  long int nfeDQ;       /* no. of calls to f due to DQ Jacobian approx.  */
 
-  long int d_last_flag;   /* last error return flag                       */
+  long int last_flag;   /* last error return flag                        */
   
 } *ARKDlsMem;
 
@@ -81,27 +75,24 @@ typedef struct ARKDlsMemRec {
 ---------------------------------------------------------------*/
 typedef struct ARKDlsMassMemRec {
 
-  int d_type;                /* SUNDIALS_DENSE or SUNDIALS_BAND            */
+  ARKDlsMassFn mass;      /* user-provided mass matrix routine to call  */
 
-  long int d_n;              /* problem dimension                          */
+  SUNLinearSolver LS;     /* generic direct linear solver object        */
 
-  long int d_ml;             /* lower bandwidth of mass matrix             */
-  long int d_mu;             /* upper bandwidth of mass matrix             */ 
-  long int d_smu;            /* upper bandwith of M = MIN(N-1,d_mu+d_ml)   */
+  SUNMatrix M;            /* mass matrix structure                      */
+  SUNMatrix M_lu;         /* mass matrix structure for LU decomposition */
 
-  ARKDlsDenseMassFn d_dmass; /* dense mass matrix routine to be called     */
-  ARKDlsBandMassFn d_bmass;  /* band mass matrix routine to be called      */
-  void *d_M_data;            /* user data is passed to djac or bjac        */
+  N_Vector x;             /* solution vector used by SUNLinearSolver    */
 
-  DlsMat d_M;                /* mass matrix structure                      */
-  DlsMat d_M_lu;             /* mass matrix structure for LU decomposition */
+  booleantype time_dependent;  /* flag stating whether M depends on t   */
+  
+  long int mass_setups;   /* number of mass matrix-solver setup calls   */
 
-  int *d_pivots;             /* pivots = int pivot array for PM = LU       */
-  long int *d_lpivots;       /* lpivots = long int pivot array for PM = LU */
+  long int mass_solves;   /* number of mass matrix solve calls          */
 
-  long int d_nme;            /* nje = no. of calls to mass matrix routine  */
+  long int mass_mults;    /* number of mass matrix product calls        */
 
-  long int d_last_flag;      /* last error return flag                     */
+  long int last_flag;     /* last error return flag                     */
   
 } *ARKDlsMassMem;
 
@@ -109,30 +100,61 @@ typedef struct ARKDlsMassMemRec {
 /*---------------------------------------------------------------
  Prototypes of internal functions
 ---------------------------------------------------------------*/
-int arkDlsDenseDQJac(long int N, realtype t, N_Vector y, 
-                     N_Vector fy, DlsMat Jac, void *data,
-                     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-int arkDlsBandDQJac(long int N, long int mupper, long int mlower,
-                    realtype t, N_Vector y, N_Vector fy, 
-                    DlsMat Jac, void *data, N_Vector tmp1, 
-                    N_Vector tmp2, N_Vector tmp3);
 
-/* Auxilliary functions */
+/* difference-quotient Jacobian approximation routines */
+int arkDlsDQJac(realtype t, N_Vector y, N_Vector fy, 
+                SUNMatrix Jac, void *data, N_Vector tmp1, 
+                N_Vector tmp2, N_Vector tmp3);
+int arkDlsDenseDQJac(realtype t, N_Vector y, N_Vector fy, 
+                     SUNMatrix Jac, ARKodeMem ark_mem, N_Vector tmp1);
+int arkDlsBandDQJac(realtype t, N_Vector y, N_Vector fy, 
+                    SUNMatrix Jac, ARKodeMem ark_mem, N_Vector tmp1, 
+                    N_Vector tmp2);
+
+/* generic linit/lsetup/lsolve/lfree interface routines for ARKode to call */
+int arkDlsInitialize(ARKodeMem ark_mem);
+
+int arkDlsSetup(ARKodeMem ark_mem, int convfail, N_Vector ypred,
+                N_Vector fpred, booleantype *jcurPtr, 
+                N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); 
+
+int arkDlsSolve(ARKodeMem ark_mem, N_Vector b, N_Vector ycur, N_Vector fcur);
 
+int arkDlsFree(ARKodeMem ark_mem);
+
+/* generic minit/msetup/mmult/msolve/mfree routines for ARKode to call */  
+int arkDlsMassInitialize(ARKodeMem ark_mem);
+  
+int arkDlsMassSetup(ARKodeMem ark_mem, N_Vector vtemp1,
+                    N_Vector vtemp2, N_Vector vtemp3); 
+
+int arkDlsMassMult(ARKodeMem ark_mem, N_Vector v, N_Vector Mv);
+
+int arkDlsMassSolve(ARKodeMem ark_mem, N_Vector b);
+
+int arkDlsMassFree(ARKodeMem ark_mem);
+
+/* Auxilliary functions */
 int arkDlsInitializeCounters(ARKDlsMem arkdls_mem);
 
+int arkDlsInitializeMassCounters(ARKDlsMassMem arkdls_mem);
+
 
 /*---------------------------------------------------------------
  Error Messages
 ---------------------------------------------------------------*/
-#define MSGD_ARKMEM_NULL    "Integrator memory is NULL."
-#define MSGD_BAD_NVECTOR    "A required vector operation is not implemented."
-#define MSGD_BAD_SIZES      "Illegal bandwidth parameter(s). Must have 0 <=  ml, mu <= N-1."
-#define MSGD_MEM_FAIL       "A memory request failed."
-#define MSGD_LMEM_NULL      "Linear solver memory is NULL."
-#define MSGD_MASSMEM_NULL   "Mass matrix solver memory is NULL."
-#define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
-#define MSGD_MASSFUNC_FAILED "The mass matrix routine failed in an unrecoverable manner."
+#define MSGD_ARKMEM_NULL         "Integrator memory is NULL."
+#define MSGD_BAD_NVECTOR         "A required vector operation is not implemented."
+#define MSGD_BAD_SIZES           "Illegal bandwidth parameter(s). Must have 0 <=  ml, mu <= N-1."
+#define MSGD_MEM_FAIL            "A memory request failed."
+#define MSGD_LMEM_NULL           "Linear solver memory is NULL."
+#define MSGD_MASSMEM_NULL        "Mass matrix solver memory is NULL."
+#define MSGD_JACFUNC_FAILED      "The Jacobian routine failed in an unrecoverable manner."
+#define MSGD_MASSFUNC_FAILED     "The mass matrix routine failed in an unrecoverable manner."
+#define MSGD_MATCOPY_FAILED      "The SUNMatCopy routine failed in an unrecoverable manner."
+#define MSGD_MATZERO_FAILED      "The SUNMatZero routine failed in an unrecoverable manner."
+#define MSGD_MATSCALEADD_FAILED  "The SUNMatScaleAdd routine failed in an unrecoverable manner."
+#define MSGD_MATSCALEADDI_FAILED "The SUNMatScaleAddI routine failed in an unrecoverable manner."
 
 #ifdef __cplusplus
 }
diff --git a/src/arkode/arkode_impl.h b/src/arkode/arkode_impl.h
index b8bfcf2..9cb9381 100644
--- a/src/arkode/arkode_impl.h
+++ b/src/arkode/arkode_impl.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -229,16 +229,16 @@ typedef struct ARKodeMemRec {
   N_Vector     ark_Vabstol;    /* vector absolute solution tolerance    */
   realtype     ark_SRabstol;   /* scalar absolute residual tolerance    */
   N_Vector     ark_VRabstol;   /* vector absolute residual tolerance    */
-  booleantype  ark_user_efun;  /* TRUE if user sets efun                */
+  booleantype  ark_user_efun;  /* SUNTRUE if user sets efun             */
   ARKEwtFn     ark_efun;       /* function to set ewt                   */
   void        *ark_e_data;     /* user pointer passed to efun           */
-  booleantype  ark_user_rfun;  /* TRUE if user sets rfun                */
+  booleantype  ark_user_rfun;  /* SUNTRUE if user sets rfun             */
   ARKRwtFn     ark_rfun;       /* function to set rwt                   */
   void        *ark_r_data;     /* user pointer passed to rfun           */
-  booleantype  ark_linear;     /* TRUE if fi is linear                  */
-  booleantype  ark_linear_timedep;  /* TRUE if dfi/dy depends on t      */
-  booleantype  ark_explicit;   /* TRUE if fi is disabled                */
-  booleantype  ark_implicit;   /* TRUE if fe is disabled                */
+  booleantype  ark_linear;     /* SUNTRUE if fi is linear               */
+  booleantype  ark_linear_timedep;  /* SUNTRUE if dfi/dy depends on t   */
+  booleantype  ark_explicit;   /* SUNTRUE if fi is disabled             */
+  booleantype  ark_implicit;   /* SUNTRUE if fe is disabled             */
 
   /*-----------------
     Stored RHS arrays
@@ -251,7 +251,7 @@ typedef struct ARKodeMemRec {
     -------------------------*/
   N_Vector ark_ewt;     /* error weight vector                               */
   N_Vector ark_rwt;     /* residual weight vector                            */
-  booleantype ark_rwt_is_ewt;     /* TRUE if rwt is a pointer to ewt         */
+  booleantype ark_rwt_is_ewt;     /* SUNTRUE if rwt is a pointer to ewt      */
   N_Vector ark_y;       /* y is used as temporary storage by the solver
 			   The memory is provided by the user to ARKode
 			   where the vector is named yout.                   */
@@ -376,7 +376,6 @@ typedef struct ARKodeMemRec {
   long int ark_nfe;          /* number of fe calls                         */
   long int ark_nfi;          /* number of fi calls                         */
   long int ark_ncfn;         /* number of corrector convergence failures   */
-  long int ark_nmassfails;   /* number of mass matrix solver failures      */
   long int ark_netf;         /* number of error test failures              */
   long int ark_nni;          /* number of Newton iterations performed      */
   long int ark_nsetups;      /* number of setup calls                      */
@@ -392,10 +391,10 @@ typedef struct ARKodeMemRec {
   /*-----------------------------
     Space requirements for ARKODE 
     -----------------------------*/
-  long int ark_lrw1;        /* no. of realtype words in 1 N_Vector          */ 
-  long int ark_liw1;        /* no. of integer words in 1 N_Vector           */ 
-  long int ark_lrw;         /* no. of realtype words in ARKODE work vectors */
-  long int ark_liw;         /* no. of integer words in ARKODE work vectors  */
+  sunindextype ark_lrw1;        /* no. of realtype words in 1 N_Vector          */ 
+  sunindextype ark_liw1;        /* no. of integer words in 1 N_Vector           */ 
+  long int ark_lrw;             /* no. of realtype words in ARKODE work vectors */
+  long int ark_liw;             /* no. of integer words in ARKODE work vectors  */
 
 
   /*-----------------------
@@ -420,29 +419,24 @@ typedef struct ARKodeMemRec {
   int (*ark_lsetup)(struct ARKodeMemRec *ark_mem, int convfail, N_Vector ypred,
 		    N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
 		    N_Vector vtemp2, N_Vector vtemp3); 
-  int (*ark_lsolve)(struct ARKodeMemRec *ark_mem, N_Vector b, N_Vector weight,
-		    N_Vector ycur, N_Vector fcur);
+  int (*ark_lsolve)(struct ARKodeMemRec *ark_mem, N_Vector b,
+                    N_Vector ycur, N_Vector fcur);
   int (*ark_lfree)(struct ARKodeMemRec *ark_mem);
   void *ark_lmem;
-  int ark_lsolve_type;   /* linear solver type: 0=iterative; 1=dense; 
-                                                2=band; 3=sparse; 4=custom */
+  int ark_lsolve_type;   /* linear solver type: 0=iterative; 1=direct; 2=custom */
 
   /*-----------------------
     Mass Matrix Solver Data 
     -----------------------*/
   booleantype ark_mass_matrix;   /* flag denoting use of a non-identity M  */
-  long int ark_mass_solves;      /* number of mass matrix solve calls      */
-  long int ark_mass_mult;        /* number of mass matrix product calls    */
-  ARKSpilsMassTimesVecFn ark_mtimes;   /* mass-matrix-vector product routine */
-  void *ark_mtimes_data;         /* user pointer passed to mtimes          */
   int (*ark_minit)(struct ARKodeMemRec *ark_mem);
-  int (*ark_msetup)(struct ARKodeMemRec *ark_mem, N_Vector vtemp1, 
+  int (*ark_msetup)(struct ARKodeMemRec *ark_mem, N_Vector vtemp1,
 		    N_Vector vtemp2, N_Vector vtemp3); 
-  int (*ark_msolve)(struct ARKodeMemRec *ark_mem, N_Vector b, N_Vector weight);
+  int (*ark_mmult)(struct ARKodeMemRec *ark_mem, N_Vector v, N_Vector Mv);
+  int (*ark_msolve)(struct ARKodeMemRec *ark_mem, N_Vector b);
   int (*ark_mfree)(struct ARKodeMemRec *ark_mem);
   void *ark_mass_mem;
-  int ark_msolve_type;   /* mass matrix type: 0=iterative; 1=dense; 
-			                      2=band; 3=sparse; 4=custom */
+  int ark_msolve_type;   /* mass matrix type: 0=iterative; 1=direct; 2=custom */
 
   /*------------
     Saved Values
@@ -453,8 +447,6 @@ typedef struct ARKodeMemRec {
   realtype    ark_hold;         /* last successful h value used               */
   booleantype ark_jcur;         /* is Jacobian info. for lin. solver current? */
   realtype    ark_tolsf;        /* tolerance scale factor                     */
-  booleantype ark_setupNonNull; /* does ark_lsetup do anything?               */
-  booleantype ark_MassSetupNonNull; /* does ark_msetup do anything?           */
   booleantype ark_VabstolMallocDone;
   booleantype ark_VRabstolMallocDone;
   booleantype ark_MallocDone;  
@@ -541,11 +533,11 @@ typedef struct ARKodeMemRec {
  int (*ark_linit)(ARKodeMem ark_mem);
 -----------------------------------------------------------------
  The purpose of ark_linit is to complete initializations for a
- specific linear solver, such as counters and statistics.
- An LInitFn should return 0 if it has successfully initialized 
- the ARKODE linear solver and a negative value otherwise.
- If an error does occur, an appropriate message should be sent 
- to the error handler function.
+ specific ARKode linear solver interface, such as counters and 
+ statistics.  An LInitFn should return 0 if it has successfully 
+ initialized the ARKODE linear solver interface and a negative 
+ value otherwise. If an error does occur, an appropriate message 
+ should be sent to the error handler function.
 ---------------------------------------------------------------*/
   
 /*---------------------------------------------------------------
@@ -554,8 +546,8 @@ typedef struct ARKodeMemRec {
 		   booleantype *jcurPtr, N_Vector vtemp1, 
 		   N_Vector vtemp2, N_Vector vtemp3);
  -----------------------------------------------------------------
- The job of ark_lsetup is to prepare the linear solver for
- subsequent calls to ark_lsolve. It may recompute Jacobian-
+ The job of ark_lsetup is to prepare the linear solver interface 
+ for subsequent calls to ark_lsolve. It may recompute Jacobian-
  related data is it deems necessary. Its parameters are as
  follows:
 
@@ -576,12 +568,12 @@ typedef struct ARKodeMemRec {
  fpred - f(tn, ypred).
 
  jcurPtr - a pointer to a boolean to be filled in by ark_lsetup.
-           The function should set *jcurPtr=TRUE if its Jacobian
+           The function should set *jcurPtr=SUNTRUE if its Jacobian
            data is current after the call and should set
-           *jcurPtr=FALSE if its Jacobian data is not current.
+           *jcurPtr=SUNFALSE if its Jacobian data is not current.
            Note: If ark_lsetup calls for re-evaluation of
            Jacobian data (based on convfail and ARKODE state
-           data), it should return *jcurPtr=TRUE always;
+           data), it should return *jcurPtr=SUNTRUE always;
            otherwise an infinite loop can result.
 
  vtemp1 - temporary N_Vector provided for use by ark_lsetup.
@@ -596,25 +588,34 @@ typedef struct ARKodeMemRec {
 ---------------------------------------------------------------*/
 
 /*---------------------------------------------------------------
- int (*ark_lsolve)(ARKodeMem ark_mem, N_Vector b, N_Vector weight,
+ int (*ark_lsolve)(ARKodeMem ark_mem, N_Vector b, 
                    N_Vector ycur, N_Vector fcur);
 -----------------------------------------------------------------
  ark_lsolve must solve the linear equation P x = b, where
  P is some approximation to (M - gamma J), M is the system mass
  matrix, J = (df/dy)(tn,ycur), and the RHS vector b is input. The 
  N-vector ycur contains the solver's current approximation to 
- y(tn) and the vector fcur contains the N_Vector f(tn,ycur). The 
- solution is to be returned in the vector b. ark_lsolve returns 
- a positive value for a recoverable error and a negative value 
- for an unrecoverable error. Success is indicated by a 0 return 
- value.
+ y(tn) and the vector fcur contains the N_Vector f(tn,ycur). 
+
+ Additional vectors that are set within the ARKode memory 
+ structure, and that may be of use within an iterative linear 
+ solver, include:
+
+ ark_ewt - the error weight vector (scaling for solution vector)
+
+ ark_rwt - the residual weight vector (scaling for rhs vector)
+
+ The solution is to be returned in the vector b. ark_lsolve 
+ returns a positive value for a recoverable error and a 
+ negative value for an unrecoverable error. Success is 
+ indicated by a 0 return value.
 ---------------------------------------------------------------*/
 
 /*---------------------------------------------------------------
  int (*ark_lfree)(ARKodeMem ark_mem);
 -----------------------------------------------------------------
  ark_lfree should free up any memory allocated by the linear
- solver. This routine is called once a problem has been
+ solver interface. This routine is called once a problem has been
  completed and the linear solver is no longer needed.  It should 
  return 0 upon success, or a nonzero on failure.
 ---------------------------------------------------------------*/
@@ -625,10 +626,10 @@ typedef struct ARKodeMemRec {
  int (*ark_minit)(ARKodeMem ark_mem);
 -----------------------------------------------------------------
  The purpose of ark_minit is to complete initializations for a
- specific mass matrix linear solver, such as counters and 
- statistics. An function of this type should return 0 if it has 
- successfully initialized the mass matrix linear solver and a 
- negative value otherwise.  If an error does occur, an 
+ specific mass matrix linear solver interface, such as counters 
+ and statistics. An function of this type should return 0 if it 
+ has successfully initialized the mass matrix linear solver and 
+ a negative value otherwise.  If an error does occur, an 
  appropriate message should be sent to the error handler function.
 ---------------------------------------------------------------*/
   
@@ -636,10 +637,10 @@ typedef struct ARKodeMemRec {
  int (*ark_msetup)(ARKodeMem ark_mem, N_Vector vtemp1, 
                    N_Vector vtemp2, N_Vector vtemp3);
  -----------------------------------------------------------------
- The job of ark_msetup is to prepare the mass matrix solver for
- subsequent calls to ark_msolve. It may recompute mass matrix
- related data is it deems necessary. Its parameters are as
- follows:
+ The job of ark_msetup is to prepare the mass matrix solver 
+ interface for subsequent calls to ark_msolve or ark_mmult. It 
+ may recompute mass matrix related data is it deems necessary. 
+ Its parameters are as follows:
 
  ark_mem - problem memory pointer of type ARKodeMem. See the
           typedef earlier in this file.
@@ -655,21 +656,40 @@ typedef struct ARKodeMemRec {
 ---------------------------------------------------------------*/
 
 /*---------------------------------------------------------------
- int (*ark_msolve)(ARKodeMem ark_mem, N_Vector b, N_Vector weight);
+ int (*ark_mmult)(ARKodeMem ark_mem, N_Vector v, N_Vector z);
+-----------------------------------------------------------------
+ ark_mmult must compute the matrix-vector product, z = M*v, 
+ where M is the system mass matrix the vector v is input, and the 
+ vector z is output. The ark_mmult routine returns a positive 
+ value for a recoverable error and a negative value for an 
+ unrecoverable error. Success is indicated by a 0 return value.
+---------------------------------------------------------------*/
+
+/*---------------------------------------------------------------
+ int (*ark_msolve)(ARKodeMem ark_mem, N_Vector b);
 -----------------------------------------------------------------
  ark_msolve must solve the linear equation M x = b, where
  M is the system mass matrix, and the RHS vector b is input. The
- solution is to be returned in the vector b.  The ark_msolve
- routine returns a positive value for a recoverable error and 
- a negative value for an unrecoverable error. Success is 
- indicated by a 0 return value.
+ solution is to be returned in the vector b.  
+
+ Additional vectors that are set within the ARKode memory 
+ structure, and that may be of use within an iterative linear 
+ solver, include:
+
+ ark_ewt - the error weight vector (scaling for solution vector)
+
+ ark_rwt - the residual weight vector (scaling for rhs vector)
+
+ The ark_msolve routine returns a positive value for a 
+ recoverable error and a negative value for an unrecoverable 
+ error. Success is indicated by a 0 return value.
 ---------------------------------------------------------------*/
 
 /*---------------------------------------------------------------
  int (*ark_mfree)(ARKodeMem ark_mem);
 -----------------------------------------------------------------
  ark_mfree should free up any memory allocated by the mass matrix
- solver. This routine is called once a problem has been
+ solver interface. This routine is called once a problem has been
  completed and the solver is no longer needed.  It should return
  0 upon success, or a nonzero on failure.
 ---------------------------------------------------------------*/
@@ -755,7 +775,7 @@ void arkProcessError(ARKodeMem ark_mem, int error_code,
 #define MSGARK_NO_ROOT       "Rootfinding was not initialized."
 
 /* ARKode Error Messages */
-#define MSGARK_LSOLVE_NULL    "The linear solver's solve routine is NULL."
+#define MSGARK_LSOLVE_NULL    "The linear solver object is NULL."
 #define MSGARK_YOUT_NULL      "yout = NULL illegal."
 #define MSGARK_TRET_NULL      "tret = NULL illegal."
 #define MSGARK_BAD_EWT        "Initial ewt has component(s) equal to zero (illegal)."
@@ -792,9 +812,9 @@ void arkProcessError(ARKodeMem ark_mem, int error_code,
 #define MSGARK_MISSING_FI     "Cannot specify that method is explicit without providing a function pointer to fe(t,y)."
 #define MSGARK_MISSING_F      "Cannot specify that method is ImEx without providing function pointers to fi(t,y) and fe(t,y)."
 #define MSGARK_RESIZE_FAIL    "Error in user-supplied resize() function."
+#define MSGARK_MASSSOLVE_NULL "The mass matrix linear solver object is NULL."
 #define MSGARK_MASSINIT_FAIL  "The mass matrix solver's init routine failed."
 #define MSGARK_MASSSETUP_FAIL "The mass matrix solver's setup routine failed."
-#define MSGARK_MASSSOLVE_NULL "The mass matrix solver's solve routine is NULL."
 #define MSGARK_MASSSOLVE_FAIL "The mass matrix solver failed."
 #define MSGARK_MASSFREE_FAIL  "The mass matrixsolver's free routine failed."
 
diff --git a/src/arkode/arkode_io.c b/src/arkode/arkode_io.c
index 7be7adf..9d2c6c6 100644
--- a/src/arkode/arkode_io.c
+++ b/src/arkode/arkode_io.c
@@ -26,6 +26,12 @@
 #include <sundials/sundials_math.h>
 #include <sundials/sundials_types.h>
 
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define RSYM "Lg"
+#else
+#define RSYM "g"
+#endif
+
 
 /*===============================================================
  ARKODE optional input functions
@@ -57,7 +63,7 @@ int ARKodeSetDefaults(void *arkode_mem)
   ark_mem->ark_dense_q          = QDENSE_DEF;     /* dense output order */
   ark_mem->ark_expstab          = arkExpStab;     /* explicit stability fn */
   ark_mem->ark_estab_data       = ark_mem;        /* explicit stability data */
-  ark_mem->ark_fixedstep        = FALSE;          /* default to use adaptive steps */
+  ark_mem->ark_fixedstep        = SUNFALSE;       /* default to use adaptive steps */
   ark_mem->ark_hadapt           = NULL;           /* step adaptivity fn */
   ark_mem->ark_hadapt_data      = NULL;           /* step adaptivity data */
   ark_mem->ark_hadapt_cfl       = CFLFAC;         /* explicit stability factor */
@@ -66,7 +72,7 @@ int ARKodeSetDefaults(void *arkode_mem)
   ark_mem->ark_hadapt_growth    = GROWTH;         /* step adaptivity growth factor */
   ark_mem->ark_hadapt_lbound    = HFIXED_LB;      /* step adaptivity no-change lower bound */
   ark_mem->ark_hadapt_ubound    = HFIXED_UB;      /* step adaptivity no-change upper bound */
-  ark_mem->ark_hadapt_pq        = FALSE;          /* use embedding order */
+  ark_mem->ark_hadapt_pq        = SUNFALSE;       /* use embedding order */
   ark_mem->ark_hadapt_imethod   = 0;              /* PID controller */
   ark_mem->ark_hadapt_k1        = AD0_K1;         /* step adaptivity parameter */
   ark_mem->ark_hadapt_k2        = AD0_K2;         /* step adaptivity parameter */
@@ -77,16 +83,16 @@ int ARKodeSetDefaults(void *arkode_mem)
   ark_mem->ark_ritol            = ARK_SS;         /* scalar-scalar residual tolerances */
   ark_mem->ark_Sabstol          = 1.e-9;          /* solution absolute tolerance */
   ark_mem->ark_SRabstol         = 1.e-9;          /* residual absolute tolerance */
-  ark_mem->ark_user_efun        = FALSE;          /* no user-supplied ewt function */
+  ark_mem->ark_user_efun        = SUNFALSE;       /* no user-supplied ewt function */
   ark_mem->ark_efun             = arkEwtSet;      /* built-in ewt function */
   ark_mem->ark_e_data           = NULL;           /* ewt function data */
-  ark_mem->ark_user_rfun        = FALSE;          /* no user-supplied rwt function */
+  ark_mem->ark_user_rfun        = SUNFALSE;       /* no user-supplied rwt function */
   ark_mem->ark_rfun             = arkRwtSet;      /* built-in rwt function */
   ark_mem->ark_e_data           = NULL;           /* rwt function data */
-  ark_mem->ark_linear           = FALSE;          /* nonlinear problem */
-  ark_mem->ark_linear_timedep   = TRUE;           /* dfi/dy depends on t */
-  ark_mem->ark_explicit         = FALSE;          /* fi(t,y) will be used */
-  ark_mem->ark_implicit         = FALSE;          /* fe(t,y) will be used */
+  ark_mem->ark_linear           = SUNFALSE;       /* nonlinear problem */
+  ark_mem->ark_linear_timedep   = SUNTRUE;        /* dfi/dy depends on t */
+  ark_mem->ark_explicit         = SUNFALSE;       /* fi(t,y) will be used */
+  ark_mem->ark_implicit         = SUNFALSE;       /* fe(t,y) will be used */
   ark_mem->ark_ehfun            = arkErrHandler;  /* default error handler fn */
   ark_mem->ark_eh_data          = ark_mem;        /* error handler data */
   ark_mem->ark_errfp            = stderr;         /* output stream for errors */
@@ -95,7 +101,7 @@ int ARKodeSetDefaults(void *arkode_mem)
   ark_mem->ark_hin              = ZERO;           /* determine initial step on-the-fly */
   ark_mem->ark_hmin             = ZERO;           /* no minimum step size */
   ark_mem->ark_hmax_inv         = ZERO;           /* no maximum step size */
-  ark_mem->ark_tstopset         = FALSE;          /* no stop time set */
+  ark_mem->ark_tstopset         = SUNFALSE;       /* no stop time set */
   ark_mem->ark_tstop            = ZERO;           /* no fixed stop time */
   ark_mem->ark_maxcor           = MAXCOR;         /* max nonlinear iters/stage */
   ark_mem->ark_maxnef           = MAXNEF;         /* max error test fails */
@@ -109,10 +115,10 @@ int ARKodeSetDefaults(void *arkode_mem)
   ark_mem->ark_rdiv             = RDIV;           /* nonlinear divergence tolerance */
   ark_mem->ark_dgmax            = DGMAX;          /* max step change before recomputing J or P */
   ark_mem->ark_msbp             = MSBP;           /* max steps between updates to J or P */
-  ark_mem->ark_use_fp           = FALSE;          /* use Newton solver */
+  ark_mem->ark_use_fp           = SUNFALSE;       /* use Newton solver */
   ark_mem->ark_fp_m             = FP_ACCEL_M;     /* num Anderson acceleration vectors */
   ark_mem->ark_diagfp           = NULL;           /* no solver diagnostics file */
-  ark_mem->ark_report           = FALSE;          /* don't report solver diagnostics */
+  ark_mem->ark_report           = SUNFALSE;       /* don't report solver diagnostics */
   ark_mem->ark_stages           = 0;              /* no stages */
   ark_mem->ark_istage           = 0;              /* current stage */
   for (i=0; i<ARK_S_MAX; i++) {                   /* no Butcher table */
@@ -385,9 +391,9 @@ int ARKodeSetDiagnostics(void *arkode_mem, FILE *diagfp)
 
   ark_mem->ark_diagfp = diagfp;
   if (diagfp != NULL) {
-    ark_mem->ark_report = TRUE;
+    ark_mem->ark_report = SUNTRUE;
   } else {
-    ark_mem->ark_report = FALSE;
+    ark_mem->ark_report = SUNFALSE;
   }
 
   return(ARK_SUCCESS);
@@ -511,7 +517,7 @@ int ARKodeSetLinear(void *arkode_mem, int timedepend)
   }
 
   ark_mem = (ARKodeMem) arkode_mem;
-  ark_mem->ark_linear = TRUE;
+  ark_mem->ark_linear = SUNTRUE;
   ark_mem->ark_linear_timedep = (timedepend == 1);
   ark_mem->ark_dgmax = RCONST(100.0)*UNIT_ROUNDOFF;
 
@@ -536,8 +542,8 @@ int ARKodeSetNonlinear(void *arkode_mem)
   }
 
   ark_mem = (ARKodeMem) arkode_mem;
-  ark_mem->ark_linear = FALSE;
-  ark_mem->ark_linear_timedep = TRUE;
+  ark_mem->ark_linear = SUNFALSE;
+  ark_mem->ark_linear_timedep = SUNTRUE;
   ark_mem->ark_dgmax = DGMAX;
 
   return(ARK_SUCCESS);
@@ -563,7 +569,7 @@ int ARKodeSetFixedPoint(void *arkode_mem, long int fp_m)
   }
 
   ark_mem = (ARKodeMem) arkode_mem;
-  ark_mem->ark_use_fp = TRUE;
+  ark_mem->ark_use_fp = SUNTRUE;
   if (fp_m < 0) {
     ark_mem->ark_fp_m = FP_ACCEL_M;
   } else {
@@ -591,7 +597,7 @@ int ARKodeSetNewton(void *arkode_mem)
   }
 
   ark_mem = (ARKodeMem) arkode_mem;
-  ark_mem->ark_use_fp = FALSE;
+  ark_mem->ark_use_fp = SUNFALSE;
 
   return(ARK_SUCCESS);
 }
@@ -621,8 +627,8 @@ int ARKodeSetExplicit(void *arkode_mem)
   }
 
   /* set the relevant parameters */
-  ark_mem->ark_explicit = TRUE;
-  ark_mem->ark_implicit = FALSE;
+  ark_mem->ark_explicit = SUNTRUE;
+  ark_mem->ark_implicit = SUNFALSE;
 
   return(ARK_SUCCESS);
 }
@@ -652,8 +658,8 @@ int ARKodeSetImplicit(void *arkode_mem)
   }
 
   /* set the relevant parameters */
-  ark_mem->ark_implicit = TRUE;
-  ark_mem->ark_explicit = FALSE;
+  ark_mem->ark_implicit = SUNTRUE;
+  ark_mem->ark_explicit = SUNFALSE;
 
   return(ARK_SUCCESS);
 }
@@ -688,8 +694,8 @@ int ARKodeSetImEx(void *arkode_mem)
   }
 
   /* set the relevant parameters */
-  ark_mem->ark_explicit = FALSE;
-  ark_mem->ark_implicit = FALSE;
+  ark_mem->ark_explicit = SUNFALSE;
+  ark_mem->ark_implicit = SUNFALSE;
 
   return(ARK_SUCCESS);
 }
@@ -757,7 +763,7 @@ int ARKodeSetERKTable(void *arkode_mem, int s, int q, int p,
 
   /* set embedding (if applicable), otherwise set as fixed-step method */
   if (bembed == NULL) {
-    ark_mem->ark_fixedstep = TRUE;
+    ark_mem->ark_fixedstep = SUNTRUE;
   } else {
     for (i=0; i<s; i++) 
       ark_mem->ark_b2e[i] = bembed[i];
@@ -836,7 +842,7 @@ int ARKodeSetIRKTable(void *arkode_mem, int s, int q, int p,
 
   /* set embedding (if applicable), otherwise set as fixed-step method */
   if (bembed == NULL) {
-    ark_mem->ark_fixedstep = TRUE;
+    ark_mem->ark_fixedstep = SUNTRUE;
   } else {
     for (i=0; i<s; i++) 
       ark_mem->ark_b2i[i] = bembed[i];
@@ -927,7 +933,7 @@ int ARKodeSetARKTables(void *arkode_mem, int s, int q, int p,
 
   /* set embeddings (if applicable), otherwise set as fixed-step method */
   if ((b2e == NULL) || (b2i == NULL)) {
-    ark_mem->ark_fixedstep = TRUE;
+    ark_mem->ark_fixedstep = SUNTRUE;
   } else {
     for (i=0; i<s; i++) {
       ark_mem->ark_b2e[i] = b2e[i];
@@ -1311,7 +1317,7 @@ int ARKodeSetStopTime(void *arkode_mem, realtype tstop)
   }
 
   ark_mem->ark_tstop    = tstop;
-  ark_mem->ark_tstopset = TRUE;
+  ark_mem->ark_tstopset = SUNTRUE;
 
   return(ARK_SUCCESS);
 }
@@ -1343,10 +1349,10 @@ int ARKodeSetFixedStep(void *arkode_mem, realtype hfixed)
 
   /* set ark_mem entry */
   if (hfixed != ZERO) {
-    ark_mem->ark_fixedstep = TRUE;
+    ark_mem->ark_fixedstep = SUNTRUE;
     ark_mem->ark_hin = hfixed;
   } else {
-    ark_mem->ark_fixedstep = FALSE;
+    ark_mem->ark_fixedstep = SUNFALSE;
   }
     
   return(ARK_SUCCESS);
@@ -2237,48 +2243,6 @@ int ARKodeGetNumLinSolvSetups(void *arkode_mem, long int *nlinsetups)
 
 
 /*---------------------------------------------------------------
- ARKodeGetNumMassSolves:
-
- Returns the current number of calls to the mass matrix solver.
----------------------------------------------------------------*/
-int ARKodeGetNumMassSolves(void *arkode_mem, long int *nMassSolves)
-{
-  ARKodeMem ark_mem;
-  if (arkode_mem==NULL) {
-    arkProcessError(NULL, ARK_MEM_NULL, "ARKODE", 
-		    "ARKodeGetNumMassSolves", MSGARK_NO_MEM);
-    return(ARK_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  *nMassSolves = ark_mem->ark_mass_solves;
-
-  return(ARK_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKodeGetNumMassMultiplies:
-
- Returns the current number of calls to the mass matrix product.
----------------------------------------------------------------*/
-int ARKodeGetNumMassMultiplies(void *arkode_mem, long int *nMassMult)
-{
-  ARKodeMem ark_mem;
-  if (arkode_mem==NULL) {
-    arkProcessError(NULL, ARK_MEM_NULL, "ARKODE", 
-		    "ARKodeGetNumMassMult", MSGARK_NO_MEM);
-    return(ARK_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  *nMassMult = ark_mem->ark_mass_mult;
-
-  return(ARK_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
  ARKodeGetNumErrTestFails:
 
  Returns the current number of error test failures
@@ -2453,7 +2417,7 @@ int ARKodeGetTolScaleFactor(void *arkode_mem, realtype *tolsfact)
 /*---------------------------------------------------------------
  ARKodeGetErrWeights:
 
- This routine returns the current weight vector.
+ This routine returns the current error weight vector.
 ---------------------------------------------------------------*/
 int ARKodeGetErrWeights(void *arkode_mem, N_Vector eweight)
 {
@@ -2472,6 +2436,27 @@ int ARKodeGetErrWeights(void *arkode_mem, N_Vector eweight)
 
 
 /*---------------------------------------------------------------
+ ARKodeGetResWeights:
+
+ This routine returns the current residual weight vector.
+---------------------------------------------------------------*/
+int ARKodeGetResWeights(void *arkode_mem, N_Vector rweight)
+{
+  ARKodeMem ark_mem;
+  if (arkode_mem==NULL) {
+    arkProcessError(NULL, ARK_MEM_NULL, "ARKODE", 
+		    "ARKodeGetResWeights", MSGARK_NO_MEM);
+    return(ARK_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+
+  N_VScale(ONE, ark_mem->ark_rwt, rweight);
+
+  return(ARK_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
  ARKodeGetEstLocalErrors: (updated to the correct vector, but 
    need to verify that it is unchanged between filling the 
    estimated error and the end of the time step)
@@ -2810,14 +2795,14 @@ int ARKodeWriteParameters(void *arkode_mem, FILE *fp)
   } else {
     if (ark_mem->ark_hadapt == NULL) {
       fprintf(fp, "  Time step adaptivity method %i\n", ark_mem->ark_hadapt_imethod);
-      fprintf(fp, "     Safety factor = %g\n", ark_mem->ark_hadapt_safety);
-      fprintf(fp, "     Bias factor = %g\n", ark_mem->ark_hadapt_bias);
-      fprintf(fp, "     Growth factor = %g\n", ark_mem->ark_hadapt_growth);
-      fprintf(fp, "     Step growth lower bound = %g\n", ark_mem->ark_hadapt_lbound);
-      fprintf(fp, "     Step growth upper bound = %g\n", ark_mem->ark_hadapt_ubound);
-      fprintf(fp, "     k1 = %g\n", ark_mem->ark_hadapt_k1);
-      fprintf(fp, "     k2 = %g\n", ark_mem->ark_hadapt_k2);
-      fprintf(fp, "     k3 = %g\n", ark_mem->ark_hadapt_k3);
+      fprintf(fp, "     Safety factor = %"RSYM"\n", ark_mem->ark_hadapt_safety);
+      fprintf(fp, "     Bias factor = %"RSYM"\n", ark_mem->ark_hadapt_bias);
+      fprintf(fp, "     Growth factor = %"RSYM"\n", ark_mem->ark_hadapt_growth);
+      fprintf(fp, "     Step growth lower bound = %"RSYM"\n", ark_mem->ark_hadapt_lbound);
+      fprintf(fp, "     Step growth upper bound = %"RSYM"\n", ark_mem->ark_hadapt_ubound);
+      fprintf(fp, "     k1 = %"RSYM"\n", ark_mem->ark_hadapt_k1);
+      fprintf(fp, "     k2 = %"RSYM"\n", ark_mem->ark_hadapt_k2);
+      fprintf(fp, "     k3 = %"RSYM"\n", ark_mem->ark_hadapt_k3);
     } else {
       fprintf(fp, "  User provided time step adaptivity function\n");
     }
@@ -2825,9 +2810,9 @@ int ARKodeWriteParameters(void *arkode_mem, FILE *fp)
   if (ark_mem->ark_itol == ARK_WF) {
     fprintf(fp, "  User provided error weight function\n");
   } else {
-    fprintf(fp, "  Solver relative tolerance = %g\n", ark_mem->ark_reltol);
+    fprintf(fp, "  Solver relative tolerance = %"RSYM"\n", ark_mem->ark_reltol);
     if (ark_mem->ark_itol == ARK_SS) {
-      fprintf(fp, "  Solver absolute tolerance = %g\n", ark_mem->ark_Sabstol);
+      fprintf(fp, "  Solver absolute tolerance = %"RSYM"\n", ark_mem->ark_Sabstol);
     } else {
       fprintf(fp, "  Vector-valued solver absolute tolerance\n");
     }
@@ -2837,24 +2822,24 @@ int ARKodeWriteParameters(void *arkode_mem, FILE *fp)
       fprintf(fp, "  User provided residual weight function\n");
     } else {
       if (ark_mem->ark_ritol == ARK_SS) {
-	fprintf(fp, "  Absolute residual tolerance = %g\n", ark_mem->ark_SRabstol);
+	fprintf(fp, "  Absolute residual tolerance = %"RSYM"\n", ark_mem->ark_SRabstol);
       } else {
 	fprintf(fp, "  Vector-valued residual absolute tolerance\n");
       }
     }
   }
   if (ark_mem->ark_hin != ZERO)  
-    fprintf(fp, "  Initial step size = %g\n",ark_mem->ark_hin);
+    fprintf(fp, "  Initial step size = %"RSYM"\n",ark_mem->ark_hin);
   if (ark_mem->ark_hmin != ZERO)  
-    fprintf(fp, "  Minimum step size = %g\n",ark_mem->ark_hmin);
+    fprintf(fp, "  Minimum step size = %"RSYM"\n",ark_mem->ark_hmin);
   if (ark_mem->ark_hmax_inv != ZERO)  
-    fprintf(fp, "  Maximum step size = %g\n",ONE/ark_mem->ark_hmax_inv);
+    fprintf(fp, "  Maximum step size = %"RSYM"\n",ONE/ark_mem->ark_hmax_inv);
   fprintf(fp, "  Maximum number of error test failures = %i\n",ark_mem->ark_maxnef);
   fprintf(fp, "  Maximum number of convergence test failures = %i\n",ark_mem->ark_maxncf);
-  fprintf(fp, "  Maximum step increase (first step) = %g\n",ark_mem->ark_etamx1);
-  fprintf(fp, "  Step reduction factor on multiple error fails = %g\n",ark_mem->ark_etamxf);
+  fprintf(fp, "  Maximum step increase (first step) = %"RSYM"\n",ark_mem->ark_etamx1);
+  fprintf(fp, "  Step reduction factor on multiple error fails = %"RSYM"\n",ark_mem->ark_etamxf);
   fprintf(fp, "  Minimum error fails before above factor is used = %i\n",ark_mem->ark_small_nef);
-  fprintf(fp, "  Step reduction factor on nonlinear convergence failure = %g\n",ark_mem->ark_etacf);
+  fprintf(fp, "  Step reduction factor on nonlinear convergence failure = %"RSYM"\n",ark_mem->ark_etacf);
 
   if (!ark_mem->ark_implicit) {
     if (ark_mem->ark_expstab == arkExpStab) {
@@ -2862,15 +2847,15 @@ int ARKodeWriteParameters(void *arkode_mem, FILE *fp)
     } else {
       fprintf(fp, "  User provided explicit stability function\n");
     }
-    fprintf(fp, "  Explicit safety factor = %g\n",ark_mem->ark_hadapt_cfl);
+    fprintf(fp, "  Explicit safety factor = %"RSYM"\n",ark_mem->ark_hadapt_cfl);
   }
   if (!ark_mem->ark_explicit) {
     fprintf(fp, "  Implicit predictor method = %i\n",ark_mem->ark_predictor);
-    fprintf(fp, "  Implicit solver tolerance coefficient = %g\n",ark_mem->ark_nlscoef);
+    fprintf(fp, "  Implicit solver tolerance coefficient = %"RSYM"\n",ark_mem->ark_nlscoef);
     fprintf(fp, "  Maximum number of nonlinear corrections = %i\n",ark_mem->ark_maxcor);
-    fprintf(fp, "  Nonlinear convergence rate constant = %g\n",ark_mem->ark_crdown);
-    fprintf(fp, "  Nonlinear divergence tolerance = %g\n",ark_mem->ark_rdiv);
-    fprintf(fp, "  Gamma factor LSetup tolerance = %g\n",ark_mem->ark_dgmax);
+    fprintf(fp, "  Nonlinear convergence rate constant = %"RSYM"\n",ark_mem->ark_crdown);
+    fprintf(fp, "  Nonlinear divergence tolerance = %"RSYM"\n",ark_mem->ark_rdiv);
+    fprintf(fp, "  Gamma factor LSetup tolerance = %"RSYM"\n",ark_mem->ark_dgmax);
     fprintf(fp, "  Number of steps between LSetup calls = %i\n",ark_mem->ark_msbp);
   }
   fprintf(fp, "\n");
@@ -2900,35 +2885,35 @@ int ARKodeWriteButcher(void *arkode_mem, FILE *fp)
   if (!ark_mem->ark_implicit) {
     fprintf(fp, "  Explicit Butcher table:\n");
     for (i=0; i<ark_mem->ark_stages; i++) {
-      fprintf(fp, "     %.5f",ark_mem->ark_ce[i]);
+      fprintf(fp, "     %"RSYM"",ark_mem->ark_ce[i]);
       for (j=0; j<ark_mem->ark_stages; j++) 
-	fprintf(fp, " %.5f",ARK_A(ark_mem->ark_Ae,i,j));
+	fprintf(fp, " %"RSYM"",ARK_A(ark_mem->ark_Ae,i,j));
       fprintf(fp,"\n");
     }
     fprintf(fp, "            ");
     for (j=0; j<ark_mem->ark_stages; j++) 
-      fprintf(fp, " %.5f",ark_mem->ark_be[j]);
+      fprintf(fp, " %"RSYM"",ark_mem->ark_be[j]);
     fprintf(fp,"\n");
     fprintf(fp, "            ");
     for (j=0; j<ark_mem->ark_stages; j++) 
-      fprintf(fp, " %.5f",ark_mem->ark_b2e[j]);
+      fprintf(fp, " %"RSYM"",ark_mem->ark_b2e[j]);
     fprintf(fp,"\n");
   }
   if (!ark_mem->ark_explicit) {
     fprintf(fp, "  Implicit Butcher table:\n");
     for (i=0; i<ark_mem->ark_stages; i++) {
-      fprintf(fp, "     %.5f",ark_mem->ark_ci[i]);
+      fprintf(fp, "     %"RSYM"",ark_mem->ark_ci[i]);
       for (j=0; j<ark_mem->ark_stages; j++) 
-	fprintf(fp, " %.5f",ARK_A(ark_mem->ark_Ai,i,j));
+	fprintf(fp, " %"RSYM"",ARK_A(ark_mem->ark_Ai,i,j));
       fprintf(fp,"\n");
     }
     fprintf(fp, "            ");
     for (j=0; j<ark_mem->ark_stages; j++) 
-      fprintf(fp, " %.5f",ark_mem->ark_bi[j]);
+      fprintf(fp, " %"RSYM"",ark_mem->ark_bi[j]);
     fprintf(fp,"\n");
     fprintf(fp, "            ");
     for (j=0; j<ark_mem->ark_stages; j++) 
-      fprintf(fp, " %.5f",ark_mem->ark_b2i[j]);
+      fprintf(fp, " %"RSYM"",ark_mem->ark_b2i[j]);
     fprintf(fp,"\n");
   }
   fprintf(fp, "\n");
diff --git a/src/arkode/arkode_klu.c b/src/arkode/arkode_klu.c
deleted file mode 100644
index 5102ac6..0000000
--- a/src/arkode/arkode_klu.c
+++ /dev/null
@@ -1,1275 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Implementation file for the ARKKLU linear solver module.
- *---------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "arkode/arkode_klu.h"
-#include "arkode/arkode_sparse.h"
-#include "arkode_sparse_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_klu_impl.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ONE RCONST(1.0)
-#define TWO RCONST(2.0)
-#define TWOTHIRDS    RCONST(0.6666666666666667)
-
-/* ARKKLU linit, lsetup, lsolve, and lfree routines */
-static int arkKLUInit(ARKodeMem ark_mem);
-static int arkKLUSetup(ARKodeMem ark_mem, int convfail, 
-		       N_Vector ypred, N_Vector fpred, 
-		       booleantype *jcurPtr, N_Vector tmp1, 
-		       N_Vector tmp2, N_Vector tmp3);
-static int arkKLUSolve(ARKodeMem ark_mem, N_Vector b, 
-		       N_Vector weight, N_Vector ycur, 
-		       N_Vector fcur);
-static int arkKLUFree(ARKodeMem ark_mem);
-
-/* ARKKLU minit, msetup, msolve, mfree and mtimes routines */
-static int arkMassKLUInit(ARKodeMem ark_mem);
-static int arkMassKLUSetup(ARKodeMem ark_mem, N_Vector tmp1, 
-			   N_Vector tmp2, N_Vector tmp3);
-static int arkMassKLUSolve(ARKodeMem ark_mem, N_Vector b, 
-			   N_Vector weight);
-static int arkMassKLUFree(ARKodeMem ark_mem);
-static int arkMassKLUMultiply(N_Vector v, N_Vector Mv, 
-			      realtype t, void *arkode_mem);
-
-
-/*---------------------------------------------------------------
- ARKKLU
-
- This routine initializes the memory record and sets various 
- function fields specific to the ARKode / KLU linear solver 
- module.  ARKKLU first calls the existing lfree routine if this 
- is not NULL.  Then it sets the ark_linit, ark_lsetup, ark_lsolve
- and ark_lfree fields in (*arkode_mem) to be arkKLUInit, 
- arkKLUSetup, arkKLUSolve and arkKLUFree, respectively.   It 
- allocates memory for a structure of type ARKSlsMemRec and sets 
- the ark_lmem field in (*arkode_mem) to the address of this 
- structure.  It sets setupNonNull in (*arkode_mem) to TRUE.  
- Finally, it allocates memory for KLU.  The return value is 
- ARKSLS_SUCCESS = 0, ARKSLS_LMEM_FAIL = -1, or 
- ARKSLS_ILL_INPUT = -2.
-
- NOTE: The KLU linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKKLU will first 
-       test for a compatible N_Vector internal representation
-       by checking that the function N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-int ARKKLU(void *arkode_mem, int n, int nnz, int sparsetype)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-  KLUData klu_data;
-  int flag;
-
-  /* Return immediately if ark_mem is NULL. */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-                    "ARKKLU", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKSLS_ILL_INPUT, "ARKSLS", 
-                    "ARKKLU", MSGSP_BAD_NVECTOR);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem. */
-  ark_mem->ark_linit  = arkKLUInit;
-  ark_mem->ark_lsetup = arkKLUSetup;
-  ark_mem->ark_lsolve = arkKLUSolve;
-  ark_mem->ark_lfree  = arkKLUFree;
-  ark_mem->ark_lsolve_type = 3;
-
-  /* Get memory for ARKSlsMemRec. */
-  arksls_mem = (ARKSlsMem) malloc(sizeof(struct ARKSlsMemRec));
-  if (arksls_mem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKKLU", MSGSP_MEM_FAIL);
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Get memory for KLUData. */
-  klu_data = (KLUData) malloc(sizeof(struct KLUDataRec));
-  if (klu_data == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKKLU", MSGSP_MEM_FAIL);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Initialize Jacobian-related data */
-  arksls_mem->s_Jeval = NULL;
-  arksls_mem->s_Jdata = NULL;
-  ark_mem->ark_setupNonNull = TRUE;
-  arksls_mem->sparsetype = sparsetype;
-
-  /* Initialize counters */
-  arksls_mem->s_nje = 0;
-  arksls_mem->s_first_factorize = 1;
-  arksls_mem->s_nstlj = 0;
-
-  /* Allocate memory for the sparse Jacobian */
-  arksls_mem->s_A = NULL;
-  arksls_mem->s_A = SparseNewMat(n, n, nnz, sparsetype);
-  if (arksls_mem->s_A == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKKLU", MSGSP_MEM_FAIL);
-    free(klu_data); klu_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Allocate memory for saved sparse Jacobian */
-  arksls_mem->s_savedJ = NULL;
-  arksls_mem->s_savedJ = SparseNewMat(n, n, nnz, sparsetype);
-  if (arksls_mem->s_savedJ == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKKLU", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_A);
-    free(klu_data); klu_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Initialize KLU structures */
-  switch (sparsetype) {
-    case CSC_MAT:
-      klu_data->sun_klu_solve = &klu_solve;
-      break;
-    case CSR_MAT:
-      klu_data->sun_klu_solve = &klu_tsolve;
-      break;
-    default:
-      SparseDestroyMat(arksls_mem->s_A);
-      SparseDestroyMat(arksls_mem->s_savedJ);
-      free(klu_data); klu_data = NULL;
-      free(arksls_mem); arksls_mem = NULL;
-      return(ARKSLS_ILL_INPUT);
-  }
-  klu_data->s_Symbolic = NULL;
-  klu_data->s_Numeric = NULL;
-
-  /* Set default parameters for KLU */
-  flag = klu_defaults(&klu_data->s_Common);
-  if (flag == 0) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKKLU", MSGSP_MEM_FAIL);
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    free(klu_data->s_Numeric);  klu_data->s_Numeric = NULL;
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    free(klu_data->s_Symbolic);  klu_data->s_Symbolic = NULL;
-    SparseDestroyMat(arksls_mem->s_A);
-    SparseDestroyMat(arksls_mem->s_savedJ);
-    free(klu_data); klu_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Set ordering to COLAMD as the arkode default use.
-     Users can set a different value with ARKKLUSetOrdering,
-     and the user-set value is loaded before any call to klu_analyze in
-     ARKKLUSetup.  */
-  klu_data->s_ordering = 1;
-  klu_data->s_Common.ordering = klu_data->s_ordering;
-
-  /* Attach linear solver memory to the integrator memory */
-  arksls_mem->s_solver_data = (void *) klu_data;
-  ark_mem->ark_lmem = arksls_mem;
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
-  ARKKLUReInit
-
-  This routine reinitializes memory and flags for a new 
-  factorization (symbolic and numeric) to be conducted at the 
-  next solver setup call.  This routine is useful in the cases 
-  where the number of nonzeroes has changed or if the structure 
-  of the linear system has changed which would require a new 
-  symbolic (and numeric) factorization.
- 
-  The reinit_type argument governs the level of reinitialization:
- 
-  reinit_type = 1: The Jacobian matrix will be destroyed and 
-                   a new one will be allocated based on the nnz
-                   value passed to this call. New symbolic and
-                   numeric factorizations will be completed at the 
-                   next solver setup.
- 
-  reinit_type = 2: Only symbolic and numeric factorizations will be 
-                   completed.  It is assumed that the Jacobian size
-                   has not exceeded the size of nnz given in the 
-                   prior call to ARKMassKLU.
- 
-  This routine assumes no other changes to solver use are necessary.
- 
-  The return value is ARKSLS_SUCCESS = 0, ARKSLS_MEM_NULL = -1, 
-  ARKSLS_MASSMEM_NULL = -8, ARKSLS_ILL_INPUT = -3, or 
-  ARKSLS_MEM_FAIL = -4.
----------------------------------------------------------------*/
-int ARKKLUReInit(void *arkode_mem, int n, int nnz, int reinit_type)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if arkode_mem is NULL. */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", "ARKKLUReInit", 
-		    MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Return immediately if ark_lmem is NULL. */
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(NULL, ARKSLS_LMEM_NULL, "ARKSLS", "ARKKLUReInit", 
-		    MSGSP_LMEM_NULL);
-    return(ARKSLS_LMEM_NULL);
-  }
-
-  arksls_mem = (ARKSlsMem) (ark_mem->ark_lmem);
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  /* Return if reinit_type is not valid */
-  if ((reinit_type != 1) && (reinit_type != 2)) {
-    arkProcessError(NULL, ARKSLS_ILL_INPUT, "ARKSLS", "ARKKLUReInit", 
-		    MSGSP_ILL_INPUT);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  if (reinit_type == 1) {
-
-    /* Destroy previous Jacobian information */
-    if (arksls_mem->s_A) {
-      SparseDestroyMat(arksls_mem->s_A);
-    }
-
-    /* Allocate memory for the sparse Jacobian */
-    arksls_mem->s_A = SparseNewMat(n, n, nnz, arksls_mem->sparsetype);
-    if (arksls_mem->s_A == NULL) {
-      arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", "ARKKLU", 
-		    MSGSP_MEM_FAIL);
-      return(ARKSLS_MEM_FAIL);
-    }
-  }
-
-  /* Free the prior factorazation and reset for first factorization */
-  if( klu_data->s_Symbolic != NULL)
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  if( klu_data->s_Numeric != NULL)
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  arksls_mem->s_first_factorize = 1;
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-
-  return(0);
-}
-
-/*---------------------------------------------------------------
- arkKLUInit:
-
- This routine does remaining initializations specific to the 
- ARKKLU linear solver module.  It returns 0 if successful.
----------------------------------------------------------------*/
-static int arkKLUInit(ARKodeMem ark_mem)
-{
-  ARKSlsMem arksls_mem;
-
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-
-  arksls_mem->s_Jdata = ark_mem->ark_user_data;
-
-  arksls_mem->s_nje = 0;
-  /* Force factorization every call to ARKODE */
-  arksls_mem->s_first_factorize = 1;
-  arksls_mem->s_nstlj = 0;
-
-  arksls_mem->s_last_flag = 0;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkKLUSetup:
-
-  This routine does the setup operations for the ARKKLU linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     ARKSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
----------------------------------------------------------------*/
-static int arkKLUSetup(ARKodeMem ark_mem, int convfail, 
-		       N_Vector ypred, N_Vector fpred, 
-		       booleantype *jcurPtr, N_Vector vtemp1, 
-		       N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  ARKSlsMem arksls_mem;
-  ARKSlsMassMem arksls_mass_mem;
-  KLUData klu_data;
-  int retval;
-
-  realtype uround_twothirds;
-  
-  uround_twothirds = SUNRpowerR(ark_mem->ark_uround,TWOTHIRDS);
-
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-  
-  /* Check that Jacobian eval routine is set */
-  if (arksls_mem->s_Jeval == NULL) {
-    arkProcessError(ark_mem, ARKSLS_JAC_NOSET, "ARKSLS", 
-		    "arkKLUSetup", MSGSP_JAC_NOSET);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_JAC_NOSET);
-  }
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arksls_mem->s_nstlj + ARKS_MSBJ) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKS_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  jok = !jbad;
-  
-  /* If jok = TRUE, use saved copy of J */
-  if (jok) {
-    *jcurPtr = FALSE;
-    SparseCopyMat(arksls_mem->s_savedJ, arksls_mem->s_A);
-
-  /* If jok = FALSE, call jac routine for new J value */
-  } else {
-    arksls_mem->s_nje++;
-    arksls_mem->s_nstlj = ark_mem->ark_nst;
-    *jcurPtr = TRUE;
-    SparseSetMatToZero(arksls_mem->s_A);
-
-    retval = arksls_mem->s_Jeval(ark_mem->ark_tn, ypred, fpred, 
-				 arksls_mem->s_A, arksls_mem->s_Jdata, 
-				 vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKSLS_JACFUNC_UNRECVR, "ARKSLS", 
-		      "arkKLUSetup", MSGSP_JACFUNC_FAILED);
-      arksls_mem->s_last_flag = ARKSLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arksls_mem->s_last_flag = ARKSLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    SparseCopyMat(arksls_mem->s_A, arksls_mem->s_savedJ);
-  }
-
-  /* Scale J by -gamma */
-  SparseScaleMat(-ark_mem->ark_gamma, arksls_mem->s_A);
-
-  /* Add mass matrix to get A = M-gamma*J */
-  if (ark_mem->ark_mass_matrix) {
-
-    /* Compute mass matrix */
-    arksls_mass_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-    SparseSetMatToZero(arksls_mass_mem->s_M);
-    retval = arksls_mass_mem->s_Meval(ark_mem->ark_tn, 
-				      arksls_mass_mem->s_M, 
-				      arksls_mass_mem->s_Mdata, 
-				      vtemp1, vtemp2, vtemp3);
-    arksls_mass_mem->s_nme++;
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKSLS_MASSFUNC_UNRECVR, "ARKSLS", 
-		      "arkKLUSetup",  MSGSP_MASSFUNC_FAILED);
-      arksls_mem->s_last_flag = ARKSLS_MASSFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arksls_mem->s_last_flag = ARKSLS_MASSFUNC_RECVR;
-      return(1);
-    }
-    
-    /* add to A */
-    retval = SparseAddMat(arksls_mem->s_A, arksls_mass_mem->s_M);
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "arkKLUSetup",  "Error in adding mass matrix to Jacobian");
-      arksls_mem->s_last_flag = ARKSLS_PACKAGE_FAIL;
-      return(retval);
-    }
-    if (retval > 0)  return(retval);
-    
-  } else {
-    SparseAddIdentityMat(arksls_mem->s_A);
-  }
-
-
-  /* On first decomposition, get the symbolic factorization */ 
-  if (arksls_mem->s_first_factorize) {
-
-    /* Update the ordering option with user-updated values */
-    klu_data->s_Common.ordering = klu_data->s_ordering;
-
-    /* Perform symbolic analysis of sparsity structure */
-    if (klu_data->s_Symbolic != NULL) {
-       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    }
-    klu_data->s_Symbolic = klu_analyze(arksls_mem->s_A->NP, 
-				       arksls_mem->s_A->indexptrs, 
-				       arksls_mem->s_A->indexvals, 
-				       &(klu_data->s_Common));
-    if (klu_data->s_Symbolic == NULL) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-
-    /* ------------------------------------------------------------
-       Compute the LU factorization of  the Jacobian.
-       ------------------------------------------------------------*/
-    if( klu_data->s_Numeric != NULL) {
-       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    }
-    klu_data->s_Numeric = klu_factor(arksls_mem->s_A->indexptrs, 
-				     arksls_mem->s_A->indexvals, 
-				     arksls_mem->s_A->data, 
-				     klu_data->s_Symbolic, 
-				     &(klu_data->s_Common));
-    if (klu_data->s_Numeric == NULL) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-
-    arksls_mem->s_first_factorize = 0;
-  }
-  else {
-
-    retval = klu_refactor(arksls_mem->s_A->indexptrs, 
-			  arksls_mem->s_A->indexvals, 
-			  arksls_mem->s_A->data, 
-			  klu_data->s_Symbolic, klu_data->s_Numeric,
-			  &(klu_data->s_Common));
-    if (retval == 0) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-    
-    /*-----------------------------------------------------------
-      Check if a cheap estimate of the reciprocal of the condition 
-      number is getting too small.  If so, delete
-      the prior numeric factorization and recompute it.
-      -----------------------------------------------------------*/
-    
-    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
-		       &(klu_data->s_Common));
-    if (retval == 0) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-
-    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
-      
-      /* Condition number may be getting large.  
-	 Compute more accurate estimate */
-      retval = klu_condest(arksls_mem->s_A->indexptrs, 
-			   arksls_mem->s_A->data, 
-			   klu_data->s_Symbolic, klu_data->s_Numeric,
-			   &(klu_data->s_Common));
-      if (retval == 0) {
-	arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-			"ARKKLUSetup", MSGSP_PACKAGE_FAIL);
-	return(ARKSLS_PACKAGE_FAIL);
-      }
-      
-      if ( (klu_data->s_Common.condest) > 
-	   (1.0/uround_twothirds) ) {
-
-	/* More accurate estimate also says condition number is 
-	   large, so recompute the numeric factorization */
-
-	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-	
-	klu_data->s_Numeric = klu_factor(arksls_mem->s_A->indexptrs, 
-					 arksls_mem->s_A->indexvals, 
-					 arksls_mem->s_A->data,
-					 klu_data->s_Symbolic, 
-					 &(klu_data->s_Common));
-
-	if (klu_data->s_Numeric == NULL) {
-	  arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-			  "ARKKLUSetup", MSGSP_PACKAGE_FAIL);
-	  return(ARKSLS_PACKAGE_FAIL);
-	}
-      }
-    }
-  }
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkKLUSolve:
-
- This routine handles the solve operation for the ARKKLU linear
- solver module.  It calls the KLU solve routine, then returns 
- ARKSLS_SUCCESS = 0.
----------------------------------------------------------------*/
-static int arkKLUSolve(ARKodeMem ark_mem, N_Vector b, 
-		       N_Vector weight, N_Vector ycur, 
-		       N_Vector fcur)
-{
-  int flag;
-  ARKSlsMem arksls_mem;
-  KLUData klu_data;
-  realtype *bd;
-  
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  bd = N_VGetArrayPointer(b);
-
-  /* Call KLU to solve the linear system */
-  flag = klu_data->sun_klu_solve(klu_data->s_Symbolic, klu_data->s_Numeric, 
-                                 arksls_mem->s_A->NP, 1, bd, 
-                                 &(klu_data->s_Common));
-  if (flag == 0) {
-    arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		    "ARKKLUSolve", MSGSP_PACKAGE_FAIL);
-    return(ARKSLS_PACKAGE_FAIL);
-  }
-
-  /* Scale the correction to account for change in gamma. */
-  if (ark_mem->ark_gamrat != ONE)
-    N_VScale(TWO/(ONE + ark_mem->ark_gamrat), b, b);
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkKLUFree:
-
- This routine frees memory specific to the ARKKLU linear solver.
----------------------------------------------------------------*/
-static int arkKLUFree(ARKodeMem ark_mem)
-{
-  ARKSlsMem arksls_mem;
-  KLUData klu_data;
-  
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  if( klu_data->s_Numeric != NULL)
-  {
-     klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  }
-  if( klu_data->s_Symbolic != NULL)
-  {
-     klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  }
-
-  if (arksls_mem->s_A) {
-    SparseDestroyMat(arksls_mem->s_A);
-    arksls_mem->s_A = NULL;
-  }
-
-  if (arksls_mem->s_savedJ) {
-    SparseDestroyMat(arksls_mem->s_savedJ);
-    arksls_mem->s_savedJ = NULL;
-  }
-
-  free(klu_data); 
-  free(arksls_mem); 
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-/*---------------------------------------------------------------
- ARKMassKLU
-
- This routine initializes the memory record and sets various 
- function fields specific to the ARKode / KLU mass matrix linear 
- solver module.  ARKMassKLU first calls the existing mfree 
- routine if this is not NULL.  Then it sets the ark_minit, 
- ark_msetup, ark_msolve and ark_mfree fields in (*arkode_mem) 
- to be arkMassKLUInit, arkMassKLUSetup, arkMassKLUSolve and 
- arkMassKLUFree, respectively.   It allocates memory for a 
- structure of type ARKSlsMassMemRec and sets the ark_mass_mem 
- field in (*arkode_mem) to the address of this structure.  It 
- sets MassSetupNonNull in (*arkode_mem) to TRUE.  Finally, it 
- allocates memory for KLU.  The return value is 
- ARKSLS_SUCCESS = 0, ARKSLS_LMEM_FAIL = -1, or 
- ARKSLS_ILL_INPUT = -2.
-
- NOTE: The KLU linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKMassKLU will first 
-       test for a compatible N_Vector internal representation
-       by checking that the function N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-int ARKMassKLU(void *arkode_mem, int n, int nnz, int sparsetype, 
-               ARKSlsSparseMassFn smass)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-  KLUData klu_data;
-  int flag;
-
-  /* Return immediately if arkode_mem is NULL. */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-                    "ARKMassKLU", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKSLS_ILL_INPUT, "ARKSLS", 
-                    "ARKMassKLU", MSGSP_BAD_NVECTOR);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set five main function fields in ark_mem, enable mass matrix. */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = arkMassKLUInit;
-  ark_mem->ark_msetup = arkMassKLUSetup;
-  ark_mem->ark_msolve = arkMassKLUSolve;
-  ark_mem->ark_mfree  = arkMassKLUFree;
-  ark_mem->ark_mtimes = arkMassKLUMultiply;
-  ark_mem->ark_mtimes_data = (void *) ark_mem;
-  ark_mem->ark_msolve_type = 3;
-
-  /* Get memory for ARKSlsMassMemRec. */
-  arksls_mem = (ARKSlsMassMem) malloc(sizeof(struct ARKSlsMassMemRec));
-  if (arksls_mem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKMassKLU", MSGSP_MEM_FAIL);
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Get memory for KLUData. */
-  klu_data = (KLUData) malloc(sizeof(struct KLUDataRec));
-  if (klu_data == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKMassKLU", MSGSP_MEM_FAIL);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Initialize mass-matrix-related data */
-  arksls_mem->s_nme = 0;
-  arksls_mem->s_first_factorize = 1;
-  arksls_mem->s_Meval = smass;
-  arksls_mem->s_Mdata = ark_mem->ark_user_data;
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = TRUE;
-  arksls_mem->sparsetype = sparsetype;
-
-  /* Allocate memory for M and M_lu */
-  arksls_mem->s_M = NULL;
-  arksls_mem->s_M = SparseNewMat(n, n, nnz, sparsetype);
-  if (arksls_mem->s_M == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKMassKLU", MSGSP_MEM_FAIL);
-    free(klu_data); klu_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-  arksls_mem->s_M_lu = NULL;
-  arksls_mem->s_M_lu = SparseNewMat(n, n, nnz, sparsetype);
-  if (arksls_mem->s_M_lu == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKMassKLU", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_M);
-    free(klu_data); klu_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Initialize KLU structures */
-  switch (sparsetype) {
-    case CSC_MAT:
-      klu_data->sun_klu_solve = &klu_solve;
-      break;
-    case CSR_MAT:
-      klu_data->sun_klu_solve = &klu_tsolve;
-      break;
-    default:
-      SparseDestroyMat(arksls_mem->s_M);
-      SparseDestroyMat(arksls_mem->s_M_lu);
-      free(klu_data); klu_data = NULL;
-      free(arksls_mem); arksls_mem = NULL;
-      return(ARKSLS_ILL_INPUT);
-  }
-  klu_data->s_Symbolic = NULL;
-  klu_data->s_Numeric = NULL;
-
-  /* Set default parameters for KLU */
-  flag = klu_defaults(&klu_data->s_Common);
-  if (flag == 0) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-                    "ARKMassKLU", MSGSP_MEM_FAIL);
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    free(klu_data->s_Numeric);  klu_data->s_Numeric = NULL;
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    free(klu_data->s_Symbolic);  klu_data->s_Symbolic = NULL;
-    SparseDestroyMat(arksls_mem->s_M);
-    SparseDestroyMat(arksls_mem->s_M_lu);
-    free(klu_data); klu_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Set ordering to COLAMD as the arkode default use.
-     Users can set a different value with ARKMassKLUSetOrdering,
-     and the user-set value is loaded before any call to klu_analyze in
-     ARKMassKLUSetup.  */
-  klu_data->s_ordering = 1;
-  klu_data->s_Common.ordering = klu_data->s_ordering;
-
-  /* Attach linear solver memory to the integrator memory */
-  arksls_mem->s_solver_data = (void *) klu_data;
-  ark_mem->ark_mass_mem = arksls_mem;
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
-  ARKMassKLUReInit
-
-  This routine reinitializes memory and flags for a new 
-  factorization (symbolic and numeric) to be conducted at the 
-  next solver setup call.  This routine is useful in the cases 
-  where the number of nonzeroes has changed or if the structure 
-  of the linear system has changed which would require a new 
-  symbolic (and numeric) factorization.
- 
-  The reinit_type argument governs the level of reinitialization:
- 
-  reinit_type = 1: The mass matrix will be destroyed and 
-                   a new one will be allocated based on the nnz
-                   value passed to this call. New symbolic and
-                   numeric factorizations will be completed at the 
-                   next solver setup.
- 
-  reinit_type = 2: Only symbolic and numeric factorizations will be 
-                   completed.  It is assumed that the mass matrix
-                   size has not exceeded the size of nnz given in 
-                   the prior call to ARKMassKLU.
- 
-  This routine assumes no other changes to solver use are necessary.
- 
-  The return value is ARKSLS_SUCCESS = 0, ARKSLS_MEM_NULL = -1, 
-  ARKSLS_MASSMEM_NULL = -8, ARKSLS_ILL_INPUT = -3, or 
-  ARKSLS_MEM_FAIL = -4.
----------------------------------------------------------------*/
-int ARKMassKLUReInit(void *arkode_mem, int n, int nnz, int reinit_type)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if arkode_mem is NULL. */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", "ARKMassKLUReInit", 
-		    MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Return immediately if ark_lmem is NULL. */
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MASSMEM_NULL, "ARKSLS", "ARKMassKLUReInit", 
-		    MSGSP_MASSMEM_NULL);
-    return(ARKSLS_MASSMEM_NULL);
-  }
-
-  arksls_mem = (ARKSlsMassMem) (ark_mem->ark_mass_mem);
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  /* Return if reinit_type is not valid */
-  if ((reinit_type != 1) && (reinit_type != 2)) {
-    arkProcessError(NULL, ARKSLS_ILL_INPUT, "ARKSLS", "ARKMassKLUReInit", 
-		    MSGSP_ILL_INPUT);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  if (reinit_type == 1) {
-
-    /* Destroy previous Jacobian information */
-    if (arksls_mem->s_M) {
-      SparseDestroyMat(arksls_mem->s_M);
-    }
-
-    /* Allocate memory for the sparse Jacobian */
-    arksls_mem->s_M = SparseNewMat(n, n, nnz, arksls_mem->sparsetype);
-    if (arksls_mem->s_M == NULL) {
-      arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", "ARKMassKLU", 
-		    MSGSP_MEM_FAIL);
-      return(ARKSLS_MEM_FAIL);
-    }
-  }
-
-  /* Free the prior factorazation and reset for first factorization */
-  if( klu_data->s_Symbolic != NULL)
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  if( klu_data->s_Numeric != NULL)
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  arksls_mem->s_first_factorize = 1;
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-
-  return(0);
-}
-
-/*---------------------------------------------------------------
- arkMassKLUInit:
-
- This routine does remaining initializations specific to the 
- ARKKLU mass matrix linear solver module.  It returns 0 if 
- successful.
----------------------------------------------------------------*/
-static int arkMassKLUInit(ARKodeMem ark_mem)
-{
-  ARKSlsMassMem arksls_mem;
-
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  arksls_mem->s_nme = 0;
-  arksls_mem->s_first_factorize = 1;
-
-  arksls_mem->s_Mdata = ark_mem->ark_user_data;
-
-  /* Set mass matrix function data */
-  arksls_mem->s_Mdata = ark_mem->ark_user_data;
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassKLUSetup:
-
-  This routine does the setup operations for the ARKMassKLU 
-  linear solver module.  It calls the mass matrix evaluation 
-  routine, updates counters, and calls the LU factorization 
-  routine.  The return value is either
-     ARkSLS_SUCCESS = 0  if successful,
-     +1  if the Meval routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the Meval routine failed unrecoverably.
----------------------------------------------------------------*/
-static int arkMassKLUSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			   N_Vector vtemp2, N_Vector vtemp3)
-{
-  ARKSlsMassMem arksls_mem;
-  KLUData klu_data;
-  int retval;
-  
-  realtype uround_twothirds;
-  
-  uround_twothirds = SUNRpowerR(ark_mem->ark_uround,TWOTHIRDS);
-
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-  
-  /* Check that mass matrix eval routine is set */
-  if (arksls_mem->s_Meval == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MASS_NOSET, "ARKSLS", 
-		    "arkMassKLUSetup", MSGSP_MASS_NOSET);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MASS_NOSET);
-  }
-
-  /* call Meval routine for new M matrix */
-  SparseSetMatToZero(arksls_mem->s_M);
-  retval = arksls_mem->s_Meval(ark_mem->ark_tn, arksls_mem->s_M, 
-			       arksls_mem->s_Mdata, vtemp1, 
-			       vtemp2, vtemp3);
-  arksls_mem->s_nme++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, ARKSLS_MASSFUNC_UNRECVR, "ARKSLS", 
-		    "arkMassKLUSetup", MSGSP_MASSFUNC_FAILED);
-    arksls_mem->s_last_flag = ARKSLS_MASSFUNC_UNRECVR;
-    return(-1);
-  }
-  if (retval > 0) {
-    arksls_mem->s_last_flag = ARKSLS_MASSFUNC_RECVR;
-    return(1);
-  }
-
-  /* Copy M into M_lu for LU decomposition */
-  SparseCopyMat(arksls_mem->s_M, arksls_mem->s_M_lu);
-
-  /* On first decomposition, get the symbolic factorization */ 
-  if (arksls_mem->s_first_factorize) {
-
-    /* Update the ordering option with user-updated values */
-    klu_data->s_Common.ordering = klu_data->s_ordering;
-
-    /* Perform symbolic analysis of sparsity structure */
-    if (klu_data->s_Symbolic != NULL) {
-       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    }
-    klu_data->s_Symbolic = klu_analyze(arksls_mem->s_M_lu->N, 
-                                       arksls_mem->s_M_lu->indexptrs, 
-				       arksls_mem->s_M_lu->indexvals, 
-				       &(klu_data->s_Common));
-    if (klu_data->s_Symbolic == NULL) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-
-    /* ------------------------------------------------------------
-       Compute the LU factorization of  the Jacobian.
-       ------------------------------------------------------------*/
-    if( klu_data->s_Numeric != NULL) {
-       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    }
-    klu_data->s_Numeric = klu_factor(arksls_mem->s_M_lu->indexptrs, 
-				     arksls_mem->s_M_lu->indexvals, 
-				     arksls_mem->s_M_lu->data, 
-				     klu_data->s_Symbolic, 
-				     &(klu_data->s_Common));
-    if (klu_data->s_Numeric == NULL) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-    
-    arksls_mem->s_first_factorize = 0;
-  }
-  else {
-
-    retval = klu_refactor(arksls_mem->s_M_lu->indexptrs, 
-			  arksls_mem->s_M_lu->indexvals, 
-			  arksls_mem->s_M_lu->data,
-			  klu_data->s_Symbolic, klu_data->s_Numeric,
-			  &(klu_data->s_Common));
-    if (retval == 0) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-    
-    /*-----------------------------------------------------------
-      Check if a cheap estimate of the reciprocal of the condition 
-      number is getting too small.  If so, delete
-      the prior numeric factorization and recompute it.
-      -----------------------------------------------------------*/
-    
-    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
-		       &(klu_data->s_Common));
-    if (retval == 0) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
-      return(ARKSLS_PACKAGE_FAIL);
-    }
-
-    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
-      
-      /* Condition number may be getting large.  
-	 Compute more accurate estimate */
-      retval = klu_condest(arksls_mem->s_M_lu->indexptrs, 
-			   arksls_mem->s_M_lu->data,
-			   klu_data->s_Symbolic, klu_data->s_Numeric,
-			   &(klu_data->s_Common));
-      if (retval == 0) {
-	arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-			"ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
-	return(ARKSLS_PACKAGE_FAIL);
-      }
-      
-      if ( (klu_data->s_Common.condest) > 
-	   (1.0/uround_twothirds) ) {
-
-	/* More accurate estimate also says condition number is 
-	   large, so recompute the numeric factorization */
-
-	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-	
-	klu_data->s_Numeric = klu_factor(arksls_mem->s_M_lu->indexptrs, 
-					 arksls_mem->s_M_lu->indexvals, 
-					 arksls_mem->s_M_lu->data, 
-					 klu_data->s_Symbolic, 
-					 &(klu_data->s_Common));
-
-	if (klu_data->s_Numeric == NULL) {
-	  arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-			  "ARKMassKLUSetup", MSGSP_PACKAGE_FAIL);
-	  return(ARKSLS_PACKAGE_FAIL);
-	}
-      }
-    }
-  }
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassKLUSolve:
-
-  This routine handles the solve operation for the ARKKLU mass 
-  matrix linear solver module.  It calls the KLU solve routine, 
-  then returns ARKSLS_SUCCESS = 0.
----------------------------------------------------------------*/
-static int arkMassKLUSolve(ARKodeMem ark_mem, N_Vector b, 
-			   N_Vector weight)
-{
-  int flag;
-  ARKSlsMassMem arksls_mem;
-  KLUData klu_data;
-  realtype *bd;
-  
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  bd = N_VGetArrayPointer(b);
-
-  /* Call KLU to solve the linear system */
-  flag = klu_data->sun_klu_solve(klu_data->s_Symbolic, klu_data->s_Numeric, 
-                                 arksls_mem->s_M_lu->NP, 1, bd, 
-                                 &(klu_data->s_Common));
-  if (flag == 0) {
-    arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		    "ARKMassKLUSolve", MSGSP_PACKAGE_FAIL);
-    return(ARKSLS_PACKAGE_FAIL);
-  }
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkMassKLUFree:
-
- This routine frees memory specific to the ARKMassKLU mass 
- matrix linear solver.
----------------------------------------------------------------*/
-static int arkMassKLUFree(ARKodeMem ark_mem)
-{
-  ARKSlsMassMem arksls_mem;
-  KLUData klu_data;
-  
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  if( klu_data->s_Numeric != NULL)
-  {
-     klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  }
-  if( klu_data->s_Symbolic != NULL)
-  {
-     klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  }
-
-  if (arksls_mem->s_M) {
-    SparseDestroyMat(arksls_mem->s_M);
-    arksls_mem->s_M = NULL;
-  }
-
-  if (arksls_mem->s_M_lu) {
-    SparseDestroyMat(arksls_mem->s_M_lu);
-    arksls_mem->s_M_lu = NULL;
-  }
-
-  free(klu_data); 
-  free(arksls_mem); 
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-/*===============================================================
- Utility Functions
-===============================================================*/
-
-/*---------------------------------------------------------------
- arkMassKLUMultiply:
-
- Multiplies the mass matrix by the vector v to fill in the 
- vector Mv.
----------------------------------------------------------------*/
-static int arkMassKLUMultiply(N_Vector v, N_Vector Mv, 
-			      realtype t, void *arkode_mem)
-{
-
-  /* extract the SlsMassMem structure from the arkode_mem pointer */
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-  realtype *vdata=NULL, *Mvdata=NULL;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "arkMassKLUMultiply", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-
-  /* zero out the result */
-  N_VConst(0.0, Mv);
-
-  /* access the vector arrays (since they must be serial vectors) */
-  vdata = N_VGetArrayPointer(v);
-  Mvdata = N_VGetArrayPointer(Mv);
-  if (vdata == NULL || Mvdata == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "arkMassKLLUMultiply", 
-		    "Vector data un-allocated.");
-    return(ARKSLS_MEM_NULL);
-  }
-
-  /* perform matrix-vector product with arksls_mem->s_M and return */
-  if (SparseMatvec(arksls_mem->s_M, vdata, Mvdata) != 0) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "arkMassKLUMultiply", 
-		    "Mass matrix data un-allocated.");
-    return(ARKSLS_MEM_NULL);
-  }
-
-  return(0);
-
-}
-
-
-/*===============================================================
- Optional Input Specification Functions
-===============================================================*/
-
-
-/*---------------------------------------------------------------
- ARKKLUSetOrdering:
-
- Sets the ordering used by KLU for reducing fill.  Options are: 
-     0 for AMD, 
-     1 for COLAMD, and 
-     2 for the natural ordering.  
- The default used is 1 (COLAMD).
----------------------------------------------------------------*/
-int ARKKLUSetOrdering(void *arkode_mem, int ordering_choice)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if ark_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKKLUSetOrdering", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) ) {
-    arkProcessError(NULL, ARKSLS_ILL_INPUT, "ARKSLS", 
-		    "ARKKLUSetOrdering", MSGSP_ILL_INPUT);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  klu_data->s_ordering = ordering_choice;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassKLUSetOrdering:
-
- Sets the ordering used by KLU for reducing fill.  Options are: 
-     0 for AMD, 
-     1 for COLAMD, and 
-     2 for the natural ordering.  
- The default used is 1 (COLAMD).
----------------------------------------------------------------*/
-int ARKMassKLUSetOrdering(void *arkode_mem, int ordering_choice)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if ark_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKKLUSetOrdering", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) ) {
-    arkProcessError(NULL, ARKSLS_ILL_INPUT, "ARKSLS", 
-		    "ARKKLUSetOrdering", MSGSP_ILL_INPUT);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  klu_data = (KLUData) arksls_mem->s_solver_data;
-
-  klu_data->s_ordering = ordering_choice;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
-   EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_lapack.c b/src/arkode/arkode_lapack.c
deleted file mode 100644
index ae7ce31..0000000
--- a/src/arkode/arkode_lapack.c
+++ /dev/null
@@ -1,1270 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the implementation file for a ARKODE dense linear solver
- * using BLAS and LAPACK functions.
- *--------------------------------------------------------------*/
-
-/* NOTE: the only operation that does not use Blas/Lapack functions
-   is matrix plus mass matrix (in calculating M-gamma*J in lsetup) */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_lapack.h>
-#include "arkode_direct_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-
-/*===============================================================
- PROTOTYPES FOR PRIVATE FUNCTIONS
-===============================================================*/
-
-/* ARKLAPACK DENSE linit, lsetup, lsolve, and lfree routines */ 
-static int arkLapackDenseInit(ARKodeMem ark_mem);
-static int arkLapackDenseSetup(ARKodeMem ark_mem, int convfail, 
-			       N_Vector yP, N_Vector fctP, 
-			       booleantype *jcurPtr, N_Vector tmp1, 
-			       N_Vector tmp2, N_Vector tmp3);
-static int arkLapackDenseSolve(ARKodeMem ark_mem, N_Vector b, 
-			       N_Vector weight, N_Vector yC, 
-			       N_Vector fctC);
-static int arkLapackDenseFree(ARKodeMem ark_mem);
-
-/* ARKLAPACK DENSE minit, msetup, msolve, mfree and mtimes routines */ 
-static int arkMassLapackDenseInit(ARKodeMem ark_mem);
-static int arkMassLapackDenseSetup(ARKodeMem ark_mem, N_Vector tmp1, 
-				   N_Vector tmp2, N_Vector tmp3);
-static int arkMassLapackDenseSolve(ARKodeMem ark_mem, N_Vector b, 
-				   N_Vector weight);
-static int arkMassLapackDenseFree(ARKodeMem ark_mem);
-static int arkMassLapackDenseMultiply(N_Vector v, N_Vector Mv, 
-				      realtype t, void *user_data);
-
-/* ARKLAPACK BAND linit, lsetup, lsolve, and lfree routines */ 
-static int arkLapackBandInit(ARKodeMem ark_mem);
-static int arkLapackBandSetup(ARKodeMem ark_mem, int convfail, 
-			      N_Vector yP, N_Vector fctP, 
-			      booleantype *jcurPtr, N_Vector tmp1, 
-			      N_Vector tmp2, N_Vector tmp3);
-static int arkLapackBandSolve(ARKodeMem ark_mem, N_Vector b, 
-			      N_Vector weight, N_Vector yC, 
-			      N_Vector fctC);
-static int arkLapackBandFree(ARKodeMem ark_mem);
-
-/* ARKLAPACK BAND minit, msetup, msolve, mfree and mtimes routines */ 
-static int arkMassLapackBandInit(ARKodeMem ark_mem);
-static int arkMassLapackBandSetup(ARKodeMem ark_mem, N_Vector tmp1, 
-				  N_Vector tmp2, N_Vector tmp3);
-static int arkMassLapackBandSolve(ARKodeMem ark_mem, N_Vector b, 
-				  N_Vector weight);
-static int arkMassLapackBandFree(ARKodeMem ark_mem);
-static int arkMassLapackBandMultiply(N_Vector v, N_Vector Mv, 
-				     realtype t, void *user_data);
-
-/*===============================================================
- EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
-===============================================================*/
-              
-/*---------------------------------------------------------------
- ARKLapackDense:
-
- This routine initializes the memory record and sets various 
- function fields specific to the linear solver module.  
- ARKLapackDense first calls the existing lfree routine if this is 
- not NULL.  Then it sets the ark_linit, ark_lsetup, ark_lsolve, 
- ark_lfree fields in (*arkode_mem) to be arkLapackDenseInit, 
- arkLapackDenseSetup, arkLapackDenseSolve, and arkLapackDenseFree, 
- respectively.  It allocates memory for a structure of type 
- ARKDlsMemRec and sets the ark_lmem field in (*arkode_mem) to the
- address of this structure.  It sets setupNonNull in (*arkode_mem) 
- to TRUE, and the d_jac field to the default arkDlsDenseDQJac. 
- Finally, it allocates memory for M, pivots, and savedJ.
- The return value is SUCCESS = 0, or LMEM_FAIL = -1.
-
- NOTE: The dense linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKLapackDense will 
-       first test for a compatible N_Vector internal 
-       representation by checking that N_VGetArrayPointer and 
-       N_VSetArrayPointer exist.  Of course, other vector 
-       implementations may also have these functions set, so 
-       this test is not sufficient to guarantee use of the 
-       serial NVECTOR package.
----------------------------------------------------------------*/
-int ARKLapackDense(void *arkode_mem, int N)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKLAPACK", 
-		    "ARKLapackDense", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the LAPACK solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL ||
-      ark_mem->ark_tempv->ops->nvsetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKLAPACK", 
-		    "ARKLapackDense", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree !=NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */
-  ark_mem->ark_linit  = arkLapackDenseInit;
-  ark_mem->ark_lsetup = arkLapackDenseSetup;
-  ark_mem->ark_lsolve = arkLapackDenseSolve;
-  ark_mem->ark_lfree  = arkLapackDenseFree;
-  ark_mem->ark_lsolve_type = 1;
-
-  /* Get memory for ARKDlsMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMem) malloc(sizeof(struct ARKDlsMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackDense", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_DENSE;
-
-  /* Initialize Jacobian-related data */
-  arkdls_mem->d_jacDQ  = TRUE;
-  arkdls_mem->d_djac   = NULL;
-  arkdls_mem->d_J_data = NULL;
-
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_setupNonNull = TRUE;
-
-  /* Initialize counters */
-  arkDlsInitializeCounters(arkdls_mem);
-  
-  /* Set problem dimension */
-  arkdls_mem->d_n = (long int) N;
-
-  /* Allocate memory for M, pivot array, and savedJ */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_pivots = NULL;
-  arkdls_mem->d_savedJ = NULL;
-
-  arkdls_mem->d_M = NewDenseMat(arkdls_mem->d_n, arkdls_mem->d_n);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackDense", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_pivots = NewIntArray(N);
-  if (arkdls_mem->d_pivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_savedJ = NewDenseMat(arkdls_mem->d_n, arkdls_mem->d_n);
-  if (arkdls_mem->d_savedJ == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    DestroyArray(arkdls_mem->d_pivots);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKLapackBand:
-
- This routine initializes the memory record and sets various 
- function fields specific to the band linear solver module. It 
- first calls the existing lfree routine if this is not NULL.  It 
- then sets the ark_linit, ark_lsetup, ark_lsolve, and ark_lfree 
- fields in (*arkode_mem) to be arkLapackBandInit, 
- arkLapackBandSetup, arkLapackBandSolve, and arkLapackBandFree, 
- respectively.  It allocates memory for a structure of type 
- ARKLapackBandMemRec and sets the ark_lmem field in (*arkode_mem) 
- to the address of this structure.  It sets setupNonNull in 
- (*arkode_mem) to be TRUE, mu to be mupper, and ml to be mlower.  
- Finally, it allocates memory for M, pivots, and savedJ.  The 
- ARKLapackBand return value is ARKDLS_SUCCESS=0, 
- ARKDLS_MEM_FAIL=-1, or ARKDLS_ILL_INPUT=-2.
-
- NOTE: The ARKLAPACK linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKLapackBand will first 
-       test for compatible a compatible N_Vector internal
-       representation by checking that the function 
-       N_VGetArrayPointer exists.  Again, this test is insufficient
-       to guarantee the serial NVECTOR package, but it's a start.
----------------------------------------------------------------*/                  
-int ARKLapackBand(void *arkode_mem, int N, int mupper, int mlower)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKLAPACK", 
-		    "ARKLapackBand", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKLAPACK", 
-		    "ARKLapackBand", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */  
-  ark_mem->ark_linit  = arkLapackBandInit;
-  ark_mem->ark_lsetup = arkLapackBandSetup;
-  ark_mem->ark_lsolve = arkLapackBandSolve;
-  ark_mem->ark_lfree  = arkLapackBandFree;
-  ark_mem->ark_lsolve_type = 2;
-  
-  /* Get memory for ARKDlsMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMem) malloc(sizeof(struct ARKDlsMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackBand", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_BAND;
-
-  /* Initialize Jacobian-related data */
-  arkdls_mem->d_jacDQ  = TRUE;
-  arkdls_mem->d_bjac   = NULL;
-  arkdls_mem->d_J_data = NULL;
-
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_setupNonNull = TRUE;
-  
-  /* Initialize counters */
-  arkDlsInitializeCounters(arkdls_mem);
-  
-  /* Load problem dimension */
-  arkdls_mem->d_n = (long int) N;
-
-  /* Load half-bandwiths in arkdls_mem */
-  arkdls_mem->d_ml = (long int) mlower;
-  arkdls_mem->d_mu = (long int) mupper;
-
-  /* Test ml and mu for legality */
-  if ((arkdls_mem->d_ml < 0) || (arkdls_mem->d_mu < 0) || 
-      (arkdls_mem->d_ml >= arkdls_mem->d_n) || 
-      (arkdls_mem->d_mu >= arkdls_mem->d_n)) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKLAPACK", 
-		    "ARKLapackBand", MSGD_BAD_SIZES);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  arkdls_mem->d_smu = SUNMIN(arkdls_mem->d_n-1,
-			  arkdls_mem->d_mu + arkdls_mem->d_ml);
-
-  /* Allocate memory for M, pivot array, and savedJ */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_pivots = NULL;
-  arkdls_mem->d_savedJ = NULL;
-
-  arkdls_mem->d_M = NewBandMat(arkdls_mem->d_n, arkdls_mem->d_mu, 
-			       arkdls_mem->d_ml, arkdls_mem->d_smu);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackBand", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }  
-  arkdls_mem->d_pivots = NewIntArray(N);
-  if (arkdls_mem->d_pivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_savedJ = NewBandMat(arkdls_mem->d_n, arkdls_mem->d_mu, 
-				    arkdls_mem->d_ml, arkdls_mem->d_smu);
-  if (arkdls_mem->d_savedJ == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    DestroyArray(arkdls_mem->d_pivots);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassLapackDense:
-
- This routine initializes the memory record and sets various 
- function fields specific to the mass matrix solver module.  
- ARKMassLapackDense first calls the existing mfree routine if 
- this is not NULL.  Then it sets the ark_minit, ark_msetup, 
- ark_msolve, ark_mfree fields in (*arkode_mem) to be 
- arkMassLapackDenseInit, arkMassLapackDenseSetup, 
- arkMassLapackDenseSolve, and arkMassLapackDenseFree, 
- respectively.  It allocates memory for a structure of type 
- ARKDlsMassMemRec and sets the ark_mass_mem field in 
- (*arkode_mem) to the address of this structure.  It sets 
- MassSetupNonNull in (*arkode_mem) to TRUE.  Finally, it 
- allocates memory for M and pivots. The return value is 
- SUCCESS = 0, or LMEM_FAIL = -1.
-
- NOTE: The dense linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKMassLapackDense will 
-       first test for a compatible N_Vector internal 
-       representation by checking that N_VGetArrayPointer and 
-       N_VSetArrayPointer exist.  Of course, other vector 
-       implementations may also have these functions set, so 
-       this test is not sufficient to guarantee use of the 
-       serial NVECTOR package.
----------------------------------------------------------------*/
-int ARKMassLapackDense(void *arkode_mem, int N, 
-		       ARKDlsDenseMassFn dmass)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKLAPACK", 
-		    "ARKMassLapackDense", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the LAPACK solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL ||
-      ark_mem->ark_tempv->ops->nvsetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKLAPACK", 
-		    "ARKMassLapackDense", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree !=NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set related function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = arkMassLapackDenseInit;
-  ark_mem->ark_msetup = arkMassLapackDenseSetup;
-  ark_mem->ark_msolve = arkMassLapackDenseSolve;
-  ark_mem->ark_mfree  = arkMassLapackDenseFree;
-  ark_mem->ark_mtimes = arkMassLapackDenseMultiply;
-  ark_mem->ark_mtimes_data = (void *) ark_mem;
-  ark_mem->ark_msolve_type = 1;
-
-  /* Get memory for ARKDlsMassMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMassMem) malloc(sizeof(struct ARKDlsMassMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKMassLapackDense", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_DENSE;
-
-  /* Initialize mass-matrix-related data */
-  arkdls_mem->d_dmass = dmass;
-  arkdls_mem->d_M_data = NULL;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = TRUE;
-
-  /* Set problem dimension */
-  arkdls_mem->d_n = (long int) N;
-
-  /* Allocate memory for M and pivot array */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_pivots = NULL;
-
-  arkdls_mem->d_M = NewDenseMat(arkdls_mem->d_n, arkdls_mem->d_n);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKMassLapackDense", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-  arkdls_mem->d_pivots = NewIntArray(N);
-  if (arkdls_mem->d_pivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKMassLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassLapackBand:
-
- This routine initializes the memory record and sets various 
- function fields specific to the band mass matrix solver module. 
- It first calls the existing mfree routine if this is not NULL.  
- It then sets the ark_minit, ark_msetup, ark_msolve, and ark_mfree 
- fields in (*arkode_mem) to be arkMassLapackBandInit, 
- arkMassLapackBandSetup, arkMassLapackBandSolve, and 
- arkMassLapackBandFree, respectively.  It allocates memory for a
- structure of type ARKMassLapackBandMemRec and sets the 
- ark_mass_mem field in (*arkode_mem) to the address of this 
- structure.  It sets MassSetupNonNull in (*arkode_mem) to be TRUE, 
- mu to be mupper, and ml to be mlower.  Finally, it allocates 
- memory for M and pivots.  The ARKMassLapackBand return value is 
- ARKDLS_SUCCESS=0, ARKDLS_MEM_FAIL=-1, or ARKDLS_ILL_INPUT=-2.
-
- NOTE: The ARKLAPACK linear solver assumes a serial implementation
-       of the NVECTOR package. Therefore, ARKMassLapackBand will first 
-       test for compatible a compatible N_Vector internal
-       representation by checking that the function 
-       N_VGetArrayPointer exists.  Again, this test is insufficient
-       to guarantee the serial NVECTOR package, but it's a start.
----------------------------------------------------------------*/                  
-int ARKMassLapackBand(void *arkode_mem, int N, int mupper, 
-		      int mlower, ARKDlsBandMassFn bmass)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKLAPACK", 
-		    "ARKMassLapackBand", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKLAPACK", 
-		    "ARKMassLapackBand", MSGD_BAD_NVECTOR);
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = arkMassLapackBandInit;
-  ark_mem->ark_msetup = arkMassLapackBandSetup;
-  ark_mem->ark_msolve = arkMassLapackBandSolve;
-  ark_mem->ark_mfree  = arkMassLapackBandFree;
-  ark_mem->ark_mtimes = arkMassLapackBandMultiply;
-  ark_mem->ark_mtimes_data = (void *) ark_mem;
-  ark_mem->ark_msolve_type = 2;
-  
-  /* Get memory for ARKDlsMassMemRec */
-  arkdls_mem = NULL;
-  arkdls_mem = (ARKDlsMassMem) malloc(sizeof(struct ARKDlsMassMemRec));
-  if (arkdls_mem == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKMassLapackBand", MSGD_MEM_FAIL);
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  arkdls_mem->d_type = SUNDIALS_BAND;
-
-  /* Initialize mass-matrix-related data */
-  arkdls_mem->d_bmass = bmass;
-  arkdls_mem->d_M_data = NULL;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  arkdls_mem->d_n = (long int) N;
-
-  /* Load half-bandwiths in arkdls_mem */
-  arkdls_mem->d_ml = (long int) mlower;
-  arkdls_mem->d_mu = (long int) mupper;
-
-  /* Test ml and mu for legality */
-  if ((arkdls_mem->d_ml < 0) || (arkdls_mem->d_mu < 0) || 
-      (arkdls_mem->d_ml >= arkdls_mem->d_n) || 
-      (arkdls_mem->d_mu >= arkdls_mem->d_n)) {
-    arkProcessError(ark_mem, ARKDLS_ILL_INPUT, "ARKLAPACK", 
-		    "ARKMassLapackBand", MSGD_BAD_SIZES);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  arkdls_mem->d_smu = SUNMIN(arkdls_mem->d_n-1,
-			  arkdls_mem->d_mu + arkdls_mem->d_ml);
-
-  /* Allocate memory for M and pivot array */
-  arkdls_mem->d_M = NULL;
-  arkdls_mem->d_pivots = NULL;
-
-  arkdls_mem->d_M = NewBandMat(arkdls_mem->d_n, arkdls_mem->d_mu, 
-			       arkdls_mem->d_ml, arkdls_mem->d_smu);
-  if (arkdls_mem->d_M == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKMassLapackBand", MSGD_MEM_FAIL);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }  
-  arkdls_mem->d_pivots = NewIntArray(N);
-  if (arkdls_mem->d_pivots == NULL) {
-    arkProcessError(ark_mem, ARKDLS_MEM_FAIL, "ARKLAPACK", 
-		    "ARKMassLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(arkdls_mem->d_M);
-    free(arkdls_mem); arkdls_mem = NULL;
-    return(ARKDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkdls_mem;
-
-  return(ARKDLS_SUCCESS);
-}
-
-
-/*===============================================================
-  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS
-===============================================================*/
-
-/*---------------------------------------------------------------
- arkLapackDenseInit does remaining initializations specific to 
- the dense linear solver.
----------------------------------------------------------------*/                  
-static int arkLapackDenseInit(ARKodeMem ark_mem)
-{
-  ARKDlsMem arkdls_mem;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  
-  arkDlsInitializeCounters(arkdls_mem);
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (arkdls_mem->d_jacDQ) {
-    arkdls_mem->d_djac = arkDlsDenseDQJac;
-    arkdls_mem->d_J_data = ark_mem;
-  } else {
-    arkdls_mem->d_J_data = ark_mem->ark_user_data;
-  }
-
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkLapackDenseSetup does the setup operations for the dense 
- linear solver. It makes a decision whether or not to call the 
- Jacobian evaluation routine based on various state variables, 
- and if not it uses the saved copy. In any case, it constructs 
- the Newton matrix A = M - gamma*J updates counters, and calls 
- the dense LU factorization routine.
----------------------------------------------------------------*/                  
-static int arkLapackDenseSetup(ARKodeMem ark_mem, int convfail,
-			       N_Vector yP, N_Vector fctP,
-			       booleantype *jcurPtr, N_Vector tmp1, 
-			       N_Vector tmp2, N_Vector tmp3)
-{
-  ARKDlsMem arkdls_mem;
-  ARKDlsMassMem arkdls_mass_mem;
-  realtype dgamma, fact, *Acol_j, *Mcol_j;
-  booleantype jbad, jok;
-  int ier, retval, one = 1;
-  int intn, lenmat, i, j;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  intn = (int) arkdls_mem->d_n;
-  lenmat = arkdls_mem->d_M->ldata ;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkdls_mem->d_nstlj + ARKD_MSBJ) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKD_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  jok = !jbad;
-  
-  /* If jok = TRUE, use saved copy of J */
-  if (jok) {
-    *jcurPtr = FALSE;
-    dcopy_f77(&lenmat, arkdls_mem->d_savedJ->data, &one, 
-	      arkdls_mem->d_M->data, &one);
-    
-  /* If jok = FALSE, call jac routine for new J value */
-  } else {
-    arkdls_mem->d_nje++;
-    arkdls_mem->d_nstlj = ark_mem->ark_nst;
-    *jcurPtr = TRUE;
-    SetToZero(arkdls_mem->d_M);
-
-    retval = arkdls_mem->d_djac(arkdls_mem->d_n, ark_mem->ark_tn, 
-				yP, fctP, arkdls_mem->d_M, 
-				arkdls_mem->d_J_data, tmp1, tmp2, tmp3);
-
-    if (retval == 0) {
-      dcopy_f77(&lenmat, arkdls_mem->d_M->data, &one, 
-		arkdls_mem->d_savedJ->data, &one);
-    } else if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_JACFUNC_UNRECVR, "ARKLAPACK", 
-		      "arkLapackDenseSetup", MSGD_JACFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_UNRECVR;
-      return(-1);
-    } else if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_RECVR;
-      return(1);
-    }
-  }
-
-  /* Scale J by -gamma */
-  fact = -ark_mem->ark_gamma;
-  dscal_f77(&lenmat, &fact, arkdls_mem->d_M->data, &one);
-  
-  /* Add mass matrix to get A = M-gamma*J*/
-  if (ark_mem->ark_mass_matrix) {
-
-    /* Compute mass matrix */
-    arkdls_mass_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-    SetToZero(arkdls_mass_mem->d_M);
-    retval = arkdls_mass_mem->d_dmass(arkdls_mass_mem->d_n, 
-				      ark_mem->ark_tn, 
-				      arkdls_mass_mem->d_M, 
-				      arkdls_mass_mem->d_M_data, 
-				      tmp1, tmp2, tmp3);
-    arkdls_mass_mem->d_nme++;
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKDENSE", 
-		      "arkLapackDenseSetup",  MSGD_MASSFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-      return(1);
-    }
-
-    /* Add to A */
-    for (j=0; j<arkdls_mem->d_M->N; j++) {
-      Acol_j = arkdls_mem->d_M->cols[j];
-      Mcol_j = arkdls_mass_mem->d_M->cols[j];
-      for (i=0; i<arkdls_mem->d_M->M; i++) 
-	Acol_j[i] += Mcol_j[i];
-    }
-  } else {
-    AddIdentity(arkdls_mem->d_M);
-  }
-
-  /* Do LU factorization of M */
-  dgetrf_f77(&intn, &intn, arkdls_mem->d_M->data, 
-	     &intn, arkdls_mem->d_pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  arkdls_mem->d_last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkLapackDenseSolve handles the solve operation for the dense 
- linear solver by calling the dense backsolve routine.
----------------------------------------------------------------*/                  
-static int arkLapackDenseSolve(ARKodeMem ark_mem, N_Vector b, 
-			       N_Vector weight, N_Vector yC, 
-			       N_Vector fctC)
-{
-  ARKDlsMem arkdls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  intn = (int) arkdls_mem->d_n;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgetrs_f77("N", &intn, &one, arkdls_mem->d_M->data, &intn, 
-	     arkdls_mem->d_pivots, bd, &intn, &ier, 1); 
-
-  if (ier > 0) return(1);
-
-  /* scale the correction to account for change in gamma */
-  if (ark_mem->ark_gamrat != ONE) {
-    fact = TWO/(ONE + ark_mem->ark_gamrat);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-  
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkLapackDenseFree frees memory specific to the dense linear 
- solver.
----------------------------------------------------------------*/                  
-static int arkLapackDenseFree(ARKodeMem ark_mem)
-{
-  ARKDlsMem  arkdls_mem;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  
-  DestroyMat(arkdls_mem->d_M);
-  DestroyArray(arkdls_mem->d_pivots);
-  DestroyMat(arkdls_mem->d_savedJ);
-  free(arkdls_mem); 
-  arkdls_mem = NULL;
-
-  return(0);
-}
-
-
-/*===============================================================
-  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE MASS MATRIX
-===============================================================*/
-
-/*---------------------------------------------------------------
- arkMassLapackDenseInit does remaining initializations specific to 
- the dense linear solver.
----------------------------------------------------------------*/                  
-static int arkMassLapackDenseInit(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem arkdls_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  arkdls_mem->d_nme = 0;
-  arkdls_mem->d_M_data = ark_mem->ark_user_data;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackDenseSetup does the setup operations for the dense 
- mass matrix solver. It calls the mass matrix evaluation routine,
- updates counters, and calls the dense LU factorization routine.
----------------------------------------------------------------*/                  
-static int arkMassLapackDenseSetup(ARKodeMem ark_mem, N_Vector tmp1, 
-				   N_Vector tmp2, N_Vector tmp3)
-{
-  ARKDlsMassMem arkdls_mem;
-  int ier, retval;
-  int intn;
-
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  intn = (int) arkdls_mem->d_n;
-
-  SetToZero(arkdls_mem->d_M);
-  retval = arkdls_mem->d_dmass(arkdls_mem->d_n, ark_mem->ark_tn, 
-			       arkdls_mem->d_M, arkdls_mem->d_M_data, 
-			       tmp1, tmp2, tmp3);
-  arkdls_mem->d_nme++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKLAPACK", 
-		    "arkMassLapackDenseSetup", MSGD_MASSFUNC_FAILED);
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-    return(-1);
-  } else if (retval > 0) {
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-    return(1);
-  }
-
-  /* Do LU factorization of M */
-  dgetrf_f77(&intn, &intn, arkdls_mem->d_M->data, 
-	     &intn, arkdls_mem->d_pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  arkdls_mem->d_last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackDenseSolve handles the solve operation for the
- dense mass matrix solver by calling the dense backsolve routine.
----------------------------------------------------------------*/                  
-static int arkMassLapackDenseSolve(ARKodeMem ark_mem, N_Vector b, 
-				   N_Vector weight)
-{
-  ARKDlsMassMem arkdls_mem;
-  realtype *bd;
-  int ier, one = 1;
-  int intn;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  intn = (int) arkdls_mem->d_n;
-  bd = N_VGetArrayPointer(b);
-  dgetrs_f77("N", &intn, &one, arkdls_mem->d_M->data, &intn, 
-	     arkdls_mem->d_pivots, bd, &intn, &ier, 1); 
-  if (ier > 0) return(1);
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackDenseFree frees memory specific to the dense mass
- matrix solver.
----------------------------------------------------------------*/                  
-static int arkMassLapackDenseFree(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem arkdls_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  DestroyMat(arkdls_mem->d_M);
-  DestroyArray(arkdls_mem->d_pivots);
-  free(arkdls_mem); 
-  arkdls_mem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackDenseMultiply performs a matrix-vector product, 
- multiplying the current mass matrix by a given vector.
----------------------------------------------------------------*/                  
-static int arkMassLapackDenseMultiply(N_Vector v, N_Vector Mv, 
-				      realtype t, void *arkode_mem)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-  realtype *vdata=NULL, *Mvdata=NULL;
-  realtype *Mcol_j;
-  int i, j;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKLAPACK", 
-		    "arkMassLapackDenseMultiply", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-
-  /* extract the DlsMassMem structure from the user_data pointer */
-  ark_mem = (ARKodeMem) arkode_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-
-  /* zero out the result */
-  N_VConst(0.0, Mv);
-
-  /* access the vector arrays (since they must be serial vectors) */
-  vdata = N_VGetArrayPointer(v);
-  Mvdata = N_VGetArrayPointer(Mv);
-  if (vdata == NULL || Mvdata == NULL)
-    return(1);
-
-  /* perform matrix-vector product and return */
-  for (j=0; j<arkdls_mem->d_M->N; j++) {
-    Mcol_j = arkdls_mem->d_M->cols[j];
-    for (i=0; i<arkdls_mem->d_M->M; i++) 
-      Mvdata[i] += Mcol_j[i]*vdata[j];
-  }
-  return(0);
-}
-
-
-/*===============================================================
-  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS
-===============================================================*/
-
-/*---------------------------------------------------------------
- arkLapackBandInit does remaining initializations specific to 
- the band linear solver.
----------------------------------------------------------------*/                  
-static int arkLapackBandInit(ARKodeMem ark_mem)
-{
-  ARKDlsMem arkdls_mem;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-
-  arkDlsInitializeCounters(arkdls_mem);
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (arkdls_mem->d_jacDQ) {
-    arkdls_mem->d_bjac = arkDlsBandDQJac;
-    arkdls_mem->d_J_data = ark_mem;
-  } else {
-    arkdls_mem->d_J_data = ark_mem->ark_user_data;
-  }
-  
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkLapackBandSetup does the setup operations for the band linear 
- solver. It makes a decision whether or not to call the Jacobian 
- evaluation routine based on various state variables, and if not 
- it uses the saved copy. In any case, it constructs the Newton 
- matrix A = M - gamma*J, updates counters, and calls the band LU
- factorization routine.
----------------------------------------------------------------*/                  
-static int arkLapackBandSetup(ARKodeMem ark_mem, int convfail, 
-			      N_Vector yP, N_Vector fctP, 
-			      booleantype *jcurPtr, N_Vector tmp1, 
-			      N_Vector tmp2, N_Vector tmp3)
-{
-  ARKDlsMem arkdls_mem;
-  ARKDlsMassMem arkdls_mass_mem;
-  realtype dgamma, fact, *Acol_j, *Mcol_j;
-  booleantype jbad, jok;
-  int ier, retval, one = 1;
-  int intn, iml, imu, lenmat, ldmat, i, j, colSize;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  intn = (int) arkdls_mem->d_n;
-  iml = (int) arkdls_mem->d_ml;
-  imu = (int) arkdls_mem->d_mu;
-  lenmat = arkdls_mem->d_M->ldata;
-  ldmat = arkdls_mem->d_M->ldim;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkdls_mem->d_nstlj + ARKD_MSBJ) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKD_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  jok = !jbad;
-  
-  /* If jok = TRUE, use saved copy of J */
-  if (jok) {
-    *jcurPtr = FALSE;
-    dcopy_f77(&lenmat, arkdls_mem->d_savedJ->data, 
-	      &one, arkdls_mem->d_M->data, &one);
-    
-  /* If jok = FALSE, call jac routine for new J value */
-  } else {
-    arkdls_mem->d_nje++;
-    arkdls_mem->d_nstlj = ark_mem->ark_nst;
-    *jcurPtr = TRUE;
-    SetToZero(arkdls_mem->d_M);
-
-    retval = arkdls_mem->d_bjac(arkdls_mem->d_n, arkdls_mem->d_mu, 
-				arkdls_mem->d_ml, ark_mem->ark_tn, 
-				yP, fctP, arkdls_mem->d_M, 
-				arkdls_mem->d_J_data, tmp1, tmp2, tmp3);
-    if (retval == 0) {
-      dcopy_f77(&lenmat, arkdls_mem->d_M->data, &one, 
-		arkdls_mem->d_savedJ->data, &one);
-    } else if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_JACFUNC_UNRECVR, "ARKLAPACK", 
-		      "arkLapackBandSetup", MSGD_JACFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_UNRECVR;
-      return(-1);
-    } else if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_JACFUNC_RECVR;
-      return(1);
-    }
-  }
-  
-  /* Scale J by -gamma */
-  fact = -ark_mem->ark_gamma;
-  dscal_f77(&lenmat, &fact, arkdls_mem->d_M->data, &one);
-  
-  /* Add mass matrix to get A = M-gamma*J*/
-  if (ark_mem->ark_mass_matrix) {
-
-    /* Compute mass matrix */
-    arkdls_mass_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-    SetToZero(arkdls_mass_mem->d_M);
-    retval = arkdls_mass_mem->d_bmass(arkdls_mass_mem->d_n, arkdls_mass_mem->d_mu, 
-				      arkdls_mass_mem->d_ml, ark_mem->ark_tn, 
-				      arkdls_mass_mem->d_M, arkdls_mass_mem->d_M_data, 
-				      tmp1, tmp2, tmp3);
-    arkdls_mass_mem->d_nme++;
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKLAPACK", 
-		      "arkLapackBandSetup",  MSGD_MASSFUNC_FAILED);
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-      return(1);
-    }
-
-    /* Add to A -- CURRENTLY ASSUMES THAT BOTH MATRICES HAVE 
-                   THE SAME BAND STRUCTURE AND COLUMN SIZE */
-    colSize = arkdls_mem->d_M->mu + arkdls_mem->d_M->ml + 1;
-    for (j=0; j<arkdls_mem->d_M->M; j++) {
-      Acol_j = arkdls_mem->d_M->cols[j] + arkdls_mem->d_M->s_mu - arkdls_mem->d_M->mu;
-      Mcol_j = arkdls_mass_mem->d_M->cols[j] + arkdls_mass_mem->d_M->s_mu 
-	     - arkdls_mass_mem->d_M->mu;
-      for (i=0; i<colSize; i++) 
-	Acol_j[i] += Mcol_j[i];
-    }
-  } else {
-    AddIdentity(arkdls_mem->d_M);
-  }
-  
-  /* Do LU factorization of M */
-  dgbtrf_f77(&intn, &intn, &iml, &imu, arkdls_mem->d_M->data, 
-	     &ldmat, arkdls_mem->d_pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  arkdls_mem->d_last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-
-}
-
-
-/*---------------------------------------------------------------
- arkLapackBandSolve handles the solve operation for the band 
- linear solver by calling the band backsolve routine.
----------------------------------------------------------------*/                  
-static int arkLapackBandSolve(ARKodeMem ark_mem, N_Vector b, 
-			      N_Vector weight, N_Vector yC, 
-			      N_Vector fctC)
-{
-  ARKDlsMem arkdls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn, iml, imu, ldmat;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  intn = (int) arkdls_mem->d_n;
-  iml = (int) arkdls_mem->d_ml;
-  imu = (int) arkdls_mem->d_mu;
-  ldmat = arkdls_mem->d_M->ldim;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgbtrs_f77("N", &intn, &iml, &imu, &one, arkdls_mem->d_M->data, 
-	     &ldmat, arkdls_mem->d_pivots, bd, &intn, &ier, 1);
-  if (ier > 0) return(1);
-
-  /* scale the correction to account for change in gamma */
-  if (ark_mem->ark_gamrat != ONE) {
-    fact = TWO/(ONE + ark_mem->ark_gamrat);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkLapackBandFree frees memory specific to the band linear 
- solver.
----------------------------------------------------------------*/                  
-static int arkLapackBandFree(ARKodeMem ark_mem)
-{
-  ARKDlsMem  arkdls_mem;
-
-  arkdls_mem = (ARKDlsMem) ark_mem->ark_lmem;
-  
-  DestroyMat(arkdls_mem->d_M);
-  DestroyArray(arkdls_mem->d_pivots);
-  DestroyMat(arkdls_mem->d_savedJ);
-  free(arkdls_mem); 
-  arkdls_mem = NULL;
-
-  return(0);
-}
-
-
-/*===============================================================
-  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND MASS MATRIX
-===============================================================*/
-
-/*---------------------------------------------------------------
- arkMassLapackBandInit does remaining initializations specific to 
- the band linear solver.
----------------------------------------------------------------*/                  
-static int arkMassLapackBandInit(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem arkdls_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  arkdls_mem->d_nme = 0;
-  arkdls_mem->d_M_data = ark_mem->ark_user_data;
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackBandSetup does the setup operations for the band 
- mass matrix solver. It constructs the mass matrix M, updates 
- counters, and calls the band LU factorization routine.
----------------------------------------------------------------*/                  
-static int arkMassLapackBandSetup(ARKodeMem ark_mem, N_Vector tmp1, 
-				  N_Vector tmp2, N_Vector tmp3)
-{
-  ARKDlsMassMem arkdls_mem;
-  int ier, retval;
-  int intn, iml, imu, ldmat;
-
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  intn = (int) arkdls_mem->d_n;
-  iml = (int) arkdls_mem->d_ml;
-  imu = (int) arkdls_mem->d_mu;
-  ldmat = arkdls_mem->d_M->ldim;
-
-  SetToZero(arkdls_mem->d_M);
-  retval = arkdls_mem->d_bmass(arkdls_mem->d_n, arkdls_mem->d_mu, 
-			       arkdls_mem->d_ml, ark_mem->ark_tn, 
-			       arkdls_mem->d_M, arkdls_mem->d_M_data, 
-			       tmp1, tmp2, tmp3);
-  arkdls_mem->d_nme++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, ARKDLS_MASSFUNC_UNRECVR, "ARKLAPACK", 
-		    "arkMassLapackBandSetup", MSGD_MASSFUNC_FAILED);
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_UNRECVR;
-    return(-1);
-  } else if (retval > 0) {
-    arkdls_mem->d_last_flag = ARKDLS_MASSFUNC_RECVR;
-    return(1);
-  }
-  
-  /* Do LU factorization of M */
-  dgbtrf_f77(&intn, &intn, &iml, &imu, arkdls_mem->d_M->data, 
-	     &ldmat, arkdls_mem->d_pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  arkdls_mem->d_last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackBandSolve handles the solve operation for the band 
- mass matrix solver by calling the band backsolve routine.
----------------------------------------------------------------*/                  
-static int arkMassLapackBandSolve(ARKodeMem ark_mem, N_Vector b, 
-				  N_Vector weight)
-{
-  ARKDlsMassMem arkdls_mem;
-  realtype *bd;
-  int ier, one = 1;
-  int intn, iml, imu, ldmat;
-
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  intn = (int) arkdls_mem->d_n;
-  iml = (int) arkdls_mem->d_ml;
-  imu = (int) arkdls_mem->d_mu;
-  ldmat = arkdls_mem->d_M->ldim;
-  bd = N_VGetArrayPointer(b);
-  dgbtrs_f77("N", &intn, &iml, &imu, &one, arkdls_mem->d_M->data, 
-	     &ldmat, arkdls_mem->d_pivots, bd, &intn, &ier, 1);
-  if (ier > 0) return(1);
-  arkdls_mem->d_last_flag = ARKDLS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackBandFree frees memory specific to the band mass
- matrix solver.
----------------------------------------------------------------*/                  
-static int arkMassLapackBandFree(ARKodeMem ark_mem)
-{
-  ARKDlsMassMem arkdls_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-  DestroyMat(arkdls_mem->d_M);
-  DestroyArray(arkdls_mem->d_pivots);
-  free(arkdls_mem); 
-  arkdls_mem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- arkMassLapackBandMultiply performs a matrix-vector product, 
- multiplying the current mass matrix by a given vector.
----------------------------------------------------------------*/                  
-static int arkMassLapackBandMultiply(N_Vector v, N_Vector Mv, 
-				     realtype t, void *arkode_mem)
-{
-  ARKodeMem ark_mem;
-  ARKDlsMassMem arkdls_mem;
-  realtype *vdata=NULL, *Mvdata=NULL;
-  realtype *Mcol_j;
-  int colSize, s_mu, i, j;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKDLS_MEM_NULL, "ARKLAPACK", 
-		    "arkMassLapackBandMultiply", MSGD_ARKMEM_NULL);
-    return(ARKDLS_MEM_NULL);
-  }
-
-  /* extract the DlsMassMem structure from the user_data pointer */
-  ark_mem = (ARKodeMem) arkode_mem;
-  arkdls_mem = (ARKDlsMassMem) ark_mem->ark_mass_mem;
-
-  /* zero out the result */
-  N_VConst(0.0, Mv);
-
-  /* access the vector arrays (since they must be serial vectors) */
-  vdata = N_VGetArrayPointer(v);
-  Mvdata = N_VGetArrayPointer(Mv);
-  if (vdata == NULL || Mvdata == NULL)
-    return(1);
-
-  /* perform matrix-vector product and return */
-  colSize = arkdls_mem->d_M->mu + arkdls_mem->d_M->ml + 1;
-  s_mu = arkdls_mem->d_M->s_mu;
-  for (j=0; j<arkdls_mem->d_M->M; j++) {
-    Mcol_j = arkdls_mem->d_M->cols[j] + arkdls_mem->d_M->s_mu - arkdls_mem->d_M->mu;
-    for (i=0; i<colSize; i++) 
-      Mvdata[i+j-s_mu] += Mcol_j[i]*vdata[j];
-  }
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
-     EOF
----------------------------------------------------------------*/                  
diff --git a/src/arkode/arkode_pcg.c b/src/arkode/arkode_pcg.c
deleted file mode 100644
index 21bf1f3..0000000
--- a/src/arkode/arkode_pcg.c
+++ /dev/null
@@ -1,772 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *--------------------------------------------------------------
- * This is the implementation file for the ARKPCG linear solver.
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_pcg.h>
-#include "arkode_spils_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_pcg.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* ARKPCG linit, lsetup, lsolve, and lfree routines */
-static int ARKPcgInit(ARKodeMem ark_mem);
-static int ARKPcgSetup(ARKodeMem ark_mem, int convfail, 
-		       N_Vector ypred, N_Vector fpred, 
-		       booleantype *jcurPtr, N_Vector vtemp1,
-		       N_Vector vtemp2, N_Vector vtemp3);
-static int ARKPcgSolve(ARKodeMem ark_mem, N_Vector b, 
-		       N_Vector weight, N_Vector ynow, 
-		       N_Vector fnow);
-static int ARKPcgFree(ARKodeMem ark_mem);
-
-/* ARKPCG minit, msetup, msolve, and mfree routines */
-static int ARKMassPcgInit(ARKodeMem ark_mem);
-static int ARKMassPcgSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			   N_Vector vtemp2, N_Vector vtemp3);
-static int ARKMassPcgSolve(ARKodeMem ark_mem, N_Vector b, 
-			   N_Vector weight);
-static int ARKMassPcgFree(ARKodeMem ark_mem);
-
-
-/*---------------------------------------------------------------
- ARKPcg:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Pcg linear solver module. 
- ARKPcg first calls the existing lfree routine if this is not 
- NULL. It then sets the ark_linit, ark_lsetup, ark_lsolve, 
- ark_lfree fields in (*arkode_mem) to be ARKPcgInit, 
- ARKPcgSetup, ARKPcgSolve, and ARKPcgFree, respectively. 
- It allocates memory for a structure of type ARKSpilsMemRec and 
- sets the ark_lmem field in (*arkode_mem) to the address of 
- this structure. It sets setupNonNull in (*arkode_mem),
- and sets various fields in the ARKSpilsMemRec structure.
- Finally, ARKPcg allocates memory for ytemp and x, and calls
- PcgMalloc to allocate memory for the Pcg solver.
----------------------------------------------------------------*/
-int ARKPcg(void *arkode_mem, int pretype, int maxl)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
-  PcgMem pcg_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKPCG", 
-		    "ARKPcg", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd and N_VWrmsNorm is present */
-  if ((ark_mem->ark_tempv->ops->nvdotprod == NULL) ||
-      (ark_mem->ark_tempv->ops->nvwrmsnorm == NULL)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKPCG", 
-		    "ARKPcg", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */
-  ark_mem->ark_linit  = ARKPcgInit;
-  ark_mem->ark_lsetup = ARKPcgSetup;
-  ark_mem->ark_lsolve = ARKPcgSolve;
-  ark_mem->ark_lfree  = ARKPcgFree;
-  ark_mem->ark_lsolve_type = 0;
-
-  /* Get memory for ARKSpilsMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMem) malloc(sizeof(struct ARKSpilsMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKPcg", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_PCG;
-
-  /* Set Pcg parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fields */
-  arkspils_mem->s_jtimesDQ = TRUE;
-  arkspils_mem->s_jtimes   = NULL;
-  arkspils_mem->s_j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-  arkspils_mem->s_nstlpre = arkspils_mem->s_njtimes = 0;
-  arkspils_mem->s_nfes = 0;
-
-  /* Set default values for the rest of the Pcg parameters */
-  arkspils_mem->s_eplifac   = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  ark_mem->ark_setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKPCG", 
-		    "ARKPcg", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKPcg", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKPcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt(N_VDotProd(arkspils_mem->s_ytemp, 
-					   arkspils_mem->s_ytemp));
-
-  /* Call PcgMalloc to allocate workspace for Pcg */
-  pcg_mem = NULL;
-  pcg_mem = PcgMalloc(mxl, ark_mem->ark_tempv);
-  if (pcg_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKPcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach PCG memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) pcg_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKPcgInit:
-
- This routine does remaining initializations specific to the 
- Pcg linear solver.
----------------------------------------------------------------*/
-static int ARKPcgInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  PcgMem pcg_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  pcg_mem = (PcgMem) arkspils_mem->s_spils_mem;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-  arkspils_mem->s_nstlpre = arkspils_mem->s_njtimes = 0;
-  arkspils_mem->s_nfes = 0;
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) && 
-      (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKPCG", 
-		    "ARKPcgInit", MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  ark_mem->ark_setupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (arkspils_mem->s_jtimesDQ) {
-    arkspils_mem->s_jtimes = ARKSpilsDQJtimes;
-    arkspils_mem->s_j_data = ark_mem;
-  } else {
-    arkspils_mem->s_j_data = ark_mem->ark_user_data;
-  }
-
-  /*  Set maxl in the PCG memory in case it was changed by the user */
-  pcg_mem->l_max = arkspils_mem->s_maxl;
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKPcgSetup:
-
- This routine does the setup operations for the Pcg linear 
- solver. It makes a decision as to whether or not to signal for 
- reevaluation of Jacobian data in the pset routine, based on 
- various state variables, then it calls pset. If we signal for 
- reevaluation, then we reset jcur = *jcurPtr to TRUE, regardless 
- of the pset output. In any case, if jcur == TRUE, we increment 
- npe and save nst in nstlpre.
----------------------------------------------------------------*/
-static int ARKPcgSetup(ARKodeMem ark_mem, int convfail, 
-		       N_Vector ypred, N_Vector fpred, 
-		       booleantype *jcurPtr, N_Vector vtemp1,
-		       N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  ARKSpilsMem arkspils_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkspils_mem->s_nstlpre + ARKSPILS_MSBPRE) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKSPILS_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, ypred, fpred, jok, 
-				jcurPtr, ark_mem->ark_gamma, 
-				arkspils_mem->s_P_data, vtemp1, 
-				vtemp2, vtemp3);
-  if (retval < 0) {
-    arkProcessError(ark_mem, PCG_PSET_FAIL_UNREC, "ARKPCG", 
-		    "ARKPcgSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = PCG_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = PCG_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    arkspils_mem->s_npe++;
-    arkspils_mem->s_nstlpre = ark_mem->ark_nst;
-  }
-
-  arkspils_mem->s_last_flag = PCG_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKPcgSolve:
-
- This routine handles the call to the generic solver PcgSolve
- for the solution of the linear system Ax = b with the PCG 
- method. The solution x is returned in the vector b.
-
- If the WRMS norm of b is small, we return x = b (if this is the 
- first Newton iteration) or x = 0 (if a later Newton iteration).
-
- Otherwise, we set the tolerance parameter and initial guess 
- (x = 0), call PcgSolve, and copy the solution x into b. The 
- x-scaling and b-scaling arrays are both equal to weight.
-
- The counters nli, nps, and ncfl are incremented, and the return 
- value is set according to the success of PcgSolve. The 
- success flag is returned if PcgSolve converged, or if this is 
- the first Newton iteration and the residual norm was reduced 
- below its initial value.
----------------------------------------------------------------*/
-static int ARKPcgSolve(ARKodeMem ark_mem, N_Vector b, 
-		       N_Vector weight, N_Vector ynow, 
-		       N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  ARKSpilsMem arkspils_mem;
-  PcgMem pcg_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  pcg_mem = (PcgMem) arkspils_mem->s_spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_eRNrm; 
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= arkspils_mem->s_deltar) {
-    if (ark_mem->ark_mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  arkspils_mem->s_ycur = ynow;
-  arkspils_mem->s_fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to PcgSolve */
-  arkspils_mem->s_delta = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  /* N_VConst(ark_mem->ark_uround, arkspils_mem->s_x); */
-
-  /* Call PcgSolve and copy x to b */
-  retval = PcgSolve(pcg_mem, ark_mem, arkspils_mem->s_x, b, 
-		    arkspils_mem->s_pretype, arkspils_mem->s_delta,
-		    ark_mem, weight, ARKSpilsAtimes, 
-		    ARKSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != PCG_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      kry  %19.16g  %19.16g  %i  %i\n", 
-	    bnorm, res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SpbcgSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case PCG_SUCCESS:
-    return 0;
-    break;
-  case PCG_RES_REDUCED:
-    /* allow reduction but not solution on first Newton iteration, 
-       otherwise return with a recoverable failure */
-    if (ark_mem->ark_mnewt == 0) return(0);
-    else                         return(1);
-    break;
-  case PCG_CONV_FAIL:
-    return 1;
-    break;
-  case PCG_PSOLVE_FAIL_REC:
-    return 1;
-    break;
-  case PCG_ATIMES_FAIL_REC:
-    return 1;
-    break;
-  case PCG_MEM_NULL:
-    return -1;
-    break;
-  case PCG_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, PCG_ATIMES_FAIL_UNREC, "ARKPCG", 
-		    "ARKPcgSolve", MSGS_JTIMES_FAILED);    
-    return -1;
-    break;
-  case PCG_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, PCG_PSOLVE_FAIL_UNREC, "ARKPCG", 
-		    "ARKPcgSolve", MSGS_PSOLVE_FAILED);
-    return -1;
-    break;
-  }
-
-  return 0;
-}
-
-
-/*---------------------------------------------------------------
- ARKPcgFree:
-
- This routine frees memory specific to the Pcg linear solver.
----------------------------------------------------------------*/
-static int ARKPcgFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  PcgMem pcg_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  pcg_mem = (PcgMem) arkspils_mem->s_spils_mem;
-  PcgFree(pcg_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassPcg:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Pcg mass matrix solver module. 
- ARKMassPcg first calls the existing mfree routine if this is not 
- NULL. It then sets the ark_minit, ark_msetup, ark_msolve, 
- ark_mfree fields in (*arkode_mem) to be ARKMassPcgInit, 
- ARKMassPcgSetup, ARKMassPcgSolve, and ARKMassPcgFree, 
- respectively. It sets MassSetupNonNull in (*arkode_mem), 
- allocates memory for a structure of type ARKSpilsMassMemRec and 
- sets the ark_mass_mem field in (*arkode_mem) to the address of 
- this structure.  Finally, ARKMassPcg allocates memory for ytemp 
- and x, and calls PcgMalloc to allocate memory for the Pcg solver.
----------------------------------------------------------------*/
-int ARKMassPcg(void *arkode_mem, int pretype, int maxl, 
-	       ARKSpilsMassTimesVecFn mtimes, void *mtimes_data)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
-  PcgMem pcg_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKPCG", 
-		    "ARKMassPcg", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd and N_VWrmsNorm is present */
-  if ((ark_mem->ark_tempv->ops->nvdotprod == NULL) ||
-      (ark_mem->ark_tempv->ops->nvwrmsnorm == NULL)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKPCG", 
-		    "ARKMassPcg", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = ARKMassPcgInit;
-  ark_mem->ark_msetup = ARKMassPcgSetup;
-  ark_mem->ark_msolve = ARKMassPcgSolve;
-  ark_mem->ark_mfree  = ARKMassPcgFree;
-  ark_mem->ark_msolve_type = 0;
-
-  /* Get memory for ARKSpilsMassMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMassMem) malloc(sizeof(struct ARKSpilsMassMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKMassPcg", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set mass-matrix-vector product routine */
-  ark_mem->ark_mtimes      = mtimes;
-  ark_mem->ark_mtimes_data = mtimes_data;
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_PCG;
-
-  /* Set Pcg parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype    = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Set default values for the rest of the Pcg parameters */
-  arkspils_mem->s_eplifac       = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag     = ARKSPILS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKPCG", 
-		    "ARKMassPcg", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKMassPcg", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKMassPcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt(N_VDotProd(arkspils_mem->s_ytemp, 
-					   arkspils_mem->s_ytemp));
-
-  /* Call PcgMalloc to allocate workspace for Pcg */
-  pcg_mem = NULL;
-  pcg_mem = PcgMalloc(mxl, ark_mem->ark_tempv);
-  if (pcg_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKPCG", 
-		    "ARKMassPcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach PCG memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) pcg_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassPcgInit:
-
- This routine does remaining initializations specific to the 
- Pcg linear solver.
----------------------------------------------------------------*/
-static int ARKMassPcgInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  PcgMem pcg_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  pcg_mem = (PcgMem) arkspils_mem->s_spils_mem;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) && 
-      (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKPCG", 
-		    "ARKMassPcgInit", MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set MassSetupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  ark_mem->ark_MassSetupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  /* Set maxl in the PCG memory in case it was changed by the user */
-  pcg_mem->l_max = arkspils_mem->s_maxl;
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassPcgSetup:
-
- This routine does the setup operations for the Pcg linear 
- solver. It makes a decision as to whether or not to signal for 
- reevaluation of Jacobian data in the pset routine, based on 
- various state variables, then it calls pset.
----------------------------------------------------------------*/
-static int ARKMassPcgSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			   N_Vector vtemp2, N_Vector vtemp3)
-{
-  int  retval;
-  ARKSpilsMassMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Call pset routine */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, 
-				arkspils_mem->s_P_data, 
-				vtemp1, vtemp2, vtemp3);
-  arkspils_mem->s_npe++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, PCG_PSET_FAIL_UNREC, "ARKPCG", 
-		    "ARKMassPcgSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = PCG_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = PCG_PSET_FAIL_REC;
-  }
-  if (retval == 0) {
-    arkspils_mem->s_last_flag = PCG_SUCCESS;
-  }
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassPcgSolve:
-
- This routine handles the call to the generic solver PcgSolve
- for the solution of the mass matrix system Mx = b with the PCG 
- method. The solution x is returned in the vector b.
-
- We set the tolerance parameter and initial guess 
- (x = 0), call PcgSolve, and copy the solution x into b. The 
- x-scaling and b-scaling arrays are both equal to weight.
-
- The counters nli, nps, and ncfl are incremented, and the return 
- value is set according to the success of PcgSolve. The 
- success flag is returned if PcgSolve converged.
----------------------------------------------------------------*/
-static int ARKMassPcgSolve(ARKodeMem ark_mem, N_Vector b, 
-			   N_Vector weight)
-{
-  realtype res_norm;
-  ARKSpilsMassMem arkspils_mem;
-  PcgMem pcg_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  pcg_mem = (PcgMem) arkspils_mem->s_spils_mem;
-
-  /* Set inputs delta and initial guess x = 0 to PcgSolve */
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_nlscoef; 
-  arkspils_mem->s_delta  = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-
-  /* Call PcgSolve and copy x to b */
-  retval = PcgSolve(pcg_mem, ark_mem, arkspils_mem->s_x, b, 
-		    arkspils_mem->s_pretype, arkspils_mem->s_delta,
-		    ark_mem, weight, ARKSpilsMtimes, 
-		    ARKSpilsMPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != PCG_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      mass  %19.16g  %i  %i\n", 
-	    res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from PcgSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case PCG_SUCCESS:
-    return 0;
-    break;
-  case PCG_RES_REDUCED:
-    return 1;
-    break;
-  case PCG_CONV_FAIL:
-    return 1;
-    break;
-  case PCG_PSOLVE_FAIL_REC:
-    return 1;
-    break;
-  case PCG_ATIMES_FAIL_REC:
-    return 1;
-    break;
-  case PCG_MEM_NULL:
-    return -1;
-    break;
-  case PCG_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, PCG_ATIMES_FAIL_UNREC, "ARKPCG", 
-		    "ARKMassPcgSolve", MSGS_MTIMES_FAILED);
-    return -1;
-    break;
-  case PCG_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, PCG_PSOLVE_FAIL_UNREC, "ARKPCG", 
-		    "ARKMassPcgSolve", MSGS_PSOLVE_FAILED);
-    return -1;
-    break;
-  }
-
-  return 0;
-}
-
-
-/*---------------------------------------------------------------
- ARKMassPcgFree:
-
- This routine frees memory specific to the Pcg linear solver.
----------------------------------------------------------------*/
-static int ARKMassPcgFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  PcgMem pcg_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  pcg_mem = (PcgMem) arkspils_mem->s_spils_mem;
-  PcgFree(pcg_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
-     EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_sparse.c b/src/arkode/arkode_sparse.c
deleted file mode 100644
index c00a0d0..0000000
--- a/src/arkode/arkode_sparse.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Implementation file for the generic ARKSLS linear solver module.
- *---------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "arkode_impl.h"
-#include "arkode_sparse_impl.h"
-#include <sundials/sundials_math.h>
-
-/*===============================================================
- FUNCTION SPECIFIC CONSTANTS (none)
-===============================================================*/
-
-/*===============================================================
- EXPORTED FUNCTIONS
-===============================================================*/
-              
-/*---------------------------------------------------------------
- ARKSlsSetSparseJacFn specifies the sparse Jacobian function.
----------------------------------------------------------------*/
-int ARKSlsSetSparseJacFn(void *arkode_mem, ARKSlsSparseJacFn jac)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		   "ARKSlsSetSparseJacFn", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_LMEM_NULL, "ARKSLS", 
-		    "ARKSlsSetSparseJacFn", MSGSP_LMEM_NULL);
-    return(ARKSLS_LMEM_NULL);
-  }
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-
-  arksls_mem->s_Jeval = jac;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSlsSetSparseMassFn specifies the sparse mass matrix function.
----------------------------------------------------------------*/
-int ARKSlsSetSparseMassFn(void *arkode_mem, ARKSlsSparseMassFn mass)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		   "ARKSlsSetSparseMassFn", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MASSMEM_NULL, "ARKSLS", 
-		    "ARKSlsSetSparseMassFn", MSGSP_MASSMEM_NULL);
-    return(ARKSLS_MASSMEM_NULL);
-  }
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-
-  arksls_mem->s_Meval = mass;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSlsGetNumJacEvals returns the number of Jacobian evaluations.
----------------------------------------------------------------*/
-int ARKSlsGetNumJacEvals(void *arkode_mem, long int *njevals)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		   "ARKSlsGetNumJacEvals", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_LMEM_NULL, "ARKSLS", 
-		    "ARKSlsGetNumJacEvals", MSGSP_LMEM_NULL);
-    return(ARKSLS_LMEM_NULL);
-  }
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-
-  *njevals = arksls_mem->s_nje;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-
-/*---------------------------------------------------------------
- ARKSlsGetNumMassEvals returns the number of mass matrix evaluations.
----------------------------------------------------------------*/
-int ARKSlsGetNumMassEvals(void *arkode_mem, long int *nmevals)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		   "ARKSlsGetNumMassEvals", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MASSMEM_NULL, "ARKSLS", 
-		    "ARKSlsGetNumMassEvals", MSGSP_MASSMEM_NULL);
-    return(ARKSLS_MASSMEM_NULL);
-  }
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-
-  *nmevals = arksls_mem->s_nme;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSlsGetReturnFlagName returns the name associated with a 
- ARKSLS return value.
----------------------------------------------------------------*/
-char *ARKSlsGetReturnFlagName(long int flag)
-{
-  char *name;
-
-  name = (char *)malloc(30*sizeof(char));
-
-  switch(flag) {
-  case ARKSLS_SUCCESS:
-    sprintf(name,"ARKSLS_SUCCESS");
-    break;   
-  case ARKSLS_MEM_NULL:
-    sprintf(name,"ARKSLS_MEM_NULL");
-    break;
-  case ARKSLS_LMEM_NULL:
-    sprintf(name,"ARKSLS_LMEM_NULL");
-    break;
-  case ARKSLS_ILL_INPUT:
-    sprintf(name,"ARKSLS_ILL_INPUT");
-    break;
-  case ARKSLS_MEM_FAIL:
-    sprintf(name,"ARKSLS_MEM_FAIL");
-    break;
-  case ARKSLS_JAC_NOSET:
-    sprintf(name,"ARKSLS_JAC_NOSET");
-    break;
-  case ARKSLS_PACKAGE_FAIL:
-    sprintf(name,"ARKSLS_PACKAGE_FAIL");
-    break;
-  case ARKSLS_MASSMEM_NULL:
-    sprintf(name,"ARKSLS_MASSMEM_NULL");
-    break;
-  case ARKSLS_JACFUNC_UNRECVR:
-    sprintf(name,"ARKSLS_JACFUNC_UNRECVR");
-    break;
-  case ARKSLS_JACFUNC_RECVR:
-    sprintf(name,"ARKSLS_JACFUNC_RECVR");
-    break;
-  case ARKSLS_MASSFUNC_UNRECVR:
-    sprintf(name,"ARKSLS_MASSFUNC_UNRECVR");
-    break;
-  case ARKSLS_MASSFUNC_RECVR:
-    sprintf(name,"ARKSLS_MASSFUNC_RECVR");
-    break;
-  default:
-    sprintf(name,"NONE");
-  }
-
-  return(name);
-}
-
-
-/*---------------------------------------------------------------
- ARKSlsGetLastFlag returns the last flag set in a ARKSLS function.
----------------------------------------------------------------*/
-int ARKSlsGetLastFlag(void *arkode_mem, long int *flag)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKSlsGetLastFlag", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_LMEM_NULL, "ARKSLS", 
-		    "ARKSlsGetLastFlag", MSGSP_LMEM_NULL);
-    return(ARKSLS_LMEM_NULL);
-  }
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-
-  *flag = arksls_mem->s_last_flag;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSlsGetLastMassFlag returns the last flag set in a ARKSLS mass
- matrix function.
----------------------------------------------------------------*/
-int ARKSlsGetLastMassFlag(void *arkode_mem, long int *flag)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKSlsGetLastMassFlag", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MASSMEM_NULL, "ARKSLS", 
-		    "ARKSlsGetLastMassFlag", MSGSP_MASSMEM_NULL);
-    return(ARKSLS_MASSMEM_NULL);
-  }
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-
-  *flag = arksls_mem->s_last_flag;
-
-  return(ARKSLS_SUCCESS);
-}
-
-/*---------------------------------------------------------------
-    EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_sparse_impl.h b/src/arkode/arkode_sparse_impl.h
deleted file mode 100644
index 331bd78..0000000
--- a/src/arkode/arkode_sparse_impl.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Implementation header file for the generic ARKSLS linear solver 
- * module.
- *---------------------------------------------------------------*/
-
-#ifndef _ARKSPARSE_IMPL_H
-#define _ARKSPARSE_IMPL_H
-
-#include "arkode/arkode_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*---------------------------------------------------------------
- ARKSLS solver constants:
-
- ARKS_MSBJ   maximum number of steps between Jacobian evaluations
- ARKS_DGMAX  maximum change in gamma between Jacobian evaluations
----------------------------------------------------------------*/
-#define ARKS_MSBJ  50
-#define ARKS_DGMAX RCONST(0.2)
-
- 
-/*---------------------------------------------------------------
- Types: ARKSlsMemRec, ARKSlsMem
-
- ARKSlsMem is pointer to a ARKSlsMemRec structure.
----------------------------------------------------------------*/
-
-typedef struct ARKSlsMemRec {
-
-  ARKSlsSparseJacFn s_Jeval; /* user Jacobian evaluation routine 
-                                to be called                   */
-  void *s_Jdata;             /* user data passed to s_Jeval    */
-
-  long int s_nje;            /* nje = no. of calls to s_Jeval  */
-
-  long int s_last_flag;      /* last error return flag         */
-
-  int s_first_factorize;     /* flag telling whether the first 
-			        factorization needs to happen  */
-
-  int s_nstlj;               /* time step of last J evaluation */
-
-  SlsMat s_A;                /* A = M - gamma * df/dy          */
-
-  SlsMat s_savedJ;           /* saved copy of Jacobian         */
-
-  int sparsetype;            /* matrix type: compressed sparse column or row */
-
-  void *s_solver_data;       /* struct for solver data         */
-
-} *ARKSlsMem;
-
-
-/*---------------------------------------------------------------
- Types: ARKSlsMassMemRec, ARKSlsMassMem
-
- ARKSlsMassMem is pointer to a ARKSlsMassMemRec structure.
----------------------------------------------------------------*/
-
-typedef struct ARKSlsMassMemRec {
-
-  ARKSlsSparseMassFn s_Meval; /* user mass matrix evaluation 
-                                    routine to be called       */
-  void *s_Mdata;              /* user data passed to s_Meval   */
-
-  long int s_nme;             /* nme = no. of calls to s_Meval */
-
-  long int s_last_flag;       /* last error return flag        */
-
-  int s_first_factorize;      /* flag telling whether the first 
-			         factorization needs to happen */
-
-  SlsMat s_M;                 /* mass matrix structure         */
-
-  SlsMat s_M_lu;              /* mass matrix for LU decomp     */
-
-  int sparsetype;             /* matrix type: compressed sparse column or row */
-
-  void *s_solver_data;        /* struct for solver data        */
-
-} *ARKSlsMassMem;
-
-
-/*---------------------------------------------------------------
- Prototypes of internal functions (none)
----------------------------------------------------------------*/
-  
-
-/*---------------------------------------------------------------
- Error Messages
----------------------------------------------------------------*/
-#define MSGSP_ARKMEM_NULL     "Integrator memory is NULL."
-#define MSGSP_BAD_NVECTOR     "A required vector operation is not implemented."
-#define MSGSP_MEM_FAIL        "A memory request failed."
-#define MSGSP_LMEM_NULL       "Linear solver memory is NULL."
-#define MSGSP_MASSMEM_NULL    "Mass matrix solver memory is NULL."
-#define MSGSP_ILL_INPUT       "Invalid input detected."
-#define MSGSP_JAC_NOSET       "Jacobian evaluation function has not been set."
-#define MSGSP_MASS_NOSET      "Mass matrix evaluation function has not been set."
-#define MSGSP_JACFUNC_FAILED  "The Jacobian routine failed in an unrecoverable manner."
-#define MSGSP_MASSFUNC_FAILED "The mass matrix routine failed in an unrecoverable manner."
-#define MSGSP_PACKAGE_FAIL    "A call to an external package failed."
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/arkode/arkode_spbcgs.c b/src/arkode/arkode_spbcgs.c
deleted file mode 100644
index 6bbed59..0000000
--- a/src/arkode/arkode_spbcgs.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the implementation file for the ARKSPBCG linear solver.
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_spbcgs.h>
-#include "arkode_spils_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_spbcgs.h>
-#include <sundials/sundials_math.h>
-
-
-/* Constants */
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* ARKSPBCG linit, lsetup, lsolve, and lfree routines */
-static int ARKSpbcgInit(ARKodeMem ark_mem);
-static int ARKSpbcgSetup(ARKodeMem ark_mem, int convfail, 
-			 N_Vector ypred, N_Vector fpred, 
-			 booleantype *jcurPtr, N_Vector vtemp1,
-			 N_Vector vtemp2, N_Vector vtemp3);
-static int ARKSpbcgSolve(ARKodeMem ark_mem, N_Vector b, 
-			 N_Vector weight, N_Vector ynow, 
-			 N_Vector fnow);
-static int ARKSpbcgFree(ARKodeMem ark_mem);
-
-/* ARKSPBCG minit, msetup, msolve, and mfree routines */
-static int ARKMassSpbcgInit(ARKodeMem ark_mem);
-static int ARKMassSpbcgSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			     N_Vector vtemp2, N_Vector vtemp3);
-static int ARKMassSpbcgSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight);
-static int ARKMassSpbcgFree(ARKodeMem ark_mem);
-
-
-/*---------------------------------------------------------------
- ARKSpbcg:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Spbcg linear solver module. 
- ARKSpbcg first calls the existing lfree routine if this is not 
- NULL. It then sets the ark_linit, ark_lsetup, ark_lsolve, 
- ark_lfree fields in (*arkode_mem) to be ARKSpbcgInit, 
- ARKSpbcgSetup, ARKSpbcgSolve, and ARKSpbcgFree, respectively. 
- It allocates memory for a structure of type ARKSpilsMemRec and 
- sets the ark_lmem field in (*arkode_mem) to the address of 
- this structure. It sets setupNonNull in (*arkode_mem),
- and sets various fields in the ARKSpilsMemRec structure.
- Finally, ARKSpbcg allocates memory for ytemp and x, and calls
- SpbcgMalloc to allocate memory for the Spbcg solver.
----------------------------------------------------------------*/
-int ARKSpbcg(void *arkode_mem, int pretype, int maxl)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPBCG", 
-		    "ARKSpbcg", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd and N_VProd are present */
-  if ((ark_mem->ark_tempv->ops->nvdotprod == NULL) ||
-      (ark_mem->ark_tempv->ops->nvprod == NULL)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPBCG", 
-		    "ARKSpbcg", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */
-  ark_mem->ark_linit  = ARKSpbcgInit;
-  ark_mem->ark_lsetup = ARKSpbcgSetup;
-  ark_mem->ark_lsolve = ARKSpbcgSolve;
-  ark_mem->ark_lfree  = ARKSpbcgFree;
-  ark_mem->ark_lsolve_type = 0;
-
-  /* Get memory for ARKSpilsMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMem) malloc(sizeof(struct ARKSpilsMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKSpbcg", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPBCG;
-
-  /* Set Spbcg parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fields */
-  arkspils_mem->s_jtimesDQ = TRUE;
-  arkspils_mem->s_jtimes   = NULL;
-  arkspils_mem->s_j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Set default values for the rest of the Spbcg parameters */
-  arkspils_mem->s_eplifac = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  ark_mem->ark_setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPBCG", 
-		    "ARKSpbcg", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKSpbcg", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt(N_VDotProd(arkspils_mem->s_ytemp, 
-					   arkspils_mem->s_ytemp));
-
-  /* Call SpbcgMalloc to allocate workspace for Spbcg */
-  spbcg_mem = NULL;
-  spbcg_mem = SpbcgMalloc(mxl, ark_mem->ark_tempv);
-  if (spbcg_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPBCG memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) spbcg_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpbcgInit:
-
- This routine does remaining initializations specific to the 
- Spbcg linear solver.
----------------------------------------------------------------*/
-static int ARKSpbcgInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  spbcg_mem = (SpbcgMem) arkspils_mem->s_spils_mem;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) && 
-      (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPBCG", 
-                    "ARKSpbcgInit", MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  ark_mem->ark_setupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (arkspils_mem->s_jtimesDQ) {
-    arkspils_mem->s_jtimes = ARKSpilsDQJtimes;
-    arkspils_mem->s_j_data = ark_mem;
-  } else {
-    arkspils_mem->s_j_data = ark_mem->ark_user_data;
-  }
-
-  /*  Set maxl in the SPBCG memory in case it was changed by the user */
-  spbcg_mem->l_max  = arkspils_mem->s_maxl;
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpbcgSetup:
-
- This routine does the setup operations for the Spbcg linear 
- solver. It makes a decision as to whether or not to signal for 
- reevaluation of Jacobian data in the pset routine, based on 
- various state variables, then it calls pset. If we signal for 
- reevaluation, then we reset jcur = *jcurPtr to TRUE, regardless 
- of the pset output. In any case, if jcur == TRUE, we increment 
- npe and save nst in nstlpre.
----------------------------------------------------------------*/
-static int ARKSpbcgSetup(ARKodeMem ark_mem, int convfail, 
-			 N_Vector ypred, N_Vector fpred, 
-			 booleantype *jcurPtr, N_Vector vtemp1,
-			 N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  ARKSpilsMem arkspils_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkspils_mem->s_nstlpre + ARKSPILS_MSBPRE) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKSPILS_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, ypred, fpred, jok, 
-				jcurPtr, ark_mem->ark_gamma, 
-				arkspils_mem->s_P_data, vtemp1, 
-				vtemp2, vtemp3);
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPBCG_PSET_FAIL_UNREC, "ARKSPBCG", 
-		    "ARKSpbcgSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPBCG_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = SPBCG_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    arkspils_mem->s_npe++;
-    arkspils_mem->s_nstlpre = ark_mem->ark_nst;
-  }
-
-  arkspils_mem->s_last_flag = SPBCG_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpbcgSolve:
-
- This routine handles the call to the generic solver SpbcgSolve
- for the solution of the linear system Ax = b with the SPBCG 
- method. The solution x is returned in the vector b.
-
- If the WRMS norm of b is small, we return x = b (if this is the 
- first Newton iteration) or x = 0 (if a later Newton iteration).
-
- Otherwise, we set the tolerance parameter and initial guess 
- (x = 0), call SpbcgSolve, and copy the solution x into b. The 
- x-scaling and b-scaling arrays are both equal to weight.
-
- The counters nli, nps, and ncfl are incremented, and the return 
- value is set according to the success of SpbcgSolve. The 
- success flag is returned if SpbcgSolve converged, or if this is 
- the first Newton iteration and the residual norm was reduced 
- below its initial value.
----------------------------------------------------------------*/
-static int ARKSpbcgSolve(ARKodeMem ark_mem, N_Vector b, 
-			 N_Vector weight, N_Vector ynow, 
-			 N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  ARKSpilsMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  spbcg_mem = (SpbcgMem) arkspils_mem->s_spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_eRNrm; 
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= arkspils_mem->s_deltar) {
-    if (ark_mem->ark_mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  arkspils_mem->s_ycur = ynow;
-  arkspils_mem->s_fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SpbcgSolve */  
-  arkspils_mem->s_delta = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SpbcgSolve and copy x to b */
-  retval = SpbcgSolve(spbcg_mem, ark_mem, arkspils_mem->s_x, b, 
-		      arkspils_mem->s_pretype, arkspils_mem->s_delta,
-		      ark_mem, weight, weight, ARKSpilsAtimes, 
-		      ARKSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPBCG_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      kry  %19.16g  %19.16g  %i  %i\n", 
-	    bnorm, res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SpbcgSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPBCG_SUCCESS:
-    return(0);
-    break;
-  case SPBCG_RES_REDUCED:
-    /* allow reduction but not solution on first Newton iteration, 
-       otherwise return with a recoverable failure */
-    if (ark_mem->ark_mnewt == 0) return(0);
-    else                         return(1);
-    break;
-  case SPBCG_CONV_FAIL:
-    return(1);
-    break;
-  case SPBCG_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_MEM_NULL:
-    return(-1);
-    break;
-  case SPBCG_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPBCG_ATIMES_FAIL_UNREC, "ARKSPBCG", 
-		    "ARKSpbcgSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPBCG_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPBCG_PSOLVE_FAIL_UNREC, "ARKSPBCG", 
-		    "ARKSpbcgSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpbcgFree:
-
- This routine frees memory specific to the Spbcg linear solver.
----------------------------------------------------------------*/
-static int ARKSpbcgFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  spbcg_mem = (SpbcgMem) arkspils_mem->s_spils_mem;
-  SpbcgFree(spbcg_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-
-/*---------------------------------------------------------------
- ARKMassSpbcg:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Spbcg mass matrix solver module. 
- ARKMassSpbcg first calls the existing mfree routine if this is 
- not NULL. It then sets the ark_minit, ark_msetup, ark_msolve, 
- ark_mfree fields in (*arkode_mem) to be ARKMassSpbcgInit, 
- ARKMassSpbcgSetup, ARKMassSpbcgSolve, and ARKMassSpbcgFree, 
- respectively. It allocates memory for a structure of type 
- ARKSpilsMassMemRec and sets the ark_mass_mem field in
- (*arkode_mem) to the address of this structure. It sets 
- MassSetupNonNull in (*arkode_mem), and sets various fields in
- the ARKSpilsMassMemRec structure, allocates memory for ytemp 
- and x, and calls SpbcgMalloc to allocate memory for the Spbcg 
- solver.
----------------------------------------------------------------*/
-int ARKMassSpbcg(void *arkode_mem, int pretype, int maxl, 
-		 ARKSpilsMassTimesVecFn mtimes, void *mtimes_data)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPBCG", 
-		    "ARKMassSpbcg", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd is present */
-  if (ark_mem->ark_tempv->ops->nvdotprod == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPBCG", 
-		    "ARKMassSpbcg", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = ARKMassSpbcgInit;
-  ark_mem->ark_msetup = ARKMassSpbcgSetup;
-  ark_mem->ark_msolve = ARKMassSpbcgSolve;
-  ark_mem->ark_mfree  = ARKMassSpbcgFree;
-  ark_mem->ark_msolve_type = 0;
-
-  /* Get memory for ARKSpilsMassMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMassMem) malloc(sizeof(struct ARKSpilsMassMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKMassSpbcg", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set mass-matrix-vector product routine */
-  ark_mem->ark_mtimes      = mtimes;
-  ark_mem->ark_mtimes_data = mtimes_data;
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPBCG;
-
-  /* Set Spbcg parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype    = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Set default values for the rest of the Spbcg parameters */
-  arkspils_mem->s_eplifac       = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag     = ARKSPILS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPBCG", 
-		    "ARKMassSpbcg", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKMassSpbcg", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKMassSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt(N_VDotProd(arkspils_mem->s_ytemp, 
-					   arkspils_mem->s_ytemp));
-
-  /* Call SpbcgMalloc to allocate workspace for Spbcg */
-  spbcg_mem = NULL;
-  spbcg_mem = SpbcgMalloc(mxl, ark_mem->ark_tempv);
-  if (spbcg_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPBCG", 
-		    "ARKMassSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPBCG memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) spbcg_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpbcgInit:
-
- This routine does remaining initializations specific to the 
- Spbcg linear solver.
----------------------------------------------------------------*/
-static int ARKMassSpbcgInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  spbcg_mem = (SpbcgMem) arkspils_mem->s_spils_mem;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) && 
-      (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPBCG", 
-		    "ARKMassSpbcgInit", MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set MassSetupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  ark_mem->ark_MassSetupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  /*  Set maxl in the SPBCG memory in case it was changed by the user */
-  spbcg_mem->l_max = arkspils_mem->s_maxl;
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpbcgSetup:
-
- This routine does the setup operations for the Spbcg mass matrix 
- solver. It calls pset and increments npe.
----------------------------------------------------------------*/
-static int ARKMassSpbcgSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			     N_Vector vtemp2, N_Vector vtemp3)
-{
-  int  retval;
-  ARKSpilsMassMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Call pset routine */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, 
-				arkspils_mem->s_P_data, 
-				vtemp1, vtemp2, vtemp3);
-  arkspils_mem->s_npe++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPBCG_PSET_FAIL_UNREC, "ARKSPBCG", 
-		    "ARKMassSpbcgSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPBCG_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = SPBCG_PSET_FAIL_REC;
-  }
-  if (retval == 0) {
-    arkspils_mem->s_last_flag = SPBCG_SUCCESS;
-  }
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpbcgSolve:
-
- This routine handles the call to the generic solver SpbcgSolve
- for the solution of the mass matrix system Mx = b with the SPBCG 
- method. The solution x is returned in the vector b.
-
- We set the tolerance parameter and initial guess (x = 0), call
- SpbcgSolve, and copy the solution x into b. The 
- x-scaling and b-scaling arrays are both equal to weight.
-
- The counters nli, nps, and ncfl are incremented, and the return 
- value is set according to the success of SpbcgSolve.
----------------------------------------------------------------*/
-static int ARKMassSpbcgSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight)
-{
-  realtype res_norm;
-  ARKSpilsMassMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  spbcg_mem = (SpbcgMem) arkspils_mem->s_spils_mem;
-
-  /* Set inputs delta and initial guess x = 0 to SpbcgSolve */  
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_nlscoef; 
-  arkspils_mem->s_delta  = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SpbcgSolve and copy x to b */
-  retval = SpbcgSolve(spbcg_mem, ark_mem, arkspils_mem->s_x, b, 
-		      arkspils_mem->s_pretype, arkspils_mem->s_delta,
-		      ark_mem, weight, weight, ARKSpilsMtimes, 
-		      ARKSpilsMPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPBCG_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      mass  %19.16g  %i  %i\n", 
-	    res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SpbcgSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPBCG_SUCCESS:
-    return(0);
-    break;
-  case SPBCG_RES_REDUCED:
-    return(1);
-    break;
-  case SPBCG_CONV_FAIL:
-    return(1);
-    break;
-  case SPBCG_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_MEM_NULL:
-    return(-1);
-    break;
-  case SPBCG_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPBCG_ATIMES_FAIL_UNREC, "ARKSPBCG", 
-		    "ARKMassSpbcgSolve", MSGS_MTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPBCG_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPBCG_PSOLVE_FAIL_UNREC, "ARKSPBCG", 
-		    "ARKMassSpbcgSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpbcgFree:
-
- This routine frees memory specific to the Spbcg mass matrix solver.
----------------------------------------------------------------*/
-static int ARKMassSpbcgFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  SpbcgMem spbcg_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  spbcg_mem = (SpbcgMem) arkspils_mem->s_spils_mem;
-  SpbcgFree(spbcg_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_mass_mem = NULL;
-  
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
-     EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_spfgmr.c b/src/arkode/arkode_spfgmr.c
deleted file mode 100644
index 4b7932d..0000000
--- a/src/arkode/arkode_spfgmr.c
+++ /dev/null
@@ -1,777 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the implementation file for the ARKSPFGMR linear solver.
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_spfgmr.h>
-#include "arkode_spils_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_spfgmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* ARKSPFGMR linit, lsetup, lsolve, and lfree routines */
-static int ARKSpfgmrInit(ARKodeMem ark_mem);
-static int ARKSpfgmrSetup(ARKodeMem ark_mem, int convfail, 
-			  N_Vector ypred, N_Vector fpred, 
-			  booleantype *jcurPtr, N_Vector vtemp1,
-			  N_Vector vtemp2, N_Vector vtemp3);
-static int ARKSpfgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			  N_Vector weight, N_Vector ynow, 
-			  N_Vector fnow);
-static int ARKSpfgmrFree(ARKodeMem ark_mem);
-
-/* ARKSPFGMR minit, msetup, msolve, and mfree routines */
-static int ARKMassSpfgmrInit(ARKodeMem ark_mem);
-static int ARKMassSpfgmrSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			      N_Vector vtemp2, N_Vector vtemp3);
-static int ARKMassSpfgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			      N_Vector weight);
-static int ARKMassSpfgmrFree(ARKodeMem ark_mem);
-
-
-/*---------------------------------------------------------------
- ARKSpfgmr:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Spfgmr linear solver module. 
- ARKSpfgmr first calls the existing lfree routine if this is not 
- NULL.  It then sets the ark_linit, ark_lsetup, ark_lsolve, 
- ark_lfree fields in (*arkode_mem) to be ARKSpfgmrInit, 
- ARKSpfgmrSetup, ARKSpfgmrSolve, and ARKSpfgmrFree, respectively.  
- It allocates memory for a structure of type ARKSpilsMemRec and
- sets the ark_lmem field in (*arkode_mem) to the address of this
- structure.  It sets setupNonNull in (*arkode_mem), and sets 
- various fields in the ARKSpilsMemRec structure. Finally, 
- ARKSpfgmr allocates memory for ytemp and x, and calls
- SpfgmrMalloc to allocate memory for the Spfgmr solver.
----------------------------------------------------------------*/
-int ARKSpfgmr(void *arkode_mem, int pretype, int maxl)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
-  SpfgmrMem spfgmr_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPFGMR", 
-		    "ARKSpfgmr", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd and N_VProd are present */
-  if ((ark_mem->ark_tempv->ops->nvdotprod == NULL) ||
-      (ark_mem->ark_tempv->ops->nvprod == NULL)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPFGMR", 
-		    "ARKSpfgmr", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */
-  ark_mem->ark_linit  = ARKSpfgmrInit;
-  ark_mem->ark_lsetup = ARKSpfgmrSetup;
-  ark_mem->ark_lsolve = ARKSpfgmrSolve;
-  ark_mem->ark_lfree  = ARKSpfgmrFree;
-  ark_mem->ark_lsolve_type = 0;
-
-  /* Get memory for ARKSpilsMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMem) malloc(sizeof(struct ARKSpilsMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKSpfgmr", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPFGMR;
-
-  /* Set Spfgmr parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype    = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fields */
-  arkspils_mem->s_jtimesDQ = TRUE;
-  arkspils_mem->s_jtimes   = NULL;
-  arkspils_mem->s_j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Set default values for the rest of the Spfgmr parameters */
-  arkspils_mem->s_gstype    = MODIFIED_GS;
-  arkspils_mem->s_eplifac   = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  ark_mem->ark_setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPFGMR", 
-		    "ARKSpfgmr", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKSpfgmr", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKSpfgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt( N_VDotProd(arkspils_mem->s_ytemp, 
-					    arkspils_mem->s_ytemp) );
-
-  /* Call SpfgmrMalloc to allocate workspace for Spfgmr */
-  spfgmr_mem = NULL;
-  spfgmr_mem = SpfgmrMalloc(mxl, ark_mem->ark_tempv);
-  if (spfgmr_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKSpfgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPFGMR memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) spfgmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpfgmrInit:
-
- This routine does remaining initializations specific to the 
- Spfgmr linear solver.
----------------------------------------------------------------*/
-static int ARKSpfgmrInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) 
-      && (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPFGMR", "ARKSpfgmrInit", 
-                    MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull=TRUE iff there is preconditioning (pretype != PREC_NONE)
-     and there is a preconditioning setup phase (pset != NULL)             */
-  ark_mem->ark_setupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (arkspils_mem->s_jtimesDQ) {
-    arkspils_mem->s_jtimes = ARKSpilsDQJtimes;
-    arkspils_mem->s_j_data = ark_mem;
-  } else {
-    arkspils_mem->s_j_data = ark_mem->ark_user_data;
-  }
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpfgmrSetup:
-
- This routine does the setup operations for the Spfgmr linear 
- solver. It makes a decision as to whether or not to signal for 
- re-evaluation of Jacobian data in the pset routine, based on 
- various state variables, then it calls pset.  If we signal for 
- re-evaluation, then we reset jcur = *jcurPtr to TRUE, regardless 
- of the pset output. In any case, if jcur == TRUE, we increment 
- npe and save nst in nstlpre.
----------------------------------------------------------------*/
-static int ARKSpfgmrSetup(ARKodeMem ark_mem, int convfail, 
-			 N_Vector ypred, N_Vector fpred, 
-			 booleantype *jcurPtr, N_Vector vtemp1,
-			 N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  ARKSpilsMem arkspils_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkspils_mem->s_nstlpre + ARKSPILS_MSBPRE) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKSPILS_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, ypred, fpred, jok, 
-				jcurPtr, ark_mem->ark_gamma, 
-				arkspils_mem->s_P_data, vtemp1, 
-				vtemp2, vtemp3);
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPFGMR_PSET_FAIL_UNREC, "ARKSPFGMR", 
-		    "ARKSpfgmrSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPFGMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) 
-    arkspils_mem->s_last_flag = SPFGMR_PSET_FAIL_REC;
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    arkspils_mem->s_npe++;
-    arkspils_mem->s_nstlpre = ark_mem->ark_nst;
-  }
-
-  arkspils_mem->s_last_flag = SPFGMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpfgmrSolve:
-
- This routine handles the call to the generic solver SpfgmrSolve
- for the solution of the linear system Ax = b with the SPFGMR 
- method, without restarts.  The solution x is returned in the 
- vector b.
-
- If the WRMS norm of b is small, we return x = b (if this is the 
- first Newton iteration) or x = 0 (if a later Newton iteration).
-
- Otherwise, we set the tolerance parameter and initial guess 
- (x = 0), call SpfgmrSolve, and copy the solution x into b.  The 
- x-scaling and b-scaling arrays are both equal to weight, and no 
- restarts are allowed.
-
- The counters nli, nps, and ncfl are incremented, and the return
- value is set according to the success of SpfgmrSolve.  The 
- success flag is returned if SpfgmrSolve converged, or if this is 
- the first Newton iteration and the residual norm was reduced 
- below its initial value.
----------------------------------------------------------------*/
-static int ARKSpfgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			  N_Vector weight, N_Vector ynow, 
-			  N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  ARKSpilsMem arkspils_mem;
-  SpfgmrMem spfgmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  spfgmr_mem = (SpfgmrMem) arkspils_mem->s_spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_eRNrm; 
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= arkspils_mem->s_deltar) {
-    if (ark_mem->ark_mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  arkspils_mem->s_ycur = ynow;
-  arkspils_mem->s_fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SpfgmrSolve */  
-  arkspils_mem->s_delta = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SpfgmrSolve and copy x to b */
-  retval = SpfgmrSolve(spfgmr_mem, ark_mem, arkspils_mem->s_x, b, 
-		       arkspils_mem->s_pretype, arkspils_mem->s_gstype, 
-		       arkspils_mem->s_delta, 0, arkspils_mem->s_maxl, 
-		       ark_mem, weight, weight, ARKSpilsAtimes, 
-		       ARKSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPFGMR_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      kry  %19.16g  %19.16g  %i  %i\n", 
-	    bnorm, res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SpfgmrSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPFGMR_SUCCESS:
-    return(0);
-    break;
-  case SPFGMR_RES_REDUCED:
-    /* allow reduction but not solution on first Newton iteration, 
-       otherwise return with a recoverable failure */
-    if (ark_mem->ark_mnewt == 0) return(0);
-    else                         return(1);
-    break;
-  case SPFGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPFGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPFGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPFGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPFGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPFGMR_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPFGMR_ATIMES_FAIL_UNREC, "ARKSPFGMR", 
-		    "ARKSpfgmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPFGMR_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPFGMR_PSOLVE_FAIL_UNREC, "ARKSPFGMR", 
-		    "ARKSpfgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPFGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPFGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpfgmrFree:
-
- This routine frees memory specific to the Spfgmr linear solver.
----------------------------------------------------------------*/
-static int ARKSpfgmrFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  SpfgmrMem spfgmr_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  spfgmr_mem = (SpfgmrMem) arkspils_mem->s_spils_mem;
-  SpfgmrFree(spfgmr_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-
-
-/*---------------------------------------------------------------
- ARKMassSpfgmr:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Spfgmr mass matrix solver 
- module. ARKMassSpfgmr first calls the existing mfree routine if 
- this is not NULL.  It then sets the ark_minit, ark_msetup, 
- ark_msolve, ark_mfree fields in (*arkode_mem) to be 
- ARKMassSpfgmrInit, ARKMassSpfgmrSetup, ARKMassSpfgmrSolve, and 
- ARKMassSpfgmrFree, respectively.  It allocates memory for a 
- structure of type ARKSpilsMassMemRec and sets the ark_mass_mem
- field in (*arkode_mem) to the address of this structure.  It 
- sets MassSetupNonNull in (*arkode_mem), and sets various fields
- in the ARKSpilsMassMemRec structure, allocates memory for ytemp 
- and x, and calls SpfgmrMalloc to allocate memory for the Spfgmr 
- solver.
----------------------------------------------------------------*/
-int ARKMassSpfgmr(void *arkode_mem, int pretype, int maxl, 
-		  ARKSpilsMassTimesVecFn mtimes, void *mtimes_data)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
-  SpfgmrMem spfgmr_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPFGMR", 
-		    "ARKMassSpfgmr", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd is present */
-  if(ark_mem->ark_tempv->ops->nvdotprod == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPFGMR", 
-		    "ARKMassSpfgmr", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = ARKMassSpfgmrInit;
-  ark_mem->ark_msetup = ARKMassSpfgmrSetup;
-  ark_mem->ark_msolve = ARKMassSpfgmrSolve;
-  ark_mem->ark_mfree  = ARKMassSpfgmrFree;
-  ark_mem->ark_msolve_type = 0;
-
-  /* Get memory for ARKSpilsMassMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMassMem) malloc(sizeof(struct ARKSpilsMassMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKMassSpfgmr", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set mass-matrix-vector product routine */
-  ark_mem->ark_mtimes      = mtimes;
-  ark_mem->ark_mtimes_data = mtimes_data;
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPFGMR;
-
-  /* Set Spfgmr parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype    = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Set default values for the rest of the Spfgmr parameters */
-  arkspils_mem->s_gstype        = MODIFIED_GS;
-  arkspils_mem->s_eplifac       = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag     = ARKSPILS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPFGMR", 
-		    "ARKMassSpfgmr", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKMassSpfgmr", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKMassSpfgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt( N_VDotProd(arkspils_mem->s_ytemp, 
-					    arkspils_mem->s_ytemp) );
-
-  /* Call SpfgmrMalloc to allocate workspace for Spfgmr */
-  spfgmr_mem = NULL;
-  spfgmr_mem = SpfgmrMalloc(mxl, ark_mem->ark_tempv);
-  if (spfgmr_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPFGMR", 
-		    "ARKMassSpfgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPFGMR memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) spfgmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpfgmrInit:
-
- This routine does remaining initializations specific to the 
- Spfgmr linear solver.
----------------------------------------------------------------*/
-static int ARKMassSpfgmrInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) 
-      && (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPFGMR", "ARKMassSpfgmrInit", 
-		    MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set MassSetupNonNull=TRUE iff there is preconditioning 
-     (pretype != PREC_NONE) and there is a preconditioning 
-     setup phase (pset != NULL)             */
-  ark_mem->ark_MassSetupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpfgmrSetup:
-
- This routine does the setup operations for the Spfgmr mass
- matrix solver. It calls pset, and increments npe.
----------------------------------------------------------------*/
-static int ARKMassSpfgmrSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			      N_Vector vtemp2, N_Vector vtemp3)
-{
-  int  retval;
-  ARKSpilsMassMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Call pset routine */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, 
-				arkspils_mem->s_P_data, 
-				vtemp1, vtemp2, vtemp3);
-  arkspils_mem->s_npe++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPFGMR_PSET_FAIL_UNREC, "ARKSPFGMR", 
-		    "ARKMassSpfgmrSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPFGMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) 
-    arkspils_mem->s_last_flag = SPFGMR_PSET_FAIL_REC;
-  if (retval == 0)
-    arkspils_mem->s_last_flag = SPFGMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpfgmrSolve:
-
- This routine handles the call to the generic solver SpfgmrSolve
- for the solution of the mass matrix system Mx = b with the 
- SPFGMR method, without restarts.  The solution x is returned in 
- the vector b.
-
- We set the tolerance parameter and initial guess (x = 0), call 
- SpfgmrSolve, and copy the solution x into b.  The x-scaling and 
- b-scaling arrays are both equal to weight, and no restarts are
- allowed.
-
- The counters nli, nps, and ncfl are incremented, and the return
- value is set according to the success of SpfgmrSolve.
----------------------------------------------------------------*/
-static int ARKMassSpfgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			      N_Vector weight)
-{
-  realtype res_norm;
-  ARKSpilsMassMem arkspils_mem;
-  SpfgmrMem spfgmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  spfgmr_mem = (SpfgmrMem) arkspils_mem->s_spils_mem;
-
-  /* Set inputs delta and initial guess x = 0 to SpfgmrSolve */  
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_nlscoef; 
-  arkspils_mem->s_delta  = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SpfgmrSolve and copy x to b */
-  retval = SpfgmrSolve(spfgmr_mem, ark_mem, arkspils_mem->s_x, b, 
-		       arkspils_mem->s_pretype, arkspils_mem->s_gstype, 
-		       arkspils_mem->s_delta, 0, arkspils_mem->s_maxl, 
-		       ark_mem, weight, weight, ARKSpilsMtimes, 
-		       ARKSpilsMPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPFGMR_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      mass  %19.16g  %i  %i\n", 
-	    res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SpfgmrSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPFGMR_SUCCESS:
-    return(0);
-    break;
-  case SPFGMR_RES_REDUCED:
-    return(1);
-    break;
-  case SPFGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPFGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPFGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPFGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPFGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPFGMR_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPFGMR_ATIMES_FAIL_UNREC, "ARKSPFGMR", 
-		    "ARKMassSpfgmrSolve", MSGS_MTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPFGMR_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPFGMR_PSOLVE_FAIL_UNREC, "ARKSPFGMR", 
-		    "ARKMassSpfgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPFGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPFGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpfgmrFree:
-
- This routine frees memory specific to the Spfgmr linear solver.
----------------------------------------------------------------*/
-static int ARKMassSpfgmrFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  SpfgmrMem spfgmr_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  spfgmr_mem = (SpfgmrMem) arkspils_mem->s_spils_mem;
-  SpfgmrFree(spfgmr_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
-    EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_spgmr.c b/src/arkode/arkode_spgmr.c
deleted file mode 100644
index 4e4d360..0000000
--- a/src/arkode/arkode_spgmr.c
+++ /dev/null
@@ -1,779 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * This is the implementation file for the ARKSPGMR linear solver.
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_spgmr.h>
-#include "arkode_spils_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_spgmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* ARKSPGMR linit, lsetup, lsolve, and lfree routines */
-static int ARKSpgmrInit(ARKodeMem ark_mem);
-static int ARKSpgmrSetup(ARKodeMem ark_mem, int convfail, 
-			 N_Vector ypred, N_Vector fpred, 
-			 booleantype *jcurPtr, N_Vector vtemp1,
-			 N_Vector vtemp2, N_Vector vtemp3);
-static int ARKSpgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			 N_Vector weight, N_Vector ynow, 
-			 N_Vector fnow);
-static int ARKSpgmrFree(ARKodeMem ark_mem);
-
-/* ARKSPGMR minit, msetup, msolve, and mfree routines */
-static int ARKMassSpgmrInit(ARKodeMem ark_mem);
-static int ARKMassSpgmrSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			     N_Vector vtemp2, N_Vector vtemp3);
-static int ARKMassSpgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight);
-static int ARKMassSpgmrFree(ARKodeMem ark_mem);
-
-
-/*---------------------------------------------------------------
- ARKSpgmr:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Spgmr linear solver module. 
- ARKSpgmr first calls the existing lfree routine if this is not 
- NULL.  It then sets the ark_linit, ark_lsetup, ark_lsolve, 
- ark_lfree fields in (*arkode_mem) to be ARKSpgmrInit, 
- ARKSpgmrSetup, ARKSpgmrSolve, and ARKSpgmrFree, respectively.  
- It allocates memory for a structure of type ARKSpilsMemRec and
- sets the ark_lmem field in (*arkode_mem) to the address of this
- structure.  It sets setupNonNull in (*arkode_mem), and sets 
- various fields in the ARKSpilsMemRec structure. Finally, 
- ARKSpgmr allocates memory for ytemp and x, and calls
- SpgmrMalloc to allocate memory for the Spgmr solver.
----------------------------------------------------------------*/
-int ARKSpgmr(void *arkode_mem, int pretype, int maxl)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
-  SpgmrMem spgmr_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPGMR", 
-		    "ARKSpgmr", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd and N_VProd are present */
-  if ((ark_mem->ark_tempv->ops->nvdotprod == NULL) ||
-      (ark_mem->ark_tempv->ops->nvprod == NULL)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPGMR", 
-		    "ARKSpgmr", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */
-  ark_mem->ark_linit  = ARKSpgmrInit;
-  ark_mem->ark_lsetup = ARKSpgmrSetup;
-  ark_mem->ark_lsolve = ARKSpgmrSolve;
-  ark_mem->ark_lfree  = ARKSpgmrFree;
-  ark_mem->ark_lsolve_type = 0;
-
-  /* Get memory for ARKSpilsMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMem) malloc(sizeof(struct ARKSpilsMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKSpgmr", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPGMR;
-
-  /* Set Spgmr parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype    = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fields */
-  arkspils_mem->s_jtimesDQ = TRUE;
-  arkspils_mem->s_jtimes   = NULL;
-  arkspils_mem->s_j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Set default values for the rest of the Spgmr parameters */
-  arkspils_mem->s_gstype = MODIFIED_GS;
-  arkspils_mem->s_eplifac = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag  = ARKSPILS_SUCCESS;
-  ark_mem->ark_setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPGMR", 
-		    "ARKSpgmr", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKSpgmr", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt( N_VDotProd(arkspils_mem->s_ytemp, 
-					    arkspils_mem->s_ytemp) );
-
-  /* Call SpgmrMalloc to allocate workspace for Spgmr */
-  spgmr_mem = NULL;
-  spgmr_mem = SpgmrMalloc(mxl, ark_mem->ark_tempv);
-  if (spgmr_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPGMR memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) spgmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpgmrInit:
-
- This routine does remaining initializations specific to the Spgmr 
- linear solver.
----------------------------------------------------------------*/
-static int ARKSpgmrInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) 
-      && (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPGMR", "ARKSpgmrInit", 
-		    MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning (pretype != PREC_NONE)
-     and there is a preconditioning setup phase (pset != NULL)             */
-  ark_mem->ark_setupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (arkspils_mem->s_jtimesDQ) {
-    arkspils_mem->s_jtimes = ARKSpilsDQJtimes;
-    arkspils_mem->s_j_data = ark_mem;
-  } else {
-    arkspils_mem->s_j_data = ark_mem->ark_user_data;
-  }
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpgmrSetup:
-
- This routine does the setup operations for the Spgmr linear 
- solver. It makes a decision as to whether or not to signal for 
- re-evaluation of Jacobian data in the pset routine, based on 
- various state variables, then it calls pset.  If we signal for 
- re-evaluation, then we reset jcur = *jcurPtr to TRUE, regardless 
- of the pset output. In any case, if jcur == TRUE, we increment 
- npe and save nst in nstlpre.
----------------------------------------------------------------*/
-static int ARKSpgmrSetup(ARKodeMem ark_mem, int convfail, 
-			 N_Vector ypred, N_Vector fpred, 
-			 booleantype *jcurPtr, N_Vector vtemp1,
-			 N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  ARKSpilsMem arkspils_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkspils_mem->s_nstlpre + ARKSPILS_MSBPRE) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKSPILS_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, ypred, fpred, jok, 
-				jcurPtr, ark_mem->ark_gamma, 
-				arkspils_mem->s_P_data, vtemp1, 
-				vtemp2, vtemp3);
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPGMR_PSET_FAIL_UNREC, "ARKSPGMR", 
-		    "ARKSpgmrSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPGMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = SPGMR_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    arkspils_mem->s_npe++;
-    arkspils_mem->s_nstlpre = ark_mem->ark_nst;
-  }
-
-  arkspils_mem->s_last_flag = SPGMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpgmrSolve:
-
- This routine handles the call to the generic solver SpgmrSolve
- for the solution of the linear system Ax = b with the SPGMR 
- method, without restarts.  The solution x is returned in the 
- vector b.
-
- If the WRMS norm of b is small, we return x = b (if this is the 
- first Newton iteration) or x = 0 (if a later Newton iteration).
-
- Otherwise, we set the tolerance parameter and initial guess 
- (x = 0), call SpgmrSolve, and copy the solution x into b.  The 
- x-scaling and b-scaling arrays are both equal to weight, and no 
- restarts are allowed.
-
- The counters nli, nps, and ncfl are incremented, and the return
- value is set according to the success of SpgmrSolve.  The 
- success flag is returned if SpgmrSolve converged, or if this is 
- the first Newton iteration and the residual norm was reduced 
- below its initial value.
----------------------------------------------------------------*/
-static int ARKSpgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			 N_Vector weight, N_Vector ynow, 
-			 N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  ARKSpilsMem arkspils_mem;
-  SpgmrMem spgmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  spgmr_mem = (SpgmrMem) arkspils_mem->s_spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_eRNrm; 
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= arkspils_mem->s_deltar) {
-    if (ark_mem->ark_mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  arkspils_mem->s_ycur = ynow;
-  arkspils_mem->s_fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SpgmrSolve */  
-  arkspils_mem->s_delta = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SpgmrSolve and copy x to b */
-  retval = SpgmrSolve(spgmr_mem, ark_mem, arkspils_mem->s_x, b, 
-		      arkspils_mem->s_pretype, arkspils_mem->s_gstype, 
-		      arkspils_mem->s_delta, 0, ark_mem, weight, weight, 
-		      ARKSpilsAtimes, ARKSpilsPSolve, &res_norm, 
-		      &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPGMR_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      kry  %19.16g  %19.16g  %i  %i\n", 
-	    bnorm, res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SpgmrSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPGMR_SUCCESS:
-    return(0);
-    break;
-  case SPGMR_RES_REDUCED:
-    /* allow reduction but not solution on first Newton iteration, 
-       otherwise return with a recoverable failure */
-    if (ark_mem->ark_mnewt == 0) return(0);
-    else                         return(1);
-    break;
-  case SPGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPGMR_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPGMR_ATIMES_FAIL_UNREC, "ARKSPGMR", 
-		    "ARKSpgmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPGMR_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPGMR_PSOLVE_FAIL_UNREC, "ARKSPGMR", 
-		    "ARKSpgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpgmrFree:
-
- This routine frees memory specific to the Spgmr linear solver.
----------------------------------------------------------------*/
-static int ARKSpgmrFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  SpgmrMem spgmr_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  spgmr_mem = (SpgmrMem) arkspils_mem->s_spils_mem;
-  SpgmrFree(spgmr_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-
-/*---------------------------------------------------------------
- ARKMassSpgmr:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Spgmr mass matrix solver module. 
- ARKMassSpgmr first calls the existing mfree routine if this is 
- not NULL.  It then sets the ark_minit, ark_msetup, ark_msolve, 
- ark_mfree fields in (*arkode_mem) to be ARKMassSpgmrInit, 
- ARKMassSpgmrSetup, ARKMassSpgmrSolve, and ARKMassSpgmrFree, 
- respectively.  It allocates memory for a structure of type 
- ARKSpilsMassMemRec and sets the ark_mass_mem field in 
- (*arkode_mem) to the address of this structure.  It sets 
- MassSetupNonNull in (*arkode_mem), and sets various fields in
- the ARKSpilsMassMemRec structure, allocates memory for ytemp
- and x, and calls SpgmrMalloc to allocate memory for the Spgmr 
- solver.
----------------------------------------------------------------*/
-int ARKMassSpgmr(void *arkode_mem, int pretype, int maxl, 
-		 ARKSpilsMassTimesVecFn mtimes, void *mtimes_data)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
-  SpgmrMem spgmr_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPGMR", 
-		    "ARKMassSpgmr", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd is present */
-  if(ark_mem->ark_tempv->ops->nvdotprod == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPGMR", 
-		    "ARKMassSpgmr", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = ARKMassSpgmrInit;
-  ark_mem->ark_msetup = ARKMassSpgmrSetup;
-  ark_mem->ark_msolve = ARKMassSpgmrSolve;
-  ark_mem->ark_mfree  = ARKMassSpgmrFree;
-  ark_mem->ark_msolve_type = 0;
-
-  /* Get memory for ARKSpilsMassMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMassMem) malloc(sizeof(struct ARKSpilsMassMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKMassSpgmr", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set mass-matrix-vector product routine */
-  ark_mem->ark_mtimes      = mtimes;
-  ark_mem->ark_mtimes_data = mtimes_data;
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPGMR;
-
-  /* Set Spgmr parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype    = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Set default values for the rest of the Spgmr parameters */
-  arkspils_mem->s_gstype        = MODIFIED_GS;
-  arkspils_mem->s_eplifac       = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag     = ARKSPILS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPGMR", 
-		    "ARKMassSpgmr", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKMassSpgmr", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKMassSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt( N_VDotProd(arkspils_mem->s_ytemp, 
-					    arkspils_mem->s_ytemp) );
-
-  /* Call SpgmrMalloc to allocate workspace for Spgmr */
-  spgmr_mem = NULL;
-  spgmr_mem = SpgmrMalloc(mxl, ark_mem->ark_tempv);
-  if (spgmr_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPGMR", 
-		    "ARKMassSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPGMR memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) spgmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpgmrInit:
-
- This routine does remaining initializations specific to the Spgmr 
- linear solver.
----------------------------------------------------------------*/
-static int ARKMassSpgmrInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) 
-      && (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPGMR", 
-		    "ARKMassSpgmrInit", MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set MassSetupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE) and there is a preconditioning setup 
-     phase (pset != NULL)             */
-  ark_mem->ark_MassSetupNonNull = (arkspils_mem->s_pretype != PREC_NONE) 
-    && (arkspils_mem->s_pset != NULL);
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpgmrSetup:
-
- This routine does the setup operations for the Spgmr mass matrix
- solver. It calls pset and increments npe.
----------------------------------------------------------------*/
-static int ARKMassSpgmrSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			     N_Vector vtemp2, N_Vector vtemp3)
-{
-  int  retval;
-  ARKSpilsMassMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Call pset routine */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, 
-				arkspils_mem->s_P_data, 
-				vtemp1, vtemp2, vtemp3);
-  arkspils_mem->s_npe++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPGMR_PSET_FAIL_UNREC, "ARKSPGMR", 
-		    "ARKMassSpgmrSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPGMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = SPGMR_PSET_FAIL_REC;
-  }
-  if (retval == 0) {
-    arkspils_mem->s_last_flag = SPGMR_SUCCESS;
-  }
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpgmrSolve:
-
- This routine handles the call to the generic solver SpgmrSolve
- for the solution of the mass matrix system Mx = b with the SPGMR 
- method, without restarts.  The solution x is returned in the 
- vector b.
-
- We set the tolerance parameter and initial guess (x = 0), call 
- SpgmrSolve, and copy the solution x into b.  The x-scaling and 
- b-scaling arrays are both equal to weight, and no restarts are
- allowed.
-
- The counters nli, nps, and ncfl are incremented, and the return
- value is set according to the success of SpgmrSolve.
----------------------------------------------------------------*/
-static int ARKMassSpgmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight)
-{
-  realtype res_norm;
-  ARKSpilsMassMem arkspils_mem;
-  SpgmrMem spgmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  spgmr_mem = (SpgmrMem) arkspils_mem->s_spils_mem;
-
-  /* Set inputs delta and initial guess x = 0 to SpgmrSolve */  
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_nlscoef; 
-  arkspils_mem->s_delta  = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SpgmrSolve and copy x to b */
-  retval = SpgmrSolve(spgmr_mem, ark_mem, arkspils_mem->s_x, b, 
-		      arkspils_mem->s_pretype, arkspils_mem->s_gstype, 
-		      arkspils_mem->s_delta, 0, ark_mem, weight, weight, 
-		      ARKSpilsMtimes, ARKSpilsMPSolve, &res_norm, 
-		      &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPGMR_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      mass  %19.16g  %i  %i\n", 
-	    res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SpgmrSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPGMR_SUCCESS:
-    return(0);
-    break;
-  case SPGMR_RES_REDUCED:
-    return(1);
-    break;
-  case SPGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPGMR_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPGMR_ATIMES_FAIL_UNREC, "ARKSPGMR", 
-		    "ARKMassSpgmrSolve", MSGS_MTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPGMR_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPGMR_PSOLVE_FAIL_UNREC, "ARKSPGMR", 
-		    "ARKMassSpgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSpgmrFree:
-
- This routine frees memory specific to the Spgmr linear solver.
----------------------------------------------------------------*/
-static int ARKMassSpgmrFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  SpgmrMem spgmr_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  spgmr_mem = (SpgmrMem) arkspils_mem->s_spils_mem;
-  SpgmrFree(spgmr_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
-    EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_spils.c b/src/arkode/arkode_spils.c
index 050cb49..c57143b 100644
--- a/src/arkode/arkode_spils.c
+++ b/src/arkode/arkode_spils.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,7 +15,8 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * This is the implementation file for the ARKSPILS linear solvers.
+ * This is the implementation file for the ARKSPILS linear solver
+ * interface.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -23,6 +24,13 @@
 
 #include "arkode_impl.h"
 #include "arkode_spils_impl.h"
+#include <sundials/sundials_math.h>
+
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+#define RSYM ".32Lg"
+#else
+#define RSYM ".16g"
+#endif
 
 /* constants */
 #define MAX_DQITERS  3  /* max. # of attempts to recover in DQ J*v */
@@ -32,750 +40,967 @@
 
 
 /*===============================================================
-   OPTIONAL INPUT and OUTPUT
+  ARKSPILS Exported functions -- Required
 ===============================================================*/
 
 /*---------------------------------------------------------------
- ARKSpilsSetPrecType
+ ARKSpilsSetLinearSolver specifies the iterative linear solver.
 ---------------------------------------------------------------*/
-int ARKSpilsSetPrecType(void *arkode_mem, int pretype)
+int ARKSpilsSetLinearSolver(void *arkode_mem, SUNLinearSolver LS)
 {
+  int retval;
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetPrecType", MSGS_ARKMEM_NULL);
+		    "ARKSpilsSetLinearSolver", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
+  if (LS == NULL) {
+    arkProcessError(NULL, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+		    "ARKSpilsSetLinearSolver", 
+                    "LS must be non-NULL");
+    return(ARKSPILS_ILL_INPUT);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetPrecType", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
+  /* Test if solver and vector are compatible with SPILS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_ITERATIVE) {
+    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+                    "ARKSpilsSetLinearSolver", 
+                    "Non-iterative LS supplied to ARKSpils interface");
+    return(ARKSPILS_ILL_INPUT);
   }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
+  if ( (ark_mem->ark_tempv->ops->nvlinearsum == NULL) ||
+       (ark_mem->ark_tempv->ops->nvconst == NULL) ||
+       (ark_mem->ark_tempv->ops->nvdotprod == NULL) ){
     arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetPrecType", MSGS_BAD_PRETYPE);
+                    "ARKSpilsSetLinearSolver", MSGS_BAD_NVECTOR);
     return(ARKSPILS_ILL_INPUT);
   }
 
-  arkspils_mem->s_pretype = pretype;
+  /* free any existing system solver attached to ARKode */
+  if (ark_mem->ark_lfree)  ark_mem->ark_lfree(ark_mem);
+
+  /* Set four main system linear solver function fields in ark_mem */
+  ark_mem->ark_linit  = arkSpilsInitialize;
+  ark_mem->ark_lsetup = arkSpilsSetup;
+  ark_mem->ark_lsolve = arkSpilsSolve;
+  ark_mem->ark_lfree  = arkSpilsFree;
+  ark_mem->ark_lsolve_type = 0;
+  
+  /* Get memory for ARKSpilsMemRec */
+  arkspils_mem = NULL;
+  arkspils_mem = (ARKSpilsMem) malloc(sizeof(struct ARKSpilsMemRec));
+  if (arkspils_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer */
+  arkspils_mem->LS = LS;
+  
+  /* Set defaults for Jacobian-related fields */
+  arkspils_mem->jtimesDQ = SUNTRUE;
+  arkspils_mem->jtsetup = NULL;
+  arkspils_mem->jtimes = ARKSpilsDQJtimes;
+  arkspils_mem->j_data = ark_mem;
+
+  /* Set defaults for preconditioner-related fields */
+  arkspils_mem->pset   = NULL;
+  arkspils_mem->psolve = NULL;
+  arkspils_mem->pfree  = NULL;
+  arkspils_mem->P_data = ark_mem->ark_user_data;
+
+  /* Initialize counters */
+  arkSpilsInitializeCounters(arkspils_mem);
+
+  /* Set default values for the rest of the SPILS parameters */
+  arkspils_mem->jbad = SUNTRUE;
+  arkspils_mem->eplifac = ARKSPILS_EPLIN;
+  arkspils_mem->last_flag = ARKSPILS_SUCCESS;
+
+  /* Attach default ARKSpils interface routines to iterative LS */
+  retval = SUNLinSolSetATimes(LS, ark_mem, ARKSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetATimes");
+    free(arkspils_mem); arkspils_mem = NULL;
+    return(ARKSPILS_SUNLS_FAIL);
+  }
+  retval = SUNLinSolSetPreconditioner(LS, ark_mem, NULL, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    free(arkspils_mem); arkspils_mem = NULL;
+    return(ARKSPILS_SUNLS_FAIL);
+  }
+
+  /* Allocate memory for ytemp and x */
+  arkspils_mem->ytemp = N_VClone(ark_mem->ark_tempv);
+  if (arkspils_mem->ytemp == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    free(arkspils_mem); arkspils_mem = NULL;
+    return(ARKSPILS_MEM_FAIL);
+  }
+
+  arkspils_mem->x = N_VClone(ark_mem->ark_tempv);
+  if (arkspils_mem->x == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    N_VDestroy(arkspils_mem->ytemp);
+    free(arkspils_mem); arkspils_mem = NULL;
+    return(ARKSPILS_MEM_FAIL);
+  }
+
+  /* Compute sqrtN from a dot product */
+  N_VConst(ONE, arkspils_mem->ytemp);
+  arkspils_mem->sqrtN = SUNRsqrt( N_VDotProd(arkspils_mem->ytemp, 
+                                             arkspils_mem->ytemp) );
+
+  /* Attach linear solver memory to integrator memory */
+  ark_mem->ark_lmem = arkspils_mem;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetMassPrecType
+ ARKSpilsSetMassLinearSolver specifies the iterative mass-matrix
+ linear solver and user-supplied routine to perform the 
+ mass-matrix-vector product.
 ---------------------------------------------------------------*/
-int ARKSpilsSetMassPrecType(void *arkode_mem, int pretype)
+int ARKSpilsSetMassLinearSolver(void *arkode_mem,
+                                SUNLinearSolver LS,
+                                booleantype time_dep)
 {
+  int retval;
   ARKodeMem ark_mem;
   ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem, LS or mtimes are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassPrecType", MSGS_ARKMEM_NULL);
+		    "ARKSpilsSetMassLinearSolver", 
+                    MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
+  if (LS == NULL) {
+    arkProcessError(NULL, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+		    "ARKSpilsSetLinearSolver", 
+                    "LS must be non-NULL");
+    return(ARKSPILS_ILL_INPUT);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
 
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassPrecType", MSGS_MASSMEM_NULL);
-    return(ARKSPILS_MASSMEM_NULL);
+  /* Test if solver and vector are compatible with SPILS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_ITERATIVE) {
+    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+                    "ARKSpilsSetMassLinearSolver", 
+                    "Non-iterative LS supplied to ARKSpils interface");
+    return(ARKSPILS_ILL_INPUT);
   }
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
+  if ( (ark_mem->ark_tempv->ops->nvconst == NULL) ||
+       (ark_mem->ark_tempv->ops->nvdotprod == NULL) ){
     arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetMassPrecType", MSGS_BAD_PRETYPE);
+                    "ARKSpilsSetMassLinearSolver", MSGS_BAD_NVECTOR);
     return(ARKSPILS_ILL_INPUT);
   }
 
-  arkspils_mem->s_pretype = pretype;
+  /* free any existing system solver attached to ARKode */
+  if (ark_mem->ark_mfree)  ark_mem->ark_mfree(ark_mem);
+
+  /* Set four main system linear solver function fields in ark_mem */
+  ark_mem->ark_minit  = arkSpilsMassInitialize;
+  ark_mem->ark_msetup = arkSpilsMassSetup;
+  ark_mem->ark_mmult  = arkSpilsMassMult;
+  ark_mem->ark_msolve = arkSpilsMassSolve;
+  ark_mem->ark_mfree  = arkSpilsMassFree;
+  ark_mem->ark_msolve_type = 0;
+  
+  /* notify arkode of non-identity mass matrix */
+  ark_mem->ark_mass_matrix = SUNTRUE;
+
+  /* Get memory for ARKSpilsMassMemRec */
+  arkspils_mem = NULL;
+  arkspils_mem = (ARKSpilsMassMem) malloc(sizeof(struct ARKSpilsMassMemRec));
+  if (arkspils_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetMassLinearSolver", MSGS_MEM_FAIL);
+    return(ARKSPILS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer; flag indicating time-dependence */
+  arkspils_mem->LS = LS;
+  arkspils_mem->time_dependent = time_dep;
+
+  /* Set mass-matrix-vector product routines to NULL */
+  arkspils_mem->mtsetup = NULL;
+  arkspils_mem->mtimes  = NULL;
+  arkspils_mem->mt_data = NULL;
+
+  /* Set defaults for preconditioner-related fields */
+  arkspils_mem->pset   = NULL;
+  arkspils_mem->psolve = NULL;
+  arkspils_mem->pfree  = NULL;
+  arkspils_mem->P_data = ark_mem->ark_user_data;
+
+  /* Initialize counters */
+  arkSpilsInitializeMassCounters(arkspils_mem);
+
+  /* Set default values for the rest of the SPILS parameters */
+  arkspils_mem->eplifac   = ARKSPILS_EPLIN;
+  arkspils_mem->last_flag = ARKSPILS_SUCCESS;
+
+  /* Attach default ARKSpils interface routines to iterative LS */
+  retval = SUNLinSolSetATimes(LS, ark_mem, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetMassLinearSolver", 
+                    "Error in calling SUNLinSolSetATimes");
+    free(arkspils_mem); arkspils_mem = NULL;
+    return(ARKSPILS_SUNLS_FAIL);
+  }
+  retval = SUNLinSolSetPreconditioner(LS, ark_mem, NULL, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetMassLinearSolver", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    free(arkspils_mem); arkspils_mem = NULL;
+    return(ARKSPILS_SUNLS_FAIL);
+  }
+
+  /* Allocate memory for x */
+  arkspils_mem->x = N_VClone(ark_mem->ark_tempv);
+  if (arkspils_mem->x == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetMassLinearSolver", MSGS_MEM_FAIL);
+    free(arkspils_mem); arkspils_mem = NULL;
+    return(ARKSPILS_MEM_FAIL);
+  }
+
+  /* Compute sqrtN from a dot product */
+  N_VConst(ONE, arkspils_mem->x);
+  arkspils_mem->sqrtN = SUNRsqrt( N_VDotProd(arkspils_mem->x, 
+                                             arkspils_mem->x) );
+
+  /* Attach linear solver memory to integrator memory */
+  ark_mem->ark_mass_mem = arkspils_mem;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
+/*===============================================================
+  ARKSPILS Exported functions -- Optional input/output
+===============================================================*/
+
 /*---------------------------------------------------------------
- ARKSpilsSetGSType
+ ARKSpilsSetEpsLin
 ---------------------------------------------------------------*/
-int ARKSpilsSetGSType(void *arkode_mem, int gstype)
+int ARKSpilsSetEpsLin(void *arkode_mem, realtype eplifac)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetGSType", MSGS_ARKMEM_NULL);
+		    "ARKSpilsSetEpsLin", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetGSType", MSGS_LMEM_NULL);
+		    "ARKSpilsSetEpsLin", MSGS_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if ((arkspils_mem->s_type != SPILS_SPGMR) &&
-      (arkspils_mem->s_type != SPILS_SPFGMR)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetGSType", MSGS_BAD_LSTYPE);
-    fprintf(stderr,"solver type = %i\n",arkspils_mem->s_type);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Check for legal gstype */
-  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
+  /* Check for legal eplifac */
+  if(eplifac < ZERO) {
     arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetGSType", MSGS_BAD_GSTYPE);
+		    "ARKSpilsSetEpsLin", MSGS_BAD_EPLIN);
     return(ARKSPILS_ILL_INPUT);
   }
-  arkspils_mem->s_gstype = gstype;
+  arkspils_mem->eplifac = (eplifac == ZERO) ? ARKSPILS_EPLIN : eplifac;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetMassGSType
+ ARKSpilsSetPreconditioner
 ---------------------------------------------------------------*/
-int ARKSpilsSetMassGSType(void *arkode_mem, int gstype)
+int ARKSpilsSetPreconditioner(void *arkode_mem, 
+			      ARKSpilsPrecSetupFn psetup, 
+			      ARKSpilsPrecSolveFn psolve)
 {
+  int retval;
   ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
+  ARKSpilsMem arkspils_mem;
+  PSetupFn arkspils_psetup;
+  PSolveFn arkspils_psolve;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassGSType", MSGS_ARKMEM_NULL);
+		    "ARKSpilsSetPreconditioner", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassGSType", MSGS_MASSMEM_NULL);
-    return(ARKSPILS_MASSMEM_NULL);
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsSetPreconditioner", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if ((arkspils_mem->s_type != SPILS_SPGMR) &&
-      (arkspils_mem->s_type != SPILS_SPFGMR)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetMassGSType", MSGS_BAD_LSTYPE);
-    return(ARKSPILS_ILL_INPUT);
-  }
+  /* store function pointers for user-supplied routines in ARKSpils interface */
+  arkspils_mem->pset   = psetup;
+  arkspils_mem->psolve = psolve;
 
-  /* Check for legal gstype */
-  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetMassGSType", MSGS_BAD_GSTYPE);
-    return(ARKSPILS_ILL_INPUT);
+  /* notify iterative linear solver to call ARKSpils interface routines */
+  arkspils_psetup = (psetup == NULL) ? NULL : ARKSpilsPSetup;
+  arkspils_psolve = (psolve == NULL) ? NULL : ARKSpilsPSolve;
+  retval = SUNLinSolSetPreconditioner(arkspils_mem->LS, ark_mem, 
+                                      arkspils_psetup, arkspils_psolve);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetPreconditioner", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    return(ARKSPILS_SUNLS_FAIL);
   }
-  arkspils_mem->s_gstype = gstype;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- Function : ARKSpilsSetMaxl
+ ARKSpilsSetJacTimes
 ---------------------------------------------------------------*/
-int ARKSpilsSetMaxl(void *arkode_mem, int maxl)
+int ARKSpilsSetJacTimes(void *arkode_mem, 
+                        ARKSpilsJacTimesSetupFn jtsetup,
+                        ARKSpilsJacTimesVecFn jtimes)
 {
+  int retval;
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
-  int mxl;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMaxl", MSGS_ARKMEM_NULL);
+                    "ARKSpilsSetJacTimes", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(NULL, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMaxl", MSGS_LMEM_NULL);
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+                    "ARKSpilsSetJacTimes", MSGS_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if ((arkspils_mem->s_type == SPILS_SPGMR) &&
-      (arkspils_mem->s_type == SPILS_SPFGMR)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetMaxl", MSGS_BAD_LSTYPE);
-    return(ARKSPILS_ILL_INPUT);
+  /* store function pointers for user-supplied routines in ARKSpils 
+     interface (NULL jtimes implies use of DQ default) */
+  if (jtimes != NULL) {
+    arkspils_mem->jtimesDQ = SUNFALSE;
+    arkspils_mem->jtimes   = jtimes;
+  } else {
+    arkspils_mem->jtimesDQ = SUNTRUE;
   }
+  arkspils_mem->jtsetup = jtsetup;
 
-  mxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-  arkspils_mem->s_maxl = mxl;
+  /* notify iterative linear solver to call ARKSpils interface routines */
+  retval = SUNLinSolSetATimes(arkspils_mem->LS, ark_mem, ARKSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetJacTimes", 
+                    "Error in calling SUNLinSolSetATimes");
+    return(ARKSPILS_SUNLS_FAIL);
+  }
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- Function : ARKSpilsSetMassMaxl
+ ARKSpilsGetWorkSpace
 ---------------------------------------------------------------*/
-int ARKSpilsSetMassMaxl(void *arkode_mem, int maxl)
+int ARKSpilsGetWorkSpace(void *arkode_mem, long int *lenrw, 
+			 long int *leniw)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
-  int mxl;
+  ARKSpilsMem arkspils_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassMaxl", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetWorkSpace", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassMaxl", MSGS_MASSMEM_NULL);
-    return(ARKSPILS_MASSMEM_NULL);
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+                    "ARKSpilsGetWorkSpace", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if ((arkspils_mem->s_type == SPILS_SPGMR) &&
-      (arkspils_mem->s_type == SPILS_SPFGMR)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetMassMaxl", MSGS_BAD_LSTYPE);
-    return(ARKSPILS_ILL_INPUT);
+  /* start with fixed sizes plus NVectors */
+  *lenrw = 4;
+  *leniw = 10;
+
+  /* add NVector sizes */
+  if (ark_mem->ark_tempv->ops->nvspace) {
+    N_VSpace(ark_mem->ark_tempv, &lrw1, &liw1);
+    *lenrw += 2*lrw1;
+    *leniw += 2*liw1;
   }
 
-  mxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-  arkspils_mem->s_maxl = mxl;
+  /* add LS sizes */
+  if (arkspils_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(arkspils_mem->LS, &lrw, &liw);
+    *lenrw += lrw;
+    *leniw += liw;
+  }
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetEpsLin
+ ARKSpilsGetNumPrecEvals
 ---------------------------------------------------------------*/
-int ARKSpilsSetEpsLin(void *arkode_mem, realtype eplifac)
+int ARKSpilsGetNumPrecEvals(void *arkode_mem, long int *npevals)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetEpsLin", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetNumPrecEvals", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetEpsLin", MSGS_LMEM_NULL);
+                    "ARKSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  /* Check for legal eplifac */
-  if(eplifac < ZERO) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetEpsLin", MSGS_BAD_EPLIN);
-    return(ARKSPILS_ILL_INPUT);
-  }
-  arkspils_mem->s_eplifac = (eplifac == ZERO) ? ARKSPILS_EPLIN : eplifac;
+  *npevals = arkspils_mem->npe;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetMassEpsLin
+ ARKSpilsGetNumPrecSolves
 ---------------------------------------------------------------*/
-int ARKSpilsSetMassEpsLin(void *arkode_mem, realtype eplifac)
+int ARKSpilsGetNumPrecSolves(void *arkode_mem, long int *npsolves)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
+  ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassEpsLin", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetNumPrecSolves", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassEpsLin", MSGS_MASSMEM_NULL);
-    return(ARKSPILS_MASSMEM_NULL);
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+                    "ARKSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  /* Check for legal eplifac */
-  if(eplifac < ZERO) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetMassEpsLin", MSGS_BAD_EPLIN);
-    return(ARKSPILS_ILL_INPUT);
-  }
-  arkspils_mem->s_eplifac = (eplifac == ZERO) ? ARKSPILS_EPLIN : eplifac;
+  *npsolves = arkspils_mem->nps;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetPreconditioner
+ ARKSpilsGetNumLinIters
 ---------------------------------------------------------------*/
-int ARKSpilsSetPreconditioner(void *arkode_mem, 
-			      ARKSpilsPrecSetupFn pset, 
-			      ARKSpilsPrecSolveFn psolve)
+int ARKSpilsGetNumLinIters(void *arkode_mem, long int *nliters)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetPreconditioner", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetNumLinIters", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetPreconditioner", MSGS_LMEM_NULL);
+                    "ARKSpilsGetNumLinIters", MSGS_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  arkspils_mem->s_pset   = pset;
-  arkspils_mem->s_psolve = psolve;
+  *nliters = arkspils_mem->nli;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetMassPreconditioner
+ ARKSpilsGetNumConvFails
 ---------------------------------------------------------------*/
-int ARKSpilsSetMassPreconditioner(void *arkode_mem, 
-				  ARKSpilsMassPrecSetupFn pset, 
-				  ARKSpilsMassPrecSolveFn psolve)
+int ARKSpilsGetNumConvFails(void *arkode_mem, long int *nlcfails)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
+  ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassPreconditioner", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetNumConvFails", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetMassPreconditioner", MSGS_MASSMEM_NULL);
-    return(ARKSPILS_MASSMEM_NULL);
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+                    "ARKSpilsGetNumConvFails", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  arkspils_mem->s_pset   = pset;
-  arkspils_mem->s_psolve = psolve;
+  *nlcfails = arkspils_mem->ncfl;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetJacTimesVecFn
+ ARKSpilsGetNumJTSetupEvals
 ---------------------------------------------------------------*/
-int ARKSpilsSetJacTimesVecFn(void *arkode_mem, 
-			     ARKSpilsJacTimesVecFn jtv)
+int ARKSpilsGetNumJTSetupEvals(void *arkode_mem, long int *njtsetups)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetJacTimesVecFn", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetNumJTSetupEvals", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
+                    "ARKSpilsGetNumJTSetupEvals", MSGS_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  if (jtv != NULL) {
-    arkspils_mem->s_jtimesDQ = FALSE;
-    arkspils_mem->s_jtimes   = jtv;
-  } else {
-    arkspils_mem->s_jtimesDQ = TRUE;
-  }
+  *njtsetups = arkspils_mem->njtsetup;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsSetMassTimesVecFn
+ ARKSpilsGetNumJtimesEvals
 ---------------------------------------------------------------*/
-int ARKSpilsSetMassTimesVecFn(void *arkode_mem, 
-			      ARKSpilsMassTimesVecFn mtv,
-			      void *mtimes_data)
+int ARKSpilsGetNumJtimesEvals(void *arkode_mem, long int *njvevals)
 {
   ARKodeMem ark_mem;
+  ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsSetJacTimesVecFn", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetNumJtimesEvals", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (mtv == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
-		    "ARKSpilsSetMassTimesVecFn", "non-NULL function must be supplied");
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+                    "ARKSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  /* set arguments into ark_mem data structure */
-  ark_mem->ark_mtimes = mtv;
-  ark_mem->ark_mtimes_data = mtimes_data;
+  *njvevals = arkspils_mem->njtimes;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetWorkSpace
+ ARKSpilsGetNumRhsEvals
 ---------------------------------------------------------------*/
-int ARKSpilsGetWorkSpace(void *arkode_mem, long int *lenrwLS, 
-			 long int *leniwLS)
+int ARKSpilsGetNumRhsEvals(void *arkode_mem, long int *nfevalsLS)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
-  int maxl;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetWorkSpace", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetNumRhsEvals", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_lmem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetWorkSpace", MSGS_LMEM_NULL);
+                    "ARKSpilsGetNumRhsEvals", MSGS_LMEM_NULL);
     return(ARKSPILS_LMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  switch(arkspils_mem->s_type) {
-  case SPILS_SPGMR:
-    maxl = arkspils_mem->s_maxl;
-    *lenrwLS = ark_mem->ark_lrw1*(maxl + 5) + maxl*(maxl + 4) + 1;
-    *leniwLS = ark_mem->ark_liw1*(maxl + 5);
-    break;
-  case SPILS_SPBCG:
-    *lenrwLS = ark_mem->ark_lrw1 * 9;
-    *leniwLS = ark_mem->ark_liw1 * 9;
-    break;
-  case SPILS_SPTFQMR:
-    *lenrwLS = ark_mem->ark_lrw1*11;
-    *leniwLS = ark_mem->ark_liw1*11;
-    break;
-  case SPILS_PCG:
-    *lenrwLS = ark_mem->ark_lrw1 * 4;
-    *leniwLS = ark_mem->ark_liw1 * 4 + 1;
-    break;
-  case SPILS_SPFGMR:
-    maxl = arkspils_mem->s_maxl;
-    *lenrwLS = ark_mem->ark_lrw1*(2*maxl + 4) + maxl*(maxl + 4) + 1;
-    *leniwLS = ark_mem->ark_liw1*(2*maxl + 4);
-    break;
-  }
+  *nfevalsLS = arkspils_mem->nfes;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetMassWorkSpace
+ ARKSpilsGetLastFlag
 ---------------------------------------------------------------*/
-int ARKSpilsGetMassWorkSpace(void *arkode_mem, long int *lenrwMLS, 
-			     long int *leniwMLS)
+int ARKSpilsGetLastFlag(void *arkode_mem, long int *flag)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
-  int maxl;
+  ARKSpilsMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetMassWorkSpace", MSGS_ARKMEM_NULL);
+                    "ARKSpilsGetLastFlag", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_mass_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetMassWorkSpace", MSGS_MASSMEM_NULL);
-    return(ARKSPILS_MASSMEM_NULL);
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+                    "ARKSpilsGetLastFlag", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+
+  *flag = arkspils_mem->last_flag;
+
+  return(ARKSPILS_SUCCESS);
+}
+
 
-  switch(arkspils_mem->s_type) {
-  case SPILS_SPGMR:
-    maxl = arkspils_mem->s_maxl;
-    *lenrwMLS = ark_mem->ark_lrw1*(maxl + 5) + maxl*(maxl + 4) + 1;
-    *leniwMLS = ark_mem->ark_liw1*(maxl + 5);
+/*---------------------------------------------------------------
+ ARKSpilsGetReturnFlagName -- ADD SIMILAR ROUTINE TO GENERIC SUNLinearSolver MODULE
+---------------------------------------------------------------*/
+char *ARKSpilsGetReturnFlagName(long int flag)
+{
+  char *name = (char *)malloc(30*sizeof(char));
+
+  switch(flag) {
+  case ARKSPILS_SUCCESS:
+    sprintf(name,"ARKSPILS_SUCCESS");
+    break; 
+  case ARKSPILS_MEM_NULL:
+    sprintf(name,"ARKSPILS_MEM_NULL");
+    break;
+  case ARKSPILS_LMEM_NULL:
+    sprintf(name,"ARKSPILS_LMEM_NULL");
+    break;
+  case ARKSPILS_ILL_INPUT:
+    sprintf(name,"ARKSPILS_ILL_INPUT");
     break;
-  case SPILS_SPBCG:
-    *lenrwMLS = ark_mem->ark_lrw1 * 9;
-    *leniwMLS = ark_mem->ark_liw1 * 9;
+  case ARKSPILS_MEM_FAIL:
+    sprintf(name,"ARKSPILS_MEM_FAIL");
     break;
-  case SPILS_SPTFQMR:
-    *lenrwMLS = ark_mem->ark_lrw1*11;
-    *leniwMLS = ark_mem->ark_liw1*11;
+  case ARKSPILS_PMEM_NULL:
+    sprintf(name,"ARKSPILS_PMEM_NULL");
     break;
-  case SPILS_PCG:
-    *lenrwMLS = ark_mem->ark_lrw1 * 4;
-    *leniwMLS = ark_mem->ark_liw1 * 4 + 1;
+  case ARKSPILS_MASSMEM_NULL:
+    sprintf(name,"ARKSPILS_MASSMEM_NULL");
     break;
-  case SPILS_SPFGMR:
-    maxl = arkspils_mem->s_maxl;
-    *lenrwMLS = ark_mem->ark_lrw1*(2*maxl + 4) + maxl*(maxl + 4) + 1;
-    *leniwMLS = ark_mem->ark_liw1*(2*maxl + 4);
+  case ARKSPILS_SUNLS_FAIL:
+    sprintf(name,"ARKSPILS_SUNLS_FAIL");
     break;
+  default:
+    sprintf(name,"NONE");
   }
 
-  return(ARKSPILS_SUCCESS);
+  return(name);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumPrecEvals
+ ARKSpilsSetMassEpsLin
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumPrecEvals(void *arkode_mem, long int *npevals)
+int ARKSpilsSetMassEpsLin(void *arkode_mem, realtype eplifac)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
+  ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumPrecEvals", MSGS_ARKMEM_NULL);
+		    "ARKSpilsSetMassEpsLin", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsSetMassEpsLin", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *npevals = arkspils_mem->s_npe;
+  /* Check for legal eplifac */
+  if(eplifac < ZERO) {
+    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+		    "ARKSpilsSetMassEpsLin", MSGS_BAD_EPLIN);
+    return(ARKSPILS_ILL_INPUT);
+  }
+  arkspils_mem->eplifac = (eplifac == ZERO) ? ARKSPILS_EPLIN : eplifac;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumMassPrecEvals
+ ARKSpilsSetMassPreconditioner
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumMassPrecEvals(void *arkode_mem, long int *npevals)
+int ARKSpilsSetMassPreconditioner(void *arkode_mem, 
+				  ARKSpilsMassPrecSetupFn psetup, 
+				  ARKSpilsMassPrecSolveFn psolve)
 {
+  int retval;
   ARKodeMem ark_mem;
   ARKSpilsMassMem arkspils_mem;
+  PSetupFn arkspils_mpsetup;
+  PSolveFn arkspils_mpsolve;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumMassPrecEvals", MSGS_ARKMEM_NULL);
+		    "ARKSpilsSetMassPreconditioner", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumMassPrecEvals", MSGS_MASSMEM_NULL);
+		    "ARKSpilsSetMassPreconditioner", MSGS_MASSMEM_NULL);
     return(ARKSPILS_MASSMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *npevals = arkspils_mem->s_npe;
+  /* store function pointers for user-supplied routines in ARKSpils interface */
+  arkspils_mem->pset   = psetup;
+  arkspils_mem->psolve = psolve;
+
+  /* notify iterative linear solver to call ARKSpils interface routines */
+  arkspils_mpsetup = (psetup == NULL) ? NULL : ARKSpilsMPSetup;
+  arkspils_mpsolve = (psolve == NULL) ? NULL : ARKSpilsMPSolve;
+  retval = SUNLinSolSetPreconditioner(arkspils_mem->LS, ark_mem, 
+                                      arkspils_mpsetup, arkspils_mpsolve);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetMassPreconditioner", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    return(ARKSPILS_SUNLS_FAIL);
+  }
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumPrecSolves
+ ARKSpilsSetMassTimes
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumPrecSolves(void *arkode_mem, long int *npsolves)
+int ARKSpilsSetMassTimes(void *arkode_mem, 
+                         ARKSpilsMassTimesSetupFn mtsetup,
+                         ARKSpilsMassTimesVecFn mtimes,
+                         void *mtimes_data)
 {
+  int retval;
   ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
+  ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem, ark_mem->ark_mass_mem or mtimes are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumPrecSolves", MSGS_ARKMEM_NULL);
+		    "ARKSpilsSetMassTimes", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsSetMassTimes", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+  if (mtimes == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+		    "ARKSpilsSetMassTimes", 
+                    "non-NULL mtimes function must be supplied");
+    return(ARKSPILS_ILL_INPUT);
   }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  *npsolves = arkspils_mem->s_nps;
+  /* store pointers for user-supplied routines and data structure
+     in ARKSpils interface */
+  arkspils_mem->mtsetup = mtsetup;
+  arkspils_mem->mtimes  = mtimes;
+  arkspils_mem->mt_data = mtimes_data;
+
+  /* notify iterative linear solver to call ARKSpils interface routines */
+  retval = SUNLinSolSetATimes(arkspils_mem->LS, ark_mem, ARKSpilsMTimes);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", 
+                    "ARKSpilsSetMassTimes", 
+                    "Error in calling SUNLinSolSetATimes");
+    return(ARKSPILS_SUNLS_FAIL);
+  }
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumMassPrecSolves
+ ARKSpilsGetMassWorkSpace
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumMassPrecSolves(void *arkode_mem, long int *npsolves)
+int ARKSpilsGetMassWorkSpace(void *arkode_mem, long int *lenrw, 
+			     long int *leniw)
 {
   ARKodeMem ark_mem;
   ARKSpilsMassMem arkspils_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumMassPrecSolves", MSGS_ARKMEM_NULL);
+		    "ARKSpilsGetMassWorkSpace", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumMassPrecSolves", MSGS_MASSMEM_NULL);
+		    "ARKSpilsGetMassWorkSpace", MSGS_MASSMEM_NULL);
     return(ARKSPILS_MASSMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *npsolves = arkspils_mem->s_nps;
+  /* start with fixed sizes */
+  *lenrw = 4;
+  *leniw = 8;
+
+  /* add NVector sizes */
+  if (ark_mem->ark_tempv->ops->nvspace) {
+    N_VSpace(ark_mem->ark_tempv, &lrw1, &liw1);
+    *lenrw += lrw1;
+    *leniw += liw1;
+  }
+  
+  /* add LS sizes */
+  if (arkspils_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(arkspils_mem->LS, &lrw, &liw);
+    *lenrw += lrw;
+    *leniw += liw;
+  }
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumLinIters
+ ARKSpilsGetNumMassPrecEvals
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumLinIters(void *arkode_mem, long int *nliters)
+int ARKSpilsGetNumMassPrecEvals(void *arkode_mem, long int *npevals)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
+  ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumLinIters", MSGS_ARKMEM_NULL);
+		    "ARKSpilsGetNumMassPrecEvals", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumLinIters", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsGetNumMassPrecEvals", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *nliters = arkspils_mem->s_nli;
+  *npevals = arkspils_mem->npe;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumMassIters
+ ARKSpilsGetNumMassPrecSolves
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumMassIters(void *arkode_mem, long int *nmiters)
+int ARKSpilsGetNumMassPrecSolves(void *arkode_mem, long int *npsolves)
 {
   ARKodeMem ark_mem;
   ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumMassLinIters", MSGS_ARKMEM_NULL);
+		    "ARKSpilsGetNumMassPrecSolves", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumMassLinIters", MSGS_MASSMEM_NULL);
+		    "ARKSpilsGetNumMassPrecSolves", MSGS_MASSMEM_NULL);
     return(ARKSPILS_MASSMEM_NULL);
   }
   arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *nmiters = arkspils_mem->s_nli;
+  *npsolves = arkspils_mem->nps;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumConvFails
+ ARKSpilsGetNumMassIters
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumConvFails(void *arkode_mem, long int *nlcfails)
+int ARKSpilsGetNumMassIters(void *arkode_mem, long int *nmiters)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
+  ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumConvFails", MSGS_ARKMEM_NULL);
+		    "ARKSpilsGetNumMassLinIters", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumConvFails", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsGetNumMassLinIters", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *nlcfails = arkspils_mem->s_ncfl;
+  *nmiters = arkspils_mem->nli;
 
   return(ARKSPILS_SUCCESS);
 }
@@ -789,14 +1014,13 @@ int ARKSpilsGetNumMassConvFails(void *arkode_mem, long int *nmcfails)
   ARKodeMem ark_mem;
   ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
 		    "ARKSpilsGetNumMassConvFails", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
 		    "ARKSpilsGetNumMassConvFails", MSGS_MASSMEM_NULL);
@@ -804,36 +1028,35 @@ int ARKSpilsGetNumMassConvFails(void *arkode_mem, long int *nmcfails)
   }
   arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *nmcfails = arkspils_mem->s_ncfl;
+  *nmcfails = arkspils_mem->ncfl;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
 /*---------------------------------------------------------------
- ARKSpilsGetNumJtimesEvals
+ ARKSpilsGetNumMTSetups
 ---------------------------------------------------------------*/
-int ARKSpilsGetNumJtimesEvals(void *arkode_mem, long int *njvevals)
+int ARKSpilsGetNumMTSetups(void *arkode_mem, long int *nmtsetups)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
+  ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumJtimesEvals", MSGS_ARKMEM_NULL);
+		    "ARKSpilsGetNumMTSetups", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsGetNumMTSetups", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *njvevals = arkspils_mem->s_njtimes;
+  *nmtsetups = arkspils_mem->nmtsetup;
 
   return(ARKSPILS_SUCCESS);
 }
@@ -845,82 +1068,23 @@ int ARKSpilsGetNumJtimesEvals(void *arkode_mem, long int *njvevals)
 int ARKSpilsGetNumMtimesEvals(void *arkode_mem, long int *nmvevals)
 {
   ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
+  ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
 		    "ARKSpilsGetNumMtimesEvals", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
 		    "ARKSpilsGetNumMtimesEvals", MSGS_MASSMEM_NULL);
     return(ARKSPILS_MASSMEM_NULL);
   }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_mass_mem;
-
-  *nmvevals = arkspils_mem->s_njtimes;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpilsGetNumRhsEvals
----------------------------------------------------------------*/
-int ARKSpilsGetNumRhsEvals(void *arkode_mem, long int *nfevalsLS)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumRhsEvals", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetNumRhsEvals", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
-  }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  *nfevalsLS = arkspils_mem->s_nfes;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSpilsGetLastFlag
----------------------------------------------------------------*/
-int ARKSpilsGetLastFlag(void *arkode_mem, long int *flag)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetLastFlag", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  if (ark_mem->ark_lmem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
-		    "ARKSpilsGetLastFlag", MSGS_LMEM_NULL);
-    return(ARKSPILS_LMEM_NULL);
-  }
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *flag = arkspils_mem->s_last_flag;
+  *nmvevals = arkspils_mem->nmtimes;
 
   return(ARKSPILS_SUCCESS);
 }
@@ -934,14 +1098,13 @@ int ARKSpilsGetLastMassFlag(void *arkode_mem, long int *flag)
   ARKodeMem ark_mem;
   ARKSpilsMassMem arkspils_mem;
 
-  /* Return immediately if arkode_mem is NULL */
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
   if (arkode_mem == NULL) {
     arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
 		    "ARKSpilsGetLastMassFlag", MSGS_ARKMEM_NULL);
     return(ARKSPILS_MEM_NULL);
   }
   ark_mem = (ARKodeMem) arkode_mem;
-
   if (ark_mem->ark_mass_mem == NULL) {
     arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
 		    "ARKSpilsGetLastMassFlag", MSGS_MASSMEM_NULL);
@@ -949,55 +1112,18 @@ int ARKSpilsGetLastMassFlag(void *arkode_mem, long int *flag)
   }
   arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  *flag = arkspils_mem->s_last_flag;
+  *flag = arkspils_mem->last_flag;
 
   return(ARKSPILS_SUCCESS);
 }
 
 
-/*---------------------------------------------------------------
- ARKSpilsGetReturnFlagName
----------------------------------------------------------------*/
-char *ARKSpilsGetReturnFlagName(long int flag)
-{
-  char *name = (char *)malloc(30*sizeof(char));
-
-  switch(flag) {
-  case ARKSPILS_SUCCESS:
-    sprintf(name,"ARKSPILS_SUCCESS");
-    break; 
-  case ARKSPILS_MEM_NULL:
-    sprintf(name,"ARKSPILS_MEM_NULL");
-    break;
-  case ARKSPILS_LMEM_NULL:
-    sprintf(name,"ARKSPILS_LMEM_NULL");
-    break;
-  case ARKSPILS_MASSMEM_NULL:
-    sprintf(name,"ARKSPILS_MASSMEM_NULL");
-    break;
-  case ARKSPILS_ILL_INPUT:
-    sprintf(name,"ARKSPILS_ILL_INPUT");
-    break;
-  case ARKSPILS_MEM_FAIL:
-    sprintf(name,"ARKSPILS_MEM_FAIL");
-    break;
-  case ARKSPILS_PMEM_NULL:
-    sprintf(name,"ARKSPILS_PMEM_NULL");
-    break;
-  default:
-    sprintf(name,"NONE");
-  }
-
-  return(name);
-}
-
-
 /*===============================================================
-   ARKSPILS private functions
+  ARKSPILS Private functions
 ===============================================================*/
 
 /*---------------------------------------------------------------
- ARKSpilsAtimes:
+ ARKSpilsATimes:
 
  This routine generates the matrix-vector product z = Av, where
  A = M - gamma*J. The product M*v is obtained either by calling 
@@ -1007,28 +1133,39 @@ char *ARKSpilsGetReturnFlagName(long int flag)
  the same as the values returned by jtimes and mtimes -- 
  0 if successful, nonzero otherwise.
 ---------------------------------------------------------------*/
-int ARKSpilsAtimes(void *arkode_mem, N_Vector v, N_Vector z)
+int ARKSpilsATimes(void *arkode_mem, N_Vector v, N_Vector z)
 {
   ARKodeMem   ark_mem;
   ARKSpilsMem arkspils_mem;
   int jtflag, mtflag;
 
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+                    "ARKSpilsATimes", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+                    "ARKSpilsATimes", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
+  }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  jtflag = arkspils_mem->s_jtimes(v, z, ark_mem->ark_tn, 
-				  arkspils_mem->s_ycur, 
-				  arkspils_mem->s_fcur, 
-				  arkspils_mem->s_j_data, 
-				  arkspils_mem->s_ytemp);
-  arkspils_mem->s_njtimes++;
+  jtflag = arkspils_mem->jtimes(v, z, ark_mem->ark_tn, 
+                                arkspils_mem->ycur, 
+                                arkspils_mem->fcur, 
+                                arkspils_mem->j_data, 
+                                arkspils_mem->ytemp);
+  arkspils_mem->njtimes++;
   if (jtflag != 0) return(jtflag);
 
   /* Compute mass matrix vector product and add to result */
   if (ark_mem->ark_mass_matrix) {
-    mtflag = ARKSpilsMtimes(arkode_mem, v, arkspils_mem->s_ytemp);
+    mtflag = ARKSpilsMTimes(arkode_mem, v, arkspils_mem->ytemp);
     if (mtflag != 0) return(mtflag);
-    N_VLinearSum(ONE, arkspils_mem->s_ytemp, -ark_mem->ark_gamma, z, z);
+    N_VLinearSum(ONE, arkspils_mem->ytemp, -ark_mem->ark_gamma, z, z);
   } else {
     N_VLinearSum(ONE, v, -ark_mem->ark_gamma, z, z);
   }
@@ -1036,63 +1173,174 @@ int ARKSpilsAtimes(void *arkode_mem, N_Vector v, N_Vector z)
   return(0);
 }
 
+/*---------------------------------------------------------------
+ ARKSpilsPSetup:
+
+ This routine interfaces between the generic iterative linear 
+ solvers and the user's psetup routine.  It passes to psetup all 
+ required state information from arkode_mem.  Its return value 
+ is the same as that returned by psetup. Note that the generic
+ iterative linear solvers guarantee that ARKSpilsPSetup will only
+ be called in the case that the user's psetup routine is non-NULL.
+---------------------------------------------------------------*/
+int ARKSpilsPSetup(void *arkode_mem)
+{
+  int         retval;
+  ARKodeMem   ark_mem;
+  ARKSpilsMem arkspils_mem;
+
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "ARKSpilsPSetup", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsPSetup", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+
+  /* Call user pset routine to update preconditioner and possibly 
+     reset jcur (pass !jbad as update suggestion) */
+  retval = arkspils_mem->pset(ark_mem->ark_tn, 
+                              arkspils_mem->ycur, 
+                              arkspils_mem->fcur, 
+                              !(arkspils_mem->jbad),
+                              &ark_mem->ark_jcur,
+                              ark_mem->ark_gamma, 
+                              arkspils_mem->P_data);
+  return(retval);     
+}
 
 /*---------------------------------------------------------------
  ARKSpilsPSolve:
 
- This routine interfaces between the generic Sp***Solve routine
- (within the SPGMR, SPBCG, SPTFQMR, SPFGMR or PCG solver) and the 
- user's psolve routine.  It passes to psolve all required state 
- information from arkode_mem.  Its return value is the same as 
- that returned by psolve. Note that the generic SP*** solver 
- guarantees that ARKSpilsPSolve will not be called in the case 
- in which preconditioning is not done. This is the only case in 
- which the user's psolve routine is allowed to be NULL.
+ This routine interfaces between the generic SUNLinSolSolve 
+ routine and the user's psolve routine.  It passes to psolve all 
+ required state information from arkode_mem.  Its return value 
+ is the same as that returned by psolve. Note that the generic 
+ SUNLinSol solver guarantees that ARKSpilsPSolve will not be 
+ called in the case in which preconditioning is not done. This 
+ is the only case in which the user's psolve routine is allowed 
+ to be NULL.
 ---------------------------------------------------------------*/
-int ARKSpilsPSolve(void *arkode_mem, N_Vector r, N_Vector z, int lr)
+int ARKSpilsPSolve(void *arkode_mem, N_Vector r, N_Vector z,
+                   realtype tol, int lr)
 {
   ARKodeMem   ark_mem;
   ARKSpilsMem arkspils_mem;
   int retval;
 
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "ARKSpilsPSolve", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsPSolve", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
+  }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
-  /* This call is counted in nps within the ARKSp***Solve routine */
-  retval = arkspils_mem->s_psolve(ark_mem->ark_tn, 
-				  arkspils_mem->s_ycur, 
-				  arkspils_mem->s_fcur, r, z, 
-				  ark_mem->ark_gamma, 
-				  arkspils_mem->s_delta, lr, 
-				  arkspils_mem->s_P_data, 
-				  arkspils_mem->s_ytemp);
+  /* call the user-supplied psolve routine, and accumulate count */
+  retval = arkspils_mem->psolve(ark_mem->ark_tn, 
+                                arkspils_mem->ycur, 
+                                arkspils_mem->fcur, r, z, 
+                                ark_mem->ark_gamma, 
+                                tol, lr, 
+                                arkspils_mem->P_data);
+  arkspils_mem->nps++;
 
   return(retval);     
 }
 
-
 /*---------------------------------------------------------------
- ARKSpilsMtimes:
+ ARKSpilsMTimes:
 
  This routine generates the matrix-vector product z = Mv, where
  M is the system mass matrix, by calling the user-supplied mtimes
  routine.. The return value is the same as the value returned 
  by mtimes -- 0 if successful, nonzero otherwise.
 ---------------------------------------------------------------*/
-int ARKSpilsMtimes(void *arkode_mem, N_Vector v, N_Vector z)
+int ARKSpilsMTimes(void *arkode_mem, N_Vector v, N_Vector z)
 {
-  ARKodeMem ark_mem;
+  ARKodeMem       ark_mem;
+  ARKSpilsMassMem arkspils_mem;
   int retval;
+
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "ARKSpilsMTimes", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
-  retval = ark_mem->ark_mtimes(v, z, ark_mem->ark_tn, 
-			       ark_mem->ark_mtimes_data);
-  ark_mem->ark_mass_mult++;
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsMTimes", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
+  /* call user-supplied mtimes routine and increment counter */
+  retval = arkspils_mem->mtimes(v, z, ark_mem->ark_tn, 
+                                arkspils_mem->mt_data);
+  arkspils_mem->nmtimes++;
   return(retval);
 }
 
 
 /*---------------------------------------------------------------
+ ARKSpilsMPSetup:
+
+ This routine interfaces between the generic iterative linear 
+ solver and the user's mass matrix psetup routine.  It passes to
+ psetup all required state information from arkode_mem.  Its 
+ return value is the same as that returned by psetup. Note that 
+ the generic iterative linear solvers guarantee that 
+ ARKSpilsMPSetup will only be called if the user's psetup 
+ routine is non-NULL.
+---------------------------------------------------------------*/
+int ARKSpilsMPSetup(void *arkode_mem)
+{
+  ARKodeMem       ark_mem;
+  ARKSpilsMassMem arkspils_mem;
+  int retval;
+
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "ARKSpilsMPSetup", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsMPSetup", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+
+  /* only proceed if the mass matrix is time-dependent or if 
+     mpsetup has not been called previously */
+  if (!arkspils_mem->time_dependent && arkspils_mem->npe) 
+    return(0);
+  
+  /* call user-supplied pset routine and increment counter */
+  retval = arkspils_mem->pset(ark_mem->ark_tn, 
+                              arkspils_mem->P_data);  
+  arkspils_mem->npe++;
+  return(retval);     
+}
+
+
+/*---------------------------------------------------------------
  ARKSpilsMPSolve:
 
  This routine interfaces between the generic Sp***Solve routine
@@ -1104,20 +1352,31 @@ int ARKSpilsMtimes(void *arkode_mem, N_Vector v, N_Vector z)
  case in which preconditioning is not done. This is the only case 
  in which the user's psolve routine is allowed to be NULL.
 ---------------------------------------------------------------*/
-int ARKSpilsMPSolve(void *arkode_mem, N_Vector r, N_Vector z, int lr)
+int ARKSpilsMPSolve(void *arkode_mem, N_Vector r, N_Vector z,
+                    realtype tol, int lr)
 {
   ARKodeMem       ark_mem;
   ARKSpilsMassMem arkspils_mem;
   int retval;
 
+  /* Return immediately if arkode_mem or ark_mem->ark_mass_mem are NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "ARKSpilsMPSolve", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
   ark_mem = (ARKodeMem) arkode_mem;
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsMPSolve", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
+  }
   arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
 
-  /* This call is counted in nps within the ARKSp***Solve routine */
-  retval = arkspils_mem->s_psolve(ark_mem->ark_tn, r, z, 
-				  arkspils_mem->s_delta, lr, 
-				  arkspils_mem->s_P_data, 
-				  arkspils_mem->s_ytemp);
+  /* call the user-supplied psolve routine, and accumulate count */
+  retval = arkspils_mem->psolve(ark_mem->ark_tn, r, z, tol, lr, 
+                                arkspils_mem->P_data);
+  arkspils_mem->nps++;
   return(retval);     
 }
 
@@ -1132,15 +1391,25 @@ int ARKSpilsMPSolve(void *arkode_mem, N_Vector r, N_Vector z, int lr)
 ---------------------------------------------------------------*/
 int ARKSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t, 
 		     N_Vector y, N_Vector fy,
-		     void *data, N_Vector work)
+		     void *arkode_mem, N_Vector work)
 {
   ARKodeMem ark_mem;
   ARKSpilsMem arkspils_mem;
   realtype sig, siginv;
   int iter, retval;
 
-  /* data is arkode_mem */
-  ark_mem = (ARKodeMem) data;
+  /* Return immediately if arkode_mem or ark_mem->ark_lmem are NULL */
+  if (arkode_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "ARKSpilsDQJtimes", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  ark_mem = (ARKodeMem) arkode_mem;
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+		    "ARKSpilsDQJtimes", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
+  }
   arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
 
   /* Initialize perturbation to 1/||v|| */
@@ -1153,7 +1422,7 @@ int ARKSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
 
     /* Set Jv = f(tn, y+sig*v) */
     retval = ark_mem->ark_fi(t, work, Jv, ark_mem->ark_user_data); 
-    arkspils_mem->s_nfes++;
+    arkspils_mem->nfes++;
     if (retval == 0) break;
     if (retval < 0)  return(-1);
 
@@ -1173,15 +1442,582 @@ int ARKSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
 }
 
 
+/*---------------------------------------------------------------
+ arkSpilsInitialize performs remaining initializations specific
+ to the iterative linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int arkSpilsInitialize(ARKodeMem ark_mem)
+{
+  int retval;
+  ARKSpilsMem arkspils_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "arkSpilsInitialize", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+		    "arkSpilsInitialize", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+  
+  arkSpilsInitializeCounters(arkspils_mem);
+
+  /* Set Jacobian-related fields, based on jtimesDQ */
+  if (arkspils_mem->jtimesDQ) {
+    arkspils_mem->jtsetup = NULL;
+    arkspils_mem->jtimes = ARKSpilsDQJtimes;
+    arkspils_mem->j_data = ark_mem;
+  } else {
+    arkspils_mem->j_data = ark_mem->ark_user_data;
+  }
+
+  /* if psetup is not present, then arkSpilsSetup does not need to be 
+     called, so set the lsetup function to NULL */
+  if (arkspils_mem->pset == NULL)  ark_mem->ark_lsetup = NULL;
+
+  /* Ensure that if a mass matrix / solver are used, that system 
+     and mass matrix solver types match (and both are set up) */
+  if (ark_mem->ark_mass_matrix) {
+
+    /* access mass matrix solver interface */
+    if (ark_mem->ark_mass_mem == NULL) {
+      arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+                      "arkSpilsInitialize", MSGS_MASSMEM_NULL);
+      return(ARKSPILS_MASSMEM_NULL);
+    }
+
+    /* check that ark_msolve_type is compatible */
+    if (ark_mem->ark_msolve_type != 0) {
+      arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+		      "arkSpilsInitialize",
+                      "Spils and Spils solvers cannot be combined");
+      arkspils_mem->last_flag = ARKSPILS_ILL_INPUT;
+      return(-1);
+    }
+
+    /* initialize mass matrix linear solver */
+    retval = arkSpilsMassInitialize(ark_mem);
+    if (retval != ARKSPILS_SUCCESS) {
+      arkspils_mem->last_flag = retval;
+      return(arkspils_mem->last_flag);
+    }
+  }
+
+  /* Call LS initialize routine */
+  arkspils_mem->last_flag = SUNLinSolInitialize(arkspils_mem->LS);
+  return(arkspils_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsSetup calls the LS 'setup' routine.
+---------------------------------------------------------------*/
+int arkSpilsSetup(ARKodeMem ark_mem, int convfail, N_Vector ypred,
+                  N_Vector fpred, booleantype *jcurPtr, 
+                  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+{
+  realtype dgamma;
+  int  retval;
+  ARKSpilsMem arkspils_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "arkSpilsSetup", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+		    "arkSpilsSetup", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+
+  /* Set ARKSpils N_Vector pointers to current solution and rhs */
+  arkspils_mem->ycur = ypred;
+  arkspils_mem->fcur = fpred;
+
+  /* Use nst, gamma/gammap, and convfail to set J/P eval. flag jok */
+  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
+  arkspils_mem->jbad = (ark_mem->ark_nst == 0) || 
+    (ark_mem->ark_nst > arkspils_mem->nstlpre + ARKSPILS_MSBPRE) ||
+    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKSPILS_DGMAX)) ||
+    (convfail == ARK_FAIL_OTHER);
+  *jcurPtr = arkspils_mem->jbad;
+  
+  /* Call LS setup routine -- the LS will call ARKSpilsPSetup, who will 
+     pass the heuristic suggestions above to the user code(s) */
+  retval = SUNLinSolSetup(arkspils_mem->LS, NULL);
+
+  /* If user set jcur to SUNTRUE, increment npe and save nst value */
+  if (*jcurPtr) {
+    arkspils_mem->npe++;
+    arkspils_mem->nstlpre = ark_mem->ark_nst;
+  }
+
+  /* Update jcurPtr flag if we suggested an update */
+  if (arkspils_mem->jbad) *jcurPtr = SUNTRUE;
+
+  return(retval);
+}
+
+/*---------------------------------------------------------------
+ arkSpilsSolve: interfaces between ARKode and the generic 
+ SUNLinearSolver object LS, by setting the appropriate tolerance 
+ and scaling vectors, calling the solver, and accumulating 
+ statistics from the solve for use/reporting by ARKode.
+---------------------------------------------------------------*/
+int arkSpilsSolve(ARKodeMem ark_mem, N_Vector b, N_Vector ynow, 
+                  N_Vector fnow)
+{
+  realtype bnorm, res_norm;
+  ARKSpilsMem arkspils_mem;
+  int nli_inc, nps_inc, retval;
+  
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "arkSpilsSolve", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  if (ark_mem->ark_lmem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_LMEM_NULL, "ARKSPILS", 
+		    "arkSpilsSolve", MSGS_LMEM_NULL);
+    return(ARKSPILS_LMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+
+  /* Test norm(b); if small, return x = 0 or x = b */
+  arkspils_mem->deltar = arkspils_mem->eplifac * ark_mem->ark_eRNrm; 
+  bnorm = N_VWrmsNorm(b, ark_mem->ark_rwt);
+  if (bnorm <= arkspils_mem->deltar) {
+    if (ark_mem->ark_mnewt > 0) N_VConst(ZERO, b); 
+    return(0);
+  }
+
+  /* Set vectors ycur and fcur for use by the Atimes and Psolve 
+     interface routines */
+  arkspils_mem->ycur = ynow;
+  arkspils_mem->fcur = fnow;
+
+  /* Set input tolerance and initial guess x = 0 to LS */  
+  arkspils_mem->delta = arkspils_mem->deltar * arkspils_mem->sqrtN;
+  N_VConst(ZERO, arkspils_mem->x);
+
+  /* Set scaling vectors for LS to use */
+  retval = SUNLinSolSetScalingVectors(arkspils_mem->LS,
+                                      ark_mem->ark_ewt,
+                                      ark_mem->ark_rwt);
+  if (retval != SUNLS_SUCCESS) {
+    arkProcessError(ark_mem, ARKSPILS_SUNLS_FAIL, "ARKSPILS", "arkSpilsSolve", 
+                    "Error in calling SUNLinSolSetScalingVectors");
+    return(ARKSPILS_SUNLS_FAIL);
+  }
+
+  /* Store previous nps value in nps_inc */
+  nps_inc = arkspils_mem->nps;
+
+  /* If a user-provided jtsetup routine is supplied, call that here */
+  if (arkspils_mem->jtsetup) {
+    retval = arkspils_mem->jtsetup(ark_mem->ark_tn, ynow, fnow, 
+                                 arkspils_mem->j_data);
+    arkspils_mem->njtsetup++;
+    if (retval != 0) {
+      arkProcessError(ark_mem, retval, "ARKSPILS", 
+                      "arkSpilsSolve", MSGS_JTSETUP_FAILED);
+      return(retval);
+    }
+  }
+  
+  /* Call solver, and copy x to b */
+  retval = SUNLinSolSolve(arkspils_mem->LS, NULL, arkspils_mem->x,
+                          b, arkspils_mem->delta);
+  N_VScale(ONE, arkspils_mem->x, b);
+
+  /* Retrieve solver statistics */
+  res_norm = SUNLinSolResNorm(arkspils_mem->LS);
+  nli_inc  = SUNLinSolNumIters(arkspils_mem->LS);
+  nps_inc  = arkspils_mem->nps - nps_inc;
+  
+  /* Increment counters nli and ncfl */
+  arkspils_mem->nli += nli_inc;
+  if (retval != SUNLS_SUCCESS) arkspils_mem->ncfl++;
+
+  /* Log solver statistics to diagnostics file (if requested) */
+  if (ark_mem->ark_report) 
+    fprintf(ark_mem->ark_diagfp, "      kry  %"RSYM"  %"RSYM"  %i  %i\n", 
+            bnorm, res_norm, nli_inc, nps_inc);
+  
+  /* Interpret solver return value  */
+  arkspils_mem->last_flag = retval;
+
+  switch(retval) {
+
+  case SUNLS_SUCCESS:
+    return(0);
+    break;
+  case SUNLS_RES_REDUCED:
+    /* allow reduction but not solution on first Newton iteration, 
+       otherwise return with a recoverable failure */
+    if (ark_mem->ark_mnewt == 0) return(0);
+    else                         return(1);
+    break;
+  case SUNLS_CONV_FAIL:
+  case SUNLS_ATIMES_FAIL_REC:
+  case SUNLS_PSOLVE_FAIL_REC:
+  case SUNLS_PACKAGE_FAIL_REC:
+  case SUNLS_QRFACT_FAIL:
+  case SUNLS_LUFACT_FAIL:
+    return(1);
+    break;
+  case SUNLS_MEM_NULL:
+  case SUNLS_ILL_INPUT:
+  case SUNLS_MEM_FAIL:
+  case SUNLS_GS_FAIL:
+  case SUNLS_QRSOL_FAIL:
+    return(-1);
+    break;
+  case SUNLS_PACKAGE_FAIL_UNREC:
+    arkProcessError(ark_mem, SUNLS_PACKAGE_FAIL_UNREC, "ARKSPILS", 
+                    "arkSpilsSolve",
+                    "Failure in SUNLinSol external package");
+    return(-1);
+    break;
+  case SUNLS_ATIMES_FAIL_UNREC:
+    arkProcessError(ark_mem, SUNLS_ATIMES_FAIL_UNREC, "ARKSPILS", 
+                    "arkSpilsSolve", MSGS_JTIMES_FAILED);    
+    return(-1);
+    break;
+  case SUNLS_PSOLVE_FAIL_UNREC:
+    arkProcessError(ark_mem, SUNLS_PSOLVE_FAIL_UNREC, "ARKSPILS", 
+                    "arkSpilsSolve", MSGS_PSOLVE_FAILED);
+    return(-1);
+    break;
+  }
+  
+  return(0); 
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsFree frees memory associates with the ARKSpils system
+ solver interface.
+---------------------------------------------------------------*/
+int arkSpilsFree(ARKodeMem ark_mem)
+{
+  ARKSpilsMem arkspils_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_lmem are NULL */
+  if (ark_mem == NULL)  return (ARKSPILS_SUCCESS);
+  if (ark_mem->ark_lmem == NULL)  return(ARKSPILS_SUCCESS);
+  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
+
+  /* Free N_Vector memory */
+  if (arkspils_mem->ytemp) {
+    N_VDestroy(arkspils_mem->ytemp);
+    arkspils_mem->ytemp = NULL;
+  }
+  if (arkspils_mem->x) {
+    N_VDestroy(arkspils_mem->x);
+    arkspils_mem->x = NULL;
+  }
+
+  /* Nullify other N_Vector pointers */
+  arkspils_mem->ycur = NULL;
+  arkspils_mem->fcur = NULL;
+
+  /* Free preconditioner memory (if applicable) */
+  if (arkspils_mem->pfree)  arkspils_mem->pfree(ark_mem);
+  
+  /* free ARKSpils interface structure */
+  free(ark_mem->ark_lmem);
+  
+  return(ARKSPILS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsMassInitialize performs remaining initializations specific
+ to the iterative linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int arkSpilsMassInitialize(ARKodeMem ark_mem)
+{
+  ARKSpilsMassMem arkspils_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "arkSpilsMassInitialize", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "arkSpilsMassInitialize", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+  
+  arkSpilsInitializeMassCounters(arkspils_mem);
+
+  /* ensure that mtimes routine and mass matrix solver exist */
+  if (arkspils_mem->mtimes == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+                    "arkSpilsMassInitialize",
+                    "SpilsMass solver cannot run without user-provided mass matrix-vector product routine");
+    arkspils_mem->last_flag = ARKSPILS_ILL_INPUT;
+    return(-1);
+  }
+  if (arkspils_mem->LS == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPILS", 
+                    "arkSpilsMassInitialize",
+                    "SpilsMass solver cannot run without SUNLinearSolver object");
+    arkspils_mem->last_flag = ARKSPILS_ILL_INPUT;
+    return(-1);
+  }
+
+  /* if psetup is not present, then arkSpilsMassSetup does not need 
+     to be called, so set the msetup function to NULL */
+  if (arkspils_mem->pset == NULL)  ark_mem->ark_msetup = NULL;
+
+  /* Call LS initialize routine */
+  arkspils_mem->last_flag = SUNLinSolInitialize(arkspils_mem->LS);
+  return(arkspils_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsMassSetup calls the LS 'setup' routine.
+---------------------------------------------------------------*/
+int arkSpilsMassSetup(ARKodeMem ark_mem, N_Vector vtemp1,
+                      N_Vector vtemp2, N_Vector vtemp3)
+{
+  int retval;
+  ARKSpilsMassMem arkspils_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "arkSpilsMassSetup", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "arkSpilsMassSetup", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+
+  /* Call LS setup routine */
+  retval = SUNLinSolSetup(arkspils_mem->LS, NULL);
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsMassMult just calls ARKSpilsMTimes routine.
+---------------------------------------------------------------*/
+int arkSpilsMassMult(ARKodeMem ark_mem, N_Vector v, N_Vector Mv)
+{
+  int retval;
+  /* Return immediately if ark_mem is  NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "arkSpilsMassMult", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  retval = ARKSpilsMTimes(ark_mem, v, Mv);
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsMassSolve: interfaces between ARKode and the generic 
+ SUNLinearSolver object LS, by setting the appropriate tolerance 
+ and scaling vectors, calling the solver, and accumulating 
+ statistics from the solve for use/reporting by ARKode.
+---------------------------------------------------------------*/
+int arkSpilsMassSolve(ARKodeMem ark_mem, N_Vector b)
+{
+  realtype res_norm;
+  ARKSpilsMassMem arkspils_mem;
+  int nli_inc, nps_inc, retval;
+  
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL) {
+    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPILS", 
+		    "arkSpilsMassSolve", MSGS_ARKMEM_NULL);
+    return(ARKSPILS_MEM_NULL);
+  }
+  if (ark_mem->ark_mass_mem == NULL) {
+    arkProcessError(ark_mem, ARKSPILS_MASSMEM_NULL, "ARKSPILS", 
+		    "arkSpilsMassSolve", MSGS_MASSMEM_NULL);
+    return(ARKSPILS_MASSMEM_NULL);
+  }
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+
+  /* Set input tolerance and initial guess x = 0 to LS */  
+  arkspils_mem->deltar = arkspils_mem->eplifac * ark_mem->ark_nlscoef; 
+  arkspils_mem->delta  = arkspils_mem->deltar * arkspils_mem->sqrtN;
+  N_VConst(ZERO, arkspils_mem->x);
+
+  /* Set scaling vectors for LS to use */
+  retval = SUNLinSolSetScalingVectors(arkspils_mem->LS,
+                                      ark_mem->ark_ewt,
+                                      ark_mem->ark_rwt);
+  if (retval != SUNLS_SUCCESS) {
+    arkspils_mem->last_flag = retval;
+    return(retval);
+  }
+
+  /* Store previous nps value in nps_inc */
+  nps_inc = arkspils_mem->nps;
+
+  /* If a user-provided mtsetup routine is supplied, the mass 
+     matrix is time-dependent, call that here */
+  if (!arkspils_mem->time_dependent && arkspils_mem->nmtsetup) {
+    retval = arkspils_mem->mtsetup(ark_mem->ark_tn, 
+                                   arkspils_mem->mt_data);
+    arkspils_mem->nmtsetup++;
+    if (retval != 0) {
+      arkProcessError(ark_mem, retval, "ARKSPILS", 
+                      "arkSpilsMassSolve", MSGS_MTSETUP_FAILED);
+      return(retval);
+    }
+  }
+  
+  /* Call solver, and copy x to b */
+  retval = SUNLinSolSolve(arkspils_mem->LS, NULL, arkspils_mem->x,
+                          b, arkspils_mem->delta);
+  if (retval != SUNLS_SUCCESS) {
+    arkspils_mem->last_flag = retval;
+    return(retval);
+  }
+  N_VScale(ONE, arkspils_mem->x, b);
+
+  /* Retrieve solver statistics */
+  res_norm = SUNLinSolResNorm(arkspils_mem->LS);
+  nli_inc  = SUNLinSolNumIters(arkspils_mem->LS);
+  nps_inc  = arkspils_mem->nps - nps_inc;
+  
+  /* Increment counters nli and ncfl */
+  arkspils_mem->nli += nli_inc;
+  if (retval != SUNLS_SUCCESS) arkspils_mem->ncfl++;
+
+  /* Log solver statistics to diagnostics file (if requested) */
+  if (ark_mem->ark_report) 
+    fprintf(ark_mem->ark_diagfp, "      mass  %"RSYM"  %i  %i\n", 
+	    res_norm, nli_inc, nps_inc);
+  
+  /* Interpret solver return value  */
+  arkspils_mem->last_flag = retval;
+
+  switch(retval) {
+
+  case SUNLS_SUCCESS:
+    return(0);
+    break;
+  case SUNLS_RES_REDUCED:
+  case SUNLS_CONV_FAIL:
+  case SUNLS_ATIMES_FAIL_REC:
+  case SUNLS_PSOLVE_FAIL_REC:
+  case SUNLS_PACKAGE_FAIL_REC:
+  case SUNLS_QRFACT_FAIL:
+  case SUNLS_LUFACT_FAIL:
+    return(1);
+    break;
+  case SUNLS_MEM_NULL:
+  case SUNLS_ILL_INPUT:
+  case SUNLS_MEM_FAIL:
+  case SUNLS_GS_FAIL:
+  case SUNLS_QRSOL_FAIL:
+    return(-1);
+    break;
+  case SUNLS_PACKAGE_FAIL_UNREC:
+    arkProcessError(ark_mem, SUNLS_PACKAGE_FAIL_UNREC, "ARKSPILS", 
+		    "arkSpilsMassSolve",
+                    "Failure in SUNLinSol external package");
+    return(-1);
+    break;
+  case SUNLS_ATIMES_FAIL_UNREC:
+    arkProcessError(ark_mem, SUNLS_ATIMES_FAIL_UNREC, "ARKSPILS", 
+		    "arkSpilsMassSolve", MSGS_MTIMES_FAILED);    
+    return(-1);
+    break;
+  case SUNLS_PSOLVE_FAIL_UNREC:
+    arkProcessError(ark_mem, SUNLS_PSOLVE_FAIL_UNREC, "ARKSPILS", 
+		    "arkSpilsMassSolve", MSGS_PSOLVE_FAILED);
+    return(-1);
+    break;
+  }
+  
+  return(0); 
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsMassFree frees memory associates with the ARKSpils mass
+ matrix solver interface.
+---------------------------------------------------------------*/
+int arkSpilsMassFree(ARKodeMem ark_mem)
+{
+  ARKSpilsMassMem arkspils_mem;
+
+  /* Return immediately if ark_mem or ark_mem->ark_mass_mem are NULL */
+  if (ark_mem == NULL)  return (ARKSPILS_SUCCESS);
+  if (ark_mem->ark_mass_mem == NULL)  return(ARKSPILS_SUCCESS);
+  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
+
+  /* detach ARKSpils interface routines from LS object (ignore return values) */
+  SUNLinSolSetATimes(arkspils_mem->LS, NULL, NULL);
+  SUNLinSolSetPreconditioner(arkspils_mem->LS, NULL, NULL, NULL);
+
+  /* Free N_Vector memory */
+  if (arkspils_mem->x) {
+    N_VDestroy(arkspils_mem->x);
+    arkspils_mem->x = NULL;
+  }
+
+  /* Nullify other N_Vector pointers */
+  arkspils_mem->ycur = NULL;
+
+  /* free ARKSpils interface structure */
+  free(ark_mem->ark_mass_mem);
+  
+  return(ARKSPILS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ arkSpilsInitializeCounters and arkSpilsInitializeMassCounters:
+
+ These routines reset all counters from an ARKSpilsMem or 
+ ARKSpilsMassMem structure.
+---------------------------------------------------------------*/
 int arkSpilsInitializeCounters(ARKSpilsMem arkspils_mem)
 {
-  arkspils_mem->s_npe     = 0;
-  arkspils_mem->s_nli     = 0;
-  arkspils_mem->s_nps     = 0;
-  arkspils_mem->s_ncfl    = 0;
-  arkspils_mem->s_nstlpre = 0;
-  arkspils_mem->s_njtimes = 0;
-  arkspils_mem->s_nfes    = 0;
+  arkspils_mem->npe      = 0;
+  arkspils_mem->nli      = 0;
+  arkspils_mem->nps      = 0;
+  arkspils_mem->ncfl     = 0;
+  arkspils_mem->nstlpre  = 0;
+  arkspils_mem->njtsetup = 0;
+  arkspils_mem->njtimes  = 0;
+  arkspils_mem->nfes     = 0;
+  return(0); 
+}
+
+int arkSpilsInitializeMassCounters(ARKSpilsMassMem arkspils_mem)
+{
+  arkspils_mem->npe      = 0;
+  arkspils_mem->nli      = 0;
+  arkspils_mem->nps      = 0;
+  arkspils_mem->ncfl     = 0;
+  arkspils_mem->nmtsetup = 0;
+  arkspils_mem->nmtimes  = 0;
   return(0); 
 }
 
diff --git a/src/arkode/arkode_spils_impl.h b/src/arkode/arkode_spils_impl.h
index 7703e46..ef19d27 100644
--- a/src/arkode/arkode_spils_impl.h
+++ b/src/arkode/arkode_spils_impl.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,8 +15,8 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Common implementation header file for the scaled, preconditioned
- * linear solver modules.
+ * Implementation header file for the scaled, preconditioned
+ * linear solver interface.
  *--------------------------------------------------------------*/
 
 #ifndef _ARKSPILS_IMPL_H
@@ -30,14 +30,6 @@ extern "C" {
 #endif
 
 
-/* Types of iterative linear solvers */
-#define SPILS_SPGMR   1
-#define SPILS_SPBCG   2
-#define SPILS_SPTFQMR 3
-#define SPILS_PCG     4
-#define SPILS_SPFGMR  5
-
-
 /*---------------------------------------------------------------
  Types: ARKSpilsMemRec, ARKSpilsMem
 
@@ -45,31 +37,28 @@ extern "C" {
 ---------------------------------------------------------------*/
 typedef struct ARKSpilsMemRec {
 
-  int s_type;           /* type of scaled preconditioned iterative LS   */
-
-  int  s_pretype;       /* type of preconditioning                      */
-  int  s_gstype;        /* type of Gram-Schmidt orthogonalization       */
-  realtype s_sqrtN;     /* sqrt(N)                                      */
-  realtype s_eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
-  realtype s_deltar;    /* deltar = delt * LTE                          */
-  realtype s_delta;     /* delta = deltar * sqrtN                       */
-  int  s_maxl;          /* maxl = maximum dimension of the Krylov space */
-
-  long int s_nstlpre;   /* value of nst at the last pset call           */
-  long int s_npe;       /* npe = total number of pset calls             */
-  long int s_nli;       /* nli = total number of linear iterations      */
-  long int s_nps;       /* nps = total number of psolve calls           */
-  long int s_ncfl;      /* ncfl = total number of convergence failures  */
-  long int s_njtimes;   /* njtimes = total number of calls to jtimes    */
-  long int s_nfes;      /* nfeSG = total number of calls to f for     
-                           difference quotient Jacobian-vector products */
-
-  N_Vector s_ytemp;     /* temp vector passed to jtimes and psolve      */
-  N_Vector s_x;         /* temp vector used by ARKSpilsSolve            */
-  N_Vector s_ycur;      /* ARKODE current y vector in Newton Iteration  */
-  N_Vector s_fcur;      /* fcur = f(tn, ycur)                           */
-
-  void* s_spils_mem;    /* memory used by the generic solver            */
+  realtype sqrtN;     /* sqrt(N)                                      */
+  realtype eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
+  realtype deltar;    /* deltar = delt * LTE                          */
+  realtype delta;     /* delta = deltar * sqrtN                       */
+
+  booleantype jbad;   /* heuristic suggestion for pset/JTimes         */
+  long int nstlpre;   /* value of nst at the last pset call           */
+  long int npe;       /* npe = total number of pset calls             */
+  long int nli;       /* nli = total number of linear iterations      */
+  long int nps;       /* nps = total number of psolve calls           */
+  long int ncfl;      /* ncfl = total number of convergence failures  */
+  long int njtsetup;  /* njtsetup = total number of calls to jtsetup  */
+  long int njtimes;   /* njtimes = total number of calls to jtimes    */
+  long int nfes;      /* nfeSG = total number of calls to f for     
+                         difference quotient Jacobian-vector products */
+
+  SUNLinearSolver LS; /* generic iterative linear solver object       */
+  
+  N_Vector ytemp;     /* temp vector passed to jtimes and psolve      */
+  N_Vector x;         /* solution vector used by SUNLinearSolver      */
+  N_Vector ycur;      /* ARKODE current y vector in Newton Iteration  */
+  N_Vector fcur;      /* fcur = f(tn, ycur)                           */
 
   /* Preconditioner computation
     (a) user-provided:
@@ -78,23 +67,24 @@ typedef struct ARKSpilsMemRec {
     (b) internal preconditioner module
         - P_data == arkode_mem
         - pfree == set by the prec. module and called in ARKodeFree  */
-  ARKSpilsPrecSetupFn s_pset;
-  ARKSpilsPrecSolveFn s_psolve;
-  int (*s_pfree)(ARKodeMem ark_mem);
-  void *s_P_data;
+  ARKSpilsPrecSetupFn pset;
+  ARKSpilsPrecSolveFn psolve;
+  int (*pfree)(ARKodeMem ark_mem);
+  void *P_data;
 
   /* Jacobian times vector compuation
     (a) jtimes function provided by the user:
         - j_data == user_data
-        - jtimesDQ == FALSE
+        - jtimesDQ == SUNFALSE
     (b) internal jtimes
         - j_data == arkode_mem
-        - jtimesDQ == TRUE   */
-  booleantype s_jtimesDQ;
-  ARKSpilsJacTimesVecFn s_jtimes;
-  void *s_j_data;
+        - jtimesDQ == SUNTRUE   */
+  booleantype jtimesDQ;
+  ARKSpilsJacTimesSetupFn jtsetup;
+  ARKSpilsJacTimesVecFn jtimes;
+  void *j_data;
 
-  long int s_last_flag; /* last error flag returned by any function     */
+  long int last_flag; /* last error flag returned by any function */
 
 } *ARKSpilsMem;
 
@@ -106,26 +96,24 @@ typedef struct ARKSpilsMemRec {
 ---------------------------------------------------------------*/
 typedef struct ARKSpilsMassMemRec {
 
-  int s_type;           /* type of scaled preconditioned iterative LS   */
-
-  int  s_pretype;       /* type of preconditioning                      */
-  int  s_gstype;        /* type of Gram-Schmidt orthogonalization       */
-  realtype s_sqrtN;     /* sqrt(N)                                      */
-  realtype s_eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
-  realtype s_deltar;    /* deltar = delt * LTE                          */
-  realtype s_delta;     /* delta = deltar * sqrtN                       */
-  int  s_maxl;          /* maxl = maximum dimension of the Krylov space */
+  realtype sqrtN;     /* sqrt(N)                                      */
+  realtype eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
+  realtype deltar;    /* deltar = delt * LTE                          */
+  realtype delta;     /* delta = deltar * sqrtN                       */
 
-  long int s_npe;       /* npe = total number of pset calls             */
-  long int s_nli;       /* nli = total number of linear iterations      */
-  long int s_nps;       /* nps = total number of psolve calls           */
-  long int s_ncfl;      /* ncfl = total number of convergence failures  */
+  long int npe;       /* npe = total number of pset calls             */
+  long int nli;       /* nli = total number of linear iterations      */
+  long int nps;       /* nps = total number of psolve calls           */
+  long int ncfl;      /* ncfl = total number of convergence failures  */
+  long int nmtsetup;  /* nmtsetup = total number of calls to mtsetup  */
+  long int nmtimes;   /* nmtimes = total number of calls to mtimes    */
 
-  N_Vector s_ytemp;     /* temp vector passed to mtimes and psolve      */
-  N_Vector s_x;         /* temp vector used by ARKSpilsSolve            */
-  N_Vector s_ycur;      /* ARKODE current y vector                      */
+  SUNLinearSolver LS; /* generic iterative linear solver object       */
 
-  void* s_spils_mem;    /* memory used by the generic solver            */
+  booleantype time_dependent;  /* flag stating whether M depends on t */
+  
+  N_Vector x;         /* solution vector used by SUNLinearSolver      */
+  N_Vector ycur;      /* ARKODE current y vector                      */
 
   /* Preconditioner computation
     (a) user-provided:
@@ -134,12 +122,17 @@ typedef struct ARKSpilsMassMemRec {
     (b) internal preconditioner module
         - P_data == arkode_mem
         - pfree == set by the prec. module and called in ARKodeFree */
-  ARKSpilsMassPrecSetupFn s_pset;
-  ARKSpilsMassPrecSolveFn s_psolve;
-  int (*s_pfree)(ARKodeMem ark_mem);
-  void *s_P_data;
-
-  long int s_last_flag; /* last error flag returned by any function     */
+  ARKSpilsMassPrecSetupFn pset;
+  ARKSpilsMassPrecSolveFn psolve;
+  int (*pfree)(ARKodeMem ark_mem);
+  void *P_data;
+
+  /* Mass matrix times vector setup and product routines, data */
+  ARKSpilsMassTimesSetupFn mtsetup;
+  ARKSpilsMassTimesVecFn mtimes;
+  void *mt_data;
+  
+  long int last_flag; /* last error flag returned by any function     */
 
 } *ARKSpilsMassMem;
 
@@ -148,41 +141,69 @@ typedef struct ARKSpilsMassMemRec {
  Prototypes of internal functions
 ---------------------------------------------------------------*/
 
-/* Atimes and PSolve routines called by generic solver */
-int ARKSpilsAtimes(void *ark_mem, N_Vector v, N_Vector z);
-int ARKSpilsPSolve(void *ark_mem, N_Vector r, N_Vector z, int lr);
+/* Interface routines called by system SUNLinearSolver */
+int ARKSpilsATimes(void *ark_mem, N_Vector v, N_Vector z);
+int ARKSpilsPSetup(void *ark_mem);
+int ARKSpilsPSolve(void *ark_mem, N_Vector r, N_Vector z,
+                   realtype tol, int lr);
 
-/* Mtimes and MPSolve routines called by mass matrix solver */
-int ARKSpilsMtimes(void *ark_mem, N_Vector v, N_Vector z);
-int ARKSpilsMPSolve(void *ark_mem, N_Vector r, N_Vector z, int lr);
+/* Interface routines called by mass SUNLinearSolver */
+int ARKSpilsMTimes(void *ark_mem, N_Vector v, N_Vector z);
+int ARKSpilsMPSetup(void *ark_mem);
+int ARKSpilsMPSolve(void *ark_mem, N_Vector r, N_Vector z,
+                    realtype tol, int lr);
 
 /* Difference quotient approximation for Jac times vector */
 int ARKSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
                      N_Vector y, N_Vector fy, void *data,
                      N_Vector work);
 
+/* Generic linit/lsetup/lsolve/lfree interface routines for ARKode to call */
+int arkSpilsInitialize(ARKodeMem ark_mem);
+
+int arkSpilsSetup(ARKodeMem ark_mem, int convfail, N_Vector ypred,
+                  N_Vector fpred, booleantype *jcurPtr, 
+                  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); 
+
+int arkSpilsSolve(ARKodeMem ark_mem, N_Vector b, N_Vector ycur, N_Vector fcur);
+
+int arkSpilsFree(ARKodeMem ark_mem);
+
+/* Generic minit/msetup/mmult/msolve/mfree routines for ARKode to call */  
+int arkSpilsMassInitialize(ARKodeMem ark_mem);
+  
+int arkSpilsMassSetup(ARKodeMem ark_mem, N_Vector vtemp1,
+                      N_Vector vtemp2, N_Vector vtemp3); 
+
+int arkSpilsMassMult(ARKodeMem ark_mem, N_Vector v, N_Vector Mv);
+
+int arkSpilsMassSolve(ARKodeMem ark_mem, N_Vector b);
+
+int arkSpilsMassFree(ARKodeMem ark_mem);
+
 /* Auxilliary functions */
 int arkSpilsInitializeCounters(ARKSpilsMem arkspils_mem);
 
+int arkSpilsInitializeMassCounters(ARKSpilsMassMem arkspils_mem);
+
 
 /*---------------------------------------------------------------
- Error Messages
+ Error Messages -- REMOVE SOME???
 ---------------------------------------------------------------*/
 #define MSGS_ARKMEM_NULL   "Integrator memory is NULL."
 #define MSGS_MEM_FAIL      "A memory request failed."
 #define MSGS_BAD_NVECTOR   "A required vector operation is not implemented."
 #define MSGS_BAD_LSTYPE    "Incompatible linear solver type."
-#define MSGS_BAD_PRETYPE   "Illegal value for pretype. Legal values are PREC_NONE, PREC_LEFT, PREC_RIGHT, and PREC_BOTH."
-#define MSGS_PSOLVE_REQ    "pretype != PREC_NONE, but PSOLVE = NULL is illegal."
 #define MSGS_LMEM_NULL     "Linear solver memory is NULL."
 #define MSGS_MASSMEM_NULL  "Mass matrix solver memory is NULL."
-#define MSGS_BAD_GSTYPE    "Illegal value for gstype. Legal values are MODIFIED_GS and CLASSICAL_GS."
 #define MSGS_BAD_EPLIN     "eplifac < 0 illegal."
 
 #define MSGS_PSET_FAILED   "The preconditioner setup routine failed in an unrecoverable manner."
 #define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner."
+#define MSGS_JTSETUP_FAILED "The Jacobian x vector setup routine failed in an unrecoverable manner."
 #define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
-#define MSGS_MTIMES_FAILED "The mass matrix * vector routine failed in an unrecoverable manner."
+#define MSGS_MTSETUP_FAILED "The mass matrix x vector setup routine failed in an unrecoverable manner."
+#define MSGS_MTIMES_FAILED "The mass matrix x vector routine failed in an unrecoverable manner."
 
 
 #ifdef __cplusplus
diff --git a/src/arkode/arkode_sptfqmr.c b/src/arkode/arkode_sptfqmr.c
deleted file mode 100644
index 605093a..0000000
--- a/src/arkode/arkode_sptfqmr.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Implementation file for the ARKSPTFQMR linear solver.
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <arkode/arkode_sptfqmr.h>
-#include "arkode_spils_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_sptfqmr.h>
-#include <sundials/sundials_math.h>
-
-/* Other Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* ARKSPTFQMR linit, lsetup, lsolve, and lfree routines */
-static int ARKSptfqmrInit(ARKodeMem ark_mem);
-static int ARKSptfqmrSetup(ARKodeMem ark_mem, int convfail, N_Vector ypred,
-			   N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-			   N_Vector vtemp2, N_Vector vtemp3);
-static int ARKSptfqmrSolve(ARKodeMem ark_mem, N_Vector b, N_Vector weight,
-			   N_Vector ynow, N_Vector fnow);
-static int ARKSptfqmrFree(ARKodeMem ark_mem);
-
-/* ARKSPTFQMR minit, msetup, msolve, and mfree routines */
-static int ARKMassSptfqmrInit(ARKodeMem ark_mem);
-static int ARKMassSptfqmrSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			       N_Vector vtemp2, N_Vector vtemp3);
-static int ARKMassSptfqmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			       N_Vector weight);
-static int ARKMassSptfqmrFree(ARKodeMem ark_mem);
-
-
-/*---------------------------------------------------------------
- ARKSptfqmr:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Sptfqmr linear solver module. 
- ARKSptfqmr first calls the existing lfree routine if this is not 
- NULL. It then sets the ark_linit, ark_lsetup, ark_lsolve, 
- ark_lfree fields in (*arkode_mem) to be ARKSptfqmrInit, 
- ARKSptfqmrSetup, ARKSptfqmrSolve, and ARKSptfqmrFree,
- respectively. It allocates memory for a structure of type
- ARKSpilsMemRec and sets the ark_lmem field in (*arkode_mem) to 
- the address of this structure. It sets setupNonNull in 
- (*arkode_mem), and sets various fields in the ARKSpilsMemRec 
- structure. Finally, ARKSptfqmr allocates memory for ytemp and 
- x, and calls SptfqmrMalloc to allocate memory for the Sptfqmr 
- solver.
----------------------------------------------------------------*/
-int ARKSptfqmr(void *arkode_mem, int pretype, int maxl)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPTFQMR", 
-		    "ARKSptfqmr", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd and N_VProd are present */
-  if ((ark_mem->ark_tempv->ops->nvdotprod == NULL) ||
-      (ark_mem->ark_tempv->ops->nvprod == NULL)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPTFQMR", 
-		    "ARKSptfqmr", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem */
-  ark_mem->ark_linit  = ARKSptfqmrInit;
-  ark_mem->ark_lsetup = ARKSptfqmrSetup;
-  ark_mem->ark_lsolve = ARKSptfqmrSolve;
-  ark_mem->ark_lfree  = ARKSptfqmrFree;
-  ark_mem->ark_lsolve_type = 0;
-
-  /* Get memory for ARKSpilsMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMem) malloc(sizeof(struct ARKSpilsMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-                    "ARKSptfqmr", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPTFQMR;
-
-  /* Set Sptfqmr parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fields */
-  arkspils_mem->s_jtimesDQ = TRUE;
-  arkspils_mem->s_jtimes   = NULL;
-  arkspils_mem->s_j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Set default values for the rest of the Sptfqmr parameters */
-  arkspils_mem->s_eplifac = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  ark_mem->ark_setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPTFQMR", 
-                    "ARKSptfqmr", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-		    "ARKSptfqmr", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-		    "ARKSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt(N_VDotProd(arkspils_mem->s_ytemp, 
-					   arkspils_mem->s_ytemp));
-
-  /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */
-  sptfqmr_mem = NULL;
-  sptfqmr_mem = SptfqmrMalloc(mxl, ark_mem->ark_tempv);
-  if (sptfqmr_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-		    "ARKSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPTFQMR memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) sptfqmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_lmem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKSptfqmrInit:
-
- This routine does remaining initializations specific to the 
- Sptfqmr linear solver.
----------------------------------------------------------------*/
-static int ARKSptfqmrInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  sptfqmr_mem = (SptfqmrMem) arkspils_mem->s_spils_mem;
-
-  /* Initialize counters */
-  arkSpilsInitializeCounters(arkspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) && 
-      (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPTFQMR", "ARKSptfqmrInit", 
-                    MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  ark_mem->ark_setupNonNull = (arkspils_mem->s_pretype != PREC_NONE) && 
-    (arkspils_mem->s_pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (arkspils_mem->s_jtimesDQ) {
-    arkspils_mem->s_jtimes = ARKSpilsDQJtimes;
-    arkspils_mem->s_j_data = ark_mem;
-  } else {
-    arkspils_mem->s_j_data = ark_mem->ark_user_data;
-  }
-
-  /* Set maxl in the SPTFQMR memory in case it was changed by the user */
-  sptfqmr_mem->l_max = arkspils_mem->s_maxl;
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-/*---------------------------------------------------------------
- ARKSptfqmrSetup:
-
- This routine does the setup operations for the Sptfqmr linear 
- solver. It makes a decision as to whether or not to signal for 
- reevaluation of Jacobian data in the pset routine, based on 
- various state variables, then it calls pset. If we signal for 
- reevaluation, then we reset jcur = *jcurPtr to TRUE, regardless 
- of the pset output. In any case, if jcur == TRUE, we increment 
- npe and save nst in nstlpre.
----------------------------------------------------------------*/
-static int ARKSptfqmrSetup(ARKodeMem ark_mem, int convfail, 
-			   N_Vector ypred, N_Vector fpred, 
-			   booleantype *jcurPtr, N_Vector vtemp1,
-			   N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  ARKSpilsMem arkspils_mem;
-
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arkspils_mem->s_nstlpre + ARKSPILS_MSBPRE) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKSPILS_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, ypred, fpred, jok, 
-				jcurPtr, ark_mem->ark_gamma, 
-				arkspils_mem->s_P_data, 
-				vtemp1, vtemp2, vtemp3);
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPTFQMR_PSET_FAIL_UNREC, "ARKSPTFQMR", 
-		    "ARKSptfqmrSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPTFQMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = SPTFQMR_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    arkspils_mem->s_npe++;
-    arkspils_mem->s_nstlpre = ark_mem->ark_nst;
-  }
-
-  arkspils_mem->s_last_flag = SPTFQMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKSptfqmrSolve:
-
- This routine handles the call to the generic solver SptfqmrSolve
- for the solution of the linear system Ax = b with the SPTFQMR 
- method. The solution x is returned in the vector b.
-
- If the WRMS norm of b is small, we return x = b (if this is the 
- first Newton iteration) or x = 0 (if a later Newton iteration).
-
- Otherwise, we set the tolerance parameter and initial guess 
- (x = 0), call SptfqmrSolve, and copy the solution x into b. The 
- x-scaling and b-scaling arrays are both equal to weight.
-
- The counters nli, nps, and ncfl are incremented, and the return 
- value is set according to the success of SptfqmrSolve. The 
- success flag is returned if SptfqmrSolve converged, or if this 
- is the first Newton iteration and the residual norm was reduced 
- below its initial value.
----------------------------------------------------------------*/
-static int ARKSptfqmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			   N_Vector weight, N_Vector ynow, 
-			   N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  ARKSpilsMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-  sptfqmr_mem = (SptfqmrMem) arkspils_mem->s_spils_mem;
-
-  /* Test norm(b); if small, return x = 0 */
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_eRNrm; 
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= arkspils_mem->s_deltar) {
-    if (ark_mem->ark_mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  arkspils_mem->s_ycur = ynow;
-  arkspils_mem->s_fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SptfqmrSolve */  
-  arkspils_mem->s_delta = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SptfqmrSolve and copy x to b */
-  retval = SptfqmrSolve(sptfqmr_mem, ark_mem, arkspils_mem->s_x, b, 
-			arkspils_mem->s_pretype, arkspils_mem->s_delta,
-                        ark_mem, weight, weight, ARKSpilsAtimes, 
-			ARKSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPTFQMR_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      kry  %19.16g  %19.16g  %i  %i\n", 
-	    bnorm, res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SptfqmrSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPTFQMR_SUCCESS:
-    return(0);
-    break;
-  case SPTFQMR_RES_REDUCED:
-    /* allow reduction but not solution on first Newton iteration, 
-       otherwise return with a recoverable failure */
-    if (ark_mem->ark_mnewt == 0) return(0);
-    else                         return(1);
-    break;
-  case SPTFQMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPTFQMR_ATIMES_FAIL_UNREC, "ARKSPTFQMR", 
-		    "ARKSptfqmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "ARKSPTFQMR", 
-		    "ARKSptfqmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKSptfqmrFree:
-
- This routine frees memory specific to the Sptfqmr linear solver.
----------------------------------------------------------------*/
-static int ARKSptfqmrFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-    
-  arkspils_mem = (ARKSpilsMem) ark_mem->ark_lmem;
-
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  sptfqmr_mem = (SptfqmrMem) arkspils_mem->s_spils_mem;
-  SptfqmrFree(sptfqmr_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-/*---------------------------------------------------------------
- ARKMassSptfqmr:
-
- This routine initializes the memory record and sets various 
- function fields specific to the Sptfqmr mass matrix solver 
- module. ARKMassSptfqmr first calls the existing mfree routine 
- if this is not NULL. It then sets the ark_minit, ark_msetup, 
- ark_msolve, ark_mfree fields in (*arkode_mem) to be 
- ARKMassSptfqmrInit, ARKMassSptfqmrSetup, ARKMassSptfqmrSolve, 
- and ARKMassSptfqmrFree, respectively. It allocates memory for a
- structure of type ARKMassSpilsMemRec and sets the ark_mass_mem
- field in (*arkode_mem) to the address of this structure. It sets 
- MassSetupNonNull in (*arkode_mem), and sets various fields in 
- the ARKSpilsMassMemRec structure, allocates memory for ytemp 
- and x, and calls SptfqmrMalloc to allocate memory for the 
- Sptfqmr solver.
----------------------------------------------------------------*/
-int ARKMassSptfqmr(void *arkode_mem, int pretype, int maxl, 
-		   ARKSpilsMassTimesVecFn mtimes, void *mtimes_data)
-{
-  ARKodeMem ark_mem;
-  ARKSpilsMassMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int mxl;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSPILS_MEM_NULL, "ARKSPTFQMR", 
-		    "ARKMassSptfqmr", MSGS_ARKMEM_NULL);
-    return(ARKSPILS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Check if N_VDotProd is present */
-  if (ark_mem->ark_tempv->ops->nvdotprod == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPTFQMR", 
-		    "ARKMassSptfqmr", MSGS_BAD_NVECTOR);
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set four main function fields in ark_mem, enable mass matrix */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = ARKMassSptfqmrInit;
-  ark_mem->ark_msetup = ARKMassSptfqmrSetup;
-  ark_mem->ark_msolve = ARKMassSptfqmrSolve;
-  ark_mem->ark_mfree  = ARKMassSptfqmrFree;
-  ark_mem->ark_msolve_type = 0;
-
-  /* Get memory for ARKSpilsMassMemRec */
-  arkspils_mem = NULL;
-  arkspils_mem = (ARKSpilsMassMem) malloc(sizeof(struct ARKSpilsMassMemRec));
-  if (arkspils_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-		    "ARKMassSptfqmr", MSGS_MEM_FAIL);
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Set mass-matrix-vector product routine */
-  ark_mem->ark_mtimes      = mtimes;
-  ark_mem->ark_mtimes_data = mtimes_data;
-
-  /* Set ILS type */
-  arkspils_mem->s_type = SPILS_SPTFQMR;
-
-  /* Set Sptfqmr parameters that have been passed in call sequence */
-  arkspils_mem->s_pretype = pretype;
-  mxl = arkspils_mem->s_maxl = (maxl <= 0) ? ARKSPILS_MAXL : maxl;
-
-  /* Set defaults for preconditioner-related fields */
-  arkspils_mem->s_pset   = NULL;
-  arkspils_mem->s_psolve = NULL;
-  arkspils_mem->s_pfree  = NULL;
-  arkspils_mem->s_P_data = ark_mem->ark_user_data;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Set default values for the rest of the Sptfqmr parameters */
-  arkspils_mem->s_eplifac   = ARKSPILS_EPLIN;
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-
-  /* Disable call to msetup in ARKode solver (for now) */
-  ark_mem->ark_MassSetupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    arkProcessError(ark_mem, ARKSPILS_ILL_INPUT, "ARKSPTFQMR", 
-		    "ARKMassSptfqmr", MSGS_BAD_PRETYPE);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  arkspils_mem->s_ytemp = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_ytemp == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-		    "ARKMassSptfqmr", MSGS_MEM_FAIL);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  arkspils_mem->s_x = N_VClone(ark_mem->ark_tempv);
-  if (arkspils_mem->s_x == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-		    "ARKMassSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, arkspils_mem->s_ytemp);
-  arkspils_mem->s_sqrtN = SUNRsqrt(N_VDotProd(arkspils_mem->s_ytemp, 
-					   arkspils_mem->s_ytemp));
-
-  /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */
-  sptfqmr_mem = NULL;
-  sptfqmr_mem = SptfqmrMalloc(mxl, ark_mem->ark_tempv);
-  if (sptfqmr_mem == NULL) {
-    arkProcessError(ark_mem, ARKSPILS_MEM_FAIL, "ARKSPTFQMR", 
-		    "ARKMassSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(arkspils_mem->s_ytemp);
-    N_VDestroy(arkspils_mem->s_x);
-    free(arkspils_mem); arkspils_mem = NULL;
-    return(ARKSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPTFQMR memory to spils memory structure */
-  arkspils_mem->s_spils_mem = (void *) sptfqmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  ark_mem->ark_mass_mem = arkspils_mem;
-
-  return(ARKSPILS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSptfqmrInit:
-
- This routine does remaining initializations specific to the 
- Sptfqmr linear solver.
----------------------------------------------------------------*/
-static int ARKMassSptfqmrInit(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  sptfqmr_mem = (SptfqmrMem) arkspils_mem->s_spils_mem;
-
-  /* Initialize counters */
-  arkspils_mem->s_npe = arkspils_mem->s_nli  = 0;
-  arkspils_mem->s_nps = arkspils_mem->s_ncfl = 0;
-
-  /* Check for legal combination pretype - psolve */
-  if ((arkspils_mem->s_pretype != PREC_NONE) && 
-      (arkspils_mem->s_psolve == NULL)) {
-    arkProcessError(ark_mem, -1, "ARKSPTFQMR", "ARKMassSptfqmrInit", 
-		    MSGS_PSOLVE_REQ);
-    arkspils_mem->s_last_flag = ARKSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set MassSetupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  ark_mem->ark_MassSetupNonNull = (arkspils_mem->s_pretype != PREC_NONE) && 
-    (arkspils_mem->s_pset != NULL);
-
-  /* Set maxl in the SPTFQMR memory in case it was changed by the user */
-  sptfqmr_mem->l_max = arkspils_mem->s_maxl;
-
-  arkspils_mem->s_last_flag = ARKSPILS_SUCCESS;
-  return(0);
-}
-
-/*---------------------------------------------------------------
- ARKMassSptfqmrSetup:
-
- This routine does the setup operations for the Sptfqmr mass 
- matrix solver. It calls the setup routine and increments npe.
----------------------------------------------------------------*/
-static int ARKMassSptfqmrSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-			       N_Vector vtemp2, N_Vector vtemp3)
-{
-  int  retval;
-  ARKSpilsMassMem arkspils_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  /* Call pset routine */
-  retval = arkspils_mem->s_pset(ark_mem->ark_tn, 
-				arkspils_mem->s_P_data, 
-				vtemp1, vtemp2, vtemp3);
-  arkspils_mem->s_npe++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, SPTFQMR_PSET_FAIL_UNREC, "ARKSPTFQMR", 
-		    "ARKMassSptfqmrSetup", MSGS_PSET_FAILED);
-    arkspils_mem->s_last_flag = SPTFQMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    arkspils_mem->s_last_flag = SPTFQMR_PSET_FAIL_REC;
-  }
-  if (retval == 0) {
-    arkspils_mem->s_last_flag = SPTFQMR_SUCCESS;
-  }
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSptfqmrSolve:
-
- This routine handles the call to the generic solver SptfqmrSolve
- for the solution of the mass matrix system Mx = b with the 
- SPTFQMR method. The solution x is returned in the vector b.
-
- We set the tolerance parameter and initial guess (x = 0), call 
- SptfqmrSolve, and copy the solution x into b. The x-scaling and 
- b-scaling arrays are both equal to weight.
-
- The counters nli, nps, and ncfl are incremented, and the return 
- value is set according to the success of SptfqmrSolve. The 
- success flag is returned if SptfqmrSolve converged.
----------------------------------------------------------------*/
-static int ARKMassSptfqmrSolve(ARKodeMem ark_mem, N_Vector b, 
-			       N_Vector weight)
-{
-  realtype res_norm;
-  ARKSpilsMassMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int nli_inc, nps_inc, retval;
-
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-  sptfqmr_mem = (SptfqmrMem) arkspils_mem->s_spils_mem;
-
-  /* Set inputs delta and initial guess x = 0 to SptfqmrSolve */  
-  arkspils_mem->s_deltar = arkspils_mem->s_eplifac * ark_mem->ark_nlscoef; 
-  arkspils_mem->s_delta  = arkspils_mem->s_deltar * arkspils_mem->s_sqrtN;
-  N_VConst(ZERO, arkspils_mem->s_x);
-  
-  /* Call SptfqmrSolve and copy x to b */
-  retval = SptfqmrSolve(sptfqmr_mem, ark_mem, arkspils_mem->s_x, b, 
-			arkspils_mem->s_pretype, arkspils_mem->s_delta,
-                        ark_mem, weight, weight, ARKSpilsMtimes, 
-			ARKSpilsMPSolve, &res_norm, &nli_inc, &nps_inc);
-  N_VScale(ONE, arkspils_mem->s_x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  arkspils_mem->s_nli += nli_inc;
-  arkspils_mem->s_nps += nps_inc;
-  if (retval != SPTFQMR_SUCCESS) arkspils_mem->s_ncfl++;
-
-  /* Log solver statistics to diagnostics file (if requested) */
-  if (ark_mem->ark_report) 
-    fprintf(ark_mem->ark_diagfp, "      mass  %19.16g  %i  %i\n", 
-	    res_norm, nli_inc, nps_inc);
-  
-  /* Interpret return value from SptfqmrSolve */
-  arkspils_mem->s_last_flag = retval;
-
-  switch(retval) {
-
-  case SPTFQMR_SUCCESS:
-    return(0);
-    break;
-  case SPTFQMR_RES_REDUCED:
-    return(1);
-    break;
-  case SPTFQMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_UNREC:
-    arkProcessError(ark_mem, SPTFQMR_ATIMES_FAIL_UNREC, "ARKSPTFQMR", 
-		    "ARKMassSptfqmrSolve", MSGS_MTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_UNREC:
-    arkProcessError(ark_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "ARKSPTFQMR", 
-		    "ARKMassSptfqmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSptfqmrFree:
-
- This routine frees memory specific to the Sptfqmr linear solver.
----------------------------------------------------------------*/
-static int ARKMassSptfqmrFree(ARKodeMem ark_mem)
-{
-  ARKSpilsMassMem arkspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  arkspils_mem = (ARKSpilsMassMem) ark_mem->ark_mass_mem;
-
-  N_VDestroy(arkspils_mem->s_ytemp);
-  N_VDestroy(arkspils_mem->s_x);
-
-  sptfqmr_mem = (SptfqmrMem) arkspils_mem->s_spils_mem;
-  SptfqmrFree(sptfqmr_mem);
-
-  if (arkspils_mem->s_pfree != NULL) (arkspils_mem->s_pfree)(ark_mem);
-
-  free(arkspils_mem);
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-
-/*---------------------------------------------------------------
-     EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/arkode_superlumt.c b/src/arkode/arkode_superlumt.c
deleted file mode 100644
index d0e3cf6..0000000
--- a/src/arkode/arkode_superlumt.c
+++ /dev/null
@@ -1,1097 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Implementation file for the ARKSUPERLUMT linear solver module.
- *---------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "arkode/arkode_superlumt.h"
-#include "arkode/arkode_sparse.h"
-#include "arkode_sparse_impl.h"
-#include "arkode_impl.h"
-
-#include <sundials/sundials_superlumt_impl.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-#define ONE RCONST(1.0)
-#define TWO RCONST(2.0)
-
-/* ARKSUPERLUMT linit, lsetup, lsolve, and lfree routines */
-static int arkSuperLUMTInit(ARKodeMem ark_mem);
-static int arkSuperLUMTSetup(ARKodeMem ark_mem, int convfail, 
-			     N_Vector ypred, N_Vector fpred, 
-			     booleantype *jcurPtr, N_Vector tmp1, 
-			     N_Vector tmp2, N_Vector tmp3);
-static int arkSuperLUMTSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight, N_Vector ycur, 
-			     N_Vector fcur);
-static int arkSuperLUMTFree(ARKodeMem ark_mem);
-
-/* ARKSUPERLUMT minit, msetup, msolve, mfree and mtimes routines */
-static int arkMassSuperLUMTInit(ARKodeMem ark_mem);
-static int arkMassSuperLUMTSetup(ARKodeMem ark_mem, N_Vector tmp1,
-			     N_Vector tmp2, N_Vector tmp3);
-static int arkMassSuperLUMTSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight);
-static int arkMassSuperLUMTFree(ARKodeMem ark_mem);
-static int arkMassSuperLUMTMultiply(N_Vector v, N_Vector Mv, 
-				    realtype t, void *arkode_mem);
-
-
-/*---------------------------------------------------------------
- ARKSuperLUMT
-
- This routine initializes the memory record and sets various 
- function fields specific to the ARKODE / SuperLUMT linear solver
- module.  ARKSuperLUMT first calls the existing lfree routine if
- this is not NULL.  Then it sets the ark_linit, ark_lsetup, 
- ark_lsolve and ark_lfree fields in (*ark_mem) to be 
- arkSuperLUMTInit, arkSuperLUMTSetup, arkSuperLUMTSolve, and 
- arkSuperLUMTFree, respectively.  It allocates memory for a 
- structure of type ARKSlsMemRec and sets the ark_lmem field in 
- (*arkode_mem) to the address of this structure.  It sets 
- setupNonNull in (*arkode_mem) to TRUE.  Finally, it allocates 
- memory for SuperLUMT.  The return value is ARKSLS_SUCCESS = 0, 
- ARKSLS_LMEM_FAIL = -1, or ARKSLS_ILL_INPUT = -2.
-
- NOTE: The SuperLUMT linear solver assumes a serial 
-       implementation of the NVECTOR package. Therefore, 
-       ARKSuperLUMT will first test for a compatible N_Vector 
-       internal representation by checking that the function 
-       N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-int ARKSuperLUMT(void *arkode_mem, int num_threads, int n, int nnz)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-  SLUMTData slumt_data;
-  int *perm_c, *perm_r;
-  int nrhs, panel_size, relax;
-  double *bd;
-  SuperMatrix *B;
-
-  /* Return immediately if ark_mem is NULL. */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKSLS_ILL_INPUT, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_BAD_NVECTOR);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_lfree != NULL) ark_mem->ark_lfree(ark_mem);
-
-  /* Set four main function fields in ark_mem. */
-  ark_mem->ark_linit  = arkSuperLUMTInit;
-  ark_mem->ark_lsetup = arkSuperLUMTSetup;
-  ark_mem->ark_lsolve = arkSuperLUMTSolve;
-  ark_mem->ark_lfree  = arkSuperLUMTFree;
-  ark_mem->ark_lsolve_type = 3;
-
-  /* Get memory for ARKSlsMemRec. */
-  arksls_mem = (ARKSlsMem) malloc(sizeof(struct ARKSlsMemRec));
-  if (arksls_mem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_MEM_FAIL);
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Get memory for SLUMTData. */
-  slumt_data = (SLUMTData) malloc(sizeof(struct SLUMTDataRec));
-  if (slumt_data == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_MEM_FAIL);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Initialize Jacobian-related data */
-  arksls_mem->s_Jeval = NULL;
-  arksls_mem->s_Jdata = ark_mem->ark_user_data;
-  ark_mem->ark_setupNonNull = TRUE;
-  arksls_mem->sparsetype = CSC_MAT;
-
-  /* Initialize counters */
-  arksls_mem->s_nje = 0;
-  arksls_mem->s_first_factorize = 1;
-  arksls_mem->s_nstlj = 0;
-
-  /* Allocate memory for the sparse Jacobian */
-  arksls_mem->s_A = NULL;
-  arksls_mem->s_A = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (arksls_mem->s_A == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_MEM_FAIL);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Allocate memory for saved sparse Jacobian */
-  arksls_mem->s_savedJ = NULL;
-  arksls_mem->s_savedJ = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (arksls_mem->s_savedJ == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_A);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Set up memory for the permutations */
-  perm_r = NULL;
-  perm_r = (int *) malloc(n*sizeof(int));
-  if (perm_r == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_A);
-    SparseDestroyMat(arksls_mem->s_savedJ);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-  perm_c = NULL;
-  perm_c = (int *) malloc(n*sizeof(int));
-  if (perm_c == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKSuperLUMT", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_A);
-    SparseDestroyMat(arksls_mem->s_savedJ);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    free(perm_r); perm_r = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-  slumt_data->perm_r = perm_r;
-  slumt_data->perm_c = perm_c;
-
-  /* Set default parameters for SuperLU */
-  slumt_data->num_threads = num_threads;
-  slumt_data->diag_pivot_thresh = 1.0;
-
-  /* Allocate structures for SuperLU */
-  slumt_data->Gstat = (Gstat_t *) malloc(sizeof(Gstat_t));
-  slumt_data->s_A   = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_AC  = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_L   = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_U   = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_A->Store  = NULL;
-  slumt_data->s_AC->Store = NULL;
-  slumt_data->s_L->Store  = NULL;
-  slumt_data->s_U->Store  = NULL;
-  slumt_data->superlumt_options = 
-    (superlumt_options_t *) malloc(sizeof(superlumt_options_t));
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  StatAlloc(arksls_mem->s_A->N, num_threads, panel_size, 
-	    relax, slumt_data->Gstat);
-  
-  /* Create RHS matrix */
-  nrhs = 1;
-  bd = NULL;
-  B = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  B->Store = NULL;
-  dCreate_Dense_Matrix(B, n, nrhs, bd, n, 
-		       SLU_DN, SLU_D, SLU_GE);
-  slumt_data->s_B = B;
-
-  /* Set ordering to COLAMD as the arkode default use.
-     Users can set a different value with ARKSuperLUMTSetOrdering,
-     and the user-set value is loaded before any call to 
-     factorize the matrix in arkSuperLUMTSetup.  */
-  slumt_data->s_ordering = 3;
-
-  /* Attach linear solver memory to the integrator memory */
-  arksls_mem->s_solver_data = (void *) slumt_data;
-  ark_mem->ark_lmem = arksls_mem;
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkSuperLUMTInit:
-
- This routine does remaining initializations specific to the 
- ARKSuperLUMT linear solver module.  It returns 0 if successful.
----------------------------------------------------------------*/
-static int arkSuperLUMTInit(ARKodeMem ark_mem)
-{
-  ARKSlsMem arksls_mem;
-  SLUMTData slumt_data;
-
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  arksls_mem->s_nje = 0;
-  arksls_mem->s_first_factorize = 1;
-  arksls_mem->s_nstlj = 0;
-
-  /* Allocate storage and initialize statistics variables. */
-  StatInit(arksls_mem->s_A->N, slumt_data->num_threads, 
-	   slumt_data->Gstat);
-
-  arksls_mem->s_Jdata = ark_mem->ark_user_data;
-  arksls_mem->s_last_flag = 0;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkSuperLUMTSetup:
-
-  This routine does the setup operations for the ARKSuperLUMT 
-  linear solver module.  It calls the Jacobian evaluation 
-  routine, updates counters, and calls the LU factorization 
-  routine.  The return value is either
-     ARKSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
----------------------------------------------------------------*/
-static int arkSuperLUMTSetup(ARKodeMem ark_mem, int convfail, 
-			     N_Vector ypred, N_Vector fpred, 
-			     booleantype *jcurPtr, N_Vector vtemp1, 
-			     N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  int retval;
-  int panel_size, relax, lwork;
-  realtype dgamma;
-  double drop_tol;
-  fact_t fact;
-  trans_t trans;
-  yes_no_t refact, usepr;
-  ARKSlsMem arksls_mem;
-  ARKSlsMassMem arksls_mass_mem;
-  SLUMTData slumt_data;
-  void *work;
-  
-  arksls_mem = (ARKSlsMem) (ark_mem->ark_lmem);
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  /* Set option values for SuperLU_MT */
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  fact = EQUILIBRATE;
-  trans = NOTRANS;
-  usepr = NO;
-  drop_tol = 0.0;
-  lwork = 0;
-  work = NULL;
-
-  /* Check that Jacobian eval routine is set */
-  if (arksls_mem->s_Jeval == NULL) {
-    arkProcessError(ark_mem, ARKSLS_JAC_NOSET, "ARKSLS", 
-		    "arkSuperLUMTSetup", MSGSP_JAC_NOSET);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_JAC_NOSET);
-  }
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((ark_mem->ark_gamma/ark_mem->ark_gammap) - ONE);
-  jbad = (ark_mem->ark_nst == 0) || 
-    (ark_mem->ark_nst > arksls_mem->s_nstlj + ARKS_MSBJ) ||
-    ((convfail == ARK_FAIL_BAD_J) && (dgamma < ARKS_DGMAX)) ||
-    (convfail == ARK_FAIL_OTHER);
-  jok = !jbad;
-  
-  /* If jok = TRUE, use saved copy of J */
-  if (jok) {
-    *jcurPtr = FALSE;
-    SparseCopyMat(arksls_mem->s_savedJ, arksls_mem->s_A);
-
-  /* If jok = FALSE, call jac routine for new J value */
-  } else {
-    arksls_mem->s_nje++;
-    arksls_mem->s_nstlj = ark_mem->ark_nst;
-    *jcurPtr = TRUE;
-    SparseSetMatToZero(arksls_mem->s_A);
-
-    retval = arksls_mem->s_Jeval(ark_mem->ark_tn, ypred, fpred, 
-				 arksls_mem->s_A, arksls_mem->s_Jdata, 
-				 vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKSLS_JACFUNC_UNRECVR, "ARKSLS", 
-		      "arkSuperLUMTSetup", MSGSP_JACFUNC_FAILED);
-      arksls_mem->s_last_flag = ARKSLS_JACFUNC_UNRECVR;
-      return(ARKSLS_JACFUNC_UNRECVR);
-    }
-    if (retval > 0) {
-      arksls_mem->s_last_flag = ARKSLS_JACFUNC_RECVR;
-      return(ARKSLS_JACFUNC_RECVR);
-    }
-
-    SparseCopyMat(arksls_mem->s_A, arksls_mem->s_savedJ);
-  }
-
-  /* Scale J by -gamma */
-  SparseScaleMat(-ark_mem->ark_gamma, arksls_mem->s_A);
-
-  /* Add mass matrix to get A = M-gamma*J */
-  if (ark_mem->ark_mass_matrix) {
-
-    /* Compute mass matrix */
-    arksls_mass_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-    SparseSetMatToZero(arksls_mass_mem->s_M);
-    retval = arksls_mass_mem->s_Meval(ark_mem->ark_tn, 
-				      arksls_mass_mem->s_M, 
-				      arksls_mass_mem->s_Mdata, 
-				      vtemp1, vtemp2, vtemp3);
-    arksls_mass_mem->s_nme++;
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKSLS_MASSFUNC_UNRECVR, "ARKSLS", 
-		      "arkSuperLUMTSetup",  MSGSP_MASSFUNC_FAILED);
-      arksls_mem->s_last_flag = ARKSLS_MASSFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      arksls_mem->s_last_flag = ARKSLS_MASSFUNC_RECVR;
-      return(1);
-    }
-    
-    /* add to A */
-    retval = SparseAddMat(arksls_mem->s_A, arksls_mass_mem->s_M);
-    if (retval < 0) {
-      arkProcessError(ark_mem, ARKSLS_PACKAGE_FAIL, "ARKSLS", 
-		      "arkSuperLUMTSetup",  
-		      "Error in adding mass matrix to Jacobian");
-      arksls_mem->s_last_flag = ARKSLS_PACKAGE_FAIL;
-      return(retval);
-    }
-    if (retval > 0)  return(retval);
-    
-  } else {
-    SparseAddIdentityMat(arksls_mem->s_A);
-  }
-
-  /* free and reallocate sparse matrix */
-  if (slumt_data->s_A->Store) {
-    SUPERLU_FREE(slumt_data->s_A->Store);
-  }
-  dCreate_CompCol_Matrix(slumt_data->s_A, arksls_mem->s_A->M, 
-			 arksls_mem->s_A->N, arksls_mem->s_A->NNZ, 
-			 arksls_mem->s_A->data, 
-			 arksls_mem->s_A->indexvals, 
-			 arksls_mem->s_A->indexptrs, 
-			 SLU_NC, SLU_D, SLU_GE);
-
-  /* On first decomposition, set up reusable pieces */ 
-  if (arksls_mem->s_first_factorize) {
-
-    /* Get column permutation vector perm_c[], according to s_ordering */
-    get_perm_c(slumt_data->s_ordering, slumt_data->s_A, 
-	       slumt_data->perm_c);
-    refact= NO;
-    arksls_mem->s_first_factorize = 0;
-
-  } else {
-    /* Re-initialize statistics variables */
-    StatInit(arksls_mem->s_A->N, slumt_data->num_threads, 
-	     slumt_data->Gstat);
-    Destroy_CompCol_Permuted(slumt_data->s_AC);
-    refact= YES;
-  }
-
-  /* Initialize the option structure superlumt_options using the
-     user-input parameters. Subsequent calls will re-initialize
-     options.  Apply perm_c to columns of original A to form AC */
-  pdgstrf_init(slumt_data->num_threads, fact, trans, refact, 
-	       panel_size, relax, slumt_data->diag_pivot_thresh, 
-	       usepr, drop_tol, slumt_data->perm_c, 
-	       slumt_data->perm_r, work, lwork, slumt_data->s_A, 
-	       slumt_data->s_AC, slumt_data->superlumt_options, 
-	       slumt_data->Gstat);
-
-  /* Compute the LU factorization of A.
-     The following routine will create num_threads threads. */
-  pdgstrf(slumt_data->superlumt_options, slumt_data->s_AC, 
-	  slumt_data->perm_r, slumt_data->s_L, slumt_data->s_U, 
-	  slumt_data->Gstat, &retval);
-  if (retval != 0) {
-    arksls_mem->s_last_flag = retval;
-    return(ARKSLS_PACKAGE_FAIL);
-  }
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkSuperLUMTSolve:
-
- This routine handles the solve operation for the ARKSuperLUMT 
- linear solver module.  It calls the SuperLU_MT solve routine,
- then returns ARKSLS_SUCCESS = 0.
----------------------------------------------------------------*/
-static int arkSuperLUMTSolve(ARKodeMem ark_mem, N_Vector b, 
-			     N_Vector weight, N_Vector ycur, 
-			     N_Vector fcur)
-{
-  int info;
-  ARKSlsMem arksls_mem;
-  DNformat *Bstore;
-  SLUMTData slumt_data;
-  realtype *bd;
-  trans_t trans;
-  
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  bd = N_VGetArrayPointer(b);
-  Bstore = (DNformat *) (slumt_data->s_B->Store);
-  Bstore->nzval = bd;
-
-  /* Call SuperLUMT to solve the linear system using L and U */
-  trans = NOTRANS;
-  dgstrs(trans, slumt_data->s_L, slumt_data->s_U, 
-	 slumt_data->perm_r, slumt_data->perm_c, 
-	 slumt_data->s_B, slumt_data->Gstat, &info);
-
-  /* Scale the correction to account for change in gamma. */
-  if (ark_mem->ark_gamrat != ONE) 
-    N_VScale(TWO/(ONE + ark_mem->ark_gamrat), b, b);
-  Bstore->nzval = NULL;
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkSuperLUMTFree:
-
- This routine frees memory specific to the ARKSuperLUMT linear 
- solver.
----------------------------------------------------------------*/
-static int arkSuperLUMTFree(ARKodeMem ark_mem)
-{
-  ARKSlsMem arksls_mem;
-  SLUMTData slumt_data;
-  
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  pxgstrf_finalize(slumt_data->superlumt_options, 
-		   slumt_data->s_AC);
-  free(slumt_data->perm_r);
-  free(slumt_data->perm_c);
-  free(slumt_data->superlumt_options);
-  Destroy_SuperNode_SCP( (slumt_data->s_L) );
-  Destroy_CompCol_NCP( (slumt_data->s_U) );
-  StatFree(slumt_data->Gstat);
-  free(slumt_data->Gstat);
-  
-  Destroy_SuperMatrix_Store(slumt_data->s_B);
-  SUPERLU_FREE(slumt_data->s_A->Store);
-  if (arksls_mem->s_A) {
-    SparseDestroyMat(arksls_mem->s_A);
-    arksls_mem->s_A = NULL;
-  }
-
-  if (arksls_mem->s_savedJ) {
-    SparseDestroyMat(arksls_mem->s_savedJ);
-    arksls_mem->s_savedJ = NULL;
-  }
-
-  free(slumt_data->s_B);
-  free(slumt_data->s_A);
-  free(slumt_data->s_AC);
-  free(slumt_data->s_L);
-  free(slumt_data->s_U);
-
-  free(slumt_data); 
-  slumt_data = NULL;
-  free(arksls_mem); 
-  ark_mem->ark_lmem = NULL;
-
-  return(0);
-}
-
-
-
-/*---------------------------------------------------------------
- ARKMassSuperLUMT
-
- This routine initializes the memory record and sets various 
- function fields specific to the ARKODE / SuperLUMT mass matrix 
- linear solver module.  ARKMassSuperLUMT first calls the 
- existing mfree routine if this is not NULL.  Then it sets the 
- ark_minit, ark_msetup, ark_msolve and ark_mfree fields in 
- (*arkode_mem) to be arkMassSuperLUMTInit, arkMassSuperLUMTSetup, 
- arkMassSuperLUMTSolve, and arkMassSuperLUMTFree, respectively.  
- It allocates memory for a structure of type ARKSlsMassMemRec and
- sets the ark_mass_mem field in (*arkode_mem) to the address of 
- this structure.  It sets MassSetupNonNull in (*arkode_mem) to 
- TRUE.  Finally, it allocates memory for SuperLUMT.  The return
- value is ARKSLS_SUCCESS = 0, ARKSLS_LMEM_FAIL = -1, or 
- ARKSLS_ILL_INPUT = -2.
-
- NOTE: The SuperLUMT linear solver assumes a serial 
-       implementation of the NVECTOR package. Therefore, 
-       ARKMassSuperLUMT will first test for a compatible 
-       N_Vector internal representation by checking that the 
-       function N_VGetArrayPointer exists.
----------------------------------------------------------------*/
-int ARKMassSuperLUMT(void *arkode_mem, int num_threads, 
-		     int n, int nnz, ARKSlsSparseMassFn smass)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-  SLUMTData slumt_data;
-  int *perm_c, *perm_r;
-  int nrhs, panel_size, relax;
-  double *bd;
-  SuperMatrix *B;
-
-  /* Return immediately if arkode_mem is NULL. */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Test if the NVECTOR package is compatible with the solver */
-  if (ark_mem->ark_tempv->ops->nvgetarraypointer == NULL) {
-    arkProcessError(ark_mem, ARKSLS_ILL_INPUT, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_BAD_NVECTOR);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  if (ark_mem->ark_mfree != NULL) ark_mem->ark_mfree(ark_mem);
-
-  /* Set main function fields in ark_mem, enable mass matrix. */
-  ark_mem->ark_mass_matrix = TRUE;
-  ark_mem->ark_minit  = arkMassSuperLUMTInit;
-  ark_mem->ark_msetup = arkMassSuperLUMTSetup;
-  ark_mem->ark_msolve = arkMassSuperLUMTSolve;
-  ark_mem->ark_mfree  = arkMassSuperLUMTFree;
-  ark_mem->ark_mtimes = arkMassSuperLUMTMultiply;
-  ark_mem->ark_mtimes_data = (void *) ark_mem;
-  ark_mem->ark_msolve_type = 3;
-
-  /* Get memory for ARKSlsMassMemRec. */
-  arksls_mem = (ARKSlsMassMem) malloc(sizeof(struct ARKSlsMassMemRec));
-  if (arksls_mem == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_MEM_FAIL);
-    return(ARKSLS_MEM_FAIL);
-  }
-  
-  /* Get memory for SLUMTData. */
-  slumt_data = (SLUMTData) malloc(sizeof(struct SLUMTDataRec));
-  if (slumt_data == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_MEM_FAIL);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Initialize mass-matrix-related data */
-  arksls_mem->s_nme = 0;
-  arksls_mem->s_first_factorize = 1;
-  arksls_mem->s_Meval = smass;
-  arksls_mem->s_Mdata = ark_mem->ark_user_data;
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  ark_mem->ark_MassSetupNonNull = TRUE;
-  arksls_mem->sparsetype = CSC_MAT;
-
-  /* Allocate memory for M and M_lu */
-  arksls_mem->s_M = NULL;
-  arksls_mem->s_M = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (arksls_mem->s_M == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_MEM_FAIL);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-  arksls_mem->s_M_lu = NULL;
-  arksls_mem->s_M_lu = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (arksls_mem->s_M_lu == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_M);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-
-  /* Set up memory for the permutations */
-  perm_r = NULL;
-  perm_r = (int *) malloc(n*sizeof(int));
-  if (perm_r == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_M);
-    SparseDestroyMat(arksls_mem->s_M_lu);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-  perm_c = NULL;
-  perm_c = (int *) malloc(n*sizeof(int));
-  if (perm_c == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MEM_FAIL, "ARKSLS", 
-		    "ARKMassSuperLUMT", MSGSP_MEM_FAIL);
-    SparseDestroyMat(arksls_mem->s_M);
-    SparseDestroyMat(arksls_mem->s_M_lu);
-    free(slumt_data); slumt_data = NULL;
-    free(arksls_mem); arksls_mem = NULL;
-    free(perm_r); perm_r = NULL;
-    return(ARKSLS_MEM_FAIL);
-  }
-  slumt_data->perm_r = perm_r;
-  slumt_data->perm_c = perm_c;
-
-  /* Set default parameters for SuperLU */
-  slumt_data->num_threads = num_threads;
-  slumt_data->diag_pivot_thresh = 1.0;
-
-  /* Allocate structures for SuperLU */
-  slumt_data->Gstat = (Gstat_t *) malloc(sizeof(Gstat_t));
-  slumt_data->s_A   = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_AC  = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_L   = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_U   = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  slumt_data->s_A->Store  = NULL;
-  slumt_data->s_AC->Store = NULL;
-  slumt_data->s_L->Store  = NULL;
-  slumt_data->s_U->Store  = NULL;
-  slumt_data->superlumt_options = 
-    (superlumt_options_t *) malloc(sizeof(superlumt_options_t));
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  StatAlloc(arksls_mem->s_M->N, num_threads, panel_size, 
-	    relax, slumt_data->Gstat);
-  
-  /* Create RHS matrix */
-  nrhs = 1;
-  bd = NULL;
-  B = (SuperMatrix *) malloc(sizeof(SuperMatrix));
-  B->Store = NULL;
-  dCreate_Dense_Matrix(B, n, nrhs, bd, n, 
-		       SLU_DN, SLU_D, SLU_GE);
-  slumt_data->s_B = B;
-
-  /* Set ordering to COLAMD as the arkode default use.
-     Users can set a different value with ARKMassSuperLUMTSetOrdering,
-     and the user-set value is loaded before any call to 
-     factorize the matrix in arkMassSuperLUMTSetup.  */
-  slumt_data->s_ordering = 3;
-
-  /* Attach linear solver memory to the integrator memory */
-  arksls_mem->s_solver_data = (void *) slumt_data;
-  ark_mem->ark_mass_mem = arksls_mem;
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkMassSuperLUMTInit:
-
- This routine does remaining initializations specific to the 
- ARKSuperLUMT mass matrix linear solver module.  It returns 0 if
- successful.
----------------------------------------------------------------*/
-static int arkMassSuperLUMTInit(ARKodeMem ark_mem)
-{
-  ARKSlsMassMem arksls_mem;
-  SLUMTData slumt_data;
-
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  arksls_mem->s_nme = 0;
-  arksls_mem->s_first_factorize = 1;
-
-  /* Allocate storage and initialize statistics variables. */
-  StatInit(arksls_mem->s_M->N, slumt_data->num_threads, 
-	   slumt_data->Gstat);
-  arksls_mem->s_Mdata = ark_mem->ark_user_data;
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkMassSuperLUMTSetup:
-
-  This routine does the setup operations for the ARKMassSuperLUMT 
-  linear solver module.  It calls the mass matrix evaluation 
-  routine, updates counters, and calls the LU factorization 
-  routine.  The return value is either
-     ARKSLS_SUCCESS = 0  if successful,
-     +1  if the Meval routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the Meval routine failed unrecoverably.
----------------------------------------------------------------*/
-static int arkMassSuperLUMTSetup(ARKodeMem ark_mem, N_Vector vtemp1, 
-				 N_Vector vtemp2, N_Vector vtemp3)
-{
-  int retval;
-  int panel_size, relax, lwork;
-  double drop_tol;
-  fact_t fact;
-  trans_t trans;
-  yes_no_t refact, usepr;
-  ARKSlsMassMem arksls_mem;
-  SLUMTData slumt_data;
-  void *work;
-  
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  /* Set option values for SuperLU_MT */
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  fact = EQUILIBRATE;
-  trans = NOTRANS;
-  usepr = NO;
-  drop_tol = 0.0;
-  lwork = 0;
-  work = NULL;
-
-  /* Check that mass matrix eval routine is set */
-  if (arksls_mem->s_Meval == NULL) {
-    arkProcessError(ark_mem, ARKSLS_MASS_NOSET, "ARKSLS", 
-		    "arkMassSuperLUMTSetup", MSGSP_MASS_NOSET);
-    free(arksls_mem); arksls_mem = NULL;
-    return(ARKSLS_MASS_NOSET);
-  }
-
-  /* call Meval routine for new M matrix */
-  SparseSetMatToZero(arksls_mem->s_M);
-  retval = arksls_mem->s_Meval(ark_mem->ark_tn, arksls_mem->s_M, 
-			       arksls_mem->s_Mdata, vtemp1, 
-			       vtemp2, vtemp3);
-  arksls_mem->s_nme++;
-  if (retval < 0) {
-    arkProcessError(ark_mem, ARKSLS_MASSFUNC_UNRECVR, "ARKSLS", 
-		    "arkMassSuperLUMTSetup", MSGSP_MASSFUNC_FAILED);
-    arksls_mem->s_last_flag = ARKSLS_MASSFUNC_UNRECVR;
-    return(ARKSLS_MASSFUNC_UNRECVR);
-  }
-  if (retval > 0) {
-    arksls_mem->s_last_flag = ARKSLS_MASSFUNC_RECVR;
-    return(ARKSLS_MASSFUNC_RECVR);
-  }
-
-  /* Copy M into M_lu for LU decomposition */
-  SparseCopyMat(arksls_mem->s_M, arksls_mem->s_M_lu);
-
-
-  /* free and reallocate sparse matrix */
-  if (slumt_data->s_A->Store) {
-    SUPERLU_FREE(slumt_data->s_A->Store);
-  }
-  dCreate_CompCol_Matrix(slumt_data->s_A, arksls_mem->s_M->M, 
-			 arksls_mem->s_M->N, arksls_mem->s_M->NNZ, 
-			 arksls_mem->s_M->data, 
-			 arksls_mem->s_M->indexvals, 
-			 arksls_mem->s_M->indexptrs, 
-			 SLU_NC, SLU_D, SLU_GE);
-
-  /* On first decomposition, set up reusable pieces */ 
-  if (arksls_mem->s_first_factorize) {
-
-    /* Get column permutation vector perm_c[], according to s_ordering */
-    get_perm_c(slumt_data->s_ordering, slumt_data->s_A, 
-	       slumt_data->perm_c);
-    refact= NO;
-    arksls_mem->s_first_factorize = 0;
-
-  } else {
-    /* Re-initialize statistics variables */
-    StatInit(arksls_mem->s_M->N, slumt_data->num_threads, 
-	     slumt_data->Gstat);
-    Destroy_CompCol_Permuted(slumt_data->s_AC);
-    refact= YES;
-  }
-
-  /* Initialize the option structure superlumt_options using the
-     user-input parameters. Subsequent calls will re-initialize
-     options.  Apply perm_c to columns of original A to form AC */
-  pdgstrf_init(slumt_data->num_threads, fact, trans, refact, 
-	       panel_size, relax, slumt_data->diag_pivot_thresh, 
-	       usepr, drop_tol, slumt_data->perm_c, 
-	       slumt_data->perm_r, work, lwork, slumt_data->s_A, 
-	       slumt_data->s_AC, slumt_data->superlumt_options, 
-	       slumt_data->Gstat);
-
-  /* Compute the LU factorization of A.
-     The following routine will create num_threads threads. */
-  pdgstrf(slumt_data->superlumt_options, slumt_data->s_AC, 
-	  slumt_data->perm_r, slumt_data->s_L, slumt_data->s_U, 
-	  slumt_data->Gstat, &retval);
-  if (retval != 0) {
-    arksls_mem->s_last_flag = retval;
-    return(ARKSLS_PACKAGE_FAIL);
-  }
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkMassSuperLUMTSolve:
-
- This routine handles the solve operation for the ARKSuperLUMT 
- mass matrix linear solver module.  It calls the SuperLU_MT 
- solve routine, then returns ARKSLS_SUCCESS = 0.
----------------------------------------------------------------*/
-static int arkMassSuperLUMTSolve(ARKodeMem ark_mem, N_Vector b, 
-				 N_Vector weight)
-{
-  int info;
-  ARKSlsMassMem arksls_mem;
-  DNformat *Bstore;
-  SLUMTData slumt_data;
-  realtype *bd;
-  trans_t trans;
-  
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  bd = N_VGetArrayPointer(b);
-  Bstore = (DNformat *) (slumt_data->s_B->Store);
-  Bstore->nzval = bd;
-
-  /* Call SuperLUMT to solve the linear system using L and U */
-  trans = NOTRANS;
-  dgstrs(trans, slumt_data->s_L, slumt_data->s_U, 
-	 slumt_data->perm_r, slumt_data->perm_c, 
-	 slumt_data->s_B, slumt_data->Gstat, &info);
-
-  arksls_mem->s_last_flag = ARKSLS_SUCCESS;
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- arkMassSuperLUMTFree:
-
- This routine frees memory specific to the ARKSuperLUMT mass 
- matrix linear solver.
----------------------------------------------------------------*/
-static int arkMassSuperLUMTFree(ARKodeMem ark_mem)
-{
-  ARKSlsMassMem arksls_mem;
-  SLUMTData slumt_data;
-  
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  pxgstrf_finalize(slumt_data->superlumt_options, 
-		   slumt_data->s_AC);
-  free(slumt_data->perm_r);
-  free(slumt_data->perm_c);
-  free(slumt_data->superlumt_options);
-  Destroy_SuperNode_SCP( (slumt_data->s_L) );
-  Destroy_CompCol_NCP( (slumt_data->s_U) );
-  StatFree(slumt_data->Gstat);
-  free(slumt_data->Gstat);
-  
-  Destroy_SuperMatrix_Store(slumt_data->s_B);
-  SUPERLU_FREE(slumt_data->s_A->Store);
-  if (arksls_mem->s_M) {
-    SparseDestroyMat(arksls_mem->s_M);
-    arksls_mem->s_M = NULL;
-  }
-
-  if (arksls_mem->s_M_lu) {
-    SparseDestroyMat(arksls_mem->s_M_lu);
-    arksls_mem->s_M_lu = NULL;
-  }
-
-  free(slumt_data->s_B);
-  free(slumt_data->s_A);
-  free(slumt_data->s_AC);
-  free(slumt_data->s_L);
-  free(slumt_data->s_U);
-
-  free(slumt_data); 
-  slumt_data = NULL;
-  free(arksls_mem); 
-  ark_mem->ark_mass_mem = NULL;
-
-  return(0);
-}
-
-
-/*===============================================================
- Utility Functions
-===============================================================*/
-
-/*---------------------------------------------------------------
- arkMassSuperLUMTMultiply:
-
- Multiplies the mass matrix by the vector v to fill in the 
- vector Mv.
----------------------------------------------------------------*/
-static int arkMassSuperLUMTMultiply(N_Vector v, N_Vector Mv, 
-				    realtype t, void *arkode_mem)
-{
-
-  /* extract the SlsMassMem structure from the arkode_mem pointer */
-  ARKodeMem ark_mem;
-  ARKSlsMassMem arksls_mem;
-  realtype *vdata=NULL, *Mvdata=NULL;
-
-  /* Return immediately if arkode_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "arkMassSuperLUMTMultiply", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-
-  /* zero out the result */
-  N_VConst(0.0, Mv);
-
-  /* access the vector arrays (since they must be serial vectors) */
-  vdata = N_VGetArrayPointer(v);
-  Mvdata = N_VGetArrayPointer(Mv);
-  if (vdata == NULL || Mvdata == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "arkMassSuperLUMTMultiply", 
-		    "Vector data un-allocated.");
-    return(ARKSLS_MEM_NULL);
-  }
-
-  /* perform matrix-vector product with arksls_mem->s_M and return */
-  if (SparseMatvec(arksls_mem->s_M, vdata, Mvdata) != 0) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "arkMassSuperLUMTMultiply", 
-		    "Mass matrix data un-allocated.");
-    return(ARKSLS_MEM_NULL);
-  }
-
-  return(0);
-
-}
-
-
-/*===============================================================
- Optional Input Specification Functions
-===============================================================*/
-
-
-/*---------------------------------------------------------------
- ARKSuperLUMTSetOrdering:
-
- Sets the ordering used by SuperLUMT for reducing fill.
- Options are: 
-     0 for natural ordering
-     1 for minimal degree ordering on A'*A
-     2 for minimal degree ordering on A'+A
-     3 for AMD ordering for unsymmetric matrices
- The default used in SUNDIALS is 3 for COLAMD.
----------------------------------------------------------------*/
-int ARKSuperLUMTSetOrdering(void *arkode_mem, int ordering_choice)
-{
-  ARKodeMem ark_mem;
-  ARKSlsMem arksls_mem;
-  SLUMTData slumt_data;
-
-  /* Return immediately if ark_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKSuperLUMTSetOrdering", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice < 0) || (ordering_choice > 3) ) {
-    arkProcessError(NULL, ARKSLS_ILL_INPUT, "ARKSLS", 
-		    "ARKSuperLUMTSetOrdering", MSGSP_ILL_INPUT);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  arksls_mem = (ARKSlsMem) ark_mem->ark_lmem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  slumt_data->s_ordering = ordering_choice;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
- ARKMassSuperLUMTSetOrdering:
-
- Sets the ordering used by SuperLUMT for reducing fill. Options 
- are: 
-     0 for natural ordering
-     1 for minimal degree ordering on A'*A
-     2 for minimal degree ordering on A'+A
-     3 for AMD ordering for unsymmetric matrices
- The default used in SUNDIALS is 3 for COLAMD.
----------------------------------------------------------------*/
-int ARKMassSuperLUMTSetOrdering(void *arkode_mem, int ordering_choice)
-{
-  ARKodeMem     ark_mem;
-  ARKSlsMassMem arksls_mem;
-  SLUMTData     slumt_data;
-
-  /* Return immediately if ark_mem is NULL */
-  if (arkode_mem == NULL) {
-    arkProcessError(NULL, ARKSLS_MEM_NULL, "ARKSLS", 
-		    "ARKMassSuperLUMTSetOrdering", MSGSP_ARKMEM_NULL);
-    return(ARKSLS_MEM_NULL);
-  }
-  ark_mem = (ARKodeMem) arkode_mem;
-
-  /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice < 0) || (ordering_choice > 3) ) {
-    arkProcessError(NULL, ARKSLS_ILL_INPUT, "ARKSLS", 
-		    "ARKMassSuperLUMTSetOrdering", MSGSP_ILL_INPUT);
-    return(ARKSLS_ILL_INPUT);
-  }
-
-  arksls_mem = (ARKSlsMassMem) ark_mem->ark_mass_mem;
-  slumt_data = (SLUMTData) arksls_mem->s_solver_data;
-
-  slumt_data->s_ordering = ordering_choice;
-
-  return(ARKSLS_SUCCESS);
-}
-
-
-/*---------------------------------------------------------------
-   EOF
----------------------------------------------------------------*/
diff --git a/src/arkode/fcmix/CMakeLists.txt b/src/arkode/fcmix/CMakeLists.txt
index cff9228..1b2f409 100644
--- a/src/arkode/fcmix/CMakeLists.txt
+++ b/src/arkode/fcmix/CMakeLists.txt
@@ -1,9 +1,19 @@
 # ---------------------------------------------------------------
 # Programmer:  Daniel R. Reynolds @ SMU
 # ---------------------------------------------------------------
-# Copyright (c) 2013, Southern Methodist University.
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the FARKODE library
 
@@ -24,31 +34,55 @@ SET(farkode_SOURCES
   farkpreco.c
   farkmasspreco.c
   farkroot.c
+  farksparse.c 
+  farksparsemass.c
   )
 
-IF(LAPACK_FOUND)
-  SET(farkode_BL_SOURCES farklapack.c farklapdense.c farklapdensemass.c farklapband.c farklapbandmass.c)
-ELSE(LAPACK_FOUND)
-  SET(farkode_BL_SOURCES "")
-ENDIF(LAPACK_FOUND)
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the ARKODE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/nvec_ser/fnvector_serial.c
+  )
+
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the ARKODE library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/fsunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/fsunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/fsunmatrix_sparse.c
+  )
 
-IF(KLU_FOUND OR SUPERLUMT_FOUND)
-  SET(farkode_SPARSE_SOURCES farksparse.c farksparsemass.c)
-ELSE(SPARSE_FOUND)
-  SET(farkode_SPARSE_SOURCES "")
-ENDIF(KLU_FOUND OR SUPERLUMT_FOUND)
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the ARKODE library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/fsunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/fsunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/fsunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/fsunlinsol_pcg.c
+  )
 
 IF(KLU_FOUND)
-  SET(farkode_KLU_SOURCES farkklu.c)
-ELSE(KLU_FOUND)
-  SET(farkode_KLU_SOURCES "")
-ENDIF(KLU_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_klu/fsunlinsol_klu.c
+    )
+ENDIF()
 
 IF(SUPERLUMT_FOUND)
-  SET(farkode_SUPERLUMT_SOURCES farksuperlumt.c)
-ELSE(SUPERLUMT_FOUND)
-  SET(farkode_SUPERLUMT_SOURCES "")
-ENDIF(SUPERLUMT_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_superlumt/fsunlinsol_superlumt.c
+    )
+ENDIF()
+
+IF(LAPACK_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackband/fsunlinsol_lapackband.c
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c
+    )
+ENDIF()
+
 
 # Add source directories to include directories for access to
 # implementation only header files (both for farkode and arkode)
@@ -63,7 +97,8 @@ ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
 # coming from inexistent user-provided functions)
 
 # Add the build target for the FARKODE library
-ADD_LIBRARY(sundials_farkode_static STATIC ${farkode_SOURCES} ${farkode_BL_SOURCES} ${farkode_SPARSE_SOURCES} ${farkode_KLU_SOURCES} ${farkode_SUPERLUMT_SOURCES})
+ADD_LIBRARY(sundials_farkode_static STATIC
+  ${farkode_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
 # Set the library name and make sure it is not deleted
 SET_TARGET_PROPERTIES(sundials_farkode_static
diff --git a/src/arkode/fcmix/farkband.c b/src/arkode/fcmix/farkband.c
index 2177ea0..1f23a89 100644
--- a/src/arkode/fcmix/farkband.c
+++ b/src/arkode/fcmix/farkband.c
@@ -2,28 +2,29 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKBAND, for the case 
- * of a user-supplied Jacobian approximation routine.                
+ * Fortran/C interface routines for ARKODE/ARKDLS, for the case
+ * of a user-supplied Jacobian approximation routine.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "farkode.h"
 #include "arkode_impl.h"
-#include <arkode/arkode_band.h>
+#include <arkode/arkode_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
 
 
 /*=============================================================*/
@@ -34,9 +35,9 @@
 extern "C" {
 #endif
 
-  extern void FARK_BJAC(long int *N, long int *MU, long int *ML,
-  			long int *EBAND, realtype *T,
-  			realtype *Y, realtype *FY,
+  extern void FARK_BJAC(long int *N, long int *MU, 
+                        long int *ML, long int *EBAND, 
+                        realtype *T, realtype *Y, realtype *FY,
   			realtype *BJAC, realtype *H,
   			long int *IPAR, realtype *RPAR,
   			realtype *V1, realtype *V2,
@@ -48,33 +49,31 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface routine to ARKDlsSetBandJacFn; see farkode.h 
+/* Fortran interface routine to ARKDlsSetJacFn; see farkode.h
    for further details */
 void FARK_BANDSETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = ARKDlsSetBandJacFn(ARK_arkodemem, NULL);
+    *ier = ARKDlsSetJacFn(ARK_arkodemem, NULL);
   } else {
-    *ier = ARKDlsSetBandJacFn(ARK_arkodemem, FARKBandJac);
+    *ier = ARKDlsSetJacFn(ARK_arkodemem, FARKBandJac);
   }
   return;
 }
 
 /*=============================================================*/
 
-/* C interface to user-supplied Fortran subroutine FARKBJAC; see 
+/* C interface to user-supplied Fortran subroutine FARKBJAC; see
    farkode.h for further details */
-int FARKBandJac(long int N, long int mupper, 
-		long int mlower, realtype t, N_Vector y, 
-		N_Vector fy, DlsMat J, void *user_data, 
-		N_Vector vtemp1, N_Vector vtemp2, 
+int FARKBandJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+                void *user_data, N_Vector vtemp1, N_Vector vtemp2,
 		N_Vector vtemp3)
 {
-  int ier;
   realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
   realtype h;
-  long int eband;
+  long int N, mupper, mlower, smu, eband;
   FARKUserData ARK_userdata;
+  int ier = 0;
 
   ARKodeGetLastStep(ARK_arkodemem, &h);
   ydata   = N_VGetArrayPointer(y);
@@ -82,12 +81,16 @@ int FARKBandJac(long int N, long int mupper,
   v1data  = N_VGetArrayPointer(vtemp1);
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
-  eband   = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
+  N = SUNBandMatrix_Columns(J);
+  mupper = SUNBandMatrix_UpperBandwidth(J);
+  mlower = SUNBandMatrix_LowerBandwidth(J);
+  smu = SUNBandMatrix_StoredUpperBandwidth(J);
+  eband   = smu + mlower + 1;
+  jacdata = SUNBandMatrix_Column(J,0) - mupper;
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata, 
-	    jacdata, &h, ARK_userdata->ipar, ARK_userdata->rpar, 
+  FARK_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata,
+	    jacdata, &h, ARK_userdata->ipar, ARK_userdata->rpar,
 	    v1data, v2data, v3data, &ier);
   return(ier);
 }
diff --git a/src/arkode/fcmix/farkbandmass.c b/src/arkode/fcmix/farkbandmass.c
index 8d69bb5..fa11c0d 100644
--- a/src/arkode/fcmix/farkbandmass.c
+++ b/src/arkode/fcmix/farkbandmass.c
@@ -2,28 +2,29 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2015, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKBAND, for the case 
- * of a user-supplied Jacobian approximation routine.                
+ * Fortran/C interface routines for ARKODE/ARKDLS, for the case
+ * of a user-supplied mass-matrix approximation routine.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "farkode.h"
 #include "arkode_impl.h"
-#include <arkode/arkode_band.h>
+#include <arkode/arkode_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
 
 
 /*=============================================================*/
@@ -34,11 +35,12 @@
 extern "C" {
 #endif
 
-  extern void FARK_BMASS(long int *N, long int *MU, long int *ML,
-  			 long int *EBAND, realtype *T,
-  			 realtype *BMASS, long int *IPAR,
-  			 realtype *RPAR, realtype *V1,
-  			 realtype *V2, realtype *V3, int *IER);
+  extern void FARK_BMASS(long int *N, long int *MU, 
+                         long int *ML, long int *EBAND, 
+                         realtype *T, realtype *BMASS,
+                         long int *IPAR, realtype *RPAR,
+                         realtype *V1, realtype *V2, realtype *V3, 
+                         int *IER);
 
 #ifdef __cplusplus
 }
@@ -46,35 +48,38 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface routine to ARKDlsSetBandMassFn; see farkode.h 
+/* Fortran interface routine to ARKDlsSetMassFn; see farkode.h
    for further details */
 void FARK_BANDSETMASS(int *ier)
 {
-  *ier = ARKDlsSetBandMassFn(ARK_arkodemem, FARKBandMass);
+  *ier = ARKDlsSetMassFn(ARK_arkodemem, FARKBandMass);
 }
 
 /*=============================================================*/
 
-/* C interface to user-supplied Fortran subroutine FARKBMASS; see 
+/* C interface to user-supplied Fortran subroutine FARKBMASS; see
    farkode.h for further details */
-int FARKBandMass(long int N, long int mupper, long int mlower, 
-		 realtype t, DlsMat M, void *user_data, 
+int FARKBandMass(realtype t, SUNMatrix M, void *user_data,
 		 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
 {
   int ier;
   realtype *massdata, *v1data, *v2data, *v3data;
-  long int eband;
+  long int N, mupper, mlower, smu, eband;
   FARKUserData ARK_userdata;
 
   v1data  = N_VGetArrayPointer(vtemp1);
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
-  eband   = (M->s_mu) + mlower + 1;
-  massdata = BAND_COL(M,0) - mupper;
+  N = SUNBandMatrix_Columns(M);
+  mupper = SUNBandMatrix_UpperBandwidth(M);
+  mlower = SUNBandMatrix_LowerBandwidth(M);
+  smu = SUNBandMatrix_StoredUpperBandwidth(M);
+  eband   = smu + mlower + 1;
+  massdata = SUNBandMatrix_Column(M,0) - mupper;
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_BMASS(&N, &mupper, &mlower, &eband, &t, massdata, 
-	     ARK_userdata->ipar, ARK_userdata->rpar, v1data, 
+  FARK_BMASS(&N, &mupper, &mlower, &eband, &t, massdata,
+	     ARK_userdata->ipar, ARK_userdata->rpar, v1data,
 	     v2data, v3data, &ier);
   return(ier);
 }
diff --git a/src/arkode/fcmix/farkbbd.c b/src/arkode/fcmix/farkbbd.c
index 15db62f..6673ab5 100644
--- a/src/arkode/fcmix/farkbbd.c
+++ b/src/arkode/fcmix/farkbbd.c
@@ -2,23 +2,23 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * This module contains the routines necessary to interface with 
+ * This module contains the routines necessary to interface with
  * the ARKBBDPRE module and user-supplied Fortran routines.
- * The routines here call the generically named routines and 
- * providea standard interface to the C code of the ARKBBDPRE 
+ * The routines here call the generically named routines and
+ * providea standard interface to the C code of the ARKBBDPRE
  * package.
  *--------------------------------------------------------------*/
 
@@ -36,12 +36,12 @@
 extern "C" {
 #endif
 
-  extern void FARK_GLOCFN(long int *NLOC, realtype *T, 
+  extern void FARK_GLOCFN(long int *NLOC, realtype *T,
 			  realtype *YLOC, realtype *GLOC,
 			  long int *IPAR, realtype *RPAR,
 			  int *ier);
-  extern void FARK_COMMFN(long int *NLOC, realtype *T, 
-			  realtype *Y, long int *IPAR, 
+  extern void FARK_COMMFN(long int *NLOC, realtype *T,
+			  realtype *Y, long int *IPAR,
 			  realtype *RPAR, int *ier);
 
 #ifdef __cplusplus
@@ -50,25 +50,28 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKBBDPrecInit; see farkbbd.h 
+/* Fortran interface to C routine ARKBBDPrecInit; see farkbbd.h
    for further details. */
-void FARK_BBDINIT(long int *Nloc, long int *mudq, long int *mldq, 
-		  long int *mu, long int *ml, realtype* dqrely, 
+void FARK_BBDINIT(long int *Nloc, long int *mudq,
+                  long int *mldq, long int *mu,
+                  long int *ml, realtype* dqrely,
 		  int *ier)
 {
-  /* Notes: FARKgloc is a pointer to the ARKLocalFn function, 
+  /* Notes: FARKgloc is a pointer to the ARKLocalFn function,
      and FARKcfn is a pointer to the ARKCommFn function */
-  *ier = ARKBBDPrecInit(ARK_arkodemem, *Nloc, *mudq, *mldq, 
-			*mu, *ml, *dqrely, FARKgloc, FARKcfn);
-  return; 
+  *ier = ARKBBDPrecInit(ARK_arkodemem, *Nloc, *mudq, *mldq,
+			*mu, *ml, *dqrely, 
+                        (ARKLocalFn) FARKgloc,
+                        (ARKCommFn) FARKcfn);
+  return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKBBDPrecReInit; see farkbbd.h 
+/* Fortran interface to C routine ARKBBDPrecReInit; see farkbbd.h
    for further details. */
-void FARK_BBDREINIT(long int *Nloc, long int *mudq, 
-		    long int *mldq, realtype* dqrely, int *ier)
+void FARK_BBDREINIT(long int *mudq, long int *mldq,
+                    realtype* dqrely, int *ier)
 {
   *ier = ARKBBDPrecReInit(ARK_arkodemem, *mudq, *mldq, *dqrely);
   return;
@@ -76,47 +79,52 @@ void FARK_BBDREINIT(long int *Nloc, long int *mudq,
 
 /*=============================================================*/
 
-/* C interface to user-supplied Fortran routine FARKGLOCFN; see 
+/* C interface to user-supplied Fortran routine FARKGLOCFN; see
    farkbbd.h for further details. */
-int FARKgloc(long int Nloc, realtype t, N_Vector yloc, 
+int FARKgloc(long int Nloc, realtype t, N_Vector yloc,
 	     N_Vector gloc, void *user_data)
 {
-  int ier;
   realtype *yloc_data, *gloc_data;
   FARKUserData ARK_userdata;
+  int ier = 0;
+
+  /* Initialize all pointers to NULL */
+  yloc_data = gloc_data = NULL;
 
   yloc_data = N_VGetArrayPointer(yloc);
   gloc_data = N_VGetArrayPointer(gloc);
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_GLOCFN(&Nloc, &t, yloc_data, gloc_data, 
+  FARK_GLOCFN(&Nloc, &t, yloc_data, gloc_data,
              ARK_userdata->ipar, ARK_userdata->rpar, &ier);
   return(ier);
 }
 
 /*=============================================================*/
 
-/* C interface to user-supplied Fortran routine FARKCOMMFN; see 
+/* C interface to user-supplied Fortran routine FARKCOMMFN; see
    farkbbd.h for further details. */
-int FARKcfn(long int Nloc, realtype t, 
-	    N_Vector y, void *user_data)
+int FARKcfn(long int Nloc, realtype t, N_Vector y, void *user_data)
 {
-  int ier;
   realtype *yloc;
   FARKUserData ARK_userdata;
+  int ier = 0;
+
+  /* Initialize all pointers to NULL */
+  yloc = NULL;
 
   yloc = N_VGetArrayPointer(y);
   ARK_userdata = (FARKUserData) user_data;
-  FARK_COMMFN(&Nloc, &t, yloc, ARK_userdata->ipar, 
+  FARK_COMMFN(&Nloc, &t, yloc, ARK_userdata->ipar,
 	      ARK_userdata->rpar, &ier);
   return(ier);
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C routines ARKBBDPrecGetWorkSpace and 
+/* Fortran interface to C routines ARKBBDPrecGetWorkSpace and
    ARKBBDPrecGetNumGfnEvals; see farkbbd.h for further details */
-void FARK_BBDOPT(long int *lenrwbbd, long int *leniwbbd, 
+void FARK_BBDOPT(long int *lenrwbbd, long int *leniwbbd,
 		 long int *ngebbd)
 {
   ARKBBDPrecGetWorkSpace(ARK_arkodemem, lenrwbbd, leniwbbd);
diff --git a/src/arkode/fcmix/farkbbd.h b/src/arkode/fcmix/farkbbd.h
index 2a82efe..0d5a382 100644
--- a/src/arkode/fcmix/farkbbd.h
+++ b/src/arkode/fcmix/farkbbd.h
@@ -2,13 +2,13 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
@@ -21,180 +21,199 @@
 
 /*===============================================================
                    FARKBBD Interface Package
- 
+
  The FARKBBD Interface Package is a package of C functions which,
  together with the FARKODE Interface Package, support the use of
- the ARKODE solver and parallel N_Vector module, along with the 
- ARKBBDPRE preconditioner module, for the solution of ODE systems
- in a mixed Fortran/C setting.  The combination of ARKODE and 
- ARKBBDPRE solves the linear systems arising from the solution 
+ the ARKODE solver and MPI-parallel N_Vector module, along with
+ the ARKBBDPRE preconditioner module, for the solution of ODE
+ systems in a mixed Fortran/C setting.  The combination of ARKODE
+ and ARKBBDPRE solves the linear systems arising from the solution
  of the implicit portions of the ODE system
-       dy/dt = fe(t,y) + fi(t,y)  
- using a Krylov iterative linear solver (SPGMR, SPTFQMR, SPBCG, 
- SPFGMR or PCG), and with a preconditioner that is block-diagonal 
- with banded blocks.  While ARKODE and ARKBBDPRE are written in C, 
- it is assumed here that the user's calling program and user-
- supplied problem-defining routines are written in Fortran.
- 
- The user-callable functions in this package, with the 
- corresponding ARKODE and ARKBBDPRE functions, are as follows: 
+       dy/dt = fe(t,y) + fi(t,y)
+ using a Krylov iterative linear solver via the ARKSPILS interface,
+ and with a preconditioner that is block-diagonal with banded
+ blocks.  While ARKODE and ARKBBDPRE are written in C, it is
+ assumed here that the user's calling program and user-supplied
+ problem-defining routines are written in Fortran.
+
+ The user-callable functions in this package, with the
+ corresponding ARKODE and ARKBBDPRE functions, are as follows:
 
    Fortran               ARKODE
    --------------        ---------------------------
-   FARKBBDININT          ARKBBDPrecInit
+   FARKBBDINIT           ARKBBDPrecInit
    FARKBBDREINIT         ARKBBDPrecReInit
    FARKBBDOPT            (accesses optional outputs)
    --------------        ---------------------------
- 
- In addition to the Fortran implicit right-hand side function 
+
+ In addition to the Fortran implicit right-hand side function
  FARKIFUN, the user-supplied functions used by this package are
- listed below, each with the corresponding interface function 
+ listed below, each with the corresponding interface function
  which calls it (and its type within ARKBBDPRE or ARKODE):
 
-   Fortran          ARKODE           Type
-   -------------    ----------       ----------------
-   FARKGLOCFN       FARKgloc         ARKLocalFn
-   FARKCOMMFN       FARKcfn          ARKCommFn
-   FARKJTIMES(*)    FARKJtimes       ARKSpilsJtimesFn
-   -------------    ----------       ----------------
+   Fortran           ARKODE            Type
+   --------------    -----------       -----------------
+   FARKGLOCFN        FARKgloc          ARKLocalFn
+   FARKCOMMFN        FARKcfn           ARKCommFn
+   FARKJTSETUP(*)    FARKJTSetup       ARKSpilsJTSetupFn
+   FARKJTIMES(*)     FARKJtimes        ARKSpilsJtimesFn
+   --------------    -----------       -----------------
    (*) = optional
 
  Important notes on portability:
 
- The names of all user-supplied routines here are fixed, in 
- order to maximize portability for the resulting mixed-language 
+ The names of all user-supplied routines here are fixed, in
+ order to maximize portability for the resulting mixed-language
  program.
 
- Additionally, the names of the interface functions, and the 
- names of the Fortran user routines called by them, appear as 
- dummy names which are mapped to actual values by a series of 
+ Additionally, the names of the interface functions, and the
+ names of the Fortran user routines called by them, appear as
+ dummy names which are mapped to actual values by a series of
  definitions in the header file farkbbd.h.
- 
+
  ================================================================
- 
+
             Usage of the FARKODE/FARKBBD Interface Packages
- 
- The usage of the combined interface packages FARKODE and 
- FARKBBD requires calls to seven to twelve interface functions, 
- and three or four user-supplied routines which define the 
- problem to be solved and indirectly define the preconditioner.  
- These function calls and user routines are summarized separately
- below.
- 
+
+ The usage of the combined interface packages FARKODE and
+ FARKBBD requires calls to a variety of interface functions, and
+ three or more user-supplied routines which define the problem to
+ be solved and indirectly define the preconditioner.  These
+ function calls and user routines are summarized separately below.
+
  Some details are omitted, and the user is referred to the ARKODE
  user document for more complete information.
- 
+
  (1) User-supplied implicit right-hand side routine: FARKIFUN
-     If any portion of the ODE system should be treated 
+
+     If any portion of the ODE system should be treated
      implicitly (and hence would require a linear solver at all),
      the user must supply the following Fortran routine:
 
        SUBROUTINE FARKIFUN(T, Y, YDOT, IPAR, RPAR, IER)
 
-     Sets the YDOT array to fi(T,Y), the implicit portion of the 
+     Sets the YDOT array to fi(T,Y), the implicit portion of the
      right-hand side of the ODE system, as function of time T and
      the state variable array Y.
 
      The arguments are:
        Y    -- array containing state variables [realtype, input]
-       YDOT -- array containing state derivatives [realtype, 
+       YDOT -- array containing state derivatives [realtype,
                output]
        IPAR -- array containing integer user data that was passed
                to FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                  >0 if a recoverable error occurred,
                  <0 if an unrecoverable error ocurred.
- 
+
  (2) User-supplied routines to define preconditoner: FARKGLOCFN
      and FARKCOMMFN
- 
-     The routines in the ARKBBDPRE module provide a 
-     preconditioner matrix for ARKODE that is block-diagonal 
-     with banded blocks.  The blocking corresponds to the 
-     distribution of the dependent variable vector y among the 
+
+     The routines in the ARKBBDPRE module provide a
+     preconditioner matrix for ARKODE that is block-diagonal
+     with banded blocks.  The blocking corresponds to the
+     distribution of the dependent variable vector y among the
      processors.  Each preconditioner block is generated from the
-     Jacobian of the local part (on the current processor) of a 
+     Jacobian of the local part (on the current processor) of a
      given function g(t,y) approximating fi(t,y).  The blocks are
      generated by a difference quotient scheme on each processor
      independently, utilizing an assumed banded structure with
      given half-bandwidths.  A separate pair of half-bandwidths
      defines the band matrix retained.
- 
+
  (2.1) Local approximate function FARKGLOCFN.
 
      The user must supply a subroutine of the form
 
-       SUBROUTINE FARKGLOCFN(NLOC, T, YLOC, GLOC, IPAR, 
-      &                      RPAR, IER)
-       DIMENSION YLOC(*), GLOC(*), IPAR(*), RPAR(*)
+       SUBROUTINE FARKGLOCFN(NLOC, T, YLOC, GLOC, IPAR, RPAR, IER)
 
-     Sets the GLOC array to the function g(T,YLOC) which 
-     approximates the right-hand side function fi(T,YLOC).  This 
-     function is to be computed locally, i.e. without 
-     inter-processor communication (the case where g is 
-     mathematically identical to fi is allowed).  
+     Sets the GLOC array to the function g(T,YLOC) which
+     approximates the right-hand side function fi(T,YLOC).  This
+     function is to be computed locally, i.e. without
+     inter-processor communication (the case where g is
+     mathematically identical to fi is allowed).
 
      The arguments are:
        NLOC -- local problem size [long int, input]
        T    -- current time [realtype, input]
-       YLOC -- array containing local state variables 
+       YLOC -- array containing local state variables
                [realtype, input]
-       GLOC -- array containing local state derivatives 
+       GLOC -- array containing local state derivatives
                [realtype, output]
        IPAR -- array containing integer user data that was passed
                to FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                  >0 if a recoverable error occurred,
                  <0 if an unrecoverable error ocurred.
- 
+
  (2.2) Communication function FARKCOMMFN.
 
      The user must also supply a subroutine of the form:
 
        SUBROUTINE FARKCOMMFN(NLOC, T, YLOC, IPAR, RPAR, IER)
-       DIMENSION YLOC(*), IPAR(*), RPAR(*)
 
      This performs all inter-processor communication necessary to
-     evaluate g described above.  It is expected to save 
-     communicated data in work space defined by the user, and 
-     made available to ARKLOCFN.  Each call to the FARKCOMMFN is
-     preceded by a call to FARKIFUN with the same (T,YLOC) 
+     evaluate g described above.  It is expected to save
+     communicated data in work space defined by the user, and
+     made available to FARKLOCFN.  Each call to the FARKCOMMFN is
+     preceded by a call to FARKIFUN with the same (T,YLOC)
      arguments.  Thus FARKCOMMFN can omit any communications done
      by FARKIFUN if relevant to the evaluation of g.
 
      The arguments are:
        NLOC -- local problem size [long int, input]
        T    -- current time [realtype, input]
-       YLOC -- array containing local state variables 
+       YLOC -- array containing local state variables
                [realtype, input]
        IPAR -- array containing integer user data that was passed
                to FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                  >0 if a recoverable error occurred,
                  <0 if an unrecoverable error ocurred.
  
- (3) Optional user-supplied Jacobian-vector product: FARKJTIMES
+ (3) Optional user-supplied Jacobian-vector setup and product 
+     functions: FARKJTSETUP and FARKJTIMES
+
+     As an option, the user may supply a routine that computes
+     the product of the system Jacobian  J = dfi(t,y)/dy and a
+     given vector v.  If supplied, a 'setup' routine to prepare
+     any user data structures must exist, and have the form:
+ 
+       SUBROUTINE FARKJTSETUP(T, Y, FY, H, IPAR, RPAR, IER)
 
-     As an option, the user may supply a routine that computes 
-     the product of the system Jacobian  J = dfi(t,y)/dy and a 
-     given vector v.  If supplied, it must have the following 
-     form:
+     Typically this routine will use only T and Y.  It must perform any 
+     relevant preparations for subsequent calls to the user-provided
+     FARKJTIMES routine (see below).
 
-       SUBROUTINE FARKJTIMES(V, FJV, T, Y, FY, H, IPAR, RPAR, 
-      &                      WORK, IER)
+     The arguments are:
+       T    -- current time [realtype, input]
+       Y    -- array containing state variables [realtype, input]
+       FY   -- array containing state derivatives [realtype, input]
+       H    -- current step size [realtype, input]
+       IPAR -- array containing integer user data that was passed to
+               FARKMALLOC [long int, input]
+       RPAR -- array containing real user data that was passed to
+               FARKMALLOC [realtype, input]
+       IER  -- return flag [int, output]:
+                  0 if successful,
+                  nonzero if an error.
 
-     Typically this routine will use only NEQ, T, Y, V, and FJV. 
-     It must compute the product vector J*v where the vector V, 
-     and store the product in FJV.  
+     The accompanying Jacobian matrix-vector product routine must
+     have the following form:
+
+       SUBROUTINE FARKJTIMES(V, FJV, T, Y, FY, H, IPAR, RPAR, WORK, IER)
+
+     Typically this routine will use only NEQ, T, Y, V, and FJV.
+     It must compute the product vector J*v, and store the product in FJV.
 
      The arguments are:
        V    -- vector to multiply [realtype, input]
@@ -210,33 +229,51 @@
        WORK -- array containing temporary workspace of same size
                as Y [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                   nonzero if an error.
 
- (4) Initialization:  FNVINITP, FARKMALLOC, linear solver
-     initialization, and FARKBBDINIT.
- 
+ (4) Initialization:  FNVINITP, generic iterative linear solver
+     initialization, FARKMALLOC, FARKSPILSINIT, and FARKBBDINIT.
+
  (4.1) To initialize the parallel vector specification, the user
      must make the following call:
 
-        CALL FNVINITP(4, NLOCAL, NGLOBAL, IER)
+        CALL FNVINITP(COMM, 4, NLOCAL, NGLOBAL, IER)
 
-     where the first argument is an int containing the ARKODE 
+     where the second argument is an int containing the ARKODE 
      solver ID (4). The other arguments are:
+        COMM = the MPI communicator [int, input]
         NLOCAL = local vector size on this processor 
-	   [long int, input]
+           [long int, input]
         NGLOBAL = system size, and the global size of vectors 
-	   (the sum of all values of NLOCAL) [long int, input]
+           (the sum of all values of NLOCAL) [long int, input]
         IER = return completion flag [int, ouptut]. 
                   0 = success, 
                  -1 = failure.
 
-     Note: If MPI was initialized by the user, the communicator 
-     must be set to MPI_COMM_WORLD.  If not, this routine 
-     initializes MPI and sets the communicator equal to 
-     MPI_COMM_WORLD.
- 
- (4.2) To set various problem and solution parameters and 
+ (4.2) To initialize a generic iterative linear solver structure for
+     solving linear systems arising from implicit or IMEX treatment
+     of the IVP, the user must make one of the following calls:
+
+          CALL FSUNPCGINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPBCGSINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPFGMRINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPGMRINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPTFQMRINIT(4, PRETYPE, MAXL, IER)
+
+     In each of these, one argument is an int containing the ARKODE solver
+     ID (4).
+
+     The other arguments are:
+
+        PRETYPE = type of preconditioning to perform (0=none, 1=left,
+           2=right, 3=both) [int, input]
+        MAXL = maximum Krylov subspace dimension [int, input]
+        IER = return completion flag [int, output]:
+	          0 = success,
+		 -1 = failure.
+
+ (4.3) To set various problem and solution parameters and
      allocate internal memory, make the following call:
 
        CALL FARKMALLOC(T0, Y0, IMEX, IATOL, RTOL, ATOL, IOUT,
@@ -245,263 +282,126 @@
      The arguments are:
         T0 = initial value of t [realtype, input]
 	Y0 = array of initial conditions [realtype, input]
-	IMEX = flag denoting integration method [int, input]: 
-                  0 = implicit, 
-                  1 = explicit, 
+	IMEX = flag denoting integration method [int, input]:
+                  0 = implicit,
+                  1 = explicit,
                   2 = imex
-        IATOL = type for absolute tolerance ATOL [int, input]: 
-                  1 = scalar, 
+        IATOL = type for absolute tolerance ATOL [int, input]:
+                  1 = scalar,
                   2 = array,
-                  3 = user-supplied function; the user must 
-                      supply a routine FARKEWT to compute the 
+                  3 = user-supplied function; the user must
+                      supply a routine FARKEWT to compute the
 		      error weight vector.
         RTOL = scalar relative tolerance [realtype, input]
 	ATOL = scalar/array absolute tolerance [realtype, input]
-	IOUT = array of length 22 for integer optional outputs
-	   [long int, output]
-	ROUT = array of length 6 for real optional outputs 
-	   [realtype, output]
+	IOUT = array of length at least 29 for integer optional 
+               outputs [long int, output]
+	ROUT = array of length at least 6 for real optional 
+               outputs [realtype, output]
 	IPAR = array of user integer data [long int, in/out]
 	RPAR = array with user real data [realtype, in/out]
 	IER  = return completion flag [int, output]:
                   0 = SUCCESS,
                  -1 = failure (see printed message for details).
 
-     The user data arrays IPAR and RPAR are passed unmodified to 
+     The user data arrays IPAR and RPAR are passed unmodified to
      all subsequent calls to user-provided routines. Changes to
-     either array inside a user-provided routine will be 
-     propagated. Using these two arrays, the user can dispense 
-     with COMMON blocks to pass data betwen user-provided 
-     routines. 
+     either array inside a user-provided routine will be
+     propagated. Using these two arrays, the user can dispense
+     with COMMON blocks to pass data betwen user-provided
+     routines.
 
- (4.3) Attach one of the SPILS linear solvers.
+ (4.4) Create the ARKSPILS interface to attach the generic 
+     iterative linear solver to ARKode, by making the following call:
     
- (4.3A) To specify the SPGMR (Scaled Preconditioned GMRES) 
-     linear solver make the following call:
-
-       CALL FARKSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)
-
-     The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
-	IER = error return flag [int, output]: 
-	       0 = success; 
-	      <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPGMR linear solver, then following the call to 
-     FARKREINIT, a call to the FARKSPGMRREINIT routine is needed
-     if any of IPRETYPE, IGSTYPE, DELT is being changed.  In that
-     case, call FARKSPGMRREINIT as follows:
-
-       CALL FARKSPGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPGMR.  If 
-     MAXL is being changed, then the user should call FARKSPGMR 
-     instead.
- 
- (4.3B) To specify the SPBCG (Scaled Preconditioned Bi-CGSTAB) 
-     linear solver make the following call:
-
-       CALL FARKSPBCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 
-              0 = default.
-       DELT = convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPBCG linear solver, then following the call to 
-     FARKREINIT, a call to the FARKSPBCGREINIT routine is needed
-     if any of its arguments is being changed.  The call is:
-
-       CALL FARKSPBCGREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKSPBCG.
-
- (4.3C) To specify the SPTFQMR (Scaled Preconditioned TFQMR) 
-     linear solver make the following call:
-
-       CALL FARKSPTFQMR(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 
-              0 = default.
-       DELT = convergence tolerance factor [realtype, input]
-	      0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPTFQMR linear solver, then following the call to
-     FARKREINIT, a call to the FARKSPTFQMRREINIT routine is 
-     needed if any of its arguments is being changed.  The call 
-     is:
-
-       CALL FARKSPTFQMRREINIT(IPRETYPE, MAXL, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPTFQMR.
-
- (4.3D) To specify the SPFGMR (Scaled Preconditioned Flexible GMRES) 
-     linear solver make the following call:
-
-       CALL FARKSPFGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)
+       CALL FARKSPILSINIT(IER)
 
      The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
 	IER = error return flag [int, output]: 
 	       0 = success; 
 	      <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPFGMR linear solver, then following the call to 
-     FARKREINIT, a call to the FARKSPFGMRREINIT routine is needed
-     if any of IPRETYPE, IGSTYPE, DELT is being changed.  In that
-     case, call FARKSPFGMRREINIT as follows:
-
-       CALL FARKSPFGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPFGMR.  If 
-     MAXL is being changed, then the user should call FARKSPFGMR 
-     instead.
- 
- (4.3E) To specify the PCG (Preconditioned Conjugate Gradient) 
-     linear solver make the following call:
-
-       CALL FARKPCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = use preconditioning
-       MAXL = maximum Krylov subspace dimension [int, input]; 
-              0 = default.
-       DELT = convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the PCG linear solver, then following the call to 
-     FARKREINIT, a call to the FARKPCGREINIT routine is needed
-     if any of its arguments is being changed.  The call is:
-
-       CALL FARKPCGREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKPCG.
 
- (4.4) To allocate memory and initialize data associated with the
+ (4.5) To allocate memory and initialize data associated with the
      ARKBBDPRE preconditioner, make the following call:
 
        CALL FARKBBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER)
- 
+
       The arguments are:
         NLOCAL = local vector size on this process 
-	     [long int, input]
+             [long int, input]
         MUDQ = upper half-bandwidth to be used in the computation
              of the local Jacobian blocks by difference 
-	     quotients.  These may be smaller than the true 
-	     half-bandwidths of the Jacobian of the local block 
-	     of g, when smaller values may provide greater 
-	     efficiency [long int, input]
+             quotients.  These may be smaller than the true 
+             half-bandwidths of the Jacobian of the local block 
+             of g, when smaller values may provide greater 
+             efficiency [long int, input]
         MLDQ = lower half-bandwidth to be used in the computation
              of the local Jacobian blocks by difference 
-	     quotients [long int, input]
-	MU = upper half-bandwidth of the band matrix that is
-	     retained as an approximation of the local Jacobian
-	     block (may be smaller than MUDQ) [long int, input]
-	ML = lower half-bandwidth of the band matrix that is
-	     retained as an approximation of the local Jacobian
-	     block (may be smaller than MLDQ) [long int, input]
-	DQRELY = relative increment factor in y for difference 
-	     quotients [realtype, input]
+             quotients [long int, input]
+        MU = upper half-bandwidth of the band matrix that is
+             retained as an approximation of the local Jacobian
+             block (may be smaller than MUDQ) [long int, input]
+        ML = lower half-bandwidth of the band matrix that is
+             retained as an approximation of the local Jacobian
+             block (may be smaller than MLDQ) [long int, input]
+        DQRELY = relative increment factor in y for difference 
+             quotients [realtype, input]
                     0.0 = default (sqrt(unit roundoff))
         IER = return completion flag [int, output]:
                     0 = success
                    <0 = an error occurred
 
- (4.5) To specify whether the Krylov linear solver should use the
-     supplied FARKJTIMES or the internal finite difference 
-     approximation, make the call
+ (4.6) To specify whether the Krylov linear solver should use the
+     supplied FARKJTSETUP and FARKJTIMES routines, or the internal 
+     finite difference approximation, make the call
 
         CALL FARKSPILSSETJAC(FLAG, IER)
 
-     with the int FLAG=1 to specify that FARKJTIMES is provided 
-     (FLAG=0 specifies to use and internal finite difference 
-     approximation to this product).  The int return flag IER=0
-     if successful, and nonzero otherwise.
+     with the int FLAG=1 to specify that FARKJTSETUP and FARKJTIMES 
+     are provided (FLAG=0 specifies to use and internal finite 
+     difference approximation to this product).  The int return 
+     flag IER=0 if successful, and nonzero otherwise.
  
  (5) Re-initialization: FARKREINIT, FARKBBDREINIT
 
      If a sequence of problems of the same size is being solved
-     using the Krylov linear solver in combination with the 
-     ARKBBDPRE preconditioner, then the ARKODE package can be 
+     using the Krylov linear solver in combination with the
+     ARKBBDPRE preconditioner, then the ARKODE package can be
      reinitialized for the second and subsequent problems so as
      to avoid further memory allocation.  First, in place of the
      call to FARKMALLOC, make the following call:
 
        CALL FARKREINIT(T0, Y0, IMEX, IATOL, RTOL, ATOL, IER)
 
-     The arguments have the same names and meanings as those of 
-     FARKMALLOC.  FARKREINIT performs the same initializations 
+     The arguments have the same names and meanings as those of
+     FARKMALLOC.  FARKREINIT performs the same initializations
      as FARKMALLOC, but does no memory allocation, using instead
-     the existing internal memory created by the previous 
-     FARKMALLOC call.  The subsequent call to specify the linear 
+     the existing internal memory created by the previous
+     FARKMALLOC call.  The subsequent call to specify the linear
      system solution method may or may not be needed.
 
-     If there is a change in any of the linear solver arguments,
-     then a call to FARKSPGMR, FARKSPBCG, FARKSPTFQMR, FARKSPFGMR
-     or FARKPCG must also be made; in this case the linear solver 
-     memory is reallocated. 
+     If there is no change in any of the linear solver or 
+     preconditioner arguments, then no additional calls are 
+     necessary.  
 
-     Following the call to FARKREINIT, a call to FARKBBDINIT may
-     or may not be needed.  If the input arguments are the same,
-     no FARKBBDINIT call is needed. If there is a change in input
-     arguments, then make the call
+     Following the call to FARKREINIT, if there is no change in 
+     any of the linear solver arguments, but the user wishes to 
+     modify the values of MUDQ, MLDQ or DQRELY from the previous 
+     call to FARKBBDINIT, then a user may call:
 
-       CALL FARKBBDREINIT(NLOCAL, MUDQ, MLDQ, DQRELY, IER)
- 
-     This reinitializes the BBD preconditioner, but without 
-     reallocating its memory.  The arguments of the have the same
-     names and meanings as FARKBBDINIT.  If the value of MU or ML
-     is being changed, then a call to FARKBBDINIT must be made.
+       CALL FARKBBDREINIT(MUDQ, MLDQ, DQRELY, IER)
+
+     The arguments have the same names and meanings as those of 
+     FARKBBDINIT.
+
+     However, if there is a change in any of the linear solver 
+     arguments or other preconditioner arguments, then a call to
+     FSUNPCGINIT, FSUNSPBCGSINIT, FSUNSPFGMRINIT, FSUNSPGMRINIT, 
+     or FSUNSPTFQMRINIT is required; in this case the linear 
+     solver memory is reallocated.  Following this call, the 
+     ARKSPILS interface must also be reconstructed using another
+     call to FARKSPILSINIT (interface memory is freed and 
+     reallocated), as well as a subsequent call to FARKBBDINIT.
  
  (6) The integrator: FARKODE
 
@@ -511,41 +411,42 @@
        CALL FARKODE(TOUT, T, Y, ITASK, IER)
 
      The arguments are:
-       TOUT = next value of t at which a solution is desired 
+       TOUT = next value of t at which a solution is desired
            [realtype, input]
        T = value of t reached by the solver [realtype, output]
-       Y = state variable array on output [realtype, output]
+       Y = state variable array [realtype, output]
        ITASK = task indicator [int, input]:
                  1 = normal mode (overshoot TOUT and interpolate)
-		 2 = one-step mode (return after each internal 
-		     step taken)
-		 3 = normal tstop mode (like 1, but integration 
-		     never proceeds past TSTOP, which must be 
-		     specified through a call to FARKSETRIN using
-		     the key 'STOP_TIME')
-		 4 = one step tstop (like 2, but integration 
-		     never goes past TSTOP)
-       IER = completion flag [int, output]: 
-                  0 = success, 
-		  1 = tstop return, 
-		  2 = root return, 
-                  values -1 ... -10 are failure modes (see 
-		     ARKODE manual).
-     The current values of the optional outputs are immediately 
+                 2 = one-step mode (return after each internal
+                     step taken)
+                 3 = normal tstop mode (like 1, but integration
+                     never proceeds past TSTOP, which must be
+                     specified through a call to FARKSETRIN using
+                     the key 'STOP_TIME')
+                 4 = one step tstop (like 2, but integration
+                     never goes past TSTOP)
+       IER = completion flag [int, output]:
+                  0 = success,
+                  1 = tstop return,
+                  2 = root return,
+                  values -1 ... -10 are failure modes (see
+                    ARKODE manual).
+     The current values of the optional outputs are immediately
      available in the IOUT and ROUT arrays.
- 
+
  (7) Optional outputs: FARKBBDOPT
 
-     Optional outputs specific to the SP* linear solvers are:
-        LENRWLS = IOUT(14) from ARKSp*GetWorkSpace (real space)
-        LENIWLS = IOUT(15) from ARKSp*GetWorkSpace (int space)
-        LSTF    = IOUT(16) from ARKSp*GetLastFlag
-        NFELS   = IOUT(17) from ARKSp*GetRhsEvals
-        NJTV    = IOUT(18) from ARKSp*GetJtimesEvals
-        NPE     = IOUT(19) from ARKSp*GetPrecEvals
-        NPS     = IOUT(20) from ARKSp*GetPrecSolves
-        NLI     = IOUT(21) from ARKSp*GetLinIters
-        NCFL    = IOUT(22) from ARKSp*GetConvFails
+     Optional outputs specific to the ARKSpils linear solver
+     interface are:
+        LENRWLS = IOUT(14) from ARKSpilsGetWorkSpace
+        LENIWLS = IOUT(15) from ARKSpilsGetWorkSpace
+        LSTF    = IOUT(16) from ARKSpilsGetLastFlag
+        NFELS   = IOUT(17) from ARKSpilsGetNumRhsEvals
+        NJTV    = IOUT(18) from ARKSpilsGetNumJtimesEvals
+        NPE     = IOUT(19) from ARKSpilsGetNumPrecEvals
+        NPS     = IOUT(20) from ARKSpilsGetNumPrecSolves
+        NLI     = IOUT(21) from ARKSpilsGetNumLinIters
+        NCFL    = IOUT(22) from ARKSpilsGetNumConvFails
      See the ARKODE manual for descriptions.
 
      To obtain the optional outputs associated with the ARKBBDPRE
@@ -554,36 +455,36 @@
        CALL FARKBBDOPT(LENRWBBD, LENIWBBD, NGEBBD)
 
      The arguments returned are:
-       LENRWBP = length of real preconditioner work space, in 
-           realtype words (this size is local to the current 
+       LENRWBP = length of real preconditioner work space, in
+           realtype words (this size is local to the current
 	   processor if run in parallel) [long int, output]
        LENIWBP = length of integer preconditioner work space, in
            integer words (processor-local) [long int, output]
        NGEBBD = number of g(t,y) evaluations (calls to ARKLOCFN)
            so far [long int, output]
- 
+
  (8) Computing solution derivatives: FARKDKY
 
-     To obtain a derivative of the solution, of order up to the 
+     To obtain a derivative of the solution, of order up to the
      method order, make the following call:
 
        CALL FARKDKY(T, K, DKY, IER)
 
      The arguments are:
-       T = time at which solution derivative is desired, within 
+       T = time at which solution derivative is desired, within
            the interval [TCUR-HU,TCUR], [realtype, input].
        K = derivative order (0 .le. K .le. QU) [int, input]
-       DKY = array containing computed K-th derivative of y 
+       DKY = array containing computed K-th derivative of y
            [realtype, output]
-       IER = return flag [int, output]: 
+       IER = return flag [int, output]:
                     0 = success
-		   <0 = illegal argument.
+                   <0 = illegal argument.
  
  (9) Memory freeing: FARKFREE
 
-     To free the internal memory created by the calls to 
-     FARKMALLOC, FNVINITS or FNVINITP, and FARKBPINIT, make the
-     call:
+     To free the internal memory created by the calls to
+     FARKMALLOC, FNVINITP, FARKSPILSINIT and FARKBBDINIT,
+     make the call:
 
        CALL FARKFREE()
 
@@ -620,16 +521,16 @@ extern "C" {
 #endif
 
 /* Prototypes of exported functions */
-void FARK_BBDINIT(long int *Nloc, long int *mudq, 
-		  long int *mldq, long int *mu, 
+void FARK_BBDINIT(long int *Nloc, long int *mudq,
+		  long int *mldq, long int *mu,
 		  long int *ml, realtype* dqrely, int *ier);
-void FARK_BBDREINIT(long int *Nloc, long int *mudq, 
-		    long int *mldq, realtype* dqrely, int *ier);
-void FARK_BBDOPT(long int *lenrwbbd, long int *leniwbbd, 
+void FARK_BBDREINIT(long int *mudq, long int *mldq,
+		    realtype* dqrely, int *ier);
+void FARK_BBDOPT(long int *lenrwbbd, long int *leniwbbd,
 		 long int *ngebbd);
 
 /* Prototypes: Functions Called by the ARKBBDPRE Module */
-int FARKgloc(long int Nloc, realtype t, N_Vector yloc, 
+int FARKgloc(long int Nloc, realtype t, N_Vector yloc,
 	     N_Vector gloc, void *user_data);
 int FARKcfn(long int Nloc, realtype t, N_Vector y, 
 	    void *user_data);
diff --git a/src/arkode/fcmix/farkbp.c b/src/arkode/fcmix/farkbp.c
index e8b8909..bb3701b 100644
--- a/src/arkode/fcmix/farkbp.c
+++ b/src/arkode/fcmix/farkbp.c
@@ -2,22 +2,22 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * This module contains the routines necessary to interface with 
- * the ARKBANDPRE module and user-supplied Fortran routines. The 
- * routines here call the generically named routines and provide 
+ * This module contains the routines necessary to interface with
+ * the ARKBANDPRE module and user-supplied Fortran routines. The
+ * routines here call the generically named routines and provide
  * a standard interface to the C code of the ARKBANDPRE package.
  *--------------------------------------------------------------*/
 
@@ -29,9 +29,9 @@
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKBandPrecInit; see farkbp.h 
+/* Fortran interface to C routine ARKBandPrecInit; see farkbp.h
    for additional information */
-void FARK_BPINIT(long int *N, long int *mu, 
+void FARK_BPINIT(long int *N, long int *mu,
 		 long int *ml, int *ier)
 {
   *ier = ARKBandPrecInit(ARK_arkodemem, *N, *mu, *ml);
@@ -40,8 +40,8 @@ void FARK_BPINIT(long int *N, long int *mu,
 
 /*=============================================================*/
 
-/* Fortran interface to C routines ARKBandPrecGetWorkSpace and 
-   ARKBandPrecGetNumRhsEvals; see farkbp.h for additional 
+/* Fortran interface to C routines ARKBandPrecGetWorkSpace and
+   ARKBandPrecGetNumRhsEvals; see farkbp.h for additional
    information */
 void FARK_BPOPT(long int *lenrwbp, long int *leniwbp, long int *nfebp)
 {
diff --git a/src/arkode/fcmix/farkbp.h b/src/arkode/fcmix/farkbp.h
index 682ffc2..6f7c79f 100644
--- a/src/arkode/fcmix/farkbp.h
+++ b/src/arkode/fcmix/farkbp.h
@@ -2,13 +2,13 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
@@ -23,20 +23,19 @@
                   FARKBP Interface Package
 
  The FARKBP Interface Package is a package of C functions which,
- together with the FARKODE Interface Package, support the use of 
- the ARKODE solver and N_VSerial vector module with the ARKBANDPRE
- preconditioner module, for the solution of ODE systems in a mixed
- Fortran/C setting.  The combination of ARKODE and ARKBANDPRE 
- solves the linear systems arising from the solution of the 
- implicit portions of the ODE system
-       dy/dt = fe(t,y) + fi(t,y)  
- using a Krylov iterative linear solver (SPGMR, SPTFQMR, SPBCG, 
- SPFGMR or PCG), and with a banded preconditioner.  This 
- preconditioner can be constructed using either a user-supplied 
- routine, or automatically via finite differencing.
+ together with the FARKODE Interface Package, support the use of
+ the ARKODE solver and serial, OpenMP or PThreads vector module
+ with the ARKBANDPRE preconditioner module, for the solution of
+ ODE systems in a mixed Fortran/C setting.  The combination of
+ ARKODE and ARKBANDPRE solves the linear systems arising from the
+ solution of the implicit portions of the ODE system
+       dy/dt = fe(t,y) + fi(t,y)
+ using a Krylov iterative linear solver via the ARKSPILS
+ interface, and with a banded difference quotient Jacobian-based
+ preconditioner.
  
- The user-callable functions in this package, with the 
- corresponding ARKODE and ARKBBDPRE functions, are as follows: 
+ The user-callable functions in this package, with the
+ corresponding ARKODE and ARKBBDPRE functions, are as follows:
 
    Fortran              ARKODE
    -------------        ---------------------------
@@ -44,73 +43,95 @@
    FARKBPOPT            (accesses optional outputs)
    -------------        ---------------------------
  
- In addition to the Fortran implicit right-hand side function 
- FARKIFUN, the user may (optionally) supply a routine FARKJTIMES 
- that is called by the C interface function FARKJtimes of type 
- ARKSpilsJtimesFn.  
+ In addition to the Fortran implicit right-hand side function
+ FARKIFUN, the user may (optionally) supply routines FARKJTSETUP
+ and FARKJTIMES that are called by the C interface function
+ FARKJTSetup of type ARKSpilsJTSetupFn and the interface function
+ FARKJtimes of type ARKSpilsJtimesFn.
 
- 
  Important notes on portability:
 
- The names of all user-supplied routines here are fixed, in 
- order to maximize portability for the resulting mixed-language 
+ The names of all user-supplied routines here are fixed, in
+ order to maximize portability for the resulting mixed-language
  program.
 
- Additionally, the names of the interface functions, and the 
- names of the Fortran user routines called by them, appear as 
- dummy names which are mapped to actual values by a series of 
+ Additionally, the names of the interface functions, and the
+ names of the Fortran user routines called by them, appear as
+ dummy names which are mapped to actual values by a series of
  definitions in the header file farkbp.h.
- 
+
  ================================================================
- 
+
            Usage of the FARKODE/FARKBP Interface Packages
- 
- The usage of the combined interface packages FARKODE and FARKBP 
- requires calls to seven to ten interface functions, and one or 
- two user-supplied routines which define the problem to be solved
- and indirectly define the preconditioner.  These function calls 
+
+ The usage of the combined interface packages FARKODE and FARKBP
+ requires calls to a variety of interface functions, and one or
+ more user-supplied routines which define the problem to be solved
+ and indirectly define the preconditioner.  These function calls
  and user routines are summarized separately below.
- 
+
  Some details are omitted, and the user is referred to the ARKODE
  user document for more complete information.
- 
+
  (1) User-supplied implicit right-hand side routine: FARKIFUN
-     If any portion of the ODE system should be treated 
-     implicitly (and hence would require a linear solver at all),
+     If any portion of the ODE system should be treated
+     implicitly (and hence would require a linear solve),
      the user must supply the following Fortran routine:
 
        SUBROUTINE FARKIFUN(T, Y, YDOT, IPAR, RPAR, IER)
 
-     Sets the YDOT array to fi(T,Y), the implicit portion of the 
+     Sets the YDOT array to fi(T,Y), the implicit portion of the
      right-hand side of the ODE system, as function of time T and
      the state variable array Y.
 
      The arguments are:
        Y    -- array containing state variables [realtype, input]
-       YDOT -- array containing state derivatives [realtype, 
+       YDOT -- array containing state derivatives [realtype,
                output]
        IPAR -- array containing integer user data that was passed
                to FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                  >0 if a recoverable error occurred,
                  <0 if an unrecoverable error ocurred.
  
- (2) Optional user-supplied Jacobian-vector product: FARKJTIMES
+ (2) Optional user-supplied Jacobian-vector setup and product 
+     functions: FARKJTSETUP and FARKJTIMES
+
+     As an option, the user may supply a routine that computes
+     the product of the system Jacobian  J = dfi(t,y)/dy and a
+     given vector v.  If supplied, a 'setup' routine to prepare
+     any user data structures must exist, and have the form:
+ 
+       SUBROUTINE FARKJTSETUP(T, Y, FY, H, IPAR, RPAR, IER)
+
+     Typically this routine will use only T and Y.  It must perform any
+     relevant preparations for subsequent calls to the user-provided
+     FARKJTIMES routine (see below).
 
-     As an option, the user may supply a routine that computes 
-     the product of the system Jacobian  J = dfi(t,y)/dy and a 
-     given vector v.  If supplied, it must have the following 
-     form:
+     The arguments are:
+       T    -- current time [realtype, input]
+       Y    -- array containing state variables [realtype, input]
+       FY   -- array containing state derivatives [realtype, input]
+       H    -- current step size [realtype, input]
+       IPAR -- array containing integer user data that was passed to
+               FARKMALLOC [long int, input]
+       RPAR -- array containing real user data that was passed to
+               FARKMALLOC [realtype, input]
+       IER  -- return flag [int, output]:
+                  0 if successful,
+                  nonzero if an error.
+ 
+     The accompanying Jacobian matrix-vector product routine must
+     have the following form:
 
-       SUBROUTINE FARKJTIMES(V, FJV, T, Y, FY, H, IPAR, RPAR, 
-      &                      WORK, IER)
+       SUBROUTINE FARKJTIMES(V, FJV, T, Y, FY, H, IPAR, RPAR, WORK, IER)
 
-     Typically this routine will use only NEQ, T, Y, V, and FJV. 
-     It must compute the product vector J*v where the vector V, 
-     and store the product in FJV.  
+     Typically this routine will use only NEQ, T, Y, V, and FJV.
+     It must compute the product vector J*v where the vector V,
+     and store the product in FJV.
 
      The arguments are:
        V    -- vector to multiply [realtype, input]
@@ -126,25 +147,54 @@
        WORK -- array containing temporary workspace of same size
                as Y [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                   nonzero if an error.
 
- (3) Initialization:  FNVINITS, FARKMALLOC, linear solver 
-     initialization, and FARKBPINIT.
+ (3) Initialization:  FNVINITS / FNVINITOMP / FNVINITPTS,
+     generic linear solver initialization, FARKMALLOC, FARKSPILSINIT,
+     and FARKBPINIT.
  
- (3.1) To initialize the serial vector specification, the user 
-      must make the following call:
+ (3.1) To initialize the vector specification, the user must make
+     one of the following calls:
 
-        CALL FNVINITS(4, NEQ, IER)
+       (serial)
+          CALL FNVINITS(4, NEQ, IER)
+       (OpenMP threaded)
+          CALL FNVINITOMP(4, NEQ, NUM_THREADS, IER)
+       (PThreads threaded)
+          CALL FNVINITPTS(4, NEQ, NUM_THREADS, IER)
 
-     where the first argument is an int containing the ARKODE 
+     where the first argument is an int containing the ARKODE
      solver ID (4). The other arguments are:
         NEQ = size of vectors [long int, input]
-	IER = return completion flag [int, output]:
+        NUM_THREADS = number of threads
+        IER = return completion flag [int, output]:
 	          0 = success, 
 		 -1 = failure.
  
- (3.2) To set various problem and solution parameters and 
+ (3.2) To initialize a generic iterative linear solver structure for 
+     solving linear systems arising from implicit or IMEX treatment 
+     of the IVP, the user must make one of the following calls:
+
+          CALL FSUNPCGINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPBCGSINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPFGMRINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPGMRINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPTFQMRINIT(4, PRETYPE, MAXL, IER)
+
+     In each of these, one argument is an int containing the ARKODE solver 
+     ID (4). 
+
+     The other arguments are:
+
+        PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+           2=right, 3=both) [int, input]
+        MAXL = maximum Krylov subspace dimension [int, input]
+	IER = return completion flag [int, output]:
+	          0 = success,
+		 -1 = failure.
+
+ (3.3) To set various problem and solution parameters and
      allocate internal memory, make the following call:
 
        CALL FARKMALLOC(T0, Y0, IMEX, IATOL, RTOL, ATOL, IOUT,
@@ -153,21 +203,21 @@
      The arguments are:
         T0 = initial value of t [realtype, input]
 	Y0 = array of initial conditions [realtype, input]
-	IMEX = flag denoting integration method [int, input]: 
-                  0 = implicit, 
-                  1 = explicit, 
+	IMEX = flag denoting integration method [int, input]:
+                  0 = implicit,
+                  1 = explicit,
                   2 = imex
-        IATOL = type for absolute tolerance ATOL [int, input]: 
-                  1 = scalar, 
+        IATOL = type for absolute tolerance ATOL [int, input]:
+                  1 = scalar,
                   2 = array,
-                  3 = user-supplied function; the user must 
-                      supply a routine FARKEWT to compute the 
+                  3 = user-supplied function; the user must
+                      supply a routine FARKEWT to compute the
 		      error weight vector.
         RTOL = scalar relative tolerance [realtype, input]
 	ATOL = scalar/array absolute tolerance [realtype, input]
 	IOUT = array of length 22 for integer optional outputs
 	   [long int, output]
-	ROUT = array of length 6 for real optional outputs 
+	ROUT = array of length 6 for real optional outputs
 	   [realtype, output]
 	IPAR = array of user integer data [long int, in/out]
 	RPAR = array with user real data [realtype, in/out]
@@ -175,192 +225,49 @@
                   0 = SUCCESS,
                  -1 = failure (see printed message for details).
 
-     The user data arrays IPAR and RPAR are passed unmodified to 
+     The user data arrays IPAR and RPAR are passed unmodified to
      all subsequent calls to user-provided routines. Changes to
-     either array inside a user-provided routine will be 
-     propagated. Using these two arrays, the user can dispense 
-     with COMMON blocks to pass data betwen user-provided 
-     routines. 
-
- (3.3) Attach one of the 3 SPILS linear solvers.
-    
- (3.3A) To specify the SPGMR (Scaled Preconditioned GMRES) 
-     linear solver make the following call:
-
-       CALL FARKSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)
-
-     The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
-	IER = error return flag [int, output]: 
-	       0 = success; 
-	      <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPGMR linear solver, then following the call to 
-     FARKREINIT, a call to the FARKSPGMRREINIT routine is needed
-     if any of IPRETYPE, IGSTYPE, DELT is being changed.  In that
-     case, call FARKSPGMRREINIT as follows:
-
-       CALL FARKSPGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPGMR.  If 
-     MAXL is being changed, then the user should call FARKSPGMR 
-     instead.
- 
- (3.3B) To specify the SPBCG (Scaled Preconditioned Bi-CGSTAB) 
-     linear solver make the following call:
-
-       CALL FARKSPBCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 
-              0 = default.
-       DELT = convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPBCG linear solver, then following the call to 
-     FARKREINIT, a call to the FARKSPBCGREINIT routine is needed
-     if any of its arguments is being changed.  The call is:
-
-       CALL FARKSPBCGREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKSPBCG.
-
- (3.3C) To specify the SPTFQMR (Scaled Preconditioned TFQMR) 
-     linear solver make the following call:
-
-       CALL FARKSPTFQMR(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 
-              0 = default.
-       DELT = convergence tolerance factor [realtype, input]
-	      0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPTFQMR linear solver, then following the call to
-     FARKREINIT, a call to the FARKSPTFQMRREINIT routine is 
-     needed if any of its arguments is being changed.  The call 
-     is:
-
-       CALL FARKSPTFQMRREINIT(IPRETYPE, MAXL, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPTFQMR.
+     either array inside a user-provided routine will be
+     propagated. Using these two arrays, the user can dispense
+     with COMMON blocks to pass data betwen user-provided
+     routines.
 
- (3.3D) To specify the SPFGMR (Scaled Preconditioned Flexible GMRES) 
-     linear solver make the following call:
+ (3.4) Create the ARKSPILS interface to attach the generic
+     iterative linear solver to ARKode, by making the following call:
 
-       CALL FARKSPFGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)
+       CALL FARKSPILSINIT(IER)
 
      The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
-	IER = error return flag [int, output]: 
-	       0 = success; 
+	IER = error return flag [int, output]:
+	       0 = success;
 	      <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the SPFGMR linear solver, then following the call to 
-     FARKREINIT, a call to the FARKSPFGMRREINIT routine is needed
-     if any of IPRETYPE, IGSTYPE, DELT is being changed.  In that
-     case, call FARKSPFGMRREINIT as follows:
-
-       CALL FARKSPFGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPFGMR.  If 
-     MAXL is being changed, then the user should call FARKSPFGMR 
-     instead.
- 
- (3.3E) To specify the PCG (Preconditioned Conjugate Gradient) 
-     linear solver make the following call:
-
-       CALL FARKPCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = use preconditioning
-       MAXL = maximum Krylov subspace dimension [int, input]; 
-              0 = default.
-       DELT = convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     If a sequence of problems of the same size is being solved 
-     using the PCG linear solver, then following the call to 
-     FARKREINIT, a call to the FARKPCGREINIT routine is needed
-     if any of its arguments is being changed.  The call is:
-
-       CALL FARKPCGREINIT(IPRETYPE, MAXL, DELT, IER)              
 
-     The arguments have the same meanings as for FARKPCG.
-
- (3.4) To allocate memory and initialize data associated with the
+ (3.5) To allocate memory and initialize data associated with the
       ARKBANDPRE preconditioner, make the following call:
 
         CALL FARKBPINIT(NEQ, MU, ML, IER)
 
       The arguments are:
         NEQ = problem size [long int, input]
-        MU = upper half-bandwidth of the band matrix that is 
-	     retained as an approximation of the Jacobian 
-	     [long int, input]
+        MU = upper half-bandwidth of the band matrix that is
+             retained as an approximation of the Jacobian
+             [long int, input]
         ML = lower half-bandwidth of the band matrix approximant
-	     to the Jacobian [long int, input]
+             to the Jacobian [long int, input]
         IER = return completion flag [int, output]:
                     0 = success
                    <0 = an error occurred
 
- (3.5) To specify whether the Krylov linear solver should use the
-     supplied FARKJTIMES or the internal finite difference 
-     approximation, make the call
+ (3.6) To specify whether the Krylov linear solver should use the
+     supplied FARKJTSETUP and FARKJTIMES routines, or the internal
+     finite difference approximation, make the call
 
         CALL FARKSPILSSETJAC(FLAG, IER)
 
-     with the int FLAG=1 to specify that FARKJTIMES is provided 
-     (FLAG=0 specifies to use and internal finite difference 
-     approximation to this product).  The int return flag IER=0
-     if successful, and nonzero otherwise.
+     with the int FLAG=1 to specify that FARKJTSETUP and FARKJTIMES 
+     are provided (FLAG=0 specifies to use and internal finite 
+     difference approximation to this product).  The int return
+     flag IER=0 if successful, and nonzero otherwise.
  
  (4) The integrator: FARKODE
 
@@ -370,81 +277,81 @@
        CALL FARKODE(TOUT, T, Y, ITASK, IER)
 
      The arguments are:
-       TOUT = next value of t at which a solution is desired 
+       TOUT = next value of t at which a solution is desired
            [realtype, input]
        T = value of t reached by the solver [realtype, output]
        Y = state variable array on output [realtype, output]
        ITASK = task indicator [int, input]:
                  1 = normal mode (overshoot TOUT and interpolate)
-		 2 = one-step mode (return after each internal 
+		 2 = one-step mode (return after each internal
 		     step taken)
-		 3 = normal tstop mode (like 1, but integration 
-		     never proceeds past TSTOP, which must be 
+		 3 = normal tstop mode (like 1, but integration
+		     never proceeds past TSTOP, which must be
 		     specified through a call to FARKSETRIN using
 		     the key 'STOP_TIME')
-		 4 = one step tstop (like 2, but integration 
+		 4 = one step tstop (like 2, but integration
 		     never goes past TSTOP)
-       IER = completion flag [int, output]: 
-                  0 = success, 
-		  1 = tstop return, 
-		  2 = root return, 
-                  values -1 ... -10 are failure modes (see 
+       IER = completion flag [int, output]:
+                  0 = success,
+		  1 = tstop return,
+		  2 = root return,
+                  values -1 ... -10 are failure modes (see
 		     ARKODE manual).
-     The current values of the optional outputs are immediately 
+     The current values of the optional outputs are immediately
      available in the IOUT and ROUT arrays.
- 
+
  (5) Optional outputs: FARKBPOPT
 
      Optional outputs specific to the SP* linear solvers are:
-        LENRWLS = IOUT(14) from ARKSp*GetWorkSpace (real space)
-        LENIWLS = IOUT(15) from ARKSp*GetWorkSpace (int space)
-        LSTF    = IOUT(16) from ARKSp*GetLastFlag
-        NFELS   = IOUT(17) from ARKSp*GetRhsEvals
-        NJTV    = IOUT(18) from ARKSp*GetJtimesEvals
-        NPE     = IOUT(19) from ARKSp*GetPrecEvals
-        NPS     = IOUT(20) from ARKSp*GetPrecSolves
-        NLI     = IOUT(21) from ARKSp*GetLinIters
-        NCFL    = IOUT(22) from ARKSp*GetConvFails
+        LENRWLS = IOUT(14) from ARKSpilsGetWorkSpace
+        LENIWLS = IOUT(15) from ARKSpilsGetWorkSpace
+        LSTF    = IOUT(16) from ARKSpilsGetLastFlag
+        NFELS   = IOUT(17) from ARKSpilsGetNumRhsEvals
+        NJTV    = IOUT(18) from ARKSpilsGetNumJtimesEvals
+        NPE     = IOUT(19) from ARKSpilsGetNumPrecEvals
+        NPS     = IOUT(20) from ARKSpilsGetNumPrecSolves
+        NLI     = IOUT(21) from ARKSpilsGetNumLinIters
+        NCFL    = IOUT(22) from ARKSpilsGetNumConvFails
      See the ARKODE manual for descriptions.
 
-     To obtain the optional outputs associated with the 
+     To obtain the optional outputs associated with the
      ARKBANDPRE module, make the following call:
 
        CALL FARKBPOPT(LENRWBP, LENIWBP, NFEBP)
 
      The arguments returned are:
-       LENRWBP = length of real preconditioner work space, in 
-           realtype words (this size is local to the current 
+       LENRWBP = length of real preconditioner work space, in
+           realtype words (this size is local to the current
 	   processor if run in parallel) [long int, output]
        LENIWBP = length of integer preconditioner work space, in
            integer words (processor-local) [long int, output]
        NFEBP = number of fi(t,y) evaluations [long int, output]
- 
+
  (6) Computing solution derivatives: FARKDKY
 
-     To obtain a derivative of the solution, of order up to the 
+     To obtain a derivative of the solution, of order up to the
      method order, make the following call:
 
        CALL FARKDKY(T, K, DKY, IER)
 
      The arguments are:
-       T = time at which solution derivative is desired, within 
+       T = time at which solution derivative is desired, within
            the interval [TCUR-HU,TCUR], [realtype, input].
        K = derivative order (0 .le. K .le. QU) [int, input]
-       DKY = array containing computed K-th derivative of y 
+       DKY = array containing computed K-th derivative of y
            [realtype, output]
-       IER = return flag [int, output]: 
+       IER = return flag [int, output]:
                     0 = success
 		   <0 = illegal argument.
- 
+
  (7) Memory freeing: FARKFREE
 
-     To free the internal memory created by the calls to 
-     FARKMALLOC, FNVINITS or FNVINITP, and FARKBPINIT, make the
-     call:
+     To free the internal memory created by the calls to
+     FARKMALLOC, FNVINITS / FNVINITOMP / FNVINITPTS,
+     FARKSPILSINIT and FARKBPINIT, make the call:
 
        CALL FARKFREE()
- 
+
 ===============================================================*/
 
 #ifndef _FARKBP_H
@@ -462,7 +369,7 @@ extern "C" {
 #if defined(SUNDIALS_F77_FUNC)
 
 #define FARK_BPINIT    SUNDIALS_F77_FUNC(farkbpinit, FARKBPINIT)
-#define FARK_BPOPT     SUNDIALS_F77_FUNC(farkbpopt, FARKBPOPT)
+#define FARK_BPOPT     SUNDIALS_F77_FUNC(farkbpopt,  FARKBPOPT)
 
 #else
 
@@ -472,12 +379,12 @@ extern "C" {
 #endif
 
 /* Prototypes of exported function */
-void FARK_BPINIT(long int *N, 
-		 long int *mu, 
-		 long int *ml, 
+void FARK_BPINIT(long int *N,
+		 long int *mu,
+		 long int *ml,
 		 int *ier);
-void FARK_BPOPT(long int *lenrwbp, 
-		long int *leniwbp, 
+void FARK_BPOPT(long int *lenrwbp,
+		long int *leniwbp,
 		long int *nfebp);
 
 #ifdef __cplusplus
diff --git a/src/arkode/fcmix/farkdense.c b/src/arkode/fcmix/farkdense.c
index fcb1a9b..d441298 100644
--- a/src/arkode/fcmix/farkdense.c
+++ b/src/arkode/fcmix/farkdense.c
@@ -2,20 +2,20 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKDENSE, for the case
+ * Fortran/C interface routines for ARKODE/ARKDLS, for the case
  * of a user-supplied Jacobian approximation routine.
  *--------------------------------------------------------------*/
 
@@ -23,7 +23,8 @@
 #include <stdlib.h>
 #include "farkode.h"
 #include "arkode_impl.h"
-#include <arkode/arkode_dense.h>
+#include <arkode/arkode_direct.h>
+#include <sunmatrix/sunmatrix_dense.h>
 
 /*=============================================================*/
 
@@ -34,9 +35,9 @@ extern "C" {
 #endif
 
   extern void FARK_DJAC(long int *N, realtype *T, realtype *Y, 
-			realtype *FY, realtype *DJAC, 
-			realtype *H, long int *IPAR, 
-			realtype *RPAR, realtype *V1, 
+			realtype *FY, realtype *DJAC,
+			realtype *H, long int *IPAR,
+			realtype *RPAR, realtype *V1,
 			realtype *V2, realtype *V3, int *ier);
 
 #ifdef __cplusplus
@@ -45,30 +46,34 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKDlsSetDenseJacFn; see 
+/* Fortran interface to C routine ARKDlsSetJacFn; see
    farkode.h for additional information */
 void FARK_DENSESETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = ARKDlsSetDenseJacFn(ARK_arkodemem, NULL);
+    *ier = ARKDlsSetJacFn(ARK_arkodemem, NULL);
   } else {
-    *ier = ARKDlsSetDenseJacFn(ARK_arkodemem, FARKDenseJac);
+    *ier = ARKDlsSetJacFn(ARK_arkodemem, FARKDenseJac);
   }
   return;
 }
 
 /*=============================================================*/
 
-/* C interface to user-supplied Fortran routine FARKDJAC; see 
+/* C interface to user-supplied Fortran routine FARKDJAC; see
    farkode.h for additional information  */
-int FARKDenseJac(long int N, realtype t, N_Vector y, N_Vector fy, 
-                 DlsMat J, void *user_data, N_Vector vtemp1, 
-                 N_Vector vtemp2, N_Vector vtemp3)
+int FARKDenseJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+                 void *user_data, N_Vector vtemp1, N_Vector vtemp2,
+                 N_Vector vtemp3)
 {
-  int ier;
   realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
   realtype h;
+  long int N;
   FARKUserData ARK_userdata;
+  int ier = 0;
+
+  /* Initialize all pointers to NULL */
+  ydata = fydata = jacdata = v1data = v2data = v3data = NULL;
 
   ARKodeGetLastStep(ARK_arkodemem, &h);
   ydata   = N_VGetArrayPointer(y);
@@ -76,12 +81,13 @@ int FARKDenseJac(long int N, realtype t, N_Vector y, N_Vector fy,
   v1data  = N_VGetArrayPointer(vtemp1);
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
-  jacdata = DENSE_COL(J,0);
+  N       = SUNDenseMatrix_Columns(J);
+  jacdata = SUNDenseMatrix_Column(J,0);
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_DJAC(&N, &t, ydata, fydata, jacdata, &h, 
-            ARK_userdata->ipar, ARK_userdata->rpar, v1data, 
-            v2data, v3data, &ier); 
+  FARK_DJAC(&N, &t, ydata, fydata, jacdata, &h,
+            ARK_userdata->ipar, ARK_userdata->rpar, v1data,
+            v2data, v3data, &ier);
   return(ier);
 }
 
diff --git a/src/arkode/fcmix/farkdensemass.c b/src/arkode/fcmix/farkdensemass.c
index 3a0253d..a458eed 100644
--- a/src/arkode/fcmix/farkdensemass.c
+++ b/src/arkode/fcmix/farkdensemass.c
@@ -2,28 +2,29 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKDENSE, for the case
- * of a user-supplied Jacobian approximation routine.
+ * Fortran/C interface routines for ARKODE/ARKDLS, for the case
+ * of a user-supplied mass-matrix approximation routine.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "farkode.h"
 #include "arkode_impl.h"
-#include <arkode/arkode_dense.h>
+#include <arkode/arkode_direct.h>
+#include <sunmatrix/sunmatrix_dense.h>
 
 /*=============================================================*/
 
@@ -33,9 +34,9 @@
 extern "C" {
 #endif
 
-  extern void FARK_DMASS(long int *N, realtype *T, 
-			 realtype *DMASS, long int *IPAR, 
-			 realtype *RPAR, realtype *V1, 
+  extern void FARK_DMASS(long int *N, realtype *T,
+			 realtype *DMASS, long int *IPAR,
+			 realtype *RPAR, realtype *V1,
 			 realtype *V2, realtype *V3, int *ier);
 
 #ifdef __cplusplus
@@ -44,32 +45,34 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface routine to ARKDlsSetDenseMassFn; see 
+/* Fortran interface routine to ARKDlsSetMassFn; see
    farkode.h for further details */
 void FARK_DENSESETMASS(int *ier)
 {
-  *ier = ARKDlsSetDenseMassFn(ARK_arkodemem, FARKDenseMass);
+  *ier = ARKDlsSetMassFn(ARK_arkodemem, FARKDenseMass);
 }
 
 /*=============================================================*/
 
-/* C interface to user-supplied Fortran routine FARKDMASS; see 
+/* C interface to user-supplied Fortran routine FARKDMASS; see
    farkode.h for additional information  */
-int FARKDenseMass(long int N, realtype t, DlsMat M, void *user_data, 
+int FARKDenseMass(realtype t, SUNMatrix M, void *user_data,
 		  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
 {
   int ier;
   realtype *massdata, *v1data, *v2data, *v3data;
+  long int N;
   FARKUserData ARK_userdata;
 
   v1data  = N_VGetArrayPointer(vtemp1);
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
-  massdata = DENSE_COL(M,0);
+  N = SUNDenseMatrix_Columns(M);
+  massdata = SUNDenseMatrix_Column(M,0);
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_DMASS(&N, &t, massdata, ARK_userdata->ipar, ARK_userdata->rpar, 
-	     v1data, v2data, v3data, &ier); 
+  FARK_DMASS(&N, &t, massdata, ARK_userdata->ipar, ARK_userdata->rpar,
+	     v1data, v2data, v3data, &ier);
   return(ier);
 }
 
diff --git a/src/arkode/fcmix/farkjtimes.c b/src/arkode/fcmix/farkjtimes.c
index f9ebdcf..a6d5818 100644
--- a/src/arkode/fcmix/farkjtimes.c
+++ b/src/arkode/fcmix/farkjtimes.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,10 +15,11 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * The C function FARKJtimes is to interface between the ARKSP* 
- * modules and the user-supplied Jacobian-vector product routine
- * FARKJTIMES. Note the use of the generic name FARK_JTIMES in
- * the code below.
+ * The C functions FARKJTSetup and FARKJtimes are to interface 
+ * between the ARKSPILS module and the user-supplied 
+ * Jacobian-vector product routines FARKJTSETUP and FARKJTIMES. 
+ * Note the use of the generic names FARK_JTSETUP and FARK_JTIMES 
+ * in the code below.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -35,6 +36,10 @@
 extern "C" {
 #endif
 
+  extern void FARK_JTSETUP(realtype *T, realtype *Y, realtype *FY, 
+                           realtype *H, long int *IPAR, 
+                           realtype *RPAR, int *IER);
+
   extern void FARK_JTIMES(realtype *V, realtype *JV, realtype *T, 
 			  realtype *Y, realtype *FY, realtype *H,
 			  long int *IPAR, realtype *RPAR,
@@ -46,20 +51,42 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKSpilsSetJacTimesVecFn; see 
+/* Fortran interface to C routine ARKSpilsSetJacTimes; see 
    farkode.h for further information */
 void FARK_SPILSSETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = ARKSpilsSetJacTimesVecFn(ARK_arkodemem, NULL);
+    *ier = ARKSpilsSetJacTimes(ARK_arkodemem, NULL, NULL);
   } else {
-    *ier = ARKSpilsSetJacTimesVecFn(ARK_arkodemem, FARKJtimes);
+    *ier = ARKSpilsSetJacTimes(ARK_arkodemem, FARKJTSetup, FARKJtimes);
   }
   return;
 }
 
 /*=============================================================*/
 
+/* C interface to user-supplied Fortran routine FARKJTSETUP; see
+   farkode.h for further information */
+int FARKJTSetup(realtype t, N_Vector y, N_Vector fy, void *user_data)
+{
+  realtype *ydata, *fydata;
+  realtype h;
+  FARKUserData ARK_userdata;
+  int ier = 0;
+  
+  /* Initialize all pointers to NULL */
+  ydata = fydata = NULL;
+  
+  ARKodeGetLastStep(ARK_arkodemem, &h);
+  ydata  = N_VGetArrayPointer(y);
+  fydata = N_VGetArrayPointer(fy);
+  ARK_userdata = (FARKUserData) user_data;
+ 
+  FARK_JTSETUP(&t, ydata, fydata, &h, ARK_userdata->ipar, 
+	      ARK_userdata->rpar, &ier);
+  return(ier);
+}
+
 /* C interface to user-supplied Fortran routine FARKJTIMES; see
    farkode.h for further information */
 int FARKJtimes(N_Vector v, N_Vector Jv, realtype t, N_Vector y, 
@@ -70,6 +97,9 @@ int FARKJtimes(N_Vector v, N_Vector Jv, realtype t, N_Vector y,
   FARKUserData ARK_userdata;
   int ier = 0;
   
+  /* Initialize all pointers to NULL */
+  vdata = Jvdata = ydata = fydata = wkdata = NULL;
+
   ARKodeGetLastStep(ARK_arkodemem, &h);
 
   vdata  = N_VGetArrayPointer(v);
diff --git a/src/arkode/fcmix/farkklu.c b/src/arkode/fcmix/farkklu.c
deleted file mode 100644
index 29df44d..0000000
--- a/src/arkode/fcmix/farkklu.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKKLU
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "farkode.h"
-#include "arkode_impl.h"
-#include <arkode/arkode_klu.h>
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKKLU; see farkode.h for 
-   further details */
-void FARK_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier)
-{
-  *ier = ARKKLU(ARK_arkodemem, *neq, *nnz, *sparsetype);
-  ARKKLUSetOrdering(ARK_arkodemem, *ordering);
-  ARK_ls = ARK_LS_KLU;
-  return;
-}
-
-/* Fortran interface to C routine ARKKLUReinit; see farkode.h for 
-   further details */
-void FARK_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier)
-{
-  *ier = ARKKLUReInit(ARK_arkodemem, *neq, *nnz, *reinit_type);
-}
-
-/* Fortran interface to C routine ARKMassKLU; see farkode.h for 
-   further details */
-void FARK_MASSKLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier)
-{
-  *ier = ARKMassKLU(ARK_arkodemem, *neq, *nnz, *sparsetype, NULL);
-  ARKMassKLUSetOrdering(ARK_arkodemem, *ordering);
-  ARK_mass_ls = ARK_LS_KLU;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassKLUReinit; see farkode.h for 
-   further details */
-void FARK_MASSKLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier)
-{
-  *ier = ARKMassKLUReInit(ARK_arkodemem, *neq, *nnz, *reinit_type);
-}
-
-/*===============================================================
-   EOF
-===============================================================*/
-
diff --git a/src/arkode/fcmix/farklapack.c b/src/arkode/fcmix/farklapack.c
deleted file mode 100644
index 100e8cf..0000000
--- a/src/arkode/fcmix/farklapack.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKLAPACK
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "farkode.h"
-#include "arkode_impl.h"
-#include <arkode/arkode_lapack.h>
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKLapackDense; see farkode.h 
-   for further information */
-void FARK_LAPACKDENSE(int *neq, int *ier)
-{
-  *ier = ARKLapackDense(ARK_arkodemem, *neq);
-  ARK_ls = ARK_LS_LAPACKDENSE;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassLapackDense; see farkode.h 
-   for further information */
-void FARK_MASSLAPACKDENSE(int *neq, int *ier)
-{
-  *ier = ARKMassLapackDense(ARK_arkodemem, *neq, NULL);
-  ARK_mass_ls = ARK_LS_LAPACKDENSE;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKLapackBand; see farkode.h 
-   for further information */
-void FARK_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier)
-{
-  *ier = ARKLapackBand(ARK_arkodemem, *neq, *mupper, *mlower);
-  ARK_ls = ARK_LS_LAPACKBAND;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassLapackBand; see farkode.h 
-   for further information */
-void FARK_MASSLAPACKBAND(int *neq, int *mupper, int *mlower, int *ier)
-{
-  *ier = ARKMassLapackBand(ARK_arkodemem, *neq, *mupper, 
-			   *mlower, NULL);
-  ARK_mass_ls = ARK_LS_LAPACKBAND;
-  return;
-}
-
-/*===============================================================
-   EOF
-===============================================================*/
-
diff --git a/src/arkode/fcmix/farklapband.c b/src/arkode/fcmix/farklapband.c
deleted file mode 100644
index 5d5f44c..0000000
--- a/src/arkode/fcmix/farklapband.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKLAPACKBAND, for the 
- * case of a user-supplied Jacobian approximation routine.                
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "farkode.h"
-#include "arkode_impl.h"
-#include <arkode/arkode_lapack.h>
-
-/*=============================================================*/
-
-/* Prototype of the Fortran routine */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-  extern void FARK_BJAC(long int *N, long int *MU, long int *ML, 
-			long int *EBAND, realtype *T, 
-			realtype *Y, realtype *FY,
-			realtype *LBJAC, realtype *H,
-			long int *IPAR, realtype *RPAR,
-			realtype *V1, realtype *V2, 
-			realtype *V3, int *IER);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*=============================================================*/
-
-/* Fortran interface routine to ARKDlsSetBandJacFn; see farkode.h 
-   for further details */
-void FARK_LAPACKBANDSETJAC(int *flag, int *ier)
-{
-  if (*flag == 0) {
-    *ier = ARKDlsSetBandJacFn(ARK_arkodemem, NULL);
-  } else {
-    *ier = ARKDlsSetBandJacFn(ARK_arkodemem, FARKLapackBandJac);
-  }
-  return;
-}
-
-/*=============================================================*/
-
-/* The C function FARKLapackBandJac interfaces between ARKODE 
-   and a Fortran subroutine FARKBJAC for the solution of a 
-   linear system using Lapack with band Jacobian approximation.
-   Addresses of arguments are passed to FARKBJAC, using the 
-   macro BAND_COL and the routine N_VGetArrayPointer from 
-   NVECTOR. The address passed for J is that of the element in 
-   column 0 with row index -mupper.  An extended bandwith equal
-   to (J->smu) + mlower + 1 is passed as the column dimension 
-   of the corresponding array */
-int FARKLapackBandJac(long int N, long int mupper, 
-		      long int mlower, realtype t, N_Vector y, 
-		      N_Vector fy, DlsMat J, void *user_data,
-		      N_Vector vtemp1, N_Vector vtemp2, 
-		      N_Vector vtemp3)
-{
-  int ier;
-  realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
-  realtype h;
-  long int eband;
-  FARKUserData ARK_userdata;
-
-  ARKodeGetLastStep(ARK_arkodemem, &h);
-  ydata   = N_VGetArrayPointer(y);
-  fydata  = N_VGetArrayPointer(fy);
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-  eband = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
-  ARK_userdata = (FARKUserData) user_data;
-
-  FARK_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata, 
-	    jacdata, &h, ARK_userdata->ipar, ARK_userdata->rpar, 
-	    v1data, v2data, v3data, &ier);
-  return(ier);
-}
-
-/*===============================================================
-   EOF
-===============================================================*/
diff --git a/src/arkode/fcmix/farklapbandmass.c b/src/arkode/fcmix/farklapbandmass.c
deleted file mode 100644
index ea26675..0000000
--- a/src/arkode/fcmix/farklapbandmass.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKLAPACKBAND, for the 
- * case of a user-supplied Jacobian approximation routine.                
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "farkode.h"
-#include "arkode_impl.h"
-#include <arkode/arkode_lapack.h>
-
-/*=============================================================*/
-
-/* Prototype of the Fortran routine */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-  extern void FARK_BMASS(long int *N, long int *MU, long int *ML,
-			 long int *EBAND, realtype *T, 
-			 realtype *BMASS, long int *IPAR, 
-			 realtype *RPAR, realtype *V1, 
-			 realtype *V2, realtype *V3, int *IER);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*=============================================================*/
-
-/* Fortran interface routine to ARKDlsSetBandMassFn; see farkode.h 
-   for further details */
-void FARK_LAPACKBANDSETMASS(int *ier)
-{
-  *ier = ARKDlsSetBandMassFn(ARK_arkodemem, FARKLapackBandMass);
-}
-
-/*=============================================================*/
-
-/* C interface to user-supplied Fortran subroutine FARKBMASS; see 
-   farkode.h for further details */
-int FARKLapackBandMass(long int N, long int mupper, 
-		       long int mlower, realtype t, DlsMat M, 
-		       void *user_data, N_Vector vtemp1, 
-		       N_Vector vtemp2, N_Vector vtemp3)
-{
-  int ier;
-  realtype *massdata, *v1data, *v2data, *v3data;
-  long int eband;
-  FARKUserData ARK_userdata;
-
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-  eband   = (M->s_mu) + mlower + 1;
-  massdata = BAND_COL(M,0) - mupper;
-  ARK_userdata = (FARKUserData) user_data;
-
-  FARK_BMASS(&N, &mupper, &mlower, &eband, &t, massdata, 
-	     ARK_userdata->ipar, ARK_userdata->rpar, v1data, 
-	     v2data, v3data, &ier);
-  return(ier);
-}
-
-/*===============================================================
-   EOF
-===============================================================*/
diff --git a/src/arkode/fcmix/farklapdense.c b/src/arkode/fcmix/farklapdense.c
deleted file mode 100644
index 48c635c..0000000
--- a/src/arkode/fcmix/farklapdense.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKLAPACKDENSE, for the
- * case of a user-supplied Jacobian approximation routine.a
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "farkode.h"
-#include "arkode_impl.h"
-#include <arkode/arkode_lapack.h>
-
-/*=============================================================*/
-
-/* Prototype of the Fortran routines */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-  extern void FARK_DJAC(long int *N, realtype *T, realtype *Y, 
-			realtype *FY, realtype *LDJAC,
-			realtype *H, long int *IPAR, 
-			realtype *RPAR, realtype *V1, 
-			realtype *V2, realtype *V3, int *ier);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKDlsSetDenseJacFn; see 
-   farkode.h for additional information */
-void FARK_LAPACKDENSESETJAC(int *flag, int *ier)
-{
-  if (*flag == 0) {
-    *ier = ARKDlsSetDenseJacFn(ARK_arkodemem, NULL);
-  } else {
-    *ier = ARKDlsSetDenseJacFn(ARK_arkodemem, FARKLapackDenseJac);
-  }
-  return;
-}
-
-/*=============================================================*/
-
-/* The C function FARKLapackDenseJac interfaces between ARKODE 
-   and a Fortran subroutine FARKDJAC for solution of a linear 
-   system using Lapack with dense Jacobian approximation.
-   Addresses of arguments are passed to FARKDJAC, using the macro 
-   DENSE_COL and the routine N_VGetArrayPointer from NVECTOR  */
-int FARKLapackDenseJac(long int N, realtype t, N_Vector y, 
-		       N_Vector fy, DlsMat J, void *user_data,
-		       N_Vector vtemp1, N_Vector vtemp2, 
-		       N_Vector vtemp3)
-{
-  int ier;
-  realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
-  realtype h;
-  FARKUserData ARK_userdata;
-
-  ARKodeGetLastStep(ARK_arkodemem, &h);
-  ydata   = N_VGetArrayPointer(y);
-  fydata  = N_VGetArrayPointer(fy);
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-  jacdata = DENSE_COL(J,0);
-  ARK_userdata = (FARKUserData) user_data;
-
-  FARK_DJAC(&N, &t, ydata, fydata, jacdata, &h, ARK_userdata->ipar, 
-	    ARK_userdata->rpar, v1data, v2data, v3data, &ier); 
-  return(ier);
-}
-
-/*===============================================================
-   EOF
-===============================================================*/
-
diff --git a/src/arkode/fcmix/farklapdensemass.c b/src/arkode/fcmix/farklapdensemass.c
deleted file mode 100644
index 481df4e..0000000
--- a/src/arkode/fcmix/farklapdensemass.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKLAPACKDENSE, for the
- * case of a user-supplied Jacobian approximation routine.a
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "farkode.h"
-#include "arkode_impl.h"
-#include <arkode/arkode_lapack.h>
-
-/*=============================================================*/
-
-/* Prototype of the Fortran routines */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-  extern void FARK_DMASS(long int *N, realtype *T, 
-			 realtype *DMASS, long int *IPAR, 
-			 realtype *RPAR, realtype *V1, 
-			 realtype *V2, realtype *V3, int *ier);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*=============================================================*/
-
-/* Fortran interface routine to ARKDlsSetDenseMassFn; see 
-   farkode.h for further details */
-void FARK_LAPACKDENSESETMASS(int *ier)
-{
-  *ier = ARKDlsSetDenseMassFn(ARK_arkodemem, FARKLapackDenseMass);
-}
-
-/*=============================================================*/
-
-/* C interface to user-supplied Fortran routine FARKDMASS; see 
-   farkode.h for additional information  */
-int FARKLapackDenseMass(long int N, realtype t, DlsMat M, 
-			void *user_data, N_Vector vtemp1, 
-			N_Vector vtemp2, N_Vector vtemp3)
-{
-  int ier;
-  realtype *massdata, *v1data, *v2data, *v3data;
-  FARKUserData ARK_userdata;
-
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-  massdata = DENSE_COL(M,0);
-  ARK_userdata = (FARKUserData) user_data;
-
-  FARK_DMASS(&N, &t, massdata, ARK_userdata->ipar, ARK_userdata->rpar, 
-	     v1data, v2data, v3data, &ier); 
-  return(ier);
-}
-
-/*===============================================================
-   EOF
-===============================================================*/
-
diff --git a/src/arkode/fcmix/farkmasspreco.c b/src/arkode/fcmix/farkmasspreco.c
index 41eeae6..c5d1df8 100644
--- a/src/arkode/fcmix/farkmasspreco.c
+++ b/src/arkode/fcmix/farkmasspreco.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,10 +15,11 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * The C function FARKPSet is to interface between the ARKSP*
- * modules and the user-supplied preconditioner setup routine 
- * FARKPSET. Note the use of the generic name FARK_PSET in the 
- * code below.
+ * The C function FARKPSet is to interface between the 
+ * ARKSPILSMASS module and the user-supplied mass matrix 
+ * preconditioner setup/solve routines FARKPSET and FARKPSOL. 
+ * Note the use of the generic names FARK_PSET and  FARK_PSOL in
+ * the code below.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -36,11 +37,10 @@ extern "C" {
 #endif
 
   extern void FARK_MASSPSET(realtype *T, long int *IPAR, 
-			    realtype *RPAR, realtype *W1, 
-			    realtype *W2, realtype *W3, int *IER);
+			    realtype *RPAR, int *IER);
   extern void FARK_MASSPSOL(realtype *T, realtype *R, realtype *Z, 
 			    realtype *DELTA, int *LR, long int *IPAR, 
-			    realtype *RPAR, realtype *WRK, int *IER);
+			    realtype *RPAR, int *IER);
 
 #ifdef __cplusplus
 }
@@ -65,20 +65,12 @@ void FARK_SPILSSETMASSPREC(int *flag, int *ier)
 
 /* C interface to user-supplied Fortran routine FARKMASSPSET; see 
    farkode.h for further details */
-int FARKMassPSet(realtype t, void *user_data, N_Vector vtemp1, 
-		 N_Vector vtemp2, N_Vector vtemp3)
+int FARKMassPSet(realtype t, void *user_data)
 {
   int ier = 0;
-  realtype *v1data, *v2data, *v3data;
   FARKUserData ARK_userdata;
-
-  v1data = N_VGetArrayPointer(vtemp1);
-  v2data = N_VGetArrayPointer(vtemp2);
-  v3data = N_VGetArrayPointer(vtemp3);
   ARK_userdata = (FARKUserData) user_data;
-
-  FARK_MASSPSET(&t, ARK_userdata->ipar, ARK_userdata->rpar,
-		v1data, v2data, v3data, &ier);
+  FARK_MASSPSET(&t, ARK_userdata->ipar, ARK_userdata->rpar, &ier);
   return(ier);
 }
 
@@ -88,19 +80,18 @@ int FARKMassPSet(realtype t, void *user_data, N_Vector vtemp1,
 /* C interface to user-supplied Fortran routine FARKMASSPSOL; see 
    farkode.h for further details */
 int FARKMassPSol(realtype t, N_Vector r, N_Vector z, realtype delta,
-		 int lr, void *user_data, N_Vector vtemp)
+		 int lr, void *user_data)
 {
   int ier = 0;
-  realtype *vtdata, *rdata, *zdata;
+  realtype *rdata, *zdata;
   FARKUserData ARK_userdata;
 
-  vtdata = N_VGetArrayPointer(vtemp);
   rdata  = N_VGetArrayPointer(r);
   zdata  = N_VGetArrayPointer(z);
   ARK_userdata = (FARKUserData) user_data;
 
   FARK_MASSPSOL(&t, rdata, zdata, &delta, &lr, ARK_userdata->ipar, 
-		ARK_userdata->rpar, vtdata, &ier);
+		ARK_userdata->rpar, &ier);
   return(ier);
 }
 
diff --git a/src/arkode/fcmix/farkmtimes.c b/src/arkode/fcmix/farkmtimes.c
index d16050a..61b1eed 100644
--- a/src/arkode/fcmix/farkmtimes.c
+++ b/src/arkode/fcmix/farkmtimes.c
@@ -15,10 +15,11 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * The C function FARKJtimes is to interface between the ARKSP* 
- * modules and the user-supplied Jacobian-vector product routine
- * FARKJTIMES. Note the use of the generic name FARK_JTIMES in
- * the code below.
+ * The C functions FARKMTSetup and FARKMtimes are to interface 
+ * between the ARKSPILS and ARKSPILSMASS modules and the 
+ * user-supplied mass-matrix-vector setup/product routines
+ * FARKMTSETUP and FARKJTIMES. Note the use of the generic names
+ * FARK_MTSETUP and FARK_MTIMES in the code below.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -35,6 +36,8 @@
 extern "C" {
 #endif
 
+  extern void FARK_MTSETUP(realtype *T, long int *IPAR, 
+                           realtype *RPAR, int *IER);
   extern void FARK_MTIMES(realtype *V, realtype *MV, realtype *T, 
 			  long int *IPAR, realtype *RPAR, int *IER);
 
@@ -44,18 +47,29 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKSpilsSetMassTimesVecFn; see 
+/* Fortran interface to C routine ARKSpilsSetMassTimes; see 
    farkode.h for further information */
 void FARK_SPILSSETMASS(int *ier)
 {
   ARKodeMem ark_mem;
   ark_mem = (ARKodeMem) ARK_arkodemem;
-  *ier = ARKSpilsSetMassTimesVecFn(ARK_arkodemem, FARKMtimes, 
-				   ark_mem->ark_user_data);
+  *ier = ARKSpilsSetMassTimes(ARK_arkodemem, FARKMTSetup, 
+                              FARKMtimes, ark_mem->ark_user_data);
 }
 
 /*=============================================================*/
 
+/* C interface to user-supplied Fortran routine FARKMTSETUP; see
+   farkode.h for further information */
+int FARKMTSetup(realtype t, void *user_data)
+{
+  FARKUserData ARK_userdata;
+  int ier = 0;
+  ARK_userdata = (FARKUserData) user_data;
+  FARK_MTSETUP(&t, ARK_userdata->ipar, ARK_userdata->rpar, &ier);
+  return(ier);
+}
+
 /* C interface to user-supplied Fortran routine FARKMTIMES; see
    farkode.h for further information */
 int FARKMtimes(N_Vector v, N_Vector Mv, realtype t, void *user_data)
diff --git a/src/arkode/fcmix/farkode.c b/src/arkode/fcmix/farkode.c
index 899a798..12fb61b 100644
--- a/src/arkode/fcmix/farkode.c
+++ b/src/arkode/fcmix/farkode.c
@@ -2,13 +2,13 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
@@ -18,9 +18,8 @@
  * This is the implementation file for the Fortran interface to
  * the ARKODE package.  See farkode.h for usage.
  * NOTE: some routines are necessarily stored elsewhere to avoid
- * linking problems.  Therefore, see also farkpreco.c, farkpsol.c,
- * farkjtimes.c, farkadapt.c and farkexpstab.c for all the 
- * available options.
+ * linking problems.  Therefore, see also the other C files in
+ * this folder for all of the available options.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -28,19 +27,20 @@
 #include <string.h>
 #include "farkode.h"
 #include "arkode_impl.h"
-#include <arkode/arkode_band.h>
-#include <arkode/arkode_dense.h>
-#include <arkode/arkode_klu.h>
-#include <arkode/arkode_superlumt.h>
-#include <arkode/arkode_spgmr.h>
-#include <arkode/arkode_spbcgs.h>
-#include <arkode/arkode_sptfqmr.h>
-#include <arkode/arkode_spfgmr.h>
-#include <arkode/arkode_pcg.h>
+#include <sundials/sundials_matrix.h>
+#include <arkode/arkode_direct.h>
+#include <arkode/arkode_spils.h>
 
 /*=============================================================*/
 
-/* Definitions for global variables shared between Fortran/C 
+/* Constants and default values (in case of illegal inputs) */
+#define  ABSTOL  RCONST(1.0e-9)
+#define  RELTOL  RCONST(1.0e-4)
+#define  ZERO    RCONST(0.0)
+
+/*=============================================================*/
+
+/* Definitions for global variables shared between Fortran/C
    interface routines */
 void     *ARK_arkodemem;
 long int *ARK_iout;
@@ -68,14 +68,14 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface routine to initialize ARKode memory 
-   structure; functions as an all-in-one interface to the C 
-   routines ARKodeCreate, ARKodeSetUserData, ARKodeInit, and 
-   ARKodeSStolerances (or ARKodeSVtolerances); see farkode.h 
+/* Fortran interface routine to initialize ARKode memory
+   structure; functions as an all-in-one interface to the C
+   routines ARKodeCreate, ARKodeSetUserData, ARKodeInit, and
+   ARKodeSStolerances (or ARKodeSVtolerances); see farkode.h
    for further details */
-void FARK_MALLOC(realtype *t0, realtype *y0, int *imex, 
-		 int *iatol, realtype *rtol, realtype *atol, 
-		 long int *iout, realtype *rout, 
+void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
+		 int *iatol, realtype *rtol, realtype *atol,
+		 long int *iout, realtype *rout,
 		 long int *ipar, realtype *rpar, int *ier) {
 
   N_Vector Vatol;
@@ -87,17 +87,17 @@ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
   /* Check for required vector operations */
   if(F2C_ARKODE_vec->ops->nvgetarraypointer == NULL) {
     *ier = -1;
-    printf("Error: getarraypointer vector operation is not implemented.\n\n");
+    fprintf(stderr, "Error: getarraypointer vector operation is not implemented.\n\n");
     return;
   }
   if(F2C_ARKODE_vec->ops->nvsetarraypointer == NULL) {
     *ier = -1;
-    printf("Error: setarraypointer vector operation is not implemented.\n\n");
+    fprintf(stderr, "Error: setarraypointer vector operation is not implemented.\n\n");
     return;
   }
   if(F2C_ARKODE_vec->ops->nvcloneempty == NULL) {
     *ier = -1;
-    printf("Error: cloneempty vector operation is not implemented.\n\n");
+    fprintf(stderr, "Error: cloneempty vector operation is not implemented.\n\n");
     return;
   }
 
@@ -105,10 +105,10 @@ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
   ARK_arkodemem = NULL;
   Vatol = NULL;
 
-  /* initialize global constants to zero */
+  /* initialize global constants to disable each option */
   ARK_nrtfn = 0;
-  ARK_ls = 0;
-  ARK_mass_ls = 0;
+  ARK_ls = -1;
+  ARK_mass_ls = -1;
 
   /* Create ARKODE object */
   ARK_arkodemem = ARKodeCreate();
@@ -139,19 +139,19 @@ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
   /* Call ARKodeInit based on imex argument */
   switch (*imex) {
   case 0:  /* purely implicit */
-    *ier = ARKodeInit(ARK_arkodemem, NULL, FARKfi, 
+    *ier = ARKodeInit(ARK_arkodemem, NULL, FARKfi,
 		      *t0, F2C_ARKODE_vec);
     break;
   case 1:  /* purely explicit */
-    *ier = ARKodeInit(ARK_arkodemem, FARKfe, NULL, 
+    *ier = ARKodeInit(ARK_arkodemem, FARKfe, NULL,
 		      *t0, F2C_ARKODE_vec);
     break;
   case 2:  /* imex */
-    *ier = ARKodeInit(ARK_arkodemem, FARKfe, FARKfi, 
+    *ier = ARKodeInit(ARK_arkodemem, FARKfe, FARKfi,
 		      *t0, F2C_ARKODE_vec);
     break;
   }
-    
+
   /* Reset data pointers */
   N_VSetArrayPointer(NULL, F2C_ARKODE_vec);
 
@@ -164,13 +164,13 @@ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
   }
 
   /* Set tolerances -- if <= 0, keep as defaults */
-  reltol=1.e-4;
-  abstol=1.e-9;
-  if (*rtol > 0.0)  reltol = *rtol;
+  reltol = RELTOL;
+  abstol = ABSTOL;
+  if (*rtol > ZERO)  reltol = *rtol;
   switch (*iatol) {
   case 1:
-    if (*atol > 0.0)  abstol = *atol;
-    *ier = ARKodeSStolerances(ARK_arkodemem, reltol, abstol); 
+    if (*atol > ZERO)  abstol = *atol;
+    *ier = ARKodeSStolerances(ARK_arkodemem, reltol, abstol);
     break;
   case 2:
     Vatol = N_VCloneEmpty(F2C_ARKODE_vec);
@@ -181,7 +181,7 @@ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
       return;
     }
     N_VSetArrayPointer(atol, Vatol);
-    if (N_VMin(Vatol) <= 0.0)  N_VConst(abstol, Vatol);
+    if (N_VMin(Vatol) <= ZERO)  N_VConst(abstol, Vatol);
     *ier = ARKodeSVtolerances(ARK_arkodemem, reltol, Vatol);
     N_VDestroy(Vatol);
     break;
@@ -189,7 +189,7 @@ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
 
   /* On failure, exit */
   if(*ier != ARK_SUCCESS) {
-    free(ARK_userdata); 
+    free(ARK_userdata);
     ARK_userdata = NULL;
     *ier = -1;
     return;
@@ -207,11 +207,11 @@ void FARK_MALLOC(realtype *t0, realtype *y0, int *imex,
 
 /*=============================================================*/
 
-/* Fortran interface routine to re-initialize ARKode memory 
-   structure; functions as an all-in-one interface to the C 
-   routines ARKodeReInit and ARKodeSStolerances (or 
+/* Fortran interface routine to re-initialize ARKode memory
+   structure; functions as an all-in-one interface to the C
+   routines ARKodeReInit and ARKodeSStolerances (or
    ARKodeSVtolerances); see farkode.h for further details */
-void FARK_REINIT(realtype *t0, realtype *y0, int *imex, int *iatol, 
+void FARK_REINIT(realtype *t0, realtype *y0, int *imex, int *iatol,
 		 realtype *rtol, realtype *atol, int *ier) {
 
   N_Vector Vatol;
@@ -227,15 +227,15 @@ void FARK_REINIT(realtype *t0, realtype *y0, int *imex, int *iatol,
   /* Call ARKodeReInit based on imex argument */
   switch (*imex) {
   case 0:  /* purely implicit */
-    *ier = ARKodeReInit(ARK_arkodemem, NULL, FARKfi, 
+    *ier = ARKodeReInit(ARK_arkodemem, NULL, FARKfi,
 			*t0, F2C_ARKODE_vec);
     break;
   case 1:  /* purely explicit */
-    *ier = ARKodeReInit(ARK_arkodemem, FARKfe, NULL, 
+    *ier = ARKodeReInit(ARK_arkodemem, FARKfe, NULL,
 			*t0, F2C_ARKODE_vec);
     break;
   case 2:  /* imex */
-    *ier = ARKodeReInit(ARK_arkodemem, FARKfe, FARKfi, 
+    *ier = ARKodeReInit(ARK_arkodemem, FARKfe, FARKfi,
 			*t0, F2C_ARKODE_vec);
     break;
   }
@@ -250,13 +250,13 @@ void FARK_REINIT(realtype *t0, realtype *y0, int *imex, int *iatol,
   }
 
   /* Set tolerances */
-  reltol=1.e-4;
-  abstol=1.e-9;
-  if (*rtol > 0.0)  reltol = *rtol;
+  reltol = RELTOL;
+  abstol = ABSTOL;
+  if (*rtol > ZERO)  reltol = *rtol;
   switch (*iatol) {
   case 1:
-    if (*atol > 0.0)  abstol = *atol;
-    *ier = ARKodeSStolerances(ARK_arkodemem, reltol, abstol); 
+    if (*atol > ZERO)  abstol = *atol;
+    *ier = ARKodeSStolerances(ARK_arkodemem, reltol, abstol);
     break;
   case 2:
     Vatol = N_VCloneEmpty(F2C_ARKODE_vec);
@@ -265,7 +265,7 @@ void FARK_REINIT(realtype *t0, realtype *y0, int *imex, int *iatol,
       return;
     }
     N_VSetArrayPointer(atol, Vatol);
-    if (N_VMin(Vatol) <= 0.0)  N_VConst(abstol, Vatol);
+    if (N_VMin(Vatol) <= ZERO)  N_VConst(abstol, Vatol);
     *ier = ARKodeSVtolerances(ARK_arkodemem, reltol, Vatol);
     N_VDestroy(Vatol);
     break;
@@ -282,10 +282,10 @@ void FARK_REINIT(realtype *t0, realtype *y0, int *imex, int *iatol,
 
 /*=============================================================*/
 
-/* Fortran interface routine to re-initialize ARKode memory 
-   structure for a problem with a new size but similar time 
-   scale; functions as an all-in-one interface to the C 
-   routines ARKodeResize (and potentially ARKodeSVtolerances); 
+/* Fortran interface routine to re-initialize ARKode memory
+   structure for a problem with a new size but similar time
+   scale; functions as an all-in-one interface to the C
+   routines ARKodeResize (and potentially ARKodeSVtolerances);
    see farkode.h for further details */
 void FARK_RESIZE(realtype *t0, realtype *y0, realtype *hscale,
 		 int *itol, realtype *rtol, realtype *atol, int *ier) {
@@ -294,8 +294,8 @@ void FARK_RESIZE(realtype *t0, realtype *y0, realtype *hscale,
 
   /* Set data in F2C_ARKODE_vec to y0 */
   N_VSetArrayPointer(y0, F2C_ARKODE_vec);
-  
-  /* Call ARKodeResize (currently does not allow Fortran 
+
+  /* Call ARKodeResize (currently does not allow Fortran
      user-supplied vector resize function) */
   *ier = ARKodeResize(ARK_arkodemem, F2C_ARKODE_vec, *hscale,
 		      *t0, NULL, NULL);
@@ -327,7 +327,7 @@ void FARK_RESIZE(realtype *t0, realtype *y0, realtype *hscale,
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeSetDefaults; see 
+/* Fortran interface to C routine ARKodeSetDefaults; see
    farkode.h for further details */
 void FARK_SETDEFAULTS(int *ier) {
   *ier = ARKodeSetDefaults(ARK_arkodemem);
@@ -336,44 +336,44 @@ void FARK_SETDEFAULTS(int *ier) {
 
 /*=============================================================*/
 
-/* Fortran interface to C "set" routines having integer 
+/* Fortran interface to C "set" routines having integer
    arguments; see farkode.h for further details */
 void FARK_SETIIN(char key_name[], long int *ival, int *ier) {
-  if (!strncmp(key_name, "ORDER", 5)) 
+  if (!strncmp(key_name, "ORDER", 5))
     *ier = ARKodeSetOrder(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "DENSE_ORDER", 11)) 
+  else if (!strncmp(key_name, "DENSE_ORDER", 11))
     *ier = ARKodeSetDenseOrder(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "LINEAR", 6)) 
+  else if (!strncmp(key_name, "LINEAR", 6))
     *ier = ARKodeSetLinear(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "NONLINEAR", 9)) 
+  else if (!strncmp(key_name, "NONLINEAR", 9))
     *ier = ARKodeSetNonlinear(ARK_arkodemem);
-  else if (!strncmp(key_name, "FIXEDPOINT", 10)) 
+  else if (!strncmp(key_name, "FIXEDPOINT", 10))
     *ier = ARKodeSetFixedPoint(ARK_arkodemem, (long int) *ival);
-  else if (!strncmp(key_name, "NEWTON", 6)) 
+  else if (!strncmp(key_name, "NEWTON", 6))
     *ier = ARKodeSetNewton(ARK_arkodemem);
-  else if (!strncmp(key_name, "EXPLICIT", 8)) 
+  else if (!strncmp(key_name, "EXPLICIT", 8))
     *ier = ARKodeSetExplicit(ARK_arkodemem);
-  else if (!strncmp(key_name, "IMPLICIT", 8)) 
+  else if (!strncmp(key_name, "IMPLICIT", 8))
     *ier = ARKodeSetImplicit(ARK_arkodemem);
-  else if (!strncmp(key_name, "IMEX", 4)) 
+  else if (!strncmp(key_name, "IMEX", 4))
     *ier = ARKodeSetImEx(ARK_arkodemem);
-  else if (!strncmp(key_name, "IRK_TABLE_NUM", 13)) 
+  else if (!strncmp(key_name, "IRK_TABLE_NUM", 13))
     *ier = ARKodeSetIRKTableNum(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "ERK_TABLE_NUM", 13)) 
+  else if (!strncmp(key_name, "ERK_TABLE_NUM", 13))
     *ier = ARKodeSetERKTableNum(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "ARK_TABLE_NUM", 13)) 
+  else if (!strncmp(key_name, "ARK_TABLE_NUM", 13))
     *ier = ARKodeSetARKTableNum(ARK_arkodemem, (int) ival[0], (int) ival[1]);
-  else if (!strncmp(key_name, "MAX_NSTEPS", 10)) 
-    *ier = ARKodeSetMaxNumSteps(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "HNIL_WARNS", 10)) 
+  else if (!strncmp(key_name, "MAX_NSTEPS", 10))
+    *ier = ARKodeSetMaxNumSteps(ARK_arkodemem, (long int) *ival);
+  else if (!strncmp(key_name, "HNIL_WARNS", 10))
     *ier = ARKodeSetMaxHnilWarns(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "PREDICT_METHOD", 14)) 
+  else if (!strncmp(key_name, "PREDICT_METHOD", 14))
     *ier = ARKodeSetPredictorMethod(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "MAX_ERRFAIL", 11)) 
+  else if (!strncmp(key_name, "MAX_ERRFAIL", 11))
     *ier = ARKodeSetMaxErrTestFails(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "MAX_CONVFAIL", 12)) 
+  else if (!strncmp(key_name, "MAX_CONVFAIL", 12))
     *ier = ARKodeSetMaxConvFails(ARK_arkodemem, (int) *ival);
-  else if (!strncmp(key_name, "MAX_NITERS", 10)) 
+  else if (!strncmp(key_name, "MAX_NITERS", 10))
     *ier = ARKodeSetMaxNonlinIters(ARK_arkodemem, (int) *ival);
   else if (!strncmp(key_name, "ADAPT_SMALL_NEF", 15))
     *ier = ARKodeSetSmallNumEFails(ARK_arkodemem, (int) *ival);
@@ -381,7 +381,7 @@ void FARK_SETIIN(char key_name[], long int *ival, int *ier) {
     *ier = ARKodeSetMaxStepsBetweenLSet(ARK_arkodemem, (int) *ival);
   else {
     *ier = -99;
-    printf("FARKSETIIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FARKSETIIN: Unrecognized key.\n\n");
   }
   return;
 }
@@ -391,23 +391,23 @@ void FARK_SETIIN(char key_name[], long int *ival, int *ier) {
 /* Fortran interface to C "set" routines having real
    arguments; see farkode.h for further details */
 void FARK_SETRIN(char key_name[], realtype *rval, int *ier) {
-  if (!strncmp(key_name, "INIT_STEP", 9)) 
+  if (!strncmp(key_name, "INIT_STEP", 9))
     *ier = ARKodeSetInitStep(ARK_arkodemem, *rval);
-  else if (!strncmp(key_name, "MAX_STEP", 8)) 
+  else if (!strncmp(key_name, "MAX_STEP", 8))
     *ier = ARKodeSetMaxStep(ARK_arkodemem, *rval);
-  else if (!strncmp(key_name, "MIN_STEP", 8)) 
+  else if (!strncmp(key_name, "MIN_STEP", 8))
     *ier = ARKodeSetMinStep(ARK_arkodemem, *rval);
-  else if (!strncmp(key_name, "STOP_TIME", 9)) 
+  else if (!strncmp(key_name, "STOP_TIME", 9))
     *ier = ARKodeSetStopTime(ARK_arkodemem, *rval);
-  else if (!strncmp(key_name, "NLCONV_COEF", 11)) 
+  else if (!strncmp(key_name, "NLCONV_COEF", 11))
     *ier = ARKodeSetNonlinConvCoef(ARK_arkodemem, *rval);
   else if (!strncmp(key_name, "ADAPT_CFL", 9))
     *ier = ARKodeSetCFLFraction(ARK_arkodemem, *rval);
-  else if (!strncmp(key_name, "ADAPT_SAFETY", 12)) 
+  else if (!strncmp(key_name, "ADAPT_SAFETY", 12))
     *ier = ARKodeSetSafetyFactor(ARK_arkodemem, *rval);
   else if (!strncmp(key_name, "ADAPT_BIAS", 10))
     *ier = ARKodeSetErrorBias(ARK_arkodemem, *rval);
-  else if (!strncmp(key_name, "ADAPT_GROWTH", 12)) 
+  else if (!strncmp(key_name, "ADAPT_GROWTH", 12))
     *ier = ARKodeSetMaxGrowth(ARK_arkodemem, *rval);
   else if (!strncmp(key_name, "ADAPT_BOUNDS", 12))
     *ier = ARKodeSetFixedStepBounds(ARK_arkodemem, rval[0], rval[1]);
@@ -427,28 +427,28 @@ void FARK_SETRIN(char key_name[], realtype *rval, int *ier) {
     *ier = ARKodeSetFixedStep(ARK_arkodemem, *rval);
   else {
     *ier = -99;
-    printf("FARKSETRIN: Unrecognized key: %s\n\n",key_name);
+    fprintf(stderr, "FARKSETRIN: Unrecognized key: %s\n\n",key_name);
   }
   return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeSetAdaptivityMethod; 
+/* Fortran interface to C routine ARKodeSetAdaptivityMethod;
    see farkode.h for further details */
-void FARK_SETADAPTMETHOD(int *imethod, int *idefault, int *ipq, 
+void FARK_SETADAPTMETHOD(int *imethod, int *idefault, int *ipq,
 			 realtype *params, int *ier) {
 
-  *ier = ARKodeSetAdaptivityMethod(ARK_arkodemem, *imethod, 
+  *ier = ARKodeSetAdaptivityMethod(ARK_arkodemem, *imethod,
 				   *idefault, *ipq, params);
   return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeSetERKTable; see 
+/* Fortran interface to C routine ARKodeSetERKTable; see
    farkode.h for further details */
-void FARK_SETERKTABLE(int *s, int *q, int *p, realtype *c, realtype *A, 
+void FARK_SETERKTABLE(int *s, int *q, int *p, realtype *c, realtype *A,
 		      realtype *b, realtype *b2, int *ier) {
   *ier = ARKodeSetERKTable(ARK_arkodemem, *s, *q, *p, c, A, b, b2);
   return;
@@ -456,9 +456,9 @@ void FARK_SETERKTABLE(int *s, int *q, int *p, realtype *c, realtype *A,
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeSetIRKTable; see 
+/* Fortran interface to C routine ARKodeSetIRKTable; see
    farkode.h for further details */
-void FARK_SETIRKTABLE(int *s, int *q, int *p, realtype *c, realtype *A, 
+void FARK_SETIRKTABLE(int *s, int *q, int *p, realtype *c, realtype *A,
 		      realtype *b, realtype *b2, int *ier) {
   *ier = ARKodeSetIRKTable(ARK_arkodemem, *s, *q, *p, c, A, b, b2);
   return;
@@ -466,22 +466,22 @@ void FARK_SETIRKTABLE(int *s, int *q, int *p, realtype *c, realtype *A,
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeSetARKTables; see 
+/* Fortran interface to C routine ARKodeSetARKTables; see
    farkode.h for further details */
-void FARK_SETARKTABLES(int *s, int *q, int *p, realtype *ci, 
-		       realtype *ce, realtype *Ai, realtype *Ae, 
-		       realtype *bi, realtype *be, realtype *b2i, 
+void FARK_SETARKTABLES(int *s, int *q, int *p, realtype *ci,
+		       realtype *ce, realtype *Ai, realtype *Ae,
+		       realtype *bi, realtype *be, realtype *b2i,
 		       realtype *b2e, int *ier) {
-  *ier = ARKodeSetARKTables(ARK_arkodemem, *s, *q, *p, ci, 
+  *ier = ARKodeSetARKTables(ARK_arkodemem, *s, *q, *p, ci,
 			    ce, Ai, Ae, bi, be, b2i, b2e);
   return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface routine to set residual tolerance 
-   scalar/array; functions as an all-in-one interface to the C 
-   routines ARKodeResStolerance and ARKodeResVtolerance; 
+/* Fortran interface routine to set residual tolerance
+   scalar/array; functions as an all-in-one interface to the C
+   routines ARKodeResStolerance and ARKodeResVtolerance;
    see farkode.h for further details */
 void FARK_SETRESTOLERANCE(int *itol, realtype *atol, int *ier) {
 
@@ -491,11 +491,11 @@ void FARK_SETRESTOLERANCE(int *itol, realtype *atol, int *ier) {
   *ier = 0;
 
   /* Set tolerance, based on itol argument */
-  abstol=1.e-9;
+  abstol = ABSTOL;
   switch (*itol) {
   case 1:
-    if (*atol > 0.0)  abstol = *atol;
-    *ier = ARKodeResStolerance(ARK_arkodemem, abstol); 
+    if (*atol > ZERO)  abstol = *atol;
+    *ier = ARKodeResStolerance(ARK_arkodemem, abstol);
     break;
   case 2:
     Vatol = NULL;
@@ -505,7 +505,7 @@ void FARK_SETRESTOLERANCE(int *itol, realtype *atol, int *ier) {
       return;
     }
     N_VSetArrayPointer(atol, Vatol);
-    if (N_VMin(Vatol) <= 0.0)  N_VConst(abstol, Vatol);
+    if (N_VMin(Vatol) <= ZERO)  N_VConst(abstol, Vatol);
     *ier = ARKodeResVtolerance(ARK_arkodemem, Vatol);
     N_VDestroy(Vatol);
     break;
@@ -516,7 +516,7 @@ void FARK_SETRESTOLERANCE(int *itol, realtype *atol, int *ier) {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeSetDiagnostics; see 
+/* Fortran interface to C routine ARKodeSetDiagnostics; see
    farkode.h for further details */
 void FARK_SETDIAGNOSTICS(char fname[], int *flen, int *ier) {
   char *filename=NULL;
@@ -540,7 +540,7 @@ void FARK_SETDIAGNOSTICS(char fname[], int *flen, int *ier) {
 
 /*=============================================================*/
 
-/* Fortran routine to close diagnostics output file; see farkode.h 
+/* Fortran routine to close diagnostics output file; see farkode.h
    for further details */
 void FARK_STOPDIAGNOSTICS(int *ier) {
   ARKodeMem ark_mem;
@@ -560,406 +560,87 @@ void FARK_STOPDIAGNOSTICS(int *ier) {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKDense; see farkode.h for 
-   further details */
-void FARK_DENSE(long int *neq, int *ier) {
-  *ier = ARKDense(ARK_arkodemem, *neq);
-  ARK_ls = ARK_LS_DENSE;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassDense; see farkode.h 
-   for further details */
-void FARK_MASSDENSE(long int *neq, int *ier) {
-  *ier = ARKMassDense(ARK_arkodemem, *neq, NULL);
-  ARK_mass_ls = ARK_LS_DENSE;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKBand; see farkode.h for 
-   further details */
-void FARK_BAND(long int *neq, long int *mupper, 
-	       long int *mlower, int *ier) {
-  *ier = ARKBand(ARK_arkodemem, *neq, *mupper, *mlower);
-  ARK_ls = ARK_LS_BAND;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassBand; see farkode.h 
-   for further details */
-void FARK_MASSBAND(long int *neq, long int *mupper, 
-		   long int *mlower, int *ier) {
-  *ier = ARKMassBand(ARK_arkodemem, *neq, *mupper, 
-		     *mlower, NULL);
-  ARK_mass_ls = ARK_LS_BAND;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKSpgmr and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_SPGMR(int *pretype, int *gstype, int *maxl, 
-		realtype *delt, int *ier) {
-
-  *ier = ARKSpgmr(ARK_arkodemem, *pretype, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPGMR;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassSpgmr and it's 
-   associated "set" routines; see farkode.h for further details */
-void FARK_MASSSPGMR(int *pretype, int *gstype, int *maxl, 
-		    realtype *delt, int *ier) {
-
-  *ier = ARKMassSpgmr(ARK_arkodemem, *pretype, *maxl, NULL, NULL);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPGMR;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKSpbcg and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_SPBCG(int *pretype, int *maxl, realtype *delt, int *ier) {
-
-  *ier = ARKSpbcg(ARK_arkodemem, *pretype, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPBCG;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassSpbcg and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_MASSSPBCG(int *pretype, int *maxl, 
-		    realtype *delt, int *ier) {
-
-  *ier = ARKMassSpbcg(ARK_arkodemem, *pretype, *maxl, NULL, NULL);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPBCG;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKSptfqmr and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_SPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier) {
-
-  *ier = ARKSptfqmr(ARK_arkodemem, *pretype, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPTFQMR;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassSptfqmr and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_MASSSPTFQMR(int *pretype, int *maxl, 
-		      realtype *delt, int *ier) {
-
-  *ier = ARKMassSptfqmr(ARK_arkodemem, *pretype, *maxl, NULL, NULL);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPTFQMR;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKSpfgmr and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_SPFGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier) {
-
-  *ier = ARKSpfgmr(ARK_arkodemem, *pretype, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPFGMR;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassSpfgmr and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_MASSSPFGMR(int *pretype, int *gstype, int *maxl, 
-		     realtype *delt, int *ier) {
-
-  *ier = ARKMassSpfgmr(ARK_arkodemem, *pretype, *maxl, NULL, NULL);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPFGMR;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKPcg and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_PCG(int *pretype, int *maxl, realtype *delt, int *ier) {
-
-  *ier = ARKPcg(ARK_arkodemem, *pretype, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_PCG;
-  return;
-}
-
-/* Fortran interface to C routine ARKMassPcg and it's associated 
-   "set" routines; see farkode.h for further details */
-void FARK_MASSPCG(int *pretype, int *maxl, 
-		  realtype *delt, int *ier) {
-
-  *ier = ARKMassPcg(ARK_arkodemem, *pretype, *maxl, NULL, NULL);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_PCG;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C "set" routines for the ARKSpgmr solver; 
-   see farkode.h for further details */
-void FARK_SPGMRREINIT(int *pretype, int *gstype, 
-		      realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPGMR;
-  return;
-}
-
-/* Fortran interface to C "set" routines for the ARKMassSpgmr solver; 
-   see farkode.h for further details */
-void FARK_MASSSPGMRREINIT(int *pretype, int *gstype, 
-			  realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetMassPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPGMR;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C "set" routines for the ARKSpbcg solver; 
-   see farkode.h for further details */
-void FARK_SPBCGREINIT(int *pretype, int *maxl, 
-		      realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMaxl(ARK_arkodemem, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPBCG;
-  return;
-}
-
-/* Fortran interface to C "set" routines for the ARKMassSpbcg solver; 
-   see farkode.h for further details */
-void FARK_MASSSPBCGREINIT(int *pretype, int *maxl, 
-			  realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetMassPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassMaxl(ARK_arkodemem, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPBCG;
-  return;
-}
-
-/*=============================================================*/
-
-/* Fortran interface to C "set" routines for the ARKSptfqmr
-   solver; see farkode.h for further details */
-void FARK_SPTFQMRREINIT(int *pretype, int *maxl, 
-			realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMaxl(ARK_arkodemem, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPTFQMR;
+/* Fortran interface to C routine ARKDlsSetLinearSolver; see
+   farkode.h for further details */
+void FARK_DLSINIT(int *ier) {
+  if ( (ARK_arkodemem == NULL) || (F2C_ARKODE_linsol == NULL) ||
+       (F2C_ARKODE_matrix == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = ARKDlsSetLinearSolver(ARK_arkodemem, F2C_ARKODE_linsol,
+                               F2C_ARKODE_matrix);
+  ARK_ls = ARK_LS_DIRECT;
   return;
 }
 
-/* Fortran interface to C "set" routines for the ARKMassSptfqmr
-   solver; see farkode.h for further details */
-void FARK_MASSSPTFQMRREINIT(int *pretype, int *maxl, 
-			    realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetMassPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassMaxl(ARK_arkodemem, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPTFQMR;
+/* Fortran interface to C routine ARKDlsSetMassLinearSolver; see
+   farkode.h for further details */
+void FARK_DLSMASSINIT(int *time_dep, int *ier) {
+  if ( (ARK_arkodemem == NULL) || (F2C_ARKODE_mass_sol == NULL) ||
+       (F2C_ARKODE_mass_matrix == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = ARKDlsSetMassLinearSolver(ARK_arkodemem, F2C_ARKODE_mass_sol,
+                                   F2C_ARKODE_mass_matrix, *time_dep);
+  ARK_mass_ls = ARK_LS_DIRECT;
   return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C "set" routines for the ARKSpfgmr solver; 
-   see farkode.h for further details */
-void FARK_SPFGMRREINIT(int *pretype, int *gstype, 
-		       realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_SPFGMR;
+/* Fortran interface to C routine ARKSpilsSetLinearSolver; see 
+   farkode.h for further details */
+void FARK_SPILSINIT(int *ier) {
+  if ( (ARK_arkodemem == NULL) || (F2C_ARKODE_linsol == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = ARKSpilsSetLinearSolver(ARK_arkodemem, F2C_ARKODE_linsol);
+  ARK_ls = ARK_LS_ITERATIVE;
   return;
 }
 
-/* Fortran interface to C "set" routines for the ARKMassSpfgmr solver; 
-   see farkode.h for further details */
-void FARK_MASSSPFGMRREINIT(int *pretype, int *gstype, 
-			   realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetMassPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassGSType(ARK_arkodemem, *gstype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_SPFGMR;
+/* Fortran interface to C routine ARKSpilsSetMassLinearSolver; see 
+   farkode.h for further details */
+void FARK_SPILSMASSINIT(int *time_dep, int *ier) {
+  if ( (ARK_arkodemem == NULL) || (F2C_ARKODE_mass_sol == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = ARKSpilsSetMassLinearSolver(ARK_arkodemem, 
+                                     F2C_ARKODE_mass_sol, 
+                                     *time_dep);
+  ARK_mass_ls = ARK_LS_ITERATIVE;
   return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C "set" routines for the ARKPcg solver; 
+/* Fortran interfaces to C "set" routines for the ARKSpils solver;
    see farkode.h for further details */
-void FARK_PCGREINIT(int *pretype, int *maxl, 
-		    realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMaxl(ARK_arkodemem, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_ls = ARK_LS_PCG;
+void FARK_SPILSSETEPSLIN(realtype *eplifac, int *ier) {
+  if (ARK_ls == ARK_LS_ITERATIVE)
+    *ier = ARKSpilsSetEpsLin(ARK_arkodemem, *eplifac);
+  else
+    *ier = 1;
   return;
 }
 
-/* Fortran interface to C "set" routines for the ARKMassPcg solver; 
-   see farkode.h for further details */
-void FARK_MASSPCGREINIT(int *pretype, int *maxl, 
-			realtype *delt, int *ier) {
-
-  *ier = ARKSpilsSetMassPrecType(ARK_arkodemem, *pretype);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassMaxl(ARK_arkodemem, *maxl);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *delt);
-  if (*ier != ARKSPILS_SUCCESS) return;
-
-  ARK_mass_ls = ARK_LS_PCG;
+void FARK_SPILSSETMASSEPSLIN(realtype *eplifac, int *ier) {
+  if (ARK_mass_ls == ARK_LS_ITERATIVE)
+    *ier = ARKSpilsSetMassEpsLin(ARK_arkodemem, *eplifac);
+  else
+    *ier = 1;
   return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKode (the main integrator); 
+/* Fortran interface to C routine ARKode (the main integrator);
    see farkode.h for further details */
-void FARK_ARKODE(realtype *tout, realtype *t, realtype *y, 
+void FARK_ARKODE(realtype *tout, realtype *t, realtype *y,
 		 int *itask, int *ier) {
 
   /* attach user solution array to solver memory */
@@ -975,24 +656,24 @@ void FARK_ARKODE(realtype *tout, realtype *t, realtype *y,
   ARKodeGetWorkSpace(ARK_arkodemem,
 		     &ARK_iout[0],          /* LENRW   */
 		     &ARK_iout[1]);         /* LENIW   */
-  ARKodeGetIntegratorStats(ARK_arkodemem, 
+  ARKodeGetIntegratorStats(ARK_arkodemem,
 			   &ARK_iout[2],    /* NST     */
 			   &ARK_iout[3],    /* NST_STB */
-			   &ARK_iout[4],    /* NST_ACC */ 
-			   &ARK_iout[5],    /* NST_ATT */ 
-			   &ARK_iout[6],    /* NFE     */ 
-			   &ARK_iout[7],    /* NFI     */ 
-			   &ARK_iout[8],    /* NSETUPS */ 
-			   &ARK_iout[9],    /* NETF    */ 
+			   &ARK_iout[4],    /* NST_ACC */
+			   &ARK_iout[5],    /* NST_ATT */
+			   &ARK_iout[6],    /* NFE     */
+			   &ARK_iout[7],    /* NFI     */
+			   &ARK_iout[8],    /* NSETUPS */
+			   &ARK_iout[9],    /* NETF    */
 			   &ARK_rout[0],    /* H0U     */
-			   &ARK_rout[1],    /* HU      */ 
-			   &ARK_rout[2],    /* HCUR    */ 
-			   &ARK_rout[3]);   /* TCUR    */ 
-  ARKodeGetTolScaleFactor(ARK_arkodemem, 
+			   &ARK_rout[1],    /* HU      */
+			   &ARK_rout[2],    /* HCUR    */
+			   &ARK_rout[3]);   /* TCUR    */
+  ARKodeGetTolScaleFactor(ARK_arkodemem,
 			  &ARK_rout[4]);    /* TOLSFAC */
   ARKodeGetNonlinSolvStats(ARK_arkodemem,
-                          &ARK_iout[10],    /* NNI     */
-                          &ARK_iout[11]);   /* NCFN    */
+                           &ARK_iout[10],   /* NNI     */
+                           &ARK_iout[11]);  /* NCFN    */
   
   /* If root finding is on, load those outputs as well */
   if (ARK_nrtfn != 0)
@@ -1000,25 +681,13 @@ void FARK_ARKODE(realtype *tout, realtype *t, realtype *y,
 
   /* Attach linear solver outputs */
   switch(ARK_ls) {
-  case ARK_LS_DENSE:
-  case ARK_LS_BAND:
-  case ARK_LS_LAPACKDENSE:
-  case ARK_LS_LAPACKBAND:
+  case ARK_LS_DIRECT:
     ARKDlsGetWorkSpace(ARK_arkodemem, &ARK_iout[13], &ARK_iout[14]);  /* LENRWLS, LENIWLS */
     ARKDlsGetLastFlag(ARK_arkodemem, &ARK_iout[15]);                  /* LSTF  */
     ARKDlsGetNumRhsEvals(ARK_arkodemem, &ARK_iout[16]);               /* NFELS */
     ARKDlsGetNumJacEvals(ARK_arkodemem, &ARK_iout[17]);               /* NJE   */
     break;
-  case ARK_LS_KLU:
-  case ARK_LS_SUPERLUMT:
-    ARKSlsGetLastFlag(ARK_arkodemem, &ARK_iout[15]);                  /* LSTF  */
-    ARKSlsGetNumJacEvals(ARK_arkodemem, &ARK_iout[17]);               /* NJE   */
-    break;
-  case ARK_LS_SPGMR:
-  case ARK_LS_SPBCG:
-  case ARK_LS_SPTFQMR:
-  case ARK_LS_SPFGMR:
-  case ARK_LS_PCG:
+  case ARK_LS_ITERATIVE:
     ARKSpilsGetWorkSpace(ARK_arkodemem, &ARK_iout[13], &ARK_iout[14]); /* LENRWLS, LENIWLS */
     ARKSpilsGetLastFlag(ARK_arkodemem, &ARK_iout[15]);                 /* LSTF  */
     ARKSpilsGetNumRhsEvals(ARK_arkodemem, &ARK_iout[16]);              /* NFELS */
@@ -1031,24 +700,14 @@ void FARK_ARKODE(realtype *tout, realtype *t, realtype *y,
 
   /* Attach mass matrix linear solver outputs */
   switch(ARK_mass_ls) {
-  case ARK_LS_DENSE:
-  case ARK_LS_BAND:
-  case ARK_LS_LAPACKDENSE:
-  case ARK_LS_LAPACKBAND:
+  case ARK_LS_DIRECT:
     ARKDlsGetMassWorkSpace(ARK_arkodemem, &ARK_iout[22], &ARK_iout[23]);  /* LENRWMS, LENIWMS */
     ARKDlsGetLastMassFlag(ARK_arkodemem, &ARK_iout[24]);                  /* LSTMF */
-    ARKDlsGetNumMassEvals(ARK_arkodemem, &ARK_iout[25]);                  /* NME   */
-    break;
-  case ARK_LS_KLU:
-  case ARK_LS_SUPERLUMT:
-    ARKSlsGetLastMassFlag(ARK_arkodemem, &ARK_iout[24]);                  /* LSTMF */
-    ARKSlsGetNumMassEvals(ARK_arkodemem, &ARK_iout[25]);                  /* NME   */
+    ARKDlsGetNumMassSetups(ARK_arkodemem, &ARK_iout[25]);                 /* NMSETUP */
+    ARKDlsGetNumMassSolves(ARK_arkodemem, &ARK_iout[26]);                 /* NMSOLVES */
+    ARKDlsGetNumMassMult(ARK_arkodemem, &ARK_iout[27]);                   /* NMMULTS */
     break;
-  case ARK_LS_SPGMR:
-  case ARK_LS_SPBCG:
-  case ARK_LS_SPTFQMR:
-  case ARK_LS_SPFGMR:
-  case ARK_LS_PCG:
+  case ARK_LS_ITERATIVE:
     ARKSpilsGetMassWorkSpace(ARK_arkodemem, &ARK_iout[22], &ARK_iout[23]); /* LENRWMS, LENIWMS */
     ARKSpilsGetLastMassFlag(ARK_arkodemem, &ARK_iout[24]);                 /* LSTMF */
     ARKSpilsGetNumMassPrecEvals(ARK_arkodemem, &ARK_iout[25]);             /* NMPE  */
@@ -1061,7 +720,7 @@ void FARK_ARKODE(realtype *tout, realtype *t, realtype *y,
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeGetDky; see farkode.h 
+/* Fortran interface to C routine ARKodeGetDky; see farkode.h
    for further details */
 void FARK_DKY(realtype *t, int *k, realtype *dky, int *ier) {
 
@@ -1082,7 +741,7 @@ void FARK_DKY(realtype *t, int *k, realtype *dky, int *ier) {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeGetErrWeights; see 
+/* Fortran interface to C routine ARKodeGetErrWeights; see
    farkode.h for further details */
 void FARK_GETERRWEIGHTS(realtype *eweight, int *ier) {
 
@@ -1103,7 +762,28 @@ void FARK_GETERRWEIGHTS(realtype *eweight, int *ier) {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeGetEstLocalErrors; see 
+/* Fortran interface to C routine ARKodeGetResWeights; see 
+   farkode.h for further details */
+void FARK_GETRESWEIGHTS(realtype *rweight, int *ier) {
+
+  /* store pointer existing F2C_ARKODE_vec data array */
+  realtype *f2c_data = N_VGetArrayPointer(F2C_ARKODE_vec);
+
+  /* attach output data array to F2C_ARKODE_vec */
+  N_VSetArrayPointer(rweight, F2C_ARKODE_vec);
+
+  /* call ARKodeGetResWeights */
+  *ier = 0;
+  *ier = ARKodeGetResWeights(ARK_arkodemem, F2C_ARKODE_vec);
+
+  /* reattach F2C_ARKODE_vec to previous data array */
+  N_VSetArrayPointer(f2c_data, F2C_ARKODE_vec);
+  return;
+}
+
+/*=============================================================*/
+
+/* Fortran interface to C routine ARKodeGetEstLocalErrors; see
    farkode.h for further details */
 void FARK_GETESTLOCALERR(realtype *ele, int *ier) {
 
@@ -1124,24 +804,48 @@ void FARK_GETESTLOCALERR(realtype *ele, int *ier) {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeFree; see farkode.h for 
+/* Fortran interface to C routine ARKodeFree; see farkode.h for
    further details */
 void FARK_FREE() {
 
   ARKodeMem ark_mem;
   ark_mem = (ARKodeMem) ARK_arkodemem;
-  free(ark_mem->ark_user_data); ark_mem->ark_user_data = NULL;
 
+  /* free DLS/SPILS interface */
+  if (ark_mem->ark_lfree)
+    ark_mem->ark_lfree(ark_mem);
+  ark_mem->ark_lmem = NULL;
+
+  /* free mass DLS/SPILS interface */
+  if (ark_mem->ark_mfree)
+    ark_mem->ark_mfree(ark_mem);
+  ark_mem->ark_mass_mem = NULL;
+
+  /* free user_data structure */
+  if (ark_mem->ark_user_data)
+    free(ark_mem->ark_user_data);
+  ark_mem->ark_user_data = NULL;
+
+  /* free main integrator memory structure */
   ARKodeFree(&ARK_arkodemem);
 
+  /* free interface vector / matrices / linear solvers */
   N_VSetArrayPointer(NULL, F2C_ARKODE_vec);
   N_VDestroy(F2C_ARKODE_vec);
+  if (F2C_ARKODE_matrix)
+    SUNMatDestroy(F2C_ARKODE_matrix);
+  if (F2C_ARKODE_mass_matrix)
+    SUNMatDestroy(F2C_ARKODE_mass_matrix);
+  if (F2C_ARKODE_linsol)
+    SUNLinSolFree(F2C_ARKODE_linsol);
+  if (F2C_ARKODE_mass_sol)
+    SUNLinSolFree(F2C_ARKODE_mass_sol);
   return;
 }
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKodeWriteParameters; see 
+/* Fortran interface to C routine ARKodeWriteParameters; see
    farkode.h for further details */
 void FARK_WRITEPARAMETERS(int *ier) {
   *ier = ARKodeWriteParameters(ARK_arkodemem, stdout);
@@ -1150,7 +854,7 @@ void FARK_WRITEPARAMETERS(int *ier) {
 
 /*=============================================================*/
 
-/* C interface to user-supplied FORTRAN function FARKEFUN; see 
+/* C interface to user-supplied FORTRAN function FARKEFUN; see
    farkode.h for further details */
 int FARKfe(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
 
@@ -1161,14 +865,14 @@ int FARKfe(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
   dydata = N_VGetArrayPointer(ydot);
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_EXP_FUN(&t, ydata, dydata, ARK_userdata->ipar, 
+  FARK_EXP_FUN(&t, ydata, dydata, ARK_userdata->ipar,
 	       ARK_userdata->rpar, &ier);
   return(ier);
 }
 
 /*=============================================================*/
 
-/* C interface to user-supplied FORTRAN function FARKIFUN; see 
+/* C interface to user-supplied FORTRAN function FARKIFUN; see
    farkode.h for further details */
 int FARKfi(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
 
@@ -1179,7 +883,7 @@ int FARKfi(realtype t, N_Vector y, N_Vector ydot, void *user_data) {
   dydata = N_VGetArrayPointer(ydot);
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_IMP_FUN(&t, ydata, dydata, ARK_userdata->ipar, 
+  FARK_IMP_FUN(&t, ydata, dydata, ARK_userdata->ipar,
 	       ARK_userdata->rpar, &ier);
   return(ier);
 }
diff --git a/src/arkode/fcmix/farkode.h b/src/arkode/fcmix/farkode.h
index c98665b..4c7c433 100644
--- a/src/arkode/fcmix/farkode.h
+++ b/src/arkode/fcmix/farkode.h
@@ -2,13 +2,13 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and
  * Lawrence Livermore National Security
  *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Southern Methodist University and Lawrence Livermore
  * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
+ * Produced at Southern Methodist University and the Lawrence
  * Livermore National Laboratory.
  *
  * All rights reserved.
@@ -16,25 +16,25 @@
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
  * This is the header file for FARKODE, the Fortran interface to
- * the ARKODE package.                                            
+ * the ARKODE package.
  *--------------------------------------------------------------*/
 
 /*===============================================================
                 FARKODE Interface Package
 
- The FARKODE Interface Package is a package of C functions which 
- support the use of the ARKODE solver, for the solution of ODE 
- systems 
-         M(t) dy/dt = fe(t,y) + fi(t,y), 
+ The FARKODE Interface Package is a package of C functions which
+ support the use of the ARKODE solver, for the solution of ODE
+ systems
+         M(t) dy/dt = fe(t,y) + fi(t,y),
  in a mixed Fortran/C setting.  While ARKODE is written in C, it
  is assumed here that the user's calling program and user-supplied
- problem-defining routines are written in Fortran.  This package 
- provides the necessary interface to ARKODE any acceptable NVECTOR
- implementation.
- 
- A summary of the user-callable functions, with the corresponding 
+ problem-defining routines are written in Fortran.  This package
+ provides the necessary interface to ARKODE for any acceptable
+ NVECTOR implementation.
+
+ A summary of the user-callable functions, with the corresponding
  ARKODE functions, are as follows:
- 
+
    Fortran                    ARKODE
    ---------------------      --------------------------------
    FNVINITS                   N_VNew_Serial
@@ -42,7 +42,41 @@
    FNVINITOMP                 N_VNew_OpenMP
    FNVINITPTS                 N_VNew_Pthreads
 
-   FARKMALLOC                 ARKodeCreate, ARKodeSetUserData, 
+   FSUNBANDMATINIT            SUNBandMatrix
+   FSUNDENSEMATINIT           SUNDenseMatrix
+   FSUNSPARSEMATINIT          SUNSparseMatrix
+
+   FSUNBANDMASSMATINIT        SUNBandMatrix
+   FSUNDENSEMASSMATINIT       SUNDenseMatrix
+   FSUNSPARSEMASSMATINIT      SUNSparseMatrix
+
+   FSUNBANDLINSOLINIT         SUNBandLinearSolver
+   FSUNDENSELINSOLINIT        SUNDenseLinearSolver
+   FSUNKLUINIT                SUNKLU
+   FSUNKLUREINIT              SUNKLUReinit
+   FSUNLAPACKBANDINIT         SUNLapackBand
+   FSUNLAPACKDENSEINIT        SUNLapackDense
+   FSUNPCGINIT                SUNPCG
+   FSUNSPBCGSINIT             SUNSPBCGS
+   FSUNSPFGMRINIT             SUNSPFGMR
+   FSUNSPGMRINIT              SUNSPGMR
+   FSUNSPTFQMRINIT            SUNSPTFQMR
+   FSUNSUPERLUMTINIT          SUNSuperLUMT
+
+   FSUNMASSBANDLINSOLINIT     SUNBandLinearSolver
+   FSUNMASSDENSELINSOLINIT    SUNDenseLinearSolver
+   FSUNMASSKLUINIT            SUNKLU
+   FSUNMASSKLUREINIT          SUNKLUReinit
+   FSUNMASSLAPACKBANDINIT     SUNLapackBand
+   FSUNMASSLAPACKDENSEINIT    SUNLapackDense
+   FSUNMASSPCGINIT            SUNPCG
+   FSUNMASSSPBCGSINIT         SUNSPBCGS
+   FSUNMASSSPFGMRINIT         SUNSPFGMR
+   FSUNMASSSPGMRINIT          SUNSPGMR
+   FSUNMASSSPTFQMRINIT        SUNSPTFQMR
+   FSUNMASSSUPERLUMTINIT      SUNSuperLUMT
+
+   FARKMALLOC                 ARKodeCreate, ARKodeSetUserData,
                                  and ARKodeInit
    FARKREINIT                 ARKReInit
    FARKRESIZE                 ARKResize
@@ -60,75 +94,39 @@
    FARKSETDIAGNOSTICS         ARKodeSetDiagnostics
    FARKSTOPDIAGNOSTICS        (none)
 
-   FARKDENSE                  ARKDense
-   FARKDENSESETJAC            ARKDlsSetDenseJacFn
-   FARKMASSDENSE              ARKMassDense
-   FARKDENSESETMASS           ARKDlsSetDenseMassFn
-
-   FARKBAND                   ARKBand
-   FARKBANDSETJAC             ARKDlsSetBandJacFn
-   FARKMASSBAND               ARKMassBand
-   FARKBANDSETMASS            ARKDlsSetBandMassFn
-
-   FARKLAPACKDENSE            ARKLapackDense
-   FARKLAPACKDENSESETJAC      ARKDlsSetDenseJacFn
-   FARKMASSLAPACKDENSE        ARKMassLapackDense
-   FARKLAPACKDENSESETMASS     ARKDlsSetDenseMassFn
-
-   FARKLAPACKBAND             ARKLapackBand
-   FARKLAPACKBANDSETJAC       ARKDlsSetBandJacFn
-   FARKMASSLAPACKBAND         ARKMassLapackBand
-   FARKLAPACKBANDSETMASS      ARKDlsSetBandMassFn
-
-   FARKKLU                    ARKKLU
-   FARKKLUREINIT              ARKKLUReinit
-   FARKSUPERLUMT              ARKSuperLUMT
-   FARKSPARSESETJAC           ARKSlsSetSparseJacFn
-   FARKMASSKLU                ARKMassKLU
-   FARKMASSKLUREINIT          ARKMassKLUReinit
-   FARKMASSSUPERLUMT          ARKMassSuperLUMT
-   FARKSPARSESETMASS          ARKSlsSetSparseMassFn
-
-   FARKSPGMR                  ARKSpgmr and ARKSpilsSet*
-   FARKSPGMRREINIT            ARKSpilsSet*
-   FARKMASSSPGMR              ARKMassSpgmr and ARKSpilsSetMass*
-   FARKMASSSPGMRREINIT        ARKSpilsSetMass*
-
-   FARKSPBCG                  ARKSpbcg and ARKSpilsSet*
-   FARKSPBCGREINIT            ARKSpilsSet*
-   FARKMASSSPBCG              ARKMassSpbcg and ARKSpilsSetMass*
-   FARKMASSSPBCGREINIT        ARKSpilsSetMass*
-
-   FARKSPTFQMR                ARKSptfqmr and ARKSpilsSet*
-   FARKSPTFQMRREINIT          ARKSpilsSet*
-   FARKMASSSPTFQMR            ARKMassSptfqmr and ARKSpilsSetMass*
-   FARKMASSSPTFQMRREINIT      ARKSpilsSetMass*
-
-   FARKSPFGMR                 ARKSpfgmr and ARKSpilsSet*
-   FARKSPFGMRREINIT           ARKSpilsSet*
-   FARKMASSSPFGMR             ARKwMASSMassSpfgmr and ARKSpilsSetMASS*
-   FARKMASSSPFGMRREINIT       ARKSpilsSetMASS*
-
-   FARKPCG                    ARKPcg and ARKSpilsSet*
-   FARKPCGREINIT              ARKSpilsSet*
-   FARKMASSPCG                ARKMASSPcg and ARKSpilsSetMASS*
-   FARKMASSPCGREINIT          ARKSpilsSetMASS*
-
-   FARKSPILSSETJAC            ARKSpilsSetJacTimesVecFn
+   FARKDLSINIT                ARKDlsSetLinearSolver
+   FARKDENSESETJAC            ARKDlsSetJacFn
+   FARKBANDSETJAC             ARKDlsSetJacFn
+   FARKSPARSESETJAC           ARKDlsSetJacFn
+
+   FARKDLSMASSINIT            ARKDlsSetMassLinearSolver
+   FARKDENSESETMASS           ARKDlsSetMassFn
+   FARKBANDSETMASS            ARKDlsSetMassFn
+   FARKSPARSESETMASS          ARKDlsSetMassFn
+
+   FARKSPILSINIT              ARKSpilsSetLinearSolver
+   FARKSPILSSETEPSLIN         ARKSpilsSetEpsLin
+
+   FARKSPILSMASSINIT          ARKSpilsSetMassLinearSolver
+   FARKSPILSSETMASSEPSLIN     ARKSpilsSetMassEpsLin
+
+   FARKSPILSSETJAC            ARKSpilsSetJacTimes
    FARKSPILSSETPREC           ARKSpilsSetPreconditioner
-   FARKSPILSSETMASS           ARKSpilsSetMassTimesVecFn
+
+   FARKSPILSSETMASS           ARKSpilsSetMassTimes
    FARKSPILSSETMASSPREC       ARKSpilsSetMassPreconditioner
- 
+
    FARKODE                    ARKode, ARKodeGet*, and ARK*Get*
    FARKDKY                    ARKodeGetDky
 
    FARKGETERRWEIGHTS          ARKodeGetErrWeights
+   FARKGETRESWEIGHTS          ARKodeGetResWeights
    FARKGETESTLOCALERR         ARKodeGetEstLocalErrors
 
    FARKFREE                   ARKodeFree
    ---------------------      --------------------------------
 
- 
+
  The user-supplied functions, each listed with the corresponding interface
  function which calls it (and its type within ARKODE), are as follows:
 
@@ -136,17 +134,19 @@
    -------------      ------------------       -----------------------
    FARKIFUN           FARKfi                   ARKRhsFn
    FARKEFUN           FARKfe                   ARKRhsFn
-   FARKDJAC           FARKDenseJac             ARKDlsDenseJacFn
-   FARKDMASS          FARKDenseMass            ARKDlsDenseMassFn
-   FARKBJAC           FARKBandJac              ARKDlsBandJacFn
-   FARKBMASS          FARKBandMass             ARKDlsBandMassFn
-   FARKSPJAC          FARKSparseJac            ARKSlsSparseJacFn
-   FARKSPMASS         FARKSparseMass           ARKSlsSparseMassFn
-   FARKPSOL           FARKPSol                 ARKSpilsPrecSolveFn
+   FARKDJAC           FARKDenseJac             ARKDlsJacFn
+   FARKDMASS          FARKDenseMass            ARKDlsMassFn
+   FARKBJAC           FARKBandJac              ARKDlsJacFn
+   FARKBMASS          FARKBandMass             ARKDlsMassFn
+   FARKSPJAC          FARKSparseJac            ARKDlsJacFn
+   FARKSPMASS         FARKSparseMass           ARKDlsMassFn
    FARKPSET           FARKPSet                 ARKSpilsPrecSetupFn
-   FARKMASSPSOL       FARKMassPSol             ARKSpilsMassPrecSolveFn
+   FARKPSOL           FARKPSol                 ARKSpilsPrecSolveFn
    FARKMASSPSET       FARKMassPSet             ARKSpilsMassPrecSetupFn
+   FARKMASSPSOL       FARKMassPSol             ARKSpilsMassPrecSolveFn
+   FARKJTSETUP        FARKJTSetup              ARKSpilsJacTimesSetupFn
    FARKJTIMES         FARKJtimes               ARKSpilsJacTimesVecFn
+   FARKMTSETUP        FARKMTSetup              ARKSpilsMassTimesSetupFn
    FARKMTIMES         FARKMtimes               ARKSpilsMassTimesVecFn
    FARKEWT            FARKEwt                  ARKEwtFn
    FARKADAPT          FARKAdapt                ARKAdaptFn
@@ -156,52 +156,57 @@
  In contrast to the case of direct use of ARKODE, and of most Fortran ODE
  solvers, the names of all user-supplied routines here are fixed, in
  order to maximize portability for the resulting mixed-language program.
- 
- Important note on portability:  In this package, the names of the interface 
- functions, and the names of the Fortran user routines called by them, appear 
- as dummy names which are mapped to actual values by a series of definitions, 
- in this and other header files.
- 
+
+ Important note on portability:  In this package, the names of the 
+ interface functions, and the names of the Fortran user routines called by
+ them, appear as dummy names which are mapped to actual values by a series 
+ of definitions, in this and other header files.
+
  =============================================================================
- 
+
                   Usage of the FARKODE Interface Package
- 
- The usage of FARKODE requires calls to five or more interface
+
+ The usage of FARKODE requires calls to a variety of interface
  functions, depending on the method options selected, and one or more
  user-supplied routines which define the problem to be solved.  These
  function calls and user routines are summarized separately below.
- 
+
  Some details are omitted, and the user is referred to the ARKODE user 
  documentation for more complete information.  Information on the arguments 
  of any given user-callable interface routine, or of a given user-supplied 
- function called by an interface function, can be found in the documentation 
- on the corresponding function in the ARKODE package.
- 
+ function called by an interface function, can be found in the 
+ documentation on the corresponding function in the ARKODE package.
+
  The number labels on the instructions below end with s for instructions
- that are specific to use with the N_VSerial package; similarly those that 
- end with p are specific to use with the N_VParallel package.
+ that are specific to use with the serial/OpenMP/PThreads NVector package; 
+ similarly those that end with p are specific to use with the N_VParallel package.
 
  -----------------------------------------------------------------------------
 
                                Data Types
 
- Throughout this documentation, we will refer to data types according to their
- usage in SUNDIALS.  The equivalent types to these may vary, depending on your
- computer architecture and on how SUNDIALS was compiled.  A Fortran user 
- should take care that all arguments passed through this Fortran/C interface 
- are declared of the appropriate type.
- 
- Integers: SUNDIALS uses both 'int' and 'long int' types:
+ Throughout this documentation, we will refer to data types according to 
+ their usage in SUNDIALS.  The equivalent types to these may vary, 
+ depending on your computer architecture and on how SUNDIALS was compiled.  
+ A Fortran user should take care that all arguments passed through this 
+ Fortran/C interface are declared of the appropriate type.
+
+ Integers: SUNDIALS uses 'int', 'long int' and 'sunindextype' types.  At 
+ compilation, SUNDIALS allows the configuration of the 'index' type, that 
+ accepts values of 32-bit signed and 64-bit signed.  This choice dictates 
+ the size of a SUNDIALS 'sunindextype' variable.
    int      -- equivalent to an INTEGER or INTEGER*4 in Fortran
-   long int -- this will depend on the computer architecture:
-                 32-bit -- equivalent to an INTEGER or INTEGER*4 in Fortran
-                 64-bit -- equivalent to an INTEGER*8 in Fortran
+   long int -- equivalent to an INTEGER*8 in Fortran (Linux/UNIX/OSX), or 
+               equivalent to an INTEGER in Windows
+   sunindextype -- this will depend on the SUNDIALS configuration:
+               32-bit -- equivalent to an INTEGER or INTEGER*4 in Fortran
+               64-bit -- equivalent to an INTEGER*8 in Fortran
 	      
  Real numbers:  At compilation, SUNDIALS allows the configuration option 
- '--with-precision', that accepts values of 'single', 'double' or 'extended' 
- (the default is 'double').  This choice dictates the size of a SUNDIALS 
- 'realtype' variable.  The corresponding Fortran types for these 'realtype' 
- sizes are:
+ '--with-precision', that accepts values of 'single', 'double' or 
+ 'extended' (the default is 'double').  This choice dictates the size of a 
+ SUNDIALS 'realtype' variable.  The corresponding Fortran types for these 
+ 'realtype' sizes are:
    single   -- equivalent to a REAL or REAL*4 in Fortran
    double   -- equivalent to a DOUBLE PRECISION or REAL*8 in Fortran
    extended -- equivalent to a REAL*16 in Fortran
@@ -209,20 +214,21 @@
  -----------------------------------------------------------------------------
 
  (1) User-supplied right-hand side routines: FARKIFUN and FARKEFUN
-     The user must in all cases supply at least one of the following Fortran 
-     routines:
+
+     The user must in all cases supply at least one of the following 
+     Fortran routines:
 
        SUBROUTINE FARKIFUN(T, Y, YDOT, IPAR, RPAR, IER)
 
-     Sets the YDOT array to fi(T,Y), the implicit portion of the right-hand 
-     side of the ODE system, as function of time T and the state variable 
+     Sets the YDOT array to fi(T,Y), the implicit portion of the right-hand
+     side of the ODE system, as function of time T and the state variable
      array Y.
 
        SUBROUTINE FARKEFUN(T, Y, YDOT, IPAR, RPAR, IER)
 
-     Sets the YDOT array to fe(t,y), the explicit portion of the right-hand 
-     side of the ODE system, as function of time T and the state variable 
-     array Y.  
+     Sets the YDOT array to fe(t,y), the explicit portion of the right-hand
+     side of the ODE system, as function of time T and the state variable
+     array Y.
 
      The arguments are:
        Y    -- array containing state variables [realtype, input]
@@ -232,21 +238,22 @@
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                  >0 if a recoverable error occurred,
                  <0 if an unrecoverable error ocurred.
- 
+
  (2s) Optional user-supplied dense Jacobian approximation routine: FARKDJAC
 
-     As an option when using the DENSE linear solver, the user may supply a
-     routine that computes a dense approximation of the system Jacobian 
-     J = dfi(t,y)/dy.  If supplied, it must have the following form:
+     As an option when using the Dense or LapackDense linear solvers, the 
+     user may supply a routine that computes a dense approximation of the 
+     system Jacobian J = dfi(t,y)/dy.  If supplied, it must have the 
+     following form:
 
-       SUBROUTINE FARKDJAC(NEQ, T, Y, FY, DJAC, H, IPAR, RPAR, WK1, WK2, 
+       SUBROUTINE FARKDJAC(NEQ, T, Y, FY, DJAC, H, IPAR, RPAR, WK1, WK2,
       &                    WK3, IER)
 
-     Typically this routine will use only NEQ, T, Y, and DJAC. It must compute
-     the Jacobian and store it column-wise in DJAC.
+     Typically this routine will use only NEQ, T, Y, and DJAC. It must 
+     compute the Jacobian and store it column-wise in DJAC.
 
      The arguments are:
        NEQ  -- number of rows in the matrix [long int, input]
@@ -260,52 +267,26 @@
                FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
-       WK*  -- array containing temporary workspace of same size as Y 
+       WK*  -- array containing temporary workspace of same size as Y
                [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                  >0 if a recoverable error occurred,
                  <0 if an unrecoverable error ocurred.
- 
- (2s) Optional user-supplied dense mass matrix routine: FARKDMASS
-
-     Required when using the DENSE or LAPACKDENSE mass matrix linear solvers,
-     the user must supply a routine that computes the system mass matrix M.  
-     This routine must have the following form: 
 
-       SUBROUTINE FARKDMASS(NEQ, T, DMASS, IPAR, RPAR, WK1, WK2, WK3, IER)
-
-     Typically this routine will use only NEQ, T, and DMASS. It must compute
-     the mass matrix and store it column-wise in DMASS.
-
-     The arguments are:
-       NEQ   -- number of rows in the matrix [long int, input]
-       T     -- current time [realtype, input]
-       DMASS -- 2D array containing the mass matrix entries [realtype 
-                of size (NEQ,NEQ), output]
-       IPAR  -- array containing integer user data that was passed to
-                FARKMALLOC [long int, input]
-       RPAR  -- array containing real user data that was passed to
-                FARKMALLOC [realtype, input]
-       WK*   -- array containing temporary workspace of same size as Y 
-                [realtype, input]
-       IER   -- return flag [int, output]:
-                   0 if successful, 
-                  >0 if a recoverable error occurred,
-                  <0 if an unrecoverable error ocurred.
- 
- (3s) Optional user-supplied band Jacobian approximation routine: FARKBJAC
+ (2s) Optional user-supplied band Jacobian approximation routine: FARKBJAC
 
-     As an option when using the BAND linear solver, the user may supply a
-     routine that computes a band approximation of the system Jacobian 
-     J = dfi(t,y)/dy. If supplied, it must have the following form:
+     As an option when using the Band or LapackBand linear solvers, the 
+     user may supply a routine that computes a band approximation of the 
+     system Jacobian J = dfi(t,y)/dy. If supplied, it must have the 
+     following form:
 
        SUBROUTINE FARKBJAC(NEQ, MU, ML, MDIM, T, Y, FY, BJAC, H,
       &                    IPAR, RPAR, WK1, WK2, WK3, IER)
 
-     Typically this routine will use only NEQ, MU, ML, T, Y, and BJAC. It 
+     Typically this routine will use only NEQ, MU, ML, T, Y, and BJAC. It
      must load the MDIM by N array BJAC with the Jacobian matrix at the
-     current (t,y) in band form.  Store in BJAC(k,j) the Jacobian element 
+     current (t,y) in band form.  Store in BJAC(k,j) the Jacobian element
      J(i,j)  with k = i - j + MU + 1 (k = 1 ... ML+MU+1) and j = 1 ... N.
 
      The arguments are:
@@ -323,18 +304,211 @@
                FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
-       WK*  -- array containing temporary workspace of same size as Y 
+       WK*  -- array containing temporary workspace of same size as Y
                [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                  >0 if a recoverable error occurred,
                  <0 if an unrecoverable error ocurred.
  
- (4s) Optional user-supplied band Mass matrix routine: FARKBMASS
+ (2s) User-supplied sparse Jacobian approximation routine: FARKSPJAC
+
+     Required when using the KLU or SuperLUMT linear solvers, the 
+     user must supply a routine that computes a compressed-sparse-column 
+     [or compressed-sparse-row] approximation of the system Jacobian 
+     J = dfi(t,y)/dy.  This routine must have the following form:
+
+       SUBROUTINE FARKSPJAC(T, Y, FY, N, NNZ, JDATA, JRVALS,
+      &                     JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
+
+     Typically this routine will use only M, N, NNZ, JDATA, JRVALS and 
+     JCPTRS. It must load the N by N compressed sparse column [or 
+     compressed sparse row] matrix with storage for NNZ nonzeros, stored 
+     in the arrays JDATA (nonzero values), JRVALS (row [or column] indices 
+     for each nonzero), JCOLPTRS (indices for start of each column 
+     [or row]), with the Jacobian matrix at the current (t,y) in CSC [or 
+     CSR] format (see sunmatrix_sparse.h for more information).
+
+     The arguments are:
+         T    -- current time [realtype, input]
+         Y    -- array containing state variables [realtype, input]
+         FY   -- array containing state derivatives [realtype, input]
+         N    -- number of matrix rows/columns in Jacobian [long int, input]
+         NNZ  -- allocated length of nonzero storage [long int, input]
+        JDATA -- nonzero values in Jacobian
+                 [realtype of length NNZ, output]
+       JRVALS -- row [or column] indices for each nonzero in Jacobian
+                 [long int of length NNZ, output]
+       JCPTRS -- pointers to each Jacobian column [or row] in preceding 
+                 arrays [long int of length N+1, output]
+         H    -- current step size [realtype, input]
+         IPAR -- array containing integer user data that was passed to
+                 FARKMALLOC [long int, input]
+         RPAR -- array containing real user data that was passed to
+                 FARKMALLOC [realtype, input]
+         WK*  -- array containing temporary workspace of same size as Y
+                 [realtype, input]
+         IER  -- return flag [int, output]:
+                    0 if successful,
+                   >0 if a recoverable error occurred,
+                   <0 if an unrecoverable error ocurred.
+ 
+     NOTE: this may ONLY be used if SUNDIALS has been configured with 
+     sunindextype set to 64-bit integers.
+ 
+ (2) Optional user-supplied Jacobian-vector product setup routine: 
+     FARKJTSETUP
+
+     As an option when using the ARKSpils iterative linear solver 
+     interface, the user may supply a routine that computes the product of 
+     the system Jacobian J = dfi(t,y)/dy and a given vector v, as well as 
+     a routine to set up any user data structures in preparation for the 
+     matrix-vector product.  If a 'setup' routine is supplied, it must 
+     have the following form:
+
+       SUBROUTINE FARKJTSETUP(T, Y, FY, H, IPAR, RPAR, IER)
+
+     Typically this routine will use only T and Y.  It must perform any 
+     relevant preparations for subsequent calls to the user-provided 
+     FARKJTIMES routine (see below).  
+
+     The arguments are:
+       T    -- current time [realtype, input]
+       Y    -- array containing state variables [realtype, input]
+       FY   -- array containing state derivatives [realtype, input]
+       H    -- current step size [realtype, input]
+       IPAR -- array containing integer user data that was passed to
+               FARKMALLOC [long int, input]
+       RPAR -- array containing real user data that was passed to
+               FARKMALLOC [realtype, input]
+       IER  -- return flag [int, output]:
+                  0 if successful, 
+                  nonzero if an error.
+ 
+ (2) Optional user-supplied Jacobian-vector product routine: FARKJTIMES
+
+     As an option when using the ARKSpils linear solver interface, the 
+     user may supply a routine that computes the product of the system 
+     Jacobian J = dfi(t,y)/dy and a given vector v.  If supplied, it 
+     must have the following form:
+
+       SUBROUTINE FARKJTIMES(V, JV, T, Y, FY, H, IPAR, RPAR, WORK, IER)
+
+     Typically this routine will use only NEQ, T, Y, V, and JV.  It must
+     compute the product vector J*v where v is stored in the vector V 
+     and the result J*v is stored in JV.  
+
+     The arguments are:
+       V    -- array containing vector to multiply [realtype, input]
+       JV   -- array containing product vector [realtype, output]
+       T    -- current time [realtype, input]
+       Y    -- array containing state variables [realtype, input]
+       FY   -- array containing state derivatives [realtype, input]
+       H    -- current step size [realtype, input]
+       IPAR -- array containing integer user data that was passed to
+               FARKMALLOC [long int, input]
+       RPAR -- array containing real user data that was passed to
+               FARKMALLOC [realtype, input]
+       WORK -- array containing temporary workspace of same size as Y
+               [realtype, input]
+       IER  -- return flag [int, output]:
+                  0 if successful, 
+                  nonzero if an error.
+
+ (3) Optional user-supplied preconditioner setup/solve routines: FARKPSET 
+   and FARKPSOL
+
+     As an option when using the ARKSPILS linear solver interface, the 
+     user may supply routines to setup and apply the preconditioner.  
+     If supplied, these must have the following form:
+
+       SUBROUTINE FARKPSET(T,Y,FY,JOK,JCUR,GAMMA,H,IPAR,RPAR,IER)
+
+     This routine must set up the preconditioner P to be used in the 
+     subsequent call to FARKPSOL.  The preconditioner (or the product of 
+     the left and right preconditioners if using both) should be an 
+     approximation to the matrix  A(T) = M(T) - GAMMA*J  
+     (M(T) = mass matrix, J = Jacobian),
+
+     The arguments are:
+       T = current time [realtype, input]
+       Y = current state variable array [realtype, input]
+       FY = current state variable derivative array [realtype, input]
+       JOK = flag indicating whether Jacobian-related data needs to be 
+           recomputed [int, input]:
+                  0 = recompute, 
+                  1 = reuse with the current value of GAMMA
+       JCUR = return flag to denote if Jacobian data was recomputed
+           [realtype, output], 1=yes, 0=no
+       GAMMA = Jacobian scaling factor [realtype, input]
+       H = current time step [realtype, input]
+       IPAR = array of user integer data [long int, input/output]
+       RPAR = array with user real data [realtype, input/output]
+       IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+                 >0 = recoverable failure
+                 <0 = non-recoverable failure
+
+     The user-supplied routine FARKPSOL must have the form:
+
+       SUBROUTINE FARKPSOL(T,Y,FY,R,Z,GAMMA,DELTA,LR,IPAR,RPAR,IER)
+
+     Typically this routine will use only T, Y, GAMMA, R, LR, and Z.  It
+     must solve the preconditioner linear system Pz = r.  The preconditioner
+     (or the product of the left and right preconditioners if both are 
+     nontrivial) should be an approximation to the matrix  M(T) - GAMMA*J  
+     (M(T) = mass matrix, J = Jacobian).
+
+     The arguments are:
+       T = current time [realtype, input]
+       Y = current state variable array [realtype, input]
+       FY = current state variable derivative array [realtype, input]
+       R = right-hand side array [realtype, input]
+       Z = solution array [realtype, output]
+       GAMMA = Jacobian scaling factor [realtype, input]
+       DELTA = desired residual tolerance [realtype, input]
+       LR = flag denoting to solve the right or left preconditioner system
+                  1 = left preconditioner
+                  2 = right preconditioner
+       IPAR = array of user integer data [long int, input/output]
+       RPAR = array with user real data [realtype, input/output]
+       IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+                 >0 = recoverable failure
+                 <0 = non-recoverable failure
+
+ (4s) Optional user-supplied dense mass matrix routine: FARKDMASS
+
+     Required when using the Dense or LapackDense mass matrix linear 
+     solvers, the user must supply a routine that computes the system mass 
+     matrix M.  This routine must have the following form: 
+
+       SUBROUTINE FARKDMASS(NEQ, T, DMASS, IPAR, RPAR, WK1, WK2, WK3, IER)
+
+     Typically this routine will use only NEQ, T, and DMASS. It must compute
+     the mass matrix and store it column-wise in DMASS.
+
+     The arguments are:
+       NEQ   -- number of rows in the matrix [long int, input]
+       T     -- current time [realtype, input]
+       DMASS -- 2D array containing the mass matrix entries [realtype 
+                of size (NEQ,NEQ), output]
+       IPAR  -- array containing integer user data that was passed to
+                FARKMALLOC [long int, input]
+       RPAR  -- array containing real user data that was passed to
+                FARKMALLOC [realtype, input]
+       WK*   -- array containing temporary workspace of same size as Y 
+                [realtype, input]
+       IER   -- return flag [int, output]:
+                   0 if successful, 
+                  >0 if a recoverable error occurred,
+                  <0 if an unrecoverable error ocurred.
+ 
+ (4s) Optional user-supplied band mass matrix routine: FARKBMASS
 
-     Required when using the BAND or LAPACKBAND mass matrix linear solvers, 
-     the user must supply a routine that computes the system mass matrix M.  
-     This routine must have the following form: 
+     Required when using the Band or LapackBand mass matrix linear solvers, 
+     the user must supply a routine that computes the system mass matrix 
+     M.  This routine must have the following form: 
 
        SUBROUTINE FARKBMASS(NEQ, MU, ML, MDIM, T, BMASS, IPAR, 
       &                     RPAR, WK1, WK2, WK3, IER)
@@ -364,122 +538,74 @@
                   >0 if a recoverable error occurred,
                   <0 if an unrecoverable error ocurred.
  
- (5s) User-supplied sparse Jacobian approximation routine: FARKSPJAC
-
-     Required when using the ARKKLU or ARKSuperLUMT linear solvers, the 
-     user must supply a routine that computes a compressed-sparse-column 
-     [or compressed-sparse-row] approximation of the system Jacobian 
-     J = dfi(t,y)/dy.  This routine must have the following form:
-
-       SUBROUTINE FARKSPJAC(T, Y, FY, N, NNZ, JDATA, JRVALS, 
-      &                     JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
-
-     Typically this routine will use only M, N, NNZ, JDATA, JRVALS and 
-     JCPTRS. It must load the N by N compressed sparse column [or 
-     compressed sparse row] matrix with storage for NNZ nonzeros, stored 
-     in the arrays JDATA (nonzero values), JRVALS (row [or column] indices 
-     for each nonzero), JCOLPTRS (indices for start of each column [or row]), 
-     with the Jacobian matrix at the current (t,y) in CSC [or CSR] format 
-     (see sundials_sparse.h for more information).
-
-     The arguments are:
-         T    -- current time [realtype, input]
-         Y    -- array containing state variables [realtype, input]
-         FY   -- array containing state derivatives [realtype, input]
-         N    -- number of matrix rows/columns in Jacobian [int, input]
-         NNZ  -- allocated length of nonzero storage [int, input]
-        JDATA -- nonzero values in Jacobian
-                 [realtype of length NNZ, output]
-       JRVALS -- row [or column] indices for each nonzero in Jacobian
-                  [int of length NNZ, output]
-       JCPTRS -- pointers to each Jacobian column [or row] in preceding arrays
-                 [int of length N+1, output]
-         H    -- current step size [realtype, input]
-         IPAR -- array containing integer user data that was passed to
-                 FARKMALLOC [long int, input]
-         RPAR -- array containing real user data that was passed to
-                 FARKMALLOC [realtype, input]
-         WK*  -- array containing temporary workspace of same size as Y 
-                 [realtype, input]
-         IER  -- return flag [int, output]:
-                    0 if successful, 
-                   >0 if a recoverable error occurred,
-                   <0 if an unrecoverable error ocurred.
- 
- (6s) User-supplied sparse Mass matrix routine: FARKSPMASS
+ (4s) User-supplied sparse mass matrix routine: FARKSPMASS
 
-     Required when using the ARKMassKLU or ARKMassSuperLUMT mass matrix 
-     linear solvers, the user must supply a routine that computes a 
+     Required when using the KLU or SuperLUMT mass matrix linear solvers, 
+     the user must supply a routine that computes a 
      compressed-sparse-column [or compressed-sparse-row] version of the 
      (possibly time-dependent) system mass matrix M(t).  If supplied, 
      it must have the following form:
 
-       SUBROUTINE FARKSPMASS(T, N, NNZ, MDATA, MRVALS, MCPTRS, 
+       SUBROUTINE FARKSPMASS(T, N, NNZ, MDATA, MRVALS, MCPTRS,
       &                      IPAR, RPAR, WK1, WK2, WK3, IER)
 
      Typically this routine will use only M, N, NNZ, MDATA, MRVALS and 
      MCPTRS. It must load the N by N compressed sparse column [or 
      compressed sparse row] matrix with storage for NNZ nonzeros, stored 
      in the arrays MDATA (nonzero values), MRVALS (row [or column] indices 
-     for each nonzero), MCOLPTRS (indices for start of each column [or row]), 
-     with the system mass matrix at the current (t) in CSC [or CSR] format 
-     (see sundials_sparse.h for more information).
+     for each nonzero), MCOLPTRS (indices for start of each column 
+     [or row]), with the system mass matrix at the current (t) in CSC [or 
+     CSR] format (see sundials_sparse.h for more information).
 
      The arguments are:
          T    -- current time [realtype, input]
-         N    -- number of rows/columns in mass matrix [int, input]
-         NNZ  -- allocated length of nonzero storage [int, input]
+         N    -- number of rows/columns in mass matrix [long int, input]
+         NNZ  -- allocated length of nonzero storage [long int, input]
         MDATA -- nonzero values in mass matrix
                  [realtype of length NNZ, output]
        MRVALS -- row [or column] indices for each nonzero in mass matrix
-                  [int of length NNZ, output]
-       MCPTRS -- pointers to each mass matrix column [or row] in preceding arrays
-                 [int of length N+1, output]
+                 [long int of length NNZ, output]
+       MCPTRS -- pointers to each mass matrix column [or row] in preceding 
+                 arrays [long int of length N+1, output]
          IPAR -- array containing integer user data that was passed to
                  FARKMALLOC [long int, input]
          RPAR -- array containing real user data that was passed to
                  FARKMALLOC [realtype, input]
-         WK*  -- array containing temporary workspace of same size as Y 
+         WK*  -- array containing temporary workspace of same size as Y
                  [realtype, input]
          IER  -- return flag [int, output]:
-                    0 if successful, 
+                    0 if successful,
                    >0 if a recoverable error occurred,
                    <0 if an unrecoverable error ocurred.
  
- (7) Optional user-supplied Jacobian-vector product routine: FARKJTIMES
+ (4) User-supplied mass-matrix-vector product routine: FARKMTSETUP
 
-     As an option when using the SP* linear solver, the user may supply a
-     routine that computes the product of the system Jacobian 
-     J = dfi(t,y)/dy and a given vector v.  If supplied, it must have the 
-     following form:
+     When using the ARKSpils iterative mass matrix linear solver interface, 
+     the user is required to supply a routine that computes the product of
+     the system Jacobian J = dfi(t,y)/dy and a given vector v.  As an 
+     option, the user may also supply a routine to set up any user data
+     structures in preparation for the mass matrix-vector product.  If this 
+     is supplied, it must have the following form:
 
-       SUBROUTINE FARKJTIMES(V, JV, T, Y, FY, H, IPAR, RPAR, WORK, IER)
+       SUBROUTINE FARKMTSETUP(T, IPAR, RPAR, IER)
 
-     Typically this routine will use only NEQ, T, Y, V, and JV.  It must
-     compute the product vector J*v where v is stored in the vector V 
-     and the result J*v is stored in JV.  
+     It must perform any relevant preparations for subsequent calls to the 
+     user-provided FARKMTIMES routine (see below).  
 
      The arguments are:
-       V    -- array containing vector to multiply [realtype, input]
-       JV   -- array containing product vector [realtype, output]
        T    -- current time [realtype, input]
-       Y    -- array containing state variables [realtype, input]
-       FY   -- array containing state derivatives [realtype, input]
-       H    -- current step size [realtype, input]
        IPAR -- array containing integer user data that was passed to
                FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
-       WORK -- array containing temporary workspace of same size as Y 
-               [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                   nonzero if an error.
- 
- (8) User-supplied mass-matrix-vector product routine: FARKMTIMES
+
+ (4) User-supplied mass-matrix-vector product routine: FARKMTIMES
 
      Required when using the SP* linear solvers, the user should supply a
-     routine that computes the product of the system mass matrix M and a 
+     routine that computes the product of the system mass matrix M and a
      given vector v.  It must have the following form:
 
        SUBROUTINE FARKMTIMES(V, MV, T, IPAR, RPAR, IER)
@@ -497,23 +623,73 @@
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                   nonzero if an error.
  
- (9) Optional user-supplied error weight vector routine: FARKEWT
- 
-     As an option to providing the relative and absolute tolerances, the user
-     may supply a routine that computes the weights used in the WRMS norms.
-     If supplied, it must have the following form:
+ (5) Optional user-supplied mass matrix preconditioner setup/solve 
+   routines: FARKMASSPSET and FARKMASSPSOL
 
-       SUBROUTINE FARKEWT(Y, EWT, IPAR, RPAR, IER)
+     As an option when using the SP* mass matrix linear solver, the user 
+     may supply routines to setup and apply the preconditioner.  If 
+     supplied, these must have the following form:
 
-     It must store the error weights in EWT, given the current solution Y. 
+       SUBROUTINE FARKMASSPSET(T, IPAR, RPAR, IER)
 
-     The arguments are:
-       Y    -- array containing state variables [realtype, input]
-       EWT  -- array containing the error weight vector [realtype, output]
-       IPAR -- array containing integer user data that was passed to
+     This routine must set up the preconditioner P to be used in the 
+     subsequent call to FARKMASSPSOL.  The preconditioner (or the product 
+     of the left and right preconditioners if using both) should be an 
+     approximation to the system mass matrix M.
+
+     The arguments are:
+       T = current time [realtype, input]
+       IPAR = array of user integer data [long int, input/output]
+       RPAR = array with user real data [realtype, input/output]
+       IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+		 >0 = recoverable failure
+                 <0 = non-recoverable failure
+
+     The user-supplied routine FARKMASSPSOL must have the form:
+
+       SUBROUTINE FARKMASSPSOL(T, R, Z, DELTA, LR, IPAR, RPAR, IER)
+
+       DIMENSION R(*), Z(*), IPAR(*), RPAR(*)
+
+     Typically this routine will use only T, R, LR, and Z.  It
+     must solve the preconditioner linear system Pz = r.  The 
+     preconditioner (or the product of the left and right 
+     preconditioners if both are nontrivial) should be an 
+     approximation to the system mass matrix M.
+
+     The arguments are:
+       T = current time [realtype, input]
+       R = right-hand side array [realtype, input]
+       Z = solution array [realtype, output]
+       DELTA = desired residual tolerance [realtype, input]
+       LR = flag denoting to solve the right or left preconditioner system
+                  1 = left preconditioner
+		  2 = right preconditioner
+       IPAR = array of user integer data [long int, input/output]
+       RPAR = array with user real data [realtype, input/output]
+       IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+		 >0 = recoverable failure
+                 <0 = non-recoverable failure
+
+ (6) Optional user-supplied error weight vector routine: FARKEWT
+ 
+     As an option to providing the relative and absolute tolerances, the 
+     user may supply a routine that computes the weights used in the WRMS 
+     norms.  If supplied, it must have the following form:
+
+       SUBROUTINE FARKEWT(Y, EWT, IPAR, RPAR, IER)
+
+     It must store the error weights in EWT, given the current solution Y. 
+
+     The arguments are:
+       Y    -- array containing state variables [realtype, input]
+       EWT  -- array containing the error weight vector [realtype, output]
+       IPAR -- array containing integer user data that was passed to
                FARKMALLOC [long int, input]
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
@@ -521,7 +697,7 @@
                   0 if successful, 
                   nonzero if an error.
 
- (10) Optional user-supplied error weight vector routine: FARKADAPT
+ (7) Optional user-supplied error weight vector routine: FARKADAPT
  
      As an option to providing the time step adaptivity, the user
      may supply a routine that computes the new time step for ARKode to 
@@ -541,7 +717,8 @@
        H3   -- previous-previous step size [realtype, input]
        E1   -- estimated temporal error in current step [realtype, input]
        E2   -- estimated temporal error in previous step [realtype, input]
-       E3   -- estimated temporal error in previous-previous step [realtype, input]
+       E3   -- estimated temporal error in previous-previous step 
+               [realtype, input]
        Q    -- global order of accuracy for RK method [int, input]
        P    -- global order of accuracy for RK embedding [int, input]
        HNEW -- predicted next step size [realtype, output]
@@ -550,18 +727,18 @@
        RPAR -- array containing real user data that was passed to
                FARKMALLOC [realtype, input]
        IER  -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                   nonzero if an error.
 
- (11) Optional user-supplied explicitly stable time step routine: FARKEXPSTAB
+ (8) Optional user-supplied explicitly stable time step routine: FARKEXPSTAB
  
-     As an option, the user may provide a routine to return the maximum stable 
-     time step size for the explicit ODE RHS function.  If supplied, it must 
-     have the following form:
+     As an option, the user may provide a routine to return the maximum 
+     stable time step size for the explicit ODE RHS function.  If supplied, 
+     it must have the following form:
 
        SUBROUTINE FARKEXPSTAB(Y, T, HSTAB, IPAR, RPAR, IER)
 
-     It must store the explicitly stable step size in the ouptut HSTAB. 
+     It must store the explicitly stable step size in the ouptut HSTAB.
 
      The arguments are:
        Y     -- array containing state variables [realtype, input]
@@ -572,98 +749,225 @@
        RPAR  -- array containing real user data that was passed to
                 FARKMALLOC [realtype, input]
        IER   -- return flag [int, output]:
-                  0 if successful, 
+                  0 if successful,
                   nonzero if an error.
 
  -----------------------------------------------------------------------------
 
- (12) Initialization:  FNVINITS/FNVINITP/FNVINITOMP/FNVINITPTS, 
-                       FARKMALLOC, FARKREINIT, FARKRESIZE
- 
- (12.1s) To initialize the serial vector specification, the user must make the
-     following call:
-
-        CALL FNVINITS(4, NEQ, IER)
+ (9) Initialization:  FNVINITS / FNVINITP / FNVINITOMP / FNVINITPTS, 
+                      FSUNBANDMATINIT / FSUNDENSEMATINIT / FSUNSPARSEMATINIT,
+                      FSUNBANDMASSMATINIT / FSUNDENSEMASSMATINIT /
+                         FSUNSPARSEMASSMATINIT,
+                      FSUNBANDLINSOLINIT / FSUNDENSELINSOLINIT / 
+                         FSUNKLUINIT / FSUNKLUREINIT / FSUNKLUSETORDERING / 
+                         FSUNLAPACKBANDINIT / FSUNLAPACKDENSEINIT / 
+                         FSUNPCGINIT / FSUNSPBCGSINIT / FSUNSPFGMRINIT / 
+                         FSUNSPGMRINIT / FSUNSPTFQMRINIT / FSUNSUPERLUMTINIT /
+                         FSUNSUPERLUMTSETORDERING,
+                      FSUNMASSBANDLINSOLINIT / FSUNMASSDENSELINSOLINIT /
+                         FSUNMASSKLUINIT / FSUNMASSKLUREINIT / 
+                         FSUNMASSKLUSETORDERING / FSUNMASSLAPACKBANDINIT / 
+                         FSUNMASSLAPACKDENSEINIT / FSUNMASSPCGINIT / 
+                         FSUNMASSSPBCGSINIT / FSUNMASSSPFGMRINIT / 
+                         FSUNMASSSPGMRINIT / FSUNMASSSPTFQMRINIT / 
+                         FSUNMASSSUPERLUMTINIT / FSUNMASSSUPERLUMTSETORDERING,
+                      FARKMALLOC,
+                      FARKDLSINIT / FARKSPILSINIT,
+                      FARKREINIT, FARKRESIZE
+
+     NOTE: the initialization order is important!  It *must* proceed as 
+     shown: vector, matrix (if used), linear solver (if used), ARKode, 
+     ARKDls/ARKSpils, reinit/resize.
+ 
+ (9.1s) To initialize the a vector specification for storing the solution 
+     data, the user must make one of the following calls:
+
+       (serial)   
+          CALL FNVINITS(4, NEQ, IER)
+       (MPI parallel)
+          CALL FNVINITP(COMM, 4, NLOCAL, NGLOBAL, IER)
+       (OpenMP threaded)
+          CALL FNVINITOMP(4, NEQ, NUM_THREADS, IER)
+       (PThreads threaded)
+          CALL FNVINITPTS(4, NEQ, NUM_THREADS, IER)
+
+     In each of these, one argument is an int containing the ARKODE solver 
+     ID (4). 
 
-     where the first argument is an int containing the ARKODE solver ID (4). 
      The other arguments are:
         NEQ = size of vectors [long int, input]
-	IER = return completion flag [int, output]:
-	          0 = success, 
-		 -1 = failure.
- 
- (12.1p) To initialize the distributed memory parallel machine environment, 
-        the user must make the following call:
-
-        CALL FNVINITP(COMM, 4, NLOCAL, NGLOBAL, IER)
-
-     The arguments are:
         COMM = the MPI communicator [int, input]
-        NLOCAL = local size of vectors on this processor [long int, input]
+        NLOCAL = local size of vectors on this processor 
+           [long int, input]
         NGLOBAL = the system size, and the global size of vectors (the sum 
            of all values of NLOCAL) [long int, input]
-        IER = return completion flag [int, ouptut]. 
+        NUM_THREADS = number of threads
+        IER = return completion flag [int, output]:
                   0 = success, 
                  -1 = failure.
 
-     Note: If MPI was initialized by the user, the communicator must be set to
-     MPI_COMM_WORLD.  If not, this routine initializes MPI and sets the
-     communicator equal to MPI_COMM_WORLD.
+ (9.2) To initialize a band/dense/sparse matrix structure for 
+     storing the system Jacobian and for use within a direct linear solver,
+     the user must make one of the following calls:
  
- (12.1omp) To initialize the openMP threaded vector kernel, 
-          the user must make the following call:
+          CALL FSUNBANDMATINIT(4, N, MU, ML, SMU, IER)
+          CALL FSUNDENSEMATINIT(4, M, N, IER)
+          CALL FSUNSPARSEMATINIT(4, M, N, NNZ, SPARSETYPE, IER)
+
+     In each of these, one argument is an int containing the ARKODE solver 
+     ID (4). 
 
-          CALL FNVINITOMP(3, NEQ, NUM_THREADS, IER)
+     The other arguments are:
 
-        The arguments are:
-          NEQ = size of vectors
-          NUM_THREADS = number of threads
-          IER = return completion flag. Values are 0 = success, -1 = failure.
+        M = the number of rows of the matrix [long int, input]
+        N = the number of columns of the matrix [long int, input]
+        MU = the number of upper bands (diagonal not included) in a banded 
+           matrix [long int, input]
+        ML = the number of lower bands (diagonal not included) in a banded 
+           matrix [long int, input]
+        SMU = the number of upper bands to store (diagonal not included) 
+           for factorization of a banded matrix [long int, input]
+        NNZ = the storage size (upper bound on the number of nonzeros) for 
+           a sparse matrix [long int, input]
+        SPARSETYPE = integer denoting use of CSC (0) vs CSR (1) storage 
+           for a sparse matrix [int, input]
+        IER = return completion flag [int, output]:
+                  0 = success, 
+                 -1 = failure.
 
- (12.1pts) To initialize the Pthreads threaded vector kernel, 
-          the user must make the following call:
+ (9.3) To initialize a band/dense/sparse matrix structure for 
+     storing the mass matrix and for use within a direct mass matrix linear 
+     solver, the user must make one of the following calls:
+  
+          CALL FSUNBANDMASSMATINIT(N, MU, ML, SMU, IER)
+          CALL FSUNDENSEMASSMATINIT(M, N, IER)
+          CALL FSUNSPARSEMASSMATINIT(M, N, NNZ, SPARSETYPE, IER)
+
+     The arguments have the same meanings as with the Jacobian matrix 
+     initialization routines above.
+
+ (9.4) To initialize a linear solver structure for solving linear systems 
+     arising from implicit or IMEX treatment of the IVP, the user must make 
+     one of the following calls:
+
+          CALL FSUNBANDLINSOLINIT(4, IER)
+          CALL FSUNDENSELINSOLINIT(4, IER)
+          CALL FSUNKLUINIT(4, IER)
+          CALL FSUNLAPACKBANDINIT(4, IER)
+          CALL FSUNLAPACKDENSEINIT(4, IER)
+          CALL FSUNPCGINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPBCGSINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPFGMRINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPGMRINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSPTFQMRINIT(4, PRETYPE, MAXL, IER)
+          CALL FSUNSUPERLUMTINIT(4, NUM_THREADS, IER)
+
+     Or once these have been initialized, their solver parameters may be
+     modified via calls to the functions
+
+          CALL FSUNKLUSETORDERING(4, ORD_CHOICE, IER)
+          CALL FSUNSUPERLUMTSETORDERING(4, ORD_CHOICE, IER)
+
+          CALL FSUNPCGSETPRECTYPE(4, PRETYPE, IER)
+          CALL FSUNPCGSETMAXL(4, MAXL, IER)
+          CALL FSUNSPBCGSSETPRECTYPE(4, PRETYPE, IER)
+          CALL FSUNSPBCGSSETMAXL(4, MAXL, IER)
+          CALL FSUNSPFGMRSETGSTYPE(4, GSTYPE, IER)
+          CALL FSUNSPFGMRSETPRECTYPE(4, PRETYPE, IER)
+          CALL FSUNSPGMRSETGSTYPE(4, GSTYPE, IER)
+          CALL FSUNSPGMRSETPRECTYPE(4, PRETYPE, IER)
+          CALL FSUNSPTFQMRSETPRECTYPE(4, PRETYPE, IER)
+          CALL FSUNSPTFQMRSETMAXL(4, MAXL, IER)
+
+     In all of the above, one argument is an int containing the ARKODE solver 
+     ID (4). 
 
-          CALL FNVINITPTS(3, NEQ, NUM_THREADS, IER)
+     The other arguments are:
 
-        The arguments are:
-          NEQ = size of vectors
-          NUM_THREADS = number of threads
-          IER = return completion flag. Values are 0 = success, -1 = failure.
+        NNZ = the storage size (upper bound on the number of nonzeros) for 
+           a sparse matrix [long int, input]
+        ORD_CHOICE = integer denoting ordering choice (see 
+           SUNKLUSetOrdering and SUNSuperLUMTSetOrdering documentation 
+           for details) [int, input]
+        PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+           2=right, 3=both) [int, input]
+        MAXL = maximum Krylov subspace dimension [int, input]
+        GSTYPE = choice of Gram-Schmidt orthogonalization algorithm 
+           (0=modified, 1=classical) [int, input]
+        IER = return completion flag [int, output]:
+                  0 = success, 
+                 -1 = failure.
 
- (12.2) To set various problem and solution parameters and allocate
+ (9.5) To initialize a linear solver structure for solving linear systems 
+     arising from use of a non-identity mass matrix, the user must make 
+     one of the following calls:
+
+          CALL FSUNMASSBANDLINSOLINIT(IER)
+          CALL FSUNMASSDENSELINSOLINIT(IER)
+          CALL FSUNMASSKLUINIT(IER)
+          CALL FSUNMASSLAPACKBANDINIT(IER)
+          CALL FSUNMASSLAPACKDENSEINIT(IER)
+          CALL FSUNMASSPCGINIT(PRETYPE, MAXL, IER)
+          CALL FSUNMASSSPBCGSINIT(PRETYPE, MAXL, IER)
+          CALL FSUNMASSSPFGMRINIT(PRETYPE, MAXL, IER)
+          CALL FSUNMASSSPGMRINIT(PRETYPE, MAXL, IER)
+          CALL FSUNMASSSPTFQMRINIT(PRETYPE, MAXL, IER)
+          CALL FSUNMASSSUPERLUMTINIT(NUM_THREADS, IER)
+          
+     Or once these have been initialized, their solver parameters may be
+     modified via calls to the functions
+
+          CALL FSUNMASSKLUSETORDERING(ORD_CHOICE, IER)
+          CALL FSUNMASSSUPERLUMTSETORDERING(ORD_CHOICE, IER)
+
+          CALL FSUNMASSPCGSETPRECTYPE(PRETYPE, IER)
+          CALL FSUNMASSPCGSETMAXL(MAXL, IER)
+          CALL FSUNMASSSPBCGSSETPRECTYPE(PRETYPE, IER)
+          CALL FSUNMASSSPBCGSSETMAXL(MAXL, IER)
+          CALL FSUNMASSSPFGMRSETGSTYPE(GSTYPE, IER)
+          CALL FSUNMASSSPFGMRSETPRECTYPE(PRETYPE, IER)
+          CALL FSUNMASSSPGMRSETGSTYPE(GSTYPE, IER)
+          CALL FSUNMASSSPGMRSETPRECTYPE(PRETYPE, IER)
+          CALL FSUNMASSSPTFQMRSETPRECTYPE(PRETYPE, IER)
+          CALL FSUNMASSSPTFQMRSETMAXL(MAXL, IER)
+
+     The arguments have the same meanings as with the Jacobian matrix 
+     initialization routines above.
+
+ (9.6) To set various problem and solution parameters and allocate
      internal memory, make the following call:
 
-       CALL FARKMALLOC(T0, Y0, IMEX, IATOL, RTOL, ATOL, IOUT, ROUT, 
+       CALL FARKMALLOC(T0, Y0, IMEX, IATOL, RTOL, ATOL, IOUT, ROUT,
       &                IPAR, RPAR, IER)
 
      The arguments are:
         T0 = initial value of t [realtype, input]
-	Y0 = array of initial conditions [realtype, input]
-	IMEX = flag denoting basic integration method [int, input]: 
+        Y0 = array of initial conditions [realtype, input]
+        IMEX = flag denoting basic integration method [int, input]: 
                   0 = implicit, 
                   1 = explicit, 
                   2 = imex
-        IATOL = type for absolute tolerance ATOL [int, input]: 
-                  1 = scalar, 
+        IATOL = type for absolute tolerance ATOL [int, input]:
+                  1 = scalar,
                   2 = array,
                   3 = user-supplied function; the user must supply a routine
-		  FARKEWT to compute the error weight vector.
+                      FARKEWT to compute the error weight vector.
         RTOL = scalar relative tolerance [realtype, input]
-	ATOL = scalar or array absolute tolerance [realtype, input]
-	IOUT = array of length 22 for integer optional outputs
-	   [long int, output]
-	ROUT = array of length 6 for real optional outputs [realtype, output]
-	IPAR = array of user integer data [long int, input/output]
-	RPAR = array with user real data [realtype, input/output]
-	IER  = return completion flag [int, output]:
+        ATOL = scalar or array absolute tolerance [realtype, input]
+        IOUT = array of length at least 29 for integer optional outputs
+               [long int, output]
+        ROUT = array of length 6 for real optional outputs [realtype, output]
+        IPAR = array of user integer data [long int, input/output]
+        RPAR = array with user real data [realtype, input/output]
+        IER  = return completion flag [int, output]:
                   0 = SUCCESS,
                  -1 = failure (see printed message for failure details).
 
      The user data arrays IPAR and RPAR are passed unmodified to all 
-     subsequent calls to user-provided routines. Modifications to either array
-     inside a user-provided routine will be propagated. Using these two 
-     arrays, the user can dispense with COMMON blocks to pass data betwen 
-     user-provided routines. 
+     subsequent calls to user-provided routines. Modifications to either 
+     array inside a user-provided routine will be propagated. Using these 
+     two arrays, the user can dispense with COMMON blocks to pass data 
+     betwen user-provided routines. 
  
      The optional outputs are:
            LENRW   = IOUT( 1) from ARKodeGetWorkSpace
@@ -686,47 +990,207 @@
            TCUR    = ROUT( 4) from ARKodeGetCurrentTime
            TOLSF   = ROUT( 5) from ARKodeGetTolScaleFactor
            UROUND  = ROUT( 6) from UNIT_ROUNDOFF
-     See the ARKODE manual for details. 
+     See the ARKODE manual for details.
+
+ (9.7) If a direct linear solver was created in step (7.4) then it must be 
+     attached to ARKode.  If the user called any one of FSUNBANDLINSOLINIT, 
+     FSUNDENSELINSOLINIT, FSUNKLUINIT, FSUNLAPACKBANDINIT, 
+     FSUNLAPACKDENSEINIT, or FSUNSUPERLUMTINIT, then this must be 
+     attached to the ARKDLS interface using the command:
+
+       CALL FARKDLSINIT(IER)
+
+     The arguments are:
+	IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+                 -1 = failure (see printed message for failure details).
+
+ (9.7) If an iterative linear solver was created in step (7.4) then it must 
+     be attached to ARKode.  If the user called any one of FSUNPCGINIT, 
+     FSUNSPBCGSINIT, FSUNSPFGMRINIT, FSUNSPGMRINIT, or FSUNSPTFQMRINIT, 
+     then this must be attached to the ARKSPILS interface using the command:
+
+       CALL FARKSPILSINIT(IER)
+
+     The arguments are:
+	IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+                 -1 = failure (see printed message for failure details).
+
+ (9.8) If a mass matrix linear solver was created in step (7.5) then it 
+     must be attached to ARKode.  If the user called any one of 
+     FSUNMASSBANDLINSOLINIT, FSUNMASSDENSELINSOLINIT, 
+     FSUNMASSKLUINIT, FSUNMASSLAPACKBANDINIT, FSUNMASSLAPACKDENSEINIT, 
+     or FSUNMASSSUPERLUMTINIT, then this must be attached to the 
+     ARKDLS interface using the command:
+
+       CALL FARKDLSMASSINIT(TIME_DEP, IER)
+
+     The arguments are:
+	TIME_DEP = flag indicating whether the mass matrix is 
+           time-dependent (1) or not (0) [int, output]:
+	IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+                 -1 = failure (see printed message for failure details).
+
+ (9.9) If a mass matrix linear solver was created in step (7.5) then it 
+     must be attached to ARKode.  If the user called any one of 
+     FSUNMASSPCGINIT, FSUNMASSSPBCGSINIT, FSUNMASSSPFGMRINIT, 
+     FSUNMASSSPGMRINIT, or FSUNMASSSPTFQMRINIT, then this must be attached
+     to the ARKDLS interface using the command:
+
+       CALL FARKSPILSMASSINIT(TIME_DEP, IER)
+
+     The arguments are:
+	TIME_DEP = flag indicating whether the mass matrix is 
+           time-dependent (1) or not (0) [int, output]:
+	IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+                 -1 = failure (see printed message for failure details).
 
- (12.3) If the user program includes the FARKEWT routine for the evaluation 
+ (9.10) If the user program includes the FARKEWT routine for the evaluation 
      of the error weights, the following call must be made
 
        CALL FARKEWTSET(FLAG, IER)
 
      with the int argument FLAG = 1 to specify that FARKEWT is provided and 
-     should be used; FLAG = 0 resets to the default EWT formulation.  The int 
-     return flag IER is 0 if successful, and nonzero otherwise.
+     should be used; FLAG = 0 resets to the default EWT formulation.  The 
+     int return flag IER is 0 if successful, and nonzero otherwise.
 
- (12.4) If the user program includes the FARKADAPT routine for performing 
+ (9.11) If the user program includes the FARKADAPT routine for performing 
      step adaptivity, the following call must be made
 
        CALL FARKADAPTSET(FLAG, IER)
 
-     with the int argument FLAG = 1 to specify that FARKADAPT is provided and 
-     should be used; FLAG = 0 resets to the default adaptivity formulation. 
-     The int return flag IER is 0 if successful, and nonzero otherwise.
+     with the int argument FLAG = 1 to specify that FARKADAPT is provided 
+     and should be used; FLAG = 0 resets to the default adaptivity 
+     formulation. The int return flag IER is 0 if successful, and nonzero 
+     otherwise.
 
- (12.5) If the user program includes the FARKEXPSTAB routine for calculation of
-     the maximum explicitly stable step size, the following call must be made
+ (9.12) If the user program includes the FARKEXPSTAB routine for 
+     calculation of the maximum explicitly stable step size, the following 
+     call must be made
 
        CALL FARKEXPSTABSET(FLAG, IER)
 
-     with the int argument FLAG = 1 to specify that FARKEXPSTAB is provided and
-     should be used; FLAG = 0 resets to the default explicit stability formulation.
-     The int return flag IER is 0 if successful, and nonzero otherwise.
+     with the int argument FLAG = 1 to specify that FARKEXPSTAB is provided 
+     and should be used; FLAG = 0 resets to the default explicit stability 
+     formulation.  The int return flag IER is 0 if successful, and nonzero 
+     otherwise.
+
+ (9.13) If the user program includes the FARKBJAC routine for the 
+     evaluation of the band approximation to the Jacobian, then following 
+     the call to FARKDLSINIT, the following call must be made 
+
+       CALL FARKBANDSETJAC(FLAG, IER)
+
+     with the int FLAG=1 to specify that FARKBJAC is provided and should be 
+     used; FLAG=0 specifies a reset to the internal finite difference 
+     Jacobian approximation.  The int return flag IER=0 if successful, 
+     nonzero otherwise.
+ 
+     If the user program includes the FARKDJAC routine for the evaluation 
+     of the dense approximation to the Jacobian, then after the call to 
+     FARKDLSINIT, the following call must be made 
+
+       CALL FARKDENSESETJAC(FLAG, IER)
+
+     with the int FLAG=1 to specify that FARKDJAC is provided and should be 
+     used; FLAG=0 specifies a reset to the internal finite difference 
+     Jacobian approximation.  The int return flag IER=0 if successful, and 
+     nonzero otherwise.
+ 
+     When using a sparse matrix and linear solver the user must provide the
+     FARKSPJAC routine for the evaluation of the sparse approximation to 
+     the Jacobian.  To indicate that this routine has been provided, after 
+     the call to FARKDLSINIT, the following call must be made 
+
+       CALL FARKSPARSESETJAC(IER)
+
+     The int return flag IER=0 if successful, and nonzero otherwise.
+
+ (9.14) If the user program includes the FARKJTSETUP and FARKJTIMES 
+     routines for setup of a Jacobian-times-vector product (for use with 
+     the ARKSpils interface), then after creating the ARKSpils interface, 
+     the following call must be made:
+
+       CALL FARKSPILSSETJAC(FLAG, IER)
+
+     with the int FLAG=1 to specify that FARKJTSETUP and FARKJTIMES are 
+     provided and should be used; FLAG=0 specifies a reset to the internal 
+     finite difference approximation to this product).  The int return 
+     flag IER=0 if successful, and nonzero otherwise.
+ 
+ (9.16) If the user program includes the FARKPSET and FARKPSOL routines 
+     for supplying a preconditioner to an iterative linear solver, then 
+     after creating the ARKSpils interface, the following call must be made
+
+       CALL FARKSPILSSETPREC(FLAG, IER)
+
+     with the int FLAG=1.  If FLAG=0 then preconditioning with these 
+     routines will be disabled. The return flag IER=0 if successful, 
+     nonzero otherwise.
+
+ (9.17) If the user wishes to use one of ARKode's built-in preconditioning 
+     modules, FARKBP or FARKBBD, then that should be initialized after 
+     creating the ARKSpils interface using one of the calls
 
- (12.6) To re-initialize the ARKODE solver for the solution of a new problem
+       CALL FARKBPINIT(NEQ, MU, ML, IER)
+       CALL FARKBBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER)
+
+     Detailed explanation of the inputs to these functions, as well as any 
+     requirements of user-supplied functions on which these preconditioning 
+     modules rely, may be found in the header files for each module, 
+     farkbp.h or farkbbd.h, respectively.
+
+ (9.18) When using a band / dense / sparse mass matrix and 
+     corresponding linear solver the user must provide the FARKBMASS / 
+     FARKDMASS / FARKSPMASS routine for the evaluation of the 
+     approximation to the mass matrix.  To indicate that the 
+     appropriate routine has been provided, after the call to 
+     FARKDLSMASSINIT, one of the following calls must be made 
+
+       CALL FARKBANDSETMASS(IER)
+       CALL FARKDENSESETMASS(IER)
+       CALL FARKSPARSESETMASS(IER)
+
+     The int return flag IER=0 if successful, nonzero otherwise.
+
+
+ (9.19) When using the ARKSPILS interface for the mass matrix solvers, the 
+     user must supply a mass matrix-times-vector routine FARKMTIMES, and 
+     an associated 'setup' routine FARKMTSETUP.  After creating the 
+     ARKSpilsMass interface, the user must make the following call to 
+     signal that FARKMTSETUP and FARKMTIMES have been provided
+
+       CALL FARKSPILSSETMASS(IER)
+
+     The int return flag IER=0 if successful, and nonzero otherwise.
+
+ (9.20) If the user program includes the FARKMASSPSET and FARKMASSPSOL 
+     routines for supplying a preconditioner to an iterative mass matrix 
+     linear solver, then after creating the ARKSpilsMass interface, the 
+     following call must be made
+
+       CALL FARKSPILSSETMASSPREC(FLAG, IER)
+
+     with the int FLAG=1.  If FLAG=0 then preconditioning with these 
+     routines will be disabled. The return flag IER=0 if successful, 
+     nonzero otherwise.
+
+ (9.21) To re-initialize the ARKODE solver for the solution of a new problem
      of the same size as one already solved, make the following call:
 
        CALL FARKREINIT(T0, Y0, IMEX, IATOL, RTOL, ATOL, IER)
 
-     The arguments have the same names and meanings as those of FARKMALLOC.  
-     FARKREINIT performs the same initializations as FARKMALLOC, but does no 
-     memory allocation, using instead the existing internal memory created by 
-     the previous FARKMALLOC call.  The subsequent call to specify the linear 
-     system solution method may or may not be needed; see paragraph (9) below.
+     The arguments have the same names and meanings as those of FARKMALLOC. 
+     FARKREINIT performs the same initializations as FARKMALLOC, but does 
+     no memory allocation, using instead the existing internal memory 
+     created by the previous FARKMALLOC call.  The subsequent calls to 
+     attach the linear system or mass matrix system solvers are only needed 
+     if those objects have been re-created.
  
- (12.7) To re-initialize the ARKODE solver for the solution of a new problem
+ (9.22) To re-initialize the ARKODE solver for the solution of a new problem
      of a different size as one already solved, but with the same dynamical 
      time scale and method choice, make the following call:
 
@@ -738,12 +1202,12 @@
 	HSCALE = desired step size scale factor [realtype, input]
 	          1.0 is the default
 		  any value <= 0.0 results in the default.
-        ITOL = flag denoting that a new relative tolerance and vector of 
+        ITOL = flag denoting that a new relative tolerance and vector of
 	   absolute tolerances are supplied in the RTOL and ATOL arguments
-	   [int, input]: 
-                  0 = retain the current relative tolerance and current 
+	   [int, input]:
+                  0 = retain the current relative tolerance and current
 		      scalar-valued or user-supplied function
-                  1 = RTOL contains the new scalar-valued relative tolerance 
+                  1 = RTOL contains the new scalar-valued relative tolerance
                       and ATOL contains a new array of absolute tolerances
 	RTOL = scalar-valued relative tolerance [realtype, input]
 	ATOL = array of absolute tolerances [realtype, input]
@@ -751,13 +1215,40 @@
                   0 = SUCCESS,
                  -1 = failure (see printed message for failure details).
 
-     FARKRESIZE performs the opposite set of of operations as FARKREINIT: it 
-     does not reinitialize any of the time-step heuristics, but it does 
-     perform memory reallocation.  The subsequent call to specify the linear 
-     system solution method is required, since its internal memory 
-     structures will no longer be the correct size.; see paragraph (9) below.
+     FARKRESIZE performs the opposite set of of operations as FARKREINIT: 
+     it does not reinitialize any of the time-step heuristics, but it does 
+     perform memory reallocation.  
+
+     Since the problem has changed size, it is likely that the linear 
+     solver object(s) must also be reconstructed.  The previous solver 
+     object(s) may be freed and new ones created by calling the respective 
+     FSUN***INIT routine again with modified arguments.  This should be 
+     performed _after_ FARKRESIZE has been called.  Following 
+     reconstruction of the linear solver object(s), the ARKSPILS or ARKDLS 
+     interface must also be reconstructed, and any options (e.g. setting
+     the Jacobian-times-vector product routine) must be specified again.
+
+ (9.23) The SUNKLU solver will reuse much of the factorization information 
+     from one solve to the next.  If at any time the user wants to force a 
+     full refactorization or if the number of nonzeros in the Jacobian 
+     matrix changes, the user should make the call
+
+        CALL FSUNKLUREINIT(4, NNZ, REINIT_TYPE, IER)
+
+     Similarly, if a user wants to force a full refactorization of the mass
+     matrix, or if the number of nonzeros in the mass matrix changes, the 
+     user should make the call
+
+        CALL FSUNMASSKLUREINIT(NNZ, REINIT_TYPE, IER)
+
+     The arguments are:
+        NNZ = the maximum number of nonzeros [int; input]
+        REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be 
+          destroyed and a new one will be allocated with NNZ nonzeros.  
+          For a value of 2, only symbolic and numeric factorizations will 
+          be completed. 
  
- (12.8) To set various integer optional inputs, make the folowing call:
+ (9.24) To set various integer optional inputs, make the folowing call:
 
        CALL FARKSETIIN(KEY, VALUE, IER)
 
@@ -765,45 +1256,48 @@
      quoted character string KEY. VALUE must be a Fortran integer of size 
      commensurate with a C "long int".  KEY must be one of the following: 
      ORDER, DENSE_ORDER, LINEAR, NONLINEAR, FIXEDPOINT, NEWTON, EXPLICIT, 
-     IMPLICIT, IMEX, IRK_TABLE_NUM, ERK_TABLE_NUM, ARK_TABLE_NUM (pass in an 
-     int array of length 2, implicit method first), MAX_NSTEPS, HNIL_WARNS, 
-     PREDICT_METHOD, MAX_ERRFAIL, MAX_CONVFAIL, MAX_NITERS, ADAPT_SMALL_NEF 
-     or LSETUP_MSBP.  The int return flag IER is 0 if successful, and 
-     nonzero otherwise.
+     IMPLICIT, IMEX, IRK_TABLE_NUM, ERK_TABLE_NUM, ARK_TABLE_NUM (pass in 
+     an int array of length 2, implicit method first), MAX_NSTEPS, 
+     HNIL_WARNS, PREDICT_METHOD, MAX_ERRFAIL, MAX_CONVFAIL, MAX_NITERS, 
+     ADAPT_SMALL_NEF or LSETUP_MSBP.  The int return flag IER is 0 if 
+     successful, and nonzero otherwise. 
 
-     To set various real optional inputs, make the following call:
+ (9.25) To set various real optional inputs, make the following call:
 
        CALL FARKSETRIN(KEY, VALUE, IER)
 
      to set the realtype value VALUE to the optional input specified by the 
-     quoted character string KEY.  VALUE must be a Fortran real-valued number
-     of size commensurate with the SUNDIALS "realtype".  KEY must one of the 
-     following: INIT_STEP, MAX_STEP, MIN_STEP, STOP_TIME, NLCONV_COEF, 
-     ADAPT_CFL, ADAPT_SAFETY, ADAPT_BIAS, ADAPT_GROWTH, ADAPT_BOUNDS (pass in 
-     a realtype array of length 2), ADAPT_ETAMX1, ADAPT_ETAMXF, ADAPT_ETACF, 
-     NONLIN_CRDOWN, NONLIN_RDIV, LSETUP_DGMAX, or FIXED_STEP.
+     quoted character string KEY.  VALUE must be a Fortran real-valued 
+     number of size commensurate with the SUNDIALS "realtype".  KEY must 
+     one of the following: INIT_STEP, MAX_STEP, MIN_STEP, STOP_TIME, 
+     NLCONV_COEF, ADAPT_CFL, ADAPT_SAFETY, ADAPT_BIAS, ADAPT_GROWTH, 
+     ADAPT_BOUNDS (pass in a realtype array of length 2), ADAPT_ETAMX1, 
+     ADAPT_ETAMXF, ADAPT_ETACF, NONLIN_CRDOWN, NONLIN_RDIV, LSETUP_DGMAX, 
+     or FIXED_STEP.  The int return flag IER is 0 if successful, and nonzero 
+     otherwise.
 
-     To set the time step adaptivity method (and its associated parameters), 
-     make the following call: 
+ (9.26) To set the time step adaptivity method (and its associated 
+     parameters), make the following call: 
 
        CALL FARKSETADAPTIVITYMETHOD(IMETHOD, IDEFAULT, IPQ, PARAMS, IER)
-       
+
      The arguments are:
-       IMETHOD  = the adaptivity method to use
-       IDEFAULT = flag to use (1) or not (0) the default adaptivity parameters
+       IMETHOD  = the adaptivity method to use [integer, input]
+       IDEFAULT = flag to use (1) or not (0) the default adaptivity 
+                  parameters [integer, input]
        IPQ      = flag to use the embedding order p (0) or the method order 
-                  q (1) for error-based step adaptivity
-       PARAMS   = if IDEFAULT=0, this should be a realtype array of length 2 
-                  containing the custom adaptivity parameters to use in the 
-		  method.
-       IMETHOD  = integer error flag (0 = success, 1 = failure)
+                  q (1) for error-based step adaptivity [integer, input]
+       PARAMS   = if IDEFAULT=0, this should be a realtype array of length 
+                  2 containing the custom adaptivity parameters to use in 
+		  the method [realtype, input].
+       IER      = integer error flag (0 = success, 1 = failure) [integer, output]
 
-     To reset all optional inputs to their default values, make the following 
-     call:
+ (9.27) To reset all optional inputs to their default values, make the 
+     following call:
 
        CALL FARKSETDEFAULTS(IER)
 
-     To set a custom explicit Runge-Kutta table, make the following call:
+ (9.28) To set a custom explicit Runge-Kutta table, make the following call:
 
        CALL FARKSETERKTABLE(S, Q, P, C, A, B, B2, IER)
 
@@ -812,15 +1306,15 @@
        Q = the global order of accuracy of the method [int, input]
        P = the global order of accuracy of the embedding [int, input]
        C = array of length S containing the stage times [realtype, input]
-       A = array of length S*S containing the ERK coefficients (stored in 
+       A = array of length S*S containing the ERK coefficients (stored in
            row-major, "C", order) [realtype, input]
        B = array of length S containing the solution coefficients
            [realtype, input]
        B2 = array of length S containing the embedding coefficients
            [realtype, input]
 
-     To set a custom diagonally-implicit Runge-Kutta table, make the following
-     call:
+     To set a custom diagonally-implicit Runge-Kutta table, make the 
+     following call:
 
        CALL FARKSETIRKTABLE(S, Q, P, C, A, B, B2, IER)
 
@@ -829,7 +1323,7 @@
        Q = the global order of accuracy of the method [int, input]
        P = the global order of accuracy of the embedding [int, input]
        C = array of length S containing the stage times [realtype, input]
-       A = array of length S*S containing the DIRK coefficients (stored in 
+       A = array of length S*S containing the DIRK coefficients (stored in
            row-major, "C", order) [realtype, input]
        B = array of length S containing the solution coefficients
            [realtype, input]
@@ -848,9 +1342,9 @@
            [realtype, input]
        CE = array of length S containing the explicit stage times
            [realtype, input]
-       AI = array of length S*S containing the DIRK coefficients (stored in 
+       AI = array of length S*S containing the DIRK coefficients (stored in
            row-major, "C", order) [realtype, input]
-       AE = array of length S*S containing the ERK coefficients (stored in 
+       AE = array of length S*S containing the ERK coefficients (stored in
            row-major, "C", order) [realtype, input]
        BI = array of length S containing the implicit solution coefficients
            [realtype, input]
@@ -861,30 +1355,31 @@
        B2E = array of length S containing the explicit embedding coefficients
            [realtype, input]
 
-     When using a non-identity mass matrix, to set an absolute residual 
+ (9.29) When using a non-identity mass matrix, to set an absolute residual 
      tolerance (scalar or vector), call:
 
        CALL FARKSETRESTOLERANCE(IATOL, ATOL, IER)
 
      The arguments are:
-       IATOL = type for absolute tolerance ATOL [int, input]: 
-                 1 = scalar, 
+       IATOL = type for absolute tolerance ATOL [int, input]:
+                 1 = scalar,
                  2 = array
 	ATOL = scalar or array absolute residual tolerance [realtype, input]
 	IER  = return completion flag [int, output]:
                  0 = SUCCESS,
                 -1 = failure (see printed message for failure details).
 
- (12.9) To set a solver diagnostics output file, make the folowing call:
+ (9.30) To set a solver diagnostics output file, make the folowing call:
 
        CALL FARKSETDIAGNOSTICS(FNAME, FLEN, IER)
 
      The desired diagnostics filename should be supplied by the 
-     quoted character string FNAME.  The integer argument FLEN should contain
-     the length (in characters) of FNAME (for portability).  The int return 
-     flag IER is 0 if successful (able to open file), and nonzero otherwise.
+     quoted character string FNAME.  The integer argument FLEN should 
+     contain the length (in characters) of FNAME (for portability).  The 
+     int return flag IER is 0 if successful (able to open file), and 
+     nonzero otherwise.
 
- (12.10) To close the solver diagnostics output file, make the folowing call:
+ (9.31) To close the solver diagnostics output file, make the folowing call:
 
        CALL FARKSTOPDIAGNOSTICS(IER)
 
@@ -894,1198 +1389,304 @@
 
  -----------------------------------------------------------------------------
 
- (13) Specification of linear system solution method.
+ (10) Optional outputs from DLS and SPILS linear solvers (stored in the 
+     IOUT array that was passed to FARKMALLOC)
+
+     Optional outputs specific to the ARKDLS interface:
+        LENRWLS  = IOUT(14) from ARKDlsGetWorkSpace (realtype space)
+        LENIWLS  = IOUT(15) from ARKDlsGetWorkSpace (integer space)
+        LSTF     = IOUT(16) from ARKDlsGetLastFlag
+        NFELS    = IOUT(17) from ARKDlsGetNumRhsEvals
+        NJED     = IOUT(18) from ARKDlsGetNumJacEvals
+
+     Optional outputs specific to the ARKDLSMASS interface:
+        LENRWMS  = IOUT(23) from ARKDlsGetMassWorkSpace (realtype space)
+        LENIWMS  = IOUT(24) from ARKDlsGetMassWorkSpace (integer space)
+        LSTMF    = IOUT(25) from ARKDlsGetLastMassFlag
+        NMSETUP  = IOUT(26) from ARKDlsGetNumMassSetups
+        NMSOLVES = IOUT(27) from ARKDlsGetNumMassSolves
+        NMMULTS  = IOUT(28) from ARKDlsGetNumMassMult
+
+     Optional outputs specific to the ARKSPILS interface:
+        LENRWLS  = IOUT(14) from ARKSpilsGetWorkSpace
+        LENIWLS  = IOUT(15) from ARKSpilsGetWorkSpace
+        LSTF     = IOUT(16) from ARKSpilsGetLastFlag
+        NFELS    = IOUT(17) from ARKSpilsGetNumRhsEvals
+        NJTV     = IOUT(18) from ARKSpilsGetNumJtimesEvals
+        NPE      = IOUT(19) from ARKSpilsGetNumPrecEvals
+        NPS      = IOUT(20) from ARKSpilsGetNumPrecSolves
+        NLI      = IOUT(21) from ARKSpilsGetNumLinIters
+        NCFL     = IOUT(22) from ARKSpilsGetNumConvFails
+ 
+     Optional outputs specific to the ARKSPILSMASS interface:
+        LENRWMS  = IOUT(23) from ARKSpilsGetMassWorkSpace
+        LENIWMS  = IOUT(24) from ARKSpilsGetMassWorkSpace
+        LSTMF    = IOUT(25) from ARKSpilsGetLastMassFlag
+        NMPE     = IOUT(26) from ARKSpilsGetNumMassPrecEvals
+        NMPS     = IOUT(27) from ARKSpilsGetNumMassPrecSolves
+        NMLI     = IOUT(28) from ARKSpilsGetNumMassIters
+        NMCFL    = IOUT(29) from ARKSpilsGetNumMassConvFails
+ 
+     See the ARKODE manual for more detailed descriptions of any of the 
+     above.
 
-     In the case of using either an implicit or ImEx method and a Newton 
-     iteration, the solution of each Runge-Kutta stage may involve the 
-     solution of linear systems related to the Jacobian J = dfi(t,y)/dy of the 
-     implicit portion of the ODE system. ARKode presently includes a variety 
-     of choices for the treatment of these systems, and the user of FARKODE 
-     must call a routine with a specific name to make the desired choice.  
-     Following any call to FARKMALLOC or FARKRESIZE, one of these solver 
-     specification routines must be called again to set up the linear solver
-     memory.
+ -----------------------------------------------------------------------------
 
- (13.1s) DENSE treatment of the linear system.
+ (11) The integrator: FARKODE
 
-     The user must make the call
+     Carrying out the integration is accomplished by making calls as follows:
 
-       CALL FARKDENSE(NEQ, IER)
+       CALL FARKODE(TOUT, T, Y, ITASK, IER)
 
      The arguments are:
-        NEQ = the problem size [long int; input]
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
+       TOUT = next value of t at which a solution is desired [realtype, input]
+       T = value of t reached by the solver [realtype, output]
+       Y = array containing state variables on output [realtype, output]
+       ITASK = task indicator [int, input]:
+                  1 = normal mode (overshoot TOUT and interpolate)
+                  2 = one-step mode (return after each internal step taken)
+                  3 = normal tstop mode (like 1, but integration never 
+                      proceeds past TSTOP, which must be specified through a 
+                      call to FARKSETRIN using the key 'STOP_TIME')
+                  4 = one step tstop (like 2, but integration never goes 
+                      past TSTOP)
+       IER = completion flag [int, output]: 
+                  0 = success, 
+                  1 = tstop return, 
+                  2 = root return, 
+                  values -1 ... -10 are failure modes (see ARKODE manual).
+     The current values of the optional outputs are immediately available in
+     the IOUT and ROUT arrays.
  
-     If the user program includes the FARKDJAC routine for the evaluation of 
-     the dense approximation to the Jacobian, then after the call to 
-     FARKDENSE, the following call must be made 
-
-       CALL FARKDENSESETJAC(FLAG, IER)
+ -----------------------------------------------------------------------------
 
-     with the int FLAG=1 to specify that FARKDJAC is provided and should be 
-     used; FLAG=0 specifies a reset to the internal finite difference Jacobian
-     approximation.  The int return flag IER=0 if successful, and nonzero 
-     otherwise.
- 
-     Optional outputs specific to the DENSE case are:
-        LENRWLS = IOUT(14) from ARKDlsGetWorkSpace (realtype space)
-        LENIWLS = IOUT(15) from ARKDlsGetWorkSpace (integer space)
-        LSTF    = IOUT(16) from ARKDlsGetLastFlag
-        NFELS   = IOUT(17) from ARKDlsGetNumRhsEvals
-        NJED    = IOUT(18) from ARKDlsGetNumJacEvals
-     See the ARKODE manual for descriptions.
- 
- (13.2s) DENSE treatment of the mass matrix linear system.
+ (12) Computing solution derivatives: FARKDKY
 
-     The user must make the call
+     To obtain a derivative of the solution, of order up to the method order,
+     make the following call:
 
-       CALL FARKMASSDENSE(NEQ, IER)
+       CALL FARKDKY(T, K, DKY, IER)
 
      The arguments are:
-        NEQ = the problem size [long int; input]
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
+       T = time at which solution derivative is desired, within the interval
+           [TCUR-HU,TCUR], [realtype, input].
+       K = derivative order (0 .le. K .le. QU) [int, input]
+       DKY = array containing computed K-th derivative of y [realtype, output]
+       IER = return flag [int, output]: 0=success, <0 = illegal argument.
  
-     When using MASSDENSE, the user program must provide the FARKDMASS routine 
-     for the evaluation of the dense mass matrix.  To indicate that this routine
-     has been provided, following the call to FARKMASSDENSE, the following call 
-     must be made 
-
-       CALL FARKDENSESETMASS(IER)
+ -----------------------------------------------------------------------------
 
-     The int return flag IER=0 if successful, nonzero otherwise.
- 
-     Optional outputs specific to the MASSDENSE case are:
-        LENRWMS = IOUT(23) from ARKDlsGetMassWorkSpace (realtype space)
-        LENIWMS = IOUT(24) from ARKDlsGetMassWorkSpace (integer space)
-        LSTMF   = IOUT(25) from ARKDlsGetLastMassFlag
-        NME     = IOUT(26) from ARKDlsGetNumMassEvals
-     See the ARKODE manual for descriptions.
- 
- (13.3s) BAND treatment of the linear system
+ (13) Get the current error weight vector: FARKGETERRWEIGHTS
 
-     The user must make the call
+     To obtain the current error weight vector, make the following call:
 
-       CALL FARKBAND(NEQ, MU, ML, IER)
+       CALL FARKGETERRWEIGHTS(EWT, IER)
 
      The arguments are:
-        NEQ = problem size [long int, input]
-	MU = upper bandwidth [long int, input]
-	ML = lower bandwidth [long int, input]
-        IER = return flag [int, output]; 0 if successful, nonzero otherwise.
+       EWT = array containing the error weight vector [realtype, output]
+       IER = return flag [int, output]: 0=success, nonzero if an error.
  
-     If the user program includes the FARKBJAC routine for the evaluation of 
-     the band approximation to the Jacobian, then following the call to 
-     FARKBAND, the following call must be made 
+ -----------------------------------------------------------------------------
 
-       CALL FARKBANDSETJAC(FLAG, IER)
+ (14) Get the current residual weight vector: FARKGETRESWEIGHTS
 
-     with the int FLAG=1 to specify that FARKBJAC is provided and should be 
-     used; FLAG=0 specifies a reset to the internal finite difference Jacobian 
-     approximation.  The int return flag IER=0 if successful, nonzero otherwise.
+     To obtain the current residual weight vector, make the following call:
+
+       CALL FARKGETRESWEIGHTS(RWT, IER)
+
+     The arguments are:
+       RWT = array containing the residual weight vector [realtype, output]
+       IER = return flag [int, output]: 0=success, nonzero if an error.
  
-     Optional outputs specific to the BAND case are:
-        LENRWLS = IOUT(14) from ARKDlsGetWorkSpace (realtype space)
-        LENIWLS = IOUT(15) from ARKDlsGetWorkSpace (integer space)
-        LSTF    = IOUT(16) from ARKDlsGetLastFlag
-        NFELS   = IOUT(17) from ARKDlsGetNumRhsEvals
-        NJED    = IOUT(18) from ARKDlsGetNumJacEvals
-     See the ARKODE manual for descriptions.
+ -----------------------------------------------------------------------------
 
- (13.4s) BAND treatment of the mass matrix linear system
+ (15) Get an estimate of the local error: FARKGETESTLOCALERR
 
-     The user must make the call
+     To obtain the current error estimate vector, make the following call:
 
-       CALL FARKMASSBAND(NEQ, MU, ML, IER)
+       CALL FARKGETESTLOCALERR(ELE, IER)
 
      The arguments are:
-        NEQ = problem size [long int, input]
-	MU = upper bandwidth [long int, input]
-	ML = lower bandwidth [long int, input]
-        IER = return flag [int, output]; 0 if successful, nonzero otherwise.
+       ELE = array with the estimated local error vector [realtype, output]
+       IER = return flag [int, output]: 0=success, nonzero if an error.
  
-     When using MASSBAND, the user program must provide the FARKBMASS routine 
-     for the evaluation of the band mass matrix.  To indicate that this routine
-     has been provided, following the call to FARKMASSBAND, the following call 
-     must be made 
+ -----------------------------------------------------------------------------
 
-       CALL FARKBANDSETMASS(IER)
+ (16) Memory freeing: FARKFREE 
 
-     The int return flag IER=0 if successful, nonzero otherwise.
+     To free the internal memory created by the calls to FARKMALLOC, 
+     FARKDLSINIT/FARKSPILSINIT, the generic linear solver and matrix modules, 
+     and FNVINIT*, make the call
+
+       CALL FARKFREE()
  
-     Optional outputs specific to the MASSBAND case are:
-        LENRWMS = IOUT(23) from ARKDlsGetMassWorkSpace (realtype space)
-        LENIWMS = IOUT(24) from ARKDlsGetMassWorkSpace (integer space)
-        LSTMF   = IOUT(25) from ARKDlsGetLastMassFlag
-        NME     = IOUT(26) from ARKDlsGetNumMassEvals
-     See the ARKODE manual for descriptions.
+===============================================================*/
 
- (13.5s) LAPACK dense treatment of the linear system
+#ifndef _FARKODE_H
+#define _FARKODE_H
 
-     The user must make the call
+/* header files  */
+#include <arkode/arkode.h>
+#include <sundials/sundials_linearsolver.h>  /* definition of type SUNLinearSolver */
+#include <sundials/sundials_matrix.h>        /* definition of type SUNMatrix */
+#include <sundials/sundials_nvector.h>       /* definition of type N_Vector */
+#include <sundials/sundials_types.h>         /* definition of type realtype */
 
-       CALL FARKLAPACKDENSE(NEQ, IER)
+/*=============================================================*/
 
-     The arguments match those for FARKDENSE, except that NEQ is now a 
-     normal int (and not a long int).
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
 
-     Following the call to FARKLAPACKDENSE, the user may optionally call
+/* Definitions of interface function names */
+#if defined(SUNDIALS_F77_FUNC)
 
-       CALL FARKLAPACKDENSESETJAC(FLAG, IER)
-       
-     with the int FLAG=1 if the user provides the function FARKDJAC (and 
-     wishes to use it); FLAG=0 implies a reset to the default finite 
-     difference Jacobian approximation.
+#define FARK_IMP_FUN             SUNDIALS_F77_FUNC(farkifun,                FARKIFUN)
+#define FARK_EXP_FUN             SUNDIALS_F77_FUNC(farkefun,                FARKEFUN)
+#define FARK_MALLOC              SUNDIALS_F77_FUNC(farkmalloc,              FARKMALLOC)
+#define FARK_REINIT              SUNDIALS_F77_FUNC(farkreinit,              FARKREINIT)
+#define FARK_RESIZE              SUNDIALS_F77_FUNC(farkresize,              FARKRESIZE)
+#define FARK_SETDEFAULTS         SUNDIALS_F77_FUNC(farksetdefaults,         FARKSETDEFAULTS)
+#define FARK_SETIIN              SUNDIALS_F77_FUNC(farksetiin,              FARKSETIIN)
+#define FARK_SETRIN              SUNDIALS_F77_FUNC(farksetrin,              FARKSETRIN)
+#define FARK_SETADAPTMETHOD      SUNDIALS_F77_FUNC(farksetadaptivitymethod, FARKSETADAPTIVITYMETHOD)
+#define FARK_SETERKTABLE         SUNDIALS_F77_FUNC(farkseterktable,         FARKSETERKTABLE)
+#define FARK_SETIRKTABLE         SUNDIALS_F77_FUNC(farksetirktable,         FARKSETIRKTABLE)
+#define FARK_SETARKTABLES        SUNDIALS_F77_FUNC(farksetarktables,        FARKSETARKTABLES)
+#define FARK_SETRESTOLERANCE     SUNDIALS_F77_FUNC(farksetrestolerance,     FARKSETRESTOLERANCE)
+#define FARK_SETDIAGNOSTICS      SUNDIALS_F77_FUNC(farksetdiagnostics,      FARKSETDIAGNOSTICS)
+#define FARK_STOPDIAGNOSTICS     SUNDIALS_F77_FUNC(farkstopdiagnostics,     FARKSTOPDIAGNOSTICS)
+#define FARK_DLSINIT             SUNDIALS_F77_FUNC(farkdlsinit,             FARKDLSINIT)
+#define FARK_DLSMASSINIT         SUNDIALS_F77_FUNC(farkdlsmassinit,         FARKDLSMASSINIT)
+#define FARK_SPILSINIT           SUNDIALS_F77_FUNC(farkspilsinit,           FARKSPILSINIT)
+#define FARK_SPILSSETEPSLIN      SUNDIALS_F77_FUNC(farkspilssetepslin,      FARKSPILSSETEPSLIN)
+#define FARK_SPILSMASSINIT       SUNDIALS_F77_FUNC(farkspilsmassinit,       FARKSPILSMASSINIT)
+#define FARK_SPILSSETMASSEPSLIN  SUNDIALS_F77_FUNC(farkspilssetmassepslin,  FARKSPILSSETMASSEPSLIN)
+#define FARK_ARKODE              SUNDIALS_F77_FUNC(farkode,                 FARKODE)
+#define FARK_DKY                 SUNDIALS_F77_FUNC(farkdky,                 FARKDKY)
+#define FARK_GETERRWEIGHTS       SUNDIALS_F77_FUNC(farkgeterrweights,       FARKGETERRWEIGHTS)
+#define FARK_GETRESWEIGHTS       SUNDIALS_F77_FUNC(farkgetresweights,       FARKGETRESWEIGHTS)
+#define FARK_GETESTLOCALERR      SUNDIALS_F77_FUNC(farkgetestlocalerr,      FARKGETESTLOCALERR)
+#define FARK_FREE                SUNDIALS_F77_FUNC(farkfree,                FARKFREE)
+#define FARK_WRITEPARAMETERS     SUNDIALS_F77_FUNC(farkwriteparameters,     FARKWRITEPARAMETERS)
 
-     The optional outputs when using FARKLAPACKDENSE match those from 
-     FARKDENSE.
+#define FARK_DENSESETJAC         SUNDIALS_F77_FUNC(farkdensesetjac,         FARKDENSESETJAC)
+#define FARK_DJAC                SUNDIALS_F77_FUNC(farkdjac,                FARKDJAC)
 
- (13.6s) LAPACK dense treatment of the mass matrix linear system
+#define FARK_BANDSETJAC          SUNDIALS_F77_FUNC(farkbandsetjac,          FARKBANDSETJAC)
+#define FARK_BJAC                SUNDIALS_F77_FUNC(farkbjac,                FARKBJAC)
 
-     The user must make the call
+#define FARK_SPARSESETJAC        SUNDIALS_F77_FUNC(farksparsesetjac,        FARKSPARSESETJAC)
+#define FARK_SPJAC               SUNDIALS_F77_FUNC(farkspjac,               FARKSPJAC)
 
-       CALL FARKMASSLAPACKDENSE(NEQ, IER)
+#define FARK_DENSESETMASS        SUNDIALS_F77_FUNC(farkdensesetmass,        FARKDENSESETMASS)
+#define FARK_DMASS               SUNDIALS_F77_FUNC(farkdmass,               FARKDMASS)
 
-     The arguments match those for FARKMASSDENSE, except that NEQ is 
-     now a normal int (and not a long int).
-
-     Following the call to FARKMASSLAPACKDENSE, the user must call 
-
-       CALL FARKLAPACKDENSESETMASS(IER)
-
-     The int return flag IER=0 if successful, nonzero otherwise.
- 
-     The optional outputs when using FARKMASSLAPACKDENSE match those 
-     from FARKMASSDENSE.
-
- (13.7s) LAPACK band treatment of the linear system
-
-     The user must make the call
-
-       CALL FARKLAPACKBAND(NEQ, MUPPER, MLOWER, IER)
-
-     The arguments match those for FARKBAND, except that now all arguments 
-     have type 'int'.
-
-     Following the call to FARKLAPACKBAND, the user may optionally call
-
-       CALL FARKLAPACKBANDSETJAC(FLAG, IER)
-
-     with the int FLAG=1 if the user provides the function FARKBJAC (and 
-     wishes to use it); FLAG=0 implies a reset to the default finite 
-     difference Jacobian approximation.
-
-     The optional outputs when using FARKLAPACKBAND match those from FARKBAND.
-
- (13.8s) LAPACK band treatment of the mass matrix linear system
-
-     The user must make the call
-
-       CALL FARKMASSLAPACKBAND(NEQ, MUPPER, MLOWER, IER)
-
-     The arguments match those for FARKMASSBAND, except that now all 
-     arguments have type 'int'.
-
-     Following the call to FARKMASSLAPACKBAND, the user must call 
-
-       CALL FARKLAPACKBANDSETMASS(IER)
-
-     The int return flag IER=0 if successful, nonzero otherwise.
- 
-     The optional outputs when using FARKMASSLAPACKBAND match those from 
-     FARKMASSBAND.
-
- (13.9s) SPARSE treatment of the linear system using the KLU solver.
-
-     The user must make the call
-
-       CALL FARKKLU(NEQ, NNZ, SPARSETYPE, ORDERING, IER)
-
-     The arguments are:
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	SPARSETYPE = choice between CSC and CSR format
-           (0 = CSC, 1 = CSR) [int; input]
-	ORDERING = the matrix ordering desired, possible values come
-	   from the KLU package (0 = AMD, 1 = COLAMD) [int; input]
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
- 
-     When using the KLU solver the user must provide the FARKSPJAC routine for the 
-     evaluation of the sparse approximation to the Jacobian.  To indicate that this
-     routine has been provided, after the call to FARKKLU, the following call must 
-     be made 
-
-       CALL FARKSPARSESETJAC(IER)
-
-     The int return flag IER=0 if successful, and nonzero otherwise.
- 
- 
-     The ARKODE KLU solver will reuse much of the factorization information from one
-     nonlinear iteration to the next.  If at any time the user wants to force a full
-     refactorization or if the number of nonzeros in the Jacobian matrix changes, the
-     user should make the call
-
-       CALL FARKKLUREINIT(NEQ, NNZ, REINIT_TYPE)
-
-     The arguments are:
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be destroyed and 
-          a new one will be allocated with NNZ nonzeros.  For a value of 2, 
-	  only symbolic and numeric factorizations will be completed. 
- 
-     Optional outputs specific to the KLU case are:
-        LSTF    = IOUT(16) from ARKSlsGetLastFlag
-        NJES    = IOUT(18) from ARKSlsGetNumJacEvals
-     See the ARKODE manual for descriptions.
- 
- (13.10s) SPARSE treatment of the mass matrix linear system using the KLU solver.
-
-     The user must make the call
-
-       CALL FARKMASSKLU(NEQ, NNZ, SPARSETYPE, ORDERING, IER)
-
-     The arguments are:
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of mass matrix nonzeros [int; input]
-	SPARSETYPE = choice between CSC and CSR format
-           (0 = CSC, 1 = CSR) [int; input]
-	ORDERING = the matrix ordering desired, possible values
-	   come from the KLU package (0 = AMD, 1 = COLAMD) [int; input]
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
- 
-     When using the MASSKLU solver the user must provide the FARKSPMASS routine for 
-     the evaluation of the sparse mass matrix.  To indicate that this routine has 
-     been provided, after the call to FARKMASSKLU, the following call must be made 
-
-       CALL FARKSPARSESETMASS(IER)
-
-     The int return flag IER=0 if successful, and nonzero otherwise.
- 
-
-     The ARKODE KLU solver will reuse much of the factorization information from one
-     mass matrix solve to the next.  If at any time the user wants to force a full
-     refactorization or if the number of nonzeros in the mass matrix changes, the
-     user should make the call
-
-       CALL FARKMASSKLUREINIT(NEQ, NNZ, REINIT_TYPE)
-
-     The arguments are:
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be destroyed and 
-          a new one will be allocated with NNZ nonzeros.  For a value of 2, 
-	  only symbolic and numeric factorizations will be completed. 
- 
-     Optional outputs specific to the MASSKLU case are:
-        LSTMF = IOUT(25) from ARKSlsGetLastMassFlag
-        NME = IOUT(26) from ARKSlsGetNumMassEvals
-     See the ARKODE manual for descriptions.
- 
- (13.11s) SPARSE treatment of the linear system using the SuperLUMT solver.
-
-     The user must make the call
-
-       CALL FARKSUPERLUMT(NTHREADS, NEQ, NNZ, ORDERING, IER)
-
-     The arguments are:
-        NTHREADS = desired number of threads to use [int; input]
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	ORDERING = the matrix ordering desired, possible values
-	   come from the SuperLU_MT package [int; input]
-           0 = Natural
-           1 = Minimum degree on A^T A
-           2 = Minimum degree on A^T + A
-           3 = COLAMD
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
- 
-     At this time, there is no reinitialization capability for the SUNDIALS 
-     interfaces to the SuperLUMT solver.
-
-     When using the SUPERLUMT solver the user must provide the FARKSPJAC routine
-     for the evaluation of the sparse approximation to the Jacobian.  To indicate 
-     that this routine has been provided, after the call to FARKKLU, the following 
-     call must be made 
-
-       CALL FARKSPARSESETJAC(IER)
-
-     The int return flag IER=0 if successful, and nonzero otherwise.
- 
-     Optional outputs specific to the SUPERLUMT case are:
-        LSTF    = IOUT(16) from ARKSlsGetLastFlag
-        NJES    = IOUT(18) from ARKSlsGetNumJacEvals
-     See the ARKODE manual for descriptions.
- 
- (13.12s) SPARSE treatment of the mass matrix linear system using the SuperLUMT solver.
-
-     The user must make the call
-
-       CALL FARKMASSSUPERLUMT(NTHREADS, NEQ, NNZ, ORDERING, IER)
-
-     The arguments are:
-        NTHREADS = desired number of threads to use [int; input]
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	ORDERING = the matrix ordering desired, possible values
-	   come from the SuperLU_MT package [int; input]
-           0 = Natural
-           1 = Minimum degree on A^T A
-           2 = Minimum degree on A^T + A
-           3 = COLAMD
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
- 
-     At this time, there is no reinitialization capability for the SUNDIALS 
-     interfaces to the SuperLUMT solver.
-
-     When using the MASSSUPERLUMT solver the user must provide the FARKSPJAC 
-     routine for the evaluation of the mass matrix.  To indicate that this 
-     routine has been provided, after the call to FARKKLU, the following call
-     must be made 
-
-       CALL FARKSPARSESETMASS(IER)
-
-     The int return flag IER=0 if successful, and nonzero otherwise.
- 
-     Optional outputs specific to the MASSSUPERLUMT case are:
-        LSTMF = IOUT(25) from ARKSlsGetLastMassFlag
-        NME = IOUT(26) from ARKSlsGetNumMassEvals
-     See the ARKODE manual for descriptions.
- 
- (13.13) SPGMR treatment of the linear systems.
-
-     For the Scaled Preconditioned GMRES solution of the linear systems,
-     the user must make the following call:
-
-       CALL FARKSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = linear convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
-	IER = error return flag [int, output]: 
-	       0 = success; 
-	      <0 = an error occured
- 
-     Optional outputs specific to the SPGMR case are:
-        LENRWLS = IOUT(14) from ARKSpilsGetWorkSpace
-        LENIWLS = IOUT(15) from ARKSpilsGetWorkSpace
-        LSTF    = IOUT(16) from ARKSpilsGetLastFlag
-        NFELS   = IOUT(17) from ARKSpilsGetNumRhsEvals
-        NJTV    = IOUT(18) from ARKSpilsGetNumJtimesEvals
-        NPE     = IOUT(19) from ARKSpilsGetNumPrecEvals
-        NPS     = IOUT(20) from ARKSpilsGetNumPrecSolves
-        NLI     = IOUT(21) from ARKSpilsGetNumLinIters
-        NCFL    = IOUT(22) from ARKSpilsGetNumConvFails
-     See the ARKODE manual for descriptions.
- 
-     If a sequence of problems of the same size is being solved using the
-     SPGMR linear solver, then following the call to FARKREINIT, a call to 
-     the FARKSPGMRREINIT routine is needed if any of IPRETYPE, IGSTYPE, DELT 
-     is being changed.  In that case, call FARKSPGMRREINIT as follows:
-
-       CALL FARKSPGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPGMR.  If MAXL is being
-     changed, then the user should call FARKSPGMR instead.  
-
-     Note: if the problem has been resized using FARKRESIZE, then FARKSPGMR 
-     must be called again. 
- 
- (13.14) SPGMR treatment of the mass matrix linear systems.
-
-     For the Scaled Preconditioned GMRES solution of the mass matrix 
-     linear systems, the user must make the following call:
-
-       CALL FARKMASSSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = linear convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
-	IER = error return flag [int, output]: 
-	       0 = success; 
-	      <0 = an error occured
- 
-     Optional outputs specific to the MASSSPGMR case are:
-        LENRWMS = IOUT(23) from ARKSpilsGetMassWorkSpace
-        LENIWMS = IOUT(24) from ARKSpilsGetMassWorkSpace
-        LSTMF   = IOUT(25) from ARKSpilsGetLastMassFlag
-        NMPE    = IOUT(26) from ARKSpilsGetNumMassPrecEvals
-        NMPS    = IOUT(27) from ARKSpilsGetNumMassPrecSolves
-        NMLI    = IOUT(28) from ARKSpilsGetNumMassIters
-        NMCFL   = IOUT(29) from ARKSpilsGetNumMassConvFails
-     See the ARKODE manual for descriptions.
- 
-     If a sequence of problems of the same size is being solved using the
-     MASSSPGMR linear solver, then following the call to FARKREINIT, a call
-     to the FARKMASSSPGMRREINIT routine is needed if any of IPRETYPE, 
-     IGSTYPE, DELT is being changed.  In that case, call FARKMASSSPGMRREINIT 
-     as follows:
-
-       CALL FARKMASSSPGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKMASSSPGMR.  If MAXL is 
-     being changed, then the user should call FARKMASSSPGMR instead.  
-
-     Note: if the problem has been resized using FARKRESIZE, then 
-     FARKMASSSPGMR must be called again. 
- 
- (13.15) SPBCG treatment of the linear systems.
-
-     For the Scaled Preconditioned Bi-CGSTAB solution of the linear systems,
-     the user must make the following call:
-
-       CALL FARKSPBCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 0 = default.
-       DELT = linear convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     Optional outputs specific to the SPBCG case are identical to 
-     those from SPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     SPBCG linear solver, then following the call to FARKREINIT, a call to the
-     FARKSPBCGREINIT routine is needed if any of its arguments is being 
-     changed.  The call is:
-
-       CALL FARKSPBCGREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKSPBCG.
-
-     Note: if the problem has been resized using FARKRESIZE, then FARKSPBCG 
-     must be called again. 
-
- (13.16) SPBCG treatment of the mass matrix linear systems.
-
-     For the Scaled Preconditioned Bi-CGSTAB solution of the mass matrix 
-     linear systems, the user must make the following call:
-
-       CALL FARKMASSSPBCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 0 = default.
-       DELT = linear convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     Optional outputs specific to the MASSSPBCG case are identical to 
-     those from MASSSPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     MASSSPBCG linear solver, then following the call to FARKREINIT, a call 
-     to the FARKMASSSPBCGREINIT routine is needed if any of its arguments 
-     is being changed.  The call is:
-
-       CALL FARKMASSSPBCGREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKMASSSPBCG.
-
-     Note: if the problem has been resized using FARKRESIZE, then 
-     FARKMASSSPBCG must be called again. 
-
- (13.17) SPTFQMR treatment of the linear systems.
-
-     For the Scaled Preconditioned TFQMR solution of the linear systems, the
-     user must make the following call:
-
-       CALL FARKSPTFQMR(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 0 = default.
-       DELT = linear convergence tolerance factor [realtype, input]
-	      0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     Optional outputs specific to the SPTFQMR case are identical to 
-     those from SPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     SPTFQMR linear solver, then following the call to FARKREINIT, a call to 
-     the FARKSPTFQMRREINIT routine is needed if any of its arguments is
-     being changed.  The call is:
-
-       CALL FARKSPTFQMRREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKSPTFQMR.
-
-     Note: if the problem has been resized using FARKRESIZE, then FARKSPTFQMR 
-     must be called again. 
-
- (13.18) SPTFQMR treatment of the mass matrix linear systems.
-
-     For the Scaled Preconditioned TFQMR solution of the mass matrix 
-     linear systems, the user must make the following call:
-
-       CALL FARKMASSSPTFQMR(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 0 = default.
-       DELT = linear convergence tolerance factor [realtype, input]
-	      0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     Optional outputs specific to the MASSSPTFQMR case are identical to 
-     those from MASSSPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     MASSSPTFQMR linear solver, then following the call to FARKREINIT, a 
-     call to the FARKMASSSPTFQMRREINIT routine is needed if any of its 
-     arguments is being changed.  The call is:
-
-       CALL FARKMASSSPTFQMRREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKMASSSPTFQMR.
-
-     Note: if the problem has been resized using FARKRESIZE, then 
-     FARKMASSSPTFQMR must be called again. 
-
- (13.19) SPFGMR treatment of the linear systems.
-
-     For the Scaled Preconditioned Flexible GMRES solution of the linear 
-     systems, the user must make the following call:
-
-       CALL FARKSPFGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = linear convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
-	IER = error return flag [int, output]: 
-	       0 = success; 
-	      <0 = an error occured
- 
-     Optional outputs specific to the SPFGMR case are identical to 
-     those from SPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     SPFGMR linear solver, then following the call to FARKREINIT, a call to 
-     the FARKSPFGMRREINIT routine is needed if any of IPRETYPE, IGSTYPE, DELT 
-     is being changed.  In that case, call FARKSPFGMRREINIT as follows:
-
-       CALL FARKSPFGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKSPFGMR.  If MAXL is being
-     changed, then the user should call FARKSPFGMR instead.  
-
-     Note: if the problem has been resized using FARKRESIZE, then FARKSPFGMR 
-     must be called again. 
- 
- (13.20) SPFGMR treatment of the mass matrix linear systems.
-
-     For the Scaled Preconditioned Flexible GMRES solution of the mass 
-     matrix linear systems, the user must make the following call:
-
-       CALL FARKMASSSPFGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-        IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-	IGSTYPE = Gram-schmidt process type [int, input]: 
-              1 = modified G-S
-              2 = classical G-S.
-	MAXL = maximum Krylov subspace dimension [int; input]; 
-	      0 = default
-	DELT = linear convergence tolerance factor [realtype, input]; 
-	      0.0 = default.
-	IER = error return flag [int, output]: 
-	       0 = success; 
-	      <0 = an error occured
- 
-     Optional outputs specific to the MASSSPFGMR case are identical to 
-     those from MASSSPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     MASSSPFGMR linear solver, then following the call to FARKREINIT, a 
-     call to the FARKMASSSPFGMRREINIT routine is needed if any of IPRETYPE, 
-     IGSTYPE, DELT is being changed.  In that case, call 
-     FARKMASSSPFGMRREINIT as follows:
-
-       CALL FARKMASSSPFGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)
-
-     The arguments have the same meanings as for FARKMASSSPFGMR.  If MAXL 
-     is being changed, then the user should call FARKMASSSPFGMR instead.  
-
-     Note: if the problem has been resized using FARKRESIZE, then 
-     FARKMASSSPFGMR must be called again. 
- 
- (13.21) PCG treatment of the linear systems.
-
-     For the Preconditioned Conjugate Gradient solution of the linear systems,
-     the user must make the following call:
-
-       CALL FARKPCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 0 = default.
-       DELT = linear convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     Optional outputs specific to the PCG case are identical to 
-     those from SPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     PCG linear solver, then following the call to FARKREINIT, a call to the
-     FARKPCGREINIT routine is needed if any of its arguments is being 
-     changed.  The call is:
-
-       CALL FARKPCGREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKPCG.
-
-     Note: if the problem has been resized using FARKRESIZE, then FARKPCG
-     must be called again. 
-
- (13.22) PCG treatment of the mass matrix linear systems.
-
-     For the Preconditioned Conjugate Gradient solution of the mass matrix 
-     linear systems, the user must make the following call:
-
-       CALL FARKMASSPCG(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments are:
-       IPRETYPE = preconditioner type [int, input]: 
-              0 = none 
-              1 = left only
-              2 = right only
-              3 = both sides
-       MAXL = maximum Krylov subspace dimension [int, input]; 0 = default.
-       DELT = linear convergence tolerance factor [realtype, input]; 
-              0.0 = default.
-       IER = error return flag [int, output]: 
-              0 = success; 
-	     <0 = an error occured
- 
-     Optional outputs specific to the MASSPCG case are identical to 
-     those from MASSSPGMR.
- 
-     If a sequence of problems of the same size is being solved using the
-     MASSPCG linear solver, then following the call to FARKREINIT, a call 
-     to the FARKMASSPCGREINIT routine is needed if any of its arguments 
-     is being changed.  The call is:
-
-       CALL FARKMASSPCGREINIT(IPRETYPE, MAXL, DELT, IER)              
-
-     The arguments have the same meanings as for FARKMASSPCG.
-
-     Note: if the problem has been resized using FARKRESIZE, then 
-     FARKMASSPCG must be called again. 
-
- (13.23) Usage of user-supplied routines for the system Krylov solvers
-
-     If the user program includes the FARKJTIMES routine for the evaluation of
-     the Jacobian vector product, then after specifying the linear solver 
-     choice (e.g. FARKSPGMR), the following call must be made
-
-       CALL FARKSPILSSETJAC(FLAG, IER)
-
-     with the int FLAG=1 to specify that FARKJTIMES is provided and should
-     be used; FLAG=0 specifies a reset to the internal finite difference 
-     approximation to this product).  The int return flag IER=0 if 
-     successful, and nonzero otherwise.
- 
-     Usage of the user-supplied routines FARKPSOL and FARKPSET for solution of
-     the preconditioner linear system similarly requires the following call after 
-     specifying the linear solver module:
-
-       CALL FARKSPILSSETPREC(FLAG, IER)
-
-     with the int FLAG=1.  If FLAG=0 then preconditioning with these routines 
-     will be disabled. The return flag IER=0 if successful, nonzero otherwise.
-
-     NOTE: following any call to FARKRESIZE, either of the above routines must 
-     again be called following re-specification of the linear solver module.
-
-     The user-supplied routine FARKPSET must have the form:
-
-       SUBROUTINE FARKPSET(T,Y,FY,JOK,JCUR,GAMMA,H,IPAR,RPAR,V1,V2,V3,IER)
-
-     This routine must set up the preconditioner P to be used in the 
-     subsequent call to FARKPSOL.  The preconditioner (or the product of the 
-     left and right preconditioners if using both) should be an approximation 
-     to the matrix  M(T) - GAMMA*J  (M(T) = mass matrix, J = Jacobian),
-
-     The arguments are:
-       T = current time [realtype, input]
-       Y = current state variable array [realtype, input]
-       FY = current state variable derivative array [realtype, input]
-       JOK = flag indicating whether Jacobian-related data needs to be 
-           recomputed [int, input]:
-                  0 = recompute, 
-		  1 = reuse with the current value of GAMMA
-       JCUR = return flag to denote if Jacobian data was recomputed
-           [realtype, output], 1=yes, 0=no
-       GAMMA = Jacobian scaling factor [realtype, input]
-       H = current time step [realtype, input]
-       IPAR = array of user integer data [long int, input/output]
-       RPAR = array with user real data [realtype, input/output]
-       V* -- array containing temporary workspace of same size as Y 
-               [realtype, input]
-       IER  = return completion flag [int, output]:
-                  0 = SUCCESS,
-		 >0 = recoverable failure
-                 <0 = non-recoverable failure
-
-     The user-supplied routine FARKPSOL must have the form:
-
-       SUBROUTINE FARKPSOL(T,Y,FY,R,Z,GAMMA,DELTA,LR,IPAR,RPAR,VT,IER)
-
-       DIMENSION Y(*), FY(*), VT(*), R(*), Z(*), IPAR(*), RPAR(*)
-
-     Typically this routine will use only T, Y, GAMMA, R, LR, and Z.  It
-     must solve the preconditioner linear system Pz = r.  The preconditioner
-     (or the product of the left and right preconditioners if both are 
-     nontrivial) should be an approximation to the matrix  M(T) - GAMMA*J  
-     (M(T) = mass matrix, J = Jacobian).
-
-     The arguments are:
-       T = current time [realtype, input]
-       Y = current state variable array [realtype, input]
-       FY = current state variable derivative array [realtype, input]
-       R = right-hand side array [realtype, input]
-       Z = solution array [realtype, output]
-       GAMMA = Jacobian scaling factor [realtype, input]
-       DELTA = desired residual tolerance [realtype, input]
-       LR = flag denoting to solve the right or left preconditioner system
-                  1 = left preconditioner
-		  2 = right preconditioner
-       IPAR = array of user integer data [long int, input/output]
-       RPAR = array with user real data [realtype, input/output]
-       VT -- array containing temporary workspace of same size as Y 
-               [realtype, input]
-       IER  = return completion flag [int, output]:
-                  0 = SUCCESS,
-		 >0 = recoverable failure
-                 <0 = non-recoverable failure
-
- (13.24) Usage of user-supplied routines for the mass matrix Krylov solvers
-
-     When using any of the MASSSPGMR, MASSSPBCG, MASSSPTFQMR, MASSSPFGMR or 
-     MASSPCG mass matrix linear solvers, the user must supply the 
-     FARKMTIMES routine for the evaluation of the mass matrix vector product.  
-     After specifying the linear solver choice (e.g. FARKMASSSPGMR), the 
-     following call must be made
-
-       CALL FARKSPILSSETMASS(IER)
-
-     The int return flag IER=0 if successful, and nonzero otherwise.
-
- 
-     Usage of the user-supplied routines FARKMASSPSOL and FARKMASSPSET for 
-     solution of the mass matrix preconditioner linear system similarly 
-     requires the following call after specifying the mass matrix linear 
-     solver module:
-
-       CALL FARKSPILSSETMASSPREC(FLAG, IER)
-
-     with the int FLAG=1. If FLAG=0 then preconditioning with these routines 
-     will be disabled. The return flag IER=0 if successful, nonzero otherwise.
-
-     NOTE: following any call to FARKRESIZE, the above routine must again 
-     be called following re-specification of the linear solver module.
-
-     The user-supplied routine FARKMASSPSET must have the form:
-
-       SUBROUTINE FARKMASSPSET(T,IPAR,RPAR,V1,V2,V3,IER)
-
-     This routine must set up the preconditioner P to be used in the 
-     subsequent call to FARKMASSPSOL.  The preconditioner (or the product 
-     of the left and right preconditioners if using both) should be an 
-     approximation to the system mass matrix M.
-
-     The arguments are:
-       T = current time [realtype, input]
-       IPAR = array of user integer data [long int, input/output]
-       RPAR = array with user real data [realtype, input/output]
-       V* -- array containing temporary workspace of same size as Y 
-               [realtype, input]
-       IER  = return completion flag [int, output]:
-                  0 = SUCCESS,
-		 >0 = recoverable failure
-                 <0 = non-recoverable failure
-
-     The user-supplied routine FARKMASSPSOL must have the form:
-
-       SUBROUTINE FARKMASSPSOL(T,R,Z,DELTA,LR,IPAR,RPAR,VT,IER)
-
-       DIMENSION VT(*), R(*), Z(*), IPAR(*), RPAR(*)
-
-     Typically this routine will use only T, R, LR, and Z.  It
-     must solve the preconditioner linear system Pz = r.  The 
-     preconditioner (or the product of the left and right 
-     preconditioners if both are nontrivial) should be an 
-     approximation to the system mass matrix M.
-
-     The arguments are:
-       T = current time [realtype, input]
-       R = right-hand side array [realtype, input]
-       Z = solution array [realtype, output]
-       DELTA = desired residual tolerance [realtype, input]
-       LR = flag denoting to solve the right or left preconditioner system
-                  1 = left preconditioner
-		  2 = right preconditioner
-       IPAR = array of user integer data [long int, input/output]
-       RPAR = array with user real data [realtype, input/output]
-       VT -- array containing temporary workspace of same size as Y 
-               [realtype, input]
-       IER  = return completion flag [int, output]:
-                  0 = SUCCESS,
-		 >0 = recoverable failure
-                 <0 = non-recoverable failure
-
- -----------------------------------------------------------------------------
-
- (14) The integrator: FARKODE
-
-     Carrying out the integration is accomplished by making calls as follows:
-
-       CALL FARKODE(TOUT, T, Y, ITASK, IER)
-
-     The arguments are:
-       TOUT = next value of t at which a solution is desired [realtype, input]
-       T = value of t reached by the solver [realtype, output]
-       Y = array containing state variables on output (realtype, output]
-       ITASK = task indicator [int, input]:
-                  1 = normal mode (overshoot TOUT and interpolate)
-		  2 = one-step mode (return after each internal step taken)
-		  3 = normal tstop mode (like 1, but integration never 
-		      proceeds past TSTOP, which must be specified through a 
-		      call to FARKSETRIN using the key 'STOP_TIME')
-		  4 = one step tstop (like 2, but integration never goes 
-		      past TSTOP)
-       IER = completion flag [int, output]: 
-                  0 = success, 
-		  1 = tstop return, 
-		  2 = root return, 
-                  values -1 ... -10 are failure modes (see ARKODE manual).
-     The current values of the optional outputs are immediately available in
-     the IOUT and ROUT arrays.
- 
- -----------------------------------------------------------------------------
-
- (15) Computing solution derivatives: FARKDKY
-
-     To obtain a derivative of the solution, of order up to the method order,
-     make the following call:
-
-       CALL FARKDKY(T, K, DKY, IER)
-
-     The arguments are:
-       T = time at which solution derivative is desired, within the interval
-           [TCUR-HU,TCUR], [realtype, input].
-       K = derivative order (0 .le. K .le. QU) [int, input]
-       DKY = array containing computed K-th derivative of y [realtype, output]
-       IER = return flag [int, output]: 0=success, <0 = illegal argument.
- 
- -----------------------------------------------------------------------------
-
- (16) Get the current weight vector: FARKGETERRWEIGHTS
-
-     To obtain the current weight vector, make the following call:
-
-       CALL FARKGETERRWEIGHTS(EWT, IER)
-
-     The arguments are:
-       EWT = array containing the error weight vector [realtype, output]
-       IER = return flag [int, output]: 0=success, nonzero if an error.
- 
- -----------------------------------------------------------------------------
-
- (17) Get an estimate of the local error: FARKGETESTLOCALERR
-
-     To obtain the current error estimate vector, make the following call:
-
-       CALL FARKGETESTLOCALERR(ELE, IER)
-
-     The arguments are:
-       ELE = array with the estimated local error vector [realtype, output]
-       IER = return flag [int, output]: 0=success, nonzero if an error.
- 
- -----------------------------------------------------------------------------
-
- (18) Memory freeing: FARKFREE 
-
-     To free the internal memory created by the calls to FARKMALLOC and
-     FNVINITS, FNVINITOMP, FNVINITPTS or FNVINITP, make the call
-
-       CALL FARKFREE()
- 
-===============================================================*/
-
-#ifndef _FARKODE_H
-#define _FARKODE_H
-
-/* header files  */
-#include <arkode/arkode.h>
-#include <sundials/sundials_direct.h>  /* definition of type DlsMat   */
-#include <sundials/sundials_sparse.h>  /* definition of type SlsMat   */
-#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
-#include <sundials/sundials_types.h>   /* definition of type realtype */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/* Definitions of interface function names */
-#if defined(SUNDIALS_F77_FUNC)
-
-#define FARK_MALLOC              SUNDIALS_F77_FUNC(farkmalloc,              FARKMALLOC)
-#define FARK_REINIT              SUNDIALS_F77_FUNC(farkreinit,              FARKREINIT)
-#define FARK_RESIZE              SUNDIALS_F77_FUNC(farkresize,              FARKRESIZE)
-#define FARK_SETDEFAULTS         SUNDIALS_F77_FUNC(farksetdefaults,         FARKSETDEFAULTS)
-#define FARK_SETIIN              SUNDIALS_F77_FUNC(farksetiin,              FARKSETIIN)
-#define FARK_SETRIN              SUNDIALS_F77_FUNC(farksetrin,              FARKSETRIN)
-#define FARK_SETERKTABLE         SUNDIALS_F77_FUNC(farkseterktable,         FARKSETERKTABLE)
-#define FARK_SETIRKTABLE         SUNDIALS_F77_FUNC(farksetirktable,         FARKSETIRKTABLE)
-#define FARK_SETARKTABLES        SUNDIALS_F77_FUNC(farksetarktables,        FARKSETARKTABLES)
-#define FARK_SETRESTOLERANCE     SUNDIALS_F77_FUNC(farksetrestolerance,     FARKSETRESTOLERANCE)
-#define FARK_SETDIAGNOSTICS      SUNDIALS_F77_FUNC(farksetdiagnostics,      FARKSETDIAGNOSTICS)
-#define FARK_STOPDIAGNOSTICS     SUNDIALS_F77_FUNC(farkstopdiagnostics,     FARKSTOPDIAGNOSTICS)
-#define FARK_DENSE               SUNDIALS_F77_FUNC(farkdense,               FARKDENSE)
-#define FARK_DENSESETJAC         SUNDIALS_F77_FUNC(farkdensesetjac,         FARKDENSESETJAC)
-#define FARK_MASSDENSE           SUNDIALS_F77_FUNC(farkmassdense,           FARKMASSDENSE)
-#define FARK_DENSESETMASS        SUNDIALS_F77_FUNC(farkdensesetmass,        FARKDENSESETMASS)
-#define FARK_BAND                SUNDIALS_F77_FUNC(farkband,                FARKBAND)
-#define FARK_BANDSETJAC          SUNDIALS_F77_FUNC(farkbandsetjac,          FARKBANDSETJAC)
-#define FARK_MASSBAND            SUNDIALS_F77_FUNC(farkmassband,            FARKMASSBAND)
 #define FARK_BANDSETMASS         SUNDIALS_F77_FUNC(farkbandsetmass,         FARKBANDSETMASS)
-#define FARK_LAPACKDENSE         SUNDIALS_F77_FUNC(farklapackdense,         FARKLAPACKDENSE)
-#define FARK_LAPACKDENSESETJAC   SUNDIALS_F77_FUNC(farklapackdensesetjac,   FARKLAPACKDENSESETJAC)
-#define FARK_MASSLAPACKDENSE     SUNDIALS_F77_FUNC(farkmasslapackdense,     FARKMASSLAPACKDENSE)
-#define FARK_LAPACKDENSESETMASS  SUNDIALS_F77_FUNC(farklapackdensesetmass,  FARKLAPACKDENSESETMASS)
-#define FARK_LAPACKBAND          SUNDIALS_F77_FUNC(farklapackband,          FARKLAPACKBAND)
-#define FARK_LAPACKBANDSETJAC    SUNDIALS_F77_FUNC(farklapackbandsetjac,    FARKLAPACKBANDSETJAC)
-#define FARK_MASSLAPACKBAND      SUNDIALS_F77_FUNC(farkmasslapackband,      FARKMASSLAPACKBAND)
-#define FARK_LAPACKBANDSETMASS   SUNDIALS_F77_FUNC(farklapackbandsetmass,   FARKLAPACKBANDSETMASS)
-#define FARK_KLU                 SUNDIALS_F77_FUNC(farkklu,                 FARKKLU)
-#define FARK_KLUREINIT           SUNDIALS_F77_FUNC(farkklureinit,           FARKKLUREINIT)
-#define FARK_SUPERLUMT           SUNDIALS_F77_FUNC(farksuperlumt,           FARKSUPERLUMT)
-#define FARK_SPARSESETJAC        SUNDIALS_F77_FUNC(farksparsesetjac,        FARKSPARSESETJAC)
-#define FARK_MASSKLU             SUNDIALS_F77_FUNC(farkmassklu,             FARKMASSKLU)
-#define FARK_MASSKLUREINIT       SUNDIALS_F77_FUNC(farkmassklureinit,       FARKMASSKLUREINIT)
-#define FARK_MASSSUPERLUMT       SUNDIALS_F77_FUNC(farkmasssuperlumt,       FARKMASSSUPERLUMT)
+#define FARK_BMASS               SUNDIALS_F77_FUNC(farkbmass,               FARKBMASS)
+
 #define FARK_SPARSESETMASS       SUNDIALS_F77_FUNC(farksparsesetmass,       FARKSPARSESETMASS)
-#define FARK_SPTFQMR             SUNDIALS_F77_FUNC(farksptfqmr,             FARKSPTFQMR)
-#define FARK_SPTFQMRREINIT       SUNDIALS_F77_FUNC(farksptfqmrreinit,       FARKSPTFQMRREINIT)
-#define FARK_MASSSPTFQMR         SUNDIALS_F77_FUNC(farkmasssptfqmr,         FARKMASSSPTFQMR)
-#define FARK_MASSSPTFQMRREINIT   SUNDIALS_F77_FUNC(farkmasssptfqmrreinit,   FARKMASSSPTFQMRREINIT)
-#define FARK_SPBCG               SUNDIALS_F77_FUNC(farkspbcg,               FARKSPBCG)
-#define FARK_SPBCGREINIT         SUNDIALS_F77_FUNC(farkspbcgreinit,         FARKSPBCGREINIT)
-#define FARK_MASSSPBCG           SUNDIALS_F77_FUNC(farkmassspbcg,           FARKMASSSPBCG)
-#define FARK_MASSSPBCGREINIT     SUNDIALS_F77_FUNC(farkmassspbcgreinit,     FARKMASSSPBCGREINIT)
-#define FARK_SPGMR               SUNDIALS_F77_FUNC(farkspgmr,               FARKSPGMR)
-#define FARK_SPGMRREINIT         SUNDIALS_F77_FUNC(farkspgmrreinit,         FARKSPGMRREINIT)
-#define FARK_MASSSPGMR           SUNDIALS_F77_FUNC(farkmassspgmr,           FARKMASSSPGMR)
-#define FARK_MASSSPGMRREINIT     SUNDIALS_F77_FUNC(farkmassspgmrreinit,     FARKMASSSPGMRREINIT)
-#define FARK_SPFGMR              SUNDIALS_F77_FUNC(farkspfgmr,              FARKSPFGMR)
-#define FARK_SPFGMRREINIT        SUNDIALS_F77_FUNC(farkspfgmrreinit,        FARKSPFGMRREINIT)
-#define FARK_MASSSPFGMR          SUNDIALS_F77_FUNC(farkmassspfgmr,          FARKMASSSPFGMR)
-#define FARK_MASSSPFGMRREINIT    SUNDIALS_F77_FUNC(farkmassspfgmrreinit,    FARKMASSSPFGMRREINIT)
-#define FARK_PCG                 SUNDIALS_F77_FUNC(farkpcg,                 FARKPCG)
-#define FARK_PCGREINIT           SUNDIALS_F77_FUNC(farkpcgreinit,           FARKPCGREINIT)
-#define FARK_MASSPCG             SUNDIALS_F77_FUNC(farkmasspcg,             FARKMASSPCG)
-#define FARK_MASSPCGREINIT       SUNDIALS_F77_FUNC(farkmasspcgreinit,       FARKMASSPCGREINIT)
+#define FARK_SPMASS              SUNDIALS_F77_FUNC(farkspmass,              FARKSPMASS)
+
 #define FARK_SPILSSETJAC         SUNDIALS_F77_FUNC(farkspilssetjac,         FARKSPILSSETJAC)
+#define FARK_JTSETUP             SUNDIALS_F77_FUNC(farkjtsetup,             FARKJTSETUP)
+#define FARK_JTIMES              SUNDIALS_F77_FUNC(farkjtimes,              FARKJTIMES)
+
 #define FARK_SPILSSETPREC        SUNDIALS_F77_FUNC(farkspilssetprec,        FARKSPILSSETPREC)
-#define FARK_SPILSSETMASS        SUNDIALS_F77_FUNC(farkspilssetmass,        FARKSPILSSETMASS)
-#define FARK_SPILSSETMASSPREC    SUNDIALS_F77_FUNC(farkspilssetmassprec,    FARKSPILSSETMASSPREC)
-#define FARK_ARKODE              SUNDIALS_F77_FUNC(farkode,                 FARKODE)
-#define FARK_DKY                 SUNDIALS_F77_FUNC(farkdky,                 FARKDKY)
-#define FARK_FREE                SUNDIALS_F77_FUNC(farkfree,                FARKFREE)
-#define FARK_IMP_FUN             SUNDIALS_F77_FUNC(farkifun,                FARKIFUN)
-#define FARK_EXP_FUN             SUNDIALS_F77_FUNC(farkefun,                FARKEFUN)
-#define FARK_DJAC                SUNDIALS_F77_FUNC(farkdjac,                FARKDJAC)
-#define FARK_DMASS               SUNDIALS_F77_FUNC(farkdmass,               FARKDMASS)
-#define FARK_BJAC                SUNDIALS_F77_FUNC(farkbjac,                FARKBJAC)
-#define FARK_BMASS               SUNDIALS_F77_FUNC(farkbmass,               FARKBMASS)
-#define FARK_SPJAC               SUNDIALS_F77_FUNC(farkspjac,               FARKSPJAC)
-#define FARK_SPMASS              SUNDIALS_F77_FUNC(farkspmass,              FARKSPMASS)
 #define FARK_PSOL                SUNDIALS_F77_FUNC(farkpsol,                FARKPSOL)
 #define FARK_PSET                SUNDIALS_F77_FUNC(farkpset,                FARKPSET)
+
+#define FARK_SPILSSETMASS        SUNDIALS_F77_FUNC(farkspilssetmass,        FARKSPILSSETMASS)
+#define FARK_MTSETUP             SUNDIALS_F77_FUNC(farkmtsetup,             FARKMTSETUP)
+#define FARK_MTIMES              SUNDIALS_F77_FUNC(farkmtimes,              FARKMTIMES)
+
+#define FARK_SPILSSETMASSPREC    SUNDIALS_F77_FUNC(farkspilssetmassprec,    FARKSPILSSETMASSPREC)
 #define FARK_MASSPSOL            SUNDIALS_F77_FUNC(farkmasspsol,            FARKMASSPSOL)
 #define FARK_MASSPSET            SUNDIALS_F77_FUNC(farkmasspset,            FARKMASSPSET)
-#define FARK_JTIMES              SUNDIALS_F77_FUNC(farkjtimes,              FARKJTIMES)
-#define FARK_MTIMES              SUNDIALS_F77_FUNC(farkmtimes,              FARKMTIMES)
-#define FARK_EWT                 SUNDIALS_F77_FUNC(farkewt,                 FARKEWT)
+
 #define FARK_EWTSET              SUNDIALS_F77_FUNC(farkewtset,              FARKEWTSET)
-#define FARK_GETERRWEIGHTS       SUNDIALS_F77_FUNC(farkgeterrweights,       FARKGETERRWEIGHTS)
-#define FARK_GETESTLOCALERR      SUNDIALS_F77_FUNC(farkgetestlocalerr,      FARKGETESTLOCALERR)
-#define FARK_WRITEPARAMETERS     SUNDIALS_F77_FUNC(farkwriteparameters,     FARKWRITEPARAMETERS)
-#define FARK_ADAPT               SUNDIALS_F77_FUNC(farkadapt,               FARKADAPT)
+#define FARK_EWT                 SUNDIALS_F77_FUNC(farkewt,                 FARKEWT)
+
 #define FARK_ADAPTSET            SUNDIALS_F77_FUNC(farkadaptset,            FARKADAPTSET)
-#define FARK_EXPSTAB             SUNDIALS_F77_FUNC(farkexpstab,             FARKEXPSTAB)
+#define FARK_ADAPT               SUNDIALS_F77_FUNC(farkadapt,               FARKADAPT)
+
 #define FARK_EXPSTABSET          SUNDIALS_F77_FUNC(farkexpstabset,          FARKEXPSTABSET)
-#define FARK_SETADAPTMETHOD      SUNDIALS_F77_FUNC(farksetadaptivitymethod, FARKSETADAPTIVITYMETHOD)
+#define FARK_EXPSTAB             SUNDIALS_F77_FUNC(farkexpstab,             FARKEXPSTAB)
 
 #else
 
+#define FARK_IMP_FUN             farkifun_
+#define FARK_EXP_FUN             farkefun_
 #define FARK_MALLOC              farkmalloc_
 #define FARK_REINIT              farkreinit_
 #define FARK_RESIZE              farkresize_
 #define FARK_SETDEFAULTS         farksetdefaults_
 #define FARK_SETIIN              farksetiin_
 #define FARK_SETRIN              farksetrin_
+#define FARK_SETADAPTMETHOD      farksetadaptivitymethod_
 #define FARK_SETERKTABLE         farkseterktable_
 #define FARK_SETIRKTABLE         farksetirktable_
 #define FARK_SETARKTABLES        farksetarktables_
 #define FARK_SETRESTOLERANCE     farksetrestolerance_
 #define FARK_SETDIAGNOSTICS      farksetdiagnostics_
 #define FARK_STOPDIAGNOSTICS     farkstopdiagnostics_
-#define FARK_DENSE               farkdense_
-#define FARK_DENSESETJAC         farkdensesetjac_
-#define FARK_MASSDENSE           farkmassdense_
-#define FARK_DENSESETMASS        farkdensesetmass_
-#define FARK_BAND                farkband_
-#define FARK_BANDSETJAC          farkbandsetjac_
-#define FARK_MASSBAND            farkmassband_
-#define FARK_BANDSETMASS         farkbandsetmass_
-#define FARK_LAPACKDENSE         farklapackdense_
-#define FARK_LAPACKDENSESETJAC   farklapackdensesetjac_
-#define FARK_MASSLAPACKDENSE     farkmasslapackdense_
-#define FARK_LAPACKDENSESETMASS  farklapackdensesetmass_
-#define FARK_LAPACKBAND          farklapackband_
-#define FARK_LAPACKBANDSETJAC    farklapackbandsetjac_
-#define FARK_MASSLAPACKBAND      farkmasslapackband_
-#define FARK_LAPACKBANDSETMASS   farklapackbandsetmass_
-#define FARK_KLU                 farkklu_
-#define FARK_KLUREINIT           farkklureinit_
-#define FARK_SUPERLUMT           farksuperlumt_
-#define FARK_SPARSESETJAC        farksparsesetjac_
-#define FARK_MASSKLU             farkmassklu_
-#define FARK_MASSKLUREINIT       farkmassklureinit_
-#define FARK_MASSSUPERLUMT       farkmasssuperlumt_
-#define FARK_SPARSESETMASS       farksparsesetmass_
-#define FARK_SPTFQMR             farksptfqmr_
-#define FARK_SPTFQMRREINIT       farksptfqmrreinit_
-#define FARK_MASSSPTFQMR         farkmasssptfqmr_
-#define FARK_MASSSPTFQMRREINIT   farkmasssptfqmrreinit_
-#define FARK_SPBCG               farkspbcg_
-#define FARK_SPBCGREINIT         farkspbcgreinit_
-#define FARK_MASSSPBCG           farkmassspbcg_
-#define FARK_MASSSPBCGREINIT     farkmassspbcgreinit_
-#define FARK_SPGMR               farkspgmr_
-#define FARK_SPGMRREINIT         farkspgmrreinit_
-#define FARK_MASSSPGMR           farkmassspgmr_
-#define FARK_MASSSPGMRREINIT     farkmassspgmrreinit_
-#define FARK_SPFGMR              farkspfgmr_
-#define FARK_SPFGMRREINIT        farkspfgmrreinit_
-#define FARK_MASSSPFGMR          farkmassspfgmr_
-#define FARK_MASSSPFGMRREINIT    farkmassspfgmrreinit_
-#define FARK_PCG                 farkpcg_
-#define FARK_PCGREINIT           farkpcgreinit_
-#define FARK_MASSPCG             farkmasspcg_
-#define FARK_MASSPCGREINIT       farkmasspcgreinit_
-#define FARK_SPILSSETJAC         farkspilssetjac_
-#define FARK_SPILSSETPREC        farkspilssetprec_
-#define FARK_SPILSSETMASS        farkspilssetmass_
-#define FARK_SPILSSETMASSPREC    farkmassspilssetprec_
+#define FARK_DLSINIT             farkdlsinit_
+#define FARK_DLSMASSINIT         farkdlsmassinit_
+#define FARK_SPILSINIT           farkspilsinit_
+#define FARK_SPILSSETEPSLIN      farkspilssetepslin_
+#define FARK_SPILSMASSINIT       farkspilsmassinit_
+#define FARK_SPILSSETMASSEPSLIN  farkspilssetmassepslin_
 #define FARK_ARKODE              farkode_
 #define FARK_DKY                 farkdky_
+#define FARK_GETERRWEIGHTS       farkgeterrweights_
+#define FARK_GETRESWEIGHTS       farkgetresweights_
+#define FARK_GETESTLOCALERR      farkgetestlocalerr_
 #define FARK_FREE                farkfree_
-#define FARK_IMP_FUN             farkifun_
-#define FARK_EXP_FUN             farkefun_
+#define FARK_WRITEPARAMETERS     farkwriteparameters_
+
+#define FARK_DENSESETJAC         farkdensesetjac_
 #define FARK_DJAC                farkdjac_
-#define FARK_DMASS               farkdmass_
+
+#define FARK_BANDSETJAC          farkbandsetjac_
 #define FARK_BJAC                farkbjac_
-#define FARK_BMASS               farkbmass_
+
+#define FARK_SPARSESETJAC        farksparsesetjac_
 #define FARK_SPJAC               farkspjac_
+
+#define FARK_DENSESETMASS        farkdensesetmass_
+#define FARK_DMASS               farkdmass_
+
+#define FARK_BANDSETMASS         farkbandsetmass_
+#define FARK_BMASS               farkbmass_
+
+#define FARK_SPARSESETMASS       farksparsesetmass_
 #define FARK_SPMASS              farkspmass_
+
+
+#define FARK_SPILSSETJAC         farkspilssetjac_
+#define FARK_JTSETUP             farkjtsetup_
+#define FARK_JTIMES              farkjtimes_
+
+#define FARK_SPILSSETPREC        farkspilssetprec_
 #define FARK_PSOL                farkpsol_
 #define FARK_PSET                farkpset_
+
+#define FARK_SPILSSETMASS        farkspilssetmass_
+#define FARK_MTSETUP             farkmtsetup_
+#define FARK_MTIMES              farkmtimes_
+
+#define FARK_SPILSSETMASSPREC    farkspilssetmassprec_
 #define FARK_MASSPSOL            farkmasspsol_
 #define FARK_MASSPSET            farkmasspset_
-#define FARK_JTIMES              farkjtimes_
-#define FARK_MTIMES              farkmtimes_
-#define FARK_EWT                 farkewt_
+
 #define FARK_EWTSET              farkewtset_
-#define FARK_GETERRWEIGHTS       farkgeterrweights_
-#define FARK_GETESTLOCALERR      farkgetestlocalerr_
-#define FARK_WRITEPARAMETERS     farkwriteparameters_
-#define FARK_ADAPT               farkadapt_
+#define FARK_EWT                 farkewt_
+
 #define FARK_ADAPTSET            farkadaptset_
-#define FARK_EXPSTAB             farkexpstab_
+#define FARK_ADAPT               farkadapt_
+
 #define FARK_EXPSTABSET          farkexpstabset_
-#define FARK_SETADAPTMETHOD      farksetadaptivitymethod_
+#define FARK_EXPSTAB             farkexpstab_
 
 #endif
 
@@ -2094,7 +1695,7 @@ extern "C" {
     realtype *rpar;
     long int *ipar;
   } *FARKUserData;
-  
+
   /* Prototypes of exported functions */
   void FARK_MALLOC(realtype *t0, realtype *y0, int *imex, 
 		   int *iatol, realtype *rtol, realtype *atol, 
@@ -2105,177 +1706,131 @@ extern "C" {
 		   int *iatol, realtype *rtol, realtype *atol,
 		   int *ier);
 
-  void FARK_RESIZE(realtype *t0, realtype *y0, realtype *hscale, 
+  void FARK_RESIZE(realtype *t0, realtype *y0, realtype *hscale,
 		   int *itol, realtype *rtol, realtype *atol, int *ier);
 
+  void FARK_SETDEFAULTS(int *ier);
   void FARK_SETIIN(char key_name[], long int *ival, int *ier);
   void FARK_SETRIN(char key_name[], realtype *rval, int *ier);
-  void FARK_SETDEFAULTS(int *ier);
+
+  void FARK_SETADAPTMETHOD(int *imethod, int *idefault, int *ipq, 
+			   realtype *params, int *ier);
+
   void FARK_SETERKTABLE(int *s, int *q, int *p, realtype *c, realtype *A, 
 			realtype *b, realtype *b2, int *ier);
-  void FARK_SETIRKTABLE(int *s, int *q, int *p, realtype *c, 
+  void FARK_SETIRKTABLE(int *s, int *q, int *p, realtype *c,
 			realtype *A, realtype *b, realtype *b2, int *ier);
-  void FARK_SETARKTABLES(int *s, int *q, int *p, realtype *ci, realtype *ce, 
-			 realtype *Ai, realtype *Ae, realtype *bi, 
-			 realtype *be, realtype *b2i, realtype *b2e, int *ier);
+  void FARK_SETARKTABLES(int *s, int *q, int *p, realtype *ci, 
+                         realtype *ce, realtype *Ai, realtype *Ae, 
+                         realtype *bi, realtype *be, realtype *b2i, 
+                         realtype *b2e, int *ier);
+
   void FARK_SETRESTOLERANCE(int *itol, realtype *atol, int *ier);
   void FARK_SETDIAGNOSTICS(char fname[], int *flen, int *ier);
   void FARK_STOPDIAGNOSTICS(int *ier);
 
-  void FARK_EWTSET(int *flag, int *ier);
-  void FARK_ADAPTSET(int *flag, int *ier);
-  void FARK_EXPSTABSET(int *flag, int *ier);
-
-  void FARK_DENSE(long int *neq, int *ier);
-  void FARK_DENSESETJAC(int *flag, int *ier);
-  void FARK_MASSDENSE(long int *neq, int *ier);
-  void FARK_DENSESETMASS(int *ier);
+  void FARK_DLSINIT(int *ier);
+  void FARK_DLSMASSINIT(int *time_dep, int *ier);
 
-  void FARK_BAND(long int *neq, long int *mupper, long int *mlower, int *ier);
-  void FARK_BANDSETJAC(int *flag, int *ier);
-  void FARK_MASSBAND(long int *neq, long int *mupper, long int *mlower, int *ier);
-  void FARK_BANDSETMASS(int *ier);
+  void FARK_SPILSINIT(int *ier);
+  void FARK_SPILSSETEPSLIN(realtype *eplifac, int *ier);
 
-  void FARK_LAPACKDENSE(int *neq, int *ier);
-  void FARK_LAPACKDENSESETJAC(int *flag, int *ier);
-  void FARK_MASSLAPACKDENSE(int *neq, int *ier);
-  void FARK_LAPACKDENSESETMASS(int *ier);
+  void FARK_SPILSMASSINIT(int *time_dep, int *ier);
+  void FARK_SPILSSETMASSEPSLIN(realtype *eplifac, int *ier);
 
-  void FARK_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier);
-  void FARK_LAPACKBANDSETJAC(int *flag, int *ier);
-  void FARK_MASSLAPACKBAND(int *neq, int *mupper, int *mlower, int *ier);
-  void FARK_LAPACKBANDSETMASS(int *ier);
+  void FARK_ARKODE(realtype *tout, realtype *t, realtype *y, 
+                   int *itask, int *ier);
+  void FARK_DKY(realtype *t, int *k, realtype *dky, int *ier);
 
-  void FARK_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier);
-  void FARK_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier);
-  void FARK_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier);
-  void FARK_SPARSESETJAC(int *ier);
-  void FARK_MASSKLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier);
-  void FARK_MASSKLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier);
-  void FARK_MASSSUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier);
-  void FARK_SPARSESETMASS(int *ier);
+  void FARK_GETERRWEIGHTS(realtype *eweight, int *ier);
+  void FARK_GETRESWEIGHTS(realtype *rweight, int *ier);
+  void FARK_GETESTLOCALERR(realtype *ele, int *ier);
 
-  void FARK_SPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier);
-  void FARK_SPGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier);
-  void FARK_MASSSPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSSPGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier);
+  void FARK_FREE(void);
 
-  void FARK_SPFGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier);
-  void FARK_SPFGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier);
-  void FARK_MASSSPFGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSSPFGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier);
+  void FARK_WRITEPARAMETERS(int *ier);
 
-  void FARK_SPBCG(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_SPBCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSSPBCG(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSSPBCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
+  void FARK_DENSESETJAC(int *flag, int *ier);
+  void FARK_BANDSETJAC(int *flag, int *ier);
+  void FARK_SPARSESETJAC(int *ier);
 
-  void FARK_SPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_SPTFQMRREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSSPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSSPTFQMRREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
+  void FARK_DENSESETMASS(int *ier);
+  void FARK_BANDSETMASS(int *ier);
+  void FARK_SPARSESETMASS(int *ier);
 
-  void FARK_PCG(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_PCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSPCG(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FARK_MASSPCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
 
   void FARK_SPILSSETJAC(int *flag, int *ier);
   void FARK_SPILSSETPREC(int *flag, int *ier);
   void FARK_SPILSSETMASS(int *ier);
   void FARK_SPILSSETMASSPREC(int *flag, int *ier);
-  
-  void FARK_ARKODE(realtype *tout, realtype *t, realtype *y, int *itask, int *ier);
-
-  void FARK_DKY(realtype *t, int *k, realtype *dky, int *ier);
-
-  void FARK_GETERRWEIGHTS(realtype *eweight, int *ier);
-  void FARK_GETESTLOCALERR(realtype *ele, int *ier);
-
-  void FARK_FREE(void);
-
-  void FARK_WRITEPARAMETERS(int *ier);
 
-  void FARK_SETADAPTMETHOD(int *imethod, int *idefault, int *ipq, 
-			   realtype *params, int *ier);
+  void FARK_EWTSET(int *flag, int *ier);
+  void FARK_ADAPTSET(int *flag, int *ier);
+  void FARK_EXPSTABSET(int *flag, int *ier);
 
 
   /* Prototypes: Functions Called by the ARKODE Solver */
-  int FARKfi(realtype t, N_Vector y, N_Vector ydot, void *user_data);
   int FARKfe(realtype t, N_Vector y, N_Vector ydot, void *user_data);
+  int FARKfi(realtype t, N_Vector y, N_Vector ydot, void *user_data);
   
-  int FARKDenseJac(long int N, realtype t, 
-		   N_Vector y, N_Vector fy, 
-		   DlsMat J, void *user_data,
-		   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-  
-  int FARKDenseMass(long int N, realtype t, DlsMat M, void *user_data,
+  int FARKDenseJac(realtype t, N_Vector y, N_Vector fy, 
+		   SUNMatrix J, void *user_data,
 		   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
   
-  int FARKBandJac(long int N, long int mupper, long int mlower,
-		  realtype t, N_Vector y, N_Vector fy,
-		  DlsMat J, void *user_data,
+  int FARKBandJac(realtype t, N_Vector y, N_Vector fy,
+		  SUNMatrix J, void *user_data,
 		  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
   
-  int FARKBandMass(long int N, long int mupper, long int mlower,
-		   realtype t, DlsMat M, void *user_data,
-		   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+  int FARKSparseJac(realtype t, N_Vector y, N_Vector fy, 
+		    SUNMatrix J, void *user_data, N_Vector vtemp1, 
+		    N_Vector vtemp2, N_Vector vtemp3);
+
   
-  int FARKLapackDenseJac(long int N, realtype t, 
-			 N_Vector y, N_Vector fy, 
-			 DlsMat J, void *user_data,
-			 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+  int FARKDenseMass(realtype t, SUNMatrix M, void *user_data, 
+                    N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
   
-  int FARKLapackDenseMass(long int N, realtype t, DlsMat M, void *user_data,
-			  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-
-  int FARKLapackBandJac(long int N, long int mupper, long int mlower,
-			realtype t, N_Vector y, N_Vector fy,
-			DlsMat J, void *user_data,
-			N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+  int FARKBandMass(realtype t, SUNMatrix M, void *user_data, 
+                    N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
   
-  int FARKLapackBandMass(long int N, long int mupper, long int mlower,
-			 realtype t, DlsMat M, void *user_data,
-			 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+  int FARKSparseMass(realtype t, SUNMatrix M, void *user_data, 
+                    N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
   
-  int FARKSparseJac(realtype t, N_Vector y, N_Vector fy, 
-		    SlsMat J, void *user_data, N_Vector vtemp1, 
-		    N_Vector vtemp2, N_Vector vtemp3);
 
-  int FARKSparseMass(realtype t, SlsMat Mass, void *user_data, 
-		     N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-  
-  int FARKPSet(realtype tn, N_Vector y,N_Vector fy, booleantype jok,
-	       booleantype *jcurPtr, realtype gamma, void *user_data,
-	       N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+  int FARKPSet(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
+	       booleantype *jcurPtr, realtype gamma, void *user_data);
   
-  int FARKMassPSet(realtype tn, void *user_data, N_Vector vtemp1, 
-		   N_Vector vtemp2, N_Vector vtemp3);
+  int FARKMassPSet(realtype tn, void *user_data);
   
-  int FARKPSol(realtype tn, N_Vector y, N_Vector fy, 
-	       N_Vector r, N_Vector z,
-	       realtype gamma, realtype delta,
-	       int lr, void *user_data, N_Vector vtemp);
+  int FARKPSol(realtype tn, N_Vector y, N_Vector fy, N_Vector r, 
+               N_Vector z, realtype gamma, realtype delta, int lr, 
+	       void *user_data);
   
   int FARKMassPSol(realtype tn, N_Vector r, N_Vector z, realtype delta, 
-		   int lr, void *user_data, N_Vector vtemp);
+		   int lr, void *user_data);
   
-  int FARKJtimes(N_Vector v, N_Vector Jv, realtype t, 
-		 N_Vector y, N_Vector fy,
-		 void *user_data, N_Vector work);
+  int FARKJTSetup(realtype t, N_Vector y, N_Vector fy, void *user_data);
   
-  int FARKMtimes(N_Vector v, N_Vector Mv, realtype t, void *user_data);
+  int FARKJtimes(N_Vector v, N_Vector Jv, realtype t, N_Vector y, 
+		 N_Vector fy, void *user_data, N_Vector work);
+  
+  int FARKMTSetup(realtype t, void *user_data);
   
+  int FARKMtimes(N_Vector v, N_Vector Mv, realtype t, void *user_data);
+
   int FARKEwt(N_Vector y, N_Vector ewt, void *user_data);
 
-  int FARKAdapt(N_Vector y, realtype t, realtype h1, realtype h2, 
-		realtype h3, realtype e1, realtype e2, realtype e3, 
+  int FARKAdapt(N_Vector y, realtype t, realtype h1, realtype h2,
+		realtype h3, realtype e1, realtype e2, realtype e3,
 		int q, int p, realtype *hnew, void *user_data);
 
   int FARKExpStab(N_Vector y, realtype t, realtype *hstab, void *user_data);
 
   /* Declarations for global variables shared amongst various routines */
-  extern N_Vector F2C_ARKODE_vec;     /* defined in FNVECTOR module */
+  extern N_Vector F2C_ARKODE_vec;             /* defined in FNVECTOR module */
+  extern SUNMatrix F2C_ARKODE_matrix;         /* defined in FSUNMATRIX module */
+  extern SUNMatrix F2C_ARKODE_mass_matrix;  
+  extern SUNLinearSolver F2C_ARKODE_linsol;   /* defined in FSUNLINSOL module */
+  extern SUNLinearSolver F2C_ARKODE_mass_sol; 
 
   extern void *ARK_arkodemem;     /* defined in farkode.c */
   extern long int *ARK_iout;      /* defined in farkode.c */
@@ -2285,17 +1840,9 @@ extern "C" {
   extern int ARK_mass_ls;         /* defined in farkode.c */
 
   /* Linear solver IDs */
-  enum { ARK_LS_DENSE       = 1, 
-	 ARK_LS_BAND        = 2, 
-         ARK_LS_LAPACKDENSE = 3, 
-	 ARK_LS_LAPACKBAND  = 4,
-	 ARK_LS_KLU         = 5, 
-	 ARK_LS_SUPERLUMT   = 6, 
-	 ARK_LS_SPGMR       = 7, 
-	 ARK_LS_SPBCG       = 8, 
-	 ARK_LS_SPTFQMR     = 9, 
-	 ARK_LS_SPFGMR      = 10, 
-	 ARK_LS_PCG         = 12 };
+  enum { ARK_LS_ITERATIVE   = 0, 
+         ARK_LS_DIRECT      = 1, 
+	 ARK_LS_CUSTOM      = 2 };
 
 #ifdef __cplusplus
 }
diff --git a/src/arkode/fcmix/farkpreco.c b/src/arkode/fcmix/farkpreco.c
index 75f2c70..495f181 100644
--- a/src/arkode/fcmix/farkpreco.c
+++ b/src/arkode/fcmix/farkpreco.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,10 +15,10 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * The C function FARKPSet is to interface between the ARKSP*
- * modules and the user-supplied preconditioner setup routine 
- * FARKPSET. Note the use of the generic name FARK_PSET in the 
- * code below.
+ * The C functions FARKPSet and FARKPSol are to interface between 
+ * the ARKSPILS module and the user-supplied preconditioner 
+ * setup/solve routines FARKPSET and FARKPSOL. Note the use of 
+ * the generic names FARK_PSET and FARK_PSOL in the code below.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
@@ -38,14 +38,12 @@ extern "C" {
   extern void FARK_PSET(realtype *T, realtype *Y, realtype *FY,
 			booleantype *JOK, booleantype *JCUR,
 			realtype *GAMMA, realtype *H,
-			long int *IPAR, realtype *RPAR, 
-			realtype *W1, realtype *W2, 
-			realtype *W3, int *IER);
+			long int *IPAR, realtype *RPAR, int *IER);
   extern void FARK_PSOL(realtype *T, realtype *Y, realtype *FY,
 			realtype *R, realtype *Z, 
 			realtype *GAMMA, realtype *DELTA,
-			int *LR, long int *IPAR, realtype *RPAR,
-			realtype *WRK, int *IER);
+			int *LR, long int *IPAR, realtype *RPAR, 
+                        int *IER);
 
 #ifdef __cplusplus
 }
@@ -72,25 +70,20 @@ void FARK_SPILSSETPREC(int *flag, int *ier)
    farkode.h for further details */
 int FARKPSet(realtype t, N_Vector y, N_Vector fy, 
 	     booleantype jok, booleantype *jcurPtr, 
-	     realtype gamma, void *user_data, N_Vector vtemp1, 
-	     N_Vector vtemp2, N_Vector vtemp3)
+	     realtype gamma, void *user_data)
 {
   int ier = 0;
-  realtype *ydata, *fydata, *v1data, *v2data, *v3data;
+  realtype *ydata, *fydata;
   realtype h;
   FARKUserData ARK_userdata;
 
   ARKodeGetLastStep(ARK_arkodemem, &h);
   ydata  = N_VGetArrayPointer(y);
   fydata = N_VGetArrayPointer(fy);
-  v1data = N_VGetArrayPointer(vtemp1);
-  v2data = N_VGetArrayPointer(vtemp2);
-  v3data = N_VGetArrayPointer(vtemp3);
   ARK_userdata = (FARKUserData) user_data;
 
   FARK_PSET(&t, ydata, fydata, &jok, jcurPtr, &gamma, &h,
-	    ARK_userdata->ipar, ARK_userdata->rpar,
-	    v1data, v2data, v3data, &ier);
+	    ARK_userdata->ipar, ARK_userdata->rpar, &ier);
   return(ier);
 }
 
@@ -101,21 +94,20 @@ int FARKPSet(realtype t, N_Vector y, N_Vector fy,
    farkode.h for further details */
 int FARKPSol(realtype t, N_Vector y, N_Vector fy, N_Vector r, 
 	     N_Vector z, realtype gamma, realtype delta,
-	     int lr, void *user_data, N_Vector vtemp)
+	     int lr, void *user_data)
 {
   int ier = 0;
-  realtype *ydata, *fydata, *vtdata, *rdata, *zdata;
+  realtype *ydata, *fydata, *rdata, *zdata;
   FARKUserData ARK_userdata;
 
   ydata  = N_VGetArrayPointer(y);
   fydata = N_VGetArrayPointer(fy);
-  vtdata = N_VGetArrayPointer(vtemp);
   rdata  = N_VGetArrayPointer(r);
   zdata  = N_VGetArrayPointer(z);
   ARK_userdata = (FARKUserData) user_data;
 
   FARK_PSOL(&t, ydata, fydata, rdata, zdata, &gamma, &delta, &lr, 
-	    ARK_userdata->ipar, ARK_userdata->rpar, vtdata, &ier);
+	    ARK_userdata->ipar, ARK_userdata->rpar, &ier);
   return(ier);
 }
 
diff --git a/src/arkode/fcmix/farkroot.c b/src/arkode/fcmix/farkroot.c
index df1695d..87045eb 100644
--- a/src/arkode/fcmix/farkroot.c
+++ b/src/arkode/fcmix/farkroot.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -86,12 +86,9 @@ int FARKrootfunc(realtype t, N_Vector y,
   FARKUserData ARK_userdata;
 
   ydata = N_VGetArrayPointer(y);
-
   ARK_userdata = (FARKUserData) user_data;
-
   FARK_ROOTFN(&t, ydata, gout, ARK_userdata->ipar, 
 	      ARK_userdata->rpar, &ier);
-
   return(ier);
 }
 
diff --git a/src/arkode/fcmix/farkroot.h b/src/arkode/fcmix/farkroot.h
index 59b103c..a55ef3a 100644
--- a/src/arkode/fcmix/farkroot.h
+++ b/src/arkode/fcmix/farkroot.h
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
diff --git a/src/arkode/fcmix/farksparse.c b/src/arkode/fcmix/farksparse.c
index c56ea43..1cd724b 100644
--- a/src/arkode/fcmix/farksparse.c
+++ b/src/arkode/fcmix/farksparse.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,7 +15,7 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKKLU, for the case
+ * Fortran/C interface routines for ARKODE/ARDLS, for the case
  * of a user-supplied sparse Jacobian routine.
  *--------------------------------------------------------------*/
 
@@ -23,7 +23,8 @@
 #include <stdlib.h>
 #include "farkode.h"
 #include "arkode_impl.h"
-#include <arkode/arkode_sparse.h>
+#include <arkode/arkode_direct.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
 /*=============================================================*/
 
@@ -33,13 +34,15 @@
 extern "C" {
 #endif
 
+ 
   extern void FARK_SPJAC(realtype *T, realtype *Y, 
-			 realtype *FY, int *N, int *NNZ, 
-			 realtype *JDATA, int *JRVALS, 
-			 int *JCPTRS, realtype *H, 
-			 long int *IPAR, realtype *RPAR, 
-			 realtype *V1, realtype *V2, 
-			 realtype *V3, int *ier);
+			 realtype *FY, long int *N, 
+                         long int *NNZ, realtype *JDATA, 
+                         long int *JRVALS, long int *JCPTRS, 
+			 realtype *H,  long int *IPAR,
+                         realtype *RPAR, realtype *V1,
+                         realtype *V2, realtype *V3,
+                         int *ier);
 
 #ifdef __cplusplus
 }
@@ -47,11 +50,18 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKSlsSetSparseJacFn; see 
+/* Fortran interface to C routine ARKDlsSetJacFn; see 
    farkode.h for further information */
 void FARK_SPARSESETJAC(int *ier)
 {
-  *ier = ARKSlsSetSparseJacFn(ARK_arkodemem, FARKSparseJac);
+#if defined(SUNDIALS_INT32_T)
+  arkProcessError((ARKodeMem) ARK_arkodemem, ARK_ILL_INPUT, "ARKODE",
+                  "FARKSPARSESETJAC", 
+                  "Sparse Fortran users must configure SUNDIALS with 64-bit integers.");
+  *ier = 1;
+#else  
+  *ier = ARKDlsSetJacFn(ARK_arkodemem, FARKSparseJac);
+#endif
 }
 
 /*=============================================================*/
@@ -59,12 +69,13 @@ void FARK_SPARSESETJAC(int *ier)
 /* C interface to user-supplied Fortran routine FARKSPJAC; see 
    farkode.h for additional information  */
 int FARKSparseJac(realtype t, N_Vector y, N_Vector fy, 
-		  SlsMat J, void *user_data, N_Vector vtemp1, 
+		  SUNMatrix J, void *user_data, N_Vector vtemp1, 
 		  N_Vector vtemp2, N_Vector vtemp3)
 {
   int ier;
-  realtype *ydata, *fydata, *v1data, *v2data, *v3data;
+  realtype *ydata, *fydata, *v1data, *v2data, *v3data, *Jdata;
   realtype h;
+  long int NP, NNZ, *indexvals, *indexptrs; 
   FARKUserData ARK_userdata;
 
   ARKodeGetLastStep(ARK_arkodemem, &h);
@@ -74,10 +85,15 @@ int FARKSparseJac(realtype t, N_Vector y, N_Vector fy,
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
   ARK_userdata = (FARKUserData) user_data;
+  NP = SUNSparseMatrix_NP(J);
+  NNZ = SUNSparseMatrix_NNZ(J);
+  Jdata = SUNSparseMatrix_Data(J);
+  indexvals = SUNSparseMatrix_IndexValues(J);
+  indexptrs = SUNSparseMatrix_IndexPointers(J);
 
-  FARK_SPJAC(&t, ydata, fydata, &(J->NP), &(J->NNZ), J->data, 
-	     J->indexvals, J->indexptrs, &h, ARK_userdata->ipar, 
-	     ARK_userdata->rpar, v1data, v2data, v3data, &ier); 
+  FARK_SPJAC(&t, ydata, fydata, &NP, &NNZ, Jdata, indexvals, 
+             indexptrs, &h, ARK_userdata->ipar, ARK_userdata->rpar, 
+             v1data, v2data, v3data, &ier); 
   return(ier);
 }
 
diff --git a/src/arkode/fcmix/farksparsemass.c b/src/arkode/fcmix/farksparsemass.c
index a8913a4..4de05eb 100644
--- a/src/arkode/fcmix/farksparsemass.c
+++ b/src/arkode/fcmix/farksparsemass.c
@@ -2,7 +2,7 @@
  * Programmer(s): Daniel R. Reynolds @ SMU
  *---------------------------------------------------------------
  * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
+ * Copyright (c) 2017, Southern Methodist University and 
  * Lawrence Livermore National Security
  *
  * This work was performed under the auspices of the U.S. Department 
@@ -15,15 +15,16 @@
  * For details, see the LICENSE file.
  * LLNS/SMU Copyright End
  *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKKLU, for the case
- * of a user-supplied sparse Jacobian routine.
+ * Fortran/C interface routines for ARKODE/ARKDLS, for the case
+ * of a user-supplied mass-matrix approximation routine.
  *--------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "farkode.h"
 #include "arkode_impl.h"
-#include <arkode/arkode_sparse.h>
+#include <arkode/arkode_direct.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
 /*=============================================================*/
 
@@ -33,11 +34,12 @@
 extern "C" {
 #endif
 
-  extern void FARK_SPMASS(realtype *T, int *N, int *NNZ, 
-			  realtype *MDATA, int *MRVALS, 
-			  int *MCPTRS, long int *IPAR, 
-			  realtype *RPAR, realtype *V1, 
-			  realtype *V2, realtype *V3, int *ier);
+  extern void FARK_SPMASS(realtype *T, long int *N, 
+                          long int *NNZ, realtype *MDATA, 
+                          long int *MRVALS, long int *MCPTRS, 
+                          long int *IPAR, realtype *RPAR, 
+                          realtype *V1, realtype *V2, realtype *V3, 
+                          int *ier);
 
 #ifdef __cplusplus
 }
@@ -45,32 +47,38 @@ extern "C" {
 
 /*=============================================================*/
 
-/* Fortran interface to C routine ARKSlsSetSparseMassFn; see 
+/* Fortran interface to C routine ARKSlsSetMassFn; see 
    farkode.h for further information */
 void FARK_SPARSESETMASS(int *ier)
 {
-  *ier = ARKSlsSetSparseMassFn(ARK_arkodemem, FARKSparseMass);
+  *ier = ARKDlsSetMassFn(ARK_arkodemem, FARKSparseMass);
 }
 
 /*=============================================================*/
 
 /* C interface to user-supplied Fortran routine FARKSPMASS; see 
    farkode.h for additional information  */
-int FARKSparseMass(realtype t, SlsMat MassMat, void *user_data, 
+int FARKSparseMass(realtype t, SUNMatrix MassMat, void *user_data, 
 		   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
 {
   int ier;
-  realtype *v1data, *v2data, *v3data;
+  realtype *v1data, *v2data, *v3data, *Mdata;
   FARKUserData ARK_userdata;
+  long int NP, NNZ, *indexvals, *indexptrs;
 
   v1data = N_VGetArrayPointer(vtemp1);
   v2data = N_VGetArrayPointer(vtemp2);
   v3data = N_VGetArrayPointer(vtemp3);
+  NP = SUNSparseMatrix_NP(MassMat);
+  NNZ = SUNSparseMatrix_NNZ(MassMat);
+  Mdata = SUNSparseMatrix_Data(MassMat);
+  indexvals = SUNSparseMatrix_IndexValues(MassMat);
+  indexptrs = SUNSparseMatrix_IndexPointers(MassMat);
   ARK_userdata = (FARKUserData) user_data;
 
-  FARK_SPMASS(&t, &(MassMat->NP), &(MassMat->NNZ), MassMat->data, 
-	      MassMat->indexvals, MassMat->indexptrs, ARK_userdata->ipar, 
-	      ARK_userdata->rpar, v1data, v2data, v3data, &ier); 
+  FARK_SPMASS(&t, &NP, &NNZ, Mdata, indexvals, indexptrs, 
+              ARK_userdata->ipar, ARK_userdata->rpar, v1data, 
+              v2data, v3data, &ier); 
   return(ier);
 }
 
diff --git a/src/arkode/fcmix/farksuperlumt.c b/src/arkode/fcmix/farksuperlumt.c
deleted file mode 100644
index 80174f7..0000000
--- a/src/arkode/fcmix/farksuperlumt.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*---------------------------------------------------------------
- * Programmer(s): Daniel R. Reynolds @ SMU
- *---------------------------------------------------------------
- * LLNS/SMU Copyright Start
- * Copyright (c) 2015, Southern Methodist University and 
- * Lawrence Livermore National Security
- *
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Southern Methodist University and Lawrence Livermore 
- * National Laboratory under Contract DE-AC52-07NA27344.
- * Produced at Southern Methodist University and the Lawrence 
- * Livermore National Laboratory.
- *
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS/SMU Copyright End
- *---------------------------------------------------------------
- * Fortran/C interface routines for ARKODE/ARKSUPERLUMT
- *--------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "farkode.h"
-#include "arkode_impl.h"
-#include <arkode/arkode_superlumt.h>
-
-/*=============================================================*/
-
-/* Fortran interface to C routine ARKSuperLUMT; see farkode.h for 
-   further details */
-void FARK_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier)
-{
-  *ier = ARKSuperLUMT(ARK_arkodemem, *nthreads, *neq, *nnz);
-  ARKSuperLUMTSetOrdering(ARK_arkodemem, *ordering);
-  ARK_ls = ARK_LS_SUPERLUMT;
-  return;
-}
-
-
-/* Fortran interface to C routine ARKMassSuperLUMT; see farkode.h for 
-   further details */
-void FARK_MASSSUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier)
-{
-  *ier = ARKMassSuperLUMT(ARK_arkodemem, *nthreads, *neq, *nnz, NULL);
-  ARKMassSuperLUMTSetOrdering(ARK_arkodemem, *ordering);
-  ARK_mass_ls = ARK_LS_SUPERLUMT;
-  return;
-}
-
-/*===============================================================
-   EOF
-===============================================================*/
-
diff --git a/src/cvode/CMakeLists.txt b/src/cvode/CMakeLists.txt
index d47cccc..556b238 100644
--- a/src/cvode/CMakeLists.txt
+++ b/src/cvode/CMakeLists.txt
@@ -1,119 +1,84 @@
 # ---------------------------------------------------------------
-# $Revision: 4759 $
-# $Date: 2016-05-18 16:25:17 -0700 (Wed, 18 May 2016) $
+# Programmer(s):  Daniel R. Reynolds @ SMU
+#                 Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
-# ---------------------------------------------------------------
-# LLNS Copyright Start
-# Copyright (c) 2014, Lawrence Livermore National Security
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
 # This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
-# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
-# Produced at the Lawrence Livermore National Laboratory.
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
-# LLNS Copyright End
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the CVODE library
 
 INSTALL(CODE "MESSAGE(\"\nInstall CVODE\n\")")
 
-IF(MPI_MPICC)
-  # use MPI_MPICC as the compiler
-  SET(CMAKE_C_COMPILER ${MPI_MPICC})
-ELSE(MPI_MPICC)
-  # add MPI_INCLUDE_PATH to include directories
-  INCLUDE_DIRECTORIES(${MPI_INCLUDE_PATH})
-ENDIF(MPI_MPICC)
-
 # Add variable cvode_SOURCES with the sources for the CVODE library
 SET(cvode_SOURCES
   cvode.c
-  cvode_io.c
-  cvode_direct.c        
-  cvode_band.c
-  cvode_dense.c
-  cvode_diag.c
-  cvode_spils.c
-  cvode_spbcgs.c
-  cvode_spgmr.c
-  cvode_sptfqmr.c
-  cvode_sparse.c
   cvode_bandpre.c
   cvode_bbdpre.c
+  cvode_diag.c        
+  cvode_direct.c        
+  cvode_io.c
+  cvode_spils.c
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND cvode_SOURCES cvode_klu.c)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND cvode_SOURCES cvode_superlumt.c)
-ENDIF()
-
-# IF(HYPRE_FOUND)
-#      LIST(APPEND cvode_SOURCES cvode_hypamgpre.c)
-# ENDIF()
-
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the CVODE library
 SET(shared_SOURCES
-  sundials_nvector.c
-  sundials_math.c
-  sundials_direct.c
-  sundials_band.c
-  sundials_dense.c
-  sundials_iterative.c
-  sundials_sparse.c
-  sundials_spbcgs.c
-  sundials_spgmr.c
-  sundials_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_band.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_dense.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_direct.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_version.c
+  ${sundials_SOURCE_DIR}/src/nvec_ser/nvector_serial.c
   )
 
-# Add prefix with complete path to the common SUNDIALS sources
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the CVODE library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/sunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/sunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/sunmatrix_sparse.c
+  )
+
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the CVODE library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/sunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/sunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/sunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/sunlinsol_pcg.c
+  )
 
 # Add variable cvode_HEADERS with the exported CVODE header files
 SET(cvode_HEADERS
-  cvode_band.h
+  cvode.h
   cvode_bandpre.h
   cvode_bbdpre.h
-  cvode_dense.h
   cvode_diag.h
   cvode_direct.h
-  cvode.h
-  cvode_sparse.h
-  cvode_spbcgs.h
-  cvode_spgmr.h
   cvode_spils.h
-  cvode_sptfqmr.h
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND cvode_HEADERS cvode_klu.h)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND cvode_HEADERS cvode_superlumt.h)
-ENDIF()
-
-# IF(HYPRE_FOUND)
-#      LIST(APPEND cvode_HEADERS cvode_hypamgpre.h)
-# ENDIF()
-
 # Add prefix with complete path to the CVODE header files
 ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvode/ cvode_HEADERS)
 
-# If Blas/Lapack support was enabled, set-up additional file lists
-IF(LAPACK_FOUND)
-  SET(cvode_BL_SOURCES cvode_lapack.c)
-  SET(cvode_BL_HEADERS cvode_lapack.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvode/ cvode_BL_HEADERS)
-ELSE(LAPACK_FOUND)
-  SET(cvode_BL_SOURCES "")
-  SET(cvode_BL_HEADERS "")
-ENDIF(LAPACK_FOUND)
-
 # Add source directories to include directories for access to
 # implementation only header files.
 INCLUDE_DIRECTORIES(.)
@@ -127,7 +92,7 @@ IF(BUILD_STATIC_LIBS)
 
   # Add the build target for the static CVODE library
   ADD_LIBRARY(sundials_cvode_static STATIC 
-    ${cvode_SOURCES}  ${cvode_BL_SOURCES} ${shared_SOURCES})
+    ${cvode_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_cvode_static
@@ -143,7 +108,11 @@ IF(BUILD_SHARED_LIBS)
 
   # Add the build target for the CVODE library
   ADD_LIBRARY(sundials_cvode_shared SHARED 
-    ${cvode_SOURCES}  ${cvode_BL_SOURCES}  ${shared_SOURCES})
+    ${cvode_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_cvode_shared m)
+  ENDIF()
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_cvode_shared
@@ -159,7 +128,7 @@ IF(BUILD_SHARED_LIBS)
 ENDIF(BUILD_SHARED_LIBS)
 
 # Install the CVODE header files
-INSTALL(FILES ${cvode_HEADERS} ${cvode_BL_HEADERS} DESTINATION include/cvode)
+INSTALL(FILES ${cvode_HEADERS} DESTINATION include/cvode)
 
 # Install the CVODE implementation header file
 INSTALL(FILES cvode_impl.h DESTINATION include/cvode)
diff --git a/src/cvode/README b/src/cvode/README
index 9e23bbf..5f497f4 100644
--- a/src/cvode/README
+++ b/src/cvode/README
@@ -1,5 +1,5 @@
                               CVODE
-                    Release 2.9.0, September 2016
+                    Release 3.1.0, November 2017
                  Alan C. Hindmarsh and Radu Serban
               Center for Applied Scientific Computing, LLNL
 
@@ -74,6 +74,8 @@ C. References
 D. Releases
 -----------
 
+v. 3.1.0       - Nov. 2017
+v. 3.0.0       - Sep. 2017
 v. 2.9.0       - Sep. 2016
 v. 2.8.2       - Aug. 2015
 v. 2.8.1       - Mar. 2015
diff --git a/src/cvode/cvode.c b/src/cvode/cvode.c
index dafab72..b5cda9d 100644
--- a/src/cvode/cvode.c
+++ b/src/cvode/cvode.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4285 $
- * $Date: 2014-12-12 13:39:23 -0800 (Fri, 12 Dec 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
  *                and Dan Shumaker @ LLNL
@@ -35,13 +35,6 @@
 #include <sundials/sundials_types.h>
 
 /*=================================================================*/
-/*             Macros                                              */
-/*=================================================================*/
-
-/* Macro: loop */
-#define loop for(;;)
-
-/*=================================================================*/
 /*             CVODE Private Constants                             */
 /*=================================================================*/
 
@@ -367,7 +360,7 @@ void *CVodeCreate(int lmm, int iter)
   cv_mem->cv_f          = NULL;
   cv_mem->cv_user_data  = NULL;
   cv_mem->cv_itol       = CV_NN;
-  cv_mem->cv_user_efun  = FALSE;
+  cv_mem->cv_user_efun  = SUNFALSE;
   cv_mem->cv_efun       = NULL;
   cv_mem->cv_e_data     = NULL;
   cv_mem->cv_ehfun      = cvErrHandler;
@@ -376,16 +369,16 @@ void *CVodeCreate(int lmm, int iter)
   cv_mem->cv_qmax       = maxord;
   cv_mem->cv_mxstep     = MXSTEP_DEFAULT;
   cv_mem->cv_mxhnil     = MXHNIL_DEFAULT;
-  cv_mem->cv_sldeton    = FALSE;
+  cv_mem->cv_sldeton    = SUNFALSE;
   cv_mem->cv_hin        = ZERO;
   cv_mem->cv_hmin       = HMIN_DEFAULT;
   cv_mem->cv_hmax_inv   = HMAX_INV_DEFAULT;
-  cv_mem->cv_tstopset   = FALSE;
+  cv_mem->cv_tstopset   = SUNFALSE;
   cv_mem->cv_maxcor     = NLS_MAXCOR;
   cv_mem->cv_maxnef     = MXNEF;
   cv_mem->cv_maxncf     = MXNCF;
   cv_mem->cv_nlscoef    = CORTES;
-
+  
   /* Initialize root finding variables */
 
   cv_mem->cv_glo        = NULL;
@@ -409,8 +402,8 @@ void *CVodeCreate(int lmm, int iter)
 
   /* No mallocs have been done yet */
 
-  cv_mem->cv_VabstolMallocDone = FALSE;
-  cv_mem->cv_MallocDone        = FALSE;
+  cv_mem->cv_VabstolMallocDone = SUNFALSE;
+  cv_mem->cv_MallocDone        = SUNFALSE;
 
   /* Return pointer to CVODE memory block */
 
@@ -419,13 +412,6 @@ void *CVodeCreate(int lmm, int iter)
 
 /*-----------------------------------------------------------------*/
 
-#define iter (cv_mem->cv_iter)  
-#define lmm  (cv_mem->cv_lmm) 
-#define lrw  (cv_mem->cv_lrw)
-#define liw  (cv_mem->cv_liw)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeInit
  * 
@@ -439,7 +425,7 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
 {
   CVodeMem cv_mem;
   booleantype nvectorOK, allocOK;
-  long int lrw1, liw1;
+  sunindextype lrw1, liw1;
   int i,k;
 
   /* Check cvode_mem */
@@ -553,18 +539,13 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
 
   /* Problem has been successfully initialized */
 
-  cv_mem->cv_MallocDone = TRUE;
+  cv_mem->cv_MallocDone = SUNTRUE;
 
   return(CV_SUCCESS);
 }
 
 /*-----------------------------------------------------------------*/
 
-#define lrw1 (cv_mem->cv_lrw1)
-#define liw1 (cv_mem->cv_liw1)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeReInit
  *
@@ -592,7 +573,7 @@ int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0)
 
   /* Check if cvode_mem was allocated */
 
-  if (cv_mem->cv_MallocDone == FALSE) {
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeReInit", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
@@ -684,7 +665,7 @@ int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol)
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (cv_mem->cv_MallocDone == FALSE) {
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeSStolerances", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
@@ -708,7 +689,7 @@ int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol)
 
   cv_mem->cv_itol = CV_SS;
 
-  cv_mem->cv_user_efun = FALSE;
+  cv_mem->cv_user_efun = SUNFALSE;
   cv_mem->cv_efun = cvEwtSet;
   cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
 
@@ -726,7 +707,7 @@ int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (cv_mem->cv_MallocDone == FALSE) {
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeSVtolerances", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
@@ -747,9 +728,9 @@ int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
   
   if ( !(cv_mem->cv_VabstolMallocDone) ) {
     cv_mem->cv_Vabstol = N_VClone(cv_mem->cv_ewt);
-    lrw += lrw1;
-    liw += liw1;
-    cv_mem->cv_VabstolMallocDone = TRUE;
+    cv_mem->cv_lrw += cv_mem->cv_lrw1;
+    cv_mem->cv_liw += cv_mem->cv_liw1;
+    cv_mem->cv_VabstolMallocDone = SUNTRUE;
   }
 
   cv_mem->cv_reltol = reltol;
@@ -757,7 +738,7 @@ int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
 
   cv_mem->cv_itol = CV_SV;
 
-  cv_mem->cv_user_efun = FALSE;
+  cv_mem->cv_user_efun = SUNFALSE;
   cv_mem->cv_efun = cvEwtSet;
   cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
 
@@ -775,14 +756,14 @@ int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun)
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (cv_mem->cv_MallocDone == FALSE) {
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVodeWFtolerances", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
 
   cv_mem->cv_itol = CV_WF;
 
-  cv_mem->cv_user_efun = TRUE;
+  cv_mem->cv_user_efun = SUNTRUE;
   cv_mem->cv_efun = efun;
   cv_mem->cv_e_data = NULL; /* will be set to user_data in InitialSetup */
 
@@ -791,16 +772,6 @@ int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun)
 
 /*-----------------------------------------------------------------*/
 
-#define gfun    (cv_mem->cv_gfun)
-#define glo     (cv_mem->cv_glo)
-#define ghi     (cv_mem->cv_ghi)
-#define grout   (cv_mem->cv_grout)
-#define iroots  (cv_mem->cv_iroots)
-#define rootdir (cv_mem->cv_rootdir)
-#define gactive (cv_mem->cv_gactive)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeRootInit
  *
@@ -829,22 +800,22 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
      functions (changing number of gfun components), then free
      currently held memory resources */
   if ((nrt != cv_mem->cv_nrtfn) && (cv_mem->cv_nrtfn > 0)) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
-    free(gactive); gactive = NULL;
-
-    lrw -= 3 * (cv_mem->cv_nrtfn);
-    liw -= 3 * (cv_mem->cv_nrtfn);
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+    free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
+    free(cv_mem->cv_gactive); cv_mem->cv_gactive = NULL;
+
+    cv_mem->cv_lrw -= 3 * (cv_mem->cv_nrtfn);
+    cv_mem->cv_liw -= 3 * (cv_mem->cv_nrtfn);
   }
 
   /* If CVodeRootInit() was called with nrtfn == 0, then set cv_nrtfn to
      zero and cv_gfun to NULL before returning */
   if (nrt == 0) {
     cv_mem->cv_nrtfn = nrt;
-    gfun = NULL;
+    cv_mem->cv_gfun = NULL;
     return(CV_SUCCESS);
   }
 
@@ -854,23 +825,23 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
   /* If g != NULL then return as currently reserved memory resources
      will suffice */
   if (nrt == cv_mem->cv_nrtfn) {
-    if (g != gfun) {
+    if (g != cv_mem->cv_gfun) {
       if (g == NULL) {
-        free(glo); glo = NULL;
-        free(ghi); ghi = NULL;
-        free(grout); grout = NULL;
-        free(iroots); iroots = NULL;
-        free(rootdir); rootdir = NULL;
-        free(gactive); gactive = NULL;
+        free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+        free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+        free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+        free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+        free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
+        free(cv_mem->cv_gactive); cv_mem->cv_gactive = NULL;
 
-        lrw -= 3*nrt;
-        liw -= 3*nrt;
+        cv_mem->cv_lrw -= 3*nrt;
+        cv_mem->cv_liw -= 3*nrt;
 
         cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeRootInit", MSGCV_NULL_G);
         return(CV_ILL_INPUT);
       }
       else {
-        gfun = g;
+        cv_mem->cv_gfun = g;
         return(CV_SUCCESS);
       }
     }
@@ -883,174 +854,78 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVodeRootInit", MSGCV_NULL_G);
     return(CV_ILL_INPUT);
   }
-  else gfun = g;
+  else cv_mem->cv_gfun = g;
 
   /* Allocate necessary memory and return */
-  glo = NULL;
-  glo = (realtype *) malloc(nrt*sizeof(realtype));
-  if (glo == NULL) {
+  cv_mem->cv_glo = NULL;
+  cv_mem->cv_glo = (realtype *) malloc(nrt*sizeof(realtype));
+  if (cv_mem->cv_glo == NULL) {
     cvProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
-  ghi = NULL;
-  ghi = (realtype *) malloc(nrt*sizeof(realtype));
-  if (ghi == NULL) {
-    free(glo); glo = NULL;
+  cv_mem->cv_ghi = NULL;
+  cv_mem->cv_ghi = (realtype *) malloc(nrt*sizeof(realtype));
+  if (cv_mem->cv_ghi == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
     cvProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
-  grout = NULL;
-  grout = (realtype *) malloc(nrt*sizeof(realtype));
-  if (grout == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
+  cv_mem->cv_grout = NULL;
+  cv_mem->cv_grout = (realtype *) malloc(nrt*sizeof(realtype));
+  if (cv_mem->cv_grout == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
     cvProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
-  iroots = NULL;
-  iroots = (int *) malloc(nrt*sizeof(int));
-  if (iroots == NULL) {
-    free(glo); glo = NULL; 
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
+  cv_mem->cv_iroots = NULL;
+  cv_mem->cv_iroots = (int *) malloc(nrt*sizeof(int));
+  if (cv_mem->cv_iroots == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL; 
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
     cvProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
-  rootdir = NULL;
-  rootdir = (int *) malloc(nrt*sizeof(int));
-  if (rootdir == NULL) {
-    free(glo); glo = NULL; 
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
+  cv_mem->cv_rootdir = NULL;
+  cv_mem->cv_rootdir = (int *) malloc(nrt*sizeof(int));
+  if (cv_mem->cv_rootdir == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL; 
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
     cvProcessError(cv_mem, CV_MEM_FAIL, "CVODE", "CVodeRootInit", MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
-  gactive = NULL;
-  gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
-  if (gactive == NULL) {
-    free(glo); glo = NULL; 
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
+  cv_mem->cv_gactive = NULL;
+  cv_mem->cv_gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
+  if (cv_mem->cv_gactive == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL; 
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+    free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
     cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
   /* Set default values for rootdir (both directions) */
-  for(i=0; i<nrt; i++) rootdir[i] = 0;
+  for(i=0; i<nrt; i++) cv_mem->cv_rootdir[i] = 0;
 
   /* Set default values for gactive (all active) */
-  for(i=0; i<nrt; i++) gactive[i] = TRUE;
+  for(i=0; i<nrt; i++) cv_mem->cv_gactive[i] = SUNTRUE;
 
-  lrw += 3*nrt;
-  liw += 3*nrt;
+  cv_mem->cv_lrw += 3*nrt;
+  cv_mem->cv_liw += 3*nrt;
 
   return(CV_SUCCESS);
 }
 
-/* 
- * =================================================================
- * Readibility Constants
- * =================================================================
- */
-
-#define f              (cv_mem->cv_f)      
-#define user_data      (cv_mem->cv_user_data) 
-#define efun           (cv_mem->cv_efun)
-#define e_data         (cv_mem->cv_e_data) 
-#define qmax           (cv_mem->cv_qmax)
-#define mxstep         (cv_mem->cv_mxstep)
-#define mxhnil         (cv_mem->cv_mxhnil)
-#define sldeton        (cv_mem->cv_sldeton)
-#define hin            (cv_mem->cv_hin)
-#define hmin           (cv_mem->cv_hmin)
-#define hmax_inv       (cv_mem->cv_hmax_inv)
-#define tstop          (cv_mem->cv_tstop)
-#define tstopset       (cv_mem->cv_tstopset)
-#define maxnef         (cv_mem->cv_maxnef)
-#define maxncf         (cv_mem->cv_maxncf)
-#define maxcor         (cv_mem->cv_maxcor)
-#define nlscoef        (cv_mem->cv_nlscoef)
-#define itol           (cv_mem->cv_itol)         
-#define reltol         (cv_mem->cv_reltol)       
-#define Sabstol        (cv_mem->cv_Sabstol)
-#define Vabstol        (cv_mem->cv_Vabstol)
-
-#define uround         (cv_mem->cv_uround)  
-#define zn             (cv_mem->cv_zn) 
-#define ewt            (cv_mem->cv_ewt)  
-#define y              (cv_mem->cv_y)
-#define acor           (cv_mem->cv_acor)
-#define tempv          (cv_mem->cv_tempv)
-#define ftemp          (cv_mem->cv_ftemp) 
-#define q              (cv_mem->cv_q)
-#define qprime         (cv_mem->cv_qprime)
-#define next_q         (cv_mem->cv_next_q)
-#define qwait          (cv_mem->cv_qwait)
-#define L              (cv_mem->cv_L)
-#define h              (cv_mem->cv_h)
-#define hprime         (cv_mem->cv_hprime)
-#define next_h         (cv_mem->cv_next_h)
-#define eta            (cv_mem->cv_eta) 
-#define etaqm1         (cv_mem->cv_etaqm1) 
-#define etaq           (cv_mem->cv_etaq) 
-#define etaqp1         (cv_mem->cv_etaqp1) 
-#define nscon          (cv_mem->cv_nscon)
-#define hscale         (cv_mem->cv_hscale)
-#define tn             (cv_mem->cv_tn)
-#define tau            (cv_mem->cv_tau)
-#define tq             (cv_mem->cv_tq)
-#define l              (cv_mem->cv_l)
-#define rl1            (cv_mem->cv_rl1)
-#define gamma          (cv_mem->cv_gamma) 
-#define gammap         (cv_mem->cv_gammap) 
-#define gamrat         (cv_mem->cv_gamrat)
-#define crate          (cv_mem->cv_crate)
-#define acnrm          (cv_mem->cv_acnrm)
-#define mnewt          (cv_mem->cv_mnewt)
-#define etamax         (cv_mem->cv_etamax)
-#define nst            (cv_mem->cv_nst)
-#define nfe            (cv_mem->cv_nfe)
-#define ncfn           (cv_mem->cv_ncfn)
-#define netf           (cv_mem->cv_netf)
-#define nni            (cv_mem->cv_nni)
-#define nsetups        (cv_mem->cv_nsetups)
-#define nhnil          (cv_mem->cv_nhnil)
-#define linit          (cv_mem->cv_linit)
-#define lsetup         (cv_mem->cv_lsetup)
-#define lsolve         (cv_mem->cv_lsolve) 
-#define lfree          (cv_mem->cv_lfree) 
-#define lmem           (cv_mem->cv_lmem) 
-#define qu             (cv_mem->cv_qu)          
-#define nstlp          (cv_mem->cv_nstlp)  
-#define h0u            (cv_mem->cv_h0u)
-#define hu             (cv_mem->cv_hu)         
-#define saved_tq5      (cv_mem->cv_saved_tq5)  
-#define indx_acor      (cv_mem->cv_indx_acor)
-#define jcur           (cv_mem->cv_jcur)         
-#define tolsf          (cv_mem->cv_tolsf)      
-#define setupNonNull   (cv_mem->cv_setupNonNull) 
-#define nor            (cv_mem->cv_nor)
-#define ssdat          (cv_mem->cv_ssdat)
-
-#define nrtfn          (cv_mem->cv_nrtfn)
-#define tlo            (cv_mem->cv_tlo)
-#define thi            (cv_mem->cv_thi)
-#define tretlast       (cv_mem->cv_tretlast)
-#define toutc          (cv_mem->cv_toutc)
-#define trout          (cv_mem->cv_trout)
-#define ttol           (cv_mem->cv_ttol)
-#define taskc          (cv_mem->cv_taskc)
-#define irfnd          (cv_mem->cv_irfnd)
-#define nge            (cv_mem->cv_nge)
-
 
 /*-----------------------------------------------------------------*/
 
@@ -1095,13 +970,13 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Check if cvode_mem was allocated */
-  if (cv_mem->cv_MallocDone == FALSE) {
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_MALLOC, "CVODE", "CVode", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
   
   /* Check for yout != NULL */
-  if ((y = yout) == NULL) {
+  if ((cv_mem->cv_y = yout) == NULL) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_YOUT_NULL);
     return(CV_ILL_INPUT);
   }
@@ -1118,8 +993,8 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     return(CV_ILL_INPUT);
   }
 
-  if (itask == CV_NORMAL) toutc = tout;
-  taskc = itask;
+  if (itask == CV_NORMAL) cv_mem->cv_toutc = tout;
+  cv_mem->cv_taskc = itask;
 
   /*
    * ----------------------------------------
@@ -1133,9 +1008,9 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
    * ----------------------------------------
    */
 
-  if (nst == 0) {
+  if (cv_mem->cv_nst == 0) {
 
-    tretlast = *tret = tn;
+    cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
 
     ier = cvInitialSetup(cv_mem);
     if (ier!= CV_SUCCESS) return(ier);
@@ -1144,69 +1019,76 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
        set initial h (from H0 or cvHin), and scale zn[1] by h.
        Also check for zeros of root function g at and near t0.    */
     
-    retval = f(tn, zn[0], zn[1], user_data); 
-    nfe++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                          cv_mem->cv_zn[1], cv_mem->cv_user_data); 
+    cv_mem->cv_nfe++;
     if (retval < 0) {
-      cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+      cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode",
+                     MSGCV_RHSFUNC_FAILED, cv_mem->cv_tn);
       return(CV_RHSFUNC_FAIL);
     }
     if (retval > 0) {
-      cvProcessError(cv_mem, CV_FIRST_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_FIRST);
+      cvProcessError(cv_mem, CV_FIRST_RHSFUNC_ERR, "CVODE", "CVode",
+                     MSGCV_RHSFUNC_FIRST);
       return(CV_FIRST_RHSFUNC_ERR);
     }
 
     /* Test input tstop for legality. */
 
-    if (tstopset) {
-      if ( (tstop - tn)*(tout - tn) <= ZERO ) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+    if (cv_mem->cv_tstopset) {
+      if ( (cv_mem->cv_tstop - cv_mem->cv_tn)*(tout - cv_mem->cv_tn) <= ZERO ) {
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode",
+                       MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn);
         return(CV_ILL_INPUT);
       }
      }
 
     /* Set initial h (from H0 or cvHin). */
 
-    h = hin;
-    if ( (h != ZERO) && ((tout-tn)*h < ZERO) ) {
+    cv_mem->cv_h = cv_mem->cv_hin;
+    if ( (cv_mem->cv_h != ZERO) && ((tout-cv_mem->cv_tn)*cv_mem->cv_h < ZERO) ) {
       cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_H0);
       return(CV_ILL_INPUT);
     }
-    if (h == ZERO) {
+    if (cv_mem->cv_h == ZERO) {
       tout_hin = tout;
-      if ( tstopset && (tout-tn)*(tout-tstop) > ZERO ) tout_hin = tstop; 
+      if ( cv_mem->cv_tstopset && (tout-cv_mem->cv_tn)*(tout-cv_mem->cv_tstop) > ZERO )
+        tout_hin = cv_mem->cv_tstop; 
       hflag = cvHin(cv_mem, tout_hin);
       if (hflag != CV_SUCCESS) {
         istate = cvHandleFailure(cv_mem, hflag);
         return(istate);
       }
     }
-    rh = SUNRabs(h)*hmax_inv;
-    if (rh > ONE) h /= rh;
-    if (SUNRabs(h) < hmin) h *= hmin/SUNRabs(h);
+    rh = SUNRabs(cv_mem->cv_h)*cv_mem->cv_hmax_inv;
+    if (rh > ONE) cv_mem->cv_h /= rh;
+    if (SUNRabs(cv_mem->cv_h) < cv_mem->cv_hmin)
+      cv_mem->cv_h *= cv_mem->cv_hmin/SUNRabs(cv_mem->cv_h);
 
     /* Check for approach to tstop */
 
-    if (tstopset) {
-      if ( (tn + h - tstop)*h > ZERO ) 
-        h = (tstop - tn)*(ONE-FOUR*uround);
+    if (cv_mem->cv_tstopset) {
+      if ( (cv_mem->cv_tn + cv_mem->cv_h - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) 
+        cv_mem->cv_h = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround);
     }
 
     /* Scale zn[1] by h.*/
 
-    hscale = h; 
-    h0u    = h;
-    hprime = h;
+    cv_mem->cv_hscale = cv_mem->cv_h; 
+    cv_mem->cv_h0u    = cv_mem->cv_h;
+    cv_mem->cv_hprime = cv_mem->cv_h;
 
-    N_VScale(h, zn[1], zn[1]);
+    N_VScale(cv_mem->cv_h, cv_mem->cv_zn[1], cv_mem->cv_zn[1]);
 
     /* Check for zeros of root function g at and near t0. */
 
-    if (nrtfn > 0) {
+    if (cv_mem->cv_nrtfn > 0) {
 
       retval = cvRcheck1(cv_mem);
 
       if (retval == CV_RTFUNC_FAIL) {
-        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck1", MSGCV_RTFUNC_FAILED, tn);
+        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck1",
+                       MSGCV_RTFUNC_FAILED, cv_mem->cv_tn);
         return(CV_RTFUNC_FAIL);
       }
 
@@ -1226,52 +1108,55 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
    * -------------------------------------------------------
    */
 
-  if (nst > 0) {
+  if (cv_mem->cv_nst > 0) {
 
     /* Estimate an infinitesimal time interval to be used as
        a roundoff for time quantities (based on current time 
        and step size) */
-    troundoff = FUZZ_FACTOR*uround*(SUNRabs(tn) + SUNRabs(h));
+    troundoff = FUZZ_FACTOR*cv_mem->cv_uround*(SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h));
 
     /* First, check for a root in the last step taken, other than the
        last root found, if any.  If itask = CV_ONE_STEP and y(tn) was not
        returned because of an intervening root, return y(tn) now.     */
-    if (nrtfn > 0) {
+    if (cv_mem->cv_nrtfn > 0) {
 
-      irfndp = irfnd;
+      irfndp = cv_mem->cv_irfnd;
       
       retval = cvRcheck2(cv_mem);
 
       if (retval == CLOSERT) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "cvRcheck2", MSGCV_CLOSE_ROOTS, tlo);
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "cvRcheck2",
+                       MSGCV_CLOSE_ROOTS, cv_mem->cv_tlo);
         return(CV_ILL_INPUT);
       } else if (retval == CV_RTFUNC_FAIL) {
-        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck2", MSGCV_RTFUNC_FAILED, tlo);
+        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck2",
+                       MSGCV_RTFUNC_FAILED, cv_mem->cv_tlo);
         return(CV_RTFUNC_FAIL);
       } else if (retval == RTFOUND) {
-        tretlast = *tret = tlo;
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tlo;
         return(CV_ROOT_RETURN);
       }
 
       /* If tn is distinct from tretlast (within roundoff),
          check remaining interval for roots */
-      if ( SUNRabs(tn - tretlast) > troundoff ) {
+      if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tretlast) > troundoff ) {
 
         retval = cvRcheck3(cv_mem);
 
         if (retval == CV_SUCCESS) {     /* no root found */
-          irfnd = 0;
+          cv_mem->cv_irfnd = 0;
           if ((irfndp == 1) && (itask == CV_ONE_STEP)) {
-            tretlast = *tret = tn;
-            N_VScale(ONE, zn[0], yout);
+            cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+            N_VScale(ONE, cv_mem->cv_zn[0], yout);
             return(CV_SUCCESS);
           }
         } else if (retval == RTFOUND) {  /* a new root was found */
-          irfnd = 1;
-          tretlast = *tret = tlo;
+          cv_mem->cv_irfnd = 1;
+          cv_mem->cv_tretlast = *tret = cv_mem->cv_tlo;
           return(CV_ROOT_RETURN);
         } else if (retval == CV_RTFUNC_FAIL) {  /* g failed */
-          cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck3", MSGCV_RTFUNC_FAILED, tlo);
+          cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck3",
+                         MSGCV_RTFUNC_FAILED, cv_mem->cv_tlo);
           return(CV_RTFUNC_FAIL);
         }
 
@@ -1280,41 +1165,44 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     } /* end of root stop check */
 
     /* In CV_NORMAL mode, test if tout was reached */
-    if ( (itask == CV_NORMAL) && ((tn-tout)*h >= ZERO) ) {
-      tretlast = *tret = tout;
+    if ( (itask == CV_NORMAL) && ((cv_mem->cv_tn-tout)*cv_mem->cv_h >= ZERO) ) {
+      cv_mem->cv_tretlast = *tret = tout;
       ier =  CVodeGetDky(cv_mem, tout, 0, yout);
       if (ier != CV_SUCCESS) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TOUT, tout);
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode",
+                       MSGCV_BAD_TOUT, tout);
         return(CV_ILL_INPUT);
       }
       return(CV_SUCCESS);
     }
 
     /* In CV_ONE_STEP mode, test if tn was returned */
-    if ( itask == CV_ONE_STEP && SUNRabs(tn - tretlast) > troundoff ) {
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
+    if ( itask == CV_ONE_STEP &&
+         SUNRabs(cv_mem->cv_tn - cv_mem->cv_tretlast) > troundoff ) {
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
       return(CV_SUCCESS);
     }
 
     /* Test for tn at tstop or near tstop */
-    if ( tstopset ) {
+    if ( cv_mem->cv_tstopset ) {
 
-      if ( SUNRabs(tn - tstop) <= troundoff) {
-        ier =  CVodeGetDky(cv_mem, tstop, 0, yout);
+      if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff) {
+        ier =  CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout);
         if (ier != CV_SUCCESS) {
-          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode",
+                         MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn);
           return(CV_ILL_INPUT);
         }
-        tretlast = *tret = tstop;
-        tstopset = FALSE;
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop;
+        cv_mem->cv_tstopset = SUNFALSE;
         return(CV_TSTOP_RETURN);
       }
       
       /* If next step would overtake tstop, adjust stepsize */
-      if ( (tn + hprime - tstop)*h > ZERO ) {
-        hprime = (tstop - tn)*(ONE-FOUR*uround);
-        eta = hprime/h;
+      if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) {
+        cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround);
+        cv_mem->cv_eta = cv_mem->cv_hprime/cv_mem->cv_h;
       }
 
     }
@@ -1338,60 +1226,65 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
    */
 
   nstloc = 0;
-  loop {
+  for(;;) {
    
-    next_h = h;
-    next_q = q;
+    cv_mem->cv_next_h = cv_mem->cv_h;
+    cv_mem->cv_next_q = cv_mem->cv_q;
     
     /* Reset and check ewt */
-    if (nst > 0) {
+    if (cv_mem->cv_nst > 0) {
 
-      ewtsetOK = efun(zn[0], ewt, e_data);
+      ewtsetOK = cv_mem->cv_efun(cv_mem->cv_zn[0], cv_mem->cv_ewt, cv_mem->cv_e_data);
 
       if (ewtsetOK != 0) {
 
-        if (itol == CV_WF) 
-          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_EWT_NOW_FAIL, tn);
+        if (cv_mem->cv_itol == CV_WF) 
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode",
+                         MSGCV_EWT_NOW_FAIL, cv_mem->cv_tn);
         else 
-          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", MSGCV_EWT_NOW_BAD, tn);
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode",
+                         MSGCV_EWT_NOW_BAD, cv_mem->cv_tn);
 	
         istate = CV_ILL_INPUT;
-        tretlast = *tret = tn;
-        N_VScale(ONE, zn[0], yout);
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+        N_VScale(ONE, cv_mem->cv_zn[0], yout);
         break;
 
       }
     }
     
     /* Check for too many steps */
-    if ( (mxstep>0) && (nstloc >= mxstep) ) {
-      cvProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODE", "CVode", MSGCV_MAX_STEPS, tn);
+    if ( (cv_mem->cv_mxstep>0) && (nstloc >= cv_mem->cv_mxstep) ) {
+      cvProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODE", "CVode",
+                     MSGCV_MAX_STEPS, cv_mem->cv_tn);
       istate = CV_TOO_MUCH_WORK;
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
       break;
     }
 
     /* Check for too much accuracy requested */
-    nrm = N_VWrmsNorm(zn[0], ewt);
-    tolsf = uround * nrm;
-    if (tolsf > ONE) {
-      cvProcessError(cv_mem, CV_TOO_MUCH_ACC, "CVODE", "CVode", MSGCV_TOO_MUCH_ACC, tn);
+    nrm = N_VWrmsNorm(cv_mem->cv_zn[0], cv_mem->cv_ewt);
+    cv_mem->cv_tolsf = cv_mem->cv_uround * nrm;
+    if (cv_mem->cv_tolsf > ONE) {
+      cvProcessError(cv_mem, CV_TOO_MUCH_ACC, "CVODE", "CVode",
+                     MSGCV_TOO_MUCH_ACC, cv_mem->cv_tn);
       istate = CV_TOO_MUCH_ACC;
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
-      tolsf *= TWO;
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
+      cv_mem->cv_tolsf *= TWO;
       break;
     } else {
-      tolsf = ONE;
+      cv_mem->cv_tolsf = ONE;
     }
 
     /* Check for h below roundoff level in tn */
-    if (tn + h == tn) {
-      nhnil++;
-      if (nhnil <= mxhnil) 
-        cvProcessError(cv_mem, CV_WARNING, "CVODE", "CVode", MSGCV_HNIL, tn, h);
-      if (nhnil == mxhnil) 
+    if (cv_mem->cv_tn + cv_mem->cv_h == cv_mem->cv_tn) {
+      cv_mem->cv_nhnil++;
+      if (cv_mem->cv_nhnil <= cv_mem->cv_mxhnil) 
+        cvProcessError(cv_mem, CV_WARNING, "CVODE", "CVode",
+                       MSGCV_HNIL, cv_mem->cv_tn, cv_mem->cv_h);
+      if (cv_mem->cv_nhnil == cv_mem->cv_mxhnil) 
         cvProcessError(cv_mem, CV_WARNING, "CVODE", "CVode", MSGCV_HNIL_DONE);
     }
 
@@ -1401,25 +1294,26 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     /* Process failed step cases, and exit loop */
     if (kflag != CV_SUCCESS) {
       istate = cvHandleFailure(cv_mem, kflag);
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
       break;
     }
     
     nstloc++;
 
     /* Check for root in last step taken. */
-    if (nrtfn > 0) {
+    if (cv_mem->cv_nrtfn > 0) {
 
       retval = cvRcheck3(cv_mem);
 
       if (retval == RTFOUND) {  /* A new root was found */
-        irfnd = 1;
+        cv_mem->cv_irfnd = 1;
         istate = CV_ROOT_RETURN;
-        tretlast = *tret = tlo;
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tlo;
         break;
       } else if (retval == CV_RTFUNC_FAIL) { /* g failed */
-        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck3", MSGCV_RTFUNC_FAILED, tlo);
+        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "cvRcheck3",
+                       MSGCV_RTFUNC_FAILED, cv_mem->cv_tlo);
         istate = CV_RTFUNC_FAIL;
         break;
       }
@@ -1429,46 +1323,47 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
        * as this may indicate a user error in the implementation
        * of the root function. */
 
-      if (nst==1) {
-        inactive_roots = FALSE;
-        for (ir=0; ir<nrtfn; ir++) { 
-          if (!gactive[ir]) {
-            inactive_roots = TRUE;
+      if (cv_mem->cv_nst==1) {
+        inactive_roots = SUNFALSE;
+        for (ir=0; ir<cv_mem->cv_nrtfn; ir++) { 
+          if (!cv_mem->cv_gactive[ir]) {
+            inactive_roots = SUNTRUE;
             break;
           }
         }
         if ((cv_mem->cv_mxgnull > 0) && inactive_roots) {
-          cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_INACTIVE_ROOTS);
+          cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode",
+                         MSGCV_INACTIVE_ROOTS);
         }
       }
 
     }
 
     /* In NORMAL mode, check if tout reached */
-    if ( (itask == CV_NORMAL) &&  (tn-tout)*h >= ZERO ) {
+    if ( (itask == CV_NORMAL) &&  (cv_mem->cv_tn-tout)*cv_mem->cv_h >= ZERO ) {
       istate = CV_SUCCESS;
-      tretlast = *tret = tout;
+      cv_mem->cv_tretlast = *tret = tout;
       (void) CVodeGetDky(cv_mem, tout, 0, yout);
-      next_q = qprime;
-      next_h = hprime;
+      cv_mem->cv_next_q = cv_mem->cv_qprime;
+      cv_mem->cv_next_h = cv_mem->cv_hprime;
       break;
     }
 
     /* Check if tn is at tstop or near tstop */
-    if ( tstopset ) {
+    if ( cv_mem->cv_tstopset ) {
 
-      troundoff = FUZZ_FACTOR*uround*(SUNRabs(tn) + SUNRabs(h));
-      if ( SUNRabs(tn - tstop) <= troundoff) {
-        (void) CVodeGetDky(cv_mem, tstop, 0, yout);
-        tretlast = *tret = tstop;
-        tstopset = FALSE;
+      troundoff = FUZZ_FACTOR*cv_mem->cv_uround*(SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h));
+      if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff) {
+        (void) CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout);
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop;
+        cv_mem->cv_tstopset = SUNFALSE;
         istate = CV_TSTOP_RETURN;
         break;
       }
 
-      if ( (tn + hprime - tstop)*h > ZERO ) {
-        hprime = (tstop - tn)*(ONE-FOUR*uround);
-        eta = hprime/h;
+      if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) {
+        cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround);
+        cv_mem->cv_eta = cv_mem->cv_hprime/cv_mem->cv_h;
       }
 
     }
@@ -1476,10 +1371,10 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     /* In ONE_STEP mode, copy y and exit loop */
     if (itask == CV_ONE_STEP) {
       istate = CV_SUCCESS;
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
-      next_q = qprime;
-      next_h = hprime;
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
+      cv_mem->cv_next_q = cv_mem->cv_qprime;
+      cv_mem->cv_next_h = cv_mem->cv_hprime;
       break;
     }
 
@@ -1526,35 +1421,36 @@ int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky)
     return(CV_BAD_DKY);
   }
 
-  if ((k < 0) || (k > q)) {
+  if ((k < 0) || (k > cv_mem->cv_q)) {
     cvProcessError(cv_mem, CV_BAD_K, "CVODE", "CVodeGetDky", MSGCV_BAD_K);
     return(CV_BAD_K);
   }
   
   /* Allow for some slack */
-  tfuzz = FUZZ_FACTOR * uround * (SUNRabs(tn) + SUNRabs(hu));
-  if (hu < ZERO) tfuzz = -tfuzz;
-  tp = tn - hu - tfuzz;
-  tn1 = tn + tfuzz;
+  tfuzz = FUZZ_FACTOR * cv_mem->cv_uround * (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_hu));
+  if (cv_mem->cv_hu < ZERO) tfuzz = -tfuzz;
+  tp = cv_mem->cv_tn - cv_mem->cv_hu - tfuzz;
+  tn1 = cv_mem->cv_tn + tfuzz;
   if ((t-tp)*(t-tn1) > ZERO) {
-    cvProcessError(cv_mem, CV_BAD_T, "CVODE", "CVodeGetDky", MSGCV_BAD_T, t, tn-hu, tn);
+    cvProcessError(cv_mem, CV_BAD_T, "CVODE", "CVodeGetDky", MSGCV_BAD_T,
+                   t, cv_mem->cv_tn-cv_mem->cv_hu, cv_mem->cv_tn);
     return(CV_BAD_T);
   }
 
   /* Sum the differentiated interpolating polynomial */
 
-  s = (t - tn) / h;
-  for (j=q; j >= k; j--) {
+  s = (t - cv_mem->cv_tn) / cv_mem->cv_h;
+  for (j=cv_mem->cv_q; j >= k; j--) {
     c = ONE;
     for (i=j; i >= j-k+1; i--) c *= i;
-    if (j == q) {
-      N_VScale(c, zn[q], dky);
+    if (j == cv_mem->cv_q) {
+      N_VScale(c, cv_mem->cv_zn[cv_mem->cv_q], dky);
     } else {
-      N_VLinearSum(c, zn[j], s, dky, dky);
+      N_VLinearSum(c, cv_mem->cv_zn[j], s, dky, dky);
     }
   }
   if (k == 0) return(CV_SUCCESS);
-  r = SUNRpowerI(h,-k);
+  r = SUNRpowerI(cv_mem->cv_h,-k);
   N_VScale(r, dky, dky);
   return(CV_SUCCESS);
 }
@@ -1578,15 +1474,15 @@ void CVodeFree(void **cvode_mem)
   
   cvFreeVectors(cv_mem);
 
-  if (iter == CV_NEWTON && lfree != NULL) lfree(cv_mem);
+  if (cv_mem->cv_lfree != NULL) cv_mem->cv_lfree(cv_mem);
 
-  if (nrtfn > 0) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
-    free(gactive); gactive = NULL;
+  if (cv_mem->cv_nrtfn > 0) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+    free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
+    free(cv_mem->cv_gactive); cv_mem->cv_gactive = NULL;
   }
 
   free(*cvode_mem);
@@ -1602,7 +1498,7 @@ void CVodeFree(void **cvode_mem)
 /*
  * cvCheckNvector
  * This routine checks if all required vector operations are present.
- * If any of them is missing it returns FALSE.
+ * If any of them is missing it returns SUNFALSE.
  */
 
 static booleantype cvCheckNvector(N_Vector tmpl)
@@ -1620,9 +1516,9 @@ static booleantype cvCheckNvector(N_Vector tmpl)
      (tmpl->ops->nvmaxnorm   == NULL) ||
      (tmpl->ops->nvwrmsnorm  == NULL) ||
      (tmpl->ops->nvmin       == NULL))
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 /*
@@ -1630,8 +1526,8 @@ static booleantype cvCheckNvector(N_Vector tmpl)
  *
  * This routine allocates the CVODE vectors ewt, acor, tempv, ftemp, and
  * zn[0], ..., zn[maxord].
- * If all memory allocations are successful, cvAllocVectors returns TRUE. 
- * Otherwise all allocated memory is freed and cvAllocVectors returns FALSE.
+ * If all memory allocations are successful, cvAllocVectors returns SUNTRUE. 
+ * Otherwise all allocated memory is freed and cvAllocVectors returns SUNFALSE.
  * This routine also sets the optional outputs lrw and liw, which are
  * (respectively) the lengths of the real and integer work spaces
  * allocated here.
@@ -1643,52 +1539,52 @@ static booleantype cvAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
 
   /* Allocate ewt, acor, tempv, ftemp */
   
-  ewt = N_VClone(tmpl);
-  if (ewt == NULL) return(FALSE);
+  cv_mem->cv_ewt = N_VClone(tmpl);
+  if (cv_mem->cv_ewt == NULL) return(SUNFALSE);
 
-  acor = N_VClone(tmpl);
-  if (acor == NULL) {
-    N_VDestroy(ewt);
-    return(FALSE);
+  cv_mem->cv_acor = N_VClone(tmpl);
+  if (cv_mem->cv_acor == NULL) {
+    N_VDestroy(cv_mem->cv_ewt);
+    return(SUNFALSE);
   }
 
-  tempv = N_VClone(tmpl);
-  if (tempv == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(acor);
-    return(FALSE);
+  cv_mem->cv_tempv = N_VClone(tmpl);
+  if (cv_mem->cv_tempv == NULL) {
+    N_VDestroy(cv_mem->cv_ewt);
+    N_VDestroy(cv_mem->cv_acor);
+    return(SUNFALSE);
   }
 
-  ftemp = N_VClone(tmpl);
-  if (ftemp == NULL) {
-    N_VDestroy(tempv);
-    N_VDestroy(ewt);
-    N_VDestroy(acor);
-    return(FALSE);
+  cv_mem->cv_ftemp = N_VClone(tmpl);
+  if (cv_mem->cv_ftemp == NULL) {
+    N_VDestroy(cv_mem->cv_tempv);
+    N_VDestroy(cv_mem->cv_ewt);
+    N_VDestroy(cv_mem->cv_acor);
+    return(SUNFALSE);
   }
 
   /* Allocate zn[0] ... zn[qmax] */
 
-  for (j=0; j <= qmax; j++) {
-    zn[j] = N_VClone(tmpl);
-    if (zn[j] == NULL) {
-      N_VDestroy(ewt);
-      N_VDestroy(acor);
-      N_VDestroy(tempv);
-      N_VDestroy(ftemp);
-      for (i=0; i < j; i++) N_VDestroy(zn[i]);
-      return(FALSE);
+  for (j=0; j <= cv_mem->cv_qmax; j++) {
+    cv_mem->cv_zn[j] = N_VClone(tmpl);
+    if (cv_mem->cv_zn[j] == NULL) {
+      N_VDestroy(cv_mem->cv_ewt);
+      N_VDestroy(cv_mem->cv_acor);
+      N_VDestroy(cv_mem->cv_tempv);
+      N_VDestroy(cv_mem->cv_ftemp);
+      for (i=0; i < j; i++) N_VDestroy(cv_mem->cv_zn[i]);
+      return(SUNFALSE);
     }
   }
 
   /* Update solver workspace lengths  */
-  lrw += (qmax + 5)*lrw1;
-  liw += (qmax + 5)*liw1;
+  cv_mem->cv_lrw += (cv_mem->cv_qmax + 5)*cv_mem->cv_lrw1;
+  cv_mem->cv_liw += (cv_mem->cv_qmax + 5)*cv_mem->cv_liw1;
 
   /* Store the value of qmax used here */
-  cv_mem->cv_qmax_alloc = qmax;
+  cv_mem->cv_qmax_alloc = cv_mem->cv_qmax;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*  
@@ -1703,19 +1599,19 @@ static void cvFreeVectors(CVodeMem cv_mem)
   
   maxord = cv_mem->cv_qmax_alloc;
 
-  N_VDestroy(ewt);
-  N_VDestroy(acor);
-  N_VDestroy(tempv);
-  N_VDestroy(ftemp);
-  for (j=0; j <= maxord; j++) N_VDestroy(zn[j]);
+  N_VDestroy(cv_mem->cv_ewt);
+  N_VDestroy(cv_mem->cv_acor);
+  N_VDestroy(cv_mem->cv_tempv);
+  N_VDestroy(cv_mem->cv_ftemp);
+  for (j=0; j <= maxord; j++) N_VDestroy(cv_mem->cv_zn[j]);
 
-  lrw -= (maxord + 5)*lrw1;
-  liw -= (maxord + 5)*liw1;
+  cv_mem->cv_lrw -= (maxord + 5)*cv_mem->cv_lrw1;
+  cv_mem->cv_liw -= (maxord + 5)*cv_mem->cv_liw1;
 
   if (cv_mem->cv_VabstolMallocDone) {
-    N_VDestroy(Vabstol);
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(cv_mem->cv_Vabstol);
+    cv_mem->cv_lrw -= cv_mem->cv_lrw1;
+    cv_mem->cv_liw -= cv_mem->cv_liw1;
   }
 }
 
@@ -1732,19 +1628,19 @@ static int cvInitialSetup(CVodeMem cv_mem)
   int ier;
 
   /* Did the user specify tolerances? */
-  if (itol == CV_NN) {
+  if (cv_mem->cv_itol == CV_NN) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "cvInitialSetup", MSGCV_NO_TOLS);
     return(CV_ILL_INPUT);
   }
 
   /* Set data for efun */
-  if (cv_mem->cv_user_efun) e_data = user_data;
-  else                      e_data = cv_mem;
+  if (cv_mem->cv_user_efun) cv_mem->cv_e_data = cv_mem->cv_user_data;
+  else                      cv_mem->cv_e_data = cv_mem;
 
   /* Load initial error weights */
-  ier = efun(zn[0], ewt, e_data);
+  ier = cv_mem->cv_efun(cv_mem->cv_zn[0], cv_mem->cv_ewt, cv_mem->cv_e_data);
   if (ier != 0) {
-    if (itol == CV_WF) 
+    if (cv_mem->cv_itol == CV_WF) 
       cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "cvInitialSetup", MSGCV_EWT_FAIL);
     else
       cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "cvInitialSetup", MSGCV_BAD_EWT);
@@ -1752,13 +1648,13 @@ static int cvInitialSetup(CVodeMem cv_mem)
   }
   
   /* Check if lsolve function exists (if needed) and call linit function (if it exists) */
-  if (iter == CV_NEWTON) {
-    if (lsolve == NULL) {
+  if (cv_mem->cv_iter == CV_NEWTON) {
+    if (cv_mem->cv_lsolve == NULL) {
       cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "cvInitialSetup", MSGCV_LSOLVE_NULL);
       return(CV_ILL_INPUT);
     }
-    if (linit != NULL) {
-      ier = linit(cv_mem);
+    if (cv_mem->cv_linit != NULL) {
+      ier = cv_mem->cv_linit(cv_mem);
       if (ier != 0) {
         cvProcessError(cv_mem, CV_LINIT_FAIL, "CVODE", "cvInitialSetup", MSGCV_LINIT_FAIL);
         return(CV_LINIT_FAIL);
@@ -1818,11 +1714,11 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
 
   /* If tout is too close to tn, give up */
   
-  if ((tdiff = tout-tn) == ZERO) return(CV_TOO_CLOSE);
+  if ((tdiff = tout-cv_mem->cv_tn) == ZERO) return(CV_TOO_CLOSE);
   
   sign = (tdiff > ZERO) ? 1 : -1;
   tdist = SUNRabs(tdiff);
-  tround = uround * SUNMAX(SUNRabs(tn), SUNRabs(tout));
+  tround = cv_mem->cv_uround * SUNMAX(SUNRabs(cv_mem->cv_tn), SUNRabs(tout));
 
   if (tdist < TWO*tround) return(CV_TOO_CLOSE);
   
@@ -1838,21 +1734,21 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
   hg  = SUNRsqrt(hlb*hub);
 
   if (hub < hlb) {
-    if (sign == -1) h = -hg;
-    else            h =  hg;
+    if (sign == -1) cv_mem->cv_h = -hg;
+    else            cv_mem->cv_h =  hg;
     return(CV_SUCCESS);
   }
   
   /* Outer loop */
 
-  hnewOK = FALSE;
+  hnewOK = SUNFALSE;
   hs = hg;         /* safeguard against 'uninitialized variable' warning */
 
   for(count1 = 1; count1 <= MAX_ITERS; count1++) {
 
     /* Attempts to estimate ydd */
 
-    hgOK = FALSE;
+    hgOK = SUNFALSE;
 
     for (count2 = 1; count2 <= MAX_ITERS; count2++) {
       hgs = hg*sign;
@@ -1860,7 +1756,7 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
       /* If f() failed unrecoverably, give up */
       if (retval < 0) return(CV_RHSFUNC_FAIL);
       /* If successful, we can use ydd */
-      if (retval == CV_SUCCESS) {hgOK = TRUE; break;}
+      if (retval == CV_SUCCESS) {hgOK = SUNTRUE; break;}
       /* f() failed recoverably; cut step size and test it again */
       hg *= POINT2;
     }
@@ -1888,13 +1784,13 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
     
     /* Accept hnew if it does not differ from hg by more than a factor of 2 */
     if ((hrat > HALF) && (hrat < TWO)) {
-      hnewOK = TRUE;
+      hnewOK = SUNTRUE;
     }
 
     /* After one pass, if ydd seems to be bad, use fall-back value. */
     if ((count1 > 1) && (hrat > TWO)) {
       hnew = hg;
-      hnewOK = TRUE;
+      hnewOK = SUNTRUE;
     }
 
     /* Send this value back through f() */
@@ -1908,7 +1804,7 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
   if (h0 < hlb) h0 = hlb;
   if (h0 > hub) h0 = hub;
   if (sign == -1) h0 = -h0;
-  h = h0;
+  cv_mem->cv_h = h0;
 
   return(CV_SUCCESS);
 }
@@ -1931,15 +1827,15 @@ static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist)
    * factor is used as a safeguard against zero components in y0. 
    */
 
-  temp1 = tempv;
-  temp2 = acor;
+  temp1 = cv_mem->cv_tempv;
+  temp2 = cv_mem->cv_acor;
 
-  N_VAbs(zn[0], temp2);
-  efun(zn[0], temp1, e_data);
+  N_VAbs(cv_mem->cv_zn[0], temp2);
+  cv_mem->cv_efun(cv_mem->cv_zn[0], temp1, cv_mem->cv_e_data);
   N_VInv(temp1, temp1);
   N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1);
 
-  N_VAbs(zn[1], temp2);
+  N_VAbs(cv_mem->cv_zn[1], temp2);
 
   N_VDiv(temp2, temp1, temp1);
   hub_inv = N_VMaxNorm(temp1);
@@ -1951,7 +1847,7 @@ static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist)
 
   hub = HUB_FACTOR*tdist;
 
-  /* Use the smaler of the two */
+  /* Use the smaller of the two */
 
   if (hub*hub_inv > ONE) hub = ONE/hub_inv;
 
@@ -1969,16 +1865,17 @@ static int cvYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm)
 {
   int retval;
 
-  N_VLinearSum(hg, zn[1], ONE, zn[0], y);
-  retval = f(tn+hg, y, tempv, user_data);
-  nfe++;
+  N_VLinearSum(hg, cv_mem->cv_zn[1], ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
+  retval = cv_mem->cv_f(cv_mem->cv_tn+hg, cv_mem->cv_y,
+                        cv_mem->cv_tempv, cv_mem->cv_user_data);
+  cv_mem->cv_nfe++;
   if (retval < 0) return(CV_RHSFUNC_FAIL);
   if (retval > 0) return(RHSFUNC_RECVR);
 
-  N_VLinearSum(ONE, tempv, -ONE, zn[1], tempv);
-  N_VScale(ONE/hg, tempv, tempv);
+  N_VLinearSum(ONE, cv_mem->cv_tempv, -ONE, cv_mem->cv_zn[1], cv_mem->cv_tempv);
+  N_VScale(ONE/hg, cv_mem->cv_tempv, cv_mem->cv_tempv);
 
-  *yddnrm = N_VWrmsNorm(tempv, ewt);
+  *yddnrm = N_VWrmsNorm(cv_mem->cv_tempv, cv_mem->cv_ewt);
 
   return(CV_SUCCESS);
 }
@@ -2008,14 +1905,15 @@ static int cvStep(CVodeMem cv_mem)
   int ncf, nef;
   int nflag, kflag, eflag;
   
-  saved_t = tn;
+  saved_t = cv_mem->cv_tn;
   ncf = nef = 0;
   nflag = FIRST_CALL;
 
-  if ((nst > 0) && (hprime != h)) cvAdjustParams(cv_mem);
+  if ((cv_mem->cv_nst > 0) && (cv_mem->cv_hprime != cv_mem->cv_h))
+    cvAdjustParams(cv_mem);
   
   /* Looping point for attempts to take a step */
-  loop {  
+  for(;;) {  
 
     cvPredict(cv_mem);  
     cvSet(cv_mem);
@@ -2053,14 +1951,14 @@ static int cvStep(CVodeMem cv_mem)
   /* If Stablilty Limit Detection is turned on, call stability limit
      detection routine for possible order reduction. */
 
-  if (sldeton) cvBDFStab(cv_mem);
+  if (cv_mem->cv_sldeton) cvBDFStab(cv_mem);
 
-  etamax = (nst <= SMALL_NST) ? ETAMX2 : ETAMX3;
+  cv_mem->cv_etamax = (cv_mem->cv_nst <= SMALL_NST) ? ETAMX2 : ETAMX3;
 
   /*  Finally, we rescale the acor array to be the 
       estimated local error vector. */
 
-  N_VScale(tq[2], acor, acor);
+  N_VScale(cv_mem->cv_tq[2], cv_mem->cv_acor, cv_mem->cv_acor);
   return(CV_SUCCESS);
       
 }
@@ -2077,11 +1975,11 @@ static int cvStep(CVodeMem cv_mem)
 
 static void cvAdjustParams(CVodeMem cv_mem)
 {
-  if (qprime != q) {
-    cvAdjustOrder(cv_mem, qprime-q);
-    q = qprime;
-    L = q+1;
-    qwait = L;
+  if (cv_mem->cv_qprime != cv_mem->cv_q) {
+    cvAdjustOrder(cv_mem, cv_mem->cv_qprime-cv_mem->cv_q);
+    cv_mem->cv_q = cv_mem->cv_qprime;
+    cv_mem->cv_L = cv_mem->cv_q+1;
+    cv_mem->cv_qwait = cv_mem->cv_L;
   }
   cvRescale(cv_mem);
 }
@@ -2098,9 +1996,9 @@ static void cvAdjustParams(CVodeMem cv_mem)
 
 static void cvAdjustOrder(CVodeMem cv_mem, int deltaq)
 {
-  if ((q==2) && (deltaq != 1)) return;
+  if ((cv_mem->cv_q==2) && (deltaq != 1)) return;
   
-  switch(lmm){
+  switch(cv_mem->cv_lmm){
   case CV_ADAMS: 
     cvAdjustAdams(cv_mem, deltaq);
     break;
@@ -2125,7 +2023,7 @@ static void cvAdjustAdams(CVodeMem cv_mem, int deltaq)
   /* On an order increase, set new column of zn to zero and return */
   
   if (deltaq==1) {
-    N_VConst(ZERO, zn[L]);
+    N_VConst(ZERO, cv_mem->cv_zn[cv_mem->cv_L]);
     return;
   }
 
@@ -2138,19 +2036,22 @@ static void cvAdjustAdams(CVodeMem cv_mem, int deltaq)
    * where xi_j = [t_n - t_(n-j)]/h => xi_0 = 0
    */
 
-  for (i=0; i <= qmax; i++) l[i] = ZERO;
-  l[1] = ONE;
+  for (i=0; i <= cv_mem->cv_qmax; i++) cv_mem->cv_l[i] = ZERO;
+  cv_mem->cv_l[1] = ONE;
   hsum = ZERO;
-  for (j=1; j <= q-2; j++) {
-    hsum += tau[j];
-    xi = hsum / hscale;
-    for (i=j+1; i >= 1; i--) l[i] = l[i]*xi + l[i-1];
+  for (j=1; j <= cv_mem->cv_q-2; j++) {
+    hsum += cv_mem->cv_tau[j];
+    xi = hsum / cv_mem->cv_hscale;
+    for (i=j+1; i >= 1; i--)
+      cv_mem->cv_l[i] = cv_mem->cv_l[i]*xi + cv_mem->cv_l[i-1];
   }
   
-  for (j=1; j <= q-2; j++) l[j+1] = q * (l[j] / (j+1));
+  for (j=1; j <= cv_mem->cv_q-2; j++)
+    cv_mem->cv_l[j+1] = cv_mem->cv_q * (cv_mem->cv_l[j] / (j+1));
   
-  for (j=2; j < q; j++)
-    N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+  for (j=2; j < cv_mem->cv_q; j++)
+    N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_zn[cv_mem->cv_q], ONE,
+                 cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 }
 
 /*
@@ -2191,25 +2092,28 @@ static void cvIncreaseBDF(CVodeMem cv_mem)
   realtype alpha0, alpha1, prod, xi, xiold, hsum, A1;
   int i, j;
   
-  for (i=0; i <= qmax; i++) l[i] = ZERO;
-  l[2] = alpha1 = prod = xiold = ONE;
+  for (i=0; i <= cv_mem->cv_qmax; i++) cv_mem->cv_l[i] = ZERO;
+  cv_mem->cv_l[2] = alpha1 = prod = xiold = ONE;
   alpha0 = -ONE;
-  hsum = hscale;
-  if (q > 1) {
-    for (j=1; j < q; j++) {
-      hsum += tau[j+1];
-      xi = hsum / hscale;
+  hsum = cv_mem->cv_hscale;
+  if (cv_mem->cv_q > 1) {
+    for (j=1; j < cv_mem->cv_q; j++) {
+      hsum += cv_mem->cv_tau[j+1];
+      xi = hsum / cv_mem->cv_hscale;
       prod *= xi;
       alpha0 -= ONE / (j+1);
       alpha1 += ONE / xi;
-      for (i=j+2; i >= 2; i--) l[i] = l[i]*xiold + l[i-1];
+      for (i=j+2; i >= 2; i--)
+        cv_mem->cv_l[i] = cv_mem->cv_l[i]*xiold + cv_mem->cv_l[i-1];
       xiold = xi;
     }
   }
   A1 = (-alpha0 - alpha1) / prod;
-  N_VScale(A1, zn[indx_acor], zn[L]);
-  for (j=2; j <= q; j++)
-    N_VLinearSum(l[j], zn[L], ONE, zn[j], zn[j]);
+  N_VScale(A1, cv_mem->cv_zn[cv_mem->cv_indx_acor],
+           cv_mem->cv_zn[cv_mem->cv_L]);
+  for (j=2; j <= cv_mem->cv_q; j++)
+    N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_zn[cv_mem->cv_L], ONE,
+                 cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 }
 
 /*
@@ -2227,17 +2131,19 @@ static void cvDecreaseBDF(CVodeMem cv_mem)
   realtype hsum, xi;
   int i, j;
   
-  for (i=0; i <= qmax; i++) l[i] = ZERO;
-  l[2] = ONE;
+  for (i=0; i <= cv_mem->cv_qmax; i++) cv_mem->cv_l[i] = ZERO;
+  cv_mem->cv_l[2] = ONE;
   hsum = ZERO;
-  for (j=1; j <= q-2; j++) {
-    hsum += tau[j];
-    xi = hsum /hscale;
-    for (i=j+2; i >= 2; i--) l[i] = l[i]*xi + l[i-1];
+  for (j=1; j <= cv_mem->cv_q-2; j++) {
+    hsum += cv_mem->cv_tau[j];
+    xi = hsum /cv_mem->cv_hscale;
+    for (i=j+2; i >= 2; i--)
+      cv_mem->cv_l[i] = cv_mem->cv_l[i]*xi + cv_mem->cv_l[i-1];
   }
   
-  for (j=2; j < q; j++)
-    N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+  for (j=2; j < cv_mem->cv_q; j++)
+    N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_zn[cv_mem->cv_q],
+                 ONE, cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 }
 
 /*
@@ -2253,15 +2159,15 @@ static void cvRescale(CVodeMem cv_mem)
   int j;
   realtype factor;
   
-  factor = eta;
-  for (j=1; j <= q; j++) {
-    N_VScale(factor, zn[j], zn[j]);
-    factor *= eta;
+  factor = cv_mem->cv_eta;
+  for (j=1; j <= cv_mem->cv_q; j++) {
+    N_VScale(factor, cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
+    factor *= cv_mem->cv_eta;
   }
-  h = hscale * eta;
-  next_h = h;
-  hscale = h;
-  nscon = 0;
+  cv_mem->cv_h = cv_mem->cv_hscale * cv_mem->cv_eta;
+  cv_mem->cv_next_h = cv_mem->cv_h;
+  cv_mem->cv_hscale = cv_mem->cv_h;
+  cv_mem->cv_nscon = 0;
 }
 
 /*
@@ -2278,13 +2184,15 @@ static void cvPredict(CVodeMem cv_mem)
 {
   int j, k;
   
-  tn += h;
-  if (tstopset) {
-    if ((tn - tstop)*h > ZERO) tn = tstop;
+  cv_mem->cv_tn += cv_mem->cv_h;
+  if (cv_mem->cv_tstopset) {
+    if ((cv_mem->cv_tn - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO)
+      cv_mem->cv_tn = cv_mem->cv_tstop;
   }
-  for (k = 1; k <= q; k++)
-    for (j = q; j >= k; j--) 
-      N_VLinearSum(ONE, zn[j-1], ONE, zn[j], zn[j-1]); 
+  for (k = 1; k <= cv_mem->cv_q; k++)
+    for (j = cv_mem->cv_q; j >= k; j--) 
+      N_VLinearSum(ONE, cv_mem->cv_zn[j-1], ONE,
+                   cv_mem->cv_zn[j], cv_mem->cv_zn[j-1]); 
 }
 
 /*
@@ -2307,7 +2215,7 @@ static void cvPredict(CVodeMem cv_mem)
 
 static void cvSet(CVodeMem cv_mem)
 {
-  switch(lmm) {
+  switch(cv_mem->cv_lmm) {
   case CV_ADAMS: 
     cvSetAdams(cv_mem);
     break;
@@ -2315,10 +2223,11 @@ static void cvSet(CVodeMem cv_mem)
     cvSetBDF(cv_mem);
     break;
   }
-  rl1 = ONE / l[1];
-  gamma = h * rl1;
-  if (nst == 0) gammap = gamma;
-  gamrat = (nst > 0) ? gamma / gammap : ONE;  /* protect x / x != 1.0 */
+  cv_mem->cv_rl1 = ONE / cv_mem->cv_l[1];
+  cv_mem->cv_gamma = cv_mem->cv_h * cv_mem->cv_rl1;
+  if (cv_mem->cv_nst == 0) cv_mem->cv_gammap = cv_mem->cv_gamma;
+  cv_mem->cv_gamrat = (cv_mem->cv_nst > 0) ?
+    cv_mem->cv_gamma / cv_mem->cv_gammap : ONE;  /* protect x / x != 1.0 */
 }
 
 /*
@@ -2343,18 +2252,18 @@ static void cvSetAdams(CVodeMem cv_mem)
 {
   realtype m[L_MAX], M[3], hsum;
   
-  if (q == 1) {
-    l[0] = l[1] = tq[1] = tq[5] = ONE;
-    tq[2] = HALF;
-    tq[3] = ONE/TWELVE;
-    tq[4] = nlscoef / tq[2];       /* = 0.1 / tq[2] */
+  if (cv_mem->cv_q == 1) {
+    cv_mem->cv_l[0] = cv_mem->cv_l[1] = cv_mem->cv_tq[1] = cv_mem->cv_tq[5] = ONE;
+    cv_mem->cv_tq[2] = HALF;
+    cv_mem->cv_tq[3] = ONE/TWELVE;
+    cv_mem->cv_tq[4] = cv_mem->cv_nlscoef / cv_mem->cv_tq[2];       /* = 0.1 / tq[2] */
     return;
   }
   
   hsum = cvAdamsStart(cv_mem, m);
   
-  M[0] = cvAltSum(q-1, m, 1);
-  M[1] = cvAltSum(q-1, m, 2);
+  M[0] = cvAltSum(cv_mem->cv_q-1, m, 1);
+  M[1] = cvAltSum(cv_mem->cv_q-1, m, 2);
   
   cvAdamsFinish(cv_mem, m, M, hsum);
 }
@@ -2371,17 +2280,17 @@ static realtype cvAdamsStart(CVodeMem cv_mem, realtype m[])
   realtype hsum, xi_inv, sum;
   int i, j;
   
-  hsum = h;
+  hsum = cv_mem->cv_h;
   m[0] = ONE;
-  for (i=1; i <= q; i++) m[i] = ZERO;
-  for (j=1; j < q; j++) {
-    if ((j==q-1) && (qwait == 1)) {
-      sum = cvAltSum(q-2, m, 2);
-      tq[1] = q * sum / m[q-2];
+  for (i=1; i <= cv_mem->cv_q; i++) m[i] = ZERO;
+  for (j=1; j < cv_mem->cv_q; j++) {
+    if ((j==cv_mem->cv_q-1) && (cv_mem->cv_qwait == 1)) {
+      sum = cvAltSum(cv_mem->cv_q-2, m, 2);
+      cv_mem->cv_tq[1] = cv_mem->cv_q * sum / m[cv_mem->cv_q-2];
     }
-    xi_inv = h / hsum;
+    xi_inv = cv_mem->cv_h / hsum;
     for (i=j; i >= 1; i--) m[i] += m[i-1] * xi_inv;
-    hsum += tau[j];
+    hsum += cv_mem->cv_tau[j];
     /* The m[i] are coefficients of product(1 to j) (1 + x/xi_i) */
   }
   return(hsum);
@@ -2400,21 +2309,22 @@ static void cvAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype
   
   M0_inv = ONE / M[0];
   
-  l[0] = ONE;
-  for (i=1; i <= q; i++) l[i] = M0_inv * (m[i-1] / i);
-  xi = hsum / h;
+  cv_mem->cv_l[0] = ONE;
+  for (i=1; i <= cv_mem->cv_q; i++)
+    cv_mem->cv_l[i] = M0_inv * (m[i-1] / i);
+  xi = hsum / cv_mem->cv_h;
   xi_inv = ONE / xi;
   
-  tq[2] = M[1] * M0_inv / xi;
-  tq[5] = xi / l[q];
+  cv_mem->cv_tq[2] = M[1] * M0_inv / xi;
+  cv_mem->cv_tq[5] = xi / cv_mem->cv_l[cv_mem->cv_q];
 
-  if (qwait == 1) {
-    for (i=q; i >= 1; i--) m[i] += m[i-1] * xi_inv;
-    M[2] = cvAltSum(q, m, 2);
-    tq[3] = M[2] * M0_inv / L;
+  if (cv_mem->cv_qwait == 1) {
+    for (i=cv_mem->cv_q; i >= 1; i--) m[i] += m[i-1] * xi_inv;
+    M[2] = cvAltSum(cv_mem->cv_q, m, 2);
+    cv_mem->cv_tq[3] = M[2] * M0_inv / cv_mem->cv_L;
   }
 
-  tq[4] = nlscoef / tq[2];
+  cv_mem->cv_tq[4] = cv_mem->cv_nlscoef / cv_mem->cv_tq[2];
 }
 
 /*  
@@ -2466,26 +2376,27 @@ static void cvSetBDF(CVodeMem cv_mem)
   realtype alpha0, alpha0_hat, xi_inv, xistar_inv, hsum;
   int i,j;
   
-  l[0] = l[1] = xi_inv = xistar_inv = ONE;
-  for (i=2; i <= q; i++) l[i] = ZERO;
+  cv_mem->cv_l[0] = cv_mem->cv_l[1] = xi_inv = xistar_inv = ONE;
+  for (i=2; i <= cv_mem->cv_q; i++) cv_mem->cv_l[i] = ZERO;
   alpha0 = alpha0_hat = -ONE;
-  hsum = h;
-  if (q > 1) {
-    for (j=2; j < q; j++) {
-      hsum += tau[j-1];
-      xi_inv = h / hsum;
+  hsum = cv_mem->cv_h;
+  if (cv_mem->cv_q > 1) {
+    for (j=2; j < cv_mem->cv_q; j++) {
+      hsum += cv_mem->cv_tau[j-1];
+      xi_inv = cv_mem->cv_h / hsum;
       alpha0 -= ONE / j;
-      for (i=j; i >= 1; i--) l[i] += l[i-1]*xi_inv;
+      for (i=j; i >= 1; i--) cv_mem->cv_l[i] += cv_mem->cv_l[i-1]*xi_inv;
       /* The l[i] are coefficients of product(1 to j) (1 + x/xi_i) */
     }
     
     /* j = q */
-    alpha0 -= ONE / q;
-    xistar_inv = -l[1] - alpha0;
-    hsum += tau[q-1];
-    xi_inv = h / hsum;
-    alpha0_hat = -l[1] - xi_inv;
-    for (i=q; i >= 1; i--) l[i] += l[i-1]*xistar_inv;
+    alpha0 -= ONE / cv_mem->cv_q;
+    xistar_inv = -cv_mem->cv_l[1] - alpha0;
+    hsum += cv_mem->cv_tau[cv_mem->cv_q-1];
+    xi_inv = cv_mem->cv_h / hsum;
+    alpha0_hat = -cv_mem->cv_l[1] - xi_inv;
+    for (i=cv_mem->cv_q; i >= 1; i--)
+      cv_mem->cv_l[i] += cv_mem->cv_l[i-1]*xistar_inv;
   }
 
   cvSetTqBDF(cv_mem, hsum, alpha0, alpha0_hat, xi_inv, xistar_inv);
@@ -2505,26 +2416,26 @@ static void cvSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0,
   realtype C, Cpinv, Cppinv;
   
   A1 = ONE - alpha0_hat + alpha0;
-  A2 = ONE + q * A1;
-  tq[2] = SUNRabs(A1 / (alpha0 * A2));
-  tq[5] = SUNRabs(A2 * xistar_inv / (l[q] * xi_inv));
-  if (qwait == 1) {
-    if (q > 1) {
-      C = xistar_inv / l[q];
-      A3 = alpha0 + ONE / q;
+  A2 = ONE + cv_mem->cv_q * A1;
+  cv_mem->cv_tq[2] = SUNRabs(A1 / (alpha0 * A2));
+  cv_mem->cv_tq[5] = SUNRabs(A2 * xistar_inv / (cv_mem->cv_l[cv_mem->cv_q] * xi_inv));
+  if (cv_mem->cv_qwait == 1) {
+    if (cv_mem->cv_q > 1) {
+      C = xistar_inv / cv_mem->cv_l[cv_mem->cv_q];
+      A3 = alpha0 + ONE / cv_mem->cv_q;
       A4 = alpha0_hat + xi_inv;
       Cpinv = (ONE - A4 + A3) / A3;
-      tq[1] = SUNRabs(C * Cpinv);
+      cv_mem->cv_tq[1] = SUNRabs(C * Cpinv);
     }
-    else tq[1] = ONE;
-    hsum += tau[q];
-    xi_inv = h / hsum;
-    A5 = alpha0 - (ONE / (q+1));
+    else cv_mem->cv_tq[1] = ONE;
+    hsum += cv_mem->cv_tau[cv_mem->cv_q];
+    xi_inv = cv_mem->cv_h / hsum;
+    A5 = alpha0 - (ONE / (cv_mem->cv_q+1));
     A6 = alpha0_hat - xi_inv;
     Cppinv = (ONE - A6 + A5) / A2;
-    tq[3] = SUNRabs(Cppinv / (xi_inv * (q+2) * A5));
+    cv_mem->cv_tq[3] = SUNRabs(Cppinv / (xi_inv * (cv_mem->cv_q+2) * A5));
   }
-  tq[4] = nlscoef / tq[2];
+  cv_mem->cv_tq[4] = cv_mem->cv_nlscoef / cv_mem->cv_tq[2];
 }
 
 /*
@@ -2540,7 +2451,7 @@ static int cvNls(CVodeMem cv_mem, int nflag)
 {
   int flag = CV_SUCCESS;
 
-  switch(iter) {
+  switch(cv_mem->cv_iter) {
   case CV_FUNCTIONAL: 
     flag = cvNlsFunctional(cv_mem);
     break;
@@ -2576,52 +2487,57 @@ static int cvNlsFunctional(CVodeMem cv_mem)
 
   /* Initialize counter and evaluate f at predicted y */
   
-  crate = ONE;
+  cv_mem->cv_crate = ONE;
   m = 0;
 
-  retval = f(tn, zn[0], tempv, user_data);
-  nfe++;
+  retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                        cv_mem->cv_tempv, cv_mem->cv_user_data);
+  cv_mem->cv_nfe++;
   if (retval < 0) return(CV_RHSFUNC_FAIL);
   if (retval > 0) return(RHSFUNC_RECVR);
 
-  N_VConst(ZERO, acor);
+  N_VConst(ZERO, cv_mem->cv_acor);
 
   /* Initialize delp to avoid compiler warning message */
   del = delp = ZERO;
 
   /* Loop until convergence; accumulate corrections in acor */
 
-  loop {
+  for(;;) {
 
-    nni++;
+    cv_mem->cv_nni++;
 
     /* Correct y directly from the last f value */
-    N_VLinearSum(h, tempv, -ONE, zn[1], tempv);
-    N_VScale(rl1, tempv, tempv);
-    N_VLinearSum(ONE, zn[0], ONE, tempv, y);
+    N_VLinearSum(cv_mem->cv_h, cv_mem->cv_tempv, -ONE,
+                 cv_mem->cv_zn[1], cv_mem->cv_tempv);
+    N_VScale(cv_mem->cv_rl1, cv_mem->cv_tempv, cv_mem->cv_tempv);
+    N_VLinearSum(ONE, cv_mem->cv_zn[0], ONE, cv_mem->cv_tempv, cv_mem->cv_y);
     /* Get WRMS norm of current correction to use in convergence test */
-    N_VLinearSum(ONE, tempv, -ONE, acor, acor);
-    del = N_VWrmsNorm(acor, ewt);
-    N_VScale(ONE, tempv, acor);
+    N_VLinearSum(ONE, cv_mem->cv_tempv, -ONE, cv_mem->cv_acor, cv_mem->cv_acor);
+    del = N_VWrmsNorm(cv_mem->cv_acor, cv_mem->cv_ewt);
+    N_VScale(ONE, cv_mem->cv_tempv, cv_mem->cv_acor);
     
     /* Test for convergence.  If m > 0, an estimate of the convergence
        rate constant is stored in crate, and used in the test.        */
-    if (m > 0) crate = SUNMAX(CRDOWN * crate, del / delp);
-    dcon = del * SUNMIN(ONE, crate) / tq[4];
+    if (m > 0) cv_mem->cv_crate = SUNMAX(CRDOWN * cv_mem->cv_crate, del / delp);
+    dcon = del * SUNMIN(ONE, cv_mem->cv_crate) / cv_mem->cv_tq[4];
     if (dcon <= ONE) {
-      acnrm = (m == 0) ? del : N_VWrmsNorm(acor, ewt);
+      cv_mem->cv_acnrm = (m == 0) ?
+        del : N_VWrmsNorm(cv_mem->cv_acor, cv_mem->cv_ewt);
       return(CV_SUCCESS);  /* Convergence achieved */
     }
 
     /* Stop at maxcor iterations or if iter. seems to be diverging */
     m++;
-    if ((m==maxcor) || ((m >= 2) && (del > RDIV * delp))) return(CONV_FAIL);
+    if ((m==cv_mem->cv_maxcor) || ((m >= 2) && (del > RDIV * delp)))
+      return(CONV_FAIL);
 
     /* Save norm of correction, evaluate f, and loop again */
     delp = del;
 
-    retval = f(tn, y, tempv, user_data);
-    nfe++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_y,
+                          cv_mem->cv_tempv, cv_mem->cv_user_data);
+    cv_mem->cv_nfe++;
     if (retval < 0) return(CV_RHSFUNC_FAIL);
     if (retval > 0) return(RHSFUNC_RECVR);
 
@@ -2654,21 +2570,23 @@ static int cvNlsNewton(CVodeMem cv_mem, int nflag)
   int convfail, retval, ier;
   booleantype callSetup;
   
-  vtemp1 = acor;  /* rename acor as vtemp1 for readability  */
-  vtemp2 = y;     /* rename y as vtemp2 for readability     */
-  vtemp3 = tempv; /* rename tempv as vtemp3 for readability */
+  vtemp1 = cv_mem->cv_acor;  /* rename acor as vtemp1 for readability  */
+  vtemp2 = cv_mem->cv_y;     /* rename y as vtemp2 for readability     */
+  vtemp3 = cv_mem->cv_tempv; /* rename tempv as vtemp3 for readability */
   
   /* Set flag convfail, input to lsetup for its evaluation decision */
   convfail = ((nflag == FIRST_CALL) || (nflag == PREV_ERR_FAIL)) ?
     CV_NO_FAILURES : CV_FAIL_OTHER;
 
   /* Decide whether or not to call setup routine (if one exists) */
-  if (setupNonNull) {      
+  if (cv_mem->cv_lsetup) {      
     callSetup = (nflag == PREV_CONV_FAIL) || (nflag == PREV_ERR_FAIL) ||
-      (nst == 0) || (nst >= nstlp + MSBP) || (SUNRabs(gamrat-ONE) > DGMAX);
+      (cv_mem->cv_nst == 0) ||
+      (cv_mem->cv_nst >= cv_mem->cv_nstlp + MSBP) ||
+      (SUNRabs(cv_mem->cv_gamrat-ONE) > DGMAX);
   } else {  
-    crate = ONE;
-    callSetup = FALSE;
+    cv_mem->cv_crate = ONE;
+    callSetup = SUNFALSE;
   }
   
   /* Looping point for the solution of the nonlinear system.
@@ -2676,29 +2594,31 @@ static int cvNlsNewton(CVodeMem cv_mem, int nflag)
      call cvNewtonIteration for the Newton iteration itself.      */
   
 
-  loop {
+  for(;;) {
 
-    retval = f(tn, zn[0], ftemp, user_data);
-    nfe++; 
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                          cv_mem->cv_ftemp, cv_mem->cv_user_data);
+    cv_mem->cv_nfe++; 
     if (retval < 0) return(CV_RHSFUNC_FAIL);
     if (retval > 0) return(RHSFUNC_RECVR);
 
     if (callSetup) {
-      ier = lsetup(cv_mem, convfail, zn[0], ftemp, &jcur, 
-                   vtemp1, vtemp2, vtemp3);
-      nsetups++;
-      callSetup = FALSE;
-      gamrat = crate = ONE; 
-      gammap = gamma;
-      nstlp = nst;
+      ier = cv_mem->cv_lsetup(cv_mem, convfail, cv_mem->cv_zn[0],
+                              cv_mem->cv_ftemp, &(cv_mem->cv_jcur),
+                              vtemp1, vtemp2, vtemp3);
+      cv_mem->cv_nsetups++;
+      callSetup = SUNFALSE;
+      cv_mem->cv_gamrat = cv_mem->cv_crate = ONE; 
+      cv_mem->cv_gammap = cv_mem->cv_gamma;
+      cv_mem->cv_nstlp = cv_mem->cv_nst;
       /* Return if lsetup failed */
       if (ier < 0) return(CV_LSETUP_FAIL);
       if (ier > 0) return(CONV_FAIL);
     }
 
     /* Set acor to zero and load prediction into y vector */
-    N_VConst(ZERO, acor);
-    N_VScale(ONE, zn[0], y);
+    N_VConst(ZERO, cv_mem->cv_acor);
+    N_VScale(ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
 
     /* Do the Newton iteration */
     ier = cvNewtonIteration(cv_mem);
@@ -2708,7 +2628,7 @@ static int cvNlsNewton(CVodeMem cv_mem, int nflag)
        in which convfail=CV_FAIL_BAD_J.  Otherwise return.                 */
     if (ier != TRY_AGAIN) return(ier);
     
-    callSetup = TRUE;
+    callSetup = SUNTRUE;
     convfail = CV_FAIL_BAD_J;
   }
 }
@@ -2732,68 +2652,79 @@ static int cvNewtonIteration(CVodeMem cv_mem)
   realtype del, delp, dcon;
   N_Vector b;
 
-  mnewt = m = 0;
+  cv_mem->cv_mnewt = m = 0;
 
   /* Initialize delp to avoid compiler warning message */
   del = delp = ZERO;
 
   /* Looping point for Newton iteration */
-  loop {
+  for(;;) {
 
     /* Evaluate the residual of the nonlinear system */
-    N_VLinearSum(rl1, zn[1], ONE, acor, tempv);
-    N_VLinearSum(gamma, ftemp, -ONE, tempv, tempv);
+    N_VLinearSum(cv_mem->cv_rl1, cv_mem->cv_zn[1], ONE,
+                 cv_mem->cv_acor, cv_mem->cv_tempv);
+    N_VLinearSum(cv_mem->cv_gamma, cv_mem->cv_ftemp, -ONE,
+                 cv_mem->cv_tempv, cv_mem->cv_tempv);
 
     /* Call the lsolve function */
-    b = tempv;
-    retval = lsolve(cv_mem, b, ewt, y, ftemp); 
-    nni++;
+    b = cv_mem->cv_tempv;
+    retval = cv_mem->cv_lsolve(cv_mem, b, cv_mem->cv_ewt,
+                               cv_mem->cv_y, cv_mem->cv_ftemp); 
+    cv_mem->cv_nni++;
     
     if (retval < 0) return(CV_LSOLVE_FAIL);
     
     /* If lsolve had a recoverable failure and Jacobian data is
        not current, signal to try the solution again            */
     if (retval > 0) { 
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(CONV_FAIL);
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(CONV_FAIL);
     }
 
     /* Get WRMS norm of correction; add correction to acor and y */
-    del = N_VWrmsNorm(b, ewt);
-    N_VLinearSum(ONE, acor, ONE, b, acor);
-    N_VLinearSum(ONE, zn[0], ONE, acor, y);
+    del = N_VWrmsNorm(b, cv_mem->cv_ewt);
+    N_VLinearSum(ONE, cv_mem->cv_acor, ONE, b, cv_mem->cv_acor);
+    N_VLinearSum(ONE, cv_mem->cv_zn[0], ONE, cv_mem->cv_acor, cv_mem->cv_y);
     
     /* Test for convergence.  If m > 0, an estimate of the convergence
        rate constant is stored in crate, and used in the test.        */
     if (m > 0) {
-      crate = SUNMAX(CRDOWN * crate, del/delp);
+      cv_mem->cv_crate = SUNMAX(CRDOWN * cv_mem->cv_crate, del/delp);
     }
-    dcon = del * SUNMIN(ONE, crate) / tq[4];
+    dcon = del * SUNMIN(ONE, cv_mem->cv_crate) / cv_mem->cv_tq[4];
     
     if (dcon <= ONE) {
-      acnrm = (m==0) ? del : N_VWrmsNorm(acor, ewt);
-      jcur = FALSE;
+      cv_mem->cv_acnrm = (m==0) ?
+        del : N_VWrmsNorm(cv_mem->cv_acor, cv_mem->cv_ewt);
+      cv_mem->cv_jcur = SUNFALSE;
       return(CV_SUCCESS); /* Nonlinear system was solved successfully */
     }
     
-    mnewt = ++m;
+    cv_mem->cv_mnewt = ++m;
     
     /* Stop at maxcor iterations or if iter. seems to be diverging.
        If still not converged and Jacobian data is not current, 
        signal to try the solution again                            */
-    if ((m == maxcor) || ((m >= 2) && (del > RDIV*delp))) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(CONV_FAIL);
+    if ((m == cv_mem->cv_maxcor) || ((m >= 2) && (del > RDIV*delp))) {
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(CONV_FAIL);
     }
     
     /* Save norm of correction, evaluate f, and loop again */
     delp = del;
-    retval = f(tn, y, ftemp, user_data);
-    nfe++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_y,
+                          cv_mem->cv_ftemp, cv_mem->cv_user_data);
+    cv_mem->cv_nfe++;
     if (retval < 0) return(CV_RHSFUNC_FAIL);
     if (retval > 0) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(RHSFUNC_RECVR);
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(RHSFUNC_RECVR);
     }
 
   } /* end loop */
@@ -2841,7 +2772,7 @@ static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
   if (nflag == CV_SUCCESS) return(DO_ERROR_TEST);
 
   /* The nonlinear soln. failed; increment ncfn and restore zn */
-  ncfn++;
+  cv_mem->cv_ncfn++;
   cvRestore(cv_mem, saved_t);
   
   /* Return if lsetup, lsolve, or rhs failed unrecoverably */
@@ -2852,19 +2783,20 @@ static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
   /* At this point, nflag = CONV_FAIL or RHSFUNC_RECVR; increment ncf */
   
   (*ncfPtr)++;
-  etamax = ONE;
+  cv_mem->cv_etamax = ONE;
 
   /* If we had maxncf failures or |h| = hmin, 
      return CV_CONV_FAILURE or CV_REPTD_RHSFUNC_ERR. */
 
-  if ((SUNRabs(h) <= hmin*ONEPSM) || (*ncfPtr == maxncf)) {
+  if ((SUNRabs(cv_mem->cv_h) <= cv_mem->cv_hmin*ONEPSM) ||
+      (*ncfPtr == cv_mem->cv_maxncf)) {
     if (nflag == CONV_FAIL)     return(CV_CONV_FAILURE);
     if (nflag == RHSFUNC_RECVR) return(CV_REPTD_RHSFUNC_ERR);    
   }
 
   /* Reduce step size; return to reattempt the step */
 
-  eta = SUNMAX(ETACF, hmin / SUNRabs(h));
+  cv_mem->cv_eta = SUNMAX(ETACF, cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h));
   *nflagPtr = PREV_CONV_FAIL;
   cvRescale(cv_mem);
 
@@ -2883,10 +2815,11 @@ static void cvRestore(CVodeMem cv_mem, realtype saved_t)
 {
   int j, k;
   
-  tn = saved_t;
-  for (k = 1; k <= q; k++)
-    for (j = q; j >= k; j--)
-      N_VLinearSum(ONE, zn[j-1], -ONE, zn[j], zn[j-1]);
+  cv_mem->cv_tn = saved_t;
+  for (k = 1; k <= cv_mem->cv_q; k++)
+    for (j = cv_mem->cv_q; j >= k; j--)
+      N_VLinearSum(ONE, cv_mem->cv_zn[j-1], -ONE,
+                   cv_mem->cv_zn[j], cv_mem->cv_zn[j-1]);
 }
 
 /*
@@ -2913,12 +2846,12 @@ static void cvRestore(CVodeMem cv_mem, realtype saved_t)
  */
 
 static booleantype cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr,
-                                realtype saved_t, int *nefPtr, realtype *dsmPtr)
+                                 realtype saved_t, int *nefPtr, realtype *dsmPtr)
 {
   realtype dsm;
   int retval;
   
-  dsm = acnrm * tq[2];
+  dsm = cv_mem->cv_acnrm * cv_mem->cv_tq[2];
 
   /* If est. local error norm dsm passes test, return CV_SUCCESS */  
   *dsmPtr = dsm; 
@@ -2926,51 +2859,54 @@ static booleantype cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr,
   
   /* Test failed; increment counters, set nflag, and restore zn array */
   (*nefPtr)++;
-  netf++;
+  cv_mem->cv_netf++;
   *nflagPtr = PREV_ERR_FAIL;
   cvRestore(cv_mem, saved_t);
 
   /* At maxnef failures or |h| = hmin, return CV_ERR_FAILURE */
-  if ((SUNRabs(h) <= hmin*ONEPSM) || (*nefPtr == maxnef)) return(CV_ERR_FAILURE);
+  if ((SUNRabs(cv_mem->cv_h) <= cv_mem->cv_hmin*ONEPSM) ||
+      (*nefPtr == cv_mem->cv_maxnef)) return(CV_ERR_FAILURE);
 
   /* Set etamax = 1 to prevent step size increase at end of this step */
-  etamax = ONE;
+  cv_mem->cv_etamax = ONE;
 
   /* Set h ratio eta from dsm, rescale, and return for retry of step */
   if (*nefPtr <= MXNEF1) {
-    eta = ONE / (SUNRpowerR(BIAS2*dsm,ONE/L) + ADDON);
-    eta = SUNMAX(ETAMIN, SUNMAX(eta, hmin / SUNRabs(h)));
-    if (*nefPtr >= SMALL_NEF) eta = SUNMIN(eta, ETAMXF);
+    cv_mem->cv_eta = ONE / (SUNRpowerR(BIAS2*dsm,ONE/cv_mem->cv_L) + ADDON);
+    cv_mem->cv_eta = SUNMAX(ETAMIN, SUNMAX(cv_mem->cv_eta,
+                                           cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h)));
+    if (*nefPtr >= SMALL_NEF) cv_mem->cv_eta = SUNMIN(cv_mem->cv_eta, ETAMXF);
     cvRescale(cv_mem);
     return(TRY_AGAIN);
   }
   
   /* After MXNEF1 failures, force an order reduction and retry step */
-  if (q > 1) {
-    eta = SUNMAX(ETAMIN, hmin / SUNRabs(h));
+  if (cv_mem->cv_q > 1) {
+    cv_mem->cv_eta = SUNMAX(ETAMIN, cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h));
     cvAdjustOrder(cv_mem,-1);
-    L = q;
-    q--;
-    qwait = L;
+    cv_mem->cv_L = cv_mem->cv_q;
+    cv_mem->cv_q--;
+    cv_mem->cv_qwait = cv_mem->cv_L;
     cvRescale(cv_mem);
     return(TRY_AGAIN);
   }
 
   /* If already at order 1, restart: reload zn from scratch */
 
-  eta = SUNMAX(ETAMIN, hmin / SUNRabs(h));
-  h *= eta;
-  next_h = h;
-  hscale = h;
-  qwait = LONG_WAIT;
-  nscon = 0;
+  cv_mem->cv_eta = SUNMAX(ETAMIN, cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h));
+  cv_mem->cv_h *= cv_mem->cv_eta;
+  cv_mem->cv_next_h = cv_mem->cv_h;
+  cv_mem->cv_hscale = cv_mem->cv_h;
+  cv_mem->cv_qwait = LONG_WAIT;
+  cv_mem->cv_nscon = 0;
 
-  retval = f(tn, zn[0], tempv, user_data);
-  nfe++;
+  retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                        cv_mem->cv_tempv, cv_mem->cv_user_data);
+  cv_mem->cv_nfe++;
   if (retval < 0)  return(CV_RHSFUNC_FAIL);
   if (retval > 0)  return(CV_UNREC_RHSFUNC_ERR);
 
-  N_VScale(h, tempv, zn[1]);
+  N_VScale(cv_mem->cv_h, cv_mem->cv_tempv, cv_mem->cv_zn[1]);
 
   return(TRY_AGAIN);
 }
@@ -2990,30 +2926,32 @@ static booleantype cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr,
  * update the tau array, and apply the corrections to the zn array.
  * The tau[i] are the last q values of h, with tau[1] the most recent.
  * The counter qwait is decremented, and if qwait == 1 (and q < qmax)
- * we save acor and tq[5] for a possible order increase.
+ * we save acor and cv_mem->cv_tq[5] for a possible order increase.
  */
 
 static void cvCompleteStep(CVodeMem cv_mem)
 {
   int i, j;
   
-  nst++;
-  nscon++;
-  hu = h;
-  qu = q;
+  cv_mem->cv_nst++;
+  cv_mem->cv_nscon++;
+  cv_mem->cv_hu = cv_mem->cv_h;
+  cv_mem->cv_qu = cv_mem->cv_q;
 
-  for (i=q; i >= 2; i--)  tau[i] = tau[i-1];
-  if ((q==1) && (nst > 1)) tau[2] = tau[1];
-  tau[1] = h;
+  for (i=cv_mem->cv_q; i >= 2; i--)  cv_mem->cv_tau[i] = cv_mem->cv_tau[i-1];
+  if ((cv_mem->cv_q==1) && (cv_mem->cv_nst > 1))
+    cv_mem->cv_tau[2] = cv_mem->cv_tau[1];
+  cv_mem->cv_tau[1] = cv_mem->cv_h;
 
   /* Apply correction to column j of zn: l_j * Delta_n */
-  for (j=0; j <= q; j++) 
-    N_VLinearSum(l[j], acor, ONE, zn[j], zn[j]);
-  qwait--;
-  if ((qwait == 1) && (q != qmax)) {
-    N_VScale(ONE, acor, zn[qmax]);
-    saved_tq5 = tq[5];
-    indx_acor = qmax;
+  for (j=0; j <= cv_mem->cv_q; j++) 
+    N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_acor, ONE,
+                 cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
+  cv_mem->cv_qwait--;
+  if ((cv_mem->cv_qwait == 1) && (cv_mem->cv_q != cv_mem->cv_qmax)) {
+    N_VScale(ONE, cv_mem->cv_acor, cv_mem->cv_zn[cv_mem->cv_qmax]);
+    cv_mem->cv_saved_tq5 = cv_mem->cv_tq[5];
+    cv_mem->cv_indx_acor = cv_mem->cv_qmax;
   }
 }
 
@@ -3029,21 +2967,21 @@ static void cvCompleteStep(CVodeMem cv_mem)
 static void cvPrepareNextStep(CVodeMem cv_mem, realtype dsm)
 {
   /* If etamax = 1, defer step size or order changes */
-  if (etamax == ONE) {
-    qwait = SUNMAX(qwait, 2);
-    qprime = q;
-    hprime = h;
-    eta = ONE;
+  if (cv_mem->cv_etamax == ONE) {
+    cv_mem->cv_qwait = SUNMAX(cv_mem->cv_qwait, 2);
+    cv_mem->cv_qprime = cv_mem->cv_q;
+    cv_mem->cv_hprime = cv_mem->cv_h;
+    cv_mem->cv_eta = ONE;
     return;
   }
 
   /* etaq is the ratio of new to old h at the current order */  
-  etaq = ONE /(SUNRpowerR(BIAS2*dsm,ONE/L) + ADDON);
+  cv_mem->cv_etaq = ONE /(SUNRpowerR(BIAS2*dsm,ONE/cv_mem->cv_L) + ADDON);
   
   /* If no order change, adjust eta and acor in cvSetEta and return */
-  if (qwait != 0) {
-    eta = etaq;
-    qprime = q;
+  if (cv_mem->cv_qwait != 0) {
+    cv_mem->cv_eta = cv_mem->cv_etaq;
+    cv_mem->cv_qprime = cv_mem->cv_q;
     cvSetEta(cv_mem);
     return;
   }
@@ -3051,9 +2989,9 @@ static void cvPrepareNextStep(CVodeMem cv_mem, realtype dsm)
   /* If qwait = 0, consider an order change.   etaqm1 and etaqp1 are 
      the ratios of new to old h at orders q-1 and q+1, respectively.
      cvChooseEta selects the largest; cvSetEta adjusts eta and acor */
-  qwait = 2;
-  etaqm1 = cvComputeEtaqm1(cv_mem);
-  etaqp1 = cvComputeEtaqp1(cv_mem);  
+  cv_mem->cv_qwait = 2;
+  cv_mem->cv_etaqm1 = cvComputeEtaqm1(cv_mem);
+  cv_mem->cv_etaqp1 = cvComputeEtaqp1(cv_mem);  
   cvChooseEta(cv_mem); 
   cvSetEta(cv_mem);
 }
@@ -3069,15 +3007,15 @@ static void cvSetEta(CVodeMem cv_mem)
 {
 
   /* If eta below the threshhold THRESH, reject a change of step size */
-  if (eta < THRESH) {
-    eta = ONE;
-    hprime = h;
+  if (cv_mem->cv_eta < THRESH) {
+    cv_mem->cv_eta = ONE;
+    cv_mem->cv_hprime = cv_mem->cv_h;
   } else {
     /* Limit eta by etamax and hmax, then set hprime */
-    eta = SUNMIN(eta, etamax);
-    eta /= SUNMAX(ONE, SUNRabs(h)*hmax_inv*eta);
-    hprime = h * eta;
-    if (qprime < q) nscon = 0;
+    cv_mem->cv_eta = SUNMIN(cv_mem->cv_eta, cv_mem->cv_etamax);
+    cv_mem->cv_eta /= SUNMAX(ONE, SUNRabs(cv_mem->cv_h)*cv_mem->cv_hmax_inv*cv_mem->cv_eta);
+    cv_mem->cv_hprime = cv_mem->cv_h * cv_mem->cv_eta;
+    if (cv_mem->cv_qprime < cv_mem->cv_q) cv_mem->cv_nscon = 0;
   }
 }
 
@@ -3092,12 +3030,12 @@ static realtype cvComputeEtaqm1(CVodeMem cv_mem)
 {
   realtype ddn;
   
-  etaqm1 = ZERO;
-  if (q > 1) {
-    ddn = N_VWrmsNorm(zn[q], ewt) * tq[1];
-    etaqm1 = ONE/(SUNRpowerR(BIAS1*ddn, ONE/q) + ADDON);
+  cv_mem->cv_etaqm1 = ZERO;
+  if (cv_mem->cv_q > 1) {
+    ddn = N_VWrmsNorm(cv_mem->cv_zn[cv_mem->cv_q], cv_mem->cv_ewt) * cv_mem->cv_tq[1];
+    cv_mem->cv_etaqm1 = ONE/(SUNRpowerR(BIAS1*ddn, ONE/cv_mem->cv_q) + ADDON);
   }
-  return(etaqm1);
+  return(cv_mem->cv_etaqm1);
 }
 
 /*
@@ -3111,15 +3049,17 @@ static realtype cvComputeEtaqp1(CVodeMem cv_mem)
 {
   realtype dup, cquot;
   
-  etaqp1 = ZERO;
-  if (q != qmax) {
-    if (saved_tq5 == ZERO) return(etaqp1);
-    cquot = (tq[5] / saved_tq5) * SUNRpowerI(h/tau[2], L);
-    N_VLinearSum(-cquot, zn[qmax], ONE, acor, tempv);
-    dup = N_VWrmsNorm(tempv, ewt) * tq[3];
-    etaqp1 = ONE / (SUNRpowerR(BIAS3*dup, ONE/(L+1)) + ADDON);
+  cv_mem->cv_etaqp1 = ZERO;
+  if (cv_mem->cv_q != cv_mem->cv_qmax) {
+    if (cv_mem->cv_saved_tq5 == ZERO) return(cv_mem->cv_etaqp1);
+    cquot = (cv_mem->cv_tq[5] / cv_mem->cv_saved_tq5) *
+      SUNRpowerI(cv_mem->cv_h/cv_mem->cv_tau[2], cv_mem->cv_L);
+    N_VLinearSum(-cquot, cv_mem->cv_zn[cv_mem->cv_qmax], ONE,
+                 cv_mem->cv_acor, cv_mem->cv_tempv);
+    dup = N_VWrmsNorm(cv_mem->cv_tempv, cv_mem->cv_ewt) * cv_mem->cv_tq[3];
+    cv_mem->cv_etaqp1 = ONE / (SUNRpowerR(BIAS3*dup, ONE/(cv_mem->cv_L+1)) + ADDON);
   }
-  return(etaqp1);
+  return(cv_mem->cv_etaqp1);
 }
 
 /*
@@ -3138,30 +3078,30 @@ static void cvChooseEta(CVodeMem cv_mem)
 {
   realtype etam;
   
-  etam = SUNMAX(etaqm1, SUNMAX(etaq, etaqp1));
+  etam = SUNMAX(cv_mem->cv_etaqm1, SUNMAX(cv_mem->cv_etaq, cv_mem->cv_etaqp1));
   
   if (etam < THRESH) {
-    eta = ONE;
-    qprime = q;
+    cv_mem->cv_eta = ONE;
+    cv_mem->cv_qprime = cv_mem->cv_q;
     return;
   }
 
-  if (etam == etaq) {
+  if (etam == cv_mem->cv_etaq) {
 
-    eta = etaq;
-    qprime = q;
+    cv_mem->cv_eta = cv_mem->cv_etaq;
+    cv_mem->cv_qprime = cv_mem->cv_q;
 
-  } else if (etam == etaqm1) {
+  } else if (etam == cv_mem->cv_etaqm1) {
 
-    eta = etaqm1;
-    qprime = q - 1;
+    cv_mem->cv_eta = cv_mem->cv_etaqm1;
+    cv_mem->cv_qprime = cv_mem->cv_q - 1;
 
   } else {
 
-    eta = etaqp1;
-    qprime = q + 1;
+    cv_mem->cv_eta = cv_mem->cv_etaqp1;
+    cv_mem->cv_qprime = cv_mem->cv_q + 1;
 
-    if (lmm == CV_BDF) {
+    if (cv_mem->cv_lmm == CV_BDF) {
       /* 
        * Store Delta_n in zn[qmax] to be used in order increase 
        *
@@ -3169,7 +3109,7 @@ static void cvChooseEta(CVodeMem cv_mem)
        * to order q+1, so it represents Delta_n in the ELTE at q+1
        */
 
-      N_VScale(ONE, acor, zn[qmax]);
+      N_VScale(ONE, cv_mem->cv_acor, cv_mem->cv_zn[cv_mem->cv_qmax]);
 
     }
   }
@@ -3195,28 +3135,36 @@ static int cvHandleFailure(CVodeMem cv_mem, int flag)
   /* Depending on flag, print error message and return error flag */
   switch (flag) {
   case CV_ERR_FAILURE:
-    cvProcessError(cv_mem, CV_ERR_FAILURE, "CVODE", "CVode", MSGCV_ERR_FAILS, tn, h);
+    cvProcessError(cv_mem, CV_ERR_FAILURE, "CVODE", "CVode", MSGCV_ERR_FAILS,
+                   cv_mem->cv_tn, cv_mem->cv_h);
     break;
   case CV_CONV_FAILURE:
-    cvProcessError(cv_mem, CV_CONV_FAILURE, "CVODE", "CVode", MSGCV_CONV_FAILS, tn, h);
+    cvProcessError(cv_mem, CV_CONV_FAILURE, "CVODE", "CVode", MSGCV_CONV_FAILS,
+                   cv_mem->cv_tn, cv_mem->cv_h);
     break;
   case CV_LSETUP_FAIL:
-    cvProcessError(cv_mem, CV_LSETUP_FAIL, "CVODE", "CVode", MSGCV_SETUP_FAILED, tn);
+    cvProcessError(cv_mem, CV_LSETUP_FAIL, "CVODE", "CVode", MSGCV_SETUP_FAILED,
+                   cv_mem->cv_tn);
     break;
   case CV_LSOLVE_FAIL:
-    cvProcessError(cv_mem, CV_LSOLVE_FAIL, "CVODE", "CVode", MSGCV_SOLVE_FAILED, tn);
+    cvProcessError(cv_mem, CV_LSOLVE_FAIL, "CVODE", "CVode", MSGCV_SOLVE_FAILED,
+                   cv_mem->cv_tn);
     break;
   case CV_RHSFUNC_FAIL:
-    cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+    cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODE", "CVode", MSGCV_RHSFUNC_FAILED,
+                   cv_mem->cv_tn);
     break;
   case CV_UNREC_RHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_UNREC_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_UNREC, tn);
+    cvProcessError(cv_mem, CV_UNREC_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_UNREC,
+                   cv_mem->cv_tn);
     break;
   case CV_REPTD_RHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_REPTD_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_REPTD, tn);
+    cvProcessError(cv_mem, CV_REPTD_RHSFUNC_ERR, "CVODE", "CVode", MSGCV_RHSFUNC_REPTD,
+                   cv_mem->cv_tn);
     break;
   case CV_RTFUNC_FAIL:
-    cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVode", MSGCV_RTFUNC_FAILED, tn);
+    cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODE", "CVode", MSGCV_RTFUNC_FAILED,
+                   cv_mem->cv_tn);
     break;
   case CV_TOO_CLOSE:
     cvProcessError(cv_mem, CV_TOO_CLOSE, "CVODE", "CVode", MSGCV_TOO_CLOSE);
@@ -3254,45 +3202,48 @@ static void cvBDFStab(CVodeMem cv_mem)
   /* If order is 3 or greater, then save scaled derivative data,
      push old data down in i, then add current values to top.    */
 
-  if (q >= 3) {
+  if (cv_mem->cv_q >= 3) {
     for (k = 1; k <= 3; k++)
       for (i = 5; i >= 2; i--)
-        ssdat[i][k] = ssdat[i-1][k];
+        cv_mem->cv_ssdat[i][k] = cv_mem->cv_ssdat[i-1][k];
     factorial = 1;
-    for (i = 1; i <= q-1; i++) factorial *= i;
-    sq = factorial*q*(q+1)*acnrm/SUNMAX(tq[5],TINY);
-    sqm1 = factorial*q*N_VWrmsNorm(zn[q], ewt);
-    sqm2 = factorial*N_VWrmsNorm(zn[q-1], ewt);
-    ssdat[1][1] = sqm2*sqm2;
-    ssdat[1][2] = sqm1*sqm1;
-    ssdat[1][3] = sq*sq;
+    for (i = 1; i <= cv_mem->cv_q-1; i++) factorial *= i;
+    sq = factorial * cv_mem->cv_q * (cv_mem->cv_q+1) *
+      cv_mem->cv_acnrm / SUNMAX(cv_mem->cv_tq[5],TINY);
+    sqm1 = factorial * cv_mem->cv_q *
+      N_VWrmsNorm(cv_mem->cv_zn[cv_mem->cv_q], cv_mem->cv_ewt);
+    sqm2 = factorial * N_VWrmsNorm(cv_mem->cv_zn[cv_mem->cv_q-1], cv_mem->cv_ewt);
+    cv_mem->cv_ssdat[1][1] = sqm2*sqm2;
+    cv_mem->cv_ssdat[1][2] = sqm1*sqm1;
+    cv_mem->cv_ssdat[1][3] = sq*sq;
   }  
 
 
-  if (qprime >= q) {
+  if (cv_mem->cv_qprime >= cv_mem->cv_q) {
 
     /* If order is 3 or greater, and enough ssdat has been saved,
        nscon >= q+5, then call stability limit detection routine.  */
 
-    if ( (q >= 3) && (nscon >= q+5) ) {
+    if ( (cv_mem->cv_q >= 3) && (cv_mem->cv_nscon >= cv_mem->cv_q+5) ) {
       ldflag = cvSLdet(cv_mem);
       if (ldflag > 3) {
         /* A stability limit violation is indicated by
            a return flag of 4, 5, or 6.
            Reduce new order.                     */
-        qprime = q-1;
-        eta = etaqm1; 
-        eta = SUNMIN(eta,etamax);
-        eta = eta/SUNMAX(ONE,SUNRabs(h)*hmax_inv*eta);
-        hprime = h*eta;
-        nor = nor + 1;
+        cv_mem->cv_qprime = cv_mem->cv_q-1;
+        cv_mem->cv_eta = cv_mem->cv_etaqm1; 
+        cv_mem->cv_eta = SUNMIN(cv_mem->cv_eta,cv_mem->cv_etamax);
+        cv_mem->cv_eta = cv_mem->cv_eta /
+          SUNMAX(ONE,SUNRabs(cv_mem->cv_h)*cv_mem->cv_hmax_inv*cv_mem->cv_eta);
+        cv_mem->cv_hprime = cv_mem->cv_h*cv_mem->cv_eta;
+        cv_mem->cv_nor = cv_mem->cv_nor + 1;
       }
     }
   }
   else {
     /* Otherwise, let order increase happen, and 
        reset stability limit counter, nscon.     */
-    nscon = 0;
+    cv_mem->cv_nscon = 0;
   }
 }
 
@@ -3365,12 +3316,12 @@ static int cvSLdet(CVodeMem cv_mem)
   /* get maxima, minima, and variances, and form quartic coefficients  */
 
   for (k=1; k<=3; k++) {
-    smink = ssdat[1][k];
+    smink = cv_mem->cv_ssdat[1][k];
     smaxk = ZERO;
     
     for (i=1; i<=5; i++) {
-      smink = SUNMIN(smink,ssdat[i][k]);
-      smaxk = SUNMAX(smaxk,ssdat[i][k]);
+      smink = SUNMIN(smink,cv_mem->cv_ssdat[i][k]);
+      smaxk = SUNMAX(smaxk,cv_mem->cv_ssdat[i][k]);
     }
     
     if (smink < TINY*smaxk) {
@@ -3383,22 +3334,26 @@ static int cvSLdet(CVodeMem cv_mem)
     sumrat = ZERO;
     sumrsq = ZERO;
     for (i=1; i<=4; i++) {
-      rat[i][k] = ssdat[i][k]/ssdat[i+1][k];
+      rat[i][k] = cv_mem->cv_ssdat[i][k]/cv_mem->cv_ssdat[i+1][k];
       sumrat = sumrat + rat[i][k];
       sumrsq = sumrsq + rat[i][k]*rat[i][k];
     } 
     rav[k] = FOURTH*sumrat;
     vrat[k] = SUNRabs(FOURTH*sumrsq - rav[k]*rav[k]);
 
-    qc[5][k] = ssdat[1][k]*ssdat[3][k] - ssdat[2][k]*ssdat[2][k];
-    qc[4][k] = ssdat[2][k]*ssdat[3][k] - ssdat[1][k]*ssdat[4][k];
+    qc[5][k] = cv_mem->cv_ssdat[1][k] * cv_mem->cv_ssdat[3][k] -
+      cv_mem->cv_ssdat[2][k] * cv_mem->cv_ssdat[2][k];
+    qc[4][k] = cv_mem->cv_ssdat[2][k] * cv_mem->cv_ssdat[3][k] -
+      cv_mem->cv_ssdat[1][k] * cv_mem->cv_ssdat[4][k];
     qc[3][k] = ZERO;
-    qc[2][k] = ssdat[2][k]*ssdat[5][k] - ssdat[3][k]*ssdat[4][k];
-    qc[1][k] = ssdat[4][k]*ssdat[4][k] - ssdat[3][k]*ssdat[5][k];
+    qc[2][k] = cv_mem->cv_ssdat[2][k] * cv_mem->cv_ssdat[5][k] -
+      cv_mem->cv_ssdat[3][k] * cv_mem->cv_ssdat[4][k];
+    qc[1][k] = cv_mem->cv_ssdat[4][k] * cv_mem->cv_ssdat[4][k] -
+      cv_mem->cv_ssdat[3][k] * cv_mem->cv_ssdat[5][k];
 
-    for (i=1; i<=5; i++) {
+    for (i=1; i<=5; i++) 
       qco[i][k] = qc[i][k];
-    }
+
   }                            /* End of k loop */
   
   /* Isolate normal or nearly-normal matrix case. Three quartic will
@@ -3539,10 +3494,10 @@ static int cvSLdet(CVodeMem cv_mem)
   /* All positive kflag drop to this section  */
   
   for (k=1; k<=3; k++) {
-    rsa = ssdat[1][k];
-    rsb = ssdat[2][k]*rr;
-    rsc = ssdat[3][k]*rr*rr;
-    rsd = ssdat[4][k]*rr*rr*rr;
+    rsa = cv_mem->cv_ssdat[1][k];
+    rsb = cv_mem->cv_ssdat[2][k]*rr;
+    rsc = cv_mem->cv_ssdat[3][k]*rr*rr;
+    rsd = cv_mem->cv_ssdat[4][k]*rr*rr*rr;
     rd1a = rsa - rsb;
     rd1b = rsb - rsc;
     rd1c = rsc - rsd;
@@ -3561,7 +3516,7 @@ static int cvSLdet(CVodeMem cv_mem)
       return(kflag);
     }
     corr1 = (rd2b/cest1)/(rr*rr);
-    sigsq[k] = ssdat[3][k] + corr1;
+    sigsq[k] = cv_mem->cv_ssdat[3][k] + corr1;
   }
   
   if (sigsq[2] < TINY) {
@@ -3571,8 +3526,8 @@ static int cvSLdet(CVodeMem cv_mem)
   
   ratp = sigsq[3]/sigsq[2];
   ratm = sigsq[1]/sigsq[2];
-  qfac1 = FOURTH*(q*q - ONE);
-  qfac2 = TWO/(q - ONE);
+  qfac1 = FOURTH*(cv_mem->cv_q*cv_mem->cv_q - ONE);
+  qfac2 = TWO/(cv_mem->cv_q - ONE);
   bb = ratp*ratm - ONE - qfac1*ratp;
   tem = ONE - qfac2*bb;
   
@@ -3625,39 +3580,43 @@ static int cvRcheck1(CVodeMem cv_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  tlo = tn;
-  ttol = (SUNRabs(tn) + SUNRabs(h))*uround*HUNDRED;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) cv_mem->cv_iroots[i] = 0;
+  cv_mem->cv_tlo = cv_mem->cv_tn;
+  cv_mem->cv_ttol = (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)) *
+    cv_mem->cv_uround*HUNDRED;
 
   /* Evaluate g at initial t and check for zero values. */
-  retval = gfun(tlo, zn[0], glo, user_data);
-  nge = 1;
+  retval = cv_mem->cv_gfun(cv_mem->cv_tlo, cv_mem->cv_zn[0],
+                           cv_mem->cv_glo, cv_mem->cv_user_data);
+  cv_mem->cv_nge = 1;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      gactive[i] = FALSE;
+  zroot = SUNFALSE;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (SUNRabs(cv_mem->cv_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      cv_mem->cv_gactive[i] = SUNFALSE;
     }
   }
   if (!zroot) return(CV_SUCCESS);
 
   /* Some g_i is zero at t0; look at g at t0+(small increment). */
-  hratio = SUNMAX(ttol/SUNRabs(h), PT1);
-  smallh = hratio*h;
-  tplus = tlo + smallh;
-  N_VLinearSum(ONE, zn[0], hratio, zn[1], y);
-  retval = gfun(tplus, y, ghi, user_data);
-  nge++;
+  hratio = SUNMAX(cv_mem->cv_ttol/SUNRabs(cv_mem->cv_h), PT1);
+  smallh = hratio*cv_mem->cv_h;
+  tplus = cv_mem->cv_tlo + smallh;
+  N_VLinearSum(ONE, cv_mem->cv_zn[0], hratio,
+               cv_mem->cv_zn[1], cv_mem->cv_y);
+  retval = cv_mem->cv_gfun(tplus, cv_mem->cv_y,
+                           cv_mem->cv_ghi, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
   /* We check now only the components of g which were exactly 0.0 at t0
    * to see if we can 'activate' them. */
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i] && SUNRabs(ghi[i]) != ZERO) {
-      gactive[i] = TRUE;
-      glo[i] = ghi[i];
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (!cv_mem->cv_gactive[i] && SUNRabs(cv_mem->cv_ghi[i]) != ZERO) {
+      cv_mem->cv_gactive[i] = SUNTRUE;
+      cv_mem->cv_glo[i] = cv_mem->cv_ghi[i];
     }
   }
   return(CV_SUCCESS);
@@ -3690,49 +3649,53 @@ static int cvRcheck2(CVodeMem cv_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  if (irfnd == 0) return(CV_SUCCESS);
+  if (cv_mem->cv_irfnd == 0) return(CV_SUCCESS);
 
-  (void) CVodeGetDky(cv_mem, tlo, 0, y);
-  retval = gfun(tlo, y, glo, user_data);
-  nge++;
+  (void) CVodeGetDky(cv_mem, cv_mem->cv_tlo, 0, cv_mem->cv_y);
+  retval = cv_mem->cv_gfun(cv_mem->cv_tlo, cv_mem->cv_y,
+                           cv_mem->cv_glo, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) cv_mem->cv_iroots[i] = 0;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (!cv_mem->cv_gactive[i]) continue;
+    if (SUNRabs(cv_mem->cv_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      cv_mem->cv_iroots[i] = 1;
     }
   }
   if (!zroot) return(CV_SUCCESS);
 
   /* One or more g_i has a zero at tlo.  Check g at tlo+smallh. */
-  ttol = (SUNRabs(tn) + SUNRabs(h))*uround*HUNDRED;
-  smallh = (h > ZERO) ? ttol : -ttol;
-  tplus = tlo + smallh;
-  if ( (tplus - tn)*h >= ZERO) {
-    hratio = smallh/h;
-    N_VLinearSum(ONE, y, hratio, zn[1], y);
+  cv_mem->cv_ttol = (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)) *
+    cv_mem->cv_uround * HUNDRED;
+  smallh = (cv_mem->cv_h > ZERO) ? cv_mem->cv_ttol : -cv_mem->cv_ttol;
+  tplus = cv_mem->cv_tlo + smallh;
+  if ( (tplus - cv_mem->cv_tn)*cv_mem->cv_h >= ZERO) {
+    hratio = smallh/cv_mem->cv_h;
+    N_VLinearSum(ONE, cv_mem->cv_y, hratio, cv_mem->cv_zn[1], cv_mem->cv_y);
   } else {
-    (void) CVodeGetDky(cv_mem, tplus, 0, y);
+    (void) CVodeGetDky(cv_mem, tplus, 0, cv_mem->cv_y);
   }
-  retval = gfun(tplus, y, ghi, user_data);
-  nge++;
+  retval = cv_mem->cv_gfun(tplus, cv_mem->cv_y,
+                           cv_mem->cv_ghi, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
   /* Check for close roots (error return), for a new zero at tlo+smallh,
   and for a g_i that changed from zero to nonzero. */
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if (iroots[i] == 1) return(CLOSERT);
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (!cv_mem->cv_gactive[i]) continue;
+    if (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) {
+      if (cv_mem->cv_iroots[i] == 1) return(CLOSERT);
+      zroot = SUNTRUE;
+      cv_mem->cv_iroots[i] = 1;
     } else {
-      if (iroots[i] == 1) glo[i] = ghi[i];
+      if (cv_mem->cv_iroots[i] == 1)
+        cv_mem->cv_glo[i] = cv_mem->cv_ghi[i];
     }
   }
   if (zroot) return(RTFOUND);
@@ -3757,39 +3720,43 @@ static int cvRcheck3(CVodeMem cv_mem)
   int i, ier, retval;
 
   /* Set thi = tn or tout, whichever comes first; set y = y(thi). */
-  if (taskc == CV_ONE_STEP) {
-    thi = tn;
-    N_VScale(ONE, zn[0], y);
+  if (cv_mem->cv_taskc == CV_ONE_STEP) {
+    cv_mem->cv_thi = cv_mem->cv_tn;
+    N_VScale(ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
   }
-  if (taskc == CV_NORMAL) {
-    if ( (toutc - tn)*h >= ZERO) {
-      thi = tn; 
-      N_VScale(ONE, zn[0], y);
+  if (cv_mem->cv_taskc == CV_NORMAL) {
+    if ( (cv_mem->cv_toutc - cv_mem->cv_tn)*cv_mem->cv_h >= ZERO) {
+      cv_mem->cv_thi = cv_mem->cv_tn; 
+      N_VScale(ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
     } else {
-      thi = toutc;
-      (void) CVodeGetDky(cv_mem, thi, 0, y);
+      cv_mem->cv_thi = cv_mem->cv_toutc;
+      (void) CVodeGetDky(cv_mem, cv_mem->cv_thi, 0, cv_mem->cv_y);
     }
   }
 
   /* Set ghi = g(thi) and call cvRootfind to search (tlo,thi) for roots. */
-  retval = gfun(thi, y, ghi, user_data);
-  nge++;
+  retval = cv_mem->cv_gfun(cv_mem->cv_thi, cv_mem->cv_y,
+                           cv_mem->cv_ghi, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
-  ttol = (SUNRabs(tn) + SUNRabs(h))*uround*HUNDRED;
+  cv_mem->cv_ttol = (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)) *
+    cv_mem->cv_uround * HUNDRED;
   ier = cvRootfind(cv_mem);
   if (ier == CV_RTFUNC_FAIL) return(CV_RTFUNC_FAIL);
-  for(i=0; i<nrtfn; i++) {
-    if(!gactive[i] && grout[i] != ZERO) gactive[i] = TRUE;
+  for(i=0; i<cv_mem->cv_nrtfn; i++) {
+    if(!cv_mem->cv_gactive[i] && cv_mem->cv_grout[i] != ZERO)
+      cv_mem->cv_gactive[i] = SUNTRUE;
   }
-  tlo = trout;
-  for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+  cv_mem->cv_tlo = cv_mem->cv_trout;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++)
+    cv_mem->cv_glo[i] = cv_mem->cv_grout[i];
 
   /* If no root found, return CV_SUCCESS. */  
   if (ier == CV_SUCCESS) return(CV_SUCCESS);
 
   /* If a root was found, interpolate to get y(trout) and return.  */
-  (void) CVodeGetDky(cv_mem, trout, 0, y);
+  (void) CVodeGetDky(cv_mem, cv_mem->cv_trout, 0, cv_mem->cv_y);
   return(RTFOUND);
 }
 
@@ -3823,10 +3790,10 @@ static int cvRcheck3(CVodeMem cv_mem)
  *
  * gactive  = array specifying whether a component of g should
  *            or should not be monitored. gactive[i] is initially
- *            set to TRUE for all i=0,...,nrtfn-1, but it may be
- *            reset to FALSE if at the first step g[i] is 0.0
+ *            set to SUNTRUE for all i=0,...,nrtfn-1, but it may be
+ *            reset to SUNFALSE if at the first step g[i] is 0.0
  *            both at the I.C. and at a small perturbation of them.
- *            gactive[i] is then set back on TRUE only after the 
+ *            gactive[i] is then set back on SUNTRUE only after the 
  *            corresponding g function moves away from 0.0.
  *
  * nge      = cumulative counter for gfun calls.
@@ -3880,19 +3847,20 @@ static int cvRootfind(CVodeMem cv_mem)
 
   /* First check for change in sign in ghi or for a zero in ghi. */
   maxfrac = ZERO;
-  zroot = FALSE;
-  sgnchg = FALSE;
-  for (i = 0;  i < nrtfn; i++) {
-    if(!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if(rootdir[i]*glo[i] <= ZERO) {
-        zroot = TRUE;
+  zroot = SUNFALSE;
+  sgnchg = SUNFALSE;
+  for (i = 0;  i < cv_mem->cv_nrtfn; i++) {
+    if(!cv_mem->cv_gactive[i]) continue;
+    if (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) {
+      if(cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) {
+        zroot = SUNTRUE;
       }
     } else {
-      if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-        gfrac = SUNRabs(ghi[i]/(ghi[i] - glo[i]));
+      if ( (cv_mem->cv_glo[i]*cv_mem->cv_ghi[i] < ZERO) &&
+           (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) ) {
+        gfrac = SUNRabs(cv_mem->cv_ghi[i]/(cv_mem->cv_ghi[i] - cv_mem->cv_glo[i]));
         if (gfrac > maxfrac) {
-          sgnchg = TRUE;
+          sgnchg = SUNTRUE;
           maxfrac = gfrac;
           imax = i;
         }
@@ -3903,14 +3871,15 @@ static int cvRootfind(CVodeMem cv_mem)
   /* If no sign change was found, reset trout and grout.  Then return
      CV_SUCCESS if no zero was found, or set iroots and return RTFOUND.  */ 
   if (!sgnchg) {
-    trout = thi;
-    for (i = 0; i < nrtfn; i++) grout[i] = ghi[i];
+    cv_mem->cv_trout = cv_mem->cv_thi;
+    for (i = 0; i < cv_mem->cv_nrtfn; i++) cv_mem->cv_grout[i] = cv_mem->cv_ghi[i];
     if (!zroot) return(CV_SUCCESS);
-    for (i = 0; i < nrtfn; i++) {
-      iroots[i] = 0;
-      if(!gactive[i]) continue;
-      if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-        iroots[i] = glo[i] > 0 ? -1:1;
+    for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+      cv_mem->cv_iroots[i] = 0;
+      if(!cv_mem->cv_gactive[i]) continue;
+      if ( (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) &&
+           (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) )
+        cv_mem->cv_iroots[i] = cv_mem->cv_glo[i] > 0 ? -1 : 1;
     }
     return(RTFOUND);
   }
@@ -3921,10 +3890,10 @@ static int cvRootfind(CVodeMem cv_mem)
   /* A sign change was found.  Loop to locate nearest root. */
 
   side = 0;  sideprev = -1;
-  loop {                                    /* Looping point */
+  for(;;) {                                    /* Looping point */
 
     /* If interval size is already less than tolerance ttol, break. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo) <= cv_mem->cv_ttol) break;
 
     /* Set weight alph.
        On the first two passes, set alph = 1.  Thereafter, reset alph
@@ -3945,38 +3914,41 @@ static int cvRootfind(CVodeMem cv_mem)
     /* Set next root approximation tmid and get g(tmid).
        If tmid is too close to tlo or thi, adjust it inward,
        by a fractional distance that is between 0.1 and 0.5.  */
-    tmid = thi - (thi - tlo)*ghi[imax]/(ghi[imax] - alph*glo[imax]);
-    if (SUNRabs(tmid - tlo) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    tmid = cv_mem->cv_thi - (cv_mem->cv_thi - cv_mem->cv_tlo) *
+      cv_mem->cv_ghi[imax] / (cv_mem->cv_ghi[imax] - alph*cv_mem->cv_glo[imax]);
+    if (SUNRabs(tmid - cv_mem->cv_tlo) < HALF*cv_mem->cv_ttol) {
+      fracint = SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo)/cv_mem->cv_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = tlo + fracsub*(thi - tlo);
+      tmid = cv_mem->cv_tlo + fracsub*(cv_mem->cv_thi - cv_mem->cv_tlo);
     }
-    if (SUNRabs(thi - tmid) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    if (SUNRabs(cv_mem->cv_thi - tmid) < HALF*cv_mem->cv_ttol) {
+      fracint = SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo)/cv_mem->cv_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = thi - fracsub*(thi - tlo);
+      tmid = cv_mem->cv_thi - fracsub*(cv_mem->cv_thi - cv_mem->cv_tlo);
     }
 
-    (void) CVodeGetDky(cv_mem, tmid, 0, y);
-    retval = gfun(tmid, y, grout, user_data);
-    nge++;
+    (void) CVodeGetDky(cv_mem, tmid, 0, cv_mem->cv_y);
+    retval = cv_mem->cv_gfun(tmid, cv_mem->cv_y, cv_mem->cv_grout, 
+                             cv_mem->cv_user_data);
+    cv_mem->cv_nge++;
     if (retval != 0) return(CV_RTFUNC_FAIL);
 
     /* Check to see in which subinterval g changes sign, and reset imax.
        Set side = 1 if sign change is on low side, or 2 if on high side.  */  
     maxfrac = ZERO;
-    zroot = FALSE;
-    sgnchg = FALSE;
+    zroot = SUNFALSE;
+    sgnchg = SUNFALSE;
     sideprev = side;
-    for (i = 0;  i < nrtfn; i++) {
-      if(!gactive[i]) continue;
-      if (SUNRabs(grout[i]) == ZERO) {
-        if(rootdir[i]*glo[i] <= ZERO) zroot = TRUE;
+    for (i = 0;  i < cv_mem->cv_nrtfn; i++) {
+      if(!cv_mem->cv_gactive[i]) continue;
+      if (SUNRabs(cv_mem->cv_grout[i]) == ZERO) {
+        if(cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) zroot = SUNTRUE;
       } else {
-        if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-          gfrac = SUNRabs(grout[i]/(grout[i] - glo[i]));
+        if ( (cv_mem->cv_glo[i]*cv_mem->cv_grout[i] < ZERO) &&
+             (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) ) {
+          gfrac = SUNRabs(cv_mem->cv_grout[i]/(cv_mem->cv_grout[i] - cv_mem->cv_glo[i]));
           if (gfrac > maxfrac) {
-            sgnchg = TRUE;
+            sgnchg = SUNTRUE;
             maxfrac = gfrac;
             imax = i;
           }
@@ -3985,41 +3957,46 @@ static int cvRootfind(CVodeMem cv_mem)
     }
     if (sgnchg) {
       /* Sign change found in (tlo,tmid); replace thi with tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      cv_mem->cv_thi = tmid;
+      for (i = 0; i < cv_mem->cv_nrtfn; i++)
+        cv_mem->cv_ghi[i] = cv_mem->cv_grout[i];
       side = 1;
       /* Stop at root thi if converged; otherwise loop. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo) <= cv_mem->cv_ttol) break;
       continue;  /* Return to looping point. */
     }
 
     if (zroot) {
       /* No sign change in (tlo,tmid), but g = 0 at tmid; return root tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      cv_mem->cv_thi = tmid;
+      for (i = 0; i < cv_mem->cv_nrtfn; i++)
+        cv_mem->cv_ghi[i] = cv_mem->cv_grout[i];
       break;
     }
 
     /* No sign change in (tlo,tmid), and no zero at tmid.
        Sign change must be in (tmid,thi).  Replace tlo with tmid. */
-    tlo = tmid;
-    for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+    cv_mem->cv_tlo = tmid;
+    for (i = 0; i < cv_mem->cv_nrtfn; i++)
+      cv_mem->cv_glo[i] = cv_mem->cv_grout[i];
     side = 2;
     /* Stop at root thi if converged; otherwise loop back. */
-    if (SUNRabs(thi - tlo) <= ttol) break;
+    if (SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo) <= cv_mem->cv_ttol) break;
 
   } /* End of root-search loop */
 
   /* Reset trout and grout, set iroots, and return RTFOUND. */
-  trout = thi;
-  for (i = 0; i < nrtfn; i++) {
-    grout[i] = ghi[i];
-    iroots[i] = 0;
-    if(!gactive[i]) continue;
-    if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-      iroots[i] = glo[i] > 0 ? -1:1;
-    if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) 
-      iroots[i] = glo[i] > 0 ? -1:1;
+  cv_mem->cv_trout = cv_mem->cv_thi;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    cv_mem->cv_grout[i] = cv_mem->cv_ghi[i];
+    cv_mem->cv_iroots[i] = 0;
+    if(!cv_mem->cv_gactive[i]) continue;
+    if ( (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) &&
+         (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) )
+      cv_mem->cv_iroots[i] = cv_mem->cv_glo[i] > 0 ? -1 : 1;
+    if ( (cv_mem->cv_glo[i]*cv_mem->cv_ghi[i] < ZERO) &&
+         (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) ) 
+      cv_mem->cv_iroots[i] = cv_mem->cv_glo[i] > 0 ? -1 : 1;
   }
   return(RTFOUND);
 }
@@ -4057,7 +4034,7 @@ int cvEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
   cv_mem = (CVodeMem) data;
 
-  switch(itol) {
+  switch(cv_mem->cv_itol) {
   case CV_SS: 
     flag = cvEwtSetSS(cv_mem, ycur, weight);
     break;
@@ -4080,11 +4057,11 @@ int cvEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
 static int cvEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv);
-  N_VScale(reltol, tempv, tempv);
-  N_VAddConst(tempv, Sabstol, tempv);
-  if (N_VMin(tempv) <= ZERO) return(-1);
-  N_VInv(tempv, weight);
+  N_VAbs(ycur, cv_mem->cv_tempv);
+  N_VScale(cv_mem->cv_reltol, cv_mem->cv_tempv, cv_mem->cv_tempv);
+  N_VAddConst(cv_mem->cv_tempv, cv_mem->cv_Sabstol, cv_mem->cv_tempv);
+  if (N_VMin(cv_mem->cv_tempv) <= ZERO) return(-1);
+  N_VInv(cv_mem->cv_tempv, weight);
   return(0);
 }
 
@@ -4099,10 +4076,11 @@ static int cvEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight)
 
 static int cvEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv);
-  N_VLinearSum(reltol, tempv, ONE, Vabstol, tempv);
-  if (N_VMin(tempv) <= ZERO) return(-1);
-  N_VInv(tempv, weight);
+  N_VAbs(ycur, cv_mem->cv_tempv);
+  N_VLinearSum(cv_mem->cv_reltol, cv_mem->cv_tempv, ONE,
+               cv_mem->cv_Vabstol, cv_mem->cv_tempv);
+  if (N_VMin(cv_mem->cv_tempv) <= ZERO) return(-1);
+  N_VInv(cv_mem->cv_tempv, weight);
   return(0);
 }
 
@@ -4119,9 +4097,6 @@ static int cvEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight)
  *   pointed to by cv_ehfun.
  */
 
-#define ehfun    (cv_mem->cv_ehfun)
-#define eh_data  (cv_mem->cv_eh_data)
-
 void cvProcessError(CVodeMem cv_mem, 
                     int error_code, const char *module, const char *fname, 
                     const char *msgfmt, ...)
@@ -4145,7 +4120,7 @@ void cvProcessError(CVodeMem cv_mem,
 #endif
 
   } else {                 /* We can call ehfun */
-    ehfun(error_code, module, fname, msg, eh_data);
+    cv_mem->cv_ehfun(error_code, module, fname, msg, cv_mem->cv_eh_data);
   }
 
   /* Finalize argument processing */
@@ -4159,8 +4134,6 @@ void cvProcessError(CVodeMem cv_mem,
  * It sends the error message to the stream pointed to by cv_errfp.
  */
 
-#define errfp    (cv_mem->cv_errfp)
-
 void cvErrHandler(int error_code, const char *module,
                   const char *function, char *msg, void *data)
 {
@@ -4177,9 +4150,9 @@ void cvErrHandler(int error_code, const char *module,
     sprintf(err_type,"ERROR");
 
 #ifndef NO_FPRINTF_OUTPUT
-  if (errfp!=NULL) {
-    fprintf(errfp,"\n[%s %s]  %s\n",module,err_type,function);
-    fprintf(errfp,"  %s\n\n",msg);
+  if (cv_mem->cv_errfp!=NULL) {
+    fprintf(cv_mem->cv_errfp,"\n[%s %s]  %s\n",module,err_type,function);
+    fprintf(cv_mem->cv_errfp,"  %s\n\n",msg);
   }
 #endif
 
diff --git a/src/cvode/cvode_band.c b/src/cvode/cvode_band.c
deleted file mode 100644
index a4913d8..0000000
--- a/src/cvode/cvode_band.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVBAND linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvode/cvode_band.h>
-#include "cvode_direct_impl.h"
-#include "cvode_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* CVBAND linit, lsetup, lsolve, and lfree routines */
-
-static int cvBandInit(CVodeMem cv_mem);
-
-static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                       N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                       N_Vector vtemp2, N_Vector vtemp3);
-
-static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                       N_Vector ycur, N_Vector fcur);
-
-static int cvBandFree(CVodeMem cv_mem);
-
-/* Readability Replacements */
-
-#define lmm       (cv_mem->cv_lmm)
-#define f         (cv_mem->cv_f)
-#define nst       (cv_mem->cv_nst)
-#define tn        (cv_mem->cv_tn)
-#define h         (cv_mem->cv_h)
-#define gamma     (cv_mem->cv_gamma)
-#define gammap    (cv_mem->cv_gammap)
-#define gamrat    (cv_mem->cv_gamrat)
-#define ewt       (cv_mem->cv_ewt)
-#define nfe       (cv_mem->cv_nfe)
-#define linit     (cv_mem->cv_linit)
-#define lsetup    (cv_mem->cv_lsetup)
-#define lsolve    (cv_mem->cv_lsolve)
-#define lfree     (cv_mem->cv_lfree)
-#define lmem      (cv_mem->cv_lmem)
-#define vec_tmpl      (cv_mem->cv_tempv)
-#define setupNonNull  (cv_mem->cv_setupNonNull)
-
-#define mtype      (cvdls_mem->d_type)
-#define n          (cvdls_mem->d_n)
-#define jacDQ      (cvdls_mem->d_jacDQ)
-#define jac        (cvdls_mem->d_bjac)
-#define M          (cvdls_mem->d_M)
-#define mu         (cvdls_mem->d_mu)
-#define ml         (cvdls_mem->d_ml)
-#define smu        (cvdls_mem->d_smu)
-#define lpivots    (cvdls_mem->d_lpivots)
-#define savedJ     (cvdls_mem->d_savedJ)
-#define nstlj      (cvdls_mem->d_nstlj)
-#define nje        (cvdls_mem->d_nje)
-#define nfeDQ       (cvdls_mem->d_nfeDQ)
-#define J_data     (cvdls_mem->d_J_data)
-#define last_flag  (cvdls_mem->d_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * CVBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module.  CVBand first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
- * to be cvBandInit, cvBandSetup, cvBandSolve, and cvBandFree,
- * respectively.  It allocates memory for a structure of type
- * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure.  It sets setupNonNull in (*cvode_mem) to be
- * TRUE, d_mu to be mupper, d_ml to be mlower, and the d_jac field to be 
- * cvDlsBandDQJac.
- * Finally, it allocates memory for M, savedJ, and pivot.  The CVBand
- * return value is SUCCESS = 0, LMEM_FAIL = -1, or LIN_ILL_INPUT = -2.
- *
- * NOTE: The band linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-                  
-int CVBand(void *cvode_mem, long int N, long int mupper, long int mlower)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVBAND", "CVBand", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVBAND", "CVBand", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */  
-  linit  = cvBandInit;
-  lsetup = cvBandSetup;
-  lsolve = cvBandSolve;
-  lfree  = cvBandFree;
-  
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-  
-  /* Initialize Jacobian-related data */
-  jacDQ = TRUE;
-  jac = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-
-  cvDlsInitializeCounters(cvdls_mem);
-
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = N;
-
-  /* Load half-bandwiths in cvdls_mem */
-  ml = mlower;
-  mu = mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVBAND", "CVBand", MSGD_BAD_SIZES);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = SUNMIN(N-1, mu + ml);
-
-  /* Allocate memory for M, savedJ, and pivot arrays */
-  M = NULL;
-  M = NewBandMat(N, mu, ml, smu);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NULL;
-  savedJ = NewBandMat(N, mu, ml, mu);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  lpivots = NULL;
-  lpivots = NewLintArray(N);
-  if (lpivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVBAND", "CVBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyMat(savedJ);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the band
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvBandInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  cvDlsInitializeCounters(cvdls_mem);
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    jac = cvDlsBandDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the band linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy.  In any case, it constructs the Newton matrix 
- * M = I - gamma*J, updates counters, and calls the band LU 
- * factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                       N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                       N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  long int ier;
-  CVDlsMem cvdls_mem;
-  int retval;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    BandCopy(savedJ, M, mu, ml);
-
-  } else {
-
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M); 
-
-    retval = jac(n, mu, ml, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVBAND", "cvBandSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    BandCopy(M, savedJ, mu, ml);
-
-  }
-  
-  /* Scale and add I to get M = I - gamma*J */
-  BandScale(-gamma, M);
-  AddIdentity(M);
-
-  /* Do LU factorization of M */
-  ier = BandGBTRF(M, lpivots);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  if (ier > 0) {
-    last_flag = ier;
-    return(1);
-  }
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandSolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the band linear solver
- * by calling the band backsolve routine.  The return value is 0.
- * -----------------------------------------------------------------
- */
-
-static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                       N_Vector ycur, N_Vector fcur)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  bd = N_VGetArrayPointer(b);
-
-  BandGBTRS(M, lpivots, bd);
-
-  /* If CV_BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the band linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvBandFree(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  DestroyMat(M);
-  DestroyMat(savedJ);
-  DestroyArray(lpivots);
-  free(cvdls_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
diff --git a/src/cvode/cvode_bandpre.c b/src/cvode/cvode_bandpre.c
index 661e0dd..ed027ec 100644
--- a/src/cvode/cvode_bandpre.c
+++ b/src/cvode/cvode_bandpre.c
@@ -1,24 +1,26 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
  *                and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This file contains implementations of the banded difference
  * quotient Jacobian-based preconditioner and solver routines for
- * use with the CVSPILS linear solvers..
+ * use with the CVSPILS linear solver interface.
  * -----------------------------------------------------------------
  */
 
@@ -28,85 +30,74 @@
 #include "cvode_impl.h"
 #include "cvode_bandpre_impl.h"
 #include "cvode_spils_impl.h"
-
-#include <cvode/cvode_sptfqmr.h>
-#include <cvode/cvode_spbcgs.h>
-#include <cvode/cvode_spgmr.h>
-
 #include <sundials/sundials_math.h>
 
 #define MIN_INC_MULT RCONST(1000.0)
-
 #define ZERO         RCONST(0.0)
 #define ONE          RCONST(1.0)
 
 /* Prototypes of CVBandPrecSetup and CVBandPrecSolve */
-  
 static int CVBandPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                            booleantype jok, booleantype *jcurPtr, 
-                           realtype gamma, void *bp_data,
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
+                           realtype gamma, void *bp_data);
 static int CVBandPrecSolve(realtype t, N_Vector y, N_Vector fy, 
                            N_Vector r, N_Vector z, 
                            realtype gamma, realtype delta,
-                           int lr, void *bp_data, N_Vector tmp);
+                           int lr, void *bp_data);
 
 /* Prototype for CVBandPrecFree */
-
 static int CVBandPrecFree(CVodeMem cv_mem);
 
 /* Prototype for difference quotient Jacobian calculation routine */
-
-static int CVBandPDQJac(CVBandPrecData pdata,
-                        realtype t, N_Vector y, N_Vector fy, 
-                        N_Vector ftemp, N_Vector ytemp);
-
-/* Redability replacements */
-
-#define vec_tmpl (cv_mem->cv_tempv)
-
-/*
- * -----------------------------------------------------------------
- * Initialization, Free, and Get Functions
- * NOTE: The band linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVBandPrecInit will
- *       first test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml)
+static int CVBandPDQJac(CVBandPrecData pdata, realtype t, N_Vector y, 
+                        N_Vector fy, N_Vector ftemp, N_Vector ytemp);
+
+
+/*-----------------------------------------------------------------
+  Initialization, Free, and Get Functions
+  NOTE: The band linear solver assumes a serial/OpenMP/Pthreads 
+        implementation of the NVECTOR package. Therefore, 
+        CVBandPrecInit will first test for a compatible N_Vector 
+        internal representation by checking that the function 
+        N_VGetArrayPointer exists.
+  -----------------------------------------------------------------*/
+int CVBandPrecInit(void *cvode_mem, sunindextype N,
+                   sunindextype mu, sunindextype ml)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBandPrecData pdata;
-  long int mup, mlp, storagemu;
+  sunindextype mup, mlp, storagemu;
   int flag;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been attached */
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE",
+                   "CVBandPrecInit", MSGBP_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  /* Test if the NVECTOR package is compatible with the BAND preconditioner */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE", "CVBandPrecInit", MSGBP_BAD_NVECTOR);
+  /* Test compatibility of NVECTOR package with the BAND preconditioner */
+  if(cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE",
+                   "CVBandPrecInit", MSGBP_BAD_NVECTOR);
     return(CVSPILS_ILL_INPUT);
   }
 
+  /* Allocate data memory */
   pdata = NULL;
-  pdata = (CVBandPrecData) malloc(sizeof *pdata);  /* Allocate data memory */
+  pdata = (CVBandPrecData) malloc(sizeof *pdata);
   if (pdata == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
@@ -121,89 +112,154 @@ int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml)
 
   /* Allocate memory for saved banded Jacobian approximation. */
   pdata->savedJ = NULL;
-  pdata->savedJ = NewBandMat(N, mup, mlp, mup);
+  pdata->savedJ = SUNBandMatrix(N, mup, mlp, mup);
   if (pdata->savedJ == NULL) {
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
   /* Allocate memory for banded preconditioner. */
   storagemu = SUNMIN(N-1, mup+mlp);
   pdata->savedP = NULL;
-  pdata->savedP = NewBandMat(N, mup, mlp, storagemu);
+  pdata->savedP = SUNBandMatrix(N, mup, mlp, storagemu);
   if (pdata->savedP == NULL) {
-    DestroyMat(pdata->savedJ);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
-  /* Allocate memory for pivot array. */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(N);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->savedP);
-    DestroyMat(pdata->savedJ);
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(cv_mem->cv_tempv, pdata->savedP);
+  if (pdata->LS == NULL) {
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+
+  /* allocate memory for temporary N_Vectors */
+  pdata->tmp1 = NULL;
+  pdata->tmp1 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp1 == NULL) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", 
+                    "CVBandPrecInit", MSGBP_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp2 = NULL;
+  pdata->tmp2 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp2 == NULL) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    N_VDestroy(pdata->tmp1);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", 
+                    "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
-  /* make sure s_P_data is free from any previous allocations */
-  if (cvspils_mem->s_pfree != NULL) {
-    cvspils_mem->s_pfree(cv_mem);
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVBANDPRE", 
+                    "CVBandPrecInit", MSGBP_SUNLS_FAIL);
+    return(CVSPILS_SUNLS_FAIL);
   }
+  
+  /* make sure P_data is free from any previous allocations */
+  if (cvspils_mem->pfree)
+    cvspils_mem->pfree(cv_mem);
 
   /* Point to the new P_data field in the SPILS memory */
-  cvspils_mem->s_P_data = pdata;
+  cvspils_mem->P_data = pdata;
 
   /* Attach the pfree function */
-  cvspils_mem->s_pfree = CVBandPrecFree;
+  cvspils_mem->pfree = CVBandPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = CVSpilsSetPreconditioner(cvode_mem, CVBandPrecSetup, CVBandPrecSolve);
-
+  flag = CVSpilsSetPreconditioner(cvode_mem,
+                                  CVBandPrecSetup,
+                                  CVBandPrecSolve);
   return(flag);
 }
 
-int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwBP, long int *leniwBP)
+
+int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwBP, 
+                            long int *leniwBP)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBandPrecData pdata;
-  long int N, ml, mu, smu;
-
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
   
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE",
+                   "CVBandPrecGetWorkSpace", MSGBP_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE",
+                   "CVBandPrecGetWorkSpace", MSGBP_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE",
+                   "CVBandPrecGetWorkSpace", MSGBP_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBandPrecData) cvspils_mem->s_P_data;
-
-  N   = pdata->N;
-  mu  = pdata->mu;
-  ml  = pdata->ml;
-  smu = SUNMIN( N-1, mu + ml);
-
-  *leniwBP = pdata->N;
-  *lenrwBP = N * ( 2*ml + smu + mu + 2 );
+  pdata = (CVBandPrecData) cvspils_mem->P_data;
+
+  /* sum space requirements for all objects in pdata */
+  *leniwBP = 4;
+  *lenrwBP = 0;
+  if (cv_mem->cv_tempv->ops->nvspace) {
+    N_VSpace(cv_mem->cv_tempv, &lrw1, &liw1);
+    *leniwBP += 2*liw1;
+    *lenrwBP += 2*lrw1;
+  }
+  if (pdata->savedJ->ops->space) {
+    flag = SUNMatSpace(pdata->savedJ, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
+  if (pdata->savedP->ops->space) {
+    flag = SUNMatSpace(pdata->savedP, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
 
   return(CVSPILS_SUCCESS);
 }
 
+
 int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP)
 {
   CVodeMem cv_mem;
@@ -211,178 +267,181 @@ int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP)
   CVBandPrecData pdata;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE",
+                   "CVBandPrecGetNumRhsEvals", MSGBP_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE",
+                   "CVBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE",
+                   "CVBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBandPrecData) cvspils_mem->P_data;
 
   *nfevalsBP = pdata->nfeBP;
 
   return(CVSPILS_SUCCESS);
 }
 
-/* Readability Replacements */
-
-#define N       (pdata->N)
-#define mu      (pdata->mu)
-#define ml      (pdata->ml)
-#define lpivots (pdata->lpivots)
-#define savedJ  (pdata->savedJ)
-#define savedP  (pdata->savedP)
-#define nfeBP   (pdata->nfeBP)
-
-/*
- * -----------------------------------------------------------------
- * CVBandPrecSetup
- * -----------------------------------------------------------------
- * Together CVBandPrecSetup and CVBandPrecSolve use a banded
- * difference quotient Jacobian to create a preconditioner.
- * CVBandPrecSetup calculates a new J, if necessary, then
- * calculates P = I - gamma*J, and does an LU factorization of P.
- *
- * The parameters of CVBandPrecSetup are as follows:
- *
- * t       is the current value of the independent variable.
- *
- * y       is the current value of the dependent variable vector,
- *         namely the predicted value of y(t).
- *
- * fy      is the vector f(t,y).
- *
- * jok     is an input flag indicating whether Jacobian-related
- *         data needs to be recomputed, as follows:
- *           jok == FALSE means recompute Jacobian-related data
- *                  from scratch.
- *           jok == TRUE means that Jacobian data from the
- *                  previous PrecSetup call will be reused
- *                  (with the current value of gamma).
- *         A CVBandPrecSetup call with jok == TRUE should only
- *         occur after a call with jok == FALSE.
- *
- * *jcurPtr is a pointer to an output integer flag which is
- *          set by CVBandPrecond as follows:
- *            *jcurPtr = TRUE if Jacobian data was recomputed.
- *            *jcurPtr = FALSE if Jacobian data was not recomputed,
- *                       but saved data was reused.
- *
- * gamma   is the scalar appearing in the Newton matrix.
- *
- * bp_data is a pointer to preconditoner data (set by CVBandPrecInit)
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated
- *           for vectors of length N for work space. This
- *           routine uses only tmp1 and tmp2.
- *
- * The value to be returned by the CVBandPrecSetup function is
- *   0  if successful, or
- *   1  if the band factorization failed.
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  CVBandPrecSetup
+  -----------------------------------------------------------------
+  Together CVBandPrecSetup and CVBandPrecSolve use a banded
+  difference quotient Jacobian to create a preconditioner.
+  CVBandPrecSetup calculates a new J, if necessary, then
+  calculates P = I - gamma*J, and does an LU factorization of P.
+ 
+  The parameters of CVBandPrecSetup are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+          namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  jok     is an input flag indicating whether Jacobian-related
+          data needs to be recomputed, as follows:
+            jok == SUNFALSE means recompute Jacobian-related data
+                   from scratch.
+            jok == SUNTRUE means that Jacobian data from the
+                   previous PrecSetup call will be reused
+                   (with the current value of gamma).
+          A CVBandPrecSetup call with jok == SUNTRUE should only
+          occur after a call with jok == SUNFALSE.
+ 
+  *jcurPtr is a pointer to an output integer flag which is
+           set by CVBandPrecSetup as follows:
+             *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+             *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
+                        but saved data was reused.
+ 
+  gamma   is the scalar appearing in the Newton matrix.
+ 
+  bp_data is a pointer to preconditoner data (set by CVBandPrecInit)
+ 
+  The value to be returned by the CVBandPrecSetup function is
+    0  if successful, or
+    1  if the band factorization failed.
+  -----------------------------------------------------------------*/
 static int CVBandPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                            booleantype jok, booleantype *jcurPtr, 
-                           realtype gamma, void *bp_data,
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+                           realtype gamma, void *bp_data)
 {
   CVBandPrecData pdata;
   CVodeMem cv_mem;
   int retval;
-  long int ier;
+  sunindextype ier;
 
   /* Assume matrix and lpivots have already been allocated. */
   pdata = (CVBandPrecData) bp_data;
-
   cv_mem = (CVodeMem) pdata->cvode_mem;
 
   if (jok) {
 
-    /* If jok = TRUE, use saved copy of J. */
-    *jcurPtr = FALSE;
-    BandCopy(savedJ, savedP, mu, ml);
+    /* If jok = SUNTRUE, use saved copy of J. */
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "CVBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   } else {
 
-    /* If jok = FALSE, call CVBandPDQJac for new J value. */
-    *jcurPtr = TRUE;
-    SetToZero(savedJ);
+    /* If jok = SUNFALSE, call CVBandPDQJac for new J value. */
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(pdata->savedJ);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "CVBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    retval = CVBandPDQJac(pdata, t, y, fy, tmp1, tmp2);
+    retval = CVBandPDQJac(pdata, t, y, fy, 
+                           pdata->tmp1, pdata->tmp2);
     if (retval < 0) {
-      cvProcessError(cv_mem, -1, "CVBANDPRE", "CVBandPrecSetup", MSGBP_RHSFUNC_FAILED);
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "CVBandPrecSetup", MSGBP_RHSFUNC_FAILED);
       return(-1);
     }
     if (retval > 0) {
       return(1);
     }
 
-    BandCopy(savedJ, savedP, mu, ml);
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "CVBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   }
   
-  /* Scale and add I to get savedP = I - gamma*J. */
-  BandScale(-gamma, savedP);
-  AddIdentity(savedP);
- 
-  /* Do LU factorization of matrix. */
-  ier = BandGBTRF(savedP, lpivots);
- 
-  /* Return 0 if the LU was complete; otherwise return 1. */
-  if (ier > 0) return(1);
-  return(0);
+  /* Scale and add identity to get savedP = I - gamma*J. */
+  retval = SUNMatScaleAddI(-gamma, pdata->savedP);
+  if (retval) {
+    cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                   "CVBandPrecSetup", MSGBP_SUNMAT_FAIL);
+    return(-1);
+  }
+
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->savedP);
+  return(ier);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVBandPrecSolve
- * -----------------------------------------------------------------
- * CVBandPrecSolve solves a linear system P z = r, where P is the
- * matrix computed by CVBandPrecond.
- *
- * The parameters of CVBandPrecSolve used here are as follows:
- *
- * r is the right-hand side vector of the linear system.
- *
- * bp_data is a pointer to preconditoner data (set by CVBandPrecInit)
- *
- * z is the output vector computed by CVBandPrecSolve.
- *
- * The value returned by the CVBandPrecSolve function is always 0,
- * indicating success.
- * -----------------------------------------------------------------
- */ 
 
+/*-----------------------------------------------------------------
+  CVBandPrecSolve
+  -----------------------------------------------------------------
+  CVBandPrecSolve solves a linear system P z = r, where P is the
+  matrix computed by CVBandPrecond.
+ 
+  The parameters of CVBandPrecSolve used here are as follows:
+ 
+  r is the right-hand side vector of the linear system.
+ 
+  bp_data is a pointer to preconditoner data (set by CVBandPrecInit)
+ 
+  z is the output vector computed by CVBandPrecSolve.
+ 
+  The value returned by the CVBandPrecSolve function is always 0,
+  indicating success.
+  -----------------------------------------------------------------*/ 
 static int CVBandPrecSolve(realtype t, N_Vector y, N_Vector fy, 
-                           N_Vector r, N_Vector z, 
-                           realtype gamma, realtype delta,
-                           int lr, void *bp_data, N_Vector tmp)
+                           N_Vector r, N_Vector z, realtype gamma, 
+                           realtype delta, int lr, void *bp_data)
 {
   CVBandPrecData pdata;
-  realtype *zd;
+  int retval;
 
   /* Assume matrix and lpivots have already been allocated. */
   pdata = (CVBandPrecData) bp_data;
 
-  /* Copy r to z. */
-  N_VScale(ONE, r, z);
-
-  /* Do band backsolve on the vector z. */
-  zd = N_VGetArrayPointer(z);
-
-  BandGBTRS(savedP, lpivots, zd);
-
-  return(0);
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->savedP, z, r, ZERO);
+  return(retval);
 }
 
 
@@ -394,12 +453,14 @@ static int CVBandPrecFree(CVodeMem cv_mem)
   if (cv_mem->cv_lmem == NULL) return(0);
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
   
-  if (cvspils_mem->s_P_data == NULL) return(0);
-  pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+  if (cvspils_mem->P_data == NULL) return(0);
+  pdata = (CVBandPrecData) cvspils_mem->P_data;
 
-  DestroyMat(savedJ);
-  DestroyMat(savedP);
-  DestroyArray(lpivots);
+  SUNLinSolFree(pdata->LS);
+  SUNMatDestroy(pdata->savedP);
+  SUNMatDestroy(pdata->savedJ);
+  N_VDestroy(pdata->tmp1);
+  N_VDestroy(pdata->tmp2);
 
   free(pdata);
   pdata = NULL;
@@ -407,39 +468,31 @@ static int CVBandPrecFree(CVodeMem cv_mem)
   return(0);
 }
 
-#define ewt       (cv_mem->cv_ewt)
-#define uround    (cv_mem->cv_uround)
-#define h         (cv_mem->cv_h)
-#define f         (cv_mem->cv_f)
-#define user_data (cv_mem->cv_user_data)
 
-/*
- * -----------------------------------------------------------------
- * CVBandPDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation to
- * the Jacobian of f(t,y). It assumes that a band matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. This makes it possible to get the address of a column
- * of J via the macro BAND_COL and to write a simple for loop to set
- * each of the elements of a column in succession.
- * -----------------------------------------------------------------
- */
-
-static int CVBandPDQJac(CVBandPrecData pdata, 
-                        realtype t, N_Vector y, N_Vector fy, 
-                        N_Vector ftemp, N_Vector ytemp)
+/*-----------------------------------------------------------------
+  CVBandPDQJac
+  -----------------------------------------------------------------
+  This routine generates a banded difference quotient approximation 
+  to the Jacobian of f(t,y). It assumes that a band SUNMatrix is 
+  stored column-wise, and that elements within each column are 
+  contiguous. This makes it possible to get the address of a column
+  of J via the accessor function SUNBandMatrix_Column() and to 
+  write a simple for loop to set each of the elements of a column 
+  in succession.
+  -----------------------------------------------------------------*/
+static int CVBandPDQJac(CVBandPrecData pdata, realtype t, N_Vector y, 
+                        N_Vector fy, N_Vector ftemp, N_Vector ytemp)
 {
   CVodeMem cv_mem;
   realtype fnorm, minInc, inc, inc_inv, srur;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
   int retval;
 
   cv_mem = (CVodeMem) pdata->cvode_mem;
 
   /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp. */
-  ewt_data   = N_VGetArrayPointer(ewt);
+  ewt_data   = N_VGetArrayPointer(cv_mem->cv_ewt);
   fy_data    = N_VGetArrayPointer(fy);
   ftemp_data = N_VGetArrayPointer(ftemp);
   y_data     = N_VGetArrayPointer(y);
@@ -449,40 +502,38 @@ static int CVBandPDQJac(CVBandPrecData pdata,
   N_VScale(ONE, y, ytemp);
 
   /* Set minimum increment based on uround and norm of f. */
-  srur = SUNRsqrt(uround);
-  fnorm = N_VWrmsNorm(fy, ewt);
+  srur = SUNRsqrt(cv_mem->cv_uround);
+  fnorm = N_VWrmsNorm(fy, cv_mem->cv_ewt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) * cv_mem->cv_uround * pdata->N * fnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing. */
-  width = ml + mu + 1;
-  ngroups = SUNMIN(width, N);
+  width = pdata->ml + pdata->mu + 1;
+  ngroups = SUNMIN(width, pdata->N);
   
   for (group = 1; group <= ngroups; group++) {
     
     /* Increment all y_j in group. */
-    for(j = group-1; j < N; j += width) {
+    for(j = group-1; j < pdata->N; j += width) {
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       ytemp_data[j] += inc;
     }
 
     /* Evaluate f with incremented y. */
-
-    retval = f(t, ytemp, ftemp, user_data);
-    nfeBP++;
+    retval = cv_mem->cv_f(t, ytemp, ftemp, cv_mem->cv_user_data);
+    pdata->nfeBP++;
     if (retval != 0) return(retval);
 
     /* Restore ytemp, then form and load difference quotients. */
-    for (j = group-1; j < N; j += width) {
+    for (j = group-1; j < pdata->N; j += width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(savedJ,j);
+      col_j = SUNBandMatrix_Column(pdata->savedJ,j);
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
-      i1 = SUNMAX(0, j-mu);
-      i2 = SUNMIN(j+ml, N-1);
+      i1 = SUNMAX(0, j-pdata->mu);
+      i2 = SUNMIN(j + pdata->ml, pdata->N - 1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) =
-          inc_inv * (ftemp_data[i] - fy_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
     }
   }
 
diff --git a/src/cvode/cvode_bandpre_impl.h b/src/cvode/cvode_bandpre_impl.h
index 9b2b7ec..c3ac451 100644
--- a/src/cvode/cvode_bandpre_impl.h
+++ b/src/cvode/cvode_bandpre_impl.h
@@ -1,20 +1,22 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Michael Wittman, Alan C. Hindmarsh and
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Michael Wittman, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * Implementation header file for the CVBANDPRE module.
  * -----------------------------------------------------------------
@@ -24,52 +26,48 @@
 #define _CVBANDPRE_IMPL_H
 
 #include <cvode/cvode_bandpre.h>
-#include <sundials/sundials_band.h>
-#include <sundials/sundials_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * Type: CVBandPrecData
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type: CVBandPrecData
+  -----------------------------------------------------------------*/
 
 typedef struct CVBandPrecDataRec {
 
   /* Data set by user in CVBandPrecInit */
-
-  long int N;
-  long int ml, mu;
+  sunindextype N;
+  sunindextype ml, mu;
 
   /* Data set by CVBandPrecSetup */
-
-  DlsMat savedJ;
-  DlsMat savedP;
-  long int *lpivots;
+  SUNMatrix savedJ;
+  SUNMatrix savedP;
+  SUNLinearSolver LS;
+  N_Vector tmp1;
+  N_Vector tmp2;
 
   /* Rhs calls */
-
   long int nfeBP;
 
   /* Pointer to cvode_mem */
-
   void *cvode_mem;
 
 } *CVBandPrecData;
 
-/*
- * -----------------------------------------------------------------
- * CVBANDPRE error messages
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVBANDPRE error messages
+  -----------------------------------------------------------------*/
 
 #define MSGBP_MEM_NULL       "Integrator memory is NULL."
 #define MSGBP_LMEM_NULL      "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBP_MEM_FAIL       "A memory request failed."
 #define MSGBP_BAD_NVECTOR    "A required vector operation is not implemented."
+#define MSGBP_SUNMAT_FAIL    "An error arose from a SUNBandMatrix routine."
+#define MSGBP_SUNLS_FAIL     "An error arose from a SUNBandLinearSolver routine."
 #define MSGBP_PMEM_NULL      "Band preconditioner memory is NULL. CVBandPrecInit must be called."
 #define MSGBP_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner."
 
diff --git a/src/cvode/cvode_bbdpre.c b/src/cvode/cvode_bbdpre.c
index 4a3f63a..7a40bd8 100644
--- a/src/cvode/cvode_bbdpre.c
+++ b/src/cvode/cvode_bbdpre.c
@@ -1,25 +1,27 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Michael Wittman, Alan C. Hindmarsh, Radu Serban,
- *                and Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *    Michael Wittman, Alan C. Hindmarsh, Radu Serban, and 
+ *    Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This file contains implementations of routines for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with CVODE, a CVSPILS linear
- * solver, and the parallel implementation of NVECTOR.
+ * matrix with banded blocks, for use with CVODE, the CVSPILS linear
+ * solver interface, and the MPI-parallel implementation of NVECTOR.
  * -----------------------------------------------------------------
  */
 
@@ -29,79 +31,64 @@
 #include "cvode_impl.h"
 #include "cvode_bbdpre_impl.h"
 #include "cvode_spils_impl.h"
-
-#include <cvode/cvode_sptfqmr.h>
-#include <cvode/cvode_spbcgs.h>
-#include <cvode/cvode_spgmr.h>
-
 #include <sundials/sundials_math.h>
+#include <nvector/nvector_serial.h>
 
 #define MIN_INC_MULT RCONST(1000.0)
-
 #define ZERO         RCONST(0.0)
 #define ONE          RCONST(1.0)
 
 /* Prototypes of functions CVBBDPrecSetup and CVBBDPrecSolve */
-
 static int CVBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                           booleantype jok, booleantype *jcurPtr, 
-                          realtype gamma, void *bbd_data, 
-                          N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
+                          realtype gamma, void *bbd_data);
 static int CVBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, 
                           N_Vector r, N_Vector z, 
                           realtype gamma, realtype delta,
-                          int lr, void *bbd_data, N_Vector tmp);
+                          int lr, void *bbd_data);
 
 /* Prototype for CVBBDPrecFree */
 static int CVBBDPrecFree(CVodeMem cv_mem);
 
-
 /* Prototype for difference quotient Jacobian calculation routine */
-
 static int CVBBDDQJac(CVBBDPrecData pdata, realtype t, 
                       N_Vector y, N_Vector gy, 
                       N_Vector ytemp, N_Vector gtemp);
 
-/* Redability replacements */
-
-#define uround   (cv_mem->cv_uround)
-#define vec_tmpl (cv_mem->cv_tempv)
-
-/*
- * -----------------------------------------------------------------
- * User-Callable Functions: initialization, reinit and free
- * -----------------------------------------------------------------
- */
-
-int CVBBDPrecInit(void *cvode_mem, long int Nlocal, 
-                   long int mudq, long int mldq,
-                   long int mukeep, long int mlkeep, 
-                   realtype dqrely, 
-                   CVLocalFn gloc, CVCommFn cfn)
+/*-----------------------------------------------------------------
+  User-Callable Functions: initialization, reinit and free
+  -----------------------------------------------------------------*/
+int CVBBDPrecInit(void *cvode_mem, sunindextype Nlocal, 
+                  sunindextype mudq, sunindextype mldq,
+                  sunindextype mukeep, sunindextype mlkeep, 
+                  realtype dqrely, CVLocalFn gloc, CVCommFn cfn)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
-  long int muk, mlk, storage_mu;
+  sunindextype muk, mlk, storage_mu, lrw1, liw1;
+  long int lrw, liw;
   int flag;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the CVSPILS linear solver interface has been created */
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  /* Test if the NVECTOR package is compatible with the BLOCK BAND preconditioner */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_BAD_NVECTOR);
+  /* Test compatibility of NVECTOR package with the BBD preconditioner */
+  if(cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_BAD_NVECTOR);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -109,7 +96,8 @@ int CVBBDPrecInit(void *cvode_mem, long int Nlocal,
   pdata = NULL;
   pdata = (CVBBDPrecData) malloc(sizeof *pdata);  
   if (pdata == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
@@ -125,91 +113,207 @@ int CVBBDPrecInit(void *cvode_mem, long int Nlocal,
   pdata->mlkeep = mlk;
 
   /* Allocate memory for saved Jacobian */
-  pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk);
+  pdata->savedJ = SUNBandMatrix(Nlocal, muk, mlk, muk);
   if (pdata->savedJ == NULL) { 
     free(pdata); pdata = NULL; 
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL); 
   }
 
   /* Allocate memory for preconditioner matrix */
   storage_mu = SUNMIN(Nlocal-1, muk + mlk);
   pdata->savedP = NULL;
-  pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+  pdata->savedP = SUNBandMatrix(Nlocal, muk, mlk, storage_mu);
   if (pdata->savedP == NULL) {
-    DestroyMat(pdata->savedJ);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+
+  /* Allocate memory for temporary N_Vectors */
+  pdata->zlocal = NULL;
+  pdata->zlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->zlocal == NULL) {
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->rlocal = NULL;
+  pdata->rlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->rlocal == NULL) {
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp1 = NULL;
+  pdata->tmp1 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp1 == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp2 = NULL;
+  pdata->tmp2 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp2 == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp3 = NULL;
+  pdata->tmp3 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp3 == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
-  /* Allocate memory for lpivots */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(Nlocal);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->savedP);
-    DestroyMat(pdata->savedJ);
+
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(pdata->rlocal, pdata->savedP);
+  if (pdata->LS == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->tmp3);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->tmp3);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    SUNLinSolFree(pdata->LS);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_SUNLS_FAIL);
+    return(CVSPILS_SUNLS_FAIL);
+  }
+
   /* Set pdata->dqrely based on input dqrely (0 implies default). */
-  pdata->dqrely = (dqrely > ZERO) ? dqrely : SUNRsqrt(uround);
+  pdata->dqrely = (dqrely > ZERO) ?
+    dqrely : SUNRsqrt(cv_mem->cv_uround);
 
   /* Store Nlocal to be used in CVBBDPrecSetup */
   pdata->n_local = Nlocal;
 
   /* Set work space sizes and initialize nge */
-  pdata->rpwsize = Nlocal*(muk + 2*mlk + storage_mu + 2);
-  pdata->ipwsize = Nlocal;
+  pdata->rpwsize = 0;
+  pdata->ipwsize = 0;
+  if (cv_mem->cv_tempv->ops->nvspace) {
+    N_VSpace(cv_mem->cv_tempv, &lrw1, &liw1);
+    pdata->rpwsize += 3*lrw1;
+    pdata->ipwsize += 3*liw1;
+  }
+  if (pdata->rlocal->ops->nvspace) {
+    N_VSpace(pdata->rlocal, &lrw1, &liw1);
+    pdata->rpwsize += 2*lrw1;
+    pdata->ipwsize += 2*liw1;
+  }
+  if (pdata->savedJ->ops->space) {
+    flag = SUNMatSpace(pdata->savedJ, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->savedP->ops->space) {
+    flag = SUNMatSpace(pdata->savedP, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
   pdata->nge = 0;
 
-  /* make sure s_P_data is free from any previous allocations */
-  if (cvspils_mem->s_pfree != NULL) {
-    cvspils_mem->s_pfree(cv_mem);
-  }
+  /* make sure P_data is free from any previous allocations */
+  if (cvspils_mem->pfree)
+    cvspils_mem->pfree(cv_mem);
 
   /* Point to the new P_data field in the SPILS memory */
-  cvspils_mem->s_P_data = pdata;
+  cvspils_mem->P_data = pdata;
 
   /* Attach the pfree function */
-  cvspils_mem->s_pfree = CVBBDPrecFree;
+  cvspils_mem->pfree = CVBBDPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = CVSpilsSetPreconditioner(cvode_mem, CVBBDPrecSetup, CVBBDPrecSolve);
-
+  flag = CVSpilsSetPreconditioner(cvode_mem,
+                                  CVBBDPrecSetup,
+                                  CVBBDPrecSolve);
   return(flag);
 }
 
 
-int CVBBDPrecReInit(void *cvode_mem, 
-                    long int mudq, long int mldq, 
-                    realtype dqrely)
+int CVBBDPrecReInit(void *cvode_mem, sunindextype mudq,
+                    sunindextype mldq, realtype dqrely)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
-  long int Nlocal;
+  sunindextype Nlocal;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecReInit", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecReInit", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
   /* Test if the preconditioner data is non-NULL */
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecReInit", MSGBBD_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
 
   /* Load half-bandwidths */
   Nlocal = pdata->n_local;
@@ -217,7 +321,8 @@ int CVBBDPrecReInit(void *cvode_mem,
   pdata->mldq = SUNMIN(Nlocal-1, SUNMAX(0,mldq));
 
   /* Set pdata->dqrely based on input dqrely (0 implies default). */
-  pdata->dqrely = (dqrely > ZERO) ? dqrely : SUNRsqrt(uround);
+  pdata->dqrely = (dqrely > ZERO) ?
+    dqrely : SUNRsqrt(cv_mem->cv_uround);
 
   /* Re-initialize nge */
   pdata->nge = 0;
@@ -225,29 +330,35 @@ int CVBBDPrecReInit(void *cvode_mem,
   return(CVSPILS_SUCCESS);
 }
 
-int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwBBDP, long int *leniwBBDP)
+
+int CVBBDPrecGetWorkSpace(void *cvode_mem,
+                          long int *lenrwBBDP,
+                          long int *leniwBBDP)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
 
   *lenrwBBDP = pdata->rpwsize;
   *leniwBBDP = pdata->ipwsize;
@@ -255,194 +366,205 @@ int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwBBDP, long int *leniwB
   return(CVSPILS_SUCCESS);
 }
 
-int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP)
+
+int CVBBDPrecGetNumGfnEvals(void *cvode_mem,
+                            long int *ngevalsBBDP)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE",
+                   "CVBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
 
   *ngevalsBBDP = pdata->nge;
 
   return(CVSPILS_SUCCESS);
 }
 
-/* Readability Replacements */
-
-#define Nlocal  (pdata->n_local)
-#define mudq    (pdata->mudq)
-#define mldq    (pdata->mldq)
-#define mukeep  (pdata->mukeep)
-#define mlkeep  (pdata->mlkeep)
-#define dqrely  (pdata->dqrely)
-#define gloc    (pdata->gloc)
-#define cfn     (pdata->cfn)
-#define savedJ  (pdata->savedJ)
-#define savedP  (pdata->savedP)
-#define lpivots (pdata->lpivots)
-#define nge     (pdata->nge)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVBBDPrecSetup                                      
- * -----------------------------------------------------------------
- * CVBBDPrecSetup generates and factors a banded block of the
- * preconditioner matrix on each processor, via calls to the
- * user-supplied gloc and cfn functions. It uses difference
- * quotient approximations to the Jacobian elements.
- *
- * CVBBDPrecSetup calculates a new J,if necessary, then calculates
- * P = I - gamma*J, and does an LU factorization of P.
- *
- * The parameters of CVBBDPrecSetup used here are as follows:
- *
- * t       is the current value of the independent variable.
- *
- * y       is the current value of the dependent variable vector,
- *         namely the predicted value of y(t).
- *
- * fy      is the vector f(t,y).
- *
- * jok     is an input flag indicating whether Jacobian-related
- *         data needs to be recomputed, as follows:
- *           jok == FALSE means recompute Jacobian-related data
- *                  from scratch.
- *           jok == TRUE  means that Jacobian data from the
- *                  previous CVBBDPrecon call can be reused
- *                  (with the current value of gamma).
- *         A CVBBDPrecon call with jok == TRUE should only occur
- *         after a call with jok == FALSE.
- *
- * jcurPtr is a pointer to an output integer flag which is
- *         set by CVBBDPrecon as follows:
- *           *jcurPtr = TRUE if Jacobian data was recomputed.
- *           *jcurPtr = FALSE if Jacobian data was not recomputed,
- *                      but saved data was reused.
- *
- * gamma   is the scalar appearing in the Newton matrix.
- *
- * bbd_data is a pointer to the preconditioner data set by
- *          CVBBDPrecInit
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated
- *           for NVectors which are be used by CVBBDPrecSetup
- *           as temporary storage or work space.
- *
- * Return value:
- * The value returned by this CVBBDPrecSetup function is the int
- *   0  if successful,
- *   1  for a recoverable error (step will be retried).
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  Function : CVBBDPrecSetup                                      
+  -----------------------------------------------------------------
+  CVBBDPrecSetup generates and factors a banded block of the
+  preconditioner matrix on each processor, via calls to the
+  user-supplied gloc and cfn functions. It uses difference
+  quotient approximations to the Jacobian elements.
+ 
+  CVBBDPrecSetup calculates a new J,if necessary, then calculates
+  P = I - gamma*J, and does an LU factorization of P.
+ 
+  The parameters of CVBBDPrecSetup used here are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+          namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  jok     is an input flag indicating whether Jacobian-related
+          data needs to be recomputed, as follows:
+            jok == SUNFALSE means recompute Jacobian-related data
+                   from scratch.
+            jok == SUNTRUE  means that Jacobian data from the
+                   previous cvBBDPrecSetup call can be reused
+                   (with the current value of gamma).
+          A cvBBDPrecSetup call with jok == SUNTRUE should only occur
+          after a call with jok == SUNFALSE.
+ 
+  jcurPtr is a pointer to an output integer flag which is
+          set by cvBBDPrecSetup as follows:
+            *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+            *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
+                       but saved data was reused.
+ 
+  gamma   is the scalar appearing in the Newton matrix.
+ 
+  bbd_data is a pointer to the preconditioner data set by
+           CVBBDPrecInit
+ 
+  Return value:
+  The value returned by this CVBBDPrecSetup function is the int
+    0  if successful,
+    1  for a recoverable error (step will be retried).
+  -----------------------------------------------------------------*/
 static int CVBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                           booleantype jok, booleantype *jcurPtr, 
-                          realtype gamma, void *bbd_data, 
-                          N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+                          realtype gamma, void *bbd_data)
 {
-  long int ier;
+  sunindextype ier;
   CVBBDPrecData pdata;
   CVodeMem cv_mem;
   int retval;
 
   pdata = (CVBBDPrecData) bbd_data;
-
   cv_mem = (CVodeMem) pdata->cvode_mem;
 
+  /* If jok = SUNTRUE, use saved copy of J */
   if (jok) {
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                     "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    BandCopy(savedJ, savedP, mukeep, mlkeep);
-
+  /* Otherwise call CVBBDDQJac for new J value */
   } else {
 
-    /* Otherwise call CVBBDDQJac for new J value */
-    *jcurPtr = TRUE;
-    SetToZero(savedJ);
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(pdata->savedJ);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                     "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    retval = CVBBDDQJac(pdata, t, y, tmp1, tmp2, tmp3);
+    retval = CVBBDDQJac(pdata, t, y, pdata->tmp1, 
+                        pdata->tmp2, pdata->tmp3);
     if (retval < 0) {
-      cvProcessError(cv_mem, -1, "CVBBDPRE", "CVBBDPrecSetup", MSGBBD_FUNC_FAILED);
+      cvProcessError(cv_mem, -1, "CVBBDPRE", "CVBBDPrecSetup", 
+                     MSGBBD_FUNC_FAILED);
       return(-1);
     }
     if (retval > 0) {
       return(1);
     }
 
-    BandCopy(savedJ, savedP, mukeep, mlkeep);
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                     "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   }
   
   /* Scale and add I to get P = I - gamma*J */
-  BandScale(-gamma, savedP);
-  AddIdentity(savedP);
- 
-  /* Do LU factorization of P in place */
-  ier = BandGBTRF(savedP, lpivots);
+  retval = SUNMatScaleAddI(-gamma, pdata->savedP);
+  if (retval) {
+    cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                   "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+    return(-1);
+  }
  
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  if (ier > 0) return(1);
-  return(0);
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->savedP);
+  return(ier);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : CVBBDPrecSolve
- * -----------------------------------------------------------------
- * CVBBDPrecSolve solves a linear system P z = r, with the
- * band-block-diagonal preconditioner matrix P generated and
- * factored by CVBBDPrecSetup.
- *
- * The parameters of CVBBDPrecSolve used here are as follows:
- *
- * r is the right-hand side vector of the linear system.
- *
- * bbd_data is a pointer to the preconditioner data set by
- *   CVBBDPrecInit.
- *
- * z is the output vector computed by CVBBDPrecSolve.
- *
- * The value returned by the CVBBDPrecSolve function is always 0,
- * indicating success.
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  Function : CVBBDPrecSolve
+  -----------------------------------------------------------------
+  CVBBDPrecSolve solves a linear system P z = r, with the
+  band-block-diagonal preconditioner matrix P generated and
+  factored by CVBBDPrecSetup.
+ 
+  The parameters of CVBBDPrecSolve used here are as follows:
+ 
+  r is the right-hand side vector of the linear system.
+ 
+  bbd_data is a pointer to the preconditioner data set by
+    CVBBDPrecInit.
+ 
+  z is the output vector computed by CVBBDPrecSolve.
+ 
+  The value returned by the CVBBDPrecSolve function is always 0,
+  indicating success.
+  -----------------------------------------------------------------*/
 static int CVBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, 
                           N_Vector r, N_Vector z, 
                           realtype gamma, realtype delta,
-                          int lr, void *bbd_data, N_Vector tmp)
+                          int lr, void *bbd_data)
 {
+  int retval;
   CVBBDPrecData pdata;
-  realtype *zd;
 
   pdata = (CVBBDPrecData) bbd_data;
 
-  /* Copy r to z, then do backsolve and return */
-  N_VScale(ONE, r, z);
+  /* Attach local data arrays for r and z to rlocal and zlocal */
+  N_VSetArrayPointer(N_VGetArrayPointer(r), pdata->rlocal);
+  N_VSetArrayPointer(N_VGetArrayPointer(z), pdata->zlocal);
   
-  zd = N_VGetArrayPointer(z);
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->savedP, pdata->zlocal, 
+                          pdata->rlocal, ZERO);
 
-  BandGBTRS(savedP, lpivots, zd);
+  /* Detach local data arrays from rlocal and zlocal */
+  N_VSetArrayPointer(NULL, pdata->rlocal);
+  N_VSetArrayPointer(NULL, pdata->zlocal);
 
-  return(0);
+  return(retval);
 }
 
 
@@ -454,12 +576,17 @@ static int CVBBDPrecFree(CVodeMem cv_mem)
   if (cv_mem->cv_lmem == NULL) return(0);
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
   
-  if (cvspils_mem->s_P_data == NULL) return(0);
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
-
-  DestroyMat(savedJ);
-  DestroyMat(savedP);
-  DestroyArray(lpivots);
+  if (cvspils_mem->P_data == NULL) return(0);
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
+
+  SUNLinSolFree(pdata->LS);
+  N_VDestroy(pdata->tmp1);
+  N_VDestroy(pdata->tmp2);
+  N_VDestroy(pdata->tmp3);
+  N_VDestroy(pdata->zlocal);
+  N_VDestroy(pdata->rlocal);
+  SUNMatDestroy(pdata->savedP);
+  SUNMatDestroy(pdata->savedJ);
 
   free(pdata);
   pdata = NULL;
@@ -468,34 +595,26 @@ static int CVBBDPrecFree(CVodeMem cv_mem)
 }
 
 
-#define ewt       (cv_mem->cv_ewt)
-#define h         (cv_mem->cv_h)
-#define user_data (cv_mem->cv_user_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVBBDDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation
- * to the local block of the Jacobian of g(t,y). It assumes that a
- * band matrix of type DlsMat is stored columnwise, and that elements
- * within each column are contiguous. All matrix elements are generated
- * as difference quotients, by way of calls to the user routine gloc.
- * By virtue of the band structure, the number of these calls is
- * bandwidth + 1, where bandwidth = mldq + mudq + 1.
- * But the band matrix kept has bandwidth = mlkeep + mukeep + 1.
- * This routine also assumes that the local elements of a vector are
- * stored contiguously.
- * -----------------------------------------------------------------
- */
-
-static int CVBBDDQJac(CVBBDPrecData pdata, realtype t, 
-                      N_Vector y, N_Vector gy, 
-                      N_Vector ytemp, N_Vector gtemp)
+/*-----------------------------------------------------------------
+  Function : CVBBDDQJac
+  -----------------------------------------------------------------
+  This routine generates a banded difference quotient approximation
+  to the local block of the Jacobian of g(t,y). It assumes that a
+  band SUNMatrix is stored columnwise, and that elements within each 
+  column are contiguous. All matrix elements are generated as 
+  difference quotients, by way of calls to the user routine gloc.
+  By virtue of the band structure, the number of these calls is
+  bandwidth + 1, where bandwidth = mldq + mudq + 1.
+  But the band matrix kept has bandwidth = mlkeep + mukeep + 1.
+  This routine also assumes that the local elements of a vector are
+  stored contiguously.
+  -----------------------------------------------------------------*/
+static int CVBBDDQJac(CVBBDPrecData pdata, realtype t, N_Vector y, 
+                      N_Vector gy, N_Vector ytemp, N_Vector gtemp)
 {
   CVodeMem cv_mem;
   realtype gnorm, minInc, inc, inc_inv;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *y_data, *ewt_data, *gy_data, *gtemp_data, *ytemp_data, *col_j;
   int retval;
 
@@ -505,55 +624,58 @@ static int CVBBDDQJac(CVBBDPrecData pdata, realtype t,
   N_VScale(ONE, y, ytemp);
 
   /* Call cfn and gloc to get base value of g(t,y) */
-  if (cfn != NULL) {
-    retval = cfn(Nlocal, t, y, user_data);
+  if (pdata->cfn != NULL) {
+    retval = pdata->cfn(pdata->n_local, t, y, cv_mem->cv_user_data);
     if (retval != 0) return(retval);
   }
 
-  retval = gloc(Nlocal, t, ytemp, gy, user_data);
-  nge++;
+  retval = pdata->gloc(pdata->n_local, t, ytemp, gy,
+                       cv_mem->cv_user_data);
+  pdata->nge++;
   if (retval != 0) return(retval);
 
   /* Obtain pointers to the data for various vectors */
   y_data     =  N_VGetArrayPointer(y);
   gy_data    =  N_VGetArrayPointer(gy);
-  ewt_data   =  N_VGetArrayPointer(ewt);
+  ewt_data   =  N_VGetArrayPointer(cv_mem->cv_ewt);
   ytemp_data =  N_VGetArrayPointer(ytemp);
   gtemp_data =  N_VGetArrayPointer(gtemp);
 
   /* Set minimum increment based on uround and norm of g */
-  gnorm = N_VWrmsNorm(gy, ewt);
+  gnorm = N_VWrmsNorm(gy, cv_mem->cv_ewt);
   minInc = (gnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * Nlocal * gnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) *
+     cv_mem->cv_uround * pdata->n_local * gnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing */
-  width = mldq + mudq + 1;
-  ngroups = SUNMIN(width, Nlocal);
+  width = pdata->mldq + pdata->mudq + 1;
+  ngroups = SUNMIN(width, pdata->n_local);
 
   /* Loop over groups */  
   for (group=1; group <= ngroups; group++) {
     
     /* Increment all y_j in group */
-    for(j=group-1; j < Nlocal; j+=width) {
-      inc = SUNMAX(dqrely*SUNRabs(y_data[j]), minInc/ewt_data[j]);
+    for(j=group-1; j < pdata->n_local; j+=width) {
+      inc = SUNMAX(pdata->dqrely * SUNRabs(y_data[j]), minInc/ewt_data[j]);
       ytemp_data[j] += inc;
     }
 
     /* Evaluate g with incremented y */
-    retval = gloc(Nlocal, t, ytemp, gtemp, user_data);
-    nge++;
+    retval = pdata->gloc(pdata->n_local, t, ytemp, gtemp,
+                         cv_mem->cv_user_data);
+    pdata->nge++;
     if (retval != 0) return(retval);
 
     /* Restore ytemp, then form and load difference quotients */
-    for (j=group-1; j < Nlocal; j+=width) {
+    for (j=group-1; j < pdata->n_local; j+=width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(savedJ,j);
-      inc = SUNMAX(dqrely*SUNRabs(y_data[j]), minInc/ewt_data[j]);
+      col_j = SUNBandMatrix_Column(pdata->savedJ,j);
+      inc = SUNMAX(pdata->dqrely * SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
-      i1 = SUNMAX(0, j-mukeep);
-      i2 = SUNMIN(j+mlkeep, Nlocal-1);
+      i1 = SUNMAX(0, j-pdata->mukeep);
+      i2 = SUNMIN(j + pdata->mlkeep, pdata->n_local-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) =
+        SM_COLUMN_ELEMENT_B(col_j,i,j) =
           inc_inv * (gtemp_data[i] - gy_data[i]);
     }
   }
diff --git a/src/cvode/cvode_bbdpre_impl.h b/src/cvode/cvode_bbdpre_impl.h
index 3415b95..16319c7 100644
--- a/src/cvode/cvode_bbdpre_impl.h
+++ b/src/cvode/cvode_bbdpre_impl.h
@@ -1,20 +1,21 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Michael Wittman, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *     Michael Wittman, Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * Implementation header file for the CVBBDPRE module.
  * -----------------------------------------------------------------
@@ -24,59 +25,58 @@
 #define _CVBBDPRE_IMPL_H
 
 #include <cvode/cvode_bbdpre.h>
-#include <sundials/sundials_band.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * Type: CVBBDPrecData
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type: CVBBDPrecData
+  -----------------------------------------------------------------*/
 
 typedef struct CVBBDPrecDataRec {
 
-  /* passed by user to CVBBDPrecAlloc and used by PrecSetup/PrecSolve */
-
-  long int mudq, mldq, mukeep, mlkeep;
+  /* passed by user to CVBBDPrecInit and used by PrecSetup/PrecSolve */
+  sunindextype mudq, mldq, mukeep, mlkeep;
   realtype dqrely;
   CVLocalFn gloc;
   CVCommFn cfn;
 
   /* set by CVBBDPrecSetup and used by CVBBDPrecSolve */
-
-  DlsMat savedJ;
-  DlsMat savedP;
-  long int *lpivots;
-
-  /* set by CVBBDPrecAlloc and used by CVBBDPrecSetup */
-
-  long int n_local;
+  SUNMatrix savedJ;
+  SUNMatrix savedP;
+  SUNLinearSolver LS;
+  N_Vector tmp1;
+  N_Vector tmp2;
+  N_Vector tmp3;
+  N_Vector zlocal;
+  N_Vector rlocal;
+
+  /* set by CVBBDPrecInit and used by CVBBDPrecSetup */
+  sunindextype n_local;
 
   /* available for optional output */
-
   long int rpwsize;
   long int ipwsize;
   long int nge;
 
   /* pointer to cvode_mem */
-
   void *cvode_mem;
 
 } *CVBBDPrecData;
 
-/*
- * -----------------------------------------------------------------
- * CVBBDPRE error messages
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVBBDPRE error messages
+  -----------------------------------------------------------------*/
 
 #define MSGBBD_MEM_NULL    "Integrator memory is NULL."
 #define MSGBBD_LMEM_NULL   "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBBD_MEM_FAIL    "A memory request failed."
 #define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGBBD_SUNMAT_FAIL "An error arose from a SUNBandMatrix routine."
+#define MSGBBD_SUNLS_FAIL  "An error arose from a SUNBandLinearSolver routine."
 #define MSGBBD_PMEM_NULL   "BBD peconditioner memory is NULL. CVBBDPrecInit must be called."
 #define MSGBBD_FUNC_FAILED "The gloc or cfn routine failed in an unrecoverable manner."
 
diff --git a/src/cvode/cvode_dense.c b/src/cvode/cvode_dense.c
deleted file mode 100644
index 77c986e..0000000
--- a/src/cvode/cvode_dense.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4951 $
- * $Date: 2016-09-22 10:21:00 -0700 (Thu, 22 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the impleentation file for the CVDENSE linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvode/cvode_dense.h>
-#include "cvode_direct_impl.h"
-#include "cvode_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* CVDENSE linit, lsetup, lsolve, and lfree routines */
- 
-static int cvDenseInit(CVodeMem cv_mem);
-
-static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, 
-                        N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-
-static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector fcur);
-
-static int cvDenseFree(CVodeMem cv_mem);
-
-/* Readability Replacements */
-
-#define lmm       (cv_mem->cv_lmm)
-#define f         (cv_mem->cv_f)
-#define nst       (cv_mem->cv_nst)
-#define tn        (cv_mem->cv_tn)
-#define h         (cv_mem->cv_h)
-#define gamma     (cv_mem->cv_gamma)
-#define gammap    (cv_mem->cv_gammap)
-#define gamrat    (cv_mem->cv_gamrat)
-#define ewt       (cv_mem->cv_ewt)
-#define linit     (cv_mem->cv_linit)
-#define lsetup    (cv_mem->cv_lsetup)
-#define lsolve    (cv_mem->cv_lsolve)
-#define lfree     (cv_mem->cv_lfree)
-#define lmem      (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define mtype     (cvdls_mem->d_type)
-#define n         (cvdls_mem->d_n)
-#define jacDQ     (cvdls_mem->d_jacDQ)
-#define jac       (cvdls_mem->d_djac)
-#define M         (cvdls_mem->d_M)
-#define lpivots   (cvdls_mem->d_lpivots)
-#define savedJ    (cvdls_mem->d_savedJ)
-#define nstlj     (cvdls_mem->d_nstlj)
-#define nje       (cvdls_mem->d_nje)
-#define nfeDQ     (cvdls_mem->d_nfeDQ)
-#define J_data    (cvdls_mem->d_J_data)
-#define last_flag (cvdls_mem->d_last_flag)
-                  
-/*
- * -----------------------------------------------------------------
- * CVDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the dense linear solver module.  CVDense first
- * calls the existing lfree routine if this is not NULL.  Then it sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be cvDenseInit, cvDenseSetup, cvDenseSolve, and cvDenseFree,
- * respectively.  It allocates memory for a structure of type
- * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure.  It sets setupNonNull in (*cvode_mem) to
- * TRUE, and the d_jac field to the default cvDlsDenseDQJac.
- * Finally, it allocates memory for M, savedJ, and lpivots.
- * The return value is SUCCESS = 0, or LMEM_FAIL = -1.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVDense will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-int CVDense(void *cvode_mem, long int N)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDENSE", "CVDense", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL ||
-      vec_tmpl->ops->nvsetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVDENSE", "CVDense", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = cvDenseInit;
-  lsetup = cvDenseSetup;
-  lsolve = cvDenseSolve;
-  lfree  = cvDenseFree;
-
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Initialize Jacobian-related data */
-  jacDQ = TRUE;
-  jac = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-
-  cvDlsInitializeCounters(cvdls_mem);
-
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = N;
-
-  /* Allocate memory for M, savedJ, and pivot array */
-
-  M = NULL;
-  M = NewDenseMat(N, N);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NULL;
-  savedJ = NewDenseMat(N, N);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  lpivots = NULL;
-  lpivots = NewLintArray(N);
-  if (lpivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDENSE", "CVDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyMat(savedJ);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the dense
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  cvDlsInitializeCounters(cvdls_mem);
-  /*   nje   = 0;
-   nfeDQ = 0;
-   nstlj = 0;
-  */
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    jac = cvDlsDenseDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the dense linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy.  In any case, it constructs the Newton matrix 
- * M = I - gamma*J, updates counters, and calls the dense LU 
- * factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, 
-                        N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  long int ier;
-  CVDlsMem cvdls_mem;
-  int retval;
-
-  cvdls_mem = (CVDlsMem) lmem;
- 
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
- 
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
- 
-  if (jok) {
-
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    DenseCopy(savedJ, M);
-
-  } else {
-
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M);
-
-    retval = jac(n, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVDENSE", "cvDenseSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    DenseCopy(M, savedJ);
-
-  }
-  
-  /* Scale and add I to get M = I - gamma*J */
-  DenseScale(-gamma, M);
-  AddIdentity(M);
-
-  /* Do LU factorization of M */
-  ier = DenseGETRF(M, lpivots); 
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseSolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.  The returned value is 0.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector fcur)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  bd = N_VGetArrayPointer(b);
-
-  DenseGETRS(M, lpivots, bd);
-
-  /* If CV_BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-  
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the dense linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseFree(CVodeMem cv_mem)
-{
-  CVDlsMem  cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  DestroyMat(M);
-  DestroyMat(savedJ);
-  DestroyArray(lpivots);
-  free(cvdls_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
diff --git a/src/cvode/cvode_diag.c b/src/cvode/cvode_diag.c
index 1f1a055..fe5d56c 100644
--- a/src/cvode/cvode_diag.c
+++ b/src/cvode/cvode_diag.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
@@ -84,7 +81,7 @@ static int CVDiagFree(CVodeMem cv_mem);
  * respectively.  It allocates memory for a structure of type
  * CVDiagMemRec and sets the cv_lmem field in (*cvode_mem) to the
  * address of this structure.  It sets setupNonNull in (*cvode_mem) to
- * TRUE.  Finally, it allocates memory for M, bit, and bitcomp.
+ * SUNTRUE.  Finally, it allocates memory for M, bit, and bitcomp.
  * The CVDiag return value is SUCCESS = 0, LMEM_FAIL = -1, or 
  * LIN_ILL_INPUT=-2.
  * -----------------------------------------------------------------
@@ -127,11 +124,9 @@ int CVDiag(void *cvode_mem)
 
   last_flag = CVDIAG_SUCCESS;
 
-  /* Set flag setupNonNull = TRUE */
-  setupNonNull = TRUE;
-
+  
   /* Allocate memory for M, bit, and bitcomp */
-    
+   
   M = N_VClone(vec_tmpl);
   if (M == NULL) {
     cvProcessError(cv_mem, CVDIAG_MEM_FAIL, "CVDIAG", "CVDiag", MSGDG_MEM_FAIL);
@@ -372,8 +367,8 @@ static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
     return(1);
   }
 
-  /* Set jcur = TRUE, save gamma in gammasv, and return */
-  *jcurPtr = TRUE;
+  /* Set jcur = SUNTRUE, save gamma in gammasv, and return */
+  *jcurPtr = SUNTRUE;
   gammasv = gamma;
   last_flag = CVDIAG_SUCCESS;
   return(0);
diff --git a/src/cvode/cvode_diag_impl.h b/src/cvode/cvode_diag_impl.h
index f39b214..9ccce3a 100644
--- a/src/cvode/cvode_diag_impl.h
+++ b/src/cvode/cvode_diag_impl.h
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
@@ -52,7 +49,7 @@ typedef struct {
   long int di_nfeDI;   /* no. of calls to f due to difference 
                           quotient diagonal Jacobian approximation  */
 
-  long int di_last_flag;    /* last error return flag                    */
+  long int di_last_flag;    /* last error return flag               */
 
 } CVDiagMemRec, *CVDiagMem;
 
diff --git a/src/cvode/cvode_direct.c b/src/cvode/cvode_direct.c
index da6eba6..8c82b9d 100644
--- a/src/cvode/cvode_direct.c
+++ b/src/cvode/cvode_direct.c
@@ -1,29 +1,30 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
  * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the implementation file for the CVDLS linear solvers
+ * This is the implementation file for the CVDLS linear solver 
+ * interface
  * -----------------------------------------------------------------
  */
 
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
+/*=================================================================
+  IMPORTED HEADER FILES
+  =================================================================*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,12 +32,13 @@
 #include "cvode_impl.h"
 #include "cvode_direct_impl.h"
 #include <sundials/sundials_math.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
+/*=================================================================
+  FUNCTION SPECIFIC CONSTANTS
+  =================================================================*/
 
 /* Constant for DQ Jacobian approximation */
 #define MIN_INC_MULT RCONST(1000.0)
@@ -45,196 +47,252 @@
 #define ONE          RCONST(1.0)
 #define TWO          RCONST(2.0)
 
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define f         (cv_mem->cv_f)
-#define user_data (cv_mem->cv_user_data)
-#define uround    (cv_mem->cv_uround)
-#define nst       (cv_mem->cv_nst)
-#define tn        (cv_mem->cv_tn)
-#define h         (cv_mem->cv_h)
-#define gamma     (cv_mem->cv_gamma)
-#define gammap    (cv_mem->cv_gammap)
-#define gamrat    (cv_mem->cv_gamrat)
-#define ewt       (cv_mem->cv_ewt)
-
-#define lmem      (cv_mem->cv_lmem)
-
-#define mtype     (cvdls_mem->d_type)
-#define n         (cvdls_mem->d_n)
-#define ml        (cvdls_mem->d_ml)
-#define mu        (cvdls_mem->d_mu)
-#define smu       (cvdls_mem->d_smu)
-#define jacDQ     (cvdls_mem->d_jacDQ)
-#define djac      (cvdls_mem->d_djac)
-#define bjac      (cvdls_mem->d_bjac)
-#define M         (cvdls_mem->d_M)
-#define nje       (cvdls_mem->d_nje)
-#define nfeDQ     (cvdls_mem->d_nfeDQ)
-#define last_flag (cvdls_mem->d_last_flag)
+/*=================================================================
+  EXPORTED FUNCTIONS -- REQUIRED
+  =================================================================*/
 
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS
- * =================================================================
- */
-              
-/*
- * CVDlsSetDenseJacFn specifies the dense Jacobian function.
- */
-int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac)
+/*---------------------------------------------------------------
+ CVDlsSetLinearSolver specifies the direct linear solver.
+---------------------------------------------------------------*/
+int CVDlsSetLinearSolver(void *cvode_mem, SUNLinearSolver LS,
+                         SUNMatrix A)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", 
+                   "CVDlsSetLinearSolver", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
+  if ( (LS == NULL)  || (A == NULL) ) {
+    cvProcessError(NULL, CVDLS_ILL_INPUT, "CVDLS", 
+                   "CVDlsSetLinearSolver",
+                    "Both LS and A must be non-NULL");
+    return(CVDLS_ILL_INPUT);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_LMEM_NULL);
-    return(CVDLS_LMEM_NULL);
+  /* Test if solver and vector are compatible with DLS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
+    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVDLS", 
+                   "CVDlsSetLinearSolver", 
+                   "Non-direct LS supplied to CVDls interface");
+    return(CVDLS_ILL_INPUT);
+  }
+  if (cv_mem->cv_tempv->ops->nvgetarraypointer == NULL ||
+      cv_mem->cv_tempv->ops->nvsetarraypointer == NULL) {
+    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVDLS", 
+                   "CVDlsSetLinearSolver", MSGD_BAD_NVECTOR);
+    return(CVDLS_ILL_INPUT);
   }
-  cvdls_mem = (CVDlsMem) lmem;
 
-  if (jac != NULL) {
-    jacDQ = FALSE;
-    djac = jac;
-  } else {
-    jacDQ = TRUE;
+  /* free any existing system solver attached to CVode */
+  if (cv_mem->cv_lfree)  cv_mem->cv_lfree(cv_mem);
+
+  /* Set four main system linear solver function fields in cv_mem */
+  cv_mem->cv_linit  = cvDlsInitialize;
+  cv_mem->cv_lsetup = cvDlsSetup;
+  cv_mem->cv_lsolve = cvDlsSolve;
+  cv_mem->cv_lfree  = cvDlsFree;
+  
+  /* Get memory for CVDlsMemRec */
+  cvdls_mem = NULL;
+  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
+  if (cvdls_mem == NULL) {
+    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDLS", 
+                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
+    return(CVDLS_MEM_FAIL);
   }
 
+  /* set SUNLinearSolver pointer */
+  cvdls_mem->LS = LS;
+  
+  /* Initialize Jacobian-related data */
+  cvdls_mem->jacDQ = SUNTRUE;
+  cvdls_mem->jac = cvDlsDQJac;
+  cvdls_mem->J_data = cv_mem;
+  cvdls_mem->last_flag = CVDLS_SUCCESS;
+
+  /* Initialize counters */
+  cvDlsInitializeCounters(cvdls_mem);
+
+  /* Store pointer to A and create saved_J */
+  cvdls_mem->A = A;
+  cvdls_mem->savedJ = SUNMatClone(A);
+  if (cvdls_mem->savedJ == NULL) {
+    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDLS", 
+                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
+    free(cvdls_mem); cvdls_mem = NULL;
+    return(CVDLS_MEM_FAIL);
+  }
+
+  /* Allocate memory for x */
+  cvdls_mem->x = N_VClone(cv_mem->cv_tempv);
+  if (cvdls_mem->x == NULL) {
+    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVDLS", 
+                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
+    SUNMatDestroy(cvdls_mem->savedJ);
+    free(cvdls_mem); cvdls_mem = NULL;
+    return(CVDLS_MEM_FAIL);
+  }
+  /* Attach linear solver memory to integrator memory */
+  cv_mem->cv_lmem = cvdls_mem;
+
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsSetBandJacFn specifies the band Jacobian function.
+
+/* 
+ * =================================================================
+ * EXPORTED FUNCTIONS -- OPTIONAL
+ * =================================================================
  */
-int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac)
+              
+/* CVDlsSetJacFn specifies the Jacobian function. */
+int CVDlsSetJacFn(void *cvode_mem, CVDlsJacFn jac)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS",
+                   "CVDlsSetJacFn", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS",
+                   "CVDlsSetJacFn", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
   if (jac != NULL) {
-    jacDQ = FALSE;
-    bjac = jac;
+    cvdls_mem->jacDQ  = SUNFALSE;
+    cvdls_mem->jac    = jac;
+    cvdls_mem->J_data = cv_mem->cv_user_data;
   } else {
-    jacDQ = TRUE;
+    cvdls_mem->jacDQ  = SUNTRUE;
+    cvdls_mem->jac    = cvDlsDQJac;
+    cvdls_mem->J_data = cv_mem;
   }
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetWorkSpace returns the length of workspace allocated for the
- * CVDLS linear solver.
- */
-int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+
+/* CVDlsGetWorkSpace returns the length of workspace allocated for the
+   CVDLS linear solver. */
+int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS,
+                      long int *leniwLS)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetWorkSpace", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS",
+                   "CVDlsGetWorkSpace", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetWorkSpace", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS",
+                   "CVDlsGetWorkSpace", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+
+  /* initialize outputs with requirements from CVDlsMem structure */
+  *lenrwLS = 0;
+  *leniwLS = 4;
 
-  if (mtype == SUNDIALS_DENSE) {
-    *lenrwLS = 2*n*n;
-    *leniwLS = n;
-  } else if (mtype == SUNDIALS_BAND) {
-    *lenrwLS = n*(smu + mu + 2*ml + 2);
-    *leniwLS = n;
+  /* add NVector size */
+  if (cvdls_mem->x->ops->nvspace) {
+    N_VSpace(cvdls_mem->x, &lrw1, &liw1);
+    *lenrwLS = lrw1;
+    *leniwLS = liw1;
+  }
+  
+  /* add SUNMatrix size (only account for the one owned by Dls interface) */
+  if (cvdls_mem->savedJ->ops->space) {
+    flag = SUNMatSpace(cvdls_mem->savedJ, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
+  }
+
+  /* add LS sizes */
+  if (cvdls_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(cvdls_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
+
+/* CVDlsGetNumJacEvals returns the number of Jacobian evaluations. */
 int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetNumJacEvals", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS",
+                   "CVDlsGetNumJacEvals", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetNumJacEvals", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS",
+                   "CVDlsGetNumJacEvals", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  *njevals = nje;
+  *njevals = cvdls_mem->nje;
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetNumRhsEvals returns the number of calls to the ODE function
- * needed for the DQ Jacobian approximation.
- */
+
+/* CVDlsGetNumRhsEvals returns the number of calls to the ODE function
+   needed for the DQ Jacobian approximation. */
 int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetNumRhsEvals", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS",
+                   "CVDlsGetNumRhsEvals", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetNumRhsEvals", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS",
+                   "CVDlsGetNumRhsEvals", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  *nfevalsLS = nfeDQ;
+  *nfevalsLS = cvdls_mem->nfeDQ;
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetReturnFlagName returns the name associated with a CVDLS
- * return value.
- */
+
+/* CVDlsGetReturnFlagName returns the name associated with a CVDLS
+   return value. */
 char *CVDlsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -263,6 +321,9 @@ char *CVDlsGetReturnFlagName(long int flag)
   case CVDLS_JACFUNC_RECVR:
     sprintf(name,"CVDLS_JACFUNC_RECVR");
     break;
+  case CVDLS_SUNMAT_FAIL:
+    sprintf(name,"CVDLS_SUNMAT_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -270,100 +331,135 @@ char *CVDlsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * CVDlsGetLastFlag returns the last flag set in a CVDLS function.
- */
+
+/* CVDlsGetLastFlag returns the last flag set in a CVDLS function. */
 int CVDlsGetLastFlag(void *cvode_mem, long int *flag)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsGetLastFlag", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS",
+                   "CVDlsGetLastFlag", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsGetLastFlag", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS",
+                   "CVDlsGetLastFlag", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  *flag = last_flag;
+  *flag = cvdls_mem->last_flag;
 
   return(CVDLS_SUCCESS);
 }
 
-/* 
- * =================================================================
- * DQ JACOBIAN APPROXIMATIONS
- * =================================================================
- */
 
-/*
- * -----------------------------------------------------------------
- * cvDlsDenseDQJac 
- * -----------------------------------------------------------------
- * This routine generates a dense difference quotient approximation to
- * the Jacobian of f(t,y). It assumes that a dense matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. The address of the jth column of J is obtained via
- * the macro DENSE_COL and this pointer is associated with an N_Vector
- * using the N_VGetArrayPointer/N_VSetArrayPointer functions. 
- * Finally, the actual computation of the jth column of the Jacobian is 
- * done with a call to N_VLinearSum.
- * -----------------------------------------------------------------
- */ 
+/*=================================================================
+  CVDLS PRIVATE FUNCTIONS
+  =================================================================*/
+
+
+/*-----------------------------------------------------------------
+  cvDlsDQJac 
+  -----------------------------------------------------------------
+  This routine is a wrapper for the Dense and Band
+  implementations of the difference quotient Jacobian 
+  approximation routines.
+  ---------------------------------------------------------------*/
+int cvDlsDQJac(realtype t, N_Vector y, N_Vector fy, 
+               SUNMatrix Jac, void *cvode_mem, N_Vector tmp1, 
+               N_Vector tmp2, N_Vector tmp3)
+{
+  int retval;
+  CVodeMem cv_mem;
+  cv_mem = (CVodeMem) cvode_mem;
+
+  /* verify that Jac is non-NULL */
+  if (Jac == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", 
+		    "cvDlsDQJac", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+
+  if (SUNMatGetID(Jac) == SUNMATRIX_DENSE) {
+    retval = cvDlsDenseDQJac(t, y, fy, Jac, cv_mem, tmp1);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_BAND) {
+    retval = cvDlsBandDQJac(t, y, fy, Jac, cv_mem, tmp1, tmp2);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_SPARSE) {
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVDLS", 
+                   "cvDlsDQJac", 
+                   "cvDlsDQJac not implemented for SUNMATRIX_SPARSE");
+    retval = CV_ILL_INPUT;
+  } else {
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVDLS", 
+                   "cvDlsDQJac", 
+                   "unrecognized matrix type for cvDlsDQJac");
+    retval = CV_ILL_INPUT;
+  }
+  return(retval);
+}
 
-int cvDlsDenseDQJac(long int N, realtype t,
-                    N_Vector y, N_Vector fy, 
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+
+/*-----------------------------------------------------------------
+  cvDlsDenseDQJac 
+  -----------------------------------------------------------------
+  This routine generates a dense difference quotient approximation 
+  to the Jacobian of f(t,y). It assumes that a dense SUNMatrix is 
+  stored column-wise, and that elements within each column are 
+  contiguous. The address of the jth column of J is obtained via
+  the accessor function SUNDenseMatrix_Column, and this pointer 
+  is associated with an N_Vector using the N_VSetArrayPointer
+  function.  Finally, the actual computation of the jth column of 
+  the Jacobian is done with a call to N_VLinearSum.
+  -----------------------------------------------------------------*/ 
+int cvDlsDenseDQJac(realtype t, N_Vector y, N_Vector fy, 
+                    SUNMatrix Jac, CVodeMem cv_mem, N_Vector tmp1)
 {
   realtype fnorm, minInc, inc, inc_inv, yjsaved, srur;
-  realtype *tmp2_data, *y_data, *ewt_data;
+  realtype *y_data, *ewt_data;
   N_Vector ftemp, jthCol;
-  long int j;
+  sunindextype j, N;
   int retval = 0;
-
-  CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* data points to cvode_mem */
-  cv_mem = (CVodeMem) data;
-  cvdls_mem = (CVDlsMem) lmem;
+  /* access DlsMem interface structure */
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  /* Save pointer to the array in tmp2 */
-  tmp2_data = N_VGetArrayPointer(tmp2);
+  /* access matrix dimension */
+  N = SUNDenseMatrix_Rows(Jac);
 
-  /* Rename work vectors for readibility */
-  ftemp = tmp1; 
-  jthCol = tmp2;
+  /* Rename work vector for readibility */
+  ftemp = tmp1;
+
+  /* Create an empty vector for matrix column calculations */
+  jthCol = N_VCloneEmpty(tmp1);
 
   /* Obtain pointers to the data for ewt, y */
-  ewt_data = N_VGetArrayPointer(ewt);
+  ewt_data = N_VGetArrayPointer(cv_mem->cv_ewt);
   y_data   = N_VGetArrayPointer(y);
 
   /* Set minimum increment based on uround and norm of f */
-  srur = SUNRsqrt(uround);
-  fnorm = N_VWrmsNorm(fy, ewt);
+  srur = SUNRsqrt(cv_mem->cv_uround);
+  fnorm = N_VWrmsNorm(fy, cv_mem->cv_ewt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) * cv_mem->cv_uround * N * fnorm) : ONE;
 
   for (j = 0; j < N; j++) {
 
     /* Generate the jth col of J(tn,y) */
 
-    N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol);
+    N_VSetArrayPointer(SUNDenseMatrix_Column(Jac,j), jthCol);
 
     yjsaved = y_data[j];
     inc = SUNMAX(srur*SUNRabs(yjsaved), minInc/ewt_data[j]);
     y_data[j] += inc;
 
-    retval = f(t, y, ftemp, user_data);
-    nfeDQ++;
+    retval = cv_mem->cv_f(t, y, ftemp, cv_mem->cv_user_data);
+    cvdls_mem->nfeDQ++;
     if (retval != 0) break;
     
     y_data[j] = yjsaved;
@@ -371,52 +467,53 @@ int cvDlsDenseDQJac(long int N, realtype t,
     inc_inv = ONE/inc;
     N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol);
 
-    DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);
+    /* DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);   /\*UNNECESSARY?? *\/ */
   }
 
-  /* Restore original array pointer in tmp2 */
-  N_VSetArrayPointer(tmp2_data, tmp2);
+  /* Destroy jthCol vector */
+  N_VSetArrayPointer(NULL, jthCol);  /* SHOULDN'T BE NEEDED */
+  N_VDestroy(jthCol);
 
   return(retval);
 }
 
-/*
- * -----------------------------------------------------------------
- * cvDlsBandDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation to
- * the Jacobian of f(t,y).  It assumes that a band matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. This makes it possible to get the address of a column
- * of J via the macro BAND_COL and to write a simple for loop to set
- * each of the elements of a column in succession.
- * -----------------------------------------------------------------
- */
 
-int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
-                   realtype t, N_Vector y, N_Vector fy, 
-                   DlsMat Jac, void *data,
-                   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+/*-----------------------------------------------------------------
+  cvDlsBandDQJac
+  -----------------------------------------------------------------
+  This routine generates a banded difference quotient approximation 
+  to the Jacobian of f(t,y).  It assumes that a band SUNMatrix is 
+  stored column-wise, and that elements within each column are 
+  contiguous. This makes it possible to get the address of a column
+  of J via the accessor function SUNBandMatrix_Column, and to write 
+  a simple for loop to set each of the elements of a column in 
+  succession.
+  -----------------------------------------------------------------*/
+int cvDlsBandDQJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix Jac, 
+                   CVodeMem cv_mem, N_Vector tmp1, N_Vector tmp2)
 {
   N_Vector ftemp, ytemp;
   realtype fnorm, minInc, inc, inc_inv, srur;
   realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   int retval = 0;
-
-  CVodeMem cv_mem;
+  sunindextype N, mupper, mlower;
   CVDlsMem cvdls_mem;
 
-  /* data points to cvode_mem */
-  cv_mem = (CVodeMem) data;
-  cvdls_mem = (CVDlsMem) lmem;
+  /* access DlsMem interface structure */
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+
+  /* access matrix dimensions */
+  N = SUNBandMatrix_Columns(Jac);
+  mupper = SUNBandMatrix_UpperBandwidth(Jac);
+  mlower = SUNBandMatrix_LowerBandwidth(Jac);
 
   /* Rename work vectors for use as temporary values of y and f */
   ftemp = tmp1;
   ytemp = tmp2;
 
   /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp */
-  ewt_data   = N_VGetArrayPointer(ewt);
+  ewt_data   = N_VGetArrayPointer(cv_mem->cv_ewt);
   fy_data    = N_VGetArrayPointer(fy);
   ftemp_data = N_VGetArrayPointer(ftemp);
   y_data     = N_VGetArrayPointer(y);
@@ -426,10 +523,10 @@ int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
   N_VScale(ONE, y, ytemp);
 
   /* Set minimum increment based on uround and norm of f */
-  srur = SUNRsqrt(uround);
-  fnorm = N_VWrmsNorm(fy, ewt);
+  srur = SUNRsqrt(cv_mem->cv_uround);
+  fnorm = N_VWrmsNorm(fy, cv_mem->cv_ewt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) * cv_mem->cv_uround * N * fnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing */
   width = mlower + mupper + 1;
@@ -445,31 +542,258 @@ int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
     }
 
     /* Evaluate f with incremented y */
-
-    retval = f(tn, ytemp, ftemp, user_data);
-    nfeDQ++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, ytemp, ftemp, cv_mem->cv_user_data);
+    cvdls_mem->nfeDQ++;
     if (retval != 0) break;
 
     /* Restore ytemp, then form and load difference quotients */
     for (j=group-1; j < N; j+=width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(Jac,j);
+      col_j = SUNBandMatrix_Column(Jac, j);
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-mupper);
       i2 = SUNMIN(j+mlower, N-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
     }
   }
   
   return(retval);
 }
 
+
+/*-----------------------------------------------------------------
+  cvDlsInitialize
+  -----------------------------------------------------------------
+  This routine performs remaining initializations specific
+  to the direct linear solver interface (and solver itself)
+  -----------------------------------------------------------------*/
+int cvDlsInitialize(CVodeMem cv_mem)
+{
+  CVDlsMem cvdls_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", 
+                    "cvDlsInitialize", MSGD_CVMEM_NULL);
+    return(CVDLS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", 
+                    "cvDlsInitialize", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+ 
+  cvDlsInitializeCounters(cvdls_mem);
+
+  /* Set Jacobian function and data, depending on jacDQ (in case 
+     it has changed based on user input) */
+  if (cvdls_mem->jacDQ) {
+    cvdls_mem->jac    = cvDlsDQJac;
+    cvdls_mem->J_data = cv_mem;
+  } else {
+    cvdls_mem->J_data = cv_mem->cv_user_data;
+  }
+
+  /* Call LS initialize routine */
+  cvdls_mem->last_flag = SUNLinSolInitialize(cvdls_mem->LS);
+  return(cvdls_mem->last_flag);
+}
+
+
+/*-----------------------------------------------------------------
+  cvDlsSetup
+  -----------------------------------------------------------------
+  This routine determines whether to update a Jacobian matrix (or
+  use a stored version), based on heuristics regarding previous 
+  convergence issues, the number of time steps since it was last
+  updated, etc.; it then creates the system matrix from this, the
+  'gamma' factor and the identity matrix, 
+    A = I-gamma*J.
+  This routine then calls the LS 'setup' routine with A.
+  -----------------------------------------------------------------*/
+int cvDlsSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+               N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
+               N_Vector vtemp2, N_Vector vtemp3)
+{
+  booleantype jbad, jok;
+  realtype dgamma;
+  CVDlsMem cvdls_mem;
+  int retval;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", 
+                    "cvDlsSetup", MSGD_CVMEM_NULL);
+    return(CVDLS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", 
+                    "cvDlsSetup", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+
+  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
+  dgamma = SUNRabs((cv_mem->cv_gamma/cv_mem->cv_gammap) - ONE);
+  jbad = (cv_mem->cv_nst == 0) || 
+    (cv_mem->cv_nst > cvdls_mem->nstlj + CVD_MSBJ) ||
+    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
+    (convfail == CV_FAIL_OTHER);
+  jok = !jbad;
+ 
+  /* If jok = SUNTRUE, use saved copy of J */
+  if (jok) {
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(cvdls_mem->savedJ, cvdls_mem->A);
+    if (retval) {
+      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
+                      "cvDlsSetup",  MSGD_MATCOPY_FAILED);
+      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+
+  /* If jok = SUNFALSE, call jac routine for new J value */
+  } else {
+    cvdls_mem->nje++;
+    cvdls_mem->nstlj = cv_mem->cv_nst;
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(cvdls_mem->A);
+    if (retval) {
+      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
+                      "cvDlsSetup",  MSGD_MATZERO_FAILED);
+      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+
+    retval = cvdls_mem->jac(cv_mem->cv_tn, ypred, 
+                            fpred, cvdls_mem->A, 
+                            cvdls_mem->J_data, vtemp1, vtemp2, vtemp3);
+    if (retval < 0) {
+      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVDLS", 
+                      "cvDlsSetup",  MSGD_JACFUNC_FAILED);
+      cvdls_mem->last_flag = CVDLS_JACFUNC_UNRECVR;
+      return(-1);
+    }
+    if (retval > 0) {
+      cvdls_mem->last_flag = CVDLS_JACFUNC_RECVR;
+      return(1);
+    }
+
+    retval = SUNMatCopy(cvdls_mem->A, cvdls_mem->savedJ);
+    if (retval) {
+      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
+                      "cvDlsSetup",  MSGD_MATCOPY_FAILED);
+      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+      return(-1);
+    }
+
+  }
+  
+  /* Scale and add I to get A = I - gamma*J */
+  retval = SUNMatScaleAddI(-cv_mem->cv_gamma, cvdls_mem->A);
+  if (retval) {
+    cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVDLS", 
+                   "cvDlsSetup",  MSGD_MATSCALEADDI_FAILED);
+    cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+    return(-1);
+  }
+
+  /* Call generic linear solver 'setup' with this system matrix, and
+     return success/failure flag */
+  cvdls_mem->last_flag = SUNLinSolSetup(cvdls_mem->LS, cvdls_mem->A);
+  return(cvdls_mem->last_flag);
+}
+
+
+/*-----------------------------------------------------------------
+  cvDlsSolve
+  -----------------------------------------------------------------
+  This routine interfaces between CVode and the generic 
+  SUNLinearSolver object LS, by calling the solver and scaling 
+  the solution appropriately when gamrat != 1.
+  -----------------------------------------------------------------*/
+int cvDlsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+               N_Vector ycur, N_Vector fcur)
+{
+  int retval;
+  CVDlsMem cvdls_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", 
+		    "cvDlsSolve", MSGD_CVMEM_NULL);
+    return(CVDLS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", 
+		    "cvDlsSolve", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+
+  /* call the generic linear system solver, and copy b to x */
+  retval = SUNLinSolSolve(cvdls_mem->LS, cvdls_mem->A, cvdls_mem->x, b, ZERO);
+  N_VScale(ONE, cvdls_mem->x, b);
+  
+  /* scale the correction to account for change in gamma */
+  if ((cv_mem->cv_lmm == CV_BDF) && (cv_mem->cv_gamrat != ONE))
+    N_VScale(TWO/(ONE + cv_mem->cv_gamrat), b, b);
+  
+  /* store solver return value and return */
+  cvdls_mem->last_flag = retval;
+  return(retval);
+}
+
+
+/*-----------------------------------------------------------------
+  cvDlsFree
+  -----------------------------------------------------------------
+  This routine frees memory associates with the CVDls solver 
+  interface.
+  -----------------------------------------------------------------*/
+int cvDlsFree(CVodeMem cv_mem)
+{
+  CVDlsMem cvdls_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL)  return (CVDLS_SUCCESS);
+  if (cv_mem->cv_lmem == NULL)  return(CVDLS_SUCCESS);
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+
+  /* Free x vector */
+  if (cvdls_mem->x) {
+    N_VDestroy(cvdls_mem->x);
+    cvdls_mem->x = NULL;
+  }
+
+  /* Free savedJ memory */
+  if (cvdls_mem->savedJ) {
+    SUNMatDestroy(cvdls_mem->savedJ);
+    cvdls_mem->savedJ = NULL;
+  }
+
+  /* Nullify other SUNMatrix pointer */
+  cvdls_mem->A = NULL;
+
+  /* free CVDls interface structure */
+  free(cv_mem->cv_lmem);
+  
+  return(CVDLS_SUCCESS);
+}
+
+
+/*-----------------------------------------------------------------
+  cvDlsInitializeCounters
+  -----------------------------------------------------------------
+  This routine resets the counters inside the CVDlsMem object.
+  -----------------------------------------------------------------*/
 int cvDlsInitializeCounters(CVDlsMem cvdls_mem)
 {
-  cvdls_mem->d_nje   = 0;
-  cvdls_mem->d_nfeDQ = 0;
-  cvdls_mem->d_nstlj = 0;
+  cvdls_mem->nje   = 0;
+  cvdls_mem->nfeDQ = 0;
+  cvdls_mem->nstlj = 0;
   return(0);
 }
diff --git a/src/cvode/cvode_direct_impl.h b/src/cvode/cvode_direct_impl.h
index e189b5f..5958c82 100644
--- a/src/cvode/cvode_direct_impl.h
+++ b/src/cvode/cvode_direct_impl.h
@@ -1,21 +1,23 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
  * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common implementation header file for the CVDLS linear solvers.
+ * Implementation header file for the CVDLS linear solver interface.
  * -----------------------------------------------------------------
  */
 
@@ -23,86 +25,84 @@
 #define _CVDLS_IMPL_H
 
 #include "cvode/cvode_direct.h"
+#include "cvode_impl.h"
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * CVDLS solver constants
- * -----------------------------------------------------------------
- * CVD_MSBJ   maximum number of steps between Jacobian evaluations
- * CVD_DGMAX  maximum change in gamma between Jacobian evaluations
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVDLS solver constants
+  -----------------------------------------------------------------
+  CVD_MSBJ   maximum number of steps between Jacobian evaluations
+  CVD_DGMAX  maximum change in gamma between Jacobian evaluations
+  -----------------------------------------------------------------*/
 
 #define CVD_MSBJ  50
 #define CVD_DGMAX RCONST(0.2)
 
-/*
- * -----------------------------------------------------------------
- * Types : CVDlsMemRec, CVDlsMem                             
- * -----------------------------------------------------------------
- * CVDlsMem is pointer to a CVDlsMemRec structure.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types : CVDlsMemRec, CVDlsMem                             
+  -----------------------------------------------------------------
+  CVDlsMem is pointer to a CVDlsMemRec structure.
+  -----------------------------------------------------------------*/
 
 typedef struct CVDlsMemRec {
 
-  int d_type;             /* SUNDIALS_DENSE or SUNDIALS_BAND              */
+  booleantype jacDQ;    /* SUNTRUE if using internal DQ Jacobian approx. */
+  CVDlsJacFn jac;       /* Jacobian routine to be called                 */
+  void *J_data;         /* user data is passed to jac                    */
 
-  long int d_n;           /* problem dimension                            */
+  SUNMatrix A;          /* A = I - gamma * df/dy                         */
+  SUNMatrix savedJ;     /* savedJ = old Jacobian                         */
 
-  long int d_ml;          /* lower bandwidth of Jacobian                  */
-  long int d_mu;          /* upper bandwidth of Jacobian                  */ 
-  long int d_smu;         /* upper bandwith of M = MIN(N-1,d_mu+d_ml)     */
+  SUNLinearSolver LS;   /* generic direct linear solver object           */
 
-  booleantype d_jacDQ;    /* TRUE if using internal DQ Jacobian approx.   */
-  CVDlsDenseJacFn d_djac; /* dense Jacobian routine to be called          */
-  CVDlsBandJacFn d_bjac;  /* band Jacobian routine to be called           */
-  void *d_J_data;         /* user data is passed to djac or bjac          */
+  N_Vector x;           /* solution vector used by SUNLinearSolver       */
+  
+  long int nstlj;       /* nstlj = nst at last Jacobian eval.            */
 
-  DlsMat d_M;             /* M = I - gamma * df/dy                        */
-  DlsMat d_savedJ;        /* savedJ = old Jacobian                        */
+  long int nje;         /* nje = no. of calls to jac                     */
 
-  int *d_pivots;          /* pivots = int pivot array for PM = LU         */
-  long int *d_lpivots;    /* lpivots = long int pivot array for PM = LU   */
+  long int nfeDQ;       /* no. of calls to f due to DQ Jacobian approx.  */
 
-  long int  d_nstlj;      /* nstlj = nst at last Jacobian eval.           */
+  long int last_flag;   /* last error return flag                        */
 
-  long int d_nje;         /* nje = no. of calls to jac                    */
+} *CVDlsMem;
 
-  long int d_nfeDQ;       /* no. of calls to f due to DQ Jacobian approx. */
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
 
-  long int d_last_flag;   /* last error return flag                       */
+/* difference-quotient Jacobian approximation routines */
+int cvDlsDQJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix Jac,
+               void *data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
   
-} *CVDlsMem;
+int cvDlsDenseDQJac(realtype t, N_Vector y, N_Vector fy, 
+                    SUNMatrix Jac, CVodeMem cv_mem, N_Vector tmp1);
+  
+int cvDlsBandDQJac(realtype t, N_Vector y, N_Vector fy, 
+                   SUNMatrix Jac, CVodeMem cv_mem, N_Vector tmp1, 
+                   N_Vector tmp2);
+  
+/* generic linit/lsetup/lsolve/lfree interface routines for CVode to call */
+int cvDlsInitialize(CVodeMem cv_mem);
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
+int cvDlsSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+               N_Vector fpred, booleantype *jcurPtr,
+               N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); 
 
-int cvDlsDenseDQJac(long int N, realtype t,
-                    N_Vector y, N_Vector fy, 
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-  
-int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
-                   realtype t, N_Vector y, N_Vector fy, 
-                   DlsMat Jac, void *data,
-                   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+int cvDlsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+               N_Vector ycur, N_Vector fcur);
+
+int cvDlsFree(CVodeMem cv_mem);
 
 /* Auxilliary functions */
 int cvDlsInitializeCounters(CVDlsMem cvdls_mem);
 
-/*
- * -----------------------------------------------------------------
- * Error Messages
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Error Messages
+  -----------------------------------------------------------------*/
 
 #define MSGD_CVMEM_NULL "Integrator memory is NULL."
 #define MSGD_BAD_NVECTOR "A required vector operation is not implemented."
@@ -110,6 +110,9 @@ int cvDlsInitializeCounters(CVDlsMem cvdls_mem);
 #define MSGD_MEM_FAIL "A memory request failed."
 #define MSGD_LMEM_NULL "Linear solver memory is NULL."
 #define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
+#define MSGD_MATCOPY_FAILED "The SUNMatCopy routine failed in an unrecoverable manner."
+#define MSGD_MATZERO_FAILED "The SUNMatZero routine failed in an unrecoverable manner."
+#define MSGD_MATSCALEADDI_FAILED "The SUNMatScaleAddI routine failed in an unrecoverable manner."
 
 #ifdef __cplusplus
 }
diff --git a/src/cvode/cvode_impl.h b/src/cvode/cvode_impl.h
index 21d9f38..0313047 100644
--- a/src/cvode/cvode_impl.h
+++ b/src/cvode/cvode_impl.h
@@ -1,20 +1,22 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                Scott D. Cohen, Alan C. Hindmarsh, Radu Serban
+ *                   and Dan Shumaker @ LLNL
  * -----------------------------------------------------------------
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban
- *                and Dan Shumaker @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * Implementation header file for the main CVODE integrator.
  * -----------------------------------------------------------------
@@ -75,7 +77,7 @@ typedef struct CVodeMemRec {
   realtype cv_reltol;        /* relative tolerance                            */
   realtype cv_Sabstol;       /* scalar absolute tolerance                     */
   N_Vector cv_Vabstol;       /* vector absolute tolerance                     */
-  booleantype cv_user_efun;  /* TRUE if user sets efun                        */
+  booleantype cv_user_efun;  /* SUNTRUE if user sets efun                     */
   CVEwtFn cv_efun;           /* function to set ewt                           */
   void *cv_e_data;           /* user pointer passed to efun                   */
 
@@ -184,10 +186,10 @@ typedef struct CVodeMemRec {
     Space requirements for CVODE 
     ----------------------------*/
 
-  long int cv_lrw1;        /* no. of realtype words in 1 N_Vector             */ 
-  long int cv_liw1;        /* no. of integer words in 1 N_Vector              */ 
-  long int cv_lrw;         /* no. of realtype words in CVODE work vectors     */
-  long int cv_liw;         /* no. of integer words in CVODE work vectors      */
+  sunindextype cv_lrw1;        /* no. of realtype words in 1 N_Vector             */ 
+  sunindextype cv_liw1;        /* no. of integer words in 1 N_Vector              */ 
+  long int cv_lrw;             /* no. of realtype words in CVODE work vectors     */
+  long int cv_liw;             /* no. of integer words in CVODE work vectors      */
 
   /*------------------
     Linear Solver Data 
@@ -223,7 +225,6 @@ typedef struct CVodeMemRec {
   realtype cv_tolsf;           /* tolerance scale factor                      */
   int cv_qmax_alloc;           /* value of qmax used when allocating memory   */
   int cv_indx_acor;            /* index of the zn vector with saved acor      */
-  booleantype cv_setupNonNull; /* does setup do anything?                     */
 
   booleantype cv_VabstolMallocDone;
   booleantype cv_MallocDone;  
@@ -355,12 +356,12 @@ typedef struct CVodeMemRec {
  * fpred - f(tn, ypred).
  *
  * jcurPtr - a pointer to a boolean to be filled in by cv_lsetup.
- *           The function should set *jcurPtr=TRUE if its Jacobian
+ *           The function should set *jcurPtr=SUNTRUE if its Jacobian
  *           data is current after the call and should set
- *           *jcurPtr=FALSE if its Jacobian data is not current.
+ *           *jcurPtr=SUNFALSE if its Jacobian data is not current.
  *           Note: If cv_lsetup calls for re-evaluation of
  *           Jacobian data (based on convfail and CVODE state
- *           data), it should return *jcurPtr=TRUE always;
+ *           data), it should return *jcurPtr=SUNTRUE always;
  *           otherwise an infinite loop can result.
  *
  * vtemp1 - temporary N_Vector provided for use by cv_lsetup.
diff --git a/src/cvode/cvode_io.c b/src/cvode/cvode_io.c
index bc50ffb..67ac642 100644
--- a/src/cvode/cvode_io.c
+++ b/src/cvode/cvode_io.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4210 $
- * $Date: 2014-08-27 15:40:02 -0700 (Wed, 27 Aug 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -29,11 +29,6 @@
 #define ZERO RCONST(0.0)
 #define ONE  RCONST(1.0)
 
-#define lrw (cv_mem->cv_lrw)
-#define liw (cv_mem->cv_liw)
-#define lrw1 (cv_mem->cv_lrw1)
-#define liw1 (cv_mem->cv_liw1)
-
 /* 
  * =================================================================
  * CVODE optional input functions
@@ -377,7 +372,7 @@ int CVodeSetStopTime(void *cvode_mem, realtype tstop)
   }
 
   cv_mem->cv_tstop = tstop;
-  cv_mem->cv_tstopset = TRUE;
+  cv_mem->cv_tstopset = SUNTRUE;
 
   return(CV_SUCCESS);
 }
@@ -534,33 +529,6 @@ int CVodeSetNoInactiveRootWarn(void *cvode_mem)
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define nst            (cv_mem->cv_nst)
-#define nfe            (cv_mem->cv_nfe)
-#define ncfn           (cv_mem->cv_ncfn)
-#define netf           (cv_mem->cv_netf)
-#define nni            (cv_mem->cv_nni)
-#define nsetups        (cv_mem->cv_nsetups)
-#define qu             (cv_mem->cv_qu)
-#define next_q         (cv_mem->cv_next_q)
-#define ewt            (cv_mem->cv_ewt)  
-#define hu             (cv_mem->cv_hu)
-#define next_h         (cv_mem->cv_next_h)
-#define h0u            (cv_mem->cv_h0u)
-#define tolsf          (cv_mem->cv_tolsf)  
-#define acor           (cv_mem->cv_acor)
-#define lrw            (cv_mem->cv_lrw)
-#define liw            (cv_mem->cv_liw)
-#define nge            (cv_mem->cv_nge)
-#define iroots         (cv_mem->cv_iroots)
-#define nor            (cv_mem->cv_nor)
-#define sldeton        (cv_mem->cv_sldeton)
-#define tn             (cv_mem->cv_tn)
-#define efun           (cv_mem->cv_efun)
-
 /*
  * CVodeGetNumSteps
  *
@@ -578,7 +546,7 @@ int CVodeGetNumSteps(void *cvode_mem, long int *nsteps)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nsteps = nst;
+  *nsteps = cv_mem->cv_nst;
 
   return(CV_SUCCESS);
 }
@@ -600,7 +568,7 @@ int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nfevals = nfe;
+  *nfevals = cv_mem->cv_nfe;
 
   return(CV_SUCCESS);
 }
@@ -622,7 +590,7 @@ int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nlinsetups = nsetups;
+  *nlinsetups = cv_mem->cv_nsetups;
 
   return(CV_SUCCESS);
 }
@@ -644,7 +612,7 @@ int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *netfails = netf;
+  *netfails = cv_mem->cv_netf;
 
   return(CV_SUCCESS);
 }
@@ -666,7 +634,7 @@ int CVodeGetLastOrder(void *cvode_mem, int *qlast)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *qlast = qu;
+  *qlast = cv_mem->cv_qu;
 
   return(CV_SUCCESS);
 }
@@ -688,7 +656,7 @@ int CVodeGetCurrentOrder(void *cvode_mem, int *qcur)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *qcur = next_q;
+  *qcur = cv_mem->cv_next_q;
 
   return(CV_SUCCESS);
 }
@@ -711,10 +679,10 @@ int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sldeton==FALSE)
+  if (cv_mem->cv_sldeton==SUNFALSE)
     *nslred = 0;
   else
-    *nslred = nor;
+    *nslred = cv_mem->cv_nor;
 
   return(CV_SUCCESS);
 }
@@ -736,7 +704,7 @@ int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *hinused = h0u;
+  *hinused = cv_mem->cv_h0u;
 
   return(CV_SUCCESS);
 }
@@ -758,7 +726,7 @@ int CVodeGetLastStep(void *cvode_mem, realtype *hlast)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *hlast = hu;
+  *hlast = cv_mem->cv_hu;
 
   return(CV_SUCCESS);
 }
@@ -780,7 +748,7 @@ int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur)
 
   cv_mem = (CVodeMem) cvode_mem;
   
-  *hcur = next_h;
+  *hcur = cv_mem->cv_next_h;
 
   return(CV_SUCCESS);
 }
@@ -802,7 +770,7 @@ int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *tcur = tn;
+  *tcur = cv_mem->cv_tn;
 
   return(CV_SUCCESS);
 }
@@ -824,7 +792,7 @@ int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfact)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *tolsfact = tolsf;
+  *tolsfact = cv_mem->cv_tolsf;
 
   return(CV_SUCCESS);
 }
@@ -846,7 +814,7 @@ int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  N_VScale(ONE, ewt, eweight);
+  N_VScale(ONE, cv_mem->cv_ewt, eweight);
 
   return(CV_SUCCESS);
 }
@@ -868,7 +836,7 @@ int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  N_VScale(ONE, acor, ele);
+  N_VScale(ONE, cv_mem->cv_acor, ele);
 
   return(CV_SUCCESS);
 }
@@ -890,8 +858,8 @@ int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *leniw = liw;
-  *lenrw = lrw;
+  *leniw = cv_mem->cv_liw;
+  *lenrw = cv_mem->cv_lrw;
 
   return(CV_SUCCESS);
 }
@@ -916,16 +884,16 @@ int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, long int *nfevals
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nsteps = nst;
-  *nfevals = nfe;
-  *nlinsetups = nsetups;
-  *netfails = netf;
-  *qlast = qu;
-  *qcur = next_q;
-  *hinused = h0u;
-  *hlast = hu;
-  *hcur = next_h;
-  *tcur = tn;
+  *nsteps = cv_mem->cv_nst;
+  *nfevals = cv_mem->cv_nfe;
+  *nlinsetups = cv_mem->cv_nsetups;
+  *netfails = cv_mem->cv_netf;
+  *qlast = cv_mem->cv_qu;
+  *qcur = cv_mem->cv_next_q;
+  *hinused = cv_mem->cv_h0u;
+  *hlast = cv_mem->cv_hu;
+  *hcur = cv_mem->cv_next_h;
+  *tcur = cv_mem->cv_tn;
 
   return(CV_SUCCESS);
 }
@@ -947,7 +915,7 @@ int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *ngevals = nge;
+  *ngevals = cv_mem->cv_nge;
 
   return(CV_SUCCESS);
 }
@@ -972,7 +940,7 @@ int CVodeGetRootInfo(void *cvode_mem, int *rootsfound)
 
   nrt = cv_mem->cv_nrtfn;
 
-  for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+  for (i=0; i<nrt; i++) rootsfound[i] = cv_mem->cv_iroots[i];
 
   return(CV_SUCCESS);
 }
@@ -995,7 +963,7 @@ int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nniters = nni;
+  *nniters = cv_mem->cv_nni;
 
   return(CV_SUCCESS);
 }
@@ -1018,7 +986,7 @@ int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nncfails = ncfn;
+  *nncfails = cv_mem->cv_ncfn;
 
   return(CV_SUCCESS);
 }
@@ -1041,8 +1009,8 @@ int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters,
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nniters = nni;
-  *nncfails = ncfn;
+  *nniters = cv_mem->cv_nni;
+  *nncfails = cv_mem->cv_ncfn;
 
   return(CV_SUCCESS);
 }
diff --git a/src/cvode/cvode_klu.c b/src/cvode/cvode_klu.c
deleted file mode 100644
index 9814c39..0000000
--- a/src/cvode/cvode_klu.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVKLU linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cvode/cvode_klu.h"
-#include "cvode_impl.h"
-#include "cvode_sparse_impl.h"
-#include "sundials/sundials_klu_impl.h"
-#include "sundials/sundials_math.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-#define TWOTHIRDS    RCONST(0.6666666666666667)
-
-/* CVKLU linit, lsetup, lsolve, and lfree routines */
- 
-static int cvKLUInit(CVodeMem cv_mem);
-
-static int cvKLUSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-		      N_Vector fpred, booleantype *jcurPtr,
-		      N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int cvKLUSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-		      N_Vector ycur, N_Vector fcur);
-
-static int cvKLUFree(CVodeMem cv_mem);
-
-/*
- * -----------------------------------------------------------------
- * CVKLU
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the CVODE / KLU linear solver module.  
- * CVKLU first calls the existing lfree routine if this is not NULL.
- * Then it sets the cv_linit, cv_lsetup, cv_lsolve, cv_lperf, and
- * cv_lfree fields in (*cv_mem) to be CVKLUInit, CVKLUSetup,
- * CVKLUSolve, NULL, and CVKLUFree, respectively.
- * It allocates memory for a structure of type CVkluMemRec and sets
- * the cv_lmem field in (*cvode_mem) to the address of this structure.
- * It sets setupNonNull in (*cvode_mem) to TRUE.
- * Finally, it allocates memory for KLU.
- * The return value is CVSLS_SUCCESS = 0, CVSLS_LMEM_FAIL = -1,
- * or CVSLS_ILL_INPUT = -2.
- *
- * NOTE: The KLU linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVKLU will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int CVKLU(void *cvode_mem, int n, int nnz, int sparsetype)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-  int flag;
-
-  /* Return immediately if cv_mem is NULL. */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "cvKLU", 
-                   MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSLS", "cvKLU", 
-                   MSGSP_BAD_NVECTOR);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  if (cv_mem->cv_lfree != NULL) cv_mem->cv_lfree(cv_mem);
-
-  /* Set five main function fields in cv_mem. */
-  cv_mem->cv_linit  = cvKLUInit;
-  cv_mem->cv_lsetup = cvKLUSetup;
-  cv_mem->cv_lsolve = cvKLUSolve;
-  cv_mem->cv_lfree  = cvKLUFree;
-
-  /* Get memory for CVSlsMemRec. */
-  cvsls_mem = (CVSlsMem) malloc(sizeof(struct CVSlsMemRec));
-  if (cvsls_mem == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Get memory for KLUData. */
-  klu_data = (KLUData)malloc(sizeof(struct KLUDataRec));
-  if (klu_data == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  cv_mem->cv_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  cvsls_mem->s_jaceval = NULL;
-  cvsls_mem->s_jacdata = NULL;
-  cvsls_mem->sparsetype = sparsetype;
-
-  /* Allocate memory for the sparse Jacobian */
-  cvsls_mem->s_JacMat = SparseNewMat(n, n, nnz, sparsetype);
-  if (cvsls_mem->s_JacMat == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Allocate memory for saved sparse Jacobian */
-  cvsls_mem->s_savedJ = SparseNewMat(n, n, nnz, sparsetype);
-  if (cvsls_mem->s_savedJ == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Initialize KLU structures */
-  switch (sparsetype) {
-    case CSC_MAT:
-      klu_data->sun_klu_solve = &klu_solve;
-      break;
-    case CSR_MAT:
-      klu_data->sun_klu_solve = &klu_tsolve;
-      break;
-    default:
-      SparseDestroyMat(cvsls_mem->s_JacMat);
-      free(klu_data);
-      free(cvsls_mem);
-      return(CVSLS_ILL_INPUT);
-  }
-  klu_data->s_Symbolic = NULL;
-  klu_data->s_Numeric = NULL;
-
-  /* Set default parameters for KLU */
-  flag = klu_defaults(&klu_data->s_Common);
-  if (flag == 0) {
-    cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_PACKAGE_FAIL);
-    return(CVSLS_PACKAGE_FAIL);
-  }
-
-  /* Set ordering to COLAMD as the cvode default use.
-     Users can set a different value with CVKLUSetOrdering,
-     and the user-set value is loaded before any call to klu_analyze in
-     CVKLUSetup.  */
-  klu_data->s_ordering = 1;
-  klu_data->s_Common.ordering = klu_data->s_ordering;
-
-  /* Attach linear solver memory to the integrator memory */
-  cvsls_mem->s_solver_data = (void *) klu_data;
-  cv_mem->cv_lmem = cvsls_mem;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to CVKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is CVSLS_SUCCESS = 0, CVSLS_MEM_NULL = -1,
- * CVSLS_LMEM_NULL = -2, CVSLS_ILL_INPUT = -3, or CVSLS_MEM_FAIL = -4.
- * -----------------------------------------------------------------
- */
-
-int CVKLUReInit(void *cvode_mem, int n, int nnz, int reinit_type)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if cv_mem is NULL. */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVKLUReInit", 
-                   MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Return immediately if cv_lmem is NULL. */
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(NULL, CVSLS_LMEM_NULL, "CVSLS", "CVKLUReInit", 
-                   MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) (cv_mem->cv_lmem);
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  /* Return if reinit_type is not valid */
-  if ((reinit_type != 1) && (reinit_type != 2)) {
-    cvProcessError(NULL, CVSLS_ILL_INPUT, "CVSLS", "CVKLUReInit", 
-                   MSGSP_ILL_INPUT);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  if (reinit_type == 1) {
-
-    /* Destroy previous Jacobian information */
-    if (cvsls_mem->s_JacMat) {
-      SparseDestroyMat(cvsls_mem->s_JacMat);
-    }
-
-    /* Allocate memory for the sparse Jacobian */
-    cvsls_mem->s_JacMat = SparseNewMat(n, n, nnz, cvsls_mem->sparsetype);
-    if (cvsls_mem->s_JacMat == NULL) {
-      cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "CVKLU", 
-                     MSGSP_MEM_FAIL);
-      return(CVSLS_MEM_FAIL);
-    }
-  }
-
-  /* Free the prior factorazation and reset for first factorization */
-  if( klu_data->s_Symbolic != NULL)
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  if( klu_data->s_Numeric != NULL)
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  cvsls_mem->s_first_factorize = 1;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVKLU interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the CVKLU
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int cvKLUInit(CVodeMem cv_mem)
-{
-  CVSlsMem cvsls_mem;
-
-  cvsls_mem = (CVSlsMem)cv_mem->cv_lmem;
-
-  cvsls_mem->s_jacdata = cv_mem->cv_user_data;
-
-  cvsls_mem->s_nje = 0;
-  /* This forces factorization for every call to CVODE */
-  cvsls_mem->s_first_factorize = 1;
-  cvsls_mem->s_nstlj = 0;
-
-  cvsls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the CVKLU linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     CVSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int cvKLUSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-		      N_Vector fpred, booleantype *jcurPtr,
-		      N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  int retval;
-  long int nst, nstlj;
-  realtype tn, gamma, gammap, dgamma;
-  CVSlsMem cvsls_mem;
-  CVSlsSparseJacFn jaceval;
-  KLUData klu_data;
-  SlsMat JacMat, savedJ;
-  void *jacdata;
-  
-  realtype uround_twothirds;
-
-  uround_twothirds = SUNRpowerR(cv_mem->cv_uround,TWOTHIRDS);
-
-  cvsls_mem = (CVSlsMem) (cv_mem->cv_lmem);
-  tn = cv_mem->cv_tn; 
-  gamma = cv_mem->cv_gamma;
-  gammap = cv_mem->cv_gammap;
-  nst = cv_mem->cv_nst;
-
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  jaceval = cvsls_mem->s_jaceval;
-  jacdata = cvsls_mem->s_jacdata;
-  JacMat = cvsls_mem->s_JacMat;
-  savedJ = cvsls_mem->s_savedJ;
-  nstlj = cvsls_mem->s_nstlj;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    cvProcessError(cv_mem, CVSLS_JAC_NOSET, "CVSLS", "cvKLUSetup", 
-		    MSGSP_JAC_NOSET);
-    free(cvsls_mem); cvsls_mem = NULL;
-    return(CVSLS_JAC_NOSET);
-  }
-
-  /* Determine whether Jacobian needs to be recalculated */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVS_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVS_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    SparseCopyMat(savedJ, JacMat);
-  } else {
-    /* If jok = FALSE, call jac routine for new J value */
-    cvsls_mem->s_nje++;
-    cvsls_mem->s_nstlj = nst;
-    *jcurPtr = TRUE;
-    SparseSetMatToZero(JacMat);
-    retval = jaceval(tn, ypred, fpred, JacMat, jacdata, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVSLS_JACFUNC_UNRECVR, "CVSLS", "cvKLUSetup", MSGSP_JACFUNC_FAILED);
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    SparseCopyMat(JacMat, savedJ);
-  }
-
-  /* Scale and add I to get M = I - gamma*J */
-  SparseScaleMat(-gamma, JacMat);
-  SparseAddIdentityMat(JacMat);
-
-  if (cvsls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get the symbolic factorization
-       ------------------------------------------------------------*/ 
-    /* Update the ordering option with any user-updated values from 
-       calls to CVKLUSetOrdering */
-    klu_data->s_Common.ordering = klu_data->s_ordering;
-
-    if (klu_data->s_Symbolic != NULL) {
-       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    }
-    klu_data->s_Symbolic = klu_analyze(JacMat->NP, JacMat->indexptrs, 
-				       JacMat->indexvals, &(klu_data->s_Common));
-    if (klu_data->s_Symbolic == NULL) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-
-    /* ------------------------------------------------------------
-       Compute the LU factorization of  the Jacobian.
-       ------------------------------------------------------------*/
-    /* If klu_factor previously called, free data */
-    if( klu_data->s_Numeric != NULL) {
-       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    }
-    klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-				     JacMat->data, 
-				     klu_data->s_Symbolic, &(klu_data->s_Common));
-
-    if (klu_data->s_Numeric == NULL) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-
-    cvsls_mem->s_first_factorize = 0;
-  }
-  else {
-
-    retval = klu_refactor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
-			  klu_data->s_Symbolic, klu_data->s_Numeric,
-			  &(klu_data->s_Common));
-    if (retval == 0) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "cvKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-    
-    /*-----------------------------------------------------------
-      Check if a cheap estimate of the reciprocal of the condition 
-      number is getting too small.  If so, delete
-      the prior numeric factorization and recompute it.
-      -----------------------------------------------------------*/
-    
-    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
-		       &(klu_data->s_Common));
-    if (retval == 0) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-
-    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
-      
-      /* Condition number may be getting large.  
-	 Compute more accurate estimate */
-      retval = klu_condest(JacMat->indexptrs, JacMat->data, 
-			   klu_data->s_Symbolic, klu_data->s_Numeric,
-			   &(klu_data->s_Common));
-      if (retval == 0) {
-	cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		       MSGSP_PACKAGE_FAIL);
-	return(CVSLS_PACKAGE_FAIL);
-      }
-      
-      if ( (klu_data->s_Common.condest) > 
-	   (1.0/uround_twothirds) ) {
-
-	/* More accurate estimate also says condition number is 
-	   large, so recompute the numeric factorization */
-
-	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-	
-	klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-					 JacMat->data, klu_data->s_Symbolic, 
-					 &(klu_data->s_Common));
-
-	if (klu_data->s_Numeric == NULL) {
-	  cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-			 MSGSP_PACKAGE_FAIL);
-	  return(CVSLS_PACKAGE_FAIL);
-	}
-      }
-    }
-  }
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-  
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the CVKLU linear
-  solver module.  It calls the KLU solve routine,
-  then returns CVSLS_SUCCESS = 0.
-*/
-
-static int cvKLUSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-		      N_Vector ycur, N_Vector fcur)
-{
-  int flag, lmm;
-  realtype gamrat;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-  SlsMat JacMat;
-  realtype *bd;
-  
-  gamrat = cv_mem->cv_gamrat;
-  lmm = cv_mem->cv_lmm;
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  JacMat = cvsls_mem->s_JacMat;
-
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  bd = N_VGetArrayPointer(b);
-
-  /* Call KLU to solve the linear system */
-  flag = klu_data->sun_klu_solve(klu_data->s_Symbolic, klu_data->s_Numeric, JacMat->NP, 1, bd, 
-                                 &(klu_data->s_Common));
-  if (flag == 0) {
-    cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSolve", 
-		    MSGSP_PACKAGE_FAIL);
-    return(CVSLS_PACKAGE_FAIL);
-  }
-
-  /* Scale the correction to account for change in gamma. */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-  return(CVSLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the CVKLU linear solver.
-*/
-
-static int cvKLUFree(CVodeMem cv_mem)
-{
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-  
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  if( klu_data->s_Numeric != NULL)
-  {
-     klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  }
-  if( klu_data->s_Symbolic != NULL)
-  {
-     klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  }
-
-  if (cvsls_mem->s_JacMat) {
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    cvsls_mem->s_JacMat = NULL;
-  }
-
-  if (cvsls_mem->s_savedJ) {
-    SparseDestroyMat(cvsls_mem->s_savedJ);
-    cvsls_mem->s_savedJ = NULL;
-  }
-
-  free(klu_data); 
-  free(cv_mem->cv_lmem); 
-
-  return(0);
-}
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in CVODE is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int CVKLUSetOrdering(void *cv_mem_v, int ordering_choice)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-
- /* Return immediately if cv_mem is NULL */
-  if (cv_mem_v == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVKLUSetOrdering",
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cv_mem_v;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) ) {
-    cvProcessError(NULL, CVSLS_ILL_INPUT, "CVSLS", "CVKLUSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  klu_data->s_ordering = ordering_choice;
-
-  return(CVSLS_SUCCESS);
-}
diff --git a/src/cvode/cvode_lapack.c b/src/cvode/cvode_lapack.c
deleted file mode 100644
index bb26876..0000000
--- a/src/cvode/cvode_lapack.c
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for a CVODE dense linear solver
- * using BLAS and LAPACK functions.
- * -----------------------------------------------------------------
- */
-
-/*
- * NOTE: the only operation that does not use Blas/Lapack functions
- *       is matrix plus identity (in calculating I-gamma*J in lsetup)
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvode/cvode_lapack.h>
-#include "cvode_direct_impl.h"
-#include "cvode_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constant */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/* CVLAPACK DENSE linit, lsetup, lsolve, and lfree routines */ 
-static int cvLapackDenseInit(CVodeMem cv_mem);
-static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail, 
-                              N_Vector yP, N_Vector fctP, 
-                              booleantype *jcurPtr,
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector fctC);
-static int cvLapackDenseFree(CVodeMem cv_mem);
-
-/* CVLAPACK BAND linit, lsetup, lsolve, and lfree routines */ 
-static int cvLapackBandInit(CVodeMem cv_mem);
-static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, 
-                             N_Vector yP, N_Vector fctP, 
-                             booleantype *jcurPtr,
-                             N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                             N_Vector yC, N_Vector fctC);
-static int cvLapackBandFree(CVodeMem cv_mem);
-
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define lmm            (cv_mem->cv_lmm)
-#define f              (cv_mem->cv_f)
-#define nst            (cv_mem->cv_nst)
-#define tn             (cv_mem->cv_tn)
-#define h              (cv_mem->cv_h)
-#define gamma          (cv_mem->cv_gamma)
-#define gammap         (cv_mem->cv_gammap)
-#define gamrat         (cv_mem->cv_gamrat)
-#define ewt            (cv_mem->cv_ewt)
-
-#define linit          (cv_mem->cv_linit)
-#define lsetup         (cv_mem->cv_lsetup)
-#define lsolve         (cv_mem->cv_lsolve)
-#define lfree          (cv_mem->cv_lfree)
-#define lmem           (cv_mem->cv_lmem)
-#define tempv          (cv_mem->cv_tempv)
-#define setupNonNull   (cv_mem->cv_setupNonNull)
-
-#define mtype          (cvdls_mem->d_type)
-#define n              (cvdls_mem->d_n)
-#define ml             (cvdls_mem->d_ml)
-#define mu             (cvdls_mem->d_mu)
-#define smu            (cvdls_mem->d_smu)
-#define jacDQ          (cvdls_mem->d_jacDQ)
-#define djac           (cvdls_mem->d_djac)
-#define bjac           (cvdls_mem->d_bjac)
-#define M              (cvdls_mem->d_M)
-#define savedJ         (cvdls_mem->d_savedJ)
-#define pivots         (cvdls_mem->d_pivots)
-#define nstlj          (cvdls_mem->d_nstlj)
-#define nje            (cvdls_mem->d_nje)
-#define nfeDQ          (cvdls_mem->d_nfeDQ)
-#define J_data         (cvdls_mem->d_J_data)
-#define last_flag      (cvdls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * -----------------------------------------------------------------
- * CVLapackDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the linear solver module.  CVLapackDense first
- * calls the existing lfree routine if this is not NULL.  Then it sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be cvLapackDenseInit, cvLapackDenseSetup, cvLapackDenseSolve, 
- * and cvLapackDenseFree, respectively.  It allocates memory for a 
- * structure of type CVDlsMemRec and sets the cv_lmem field in 
- * (*cvode_mem) to the address of this structure.  It sets setupNonNull 
- * in (*cvode_mem) to TRUE, and the d_jac field to the default 
- * cvDlsDenseDQJac. Finally, it allocates memory for M, pivots, and 
- * savedJ.
- * The return value is SUCCESS = 0, or LMEM_FAIL = -1.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVLapackDense will first 
- *       test for a compatible N_Vector internal representation 
- *       by checking that N_VGetArrayPointer and N_VSetArrayPointer 
- *       exist.
- * -----------------------------------------------------------------
- */
-int CVLapackDense(void *cvode_mem, int N)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVLAPACK", "CVLapackDense", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the LAPACK solver */
-  if (tempv->ops->nvgetarraypointer == NULL ||
-      tempv->ops->nvsetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVLAPACK", "CVLapackDense", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = cvLapackDenseInit;
-  lsetup = cvLapackDenseSetup;
-  lsolve = cvLapackDenseSolve;
-  lfree  = cvLapackDenseFree;
-
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Initialize Jacobian-related data */
-  jacDQ  = TRUE;
-  djac   = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-  cvDlsInitializeCounters(cvdls_mem);
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = (long int) N;
-
-  /* Allocate memory for M, pivot array, and savedJ */
-  M = NULL;
-  pivots = NULL;
-  savedJ = NULL;
-
-  M = NewDenseMat(n, n);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NewDenseMat(n, n);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyArray(pivots);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVLapackBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module. It first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
- * to be cvLapackBandInit, cvLapackBandSetup, cvLapackBandSolve, 
- * and cvLapackBandFree, respectively.  It allocates memory for a 
- * structure of type CVLapackBandMemRec and sets the cv_lmem field in 
- * (*cvode_mem) to the address of this structure.  It sets setupNonNull 
- * in (*cvode_mem) to be TRUE, mu to be mupper, ml to be mlower, and 
- * the jacE and jacI field to NULL.
- * Finally, it allocates memory for M, pivots, and savedJ.  
- * The CVLapackBand return value is CVDLS_SUCCESS = 0, 
- * CVDLS_MEM_FAIL = -1, or CVDLS_ILL_INPUT = -2.
- *
- * NOTE: The CVLAPACK linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVLapackBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */                  
-int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVLAPACK", "CVLapackBand", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (tempv->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVLAPACK", "CVLapackBand", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */  
-  linit  = cvLapackBandInit;
-  lsetup = cvLapackBandSetup;
-  lsolve = cvLapackBandSolve;
-  lfree  = cvLapackBandFree;
-  
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-
-  /* Initialize Jacobian-related data */
-  jacDQ  = TRUE;
-  bjac   = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-  cvDlsInitializeCounters(cvdls_mem);
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = (long int) N;
-
-  /* Load half-bandwiths in cvdls_mem */
-  ml = (long int) mlower;
-  mu = (long int) mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= n) || (mu >= n)) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVLAPACK", "CVLapackBand", MSGD_BAD_SIZES);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = mu + ml;
-
-  /* Allocate memory for M, pivot array, and savedJ */
-  M = NULL;
-  pivots = NULL;
-  savedJ = NULL;
-
-  M = NewBandMat(n, mu, ml, smu);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }  
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NewBandMat(n, mu, ml, smu);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyArray(pivots);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS
- * =================================================================
- */
-
-/*
- * cvLapackDenseInit does remaining initializations specific to the dense
- * linear solver.
- */
-static int cvLapackDenseInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  cvDlsInitializeCounters(cvdls_mem);
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    djac = cvDlsDenseDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackDenseSetup does the setup operations for the dense linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J
- * updates counters, and calls the dense LU factorization routine.
- */
-static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail,
-                              N_Vector yP, N_Vector fctP,
-                              booleantype *jcurPtr,
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  CVDlsMem cvdls_mem;
-  realtype dgamma, fact;
-  booleantype jbad, jok;
-  int ier, retval, one = 1;
-  int intn, lenmat;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  intn = (int) n;
-  lenmat = M->ldata ;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-    (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    dcopy_f77(&lenmat, savedJ->data, &one, M->data, &one);
-    
-  } else {
-    
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M);
-
-    retval = djac(n, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3);
-
-    if (retval == 0) {
-      dcopy_f77(&lenmat, M->data, &one, savedJ->data, &one);
-    } else if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVLAPACK", "cvLapackDenseSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    } else if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-    
-  }
-
-  /* Scale J by - gamma */
-  fact = -gamma;
-  dscal_f77(&lenmat, &fact, M->data, &one);
-  
-  /* Add identity to get M = I - gamma*J*/
-  AddIdentity(M);
-
-  /* Do LU factorization of M */
-  dgetrf_f77(&intn, &intn, M->data, &intn, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-/*
- * cvLapackDenseSolve handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.
- */
-static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector fctC)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  intn = (int) n;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgetrs_f77("N", &intn, &one, M->data, &intn, pivots, bd, &intn, &ier, 1); 
-
-  if (ier > 0) return(1);
-
-  /* For BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    fact = TWO/(ONE + gamrat);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-  
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackDenseFree frees memory specific to the dense linear solver.
- */
-static int cvLapackDenseFree(CVodeMem cv_mem)
-{
-  CVDlsMem  cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  DestroyMat(M);
-  DestroyArray(pivots);
-  DestroyMat(savedJ);
-  free(cvdls_mem); 
-  cvdls_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS
- * =================================================================
- */
-
-/*
- * cvLapackBandInit does remaining initializations specific to the band
- * linear solver.
- */
-static int cvLapackBandInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  cvDlsInitializeCounters(cvdls_mem);
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    bjac = cvDlsBandDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-  
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackBandSetup does the setup operations for the band linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J, 
- * updates counters, and calls the band LU factorization routine.
- */
-static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, 
-                             N_Vector yP, N_Vector fctP, 
-                             booleantype *jcurPtr,
-                             N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  CVDlsMem cvdls_mem;
-  realtype dgamma, fact;
-  booleantype jbad, jok;
-  int ier, retval, one = 1;
-  int intn, iml, imu, lenmat, ldmat;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  lenmat = M->ldata;
-  ldmat = M->ldim;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-    (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    dcopy_f77(&lenmat, savedJ->data, &one, M->data, &one);
-    
-  } else {
-    
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M);
-
-    retval = bjac(n, mu, ml, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3);
-    if (retval == 0) {
-      dcopy_f77(&lenmat, M->data, &one, savedJ->data, &one);
-    } else if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVLAPACK", "cvLapackBandSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    } else if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-    
-  }
-  
-  /* Scale J by - gamma */
-  fact = -gamma;
-  dscal_f77(&lenmat, &fact, M->data, &one);
-  
-  /* Add identity to get M = I - gamma*J*/
-  AddIdentity(M);
-  
-  /* Do LU factorization of M */
-  dgbtrf_f77(&intn, &intn, &iml, &imu, M->data, &ldmat, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-
-}
-
-/*
- * cvLapackBandSolve handles the solve operation for the band linear solver
- * by calling the band backsolve routine.
- */
-static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                             N_Vector yC, N_Vector fctC)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn, iml, imu, ldmat;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = M->ldim;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgbtrs_f77("N", &intn, &iml, &imu, &one, M->data, &ldmat, pivots, bd, &intn, &ier, 1);
-  if (ier > 0) return(1);
-
-  /* For BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    fact = TWO/(ONE + gamrat);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackBandFree frees memory specific to the band linear solver.
- */
-static int cvLapackBandFree(CVodeMem cv_mem)
-{
-  CVDlsMem  cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  DestroyMat(M);
-  DestroyArray(pivots);
-  DestroyMat(savedJ);
-  free(cvdls_mem); 
-  cvdls_mem = NULL;
-
-  return(0);
-}
-
diff --git a/src/cvode/cvode_sparse.c b/src/cvode/cvode_sparse.c
deleted file mode 100644
index c71996d..0000000
--- a/src/cvode/cvode_sparse.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for an CVSLS linear solver.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cvode_impl.h"
-#include "cvode_sparse_impl.h"
-#include <sundials/sundials_math.h>
-
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * CVSlsSetSparseJacFn specifies the sparse Jacobian function.
- */
-int CVSlsSetSparseJacFn(void *cvode_mem, CVSlsSparseJacFn jac)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSlsSetSparseJacFn", 
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEM_NULL, "CVSLS", 
-		    "CVSlsSetSparseJacFn", MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  cvsls_mem->s_jaceval = jac;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * CVSlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
-int CVSlsGetNumJacEvals(void *cvode_mem, long int *njevals)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSlsGetNumJacEvals", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEM_NULL, "CVSLS", 
-		    "CVSlsGetNumJacEvals", MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  *njevals = cvsls_mem->s_nje;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * CVSlsGetReturnFlagName returns the name associated with a CVSLS
- * return value.
- */
-char *CVSlsGetReturnFlagName(long int flag)
-{
-  char *name;
-
-  name = (char *)malloc(30*sizeof(char));
-
-  switch(flag) {
-  case CVSLS_SUCCESS:
-    sprintf(name,"CVSLS_SUCCESS");
-    break;   
-  case CVSLS_MEM_NULL:
-    sprintf(name,"CVSLS_MEM_NULL");
-    break;
-  case CVSLS_LMEM_NULL:
-    sprintf(name,"CVSLS_LMEM_NULL");
-    break;
-  case CVSLS_ILL_INPUT:
-    sprintf(name,"CVSLS_ILL_INPUT");
-    break;
-  case CVSLS_MEM_FAIL:
-    sprintf(name,"CVSLS_MEM_FAIL");
-    break;
-  case CVSLS_JAC_NOSET:
-    sprintf(name,"CVSLS_JAC_NOSET");
-    break;
-  case CVSLS_JACFUNC_UNRECVR:
-    sprintf(name,"CVSLS_JACFUNC_UNRECVR");
-    break;
-  case CVSLS_JACFUNC_RECVR:
-    sprintf(name,"CVSLS_JACFUNC_RECVR");
-    break;
-  default:
-    sprintf(name,"NONE");
-  }
-
-  return(name);
-}
-
-/*
- * CVSlsGetLastFlag returns the last flag set in a CVSLS function.
- */
-int CVSlsGetLastFlag(void *cvode_mem, long int *flag)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSlsGetLastFlag", 
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEM_NULL, "CVSLS", 
-		    "CVSlsGetLastFlag", MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  *flag = cvsls_mem->s_last_flag;
-
-  return(CVSLS_SUCCESS);
-}
-
diff --git a/src/cvode/cvode_sparse_impl.h b/src/cvode/cvode_sparse_impl.h
deleted file mode 100644
index f50e046..0000000
--- a/src/cvode/cvode_sparse_impl.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Implementation header file for the CVSLS linear solvers.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSPARSE_IMPL_H
-#define _CVSPARSE_IMPL_H
-
-#include "cvode/cvode_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * C V S P A R S E    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * CVSLS solver constants
- * -----------------------------------------------------------------
- * CVS_MSBJ   maximum number of steps between Jacobian evaluations
- * CVS_DGMAX  maximum change in gamma between Jacobian evaluations
- * -----------------------------------------------------------------
- */
- 
-#define CVS_MSBJ  50
-#define CVS_DGMAX RCONST(0.2)
- 
-/*
- * -----------------------------------------------------------------
- * Types : CVSlsMemRec, CVSlsMem                             
- * -----------------------------------------------------------------
- * CVSlsMem is pointer to a CVSlsMemRec structure.
- * -----------------------------------------------------------------
- */
-
-typedef struct CVSlsMemRec {
-
-  CVSlsSparseJacFn s_jaceval; /* user Jacobian evaluation routine 
-				  to be called */
-  void *s_jacdata;           /* J_data is passed to djac or bjac */
-
-  long int s_nje;           /* nje = no. of calls to jac */
-
-  long int s_last_flag;     /* last error return flag */
-
-  int s_first_factorize;    /* flag telling whether the first 
-			       factorization needs to happen */
-
-  int s_nstlj;              /* time step of last Jacobian evaluation */
-
-  SlsMat s_JacMat;          /* M = I - gamma * df/dy */
-
-  SlsMat s_savedJ;          /* saved copy of Jacobian */
-
-  int sparsetype;           /* matrix type: compressed sparse column or row */
-
-  void *s_solver_data;      /* structure for solver-specific data */
-  
-
-} *CVSlsMem;
-
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-  
-
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
-
-#define MSGSP_CVMEM_NULL "Integrator memory is NULL."
-#define MSGSP_BAD_NVECTOR "A required vector operation is not implemented."
-#define MSGSP_MEM_FAIL "A memory request failed."
-#define MSGSP_LMEM_NULL "Linear solver memory is NULL."
-#define MSGSP_ILL_INPUT "Invalid input detected."
-#define MSGSP_JAC_NOSET "Jacobian evaluation function has not been set."
-#define MSGSP_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
-#define MSGSP_PACKAGE_FAIL "A call to an external package failed."
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/cvode/cvode_spbcgs.c b/src/cvode/cvode_spbcgs.c
deleted file mode 100644
index 3fd7ad6..0000000
--- a/src/cvode/cvode_spbcgs.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSPBCG linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvode/cvode_spbcgs.h>
-#include "cvode_spils_impl.h"
-#include "cvode_impl.h"
-
-#include <sundials/sundials_spbcgs.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* CVSPBCG linit, lsetup, lsolve, and lfree routines */
-
-static int CVSpbcgInit(CVodeMem cv_mem);
-
-static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3);
-
-static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow);
-
-static int CVSpbcgFree(CVodeMem cv_mem);
-
-
-/* Readability Replacements */
-
-#define tq           (cv_mem->cv_tq)
-#define nst          (cv_mem->cv_nst)
-#define tn           (cv_mem->cv_tn)
-#define gamma        (cv_mem->cv_gamma)
-#define gammap       (cv_mem->cv_gammap)
-#define f            (cv_mem->cv_f)
-#define user_data    (cv_mem->cv_user_data)
-#define ewt          (cv_mem->cv_ewt)
-#define errfp        (cv_mem->cv_errfp)
-#define mnewt        (cv_mem->cv_mnewt)
-#define linit        (cv_mem->cv_linit)
-#define lsetup       (cv_mem->cv_lsetup)
-#define lsolve       (cv_mem->cv_lsolve)
-#define lfree        (cv_mem->cv_lfree)
-#define lmem         (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define sqrtN     (cvspils_mem->s_sqrtN)   
-#define ytemp     (cvspils_mem->s_ytemp)
-#define x         (cvspils_mem->s_x)
-#define ycur      (cvspils_mem->s_ycur)
-#define fcur      (cvspils_mem->s_fcur)
-#define delta     (cvspils_mem->s_delta)
-#define deltar    (cvspils_mem->s_deltar)
-#define npe       (cvspils_mem->s_npe)
-#define nli       (cvspils_mem->s_nli)
-#define nps       (cvspils_mem->s_nps)
-#define ncfl      (cvspils_mem->s_ncfl)
-#define nstlpre   (cvspils_mem->s_nstlpre)
-#define njtimes   (cvspils_mem->s_njtimes)
-#define nfes      (cvspils_mem->s_nfes)
-#define spils_mem (cvspils_mem->s_spils_mem)
-
-#define jtimesDQ (cvspils_mem->s_jtimesDQ)
-#define jtimes  (cvspils_mem->s_jtimes)
-#define j_data  (cvspils_mem->s_j_data)
-
-#define last_flag (cvspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcg
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the Spbcg linear solver module. CVSpbcg first
- * calls the existing lfree routine if this is not NULL. It then sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be CVSpbcgInit, CVSpbcgSetup, CVSpbcgSolve, and CVSpbcgFree,
- * respectively. It allocates memory for a structure of type
- * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure. It sets setupNonNull in (*cvode_mem),
- * and sets various fields in the CVSpilsMemRec structure.
- * Finally, CVSpbcg allocates memory for ytemp and x, and calls
- * SpbcgMalloc to allocate memory for the Spbcg solver.
- * -----------------------------------------------------------------
- */
-
-int CVSpbcg(void *cvode_mem, int pretype, int maxl)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-  int mxl;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPBCG", "CVSpbcg", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_NVECTOR);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = CVSpbcgInit;
-  lsetup = CVSpbcgSetup;
-  lsolve = CVSpbcgSolve;
-  lfree  = CVSpbcgFree;
-
-  /* Get memory for CVSpilsMemRec */
-  cvspils_mem = NULL;
-  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
-  if (cvspils_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  cvspils_mem->s_type = SPILS_SPBCG;
-
-  /* Set Spbcg parameters that have been passed in call sequence */
-  cvspils_mem->s_pretype = pretype;
-  mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  cvspils_mem->s_pset   = NULL;
-  cvspils_mem->s_psolve = NULL;
-  cvspils_mem->s_pfree  = NULL;
-  cvspils_mem->s_P_data = cv_mem->cv_user_data;
-
-  /* Set default values for the rest of the Spbcg parameters */
-  cvspils_mem->s_eplifac = CVSPILS_EPLIN;
-
-  cvspils_mem->s_last_flag = CVSPILS_SUCCESS;
-
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_PRETYPE);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  x = N_VClone(vec_tmpl);
-  if (x == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SpbcgMalloc to allocate workspace for Spbcg */
-  spbcg_mem = NULL;
-  spbcg_mem = SpbcgMalloc(mxl, vec_tmpl);
-  if (spbcg_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(x);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPBCG memory to spils memory structure */
-  spils_mem = (void *) spbcg_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvspils_mem;
-
-  return(CVSPILS_SUCCESS);
-}
-
-
-
-/* Additional readability replacements */
-
-#define pretype (cvspils_mem->s_pretype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define pset    (cvspils_mem->s_pset)
-#define P_data  (cvspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the Spbcg
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgInit(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-  /* Initialize counters */
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((pretype != PREC_NONE) && (psolve == NULL)) {
-    cvProcessError(cv_mem, -1, "CVSPBCG", "CVSpbcgInit", MSGS_PSOLVE_REQ);
-    last_flag = CVSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  setupNonNull = (pretype != PREC_NONE) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = CVSpilsDQJtimes;
-    j_data = cv_mem;
-  } else {
-    j_data = user_data;
-  }
-
-  /*  Set maxl in the SPBCG memory in case it was changed by the user */
-  spbcg_mem->l_max  = maxl;
-
-  last_flag = CVSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the Spbcg linear solver.
- * It makes a decision as to whether or not to signal for reevaluation
- * of Jacobian data in the pset routine, based on various state
- * variables, then it calls pset. If we signal for reevaluation,
- * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output.
- * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  CVSpilsMem cvspils_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) ||
-      ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
-      (convfail == CV_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, 
-                vtemp1, vtemp2, vtemp3);
-  if (retval < 0) {
-    cvProcessError(cv_mem, SPBCG_PSET_FAIL_UNREC, "CVSPBCG", "CVSpbcgSetup", MSGS_PSET_FAILED);
-    last_flag = SPBCG_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    last_flag = SPBCG_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    npe++;
-    nstlpre = nst;
-  }
-
-  last_flag = SPBCG_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic solver SpbcgSolve
- * for the solution of the linear system Ax = b with the SPBCG method.
- * The solution x is returned in the vector b.
- *
- * If the WRMS norm of b is small, we return x = b (if this is the first
- * Newton iteration) or x = 0 (if a later Newton iteration).
- *
- * Otherwise, we set the tolerance parameter and initial guess (x = 0),
- * call SpbcgSolve, and copy the solution x into b. The x-scaling and
- * b-scaling arrays are both equal to weight.
- *
- * The counters nli, nps, and ncfl are incremented, and the return value
- * is set according to the success of SpbcgSolve. The success flag is
- * returned if SpbcgSolve converged, or if this is the first Newton
- * iteration and the residual norm was reduced below its initial value.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-  int nli_inc, nps_inc, retval;
-  
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  deltar = eplifac * tq[4]; 
-
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= deltar) {
-    if (mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  ycur = ynow;
-  fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SpbcgSolve */  
-  delta = deltar * sqrtN;
-  N_VConst(ZERO, x);
-  
-  /* Call SpbcgSolve and copy x to b */
-  retval = SpbcgSolve(spbcg_mem, cv_mem, x, b, pretype, delta,
-                   cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve,
-                   &res_norm, &nli_inc, &nps_inc);
-
-  N_VScale(ONE, x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPBCG_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpbcgSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPBCG_SUCCESS:
-    return(0);
-    break;
-  case SPBCG_RES_REDUCED:
-    if (mnewt == 0) return(0);
-    else            return(1);
-    break;
-  case SPBCG_CONV_FAIL:
-    return(1);
-    break;
-  case SPBCG_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_MEM_NULL:
-    return(-1);
-    break;
-  case SPBCG_ATIMES_FAIL_UNREC:
-    cvProcessError(cv_mem, SPBCG_ATIMES_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPBCG_PSOLVE_FAIL_UNREC:
-    cvProcessError(cv_mem, SPBCG_PSOLVE_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the Spbcg linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgFree(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(x);
-
-  spbcg_mem = (SpbcgMem) spils_mem;
-  SpbcgFree(spbcg_mem);
-
-  if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem);
-
-  free(cvspils_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
diff --git a/src/cvode/cvode_spgmr.c b/src/cvode/cvode_spgmr.c
deleted file mode 100644
index 1f53d7c..0000000
--- a/src/cvode/cvode_spgmr.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
- *                Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSPGMR linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvode/cvode_spgmr.h>
-#include "cvode_spils_impl.h"
-#include "cvode_impl.h"
-
-#include <sundials/sundials_spgmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* CVSPGMR linit, lsetup, lsolve, and lfree routines */
-
-static int CVSpgmrInit(CVodeMem cv_mem);
-
-static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3);
-
-static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow);
-
-static int CVSpgmrFree(CVodeMem cv_mem);
-
-/* Readability Replacements */
-
-#define tq           (cv_mem->cv_tq)
-#define nst          (cv_mem->cv_nst)
-#define tn           (cv_mem->cv_tn)
-#define h            (cv_mem->cv_h)
-#define gamma        (cv_mem->cv_gamma)
-#define gammap       (cv_mem->cv_gammap)   
-#define f            (cv_mem->cv_f)
-#define user_data    (cv_mem->cv_user_data)
-#define ewt          (cv_mem->cv_ewt)
-#define mnewt        (cv_mem->cv_mnewt)
-#define ropt         (cv_mem->cv_ropt)
-#define linit        (cv_mem->cv_linit)
-#define lsetup       (cv_mem->cv_lsetup)
-#define lsolve       (cv_mem->cv_lsolve)
-#define lfree        (cv_mem->cv_lfree)
-#define lmem         (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define sqrtN   (cvspils_mem->s_sqrtN)   
-#define ytemp   (cvspils_mem->s_ytemp)
-#define x       (cvspils_mem->s_x)
-#define ycur    (cvspils_mem->s_ycur)
-#define fcur    (cvspils_mem->s_fcur)
-#define delta   (cvspils_mem->s_delta)
-#define deltar  (cvspils_mem->s_deltar)
-#define npe     (cvspils_mem->s_npe)
-#define nli     (cvspils_mem->s_nli)
-#define nps     (cvspils_mem->s_nps)
-#define ncfl    (cvspils_mem->s_ncfl)
-#define nstlpre (cvspils_mem->s_nstlpre)
-#define njtimes (cvspils_mem->s_njtimes)
-#define nfes    (cvspils_mem->s_nfes)
-#define spils_mem (cvspils_mem->s_spils_mem)
-
-#define jtimesDQ (cvspils_mem->s_jtimesDQ)
-#define jtimes  (cvspils_mem->s_jtimes)
-#define j_data  (cvspils_mem->s_j_data)
-
-#define last_flag (cvspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmr
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the Spgmr linear solver module. CVSpgmr first
- * calls the existing lfree routine if this is not NULL.  It then sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be CVSpgmrInit, CVSpgmrSetup, CVSpgmrSolve, and CVSpgmrFree,
- * respectively.  It allocates memory for a structure of type
- * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure.  It sets setupNonNull in (*cvode_mem),
- * and sets various fields in the CVSpilsMemRec structure.
- * Finally, CVSpgmr allocates memory for ytemp and x, and calls
- * SpgmrMalloc to allocate memory for the Spgmr solver.
- * -----------------------------------------------------------------
- */
-
-int CVSpgmr(void *cvode_mem, int pretype, int maxl)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-  SpgmrMem spgmr_mem;
-  int mxl;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPGMR", "CVSpgmr", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Check if N_VDotProd is present */
-  if(vec_tmpl->ops->nvdotprod == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_NVECTOR);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = CVSpgmrInit;
-  lsetup = CVSpgmrSetup;
-  lsolve = CVSpgmrSolve;
-  lfree  = CVSpgmrFree;
-
-  /* Get memory for CVSpilsMemRec */
-  cvspils_mem = NULL;
-  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
-  if (cvspils_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  cvspils_mem->s_type = SPILS_SPGMR;
-
-  /* Set Spgmr parameters that have been passed in call sequence */
-  cvspils_mem->s_pretype    = pretype;
-  mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  cvspils_mem->s_pset   = NULL;
-  cvspils_mem->s_psolve = NULL;
-  cvspils_mem->s_pfree  = NULL;
-  cvspils_mem->s_P_data = cv_mem->cv_user_data;
-
-  /* Set default values for the rest of the Spgmr parameters */
-  cvspils_mem->s_gstype = MODIFIED_GS;
-  cvspils_mem->s_eplifac = CVSPILS_EPLIN;
-
-  cvspils_mem->s_last_flag  = CVSPILS_SUCCESS;
-
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_PRETYPE);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  x = N_VClone(vec_tmpl);
-  if (x == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt( N_VDotProd(ytemp, ytemp) );
-
-  /* Call SpgmrMalloc to allocate workspace for Spgmr */
-  spgmr_mem = NULL;
-  spgmr_mem = SpgmrMalloc(mxl, vec_tmpl);
-  if (spgmr_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(x);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPGMR memory to spils memory structure */
-  spils_mem = (void *) spgmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvspils_mem;
-
-  return(CVSPILS_SUCCESS);
-}
-
-
-/* Additional readability Replacements */
-
-#define pretype (cvspils_mem->s_pretype)
-#define gstype  (cvspils_mem->s_gstype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define pset    (cvspils_mem->s_pset)
-#define P_data  (cvspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the Spgmr 
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrInit(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Initialize counters */
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((pretype != PREC_NONE) && (psolve == NULL)) {
-    cvProcessError(cv_mem, -1, "CVSPGMR", "CVSpgmrInit", MSGS_PSOLVE_REQ);
-    last_flag = CVSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning (pretype != PREC_NONE)
-     and there is a preconditioning setup phase (pset != NULL)             */
-  setupNonNull = (pretype != PREC_NONE) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = CVSpilsDQJtimes;
-    j_data = cv_mem;
-  } else {
-    j_data = user_data;
-  }
-
-  last_flag = CVSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the Spgmr linear solver.
- * It makes a decision as to whether or not to signal for re-evaluation
- * of Jacobian data in the pset routine, based on various state
- * variables, then it calls pset.  If we signal for re-evaluation,
- * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output.
- * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  CVSpilsMem cvspils_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) ||
-    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
-    (convfail == CV_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, 
-                vtemp1, vtemp2, vtemp3);
-  if (retval < 0) {
-    cvProcessError(cv_mem, SPGMR_PSET_FAIL_UNREC, "CVSPGMR", "CVSpgmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPGMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    last_flag = SPGMR_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    npe++;
-    nstlpre = nst;
-  }
-
-  last_flag = SPGMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic solver SpgmrSolve
- * for the solution of the linear system Ax = b with the SPGMR method,
- * without restarts.  The solution x is returned in the vector b.
- *
- * If the WRMS norm of b is small, we return x = b (if this is the first
- * Newton iteration) or x = 0 (if a later Newton iteration).
- *
- * Otherwise, we set the tolerance parameter and initial guess (x = 0),
- * call SpgmrSolve, and copy the solution x into b.  The x-scaling and
- * b-scaling arrays are both equal to weight, and no restarts are allowed.
- *
- * The counters nli, nps, and ncfl are incremented, and the return value
- * is set according to the success of SpgmrSolve.  The success flag is
- * returned if SpgmrSolve converged, or if this is the first Newton
- * iteration and the residual norm was reduced below its initial value.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  CVSpilsMem cvspils_mem;
-  SpgmrMem spgmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  deltar = eplifac * tq[4]; 
-
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= deltar) {
-    if (mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  ycur = ynow;
-  fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SpgmrSolve */  
-  delta = deltar * sqrtN;
-  N_VConst(ZERO, x);
-  
-  /* Call SpgmrSolve and copy x to b */
-  retval = SpgmrSolve(spgmr_mem, cv_mem, x, b, pretype, gstype, delta, 0,
-                      cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve,
-                      &res_norm, &nli_inc, &nps_inc);
-
-  N_VScale(ONE, x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPGMR_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPGMR_SUCCESS:
-    return(0);
-    break;
-  case SPGMR_RES_REDUCED:
-    if (mnewt == 0) return(0);
-    else            return(1);
-    break;
-  case SPGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPGMR_ATIMES_FAIL_UNREC:
-    cvProcessError(cv_mem, SPGMR_ATIMES_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPGMR_PSOLVE_FAIL_UNREC:
-    cvProcessError(cv_mem, SPGMR_PSOLVE_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the Spgmr linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrFree(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SpgmrMem spgmr_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-  
-  N_VDestroy(ytemp);
-  N_VDestroy(x);
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-  SpgmrFree(spgmr_mem);
-
-  if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem);
-
-  free(cvspils_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
diff --git a/src/cvode/cvode_spils.c b/src/cvode/cvode_spils.c
index 5bcdc9e..1a05b07 100644
--- a/src/cvode/cvode_spils.c
+++ b/src/cvode/cvode_spils.c
@@ -1,21 +1,24 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the implementation file for the CVSPILS linear solvers.
+ * This is the implementation file for the CVSPILS linear solver
+ * interface.
  * -----------------------------------------------------------------
  */
 
@@ -24,6 +27,7 @@
 
 #include "cvode_impl.h"
 #include "cvode_spils_impl.h"
+#include <sundials/sundials_math.h>
 
 /* Private constants */
 
@@ -35,514 +39,508 @@
 
 #define MAX_ITERS  3  /* max. number of attempts to recover in DQ J*v */
 
-/* Readability Replacements */
-
-#define lrw1      (cv_mem->cv_lrw1)
-#define liw1      (cv_mem->cv_liw1)
-#define tq        (cv_mem->cv_tq)
-#define tn        (cv_mem->cv_tn)
-#define h         (cv_mem->cv_h)
-#define gamma     (cv_mem->cv_gamma)
-#define nfe       (cv_mem->cv_nfe)
-#define f         (cv_mem->cv_f)
-#define user_data (cv_mem->cv_user_data)
-#define ewt       (cv_mem->cv_ewt)
-#define lmem      (cv_mem->cv_lmem)
-
-#define ils_type  (cvspils_mem->s_type)
-#define sqrtN     (cvspils_mem->s_sqrtN)   
-#define ytemp     (cvspils_mem->s_ytemp)
-#define x         (cvspils_mem->s_x)
-#define ycur      (cvspils_mem->s_ycur)
-#define fcur      (cvspils_mem->s_fcur)
-#define delta     (cvspils_mem->s_delta)
-#define npe       (cvspils_mem->s_npe)
-#define nli       (cvspils_mem->s_nli)
-#define nps       (cvspils_mem->s_nps)
-#define ncfl      (cvspils_mem->s_ncfl)
-#define njtimes   (cvspils_mem->s_njtimes)
-#define nfes      (cvspils_mem->s_nfes)
-
-#define jtimesDQ  (cvspils_mem->s_jtimesDQ)
-#define jtimes    (cvspils_mem->s_jtimes)
-#define j_data    (cvspils_mem->s_j_data)
-
-#define last_flag (cvspils_mem->s_last_flag)
 
-/*
- * -----------------------------------------------------------------
- * OPTIONAL INPUT and OUTPUT
- * -----------------------------------------------------------------
- */
-
-
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetPrecType
- * -----------------------------------------------------------------
- */
+/*===============================================================
+  CVSPILS Exported functions -- Required
+===============================================================*/
 
-int CVSpilsSetPrecType(void *cvode_mem, int pretype)
+/*---------------------------------------------------------------
+ CVSpilsSetLinearSolver specifies the iterative linear solver.
+---------------------------------------------------------------*/
+int CVSpilsSetLinearSolver(void *cvode_mem, SUNLinearSolver LS)
 {
+  int retval;
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+		    "CVSpilsSetLinearSolver", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
+  if (LS == NULL) {
+    cvProcessError(NULL, CVSPILS_ILL_INPUT, "CVSPILS", 
+		    "CVSpilsSetLinearSolver", 
+                    "LS must be non-NULL");
+    return(CVSPILS_ILL_INPUT);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_LMEM_NULL);
-    return(CVSPILS_LMEM_NULL);
+  /* Test if solver and vector are compatible with SPILS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_ITERATIVE) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", 
+                    "CVSpilsSetLinearSolver", 
+                    "Non-iterative LS supplied to CVSpils interface");
+    return(CVSPILS_ILL_INPUT);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPrecType", MSGS_BAD_PRETYPE);
+  if ( (cv_mem->cv_tempv->ops->nvlinearsum == NULL) ||
+       (cv_mem->cv_tempv->ops->nvconst == NULL) ||
+       (cv_mem->cv_tempv->ops->nvdotprod == NULL) ){
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_BAD_NVECTOR);
     return(CVSPILS_ILL_INPUT);
   }
 
-  cvspils_mem->s_pretype = pretype;
+  /* free any existing system solver attached to CVode */
+  if (cv_mem->cv_lfree)  cv_mem->cv_lfree(cv_mem);
 
-  return(CVSPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetGSType
- * -----------------------------------------------------------------
- */
-
-int CVSpilsSetGSType(void *cvode_mem, int gstype)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
+  /* Set four main system linear solver function fields in cv_mem */
+  cv_mem->cv_linit  = cvSpilsInitialize;
+  cv_mem->cv_lsetup = cvSpilsSetup;
+  cv_mem->cv_lsolve = cvSpilsSolve;
+  cv_mem->cv_lfree  = cvSpilsFree;
+  
+  /* Get memory for CVSpilsMemRec */
+  cvspils_mem = NULL;
+  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
+  if (cvspils_mem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
   }
-  cv_mem = (CVodeMem) cvode_mem;
 
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_LMEM_NULL);
-    return(CVSPILS_LMEM_NULL);
+  /* set SUNLinearSolver pointer */
+  cvspils_mem->LS = LS;
+  
+  /* Set defaults for Jacobian-related fields */
+  cvspils_mem->jtimesDQ = SUNTRUE;
+  cvspils_mem->jtsetup = NULL;
+  cvspils_mem->jtimes = CVSpilsDQJtimes;
+  cvspils_mem->j_data = cv_mem;
+
+  /* Set defaults for preconditioner-related fields */
+  cvspils_mem->pset   = NULL;
+  cvspils_mem->psolve = NULL;
+  cvspils_mem->pfree  = NULL;
+  cvspils_mem->P_data = cv_mem->cv_user_data;
+
+  /* Initialize counters */
+  cvSpilsInitializeCounters(cvspils_mem);
+
+  /* Set default values for the rest of the SPILS parameters */
+  cvspils_mem->jbad = SUNTRUE;
+  cvspils_mem->eplifac = CVSPILS_EPLIN;
+  cvspils_mem->last_flag = CVSPILS_SUCCESS;
+
+  /* Attach default CVSpils interface routines to iterative LS */
+  retval = SUNLinSolSetATimes(LS, cv_mem, CVSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSPILS", 
+                    "CVSpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetATimes");
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_SUNLS_FAIL);
+  }
+  retval = SUNLinSolSetPreconditioner(LS, cv_mem, NULL, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSPILS", 
+                    "CVSpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_SUNLS_FAIL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
 
-  if (ils_type != SPILS_SPGMR) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_LSTYPE);
-    return(CVSPILS_ILL_INPUT);
+  /* Allocate memory for ytemp and x */
+  cvspils_mem->ytemp = N_VClone(cv_mem->cv_tempv);
+  if (cvspils_mem->ytemp == NULL) {
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_MEM_FAIL);
   }
 
-  /* Check for legal gstype */
-  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_GSTYPE);
-    return(CVSPILS_ILL_INPUT);
+  cvspils_mem->x = N_VClone(cv_mem->cv_tempv);
+  if (cvspils_mem->x == NULL) {
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    N_VDestroy(cvspils_mem->ytemp);
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_MEM_FAIL);
   }
 
-  cvspils_mem->s_gstype = gstype;
+  /* Compute sqrtN from a dot product */
+  N_VConst(ONE, cvspils_mem->ytemp);
+  cvspils_mem->sqrtN = SUNRsqrt( N_VDotProd(cvspils_mem->ytemp, 
+                                            cvspils_mem->ytemp) );
+
+  /* Attach linear solver memory to integrator memory */
+  cv_mem->cv_lmem = cvspils_mem;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : CVSpilsSetMaxl
- * -----------------------------------------------------------------
- */
 
-int CVSpilsSetMaxl(void *cvode_mem, int maxl)
+/*===============================================================
+  CVSPILS Exported functions -- Optional input/output
+===============================================================*/
+
+
+int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
-  int mxl;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsSetEpsLin", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(NULL, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsSetEpsLin", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (ils_type == SPILS_SPGMR) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetMaxl", MSGS_BAD_LSTYPE);
+  /* Check for legal eplifac */
+  if(eplifac < ZERO) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS",
+                   "CVSpilsSetEpsLin", MSGS_BAD_EPLIN);
     return(CVSPILS_ILL_INPUT);
   }
 
-  mxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-  cvspils_mem->s_maxl = mxl;
+  cvspils_mem->eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac;
 
   return(CVSPILS_SUCCESS);
 }
 
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetEpsLin
- * -----------------------------------------------------------------
- */
-
-int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac)
+int CVSpilsSetPreconditioner(void *cvode_mem, 
+                             CVSpilsPrecSetupFn psetup,
+                             CVSpilsPrecSolveFn psolve)
 {
+  int retval;
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
+  PSetupFn cvspils_psetup;
+  PSolveFn cvspils_psolve;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsSetPreconditioner", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsSetPreconditioner", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Check for legal eplifac */
-  if(eplifac < ZERO) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetEpsLin", MSGS_BAD_EPLIN);
-    return(CVSPILS_ILL_INPUT);
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* store function pointers for user-supplied routines in CVSpils interface */
+  cvspils_mem->pset   = psetup;
+  cvspils_mem->psolve = psolve;
+
+  /* notify iterative linear solver to call CVSpils interface routines */
+  cvspils_psetup = (psetup == NULL) ? NULL : CVSpilsPSetup;
+  cvspils_psolve = (psolve == NULL) ? NULL : CVSpilsPSolve;
+  retval = SUNLinSolSetPreconditioner(cvspils_mem->LS, cv_mem, 
+                                      cvspils_psetup, cvspils_psolve);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSPILS", 
+                   "CVSpilsSetPreconditioner", 
+                   "Error in calling SUNLinSolSetPreconditioner");
+    return(CVSPILS_SUNLS_FAIL);
   }
 
-  cvspils_mem->s_eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac;
-
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetPrecSetupFn
- * -----------------------------------------------------------------
- */
 
-int CVSpilsSetPreconditioner(void *cvode_mem, 
-                             CVSpilsPrecSetupFn pset, CVSpilsPrecSolveFn psolve)
+int CVSpilsSetJacTimes(void *cvode_mem,
+                       CVSpilsJacTimesSetupFn jtsetup,
+                       CVSpilsJacTimesVecFn jtimes)
 {
+  int retval;
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsSetJacTimes", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsSetJacTimes", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  cvspils_mem->s_pset = pset;
-  cvspils_mem->s_psolve = psolve;
+  /* store function pointers for user-supplied routines in CVSpils 
+     interface (NULL jtimes implies use of DQ default) */
+  if (jtimes != NULL) {
+    cvspils_mem->jtimesDQ = SUNFALSE;
+    cvspils_mem->jtimes   = jtimes;
+  } else {
+    cvspils_mem->jtimesDQ = SUNTRUE;
+  }
+  cvspils_mem->jtsetup = jtsetup;
+
+  /* notify iterative linear solver to call CVSpils interface routines */
+  retval = SUNLinSolSetATimes(cvspils_mem->LS, cv_mem, CVSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSPILS", 
+                    "CVSpilsSetJacTimes", 
+                    "Error in calling SUNLinSolSetATimes");
+    return(CVSPILS_SUNLS_FAIL);
+  }
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetJacTimesVecFn
- * -----------------------------------------------------------------
- */
 
-int CVSpilsSetJacTimesVecFn(void *cvode_mem, CVSpilsJacTimesVecFn jtv)
+int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS,
+                        long int *leniwLS)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetWorkSpace", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetWorkSpace", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (jtv != NULL) {
-    jtimesDQ = FALSE;
-    jtimes = jtv;
-  } else {
-    jtimesDQ = TRUE;
+  /* start with fixed sizes plus NVectors */
+  *lenrwLS = 4;
+  *leniwLS = 10;
+
+  /* add NVector sizes */
+  if (cv_mem->cv_tempv->ops->nvspace) {
+    N_VSpace(cv_mem->cv_tempv, &lrw1, &liw1);
+    *lenrwLS += 2*lrw1;
+    *leniwLS += 2*liw1;
+  }
+
+  /* add LS sizes */
+  if (cvspils_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(cvspils_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetWorkSpace
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
-  int maxl;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumPrecEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  
-  switch(ils_type) {
-  case SPILS_SPGMR:
-    maxl = cvspils_mem->s_maxl;
-    *lenrwLS = lrw1*(maxl + 5) + maxl*(maxl + 4) + 1;
-    *leniwLS = liw1*(maxl + 5);
-    break;
-  case SPILS_SPBCG:
-    *lenrwLS = lrw1 * 9;
-    *leniwLS = liw1 * 9;
-    break;
-  case SPILS_SPTFQMR:
-    *lenrwLS = lrw1*11;
-    *leniwLS = liw1*11;
-    break;
-  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
+  *npevals = cvspils_mem->npe;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumPrecEvals
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals)
+int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumPrecSolves", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *npevals = npe;
+  *npsolves = cvspils_mem->nps;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumPrecSolves
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves)
+int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumLinIters", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumLinIters", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *npsolves = nps;
+  *nliters = cvspils_mem->nli;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumLinIters
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters)
+int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumConvFails", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumConvFails", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *nliters = nli;
+  *nlcfails = cvspils_mem->ncfl;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumConvFails
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails)
+int CVSpilsGetNumJTSetupEvals(void *cvode_mem, long int *njtsetups)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumJTSetupEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumJTSetupEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *nlcfails = ncfl;
+  *njtsetups = cvspils_mem->njtsetup;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumJtimesEvals
- * -----------------------------------------------------------------
- */
 
 int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumJtimesEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *njvevals = njtimes;
+  *njvevals = cvspils_mem->njtimes;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumRhsEvals
- * -----------------------------------------------------------------
- */
 
 int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumRhsEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetNumRhsEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *nfevalsLS = nfes;
+  *nfevalsLS = cvspils_mem->nfes;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetLastFlag
- * -----------------------------------------------------------------
- */
 
 int CVSpilsGetLastFlag(void *cvode_mem, long int *flag)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS",
+                   "CVSpilsGetLastFlag", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS",
+                   "CVSpilsGetLastFlag", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *flag = last_flag;
+  *flag = cvspils_mem->last_flag;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetReturnFlagName
- * -----------------------------------------------------------------
- */
 
 char *CVSpilsGetReturnFlagName(long int flag)
 {
@@ -569,6 +567,9 @@ char *CVSpilsGetReturnFlagName(long int flag)
   case CVSPILS_PMEM_NULL:
     sprintf(name,"CVSPILS_PMEM_NULL");
     break;
+  case CVSPILS_SUNLS_FAIL:
+    sprintf(name,"CVSPILS_SUNLS_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -576,107 +577,172 @@ char *CVSpilsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSPILS private functions
- * -----------------------------------------------------------------
- */
-
-
-/* Additional readability Replacements */
+/*=================================================================
+  CVSPILS private functions
+  =================================================================*/
 
-#define pretype (cvspils_mem->s_pretype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define P_data  (cvspils_mem->s_P_data)
+/*-----------------------------------------------------------------
+  CVSpilsATimes
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsAtimes
- * -----------------------------------------------------------------
- * This routine generates the matrix-vector product z = Mv, where
- * M = I - gamma*J. The product J*v is obtained by calling the jtimes 
- * routine. It is then scaled by -gamma and added to v to obtain M*v.
- * The return value is the same as the value returned by jtimes --
- * 0 if successful, nonzero otherwise.
- * -----------------------------------------------------------------
- */
-
-int CVSpilsAtimes(void *cvode_mem, N_Vector v, N_Vector z)
+  This routine generates the matrix-vector product z = Mv, where
+  M = I - gamma*J. The product J*v is obtained by calling the jtimes 
+  routine. It is then scaled by -gamma and added to v to obtain M*v.
+  The return value is the same as the value returned by jtimes --
+  0 if successful, nonzero otherwise.
+  -----------------------------------------------------------------*/
+int CVSpilsATimes(void *cvode_mem, N_Vector v, N_Vector z)
 {
   CVodeMem   cv_mem;
   CVSpilsMem cvspils_mem;
   int jtflag;
 
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+                   "CVSpilsATimes", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  jtflag = jtimes(v, z, tn, ycur, fcur, j_data, ytemp);
-  njtimes++;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", 
+                   "CVSpilsATimes", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  jtflag = cvspils_mem->jtimes(v, z, cv_mem->cv_tn,
+                               cvspils_mem->ycur,
+                               cvspils_mem->fcur,
+                               cvspils_mem->j_data,
+                               cvspils_mem->ytemp);
+  cvspils_mem->njtimes++;
   if (jtflag != 0) return(jtflag);
 
-  N_VLinearSum(ONE, v, -gamma, z, z);
+  N_VLinearSum(ONE, v, -cv_mem->cv_gamma, z, z);
 
   return(0);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsPSolve
- * -----------------------------------------------------------------
- * This routine interfaces between the generic Sp***Solve routine
- * (within the SPGMR, SPBCG, or SPTFQMR solver) and the
- * user's psolve routine.  It passes to psolve all required state 
- * information from cvode_mem.  Its return value is the same as that
- * returned by psolve. Note that the generic SP*** solver guarantees
- * that CVSpilsPSolve will not be called in the case in which
- * preconditioning is not done. This is the only case in which the
- * user's psolve routine is allowed to be NULL.
- * -----------------------------------------------------------------
- */
 
-int CVSpilsPSolve(void *cvode_mem, N_Vector r, N_Vector z, int lr)
+/*---------------------------------------------------------------
+ CVSpilsPSetup:
+
+ This routine interfaces between the generic iterative linear 
+ solvers and the user's psetup routine.  It passes to psetup all 
+ required state information from cvode_mem.  Its return value 
+ is the same as that returned by psetup. Note that the generic
+ iterative linear solvers guarantee that CVSpilsPSetup will only
+ be called in the case that the user's psetup routine is non-NULL.
+---------------------------------------------------------------*/
+int CVSpilsPSetup(void *cvode_mem)
 {
+  int        retval;
   CVodeMem   cv_mem;
   CVSpilsMem cvspils_mem;
-  int retval;
 
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+                   "CVSpilsPSetup", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
-  cvspils_mem = (CVSpilsMem)lmem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", 
+                   "CVSpilsPSetup", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* Call user pset routine to update preconditioner and possibly 
+     reset jcur (pass !jbad as update suggestion) */
+  retval = cvspils_mem->pset(cv_mem->cv_tn, 
+                             cvspils_mem->ycur, 
+                             cvspils_mem->fcur, 
+                             !(cvspils_mem->jbad),
+                             &cv_mem->cv_jcur,
+                             cv_mem->cv_gamma, 
+                             cvspils_mem->P_data);
+  return(retval);     
+}
 
-  /* This call is counted in nps within the CVSp***Solve routine */
-  retval = psolve(tn, ycur, fcur, r, z, gamma, delta, lr, P_data, ytemp);
 
+/*-----------------------------------------------------------------
+  CVSpilsPSolve
+
+  This routine interfaces between the generic SUNLinSolSolve 
+  routine and the user's psolve routine.  It passes to psolve all
+  required state information from cvode_mem.  Its return value is 
+  the same as that returned by psolve. Note that the generic 
+  SUNLinSol solver guarantees that CVSpilsPSolve will not be called 
+  in the case in which preconditioning is not done. This is the 
+  only case in which the user's psolve routine is allowed to be 
+  NULL.
+  -----------------------------------------------------------------*/
+int CVSpilsPSolve(void *cvode_mem, N_Vector r, N_Vector z,
+                  realtype tol, int lr)
+{
+  CVodeMem   cv_mem;
+  CVSpilsMem cvspils_mem;
+  int retval;
+
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+                   "CVSpilsPSolve", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  cv_mem = (CVodeMem) cvode_mem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", 
+                   "CVSpilsPSolve", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* call the user-supplied psolve routine, and accumulate count */
+  retval = cvspils_mem->psolve(cv_mem->cv_tn, cvspils_mem->ycur,
+                               cvspils_mem->fcur, r, z,
+                               cv_mem->cv_gamma, tol, lr,
+                               cvspils_mem->P_data);
+  cvspils_mem->nps++;
   return(retval);     
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsDQJtimes
- * -----------------------------------------------------------------
- * This routine generates a difference quotient approximation to
- * the Jacobian times vector f_y(t,y) * v. The approximation is 
- * Jv = vnrm[f(y + v/vnrm) - f(y)], where vnrm = (WRMS norm of v) is
- * input, i.e. the WRMS norm of v/vnrm is 1.
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  CVSpilsDQJtimes
+
+  This routine generates a difference quotient approximation to
+  the Jacobian times vector f_y(t,y) * v. The approximation is 
+  Jv = vnrm[f(y + v/vnrm) - f(y)], where vnrm = (WRMS norm of v) is
+  input, i.e. the WRMS norm of v/vnrm is 1.
+  -----------------------------------------------------------------*/
 int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t, 
                     N_Vector y, N_Vector fy,
-                    void *data, N_Vector work)
+                    void *cvode_mem, N_Vector work)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   realtype sig, siginv;
   int iter, retval;
 
-  /* data is cvode_mem */
-  cv_mem = (CVodeMem) data;
-  cvspils_mem = (CVSpilsMem) lmem;
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+                   "CVSpilsDQJtimes", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  cv_mem = (CVodeMem) cvode_mem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", 
+                   "CVSpilsDQJtimes", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
   /* Initialize perturbation to 1/||v|| */
-  sig = ONE/N_VWrmsNorm(v, ewt);
+  sig = ONE/N_VWrmsNorm(v, cv_mem->cv_ewt);
 
   for (iter=0; iter<MAX_ITERS; iter++) {
 
@@ -684,8 +750,8 @@ int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
     N_VLinearSum(sig, v, ONE, y, work);
 
     /* Set Jv = f(tn, y+sig*v) */
-    retval = f(t, work, Jv, user_data); 
-    nfes++;
+    retval = cv_mem->cv_f(t, work, Jv, cv_mem->cv_user_data); 
+    cvspils_mem->nfes++;
     if (retval == 0) break;
     if (retval < 0)  return(-1);
 
@@ -702,14 +768,288 @@ int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
 }
 
 
+/*-----------------------------------------------------------------
+  cvSpilsInitialize
+
+  This routine performs remaining initializations specific
+  to the iterative linear solver interface (and solver itself)
+  -----------------------------------------------------------------*/
+int cvSpilsInitialize(CVodeMem cv_mem)
+{
+  CVSpilsMem cvspils_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+                   "cvSpilsInitialize", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", 
+                   "cvSpilsInitialize", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+  
+  cvSpilsInitializeCounters(cvspils_mem);
+
+  /* Set Jacobian-related fields, based on jtimesDQ */
+  if (cvspils_mem->jtimesDQ) {
+    cvspils_mem->jtsetup = NULL;
+    cvspils_mem->jtimes = CVSpilsDQJtimes;
+    cvspils_mem->j_data = cv_mem;
+  } else {
+    cvspils_mem->j_data = cv_mem->cv_user_data;
+  }
+
+  /* if psetup is not present, then cvSpilsSetup does not need to be 
+     called, so set the lsetup function to NULL */
+  if (cvspils_mem->pset == NULL)  cv_mem->cv_lsetup = NULL;
+
+  /* Call LS initialize routine */
+  cvspils_mem->last_flag = SUNLinSolInitialize(cvspils_mem->LS);
+  return(cvspils_mem->last_flag);
+}
+
+
+/*-----------------------------------------------------------------
+  cvSpilsSetup
+
+  This routine calls the LS 'setup' routine.
+  -----------------------------------------------------------------*/
+int cvSpilsSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+                 N_Vector fpred, booleantype *jcurPtr,
+                 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+{
+  realtype dgamma;
+  int  retval;
+  CVSpilsMem cvspils_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+                   "cvSpilsSetup", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", 
+                   "cvSpilsSetup", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* Set CVSpils N_Vector pointers to current solution and rhs */
+  cvspils_mem->ycur = ypred;
+  cvspils_mem->fcur = fpred;
+
+  /* Use nst, gamma/gammap, and convfail to set J/P eval. flag jok */
+  dgamma = SUNRabs((cv_mem->cv_gamma/cv_mem->cv_gammap) - ONE);
+  cvspils_mem->jbad = (cv_mem->cv_nst == 0) || 
+    (cv_mem->cv_nst > cvspils_mem->nstlpre + CVSPILS_MSBPRE) ||
+    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
+    (convfail == CV_FAIL_OTHER);
+  *jcurPtr = cvspils_mem->jbad;
+  
+  /* Call LS setup routine -- the LS will call CVSpilsPSetup, who will 
+     pass the heuristic suggestions above to the user code(s) */
+  retval = SUNLinSolSetup(cvspils_mem->LS, NULL);
+
+  /* If user set jcur to SUNTRUE, increment npe and save nst value */
+  if (*jcurPtr) {
+    cvspils_mem->npe++;
+    cvspils_mem->nstlpre = cv_mem->cv_nst;
+  }
+  
+  /* Update jcur flag if we suggested an update */
+  if (cvspils_mem->jbad) *jcurPtr = SUNTRUE;
+
+  return(retval);
+}
+
+
+/*-----------------------------------------------------------------
+  cvSpilsSolve
+
+  This routine interfaces between CVode and the generic 
+  SUNLinearSolver object LS, by setting the appropriate tolerance 
+  and scaling vectors, calling the solver, and accumulating 
+  statistics from the solve for use/reporting by CVode.
+  -----------------------------------------------------------------*/
+int cvSpilsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+                 N_Vector ynow, N_Vector fnow)
+{
+  realtype bnorm;
+  CVSpilsMem cvspils_mem;
+  int nli_inc, retval;
+  
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", 
+                   "cvSpilsSolve", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", 
+                   "cvSpilsSolve", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* Test norm(b); if small, return x = 0 or x = b */
+  cvspils_mem->deltar = cvspils_mem->eplifac * cv_mem->cv_tq[4]; 
+  bnorm = N_VWrmsNorm(b, weight);
+  if (bnorm <= cvspils_mem->deltar) {
+    if (cv_mem->cv_mnewt > 0) N_VConst(ZERO, b); 
+    return(0);
+  }
+
+  /* Set vectors ycur and fcur for use by the Atimes and Psolve 
+     interface routines */
+  cvspils_mem->ycur = ynow;
+  cvspils_mem->fcur = fnow;
+
+  /* Set input tolerance and initial guess x = 0 to LS */  
+  cvspils_mem->delta = cvspils_mem->deltar * cvspils_mem->sqrtN;
+  N_VConst(ZERO, cvspils_mem->x);
+
+  /* Set scaling vectors for LS to use */
+  retval = SUNLinSolSetScalingVectors(cvspils_mem->LS,
+                                      weight,
+                                      weight);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSPILS", "cvSpilsSolve", 
+                    "Error in calling SUNLinSolSetScalingVectors");
+    return(CVSPILS_SUNLS_FAIL);
+  }
+
+  /* If a user-provided jtsetup routine is supplied, call that here */
+  if (cvspils_mem->jtsetup) {
+    retval = cvspils_mem->jtsetup(cv_mem->cv_tn, ynow, fnow, 
+                                  cvspils_mem->j_data);
+    cvspils_mem->njtsetup++;
+    if (retval != 0) {
+      cvProcessError(cv_mem, retval, "CVSPILS", 
+                      "cvSpilsSolve", MSGS_JTSETUP_FAILED);
+      return(retval);
+    }
+  }
+  
+  /* Call solver, and copy x to b */
+  retval = SUNLinSolSolve(cvspils_mem->LS, NULL, cvspils_mem->x,
+                          b, cvspils_mem->delta);
+  N_VScale(ONE, cvspils_mem->x, b);
+
+  /* Retrieve solver statistics */
+  nli_inc = SUNLinSolNumIters(cvspils_mem->LS);
+  
+  /* Increment counters nli and ncfl */
+  cvspils_mem->nli += nli_inc;
+  if (retval != SUNLS_SUCCESS) cvspils_mem->ncfl++;
+
+  /* Interpret solver return value  */
+  cvspils_mem->last_flag = retval;
+
+  switch(retval) {
+
+  case SUNLS_SUCCESS:
+    return(0);
+    break;
+  case SUNLS_RES_REDUCED:
+    /* allow reduction but not solution on first Newton iteration, 
+       otherwise return with a recoverable failure */
+    if (cv_mem->cv_mnewt == 0) return(0);
+    else                       return(1);
+    break;
+  case SUNLS_CONV_FAIL:
+  case SUNLS_ATIMES_FAIL_REC:
+  case SUNLS_PSOLVE_FAIL_REC:
+  case SUNLS_PACKAGE_FAIL_REC:
+  case SUNLS_QRFACT_FAIL:
+  case SUNLS_LUFACT_FAIL:
+    return(1);
+    break;
+  case SUNLS_MEM_NULL:
+  case SUNLS_ILL_INPUT:
+  case SUNLS_MEM_FAIL:
+  case SUNLS_GS_FAIL:
+  case SUNLS_QRSOL_FAIL:
+    return(-1);
+    break;
+  case SUNLS_PACKAGE_FAIL_UNREC:
+    cvProcessError(cv_mem, SUNLS_PACKAGE_FAIL_UNREC, "CVSPILS", 
+                   "cvSpilsSolve",
+                    "Failure in SUNLinSol external package");
+    return(-1);
+    break;
+  case SUNLS_ATIMES_FAIL_UNREC:
+    cvProcessError(cv_mem, SUNLS_ATIMES_FAIL_UNREC, "CVSPILS", 
+                   "cvSpilsSolve", MSGS_JTIMES_FAILED);    
+    return(-1);
+    break;
+  case SUNLS_PSOLVE_FAIL_UNREC:
+    cvProcessError(cv_mem, SUNLS_PSOLVE_FAIL_UNREC, "CVSPILS", 
+                   "cvSpilsSolve", MSGS_PSOLVE_FAILED);
+    return(-1);
+    break;
+  }
+  
+  return(0); 
+}
+
+
+/*-----------------------------------------------------------------
+  cvSpilsFree
+
+  This routine frees memory associates with the CVSpils system
+  solver interface.
+  -----------------------------------------------------------------*/
+int cvSpilsFree(CVodeMem cv_mem)
+{
+  CVSpilsMem cvspils_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL)  return (CVSPILS_SUCCESS);
+  if (cv_mem->cv_lmem == NULL)  return(CVSPILS_SUCCESS);
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* Free N_Vector memory */
+  if (cvspils_mem->ytemp) {
+    N_VDestroy(cvspils_mem->ytemp);
+    cvspils_mem->ytemp = NULL;
+  }
+  if (cvspils_mem->x) {
+    N_VDestroy(cvspils_mem->x);
+    cvspils_mem->x = NULL;
+  }
+
+  /* Nullify other N_Vector pointers */
+  cvspils_mem->ycur = NULL;
+  cvspils_mem->fcur = NULL;
+
+  /* Free preconditioner memory (if applicable) */
+  if (cvspils_mem->pfree)  cvspils_mem->pfree(cv_mem);
+  
+  /* free CVSpils interface structure */
+  free(cv_mem->cv_lmem);
+  
+  return(CVSPILS_SUCCESS);
+}
+
+
+/*-----------------------------------------------------------------
+  cvSpilsInitializeCounters
+
+  This routine resets all counters from an CVSpilsMem structure.
+  -----------------------------------------------------------------*/
 int cvSpilsInitializeCounters(CVSpilsMem cvspils_mem)
 {
-  cvspils_mem->s_npe     = 0;
-  cvspils_mem->s_nli     = 0;
-  cvspils_mem->s_nps     = 0;
-  cvspils_mem->s_ncfl    = 0;
-  cvspils_mem->s_nstlpre = 0;
-  cvspils_mem->s_njtimes = 0;
-  cvspils_mem->s_nfes    = 0;
+  cvspils_mem->npe      = 0;
+  cvspils_mem->nli      = 0;
+  cvspils_mem->nps      = 0;
+  cvspils_mem->ncfl     = 0;
+  cvspils_mem->nstlpre  = 0;
+  cvspils_mem->njtsetup = 0;
+  cvspils_mem->njtimes  = 0;
+  cvspils_mem->nfes     = 0;
   return(0);
 }
diff --git a/src/cvode/cvode_spils_impl.h b/src/cvode/cvode_spils_impl.h
index 5e3f199..3bb5044 100644
--- a/src/cvode/cvode_spils_impl.h
+++ b/src/cvode/cvode_spils_impl.h
@@ -1,22 +1,24 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common implementation header file for the scaled, preconditioned
- * linear solver modules.
+ * Implementation header file for the scaled, preconditioned
+ * linear solver interface.
  * -----------------------------------------------------------------
  */
 
@@ -30,47 +32,37 @@
 extern "C" {
 #endif
 
-/* Types of iterative linear solvers */
-
-#define SPILS_SPGMR   1
-#define SPILS_SPBCG   2
-#define SPILS_SPTFQMR 3
 
-/*
- * -----------------------------------------------------------------
- * Types : CVSpilsMemRec, CVSpilsMem
- * -----------------------------------------------------------------
- * The type CVSpilsMem is pointer to a CVSpilsMemRec.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types : CVSpilsMemRec, CVSpilsMem
+  -----------------------------------------------------------------
+  The type CVSpilsMem is pointer to a CVSpilsMemRec.
+  -----------------------------------------------------------------*/
 
 typedef struct CVSpilsMemRec {
 
-  int s_type;           /* type of scaled preconditioned iterative LS   */
-
-  int  s_pretype;       /* type of preconditioning                      */
-  int  s_gstype;        /* type of Gram-Schmidt orthogonalization       */
-  realtype s_sqrtN;     /* sqrt(N)                                      */
-  realtype s_eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
-  realtype s_deltar;    /* deltar = delt * tq4                          */
-  realtype s_delta;     /* delta = deltar * sqrtN                       */
-  int  s_maxl;          /* maxl = maximum dimension of the Krylov space */
-
-  long int s_nstlpre;   /* value of nst at the last pset call           */
-  long int s_npe;       /* npe = total number of pset calls             */
-  long int s_nli;       /* nli = total number of linear iterations      */
-  long int s_nps;       /* nps = total number of psolve calls           */
-  long int s_ncfl;      /* ncfl = total number of convergence failures  */
-  long int s_njtimes;   /* njtimes = total number of calls to jtimes    */
-  long int s_nfes;      /* nfeSG = total number of calls to f for     
-                           difference quotient Jacobian-vector products */
-
-  N_Vector s_ytemp;     /* temp vector passed to jtimes and psolve      */
-  N_Vector s_x;         /* temp vector used by CVSpilsSolve             */
-  N_Vector s_ycur;      /* CVODE current y vector in Newton Iteration   */
-  N_Vector s_fcur;      /* fcur = f(tn, ycur)                           */
-
-  void* s_spils_mem;    /* memory used by the generic solver            */
+  realtype sqrtN;     /* sqrt(N)                                      */
+  realtype eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
+  realtype deltar;    /* deltar = delt * tq4                          */
+  realtype delta;     /* delta = deltar * sqrtN                       */
+
+  booleantype jbad;   /* heuristic suggestion for pset/jtsetup        */
+  long int nstlpre;   /* value of nst at the last pset call           */
+  long int npe;       /* npe = total number of pset calls             */
+  long int nli;       /* nli = total number of linear iterations      */
+  long int nps;       /* nps = total number of psolve calls           */
+  long int ncfl;      /* ncfl = total number of convergence failures  */
+  long int njtsetup;  /* njtsetup = total number of calls to jtsetup  */
+  long int njtimes;   /* njtimes = total number of calls to jtimes    */
+  long int nfes;      /* nfeSG = total number of calls to f for     
+                         difference quotient Jacobian-vector products */
+
+  SUNLinearSolver LS; /* generic iterative linear solver object       */
+  
+  N_Vector ytemp;     /* temp vector passed to jtimes and psolve      */
+  N_Vector x;         /* temp vector used by CVSpilsSolve             */
+  N_Vector ycur;      /* CVODE current y vector in Newton Iteration   */
+  N_Vector fcur;      /* fcur = f(tn, ycur)                           */
 
   /* Preconditioner computation
    * (a) user-provided:
@@ -78,69 +70,70 @@ typedef struct CVSpilsMemRec {
    *     - pfree == NULL (the user dealocates memory for user_data)
    * (b) internal preconditioner module
    *     - P_data == cvode_mem
-   *     - pfree == set by the prec. module and called in CVodeFree
-   */
-  CVSpilsPrecSetupFn s_pset;
-  CVSpilsPrecSolveFn s_psolve;
-  int (*s_pfree)(CVodeMem cv_mem);
-  void *s_P_data;
+   *     - pfree == set by the prec. module and called in CVodeFree */
+  CVSpilsPrecSetupFn pset;
+  CVSpilsPrecSolveFn psolve;
+  int (*pfree)(CVodeMem cv_mem);
+  void *P_data;
 
   /* Jacobian times vector compuation
    * (a) jtimes function provided by the user:
    *     - j_data == user_data
-   *     - jtimesDQ == FALSE
+   *     - jtimesDQ == SUNFALSE
    * (b) internal jtimes
    *     - j_data == cvode_mem
-   *     - jtimesDQ == TRUE
-   */
-  booleantype s_jtimesDQ;
-  CVSpilsJacTimesVecFn s_jtimes;
-  void *s_j_data;
+   *     - jtimesDQ == SUNTRUE */
+  booleantype jtimesDQ;
+  CVSpilsJacTimesSetupFn jtsetup;
+  CVSpilsJacTimesVecFn jtimes;
+  void *j_data;
 
-  long int s_last_flag; /* last error flag returned by any function     */
+  long int last_flag; /* last error flag returned by any function */
 
 } *CVSpilsMem;
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
 
-/* Atimes and PSolve routines called by generic solver */
-
-int CVSpilsAtimes(void *cv_mem, N_Vector v, N_Vector z);
-
-int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z, int lr);
+/* Interface routines called by system SUNLinearSolver */
+int CVSpilsATimes(void *cv_mem, N_Vector v, N_Vector z);
+int CVSpilsPSetup(void *cv_mem);
+int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z,
+                  realtype tol, int lr);
 
 /* Difference quotient approximation for Jac times vector */
-
 int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
                     N_Vector y, N_Vector fy, void *data,
                     N_Vector work);
 
+/* Generic linit/lsetup/lsolve/lfree interface routines for CVode to call */
+int cvSpilsInitialize(CVodeMem cv_mem);
+int cvSpilsSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
+                 N_Vector fpred, booleantype *jcurPtr,
+                 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3); 
+int cvSpilsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+                 N_Vector ycur, N_Vector fcur);
+int cvSpilsFree(CVodeMem cv_mem);
+
 /* Auxilliary functions */
 int cvSpilsInitializeCounters(CVSpilsMem cvspils_mem);
 
 
-/*
- * -----------------------------------------------------------------
- * Error Messages
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Error Messages
+  -----------------------------------------------------------------*/
 
 #define MSGS_CVMEM_NULL  "Integrator memory is NULL."
 #define MSGS_MEM_FAIL    "A memory request failed."
 #define MSGS_BAD_NVECTOR "A required vector operation is not implemented."
 #define MSGS_BAD_LSTYPE  "Incompatible linear solver type."
-#define MSGS_BAD_PRETYPE "Illegal value for pretype. Legal values are PREC_NONE, PREC_LEFT, PREC_RIGHT, and PREC_BOTH."
-#define MSGS_PSOLVE_REQ  "pretype != PREC_NONE, but PSOLVE = NULL is illegal."
 #define MSGS_LMEM_NULL   "Linear solver memory is NULL."
-#define MSGS_BAD_GSTYPE  "Illegal value for gstype. Legal values are MODIFIED_GS and CLASSICAL_GS."
 #define MSGS_BAD_EPLIN   "eplifac < 0 illegal."
 
 #define MSGS_PSET_FAILED "The preconditioner setup routine failed in an unrecoverable manner."
 #define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner."
+#define MSGS_JTSETUP_FAILED "The Jacobian x vector setup routine failed in an unrecoverable manner."
 #define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
 
 
diff --git a/src/cvode/cvode_sptfqmr.c b/src/cvode/cvode_sptfqmr.c
deleted file mode 100644
index abf2d02..0000000
--- a/src/cvode/cvode_sptfqmr.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSPTFQMR linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvode/cvode_sptfqmr.h>
-#include "cvode_spils_impl.h"
-#include "cvode_impl.h"
-
-#include <sundials/sundials_sptfqmr.h>
-#include <sundials/sundials_math.h>
-
-/* Other Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* CVSPTFQMR linit, lsetup, lsolve, and lfree routines */
-
-static int CVSptfqmrInit(CVodeMem cv_mem);
-
-static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                          N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                          N_Vector vtemp2, N_Vector vtemp3);
-
-static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                          N_Vector ynow, N_Vector fnow);
-
-static int CVSptfqmrFree(CVodeMem cv_mem);
-
-
-/* Readability Replacements */
-
-#define tq           (cv_mem->cv_tq)
-#define nst          (cv_mem->cv_nst)
-#define tn           (cv_mem->cv_tn)
-#define gamma        (cv_mem->cv_gamma)
-#define gammap       (cv_mem->cv_gammap)
-#define f            (cv_mem->cv_f)
-#define user_data    (cv_mem->cv_user_data)
-#define ewt          (cv_mem->cv_ewt)
-#define errfp        (cv_mem->cv_errfp)
-#define mnewt        (cv_mem->cv_mnewt)
-#define linit        (cv_mem->cv_linit)
-#define lsetup       (cv_mem->cv_lsetup)
-#define lsolve       (cv_mem->cv_lsolve)
-#define lfree        (cv_mem->cv_lfree)
-#define lmem         (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define sqrtN       (cvspils_mem->s_sqrtN)   
-#define ytemp       (cvspils_mem->s_ytemp)
-#define x           (cvspils_mem->s_x)
-#define ycur        (cvspils_mem->s_ycur)
-#define fcur        (cvspils_mem->s_fcur)
-#define delta       (cvspils_mem->s_delta)
-#define deltar      (cvspils_mem->s_deltar)
-#define npe         (cvspils_mem->s_npe)
-#define nli         (cvspils_mem->s_nli)
-#define nps         (cvspils_mem->s_nps)
-#define ncfl        (cvspils_mem->s_ncfl)
-#define nstlpre     (cvspils_mem->s_nstlpre)
-#define njtimes     (cvspils_mem->s_njtimes)
-#define nfes        (cvspils_mem->s_nfes)
-#define spils_mem   (cvspils_mem->s_spils_mem)
-
-#define jtimesDQ (cvspils_mem->s_jtimesDQ)
-#define jtimes  (cvspils_mem->s_jtimes)
-#define j_data  (cvspils_mem->s_j_data)
-
-#define last_flag   (cvspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmr
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the Sptfqmr linear solver module. CVSptfqmr first
- * calls the existing lfree routine if this is not NULL. It then sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be CVSptfqmrInit, CVSptfqmrSetup, CVSptfqmrSolve, and CVSptfqmrFree,
- * respectively. It allocates memory for a structure of type
- * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure. It sets setupNonNull in (*cvode_mem),
- * and sets various fields in the CVSpilsMemRec structure.
- * Finally, CVSptfqmr allocates memory for ytemp and x, and calls
- * SptfqmrMalloc to allocate memory for the Sptfqmr solver.
- * -----------------------------------------------------------------
- */
-
-int CVSptfqmr(void *cvode_mem, int pretype, int maxl)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int mxl;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPTFQMR", "CVSptfqmr", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_NVECTOR);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = CVSptfqmrInit;
-  lsetup = CVSptfqmrSetup;
-  lsolve = CVSptfqmrSolve;
-  lfree  = CVSptfqmrFree;
-
-  /* Get memory for CVSpilsMemRec */
-  cvspils_mem = NULL;
-  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
-  if (cvspils_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  cvspils_mem->s_type = SPILS_SPTFQMR;
-
-  /* Set Sptfqmr parameters that have been passed in call sequence */
-  cvspils_mem->s_pretype = pretype;
-  mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  cvspils_mem->s_pset   = NULL;
-  cvspils_mem->s_psolve = NULL;
-  cvspils_mem->s_pfree  = NULL;
-  cvspils_mem->s_P_data = cv_mem->cv_user_data;
-
-  /* Set default values for the rest of the Sptfqmr parameters */
-  cvspils_mem->s_eplifac = CVSPILS_EPLIN;
-
-  cvspils_mem->s_last_flag = CVSPILS_SUCCESS;
-
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_PRETYPE);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  x = N_VClone(vec_tmpl);
-  if (x == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */
-  sptfqmr_mem = NULL;
-  sptfqmr_mem = SptfqmrMalloc(mxl, vec_tmpl);
-  if (sptfqmr_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(x);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPTFQMR memory to spils memory structure */
-  spils_mem = (void *) sptfqmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvspils_mem;
-
-  return(CVSPILS_SUCCESS);
-}
-
-/* Additional readability replacements */
-
-#define pretype (cvspils_mem->s_pretype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define pset    (cvspils_mem->s_pset)
-#define P_data  (cvspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the Sptfqmr
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrInit(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-
-  /* Initialize counters */
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((pretype != PREC_NONE) && (psolve == NULL)) {
-    cvProcessError(cv_mem, -1, "CVSPTFQMR", "CVSptfqmrInit", MSGS_PSOLVE_REQ);
-    last_flag = CVSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  setupNonNull = (pretype != PREC_NONE) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = CVSpilsDQJtimes;
-    j_data = cv_mem;
-  } else {
-    j_data = user_data;
-  }
-
-  /*  Set maxl in the SPTFQMR memory in case it was changed by the user */
-  sptfqmr_mem->l_max  = maxl;
-
-  last_flag = CVSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the Sptfqmr linear solver.
- * It makes a decision as to whether or not to signal for reevaluation
- * of Jacobian data in the pset routine, based on various state
- * variables, then it calls pset. If we signal for reevaluation,
- * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output.
- * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-			  N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-			  N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  CVSpilsMem cvspils_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) ||
-      ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
-      (convfail == CV_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, 
-                vtemp1, vtemp2, vtemp3);
-  if (retval < 0) {
-    cvProcessError(cv_mem, SPTFQMR_PSET_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPTFQMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    last_flag = SPTFQMR_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    npe++;
-    nstlpre = nst;
-  }
-
-  last_flag = SPTFQMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic solver SptfqmrSolve
- * for the solution of the linear system Ax = b with the SPTFQMR method.
- * The solution x is returned in the vector b.
- *
- * If the WRMS norm of b is small, we return x = b (if this is the first
- * Newton iteration) or x = 0 (if a later Newton iteration).
- *
- * Otherwise, we set the tolerance parameter and initial guess (x = 0),
- * call SptfqmrSolve, and copy the solution x into b. The x-scaling and
- * b-scaling arrays are both equal to weight.
- *
- * The counters nli, nps, and ncfl are incremented, and the return value
- * is set according to the success of SptfqmrSolve. The success flag is
- * returned if SptfqmrSolve converged, or if this is the first Newton
- * iteration and the residual norm was reduced below its initial value.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-			  N_Vector ynow, N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  deltar = eplifac * tq[4]; 
-
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= deltar) {
-    if (mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  ycur = ynow;
-  fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SptfqmrSolve */  
-  delta = deltar * sqrtN;
-  N_VConst(ZERO, x);
-  
-  /* Call SptfqmrSolve and copy x to b */
-  retval = SptfqmrSolve(sptfqmr_mem, cv_mem, x, b, pretype, delta,
-                        cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve,
-                        &res_norm, &nli_inc, &nps_inc);
-
-  N_VScale(ONE, x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPTFQMR_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPTFQMR_SUCCESS:
-    return(0);
-    break;
-  case SPTFQMR_RES_REDUCED:
-    if (mnewt == 0) return(0);
-    else            return(1);
-    break;
-  case SPTFQMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_UNREC:
-    cvProcessError(cv_mem, SPTFQMR_ATIMES_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_UNREC:
-    cvProcessError(cv_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the Sptfqmr linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrFree(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-    
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(x);
-
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-  SptfqmrFree(sptfqmr_mem);
-
-  if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem);
-
-  free(cvspils_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
diff --git a/src/cvode/cvode_superlumt.c b/src/cvode/cvode_superlumt.c
deleted file mode 100644
index f601898..0000000
--- a/src/cvode/cvode_superlumt.c
+++ /dev/null
@@ -1,554 +0,0 @@
-
-/*
- * -----------------------------------------------------------------
- * $Revision: 4922 $
- * $Date: 2016-09-19 14:35:32 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSUPERLUMT linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cvode_impl.h"
-#include "cvode_sparse_impl.h"
-#include "cvode/cvode_superlumt.h"
-#include "sundials/sundials_superlumt_impl.h"
-#include "sundials/sundials_math.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* CVSUPERLUMT linit, lsetup, lsolve, and lfree routines */
- 
-static int cvSuperLUMTInit(CVodeMem cv_mem);
-
-static int cvSuperLUMTSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-			    N_Vector fpred, booleantype *jcurPtr,
-			    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int cvSuperLUMTSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-			    N_Vector ycur, N_Vector fcur);
-
-static int cvSuperLUMTFree(CVodeMem cv_mem);
-
-/*
- * -----------------------------------------------------------------
- * CVSuperLUMT
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the CVODE / SuperLUMT linear solver module.  
- * CVSUPERLUMT first calls the existing lfree routine if this is not NULL.
- * Then it sets the cv_linit, cv_lsetup, cv_lsolve, and
- * cv_lfree fields in (*cv_mem) to be cvSuperLUMTInit, cvSuperLUMTSetup,
- * cvSuperLUMTSolve, and cvSuperLUMTFree, respectively.
- * It allocates memory for a structure of type CVsluMemRec and sets
- * the cv_lmem field in (*cvode_mem) to the address of this structure.
- * It sets setupNonNull in (*cvode_mem) to TRUE.
- * Finally, it allocates memory for SuperLUMT.
- * The return value is CVSLS_SUCCESS = 0, CVSLS_LMEM_FAIL = -1,
- * or CVSLS_ILL_INPUT = -2.
- *
- * NOTE: The SuperLUMT linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVSuperLUMT will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int CVSuperLUMT(void *cvode_mem, int num_threads, int n, int nnz)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-  int *perm_c, *perm_r;
-  int nrhs, panel_size, relax;
-  double *bd;
-  SuperMatrix *B;
-
-  /* Return immediately if cv_mem is NULL. */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_BAD_NVECTOR);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  if (cv_mem->cv_lfree != NULL) cv_mem->cv_lfree(cv_mem);
-
-  /* Set five main function fields in cv_mem. */
-  cv_mem->cv_linit  = cvSuperLUMTInit;
-  cv_mem->cv_lsetup = cvSuperLUMTSetup;
-  cv_mem->cv_lsolve = cvSuperLUMTSolve;
-  cv_mem->cv_lfree  = cvSuperLUMTFree;
-
-  /* Get memory for CVSlsMemRec. */
-  cvsls_mem = (CVSlsMem) malloc(sizeof(struct CVSlsMemRec));
-  if (cvsls_mem == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Get memory for SLUMT_data. */
-  slumt_data = (SLUMTData)malloc(sizeof(struct SLUMTDataRec));
-  if (slumt_data == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  cv_mem->cv_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  cvsls_mem->s_jaceval = NULL;
-  cvsls_mem->s_jacdata = cv_mem->cv_user_data;
-
-  /* Allocate memory for the sparse Jacobian */
-  cvsls_mem->s_JacMat = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (cvsls_mem->s_JacMat == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Allocate memory for saved sparse Jacobian */
-  cvsls_mem->s_savedJ = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (cvsls_mem->s_savedJ == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Set up memory for the permutations */
-  perm_r = (int *)malloc(n*sizeof(int));
-  if (perm_r == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		   MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-  perm_c = (int *)malloc(n*sizeof(int));
-  if (perm_c == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		   MSGSP_MEM_FAIL);
-    free(perm_r);
-    return(CVSLS_MEM_FAIL);
-  }
-  slumt_data->perm_r = perm_r;
-  slumt_data->perm_c = perm_c;
-
-  /* Set default parameters for SuperLU */
-  slumt_data->num_threads = num_threads;
-  slumt_data->diag_pivot_thresh = 1.0;
-
-  /* Allocate structures for SuperLU */
-  slumt_data->Gstat = (Gstat_t *)malloc(sizeof(Gstat_t));
-  slumt_data->s_A = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_AC = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_L = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_U = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_A->Store  = NULL;
-  slumt_data->s_AC->Store = NULL;
-  slumt_data->s_L->Store  = NULL;
-  slumt_data->s_U->Store  = NULL;
-  slumt_data->superlumt_options = (superlumt_options_t *)malloc(sizeof(superlumt_options_t));
-
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  StatAlloc(cvsls_mem->s_JacMat->N, num_threads, panel_size, relax, 
-	    slumt_data->Gstat);
-  
-  /* Create RHS matrix */
-  nrhs = 1;
-  bd = NULL;
-  B = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  B->Store = NULL;
-  dCreate_Dense_Matrix(B, n, nrhs, bd, n, 
-		       SLU_DN, SLU_D, SLU_GE);
-  slumt_data->s_B = B;
-
-  /* Set ordering to COLAMD as the cvode default use.
-     Users can set a different value with CVSuperLUMTSetOrdering,
-     and the user-set value is loaded before any call to factorize the
-     matrix in cvSuperLUMTSetup.  */
-  slumt_data->s_ordering = 3;
-
-  /* Attach linear solver memory to the integrator memory */
-  cvsls_mem->s_solver_data = (void *) slumt_data;
-  cv_mem->cv_lmem = cvsls_mem;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSuperLUMT interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the CVSuperLUMT
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int cvSuperLUMTInit(CVodeMem cv_mem)
-{
-  int num_threads, n;
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-
-  cvsls_mem = (CVSlsMem)cv_mem->cv_lmem;
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  cvsls_mem->s_nje = 0;
-  cvsls_mem->s_first_factorize = 1;
-  cvsls_mem->s_nstlj = 0;
-
-  /* ------------------------------------------------------------
-     Allocate storage and initialize statistics variables. 
-     ------------------------------------------------------------*/
-  n = cvsls_mem->s_JacMat->N;
-  num_threads = slumt_data->num_threads;
-
-  StatInit(n, num_threads, slumt_data->Gstat);
-
-  cvsls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the CVSuperLUMT linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     CVSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int cvSuperLUMTSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-			   N_Vector fpred, booleantype *jcurPtr,
-			   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  int retval, info;
-  int nprocs, panel_size, relax, permc_spec, lwork;
-  int *perm_r, *perm_c;
-  long int nst, nstlj;
-  realtype tn, gamma, gammap, dgamma;
-  double diag_pivot_thresh, drop_tol;
-  fact_t fact;
-  trans_t trans;
-  yes_no_t refact, usepr;
-  CVSlsMem cvsls_mem;
-  CVSlsSparseJacFn jaceval;
-  SuperMatrix *A, *AC, *L, *U;
-  Gstat_t *Gstat;
-  superlumt_options_t *superlumt_options;
-  SLUMTData slumt_data;
-  SlsMat JacMat, savedJ;
-  void *jacdata;
-  void *work;
-  
-  cvsls_mem = (CVSlsMem) (cv_mem->cv_lmem);
-  tn = cv_mem->cv_tn; 
-  gamma = cv_mem->cv_gamma;
-  gammap = cv_mem->cv_gammap;
-  nst = cv_mem->cv_nst;
-
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  jaceval = cvsls_mem->s_jaceval;
-  jacdata = cvsls_mem->s_jacdata;
-  JacMat = cvsls_mem->s_JacMat;
-  savedJ = cvsls_mem->s_savedJ;
-  nstlj = cvsls_mem->s_nstlj;
-
-  superlumt_options = slumt_data->superlumt_options;
-  A = slumt_data->s_A;
-  AC = slumt_data->s_AC;
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  Gstat = slumt_data->Gstat;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  nprocs = slumt_data->num_threads;
-  diag_pivot_thresh = slumt_data->diag_pivot_thresh;
-
-  /* Set option values for SuperLU_MT */
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  fact = EQUILIBRATE;
-  trans = NOTRANS;
-  usepr = NO;
-  drop_tol = 0.0;
-  lwork = 0;
-  work = NULL;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    cvProcessError(cv_mem, CVSLS_JAC_NOSET, "CVSLS", "cvSuperLUMTSetup", 
-		    MSGSP_JAC_NOSET);
-    free(cvsls_mem); cvsls_mem = NULL;
-    return(CVSLS_JAC_NOSET);
-  }
-
-  /* Determine whether Jacobian needs to be recalculated */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVS_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVS_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    SparseCopyMat(savedJ, JacMat);
-  } else {
-    /* If jok = FALSE, call jac routine for new J value */
-    cvsls_mem->s_nje++;
-    cvsls_mem->s_nstlj = nst;
-    *jcurPtr = TRUE;
-    SparseSetMatToZero(JacMat);
-    retval = jaceval(tn, ypred, fpred, JacMat, jacdata, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVSLS_JACFUNC_UNRECVR, "CVSLS", "cvSuperLUMTSetup", MSGSP_JACFUNC_FAILED);
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    SparseCopyMat(JacMat, savedJ);
-  }
-
-  /* Scale and add I to get M = I - gamma*J */
-  SparseScaleMat(-gamma, JacMat);
-  SparseAddIdentityMat(JacMat);
-
-  if (A->Store) {
-    SUPERLU_FREE(A->Store);
-  }
-  dCreate_CompCol_Matrix(A, JacMat->M, JacMat->N, JacMat->NNZ, 
-			 JacMat->data, JacMat->indexvals, JacMat->indexptrs, 
-			 SLU_NC, SLU_D, SLU_GE);
-
-  if (cvsls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get column permutation vector perm_c[], according to permc_spec:
-       permc_spec = 3: approximate minimum degree for unsymmetric matrices
-       ------------------------------------------------------------*/ 
-    permc_spec = slumt_data->s_ordering;
-    get_perm_c(permc_spec, A, perm_c);
-
-    refact= NO;
-    cvsls_mem->s_first_factorize = 0;
-  }
-  else {
-    /* ------------------------------------------------------------
-       Re-initialize statistics variables 
-       ------------------------------------------------------------*/
-    StatInit(JacMat->N, nprocs, Gstat);
-    Destroy_CompCol_Permuted(AC);
-    refact= YES;
-  }
-
-  /* ------------------------------------------------------------
-     Initialize the option structure superlumt_options using the
-     user-input parameters;  Subsequent calls will re-initialize
-     options.
-     Apply perm_c to the columns of original A to form AC.
-     ------------------------------------------------------------*/
-  pdgstrf_init(nprocs, fact, trans, refact, panel_size, relax,
-	       diag_pivot_thresh, usepr, drop_tol, perm_c, perm_r,
-	       work, lwork, A, AC, superlumt_options, Gstat);
-  /* ------------------------------------------------------------
-     Compute the LU factorization of A.
-     The following routine will create nprocs threads.
-     ------------------------------------------------------------*/
-  pdgstrf(superlumt_options, AC, perm_r, L, U, Gstat, &info);
-    
-  if (info != 0) {
-    cvsls_mem->s_last_flag = info;
-    return(+1);
-  }
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the CVSuperLUMT linear
-  solver module.  It calls the SuperLU_MT solve routine,
-  then returns CVSLS_SUCCESS = 0.
-*/
-
-static int cvSuperLUMTSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-			    N_Vector ycur, N_Vector fcur)
-{
-  int info, trans, lmm;
-  int *perm_r, *perm_c;
-  realtype gamrat;
-  CVSlsMem cvsls_mem;
-  SuperMatrix *L, *U, *B;
-  Gstat_t *Gstat;
-  DNformat *Bstore;
-  SLUMTData slumt_data;
-  realtype *bd;
-  
-  gamrat = cv_mem->cv_gamrat;
-  lmm = cv_mem->cv_lmm;
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  Gstat = slumt_data->Gstat;
-  B = slumt_data->s_B;
-   
-  bd = N_VGetArrayPointer(b);
-  Bstore = (DNformat *) (B->Store);
-  Bstore->nzval = bd;
-
-  /* Call SuperLUMT to solve the linear system using L and U */
-  trans = NOTRANS;
-  dgstrs(trans, L, U, perm_r, perm_c, B, Gstat, &info);
-
-  /* Scale the correction to account for change in gamma. */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-
-  Bstore->nzval = NULL;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-  return(CVSLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the CVSuperLUMT linear solver.
-*/
-
-static int cvSuperLUMTFree(CVodeMem cv_mem)
-{
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-  
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  pxgstrf_finalize(slumt_data->superlumt_options, slumt_data->s_AC);
-
-  free(slumt_data->perm_r);
-  free(slumt_data->perm_c);
-  free(slumt_data->superlumt_options);
-  Destroy_SuperNode_SCP( (slumt_data->s_L) );
-  Destroy_CompCol_NCP( (slumt_data->s_U) );
-  StatFree( (slumt_data->Gstat) );
-  free(slumt_data->Gstat);
-  
-  Destroy_SuperMatrix_Store(slumt_data->s_B);
-  SUPERLU_FREE(slumt_data->s_A->Store);
-  if (cvsls_mem->s_JacMat) {
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    cvsls_mem->s_JacMat = NULL;
-  }
-  if (cvsls_mem->s_savedJ) {
-    SparseDestroyMat(cvsls_mem->s_savedJ);
-    cvsls_mem->s_savedJ = NULL;
-  }
-
-  free(slumt_data->s_B);
-  free(slumt_data->s_A);
-  free(slumt_data->s_AC);
-  free(slumt_data->s_L);
-  free(slumt_data->s_U);
-
-  free(slumt_data); 
-  slumt_data = NULL;
-  free(cv_mem->cv_lmem); 
-
-  return(0);
-}
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVSuperLUMTSetOrdering sets the ordering used by SuperLUMT for reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int CVSuperLUMTSetOrdering(void *cv_mem_v, int ordering_choice)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-
- /* Return immediately if cv_mem is NULL */
-  if (cv_mem_v == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSuperLUMTSetOrdering",
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cv_mem_v;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) && (ordering_choice != 3) ) {
-    cvProcessError(NULL, CVSLS_ILL_INPUT, "CVSLS", "CVSuperLUMTSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  slumt_data->s_ordering = ordering_choice;
-
-  return(CVSLS_SUCCESS);
-}
diff --git a/src/cvode/fcmix/CMakeLists.txt b/src/cvode/fcmix/CMakeLists.txt
index 44a82d4..7d4405b 100644
--- a/src/cvode/fcmix/CMakeLists.txt
+++ b/src/cvode/fcmix/CMakeLists.txt
@@ -11,31 +11,54 @@ SET(fcvode_SOURCES
   fcvode.c
   fcvpreco.c
   fcvroot.c
+  fcvsparse.c
   )
 
-IF(LAPACK_FOUND)
-  SET(fcvode_BL_SOURCES fcvlapack.c fcvlapband.c fcvlapdense.c)
-ELSE(LAPACK_FOUND)
-  SET(fcvode_BL_SOURCES "")
-ENDIF(LAPACK_FOUND)
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the CVODE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/nvec_ser/fnvector_serial.c
+  )
+
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the CVODE library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/fsunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/fsunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/fsunmatrix_sparse.c
+  )
 
-IF(KLU_FOUND OR SUPERLUMT_FOUND)
-  SET(fcvode_SPARSE_SOURCES fcvsparse.c)
-ELSE(SPARSE_FOUND)
-  SET(fcvode_SPARSE_SOURCES "")
-ENDIF(KLU_FOUND OR SUPERLUMT_FOUND)
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the CVODE library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/fsunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/fsunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/fsunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/fsunlinsol_pcg.c
+  )
 
 IF(KLU_FOUND)
-  SET(fcvode_KLU_SOURCES fcvklu.c)
-ELSE(KLU_FOUND)
-  SET(fcvode_KLU_SOURCES "")
-ENDIF(KLU_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_klu/fsunlinsol_klu.c
+    )
+ENDIF()
 
 IF(SUPERLUMT_FOUND)
-  SET(fcvode_SUPERLUMT_SOURCES fcvsuperlumt.c)
-ELSE(SUPERLUMT_FOUND)
-  SET(fcvode_SUPERLUMT_SOURCES "")
-ENDIF(SUPERLUMT_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_superlumt/fsunlinsol_superlumt.c
+    )
+ENDIF()
+
+IF(LAPACK_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackband/fsunlinsol_lapackband.c
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c
+    )
+ENDIF()
+
 
 # Add source directories to include directories for access to
 # implementation only header files (both for fcvode and cvode)
@@ -50,7 +73,8 @@ ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
 # coming from inexistent user-provided functions)
 
 # Add the build target for the FCVODE library
-ADD_LIBRARY(sundials_fcvode_static STATIC ${fcvode_SOURCES} ${fcvode_BL_SOURCES} ${fcvode_SPARSE_SOURCES} ${fcvode_KLU_SOURCES} ${fcvode_SUPERLUMT_SOURCES})
+ADD_LIBRARY(sundials_fcvode_static STATIC
+  ${fcvode_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
 # Set the library name and make sure it is not deleted
 SET_TARGET_PROPERTIES(sundials_fcvode_static
diff --git a/src/cvode/fcmix/fcvband.c b/src/cvode/fcmix/fcvband.c
index 8d40052..69f6ea9 100644
--- a/src/cvode/fcmix/fcvband.c
+++ b/src/cvode/fcmix/fcvband.c
@@ -1,21 +1,23 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Fortran/C interface routines for CVODE/CVBAND, for the case of 
+ * Fortran/C interface routines for CVODE/CVDLS, for the case of 
  * a user-supplied Jacobian approximation routine.                
  * -----------------------------------------------------------------
  */
@@ -26,7 +28,8 @@
 #include "fcvode.h"     /* actual fn. names, prototypes and global vars.*/
 #include "cvode_impl.h" /* definition of CVodeMem type                  */
 
-#include <cvode/cvode_band.h>
+#include <cvode/cvode_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
 
 /******************************************************************************/
 
@@ -35,13 +38,11 @@
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
-  extern void FCV_BJAC(long int*, long int*, long int*, long int*,  /* N,MU,ML,EBAND */
-                       realtype*, realtype*, realtype*,  /* T, Y, FY         */
-                       realtype*,                        /* BJAC             */
-                       realtype*,                        /* H                */
-                       long int*, realtype*,             /* IPAR, RPAR       */
-                       realtype*, realtype*, realtype*,  /* V1, V2, V3       */
-                       int*);                            /* IER              */
+  extern void FCV_BJAC(long int *N, long int *MU, long int *ML,
+                       long int *EBAND, realtype *T, realtype *Y,
+                       realtype *FY, realtype *BJAC, realtype *H,
+                       long int *IPAR, realtype *RPAR, realtype *V1, 
+                       realtype *V2, realtype *V3, int *IER);
 #ifdef __cplusplus
 }
 #endif
@@ -51,9 +52,9 @@ extern "C" {
 void FCV_BANDSETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = CVDlsSetBandJacFn(CV_cvodemem, NULL);
+    *ier = CVDlsSetJacFn(CV_cvodemem, NULL);
   } else {
-    *ier = CVDlsSetBandJacFn(CV_cvodemem, FCVBandJac);
+    *ier = CVDlsSetJacFn(CV_cvodemem, FCVBandJac);
   }
 }
 
@@ -61,22 +62,20 @@ void FCV_BANDSETJAC(int *flag, int *ier)
 
 /* C function CVBandJac interfaces between CVODE and a Fortran subroutine
    FCVBJAC for solution of a linear system with band Jacobian approximation.
-   Addresses of arguments are passed to FCVBJAC, using the macro 
-   BAND_COL from BAND and the routine N_VGetArrayPointer from NVECTOR.
+   Addresses of arguments are passed to FCVBJAC, using the accessor routines
+   from the SUNBandMatrix and N_Vector modules.
    The address passed for J is that of the element in column 0 with row 
    index -mupper.  An extended bandwith equal to (J->smu) + mlower + 1 is
-   passed as the column dimension of the corresponding array.
-   Auxiliary data is assumed to be communicated by Common. */
+   passed as the column dimension of the corresponding array. */
 
-int FCVBandJac(long int N, long int mupper, long int mlower,
-               realtype t, N_Vector y, N_Vector fy, 
-               DlsMat J, void *user_data,
-               N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+int FCVBandJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+               void *user_data, N_Vector vtemp1, N_Vector vtemp2,
+               N_Vector vtemp3)
 {
   int ier;
   realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
   realtype h;
-  long int eband;
+  long int N, mupper, mlower, smu, eband;
   FCVUserData CV_userdata;
 
   CVodeGetLastStep(CV_cvodemem, &h);
@@ -87,13 +86,18 @@ int FCVBandJac(long int N, long int mupper, long int mlower,
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
 
-  eband = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
+  N = SUNBandMatrix_Columns(J);
+  mupper = SUNBandMatrix_UpperBandwidth(J);
+  mlower = SUNBandMatrix_LowerBandwidth(J);
+  smu = SUNBandMatrix_StoredUpperBandwidth(J);
+  eband = smu + mlower + 1;
+  jacdata = SUNBandMatrix_Column(J,0) - mupper;
 
   CV_userdata = (FCVUserData) user_data;
 
-  FCV_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata, jacdata, &h,
-           CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier);
+  FCV_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata,
+           jacdata, &h, CV_userdata->ipar, CV_userdata->rpar,
+           v1data, v2data, v3data, &ier);
 
   return(ier);
 }
diff --git a/src/cvode/fcmix/fcvbbd.c b/src/cvode/fcmix/fcvbbd.c
index 38674b1..46ab795 100644
--- a/src/cvode/fcmix/fcvbbd.c
+++ b/src/cvode/fcmix/fcvbbd.c
@@ -1,20 +1,21 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *     Alan C. Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This module contains the routines necessary to interface with the
  * CVBBDPRE module and user-supplied Fortran routines.
@@ -30,9 +31,6 @@
 #include "fcvbbd.h"              /* prototypes of interfaces to CVBBDPRE           */
 
 #include <cvode/cvode_bbdpre.h>  /* prototypes of CVBBDPRE functions and macros    */
-#include <cvode/cvode_sptfqmr.h> /* prototypes of CVSPTFQMR interface routines     */
-#include <cvode/cvode_spbcgs.h>  /* prototypes of CVSPBCG interface routines       */
-#include <cvode/cvode_spgmr.h>   /* prototypes of CVSPGMR interface routines       */
 
 /***************************************************************************/
 
@@ -42,15 +40,14 @@
 extern "C" {
 #endif
 
-  extern void FCV_GLOCFN(long int*,                        /* NLOC          */
-                         realtype*, realtype*, realtype*,  /* T, YLOC, GLOC */
-                         long int*, realtype*,             /* IPAR, RPAR    */
-                         int *ier);                        /* IER           */
+  extern void FCV_GLOCFN(long int *NLOC, realtype *T, 
+                         realtype *YLOC, realtype *GLOC,
+                         long int *IPAR, realtype *RPAR,
+                         int *ier);
 
-  extern void FCV_COMMFN(long int*,                        /* NLOC          */
-                         realtype*, realtype*,             /* T, Y          */
-                         long int*, realtype*,             /* IPAR, RPAR    */
-                         int *ier);                        /* IER           */
+  extern void FCV_COMMFN(long int *NLOC, realtype *T,
+                         realtype *Y, long int *IPAR,
+                         realtype *RPAR, int *ier);
 
 #ifdef __cplusplus
 }
@@ -58,8 +55,8 @@ extern "C" {
 
 /***************************************************************************/
 
-void FCV_BBDINIT(long int *Nloc, long int *mudq, long int *mldq, long int *mu, long int *ml, 
-                 realtype* dqrely, int *ier)
+void FCV_BBDINIT(long int *Nloc, long int *mudq, long int *mldq,
+                 long int *mu, long int *ml, realtype* dqrely, int *ier)
 {
 
   /* 
@@ -72,15 +69,16 @@ void FCV_BBDINIT(long int *Nloc, long int *mudq, long int *mldq, long int *mu, l
      FCVcfn     is a pointer to the CVCommFn function 
   */
 
-  *ier = CVBBDPrecInit(CV_cvodemem, *Nloc, *mudq, *mldq, *mu, *ml, 
-                       *dqrely, FCVgloc, FCVcfn);
+  *ier = CVBBDPrecInit(CV_cvodemem, *Nloc, *mudq, *mldq, *mu, *ml, *dqrely,
+                       (CVLocalFn) FCVgloc, (CVCommFn) FCVcfn);
 
   return; 
 }
 
 /***************************************************************************/
 
-void FCV_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq, realtype* dqrely, int *ier)
+void FCV_BBDREINIT(long int *mudq, long int *mldq,
+                   realtype* dqrely, int *ier)
 {
   /* 
      First call CVReInitBBD to re-initialize CVBBDPRE module:
@@ -98,7 +96,8 @@ void FCV_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq, realtype* dqr
 /* C function FCVgloc to interface between CVBBDPRE module and a Fortran 
    subroutine FCVLOCFN. */
 
-int FCVgloc(long int Nloc, realtype t, N_Vector yloc, N_Vector gloc, void *user_data)
+int FCVgloc(long int Nloc, realtype t, N_Vector yloc, N_Vector gloc,
+            void *user_data)
 {
   int ier;
   realtype *yloc_data, *gloc_data;
@@ -110,8 +109,7 @@ int FCVgloc(long int Nloc, realtype t, N_Vector yloc, N_Vector gloc, void *user_
   CV_userdata = (FCVUserData) user_data;
 
   FCV_GLOCFN(&Nloc, &t, yloc_data, gloc_data, 
-             CV_userdata->ipar, CV_userdata->rpar,
-             &ier);
+             CV_userdata->ipar, CV_userdata->rpar, &ier);
   return(ier);
 }
 
diff --git a/src/cvode/fcmix/fcvbbd.h b/src/cvode/fcmix/fcvbbd.h
index c47aba6..d229329 100644
--- a/src/cvode/fcmix/fcvbbd.h
+++ b/src/cvode/fcmix/fcvbbd.h
@@ -1,21 +1,22 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *    Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
+ * LLNS/SMU Copyright End
+ *---------------------------------------------------------------
  * This is the Fortran interface include file for the BBD
  * preconditioner (CVBBDPRE)
  * -----------------------------------------------------------------
@@ -28,34 +29,44 @@
  * 
  * The FCVBBD Interface Package is a package of C functions which,
  * together with the FCVODE Interface Package, support the use of the
- * CVODE solver (parallel MPI version) with the CVBBDPRE preconditioner module,
- * for the solution of ODE systems in a mixed Fortran/C setting.  The
- * combination of CVODE and CVBBDPRE solves systems dy/dt = f(t,y) with
- * the SPGMR (scaled preconditioned GMRES), SPTFQMR (scaled preconditioned TFQMR),
- * or SPBCG (scaled preconditioned Bi-CGSTAB) method for the linear systems that
- * arise, and with a preconditioner that is block-diagonal with banded blocks.
+ * CVODE solver and MPI-parallel N_Vector module, along with the CVBBDPRE 
+ * preconditioner module, for the solution of ODE systems in a mixed 
+ * Fortran/C setting.  The combination of CVODE and CVBBDPRE solves systems 
+ * dy/dt = f(t,y) using a Krylov iterative linear solver via the CVSPILS 
+ * interface, and with a preconditioner that is block-diagonal with banded blocks.
  * While CVODE and CVBBDPRE are written in C, it is assumed here that the user's
  * calling program and user-supplied problem-defining routines are written in
  * Fortran.
  * 
  * The user-callable functions in this package, with the corresponding
  * CVODE and CVBBDPRE functions, are as follows: 
- *   FCVBBDININT   interfaces to CVBBDPrecInit
- *   FCVBBDREINIT  interfaces to CVBBDPrecReInit
- *   FCVBBDOPT     accesses optional outputs
+ *
+ *   Fortran               CVODE
+ *   --------------        ---------------------------
+ *   FCVBBDININT           CVBBDPrecInit
+ *   FCVBBDREINIT          CVBBDPrecReInit
+ *   FCVBBDOPT             (accesses optional outputs)
+ *   --------------        ---------------------------
  * 
  * In addition to the Fortran right-hand side function FCVFUN, the
  * user-supplied functions used by this package, are listed below,
  * each with the corresponding interface function which calls it (and its
  * type within CVBBDPRE or CVODE):
- *   FCVLOCFN  is called by the interface function FCVgloc of type CVLocalFn
- *   FCVCOMMF  is called by the interface function FCVcfn of type CVCommFn
- *   FCVJTIMES (optional) is called by the interface function FCVJtimes of 
- *             type CVSpilsJtimesFn
- * (The names of all user-supplied routines here are fixed, in order to
- * maximize portability for the resulting mixed-language program.)
+ *
+ *   Fortran           CVODE            Type
+ *   --------------    -----------      -----------------
+ *   FCVLOCFN          FCVgloc          CVLocalFn
+ *   FCVCOMMF          FCVcfn           CVCommFn
+ *   FCVJTSETUP(*)     FCVJTSetup       CVSpilsJTSetupFn
+ *   FCVJTIMES(*)      FCVJtimes        CVSpilsJtimesFn
+ *   --------------    -----------      -----------------
+ *   (*) = optional
  * 
- * Important note on portability.
+ * Important notes on portability:
+ *
+ * The names of all user-supplied routines here are fixed, in order to
+ * maximize portability for the resulting mixed-language program.
+ *
  * In this package, the names of the interface functions, and the names of
  * the Fortran user routines called by them, appear as dummy names
  * which are mapped to actual values by a series of definitions in the
@@ -66,7 +77,7 @@
  *               Usage of the FCVODE/FCVBBD Interface Packages
  * 
  * The usage of the combined interface packages FCVODE and FCVBBD requires
- * calls to seven to twelve interface functions, and three or four user-supplied
+ * calls to a variety of interface functions, and three or more user-supplied
  * routines which define the problem to be solved and indirectly define
  * the preconditioner.  These function calls and user routines are
  * summarized separately below.
@@ -75,200 +86,390 @@
  * for more complete information.
  * 
  * (1) User-supplied right-hand side routine: FCVFUN
- * The user must in all cases supply the following Fortran routine
+ *
+ *   The user must in all cases supply the following Fortran routine
+ *
  *       SUBROUTINE FCVFUN (T, Y, YDOT, IPAR, RPAR, IER)
- *       DIMENSION Y(*), YDOT(*), IPAR(*), RPAR(*)
- * It must set the YDOT array to f(t,y), the right-hand side of the ODE
- * system, as function of T = t and the array Y = y.  Here Y and YDOT
- * are distributed vectors.
+ *
+ *   It must set the YDOT array to f(t,y), the right-hand side of the ODE
+ *   system, as function of T = t and the array Y = y.  
+ *
+ *   The arguments are:
+ *       Y    -- array containing state variables [realtype, input]
+ *       YDOT -- array containing state derivatives [realtype, 
+ *               output]
+ *       IPAR -- array containing integer user data that was passed
+ *               to FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                 >0 if a recoverable error occurred,
+ *                 <0 if an unrecoverable error ocurred.
  * 
  * (2) User-supplied routines to define preconditoner: FCVLOCFN and FCVCOMMF
  * 
- * The routines in the CVBBDPRE module provide a preconditioner matrix
- * for CVODE that is block-diagonal with banded blocks.  The blocking
- * corresponds to the distribution of the dependent variable vector y
- * among the processors.  Each preconditioner block is generated from the
- * Jacobian of the local part (on the current processor) of a given
- * function g(t,y) approximating f(t,y).  The blocks are generated by a
- * difference quotient scheme on each processor independently, utilizing
- * an assumed banded structure with given half-bandwidths.  A separate
- * pair of half-bandwidths defines the band matrix retained.
+ *   The routines in the CVBBDPRE module provide a preconditioner matrix
+ *   for CVODE that is block-diagonal with banded blocks.  The blocking
+ *   corresponds to the distribution of the dependent variable vector y
+ *   among the processors.  Each preconditioner block is generated from the
+ *   Jacobian of the local part (on the current processor) of a given
+ *   function g(t,y) approximating f(t,y).  The blocks are generated by a
+ *   difference quotient scheme on each processor independently, utilizing
+ *   an assumed banded structure with given half-bandwidths.  A separate
+ *   pair of half-bandwidths defines the band matrix retained.
  * 
  * (2.1) Local approximate function FCVLOCFN.
- * The user must supply a subroutine of the form
+ * 
+ *   The user must supply a subroutine of the form
+ *
  *       SUBROUTINE FCVLOCFN (NLOC, T, YLOC, GLOC, IPAR, RPAR, IER)
- *       DIMENSION YLOC(*), GLOC(*), IPAR(*), RPAR(*)
- * to compute the function g(t,y) which approximates the right-hand side
- * function f(t,y).  This function is to be computed locally, i.e. without 
- * interprocess communication.  (The case where g is mathematically
- * identical to f is allowed.)  It takes as input the local vector length
- * NLOC, the independent variable value T = t, and the local realtype
- * dependent variable array YLOC.  It is to compute the local part of
- * g(t,y) and store this in the realtype array GLOC.
- * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred,
- * and IER < 0 if an unrecoverable error ocurred.
+ *
+ *   To compute the function g(t,y) which approximates the right-hand side
+ *   function f(t,y).  This function is to be computed locally, i.e. without 
+ *   interprocess communication.  (The case where g is mathematically
+ *   identical to f is allowed.)  
+ * 
+ *   The arguments are:
+ *       NLOC -- local problem size [long int, input]
+ *       T    -- current time [realtype, input]
+ *       YLOC -- array containing local state variables 
+ *               [realtype, input]
+ *       GLOC -- array containing local state derivatives 
+ *               [realtype, output]
+ *       IPAR -- array containing integer user data that was passed
+ *               to FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                 >0 if a recoverable error occurred,
+ *                 <0 if an unrecoverable error ocurred.
  * 
  * (2.2) Communication function FCVCOMMF.
- * The user must also supply a subroutine of the form
+ *
+ *   The user must also supply a subroutine of the form
+ *
  *       SUBROUTINE FCVCOMMF (NLOC, T, YLOC, IPAR, RPAR, IER)
- *       DIMENSION YLOC(*), IPAR(*), RPAR(*)
- * which is to perform all interprocess communication necessary to
- * evaluate the approximate right-hand side function g described above.
- * This function takes as input the local vector length NLOC, the
- * independent variable value T = t, and the local real dependent
- * variable array YLOC.  It is expected to save communicated data in 
- * work space defined by the user, and made available to CVLOCFN.
- * Each call to the FCVCOMMF is preceded by a call to FCVFUN with the same
- * (t,y) arguments.  Thus FCVCOMMF can omit any communications done by 
- * FCVFUN if relevant to the evaluation of g.
- * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred,
- * and IER < 0 if an unrecoverable error ocurred.
+ *
+ *   which is to perform all interprocess communication necessary to
+ *   evaluate the approximate right-hand side function g described above.
+ *   This function takes as input the local vector length NLOC, the
+ *   independent variable value T = t, and the local real dependent
+ *   variable array YLOC.  It is expected to save communicated data in 
+ *   work space defined by the user, and made available to CVLOCFN.
+ *   Each call to the FCVCOMMF is preceded by a call to FCVFUN with the same
+ *   (t,y) arguments.  Thus FCVCOMMF can omit any communications done by 
+ *   FCVFUN if relevant to the evaluation of g.
+ *
+ *   The arguments are:
+ *       NLOC -- local problem size [long int, input]
+ *       T    -- current time [realtype, input]
+ *       YLOC -- array containing local state variables 
+ *               [realtype, input]
+ *       IPAR -- array containing integer user data that was passed
+ *               to FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                 >0 if a recoverable error occurred,
+ *                 <0 if an unrecoverable error ocurred.
  * 
- * (3) Optional user-supplied Jacobian-vector product routine: FCVJTIMES
- * As an option, the user may supply a routine that computes the product
- * of the system Jacobian J = df/dy and a given vector v.  If supplied, it
- * must have the following form:
- *       SUBROUTINE FCVJTIMES (V, FJV, T, Y, FY, EWT, IPAR, RPAR, WORK, IER)
- *       DIMENSION V(*), FJV(*), Y(*), FY(*), EWT(*), IPAR(*), RPAR(*), WORK(*)
- * Typically this routine will use only NEQ, T, Y, V, and FJV.  It must
- * compute the product vector Jv, where the vector v is stored in V, and store
- * the product in FJV.  On return, set IER = 0 if FCVJTIMES was successful,
- * and nonzero otherwise.
+ * (3) Optional user-supplied Jacobian-vector setup and product 
+ *   functions: FCVJTSETUP and FCVJTIMES
+ *
+ *   As an option, the user may supply a routine that computes the product
+ *   of the system Jacobian J = df/dy and a given vector v.  If supplied, a 
+ *   'setup' routine to prepare any user data structures must exist, and 
+ *   have the form:
  * 
- * (4) Initialization:  FNVINITP, FCVMALLOC, FCVBBDINIT.
+ *       SUBROUTINE FCVJTSETUP(T, Y, FY, H, IPAR, RPAR, IER)
+ *
+ *   Typically this routine will use only T and Y.  It must perform any 
+ *   relevant preparations for subsequent calls to the user-provided 
+ *   FCVJTIMES routine (see below).  
+ *
+ *   The arguments are:
+ *       T    -- current time [realtype, input]
+ *       Y    -- array containing state variables [realtype, input]
+ *       FY   -- array containing state derivatives [realtype, input]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                  nonzero if an error.
  * 
- * (4.1) To initialize the parallel vector specification, the user must make 
- * the following call:
- *        CALL FNVINITP (NLOCAL, NGLOBAL, IER)
- * The arguments are:
- * NLOCAL  = local size of vectors on this processor
- * NGLOBAL = the system size, and the global size of vectors (the sum 
- *           of all values of NLOCAL)
- * IER     = return completion flag. Values are 0 = success, -1 = failure.
+ *   The accompanying Jacobian matrix-vector product routine must 
+ *   have the following form:
+ *
+ *       SUBROUTINE FCVJTIMES (V, FJV, T, Y, FY, EWT, IPAR, RPAR, WORK, IER)
+ *
+ *   Typically this routine will use only NEQ, T, Y, V, and FJV.  It must
+ *   compute the product vector Jv, where the vector v is stored in V, and store
+ *   the product in FJV.  
  * 
- * Note: If MPI was initialized by the user, the communicator must be
- * set to MPI_COMM_WORLD.  If not, this routine initializes MPI and sets
- * the communicator equal to MPI_COMM_WORLD.
+ *     The arguments are:
+ *       V    -- vector to multiply [realtype, input]
+ *       FJV  -- product vector [realtype, output]
+ *       T    -- current time [realtype, input]
+ *       Y    -- state variables [realtype, input]
+ *       FY   -- state derivatives [realtype, input]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed
+ *               to FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       WORK -- array containing temporary workspace of same size
+ *               as Y [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                  nonzero if an error.
+ *
+ * (4) Initialization:  FNVINITP, generic iterative linear solver
+ *   initialization, FCVMALLOC, FCVSPILSINIT, and FCVBBDINIT.
  * 
- * (4.2) To set various problem and solution parameters and allocate
+ * (4.1) To initialize the parallel vector specification, the user must make 
+ *   the following call:
+ *
+ *        CALL FNVINITP(COMM, 1, NLOCAL, NGLOBAL, IER)
+ *
+ *   where the second argument is an int containing the CVODE 
+ *   solver ID (1). The other arguments are:
+ *        COMM = the MPI communicator [int, input]
+ *        NLOCAL = local vector size on this processor 
+ *           [long int, input]
+ *        NGLOBAL = system size, and the global size of vectors 
+ *           (the sum of all values of NLOCAL) [long int, input]
+ *        IER = return completion flag [int, ouptut]. 
+ *                  0 = success, 
+ *                 -1 = failure.
+ *
+ * (4.2) To initialize a generic iterative linear solver structure for 
+ *   solving linear systems arising from implicit or IMEX treatment 
+ *   of the IVP, the user must make one of the following calls:
+ *
+ *          CALL FSUNPCGINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPBCGSINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPFGMRINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPGMRINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPTFQMRINIT(1, PRETYPE, MAXL, IER)
+ *
+ *   In each of these, one argument is an int containing the CVODE solver 
+ *   ID (1). 
+ *
+ *     The other arguments are:
+ *
+ *        PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+ *           2=right, 3=both) [int, input]
+ *        MAXL = maximum Krylov subspace dimension [int, input]
+ *        IER = return completion flag [int, output]:
+ *	          0 = success, 
+ *		 -1 = failure.
+ *
+ * (4.3) To set various problem and solution parameters and allocate
  * internal memory for CVODE, make the following call:
+ *
  *       CALL FCVMALLOC(T0, Y0, METH, ITMETH, IATOL, RTOL, ATOL,
  *      1               IOUT, ROUT, IPAR, RPAR, IER)
+ *
  * The arguments are:
- * T0     = initial value of t
- * Y0     = array of initial conditions
- * METH   = basic integration method: 1 = Adams (nonstiff), 2 = BDF (stiff)
- * ITMETH = nonlinear iteration method: 1 = functional iteration, 2 = Newton iter.
- * IATOL  = type for absolute tolerance ATOL: 1 = scalar, 2 = array
- * RTOL   = relative tolerance (scalar)
- * ATOL   = absolute tolerance (scalar or array)
- * IOUT   = array of length 21 for integer optional outputs
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * ROUT   = array of length 6 for real optional outputs
- * IPAR   = array with user integer data
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * RPAR   = array with user real data
- * IER    = return completion flag.  Values are 0 = success, and -1 = failure.
- *          See printed message for details in case of failure.
+ *      T0     = initial value of t [realtype, input]
+ *      Y0     = array of initial conditions [realtype, input]
+ *      METH   = flag denoting integration method [int, input]: 
+ *                  1 = Adams (nonstiff), 
+ *                  2 = BDF (stiff)
+ *      ITMETH = flag denoting type of nonlinear iteration method [int, input]:
+ *                  1 = functional iteration, 
+ *                  2 = Newton iteration
+ *      IATOL  = flag denoting type for absolute tolerance ATOL [int, input]: 
+ *                  1 = scalar, 
+ *                  2 = array
+ *      RTOL   = scalar relative tolerance [realtype, input]
+ *      ATOL   = scalar or array absolute tolerance [realtype, input]
+ *      IOUT   = array of length at least 21 for integer optional outputs
+ *               [long int, output]
+ *      ROUT   = array of length at least 6 for real optional outputs
+ *               [realtype, output]
+ *      IPAR   = array with user integer data [long int, in/out]
+ *      RPAR   = array with user real data [realtype, in/out]
+ *      IER    = return completion flag [int, output]:
+ *                  0 = success, 
+ *                 -1 = failure (see printed message for details).
+ *
+ *   The user data arrays IPAR and RPAR are passed unmodified to 
+ *   all subsequent calls to user-provided routines. Changes to
+ *   either array inside a user-provided routine will be 
+ *   propagated. Using these two arrays, the user can dispense 
+ *   with COMMON blocks to pass data betwen user-provided 
+ *   routines. 
  * 
- * (4.3) Attach one of the 3 SPILS linear solvers. Make one of the 
- * following calls (see fcvode.h for more details).
- *       CALL FCVSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)
- *       CALL FCVSPBCG(IPRETYPE, MAXL, DELT, IER)
- *       CALL FCVSPTFQMR(IPRETYPE, MAXL, DELT, IER)
+ * (4.3) Create the CVSPILS interface to attach the generic 
+ *   iterative linear solver to CVode, by making the following call:
+ *    
+ *       CALL FCVSPILSINIT(IER)
+ *
+ *   The arguments are:
+ *	IER = error return flag [int, output]: 
+ *	       0 = success; 
+ *	      <0 = an error occured
  *    
  * (4.4) To allocate memory and initialize data associated with the CVBBDPRE
- * preconditioner, make the following call:
+ *   preconditioner, make the following call:
+ *
  *       CALL FCVBBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER)
  * 
  * The arguments are:
- * NLOCAL    = local size of vectors on this processor
- * MUDQ,MLDQ = upper and lower half-bandwidths to be used in the computation
- *             of the local Jacobian blocks by difference quotients.
- *             These may be smaller than the true half-bandwidths of the
- *             Jacobian of the local block of g, when smaller values may
- *             provide greater efficiency.
- * MU, ML    = upper and lower half-bandwidths of the band matrix that 
- *             is retained as an approximation of the local Jacobian block.
- *             These may be smaller than MUDQ and MLDQ.
- * DQRELY    = relative increment factor in y for difference quotients
- *             (optional). 0.0 indicates the default, sqrt(unit roundoff).
- * IER       = return completion flag: IER=0: success, IER<0: an error occurred
- *
- * (4.5) To specify whether the Krylov linear solver (GMRES, Bi-CGSTAB, or TFQMR)
- * should use the supplied FCVJTIMES or the internal finite difference approximation, 
- * make the call
+ *        NLOCAL = local vector size on this process 
+ *             [long int, input]
+ *        MUDQ = upper half-bandwidth to be used in the computation
+ *             of the local Jacobian blocks by difference 
+ *             quotients.  These may be smaller than the true 
+ *             half-bandwidths of the Jacobian of the local block 
+ *             of g, when smaller values may provide greater 
+ *             efficiency [long int, input]
+ *        MLDQ = lower half-bandwidth to be used in the computation
+ *             of the local Jacobian blocks by difference 
+ *             quotients [long int, input]
+ *        MU = upper half-bandwidth of the band matrix that is
+ *             retained as an approximation of the local Jacobian
+ *             block (may be smaller than MUDQ) [long int, input]
+ *        ML = lower half-bandwidth of the band matrix that is
+ *             retained as an approximation of the local Jacobian
+ *             block (may be smaller than MLDQ) [long int, input]
+ *        DQRELY = relative increment factor in y for difference 
+ *             quotients [realtype, input]
+ *                    0.0 = default (sqrt(unit roundoff))
+ *        IER = return completion flag [int, output]:
+ *                    0 = success
+ *                   <0 = an error occurred
+ *
+ * (4.5) To specify whether the Krylov linear solver should use the 
+ *   supplied FCVJTIMES or the internal finite difference approximation, 
+ *   make the call
+ *
  *        CALL FCVSPILSSETJAC(FLAG, IER)
- * where FLAG=0 for finite differences approximation or
- *       FLAG=1 to use the supplied routine FCVJTIMES
+ *
+ *   with the int FLAG=1 to specify that FCVJTSETUP and FCVJTIMES 
+ *   are provided (FLAG=0 specifies to use and internal finite 
+ *   difference approximation to this product).  The int return 
+ *   flag IER=0 if successful, and nonzero otherwise.
  * 
  * (5) Re-initialization: FCVREINIT, FCVBBDREINIT
- * If a sequence of problems of the same size is being solved using the SPGMR, SPBCG,
- * SPTFQMR linear solver in combination with the CVBBDPRE preconditioner, then the
- * CVODE package can be reinitialized for the second and subsequent problems
- * so as to avoid further memory allocation.  First, in place of the call
- * to FCVMALLOC, make the following call:
+ *
+ *   If a sequence of problems of the same size is being solved using the 
+ *   Krylov linear solver in combination with the CVBBDPRE preconditioner, 
+ *   then the CVODE package can be reinitialized for the second and 
+ *   subsequent problems so as to avoid further memory allocation.  First, 
+ *   in place of the call to FCVMALLOC, make the following call:
+ *
  *       CALL FCVREINIT(T0, Y0, IATOL, RTOL, ATOL, IER)
- * The arguments have the same names and meanings as those of FCVMALLOC, except
- * that METH and ITMETH have been omitted from the argument list (being unchanged
- * for the new problem).  FCVREINIT performs the same initializations as
- * FCVMALLOC, but does no memory allocation, using instead the existing
- * internal memory created by the previous FCVMALLOC call.
- *
- * If there is a change in any of the linear solver arguments, then
- * a call to FCVSPGMR, FCVSPBCG, or FCVSPTFQMR must also be made;
- * in this case the linear solver memory is reallocated. 
- *
- * Following the call to FCVREINIT, a call to FCVBBDINIT may or may not be needed.
- * If the input arguments are the same, no FCVBBDINIT call is needed.
- * If there is a change in input arguments, then make the call
- *      CALL FCVBBDREINIT(NLOCAL, MUDQ, MLDQ, DQRELY, IER)
- * This reinitializes the BBD preconditioner, but without reallocating its memory.
- * The arguments of the have the same names and meanings as FCVBBDINIT.  
- * If the value of MU or ML is being changed, then a call to FCVBBDINIT must
- * be made.
+ *
+ *   The arguments have the same names and meanings as those of FCVMALLOC, except
+ *   that METH and ITMETH have been omitted from the argument list (being unchanged
+ *   for the new problem).  FCVREINIT performs the same initializations as
+ *   FCVMALLOC, but does no memory allocation, using instead the existing
+ *   internal memory created by the previous FCVMALLOC call.
+ *
+ *   If there is no change in any of the linear solver or 
+ *   preconditioner arguments, then no additional calls are 
+ *   necessary.  
+ *
+ *   Following the call to FCVREINIT, if there is no change in any of the 
+ *   linear solver arguments, but the user wishes to modify the values of 
+ *   MUDQ, MLDQ or DQRELY from the previous call to FCVBBDINIT, then a user 
+ *   may call:
+ *
+ *      CALL FCVBBDREINIT(MUDQ, MLDQ, DQRELY, IER)
+ *
+ *   This reinitializes the BBD preconditioner, but without reallocating 
+ *   its memory. The arguments of the have the same names and meanings as 
+ *   FCVBBDINIT.  
+ *
+ *   However, if there is a change in any of the linear solver 
+ *   arguments or other preconditioner arguments, then a call to
+ *   FSUNPCGINIT, FSUNSPBCGSINIT, FSUNSPFGMRINIT, FSUNSPGMRINIT, 
+ *   or FSUNSPTFQMRINIT is required; in this case the linear 
+ *   solver memory is reallocated.  Following this call, the 
+ *   CVSPILS interface must also be reconstructed using another
+ *   call to FCVSPILSINIT (interface memory is freed and 
+ *   reallocated), as well as a subsequent call to FCVBBDINIT.
+ * 
  * 
  * (6) The integrator: FCVODE
- * Carrying out the integration is accomplished by making calls as follows:
+ *
+ *   Carrying out the integration is accomplished by making calls as follows:
+ *
  *       CALL FCVODE (TOUT, T, Y, ITASK, IER)
- * The arguments are:
- * TOUT  = next value of t at which a solution is desired (input)
- * T     = value of t reached by the solver on output
- * Y     = array containing the computed solution on output
- * ITASK = task indicator: 
- *         1 = normal mode (overshoot TOUT and interpolate)
- *         2 = one-step mode (return after each internal step taken)
- *         3 = normal mode with TSTOP check
- *         4 = one-step mode with TSTOP check
- * IER   = completion flag: 0 = success, 1 = TSTOP return, 2 = root return,
- *         negative values are various failure modes (see CVODE User Guide).
- * The current values of the optional outputs are available in IOUT and ROUT.
+ *
+ *   The arguments are:
+ *      TOUT  = next value of t at which a solution is desired [realtype, input]
+ *      T     = value of t reached by the solver [realtype, output]
+ *      Y     = array containing the computed solution [realtype, output]
+ *      ITASK = task indicator [int, input]: 
+ *              1 = normal mode (overshoot TOUT and interpolate)
+ *              2 = one-step mode (return after each internal step taken)
+ *              3 = normal mode with TSTOP check
+ *              4 = one-step mode with TSTOP check
+ *      IER   = completion flag [int, output]: 
+ *              0 = success, 
+ *              1 = TSTOP return, 
+ *              2 = root return,
+ *              negative values are various failure modes (see CVODE User Guide).
+ *    The current values of the optional outputs are available in IOUT and ROUT.
  * 
  * (7) Optional outputs: FCVBBDOPT
- * Optional outputs specific to the SP* solver are LRW, LIW, LFLG, NFELS, NJTV,
- * NPE, NPS, NLI, NCFL, stored in IOUT(13)...IOUT(21).
- * To obtain the optional outputs associated with the CVBBDPRE module, make
- * the following call:
+ *
+ *   Optional outputs specific to the CVSPILS solver interface are 
+ *        LENRWLS = IOUT(13) from CVSpilsGetWorkSpace
+ *        LENIWLS = IOUT(14) from CVSpilsGetWorkSpace
+ *        LSTF    = IOUT(15) from CVSpilsGetLastFlag
+ *        NFELS   = IOUT(16) from CVSpilsGetNumRhsEvals
+ *        NJTV    = IOUT(17) from CVSpilsGetNumJtimesEvals
+ *        NPE     = IOUT(18) from CVSpilsGetNumPrecEvals
+ *        NPS     = IOUT(19) from CVSpilsGetNumPrecSolves
+ *        NLI     = IOUT(20) from CVSpilsGetNumLinIters
+ *        NCFL    = IOUT(21) from CVSpilsGetNumConvFails
+ *   See the CVODE manual for descriptions.
+ *
+ *   To obtain the optional outputs associated with the CVBBDPRE module, make
+ *   the following call:
+ *
  *       CALL FCVBBDOPT (LENRWBBD, LENIWBBD, NGEBBD)
- * The arguments returned are:
- * LENRWBBD = length of real preconditioner work space, in realtype words.
- *            This size is local to the current processor.
- * LENIWBBD = length of integer preconditioner work space, in integer words.
- *            This size is local to the current processor.
- * NGEBBD   = number of g(t,y) evaluations (calls to CVLOCFN) so far.
+ *
+ *   The arguments returned are:
+ *      LENRWBBD = length of real preconditioner work space, in realtype words.
+ *                 This size is local to the current processor [long int, output]
+ *      LENIWBBD = length of integer preconditioner work space, in integer words.
+ *                 This size is local to the current processor [long int, output]
+ *      NGEBBD   = number of g(t,y) evaluations (calls to CVLOCFN) so far
+ *                 [long int, output]
  * 
  * (8) Computing solution derivatives: FCVDKY
- * To obtain a derivative of the solution (optionally), of order up to
- * the current method order, make the following call:
+ *
+ *   To obtain a derivative of the solution (optionally), of order up to
+ *   the current method order, make the following call:
+ *
  *       CALL FCVDKY (T, K, DKY)
- * The arguments are:
- * T   = value of t at which solution derivative is desired
- * K   = derivative order (0 .le. K .le. QU)
- * DKY = array containing computed K-th derivative of y on return
+ *
+ *   The arguments are:
+ *       T = time at which solution derivative is desired, within 
+ *           the interval [TCUR-HU,TCUR], [realtype, input].
+ *       K = derivative order (0 .le. K .le. QU) [int, input]
+ *       DKY = array containing computed K-th derivative of y 
+ *           [realtype, output]
+ *       IER = return flag [int, output]: 
+ *                    0 = success
+ *                   <0 = illegal argument.
  * 
  * (9) Memory freeing: FCVFREE
- *   To the free the internal memory created by the calls to FNVINITP,
- * FCVMALLOC, and FCVBBDINIT, make the following call:
+ *
+ *   To the free the internal memory created by the calls to FNVINIT*,
+ *   FCVMALLOC, FCVSPILSINIT and FCVBBDINIT, make the following call:
+ *
  *       CALL FCVFREE
  *
  * ==============================================================================
@@ -307,16 +508,21 @@ extern "C" {
 
 /* Prototypes of exported functions */
 
-void FCV_BBDINIT(long int *Nloc, long int *mudq, long int *mldq, long int *mu, long int *ml,
-                 realtype* dqrely, int *ier);
-void FCV_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq, realtype* dqrely, int *ier);
-void FCV_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd);
+void FCV_BBDINIT(long int *Nloc, long int *mudq,
+                 long int *mldq, long int *mu,
+                 long int *ml, realtype* dqrely, int *ier);
+void FCV_BBDREINIT(long int *mudq, long int *mldq,
+                   realtype* dqrely, int *ier);
+void FCV_BBDOPT(long int *lenrwbbd, long int *leniwbbd,
+                long int *ngebbd);
 
 /* Prototypes: Functions Called by the CVBBDPRE Module */
 
-int FCVgloc(long int Nloc, realtype t, N_Vector yloc, N_Vector gloc, void *user_data);
+int FCVgloc(long int Nloc, realtype t, N_Vector yloc,
+            N_Vector gloc, void *user_data);
 
-int FCVcfn(long int Nloc, realtype t, N_Vector y, void *user_data);
+int FCVcfn(long int Nloc, realtype t, N_Vector y,
+           void *user_data);
 
 #ifdef __cplusplus
 }
diff --git a/src/cvode/fcmix/fcvbp.c b/src/cvode/fcmix/fcvbp.c
index 204c129..2c49463 100644
--- a/src/cvode/fcmix/fcvbp.c
+++ b/src/cvode/fcmix/fcvbp.c
@@ -1,19 +1,21 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *      Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This module contains the routines necessary to interface with the
  * CVBANDPRE module and user-supplied Fortran routines.
@@ -29,9 +31,6 @@
 #include "fcvbp.h"                  /* prototypes of interfaces to CVBANDPRE        */
 
 #include <cvode/cvode_bandpre.h>    /* prototypes of CVBANDPRE functions and macros */
-#include <cvode/cvode_sptfqmr.h>    /* prototypes of CVSPTFQMR interface routines   */
-#include <cvode/cvode_spbcgs.h>     /* prototypes of CVSPBCG interface routines     */
-#include <cvode/cvode_spgmr.h>      /* prototypes of CVSPGMR interface routines     */
 
 /***************************************************************************/
 
diff --git a/src/cvode/fcmix/fcvbp.h b/src/cvode/fcmix/fcvbp.h
index 51d5793..3ca7c80 100644
--- a/src/cvode/fcmix/fcvbp.h
+++ b/src/cvode/fcmix/fcvbp.h
@@ -1,19 +1,21 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the Fortran interface include file for the BAND
  * preconditioner (CVBANDPRE).
@@ -27,25 +29,31 @@
  *
  * The FCVBP Interface Package is a package of C functions which,
  * together with the FCVODE Interface Package, support the use of the
- * CVODE solver (serial version) with the CVBANDPRE preconditioner module,
- * for the solution of ODE systems in a mixed Fortran/C setting.  The
- * combination of CVODE and CVBANDPRE solves systems dy/dt = f(t,y) with the
- * SPGMR (scaled preconditioned GMRES), SPTFQMR (scaled preconditioned TFQMR),
- *  or SPBCG (scaled preconditioned Bi-CGSTAB) method for the linear systems
- * that arise, and with a banded difference quotient Jacobian-based preconditioner.
+ * CVODE solver and serial, OpenMP or PThreads vector module with the 
+ * CVBANDPRE preconditioner module, for the solution of ODE systems in 
+ * a mixed Fortran/C setting.  The combination of CVODE and CVBANDPRE solves 
+ * systems dy/dt = f(t,y) using a Krylov iterative linear solver with a banded
+ * difference quotient Jacobian-based preconditioner.
  * 
  * The user-callable functions in this package, with the corresponding
  * CVODE and CVBBDPRE functions, are as follows: 
- *   FCVBPINIT    interfaces to CVBandPrecInit
- *   FCVBPOPT     accesses optional outputs
+ *
+ *   Fortran              CVODE
+ *   -------------        ---------------------------
+ *   FCVBPINIT            CVBandPrecInit
+ *   FCVBPOPT             (accesses optional outputs)
+ *   -------------        ---------------------------
  * 
  * In addition to the Fortran right-hand side function FCVFUN, the
- * user may (optionally) supply a routine FCVJTIMES which is called by 
- * the interface function FCVJtimes of type CVSpilsJtimesFn.
- * (The names of all user-supplied routines here are fixed, in order to
- * maximize portability for the resulting mixed-language program.)
+ * user may (optionally) supply routines FCVJTSETUP and FCVJTIMES which
+ * are called by the interface function FCVJTSetup of type CVSpilsJTSetupFn 
+ * and the interface function FCVJtimes of type CVSpilsJtimesFn.
  * 
- * Important note on portability.
+ * Important notes on portability.
+ *
+ * The names of all user-supplied routines here are fixed, in order to
+ * maximize portability for the resulting mixed-language program.
+ *
  * In this package, the names of the interface functions, and the names of
  * the Fortran user routines called by them, appear as dummy names
  * which are mapped to actual values by a series of definitions in the
@@ -56,7 +64,7 @@
  *               Usage of the FCVODE/FCVBP Interface Packages
  * 
  * The usage of the combined interface packages FCVODE and FCVBP requires
- * calls to seven to ten interface functions, and one or two user-supplied
+ * calls to a variety of interface functions, and three or more user-supplied
  * routines which define the problem to be solved and indirectly define
  * the preconditioner.  These function calls and user routines are
  * summarized separately below.
@@ -65,148 +73,269 @@
  * for more complete information.
  * 
  * (1) User-supplied right-hand side routine: FCVFUN
- * The user must in all cases supply the following Fortran routine
+ *
+ *   The user must in all cases supply the following Fortran routine
+ *
  *       SUBROUTINE FCVFUN (T, Y, YDOT, IPAR, RPAR, IER)
- *       DIMENSION Y(*), YDOT(*), IPAR(*), RPAR(*)
- * It must set the YDOT array to f(t,y), the right-hand side of the ODE
- * system, as function of T = t and the array Y = y.  Here Y and YDOT
- * are distributed vectors.
- * 
- * (2) Optional user-supplied Jacobian-vector product routine: FCVJTIMES
- * As an option, the user may supply a routine that computes the product
- * of the system Jacobian J = df/dy and a given vector v.  If supplied, it
- * must have the following form:
+ *
+ *   It must set the YDOT array to f(t,y), the right-hand side of the ODE
+ *   system, as function of T = t and the array Y = y.  
+ *
+ *   The arguments are:
+ *       Y    -- array containing state variables [realtype, input]
+ *       YDOT -- array containing state derivatives [realtype, 
+ *               output]
+ *       IPAR -- array containing integer user data that was passed
+ *               to FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                 >0 if a recoverable error occurred,
+ *                 <0 if an unrecoverable error ocurred.
+ * 
+ * 
+ * (2) Optional user-supplied Jacobian-vector setup and product 
+ *   functions: FCVJTSETUP and FCVJTIMES
+ *
+ *   As an option, the user may supply a routine that computes the product
+ *   of the system Jacobian J = df/dy and a given vector v.  If supplied, a 
+ *   'setup' routine to prepare any user data structures must exist, and 
+ *   have the form:
+ * 
+ *       SUBROUTINE FCVJTSETUP(T, Y, FY, H, IPAR, RPAR, IER)
+ *
+ *   Typically this routine will use only T and Y.  It must perform any 
+ *   relevant preparations for subsequent calls to the user-provided 
+ *   FCVJTIMES routine (see below).  
+ *
+ *   The arguments are:
+ *       T    -- current time [realtype, input]
+ *       Y    -- array containing state variables [realtype, input]
+ *       FY   -- array containing state derivatives [realtype, input]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                  nonzero if an error.
+ * 
+ *   The accompanying Jacobian matrix-vector product routine must 
+ *   have the following form:
+ *
  *       SUBROUTINE FCVJTIMES (V, FJV, T, Y, FY, EWT, IPAR, RPAR, WORK, IER)
- *       DIMENSION V(*), FJV(*), Y(*), FY(*), EWT(*), IPAR(*), RPAR(*), WORK(*)
- * Typically this routine will use only NEQ, T, Y, V, and FJV.  It must
- * compute the product vector Jv, where the vector v is stored in V, and store
- * the product in FJV.  On return, set IER = 0 if FCVJTIMES was successful,
- * and nonzero otherwise.
+ *
+ *   Typically this routine will use only NEQ, T, Y, V, and FJV.  It must
+ *   compute the product vector Jv, where the vector v is stored in V, and store
+ *   the product in FJV.  
  * 
- * (3) Initialization:  FNVINITS, FCVMALLOC, FCVBPINIT.
+ *     The arguments are:
+ *       V    -- vector to multiply [realtype, input]
+ *       FJV  -- product vector [realtype, output]
+ *       T    -- current time [realtype, input]
+ *       Y    -- state variables [realtype, input]
+ *       FY   -- state derivatives [realtype, input]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed
+ *               to FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       WORK -- array containing temporary workspace of same size
+ *               as Y [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                  nonzero if an error.
+ *
+ * (3) Initialization:  FNVINITP, generic iterative linear solver
+ *   initialization, FCVMALLOC, FCVSPILSINIT, and FCVBPINIT.
  * 
- * (3.1) To initialize the serial vector specification, the user must make 
- * the following call:
- *        CALL FNVINITS(NEQ, IER)
- * where NEQ is the problem size and IER is a return completion flag.
- * Possible values for IER are 0 = success, -1 = failure.
+ * (3.1) To initialize the vector specification, the user must make
+ *   one of the following calls:
+ *
+ *       (serial)   
+ *          CALL FNVINITS(4, NEQ, IER)
+ *       (OpenMP threaded)
+ *          CALL FNVINITOMP(4, NEQ, NUM_THREADS, IER)
+ *       (PThreads threaded)
+ *          CALL FNVINITPTS(4, NEQ, NUM_THREADS, IER)
+ *
+ *   where the first argument is an int containing the CVODE 
+ *   solver ID (4). The other arguments are:
+ *        NEQ = size of vectors [long int, input]
+ *        NUM_THREADS = number of threads
+ *        IER = return completion flag [int, output]:
+ *	          0 = success, 
+ *		 -1 = failure.
+ *
+ * (3.2) To initialize a generic iterative linear solver structure for 
+ *   solving linear systems arising from implicit or IMEX treatment 
+ *   of the IVP, the user must make one of the following calls:
+ *
+ *          CALL FSUNPCGINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPBCGSINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPFGMRINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPGMRINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPTFQMRINIT(1, PRETYPE, MAXL, IER)
+ *
+ *   In each of these, one argument is an int containing the CVODE solver 
+ *   ID (1). 
+ *
+ *     The other arguments are:
+ *
+ *        PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+ *           2=right, 3=both) [int, input]
+ *        MAXL = maximum Krylov subspace dimension [int, input]
+ *        IER = return completion flag [int, output]:
+ *	          0 = success, 
+ *		 -1 = failure.
+ *
  * 
  * (3.2) To set various problem and solution parameters and allocate
  * internal memory for CVODE, make the following call:
+ *
  *       CALL FCVMALLOC(T0, Y0, METH, ITMETH, IATOL, RTOL, ATOL,
  *      1               IOUT, ROUT, IPAR, RPAR, IER)
+ *
  * The arguments are:
- * T0     = initial value of t
- * Y0     = array of initial conditions
- * METH   = basic integration method: 1 = Adams (nonstiff), 2 = BDF (stiff)
- * ITMETH = nonlinear iteration method: 1 = functional iteration, 2 = Newton iter.
- * IATOL  = type for absolute tolerance ATOL: 1 = scalar, 2 = array
- * RTOL   = relative tolerance (scalar)
- * ATOL   = absolute tolerance (scalar or array)
- * IOUT   = array of length 21 for integer optional outputs
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * ROUT   = array of length 6 for real optional outputs
- * IPAR   = array with user integer data
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * RPAR   = array with user real data
- * IER    = return completion flag.  Values are 0 = success, and -1 = failure.
- *          See printed message for details in case of failure.
- * 
- * (3.3) To allocate memory and initialize data associated with the CVBANDPRE
- * preconditioner, make the following call:
+ *      T0     = initial value of t [realtype, input]
+ *      Y0     = array of initial conditions [realtype, input]
+ *      METH   = flag denoting integration method [int, input]: 
+ *                  1 = Adams (nonstiff), 
+ *                  2 = BDF (stiff)
+ *      ITMETH = flag denoting type of nonlinear iteration method [int, input]:
+ *                  1 = functional iteration, 
+ *                  2 = Newton iteration
+ *      IATOL  = flag denoting type for absolute tolerance ATOL [int, input]: 
+ *                  1 = scalar, 
+ *                  2 = array
+ *      RTOL   = scalar relative tolerance [realtype, input]
+ *      ATOL   = scalar or array absolute tolerance [realtype, input]
+ *      IOUT   = array of length at least 21 for integer optional outputs
+ *               [long int, output]
+ *      ROUT   = array of length at least 6 for real optional outputs
+ *               [realtype, output]
+ *      IPAR   = array with user integer data [long int, in/out]
+ *      RPAR   = array with user real data [realtype, in/out]
+ *      IER    = return completion flag [int, output]:
+ *                  0 = success, 
+ *                 -1 = failure (see printed message for details).
+ *
+ *   The user data arrays IPAR and RPAR are passed unmodified to 
+ *   all subsequent calls to user-provided routines. Changes to
+ *   either array inside a user-provided routine will be 
+ *   propagated. Using these two arrays, the user can dispense 
+ *   with COMMON blocks to pass data betwen user-provided 
+ *   routines. 
+ * 
+ * (3.3) Create the CVSPILS interface to attach the generic 
+ *   iterative linear solver to CVode, by making the following call:
+ *    
+ *       CALL FCVSPILSINIT(IER)
+ *
+ *   The arguments are:
+ *	IER = error return flag [int, output]: 
+ *	       0 = success; 
+ *	      <0 = an error occured
+ * 
+ * (3.4) To allocate memory and initialize data associated with the CVBANDPRE
+ *   preconditioner, make the following call:
+ *
  *       CALL FCVBPINIT(NEQ, MU, ML, IER)
- * The arguments are:
- * NEQ       = problem size
- * MU, ML    = upper and lower half-bandwidths of the band matrix that 
- *             is retained as an approximation of the Jacobian.
- * IER       = return completion flag: IER=0: success, IER<0: and error occurred
- *
- * (3.4A) To specify the SPGMR linear solver with the CVBANDPRE preconditioner,
- * make the following call
- *       CALL FCVSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)
- * The arguments are:
- * IPRETYPE  = preconditioner type: 
- *            0 = none
- *            1 = left only
- *            2 = right only
- *            3 = both sides.
- * IGSTYPE   = Gram-schmidt process type: 0 = modified G-S, 1 = classical G-S.
- * MAXL      = maximum Krylov subspace dimension; 0 indicates default.
- * DELT      = linear convergence tolerance factor; 0.0 indicates default.
- * IER       = return completion flag: IER=0: success, IER<0: ans error occurred
- *
- * (3.4B) To specify the SPBCG linear solver with the CVBANDPRE preconditioner,
- * make the following call
- *       CALL FCVSPBCG(IPRETYPE, MAXL, DELT, IER)
- * The arguments are:
- * IPRETYPE  = preconditioner type: 
- *            0 = none
- *            1 = left only
- *            2 = right only
- *            3 = both sides.
- * MAXL      = maximum Krylov subspace dimension; 0 indicates default.
- * DELT      = linear convergence tolerance factor; 0.0 indicates default.
- * IER       = return completion flag: IER=0: success, IER<0: ans error occurred
- *
- * (3.4C) To specify the SPTFQMR linear solver with the CVBANDPRE preconditioner,
- * make the following call
- *       CALL FCVSPTFQMR(IPRETYPE, MAXL, DELT, IER)
- * The arguments are:
- * IPRETYPE  = preconditioner type: 
- *            0 = none
- *            1 = left only
- *            2 = right only
- *            3 = both sides.
- * MAXL      = maximum Krylov subspace dimension; 0 indicates default.
- * DELT      = linear convergence tolerance factor; 0.0 indicates default.
- * IER       = return completion flag: IER=0: success, IER<0: ans error occurred
- *
- * (3.5) To specify whether the Krylov linear solver (GMRES, Bi-CGSTAB, or TFQMR) 
- * should use the supplied FCVJTIMES or the internal finite difference approximation, 
- * make the call
+ *
+ *   The arguments are:
+ *        NEQ = problem size [long int, input]
+ *        MU = upper half-bandwidth of the band matrix that is retained as 
+ *             an approximation of the Jacobian [long int, input]
+ *        ML = lower half-bandwidth of the band matrix approximant
+ *             to the Jacobian [long int, input]
+ *        IER = return completion flag [int, output]:
+ *                    0 = success
+ *                   <0 = an error occurred
+ *
+ *
+ * (3.5) To specify whether the Krylov linear solver should use the 
+ *   supplied FCVJTIMES or the internal finite difference approximation, 
+ *   make the call
+ *
  *        CALL FCVSPILSSETJAC(FLAG, IER)
- * where FLAG=0 for finite differences approxaimtion or
- *       FLAG=1 to use the supplied routine FCVJTIMES
+ *
+ *   with the int FLAG=1 to specify that FCVJTSETUP and FCVJTIMES 
+ *   are provided (FLAG=0 specifies to use and internal finite 
+ *   difference approximation to this product).  The int return 
+ *   flag IER=0 if successful, and nonzero otherwise.
  *
  * (4) The integrator: FCVODE
- * Carrying out the integration is accomplished by making calls as follows:
+ *
+ *   Carrying out the integration is accomplished by making calls as follows:
+ *
  *       CALL FCVODE (TOUT, T, Y, ITASK, IER)
- * The arguments are:
- * TOUT  = next value of t at which a solution is desired (input)
- * T     = value of t reached by the solver on output
- * Y     = array containing the computed solution on output
- * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate);
- *         2 = one-step mode (return after each internal step taken);
- *         3 = normal mode with TSTOP; 4 = one-step mode with TSTOP.
- * IER   = completion flag: 0 = success, 1 = TSTOP return, 2 = root return,
- *         negative values are various failure modes (see CVODE User Guide).
- * The current values of the optional outputs are available in IOUT and ROUT.
+ *
+ *   The arguments are:
+ *      TOUT  = next value of t at which a solution is desired [realtype, input]
+ *      T     = value of t reached by the solver [realtype, output]
+ *      Y     = array containing the computed solution [realtype, output]
+ *      ITASK = task indicator [int, input]: 
+ *              1 = normal mode (overshoot TOUT and interpolate)
+ *              2 = one-step mode (return after each internal step taken)
+ *              3 = normal mode with TSTOP check
+ *              4 = one-step mode with TSTOP check
+ *      IER   = completion flag [int, output]: 
+ *              0 = success, 
+ *              1 = TSTOP return, 
+ *              2 = root return,
+ *              negative values are various failure modes (see CVODE User Guide).
+ *    The current values of the optional outputs are available in IOUT and ROUT.
  * 
  * (5) Optional outputs: FCVBPOPT
- * Optional outputs specific to the SP* solver are LRW, LIW, LFLG, NFELS, NJTV,
- * NPE, NPS, NLI, NCFL, stored in IOUT(13)...IOUT(21).
- * To obtain the optional outputs associated with the CVBANDPRE module, make
- * the following call:
+ *
+ *   Optional outputs specific to the CVSPILS solver interface are 
+ *        LENRWLS = IOUT(13) from CVSpilsGetWorkSpace
+ *        LENIWLS = IOUT(14) from CVSpilsGetWorkSpace
+ *        LSTF    = IOUT(15) from CVSpilsGetLastFlag
+ *        NFELS   = IOUT(16) from CVSpilsGetNumRhsEvals
+ *        NJTV    = IOUT(17) from CVSpilsGetNumJtimesEvals
+ *        NPE     = IOUT(18) from CVSpilsGetNumPrecEvals
+ *        NPS     = IOUT(19) from CVSpilsGetNumPrecSolves
+ *        NLI     = IOUT(20) from CVSpilsGetNumLinIters
+ *        NCFL    = IOUT(21) from CVSpilsGetNumConvFails
+ *   See the CVODE manual for descriptions.
+ *
+ *   To obtain the optional outputs associated with the CVBANDPRE module, make
+ *   the following call:
+ *
  *       CALL FCVBPOPT(LENRWBP, LENIWBP, NFEBP)
- * The arguments returned are:
- * LENRWBP = length of real preconditioner work space, in realtype words.
- *           This size is local to the current processor.
- * LENIWBP = length of integer preconditioner work space, in integer words.
- *           This size is local to the current processor.
- * NFEBP   = number of f(t,y) evaluations for CVBANDPRE
+ *
+ *   The arguments returned are:
+ *      LENRWBP = length of real preconditioner work space, in realtype words.
+ *                This size is local to the current processor.
+ *      LENIWBP = length of integer preconditioner work space, in integer words.
+ *                This size is local to the current processor.
+ *      NFEBP   = number of f(t,y) evaluations for CVBANDPRE
  * 
  * (6) Computing solution derivatives: FCVDKY
- * To obtain a derivative of the solution (optionally), of order up to
- * the current method order, make the following call:
+ *
+ *   To obtain a derivative of the solution (optionally), of order up to
+ *   the current method order, make the following call:
+ *
  *       CALL FCVDKY (T, K, DKY)
- * The arguments are:
- * T   = value of t at which solution derivative is desired
- * K   = derivative order (0 .le. K .le. QU)
- * DKY = array containing computed K-th derivative of y on return
+ *
+ *   The arguments are:
+ *       T = time at which solution derivative is desired, within 
+ *           the interval [TCUR-HU,TCUR], [realtype, input].
+ *       K = derivative order (0 .le. K .le. QU) [int, input]
+ *       DKY = array containing computed K-th derivative of y 
+ *           [realtype, output]
+ *       IER = return flag [int, output]: 
+ *                    0 = success
+ *                   <0 = illegal argument.
  * 
  * (7) Memory freeing: FCVFREE
- *   To the free the internal memory created by the calls to FNVINITS,
- * FCVMALLOC, and FCVBPINIT, make the following call:
+ *
+ *   To the free the internal memory created by the calls to FNVINIT*,
+ *   FCVMALLOC, FCVSPILSINIT and FCVBPINIT, make the following call:
+ *
  *       CALL FCVFREE
  * 
  * ==============================================================================
@@ -238,8 +367,10 @@ extern "C" {
 #endif
 
 /* Prototypes of exported function */
-void FCV_BPINIT(long int *N, long int *mu, long int *ml, int *ier);
-void FCV_BPOPT(long int *lenrwbp, long int *leniwbp, long int *nfebp);
+void FCV_BPINIT(long int *N, long int *mu,
+                long int *ml, int *ier);
+void FCV_BPOPT(long int *lenrwbp, long int *leniwbp,
+               long int *nfebp);
 
 #ifdef __cplusplus
 }
diff --git a/src/cvode/fcmix/fcvdense.c b/src/cvode/fcmix/fcvdense.c
index 70f8609..0ae03ba 100644
--- a/src/cvode/fcmix/fcvdense.c
+++ b/src/cvode/fcmix/fcvdense.c
@@ -1,21 +1,23 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Fortran/C interface routines for CVODE/CVDENSE, for the case
+ * Fortran/C interface routines for CVODE/CVDLS, for the case
  * of a user-supplied Jacobian approximation routine.
  * -----------------------------------------------------------------
  */
@@ -26,7 +28,8 @@
 #include "fcvode.h"     /* actual fn. names, prototypes and global vars.*/
 #include "cvode_impl.h" /* definition of CVodeMem type                  */
 
-#include <cvode/cvode_dense.h>
+#include <cvode/cvode_direct.h>
+#include <sunmatrix/sunmatrix_dense.h>
 
 /***************************************************************************/
 
@@ -35,13 +38,10 @@
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
-  extern void FCV_DJAC(long int*,                        /* N          */
-                       realtype*, realtype*, realtype*,  /* T, Y, FY   */
-                       realtype*,                        /* DJAC       */
-                       realtype*,                        /* H          */ 
-                       long int*, realtype*,             /* IPAR, RPAR */
-                       realtype*, realtype*, realtype*,  /* V1, V2, V3 */
-                       int *ier);                        /* IER        */
+  extern void FCV_DJAC(long int *N, realtype *T, realtype *Y,
+                       realtype *FY, realtype *DJAC, realtype *H,
+                       long int *IPAR, realtype *RPAR, realtype *V1, 
+                       realtype *V2, realtype *V3, int *ier);
 #ifdef __cplusplus
 }
 #endif
@@ -51,9 +51,9 @@ extern "C" {
 void FCV_DENSESETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = CVDlsSetDenseJacFn(CV_cvodemem, NULL);
+    *ier = CVDlsSetJacFn(CV_cvodemem, NULL);
   } else {
-    *ier = CVDlsSetDenseJacFn(CV_cvodemem, FCVDenseJac);
+    *ier = CVDlsSetJacFn(CV_cvodemem, FCVDenseJac);
   }
 }
 
@@ -61,18 +61,17 @@ void FCV_DENSESETJAC(int *flag, int *ier)
 
 /* C function CVDenseJac interfaces between CVODE and a Fortran subroutine
    FCVDJAC for solution of a linear system with dense Jacobian approximation.
-   Addresses of arguments are passed to FCVDJAC, using the macro 
-   DENSE_COL from DENSE and the routine N_VGetArrayPointer from NVECTOR.
-   Auxiliary data is assumed to be communicated by Common. */
-
-int FCVDenseJac(long int N, realtype t, 
-                N_Vector y, N_Vector fy, 
-                DlsMat J, void *user_data,
-                N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+   Addresses of arguments are passed to FCVDJAC, using accessor functions 
+   from the SUNDenseMatrix and N_Vector modules. */
+
+int FCVDenseJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
+                void *user_data, N_Vector vtemp1, N_Vector vtemp2,
+                N_Vector vtemp3)
 {
   int ier;
   realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
   realtype h;
+  long int N;
   FCVUserData CV_userdata;
 
   CVodeGetLastStep(CV_cvodemem, &h);
@@ -83,13 +82,14 @@ int FCVDenseJac(long int N, realtype t,
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
 
-  jacdata = DENSE_COL(J,0);
+  N = SUNDenseMatrix_Columns(J);
+  jacdata = SUNDenseMatrix_Column(J,0);
 
   CV_userdata = (FCVUserData) user_data;
 
   FCV_DJAC(&N, &t, ydata, fydata, jacdata, &h, 
-           CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier); 
-
+           CV_userdata->ipar, CV_userdata->rpar, v1data,
+           v2data, v3data, &ier); 
   return(ier);
 }
 
diff --git a/src/cvode/fcmix/fcvewt.c b/src/cvode/fcmix/fcvewt.c
index e18ed81..5c3b127 100644
--- a/src/cvode/fcmix/fcvewt.c
+++ b/src/cvode/fcmix/fcvewt.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
  * ----------------------------------------------------------------- 
  * Programmer: Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -33,9 +30,9 @@
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
-  extern void FCV_EWT(realtype*, realtype*,  /* Y, EWT */ 
-                      long int*, realtype*,  /* IPAR, RPAR */
-                      int*);                 /* IER */
+  extern void FCV_EWT(realtype *Y, realtype *EWT,
+                      long int *IPAR, realtype *RPAR,
+                      int *IER);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/cvode/fcmix/fcvjtimes.c b/src/cvode/fcmix/fcvjtimes.c
index 0ad26d8..24446c8 100644
--- a/src/cvode/fcmix/fcvjtimes.c
+++ b/src/cvode/fcmix/fcvjtimes.c
@@ -1,25 +1,27 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *    Alan C. Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * The C function FCVJtimes is to interface between the
- * CVSP* module and the user-supplied Jacobian-vector
- * product routine FCVJTIMES. Note the use of the generic name
- * FCV_JTIMES below.
+ * The C functions FCVJTSetup and FCVJtimes are to interface 
+ * between the CVSPILS module and the user-supplied 
+ * Jacobian-vector product routines FCVJTSETUP and FCVJTIMES. 
+ * Note the use of the generic names FCV_JTSETUP and FCV_JTIMES 
+ * in the code below.
  * -----------------------------------------------------------------
  */
 
@@ -39,12 +41,14 @@
 extern "C" {
 #endif
 
-  extern void FCV_JTIMES(realtype*, realtype*,            /* V, JV      */
-                         realtype*, realtype*, realtype*, /* T, Y, FY   */
-                         realtype*,                       /* H          */
-                         long int*, realtype*,            /* IPAR, RPAR */
-                         realtype*,                       /* WRK        */
-                         int*);                           /* IER        */
+  extern void FCV_JTSETUP(realtype *T, realtype *Y, realtype *FY, 
+                          realtype *H, long int *IPAR, 
+                          realtype *RPAR, int *IER);
+
+  extern void FCV_JTIMES(realtype *V, realtype *JV, realtype *T, 
+			  realtype *Y, realtype *FY, realtype *H,
+			  long int *IPAR, realtype *RPAR,
+			  realtype *WRK, int *IER);
 
 #ifdef __cplusplus
 }
@@ -55,20 +59,42 @@ extern "C" {
 void FCV_SPILSSETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = CVSpilsSetJacTimesVecFn(CV_cvodemem, NULL);
+    *ier = CVSpilsSetJacTimes(CV_cvodemem, NULL, NULL);
   } else {
-    *ier = CVSpilsSetJacTimesVecFn(CV_cvodemem, FCVJtimes);
+    *ier = CVSpilsSetJacTimes(CV_cvodemem, FCVJTSetup, FCVJtimes);
   }
 }
 
 /***************************************************************************/
 
+/* C function  FCVJTSetup to interface between CVODE and user-supplied
+   Fortran routine FCVJTSETUP for preparing a Jacobian * vector product.
+   Addresses of t, y, fy and h are passed to FCVJTSETUP,
+   using the routine N_VGetArrayPointer from NVECTOR.
+   A return flag ier from FCVJTSETUP is returned by FCVJTSetup. */
+
+int FCVJTSetup(realtype t, N_Vector y, N_Vector fy, void *user_data)
+{
+  realtype *ydata, *fydata;
+  realtype h;
+  FCVUserData CV_userdata;
+  int ier = 0;
+  
+  CVodeGetLastStep(CV_cvodemem, &h);
+  ydata  = N_VGetArrayPointer(y);
+  fydata = N_VGetArrayPointer(fy);
+  CV_userdata = (FCVUserData) user_data;
+ 
+  FCV_JTSETUP(&t, ydata, fydata, &h, CV_userdata->ipar, 
+	      CV_userdata->rpar, &ier);
+  return(ier);
+}
+
 /* C function  FCVJtimes to interface between CVODE and  user-supplied
    Fortran routine FCVJTIMES for Jacobian * vector product.
    Addresses of v, Jv, t, y, fy, h, and work are passed to FCVJTIMES,
    using the routine N_VGetArrayPointer from NVECTOR.
-   A return flag ier from FCVJTIMES is returned by FCVJtimes.
-   Auxiliary data is assumed to be communicated by common blocks. */
+   A return flag ier from FCVJTIMES is returned by FCVJtimes. */
 
 int FCVJtimes(N_Vector v, N_Vector Jv, realtype t, 
               N_Vector y, N_Vector fy,
diff --git a/src/cvode/fcmix/fcvklu.c b/src/cvode/fcmix/fcvklu.c
deleted file mode 100644
index ec6c77d..0000000
--- a/src/cvode/fcmix/fcvklu.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4654 $
- * $Date: 2016-02-17 20:12:58 -0800 (Wed, 17 Feb 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the Fortran interface to
- * the CVKLU solver. See fcvode.h for usage.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "fcvode.h"
-#include "cvode_impl.h"
-#include <cvode/cvode_klu.h>
- 
-/*
- * ----------------------------------------------------------------
- * Function : FCV_KLU
- * ----------------------------------------------------------------
- */
-
-void FCV_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier)
-{
-  *ier = CVKLU(CV_cvodemem, *neq, *nnz, *sparsetype);
-  CVKLUSetOrdering(CV_cvodemem, *ordering);
-  CV_ls = CV_LS_KLU;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FCV_KLUReinit
- * ----------------------------------------------------------------
- */
-
-void FCV_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier)
-{
-  *ier = CVKLUReInit(CV_cvodemem, *neq, *nnz, *reinit_type);
-}
-
diff --git a/src/cvode/fcmix/fcvlapack.c b/src/cvode/fcmix/fcvlapack.c
deleted file mode 100644
index af265d9..0000000
--- a/src/cvode/fcmix/fcvlapack.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for CVODE/CVLAPACK
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fcvode.h"     /* actual fn. names, prototypes and global vars.*/
-#include "cvode_impl.h" /* definition of CVodeMem type                  */
-
-#include <cvode/cvode_lapack.h>
-
-/***************************************************************************/
-
-void FCV_LAPACKDENSE(int *neq, int *ier)
-{
-  /* neq  is the problem size */
-
-  *ier = CVLapackDense(CV_cvodemem, *neq);
-
-  CV_ls = CV_LS_LAPACKDENSE;
-}
-
-/***************************************************************************/
-
-void FCV_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier)
-{
-  /* 
-     neq        is the problem size
-     mupper     is the upper bandwidth
-     mlower     is the lower bandwidth 
-  */
-
-  *ier = CVLapackBand(CV_cvodemem, *neq, *mupper, *mlower);
-
-  CV_ls = CV_LS_LAPACKBAND;
-}
-
-/***************************************************************************/
-
diff --git a/src/cvode/fcmix/fcvlapband.c b/src/cvode/fcmix/fcvlapband.c
deleted file mode 100644
index 476e94e..0000000
--- a/src/cvode/fcmix/fcvlapband.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for CVODE/CVLAPACK, for the case
- * of a user-supplied band Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fcvode.h"     /* actual fn. names, prototypes and global vars.*/
-#include "cvode_impl.h" /* definition of CVodeMem type                  */
-
-#include <cvode/cvode_lapack.h>
-
-/***************************************************************************/
-
-/* Prototype of the Fortran routines */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-  extern void FCV_BJAC(long int*, long int*, long int*, long int*,    /* N,MU,ML,EBAND */
-                       realtype*, realtype*, realtype*,  /* T, Y, FY         */
-                       realtype*,                        /* LBJAC            */
-                       realtype*,                        /* H                */
-                       long int*, realtype*,             /* IPAR, RPAR       */
-                       realtype*, realtype*, realtype*,  /* V1, V2, V3       */
-                       int*);                            /* IER              */
-
-#ifdef __cplusplus
-}
-#endif
-
-/***************************************************************************/
-
-void FCV_LAPACKBANDSETJAC(int *flag, int *ier)
-{
-  if (*flag == 0) {
-    *ier = CVDlsSetBandJacFn(CV_cvodemem, NULL);
-  } else {
-    *ier = CVDlsSetBandJacFn(CV_cvodemem, FCVLapackBandJac);
-  }
-}
-
-/***************************************************************************/
-
-/* The C function FCVLapackBandJac interfaces between CVODE and a 
- * Fortran subroutine FCVBJAC for the solution of a linear system using
- * Lapack with band Jacobian approximation.
- * Addresses of arguments are passed to FCVBJAC, using the macro 
- * BAND_COL and the routine N_VGetArrayPointer from NVECTOR.
- * The address passed for J is that of the element in column 0 with row 
- * index -mupper.  An extended bandwith equal to (J->smu) + mlower + 1 is
- * passed as the column dimension of the corresponding array.
- * Auxiliary data is assumed to be communicated by Common. 
- */
-
-int FCVLapackBandJac(long int N, long int mupper, long int mlower,
-                     realtype t, N_Vector y, N_Vector fy, 
-                     DlsMat J, void *user_data,
-                     N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  int ier;
-  realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
-  realtype h;
-  long int eband;
-  FCVUserData CV_userdata;
-
-  CVodeGetLastStep(CV_cvodemem, &h);
-
-  ydata   = N_VGetArrayPointer(y);
-  fydata  = N_VGetArrayPointer(fy);
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-
-  eband = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
-
-  CV_userdata = (FCVUserData) user_data;
-
-  FCV_BJAC(&N, &mupper, &mlower, &eband, &t, ydata, fydata, jacdata, &h,
-           CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier);
-
-  return(ier);
-}
diff --git a/src/cvode/fcmix/fcvlapdense.c b/src/cvode/fcmix/fcvlapdense.c
deleted file mode 100644
index 9c72630..0000000
--- a/src/cvode/fcmix/fcvlapdense.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for CVODE/CVLAPACK, for the case
- * of a user-supplied dense Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fcvode.h"     /* actual fn. names, prototypes and global vars.*/
-#include "cvode_impl.h" /* definition of CVodeMem type                  */
-
-#include <cvode/cvode_lapack.h>
-
-/***************************************************************************/
-
-/* Prototype of the Fortran routines */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-  extern void FCV_DJAC(long int*,                        /* N          */
-                       realtype*, realtype*, realtype*,  /* T, Y, FY   */
-                       realtype*,                        /* LDJAC      */
-                       realtype*,                        /* H          */ 
-                       long int*, realtype*,             /* IPAR, RPAR */
-                       realtype*, realtype*, realtype*,  /* V1, V2, V3 */
-                       int *ier);                        /* IER        */
-#ifdef __cplusplus
-}
-#endif
-
-/***************************************************************************/
-
-void FCV_LAPACKDENSESETJAC(int *flag, int *ier)
-{
-  if (*flag == 0) {
-    *ier = CVDlsSetDenseJacFn(CV_cvodemem, NULL);
-  } else {
-    *ier = CVDlsSetDenseJacFn(CV_cvodemem, FCVLapackDenseJac);
-  }
-}
-
-/***************************************************************************/
-
-/* The C function FCVLapackDenseJac interfaces between CVODE and a 
- * Fortran subroutine FCVDJAC for solution of a linear system using 
- * Lapack with dense Jacobian approximation.
- * Addresses of arguments are passed to FCVDJAC, using the macro 
- * DENSE_COL and the routine N_VGetArrayPointer from NVECTOR.
- * Auxiliary data is assumed to be communicated by Common. 
- */
-
-int FCVLapackDenseJac(long int N, realtype t,
-                      N_Vector y, N_Vector fy, 
-                      DlsMat J, void *user_data,
-                      N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  int ier;
-  realtype *ydata, *fydata, *jacdata, *v1data, *v2data, *v3data;
-  realtype h;
-  FCVUserData CV_userdata;
-
-  CVodeGetLastStep(CV_cvodemem, &h);
-
-  ydata   = N_VGetArrayPointer(y);
-  fydata  = N_VGetArrayPointer(fy);
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-
-  jacdata = DENSE_COL(J,0);
-
-  CV_userdata = (FCVUserData) user_data;
-
-  FCV_DJAC(&N, &t, ydata, fydata, jacdata, &h, 
-           CV_userdata->ipar, CV_userdata->rpar, v1data, v2data, v3data, &ier); 
-
-  return(ier);
-}
-
diff --git a/src/cvode/fcmix/fcvode.c b/src/cvode/fcmix/fcvode.c
index c8c2dca..9029c8a 100644
--- a/src/cvode/fcmix/fcvode.c
+++ b/src/cvode/fcmix/fcvode.c
@@ -1,26 +1,27 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4474 $
- * $Date: 2015-04-03 10:14:53 -0700 (Fri, 03 Apr 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *     Alan C. Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the implementation file for the Fortran interface to
  * the CVODE package.  See fcvode.h for usage.
  * NOTE: some routines are necessarily stored elsewhere to avoid
- * linking problems.  Therefore, see also fcvpreco.c, fcvpsol.c,
- * and fcvjtimes.c for all the options available.
+ * linking problems.  Therefore, see the othe C files in this folder
+ * for all the options available.
  * -----------------------------------------------------------------
  */
 
@@ -30,15 +31,11 @@
 
 #include "fcvode.h"                    /* actual function names, prototypes, global vars.*/ 
 #include "cvode_impl.h"                /* definition of CVodeMem type                    */
+#include <sundials/sundials_matrix.h>
+#include <cvode/cvode_direct.h>
+#include <cvode/cvode_spils.h>
+#include <cvode/cvode_diag.h>
 
-#include <cvode/cvode_band.h>          /* prototypes for CVBAND interface routines       */
-#include <cvode/cvode_dense.h>         /* prototypes for CVDENSE interface routines      */
-#include <cvode/cvode_diag.h>          /* prototypes for CVDIAG interface routines       */
-#include <cvode/cvode_klu.h>           /* prototypes for CVKLU interface routines        */
-#include <cvode/cvode_superlumt.h>     /* prototypes for CVSUPERLUMT interface routines  */
-#include <cvode/cvode_spgmr.h>         /* prototypes for CVSPGMR interface routines      */
-#include <cvode/cvode_spbcgs.h>        /* prototypes for CVSPBCG interface routines      */
-#include <cvode/cvode_sptfqmr.h>       /* prototypes for CVSPTFQMR interface routines    */
 
 /***************************************************************************/
 
@@ -91,7 +88,7 @@ void FCV_MALLOC(realtype *t0, realtype *y0,
   if(F2C_CVODE_vec->ops->nvgetarraypointer == NULL ||
      F2C_CVODE_vec->ops->nvsetarraypointer == NULL) {
     *ier = -1;
-    printf("A required vector operation is not implemented.\n\n");
+    fprintf(stderr, "A required vector operation is not implemented.\n\n");
     return;
   }
 
@@ -99,6 +96,10 @@ void FCV_MALLOC(realtype *t0, realtype *y0,
   CV_cvodemem = NULL;
   Vatol = NULL;
 
+  /* initialize global constants to disable each option */
+  CV_nrtfn = 0;
+  CV_ls = -1;
+  
   /* Create CVODE object */
   lmm = (*meth == 1) ? CV_ADAMS : CV_BDF;
   iter = (*itmeth == 1) ? CV_FUNCTIONAL : CV_NEWTON;
@@ -239,7 +240,7 @@ void FCV_SETIIN(char key_name[], long int *ival, int *ier)
   if (!strncmp(key_name,"MAX_ORD",7))
     *ier = CVodeSetMaxOrd(CV_cvodemem, (int) *ival);
   else if (!strncmp(key_name,"MAX_NSTEPS",10))
-    *ier = CVodeSetMaxNumSteps(CV_cvodemem, (int) *ival);
+    *ier = CVodeSetMaxNumSteps(CV_cvodemem, (long int) *ival);
   else if (!strncmp(key_name,"MAX_ERRFAIL",11))
     *ier = CVodeSetMaxErrTestFails(CV_cvodemem, (int) *ival);
   else if (!strncmp(key_name,"MAX_NITERS",10))
@@ -249,10 +250,10 @@ void FCV_SETIIN(char key_name[], long int *ival, int *ier)
   else if (!strncmp(key_name,"HNIL_WARNS",10))
     *ier = CVodeSetMaxHnilWarns(CV_cvodemem, (int) *ival);
   else if (!strncmp(key_name,"STAB_LIM",8))
-    *ier = CVodeSetStabLimDet(CV_cvodemem, (int) *ival);
+    *ier = CVodeSetStabLimDet(CV_cvodemem, (booleantype) *ival);
   else {
     *ier = -99;
-    printf("FCVSETIIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FCVSETIIN: Unrecognized key.\n\n");
   }
 
 }
@@ -273,171 +274,48 @@ void FCV_SETRIN(char key_name[], realtype *rval, int *ier)
     *ier = CVodeSetNonlinConvCoef(CV_cvodemem, *rval);
   else {
     *ier = -99;
-    printf("FCVSETRIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FCVSETRIN: Unrecognized key.\n\n");
   }
 
 }
 
 /***************************************************************************/
 
-void FCV_DENSE(long int *neq, int *ier)
-{
-  /* neq  is the problem size */
-
-  *ier = CVDense(CV_cvodemem, *neq);
-
-  CV_ls = CV_LS_DENSE;
+void FCV_DLSINIT(int *ier) {
+  if ( (CV_cvodemem == NULL) || (F2C_CVODE_linsol == NULL) || 
+       (F2C_CVODE_matrix == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = CVDlsSetLinearSolver(CV_cvodemem, F2C_CVODE_linsol, 
+                              F2C_CVODE_matrix);
+  CV_ls = CV_LS_DIRECT;
+  return;
 }
 
 /***************************************************************************/
 
-void FCV_BAND(long int *neq, long int *mupper, long int *mlower, int *ier)
-{
-  /* 
-     neq        is the problem size
-     mupper     is the upper bandwidth
-     mlower     is the lower bandwidth 
-  */
-
-  *ier = CVBand(CV_cvodemem, *neq, *mupper, *mlower);
-
-  CV_ls = CV_LS_BAND;
+void FCV_SPILSINIT(int *ier) {
+  if ( (CV_cvodemem == NULL) || (F2C_CVODE_linsol == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = CVSpilsSetLinearSolver(CV_cvodemem, F2C_CVODE_linsol);
+  CV_ls = CV_LS_ITERATIVE;
+  return;
 }
 
 /***************************************************************************/
 
 void FCV_DIAG(int *ier)
 {
+  if (CV_cvodemem == NULL) {
+    *ier = -1;
+    return;
+  }
   *ier = CVDiag(CV_cvodemem);
-
   CV_ls = CV_LS_DIAG;
-}
-
-/***************************************************************************/
-
-void FCV_SPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier)
-{
-  /* 
-     pretype    the preconditioner type
-     maxl       the maximum Krylov dimension
-     gstype     the Gram-Schmidt process type
-     delt       the linear convergence tolerance factor 
-  */
-
-  *ier = CVSpgmr(CV_cvodemem, *pretype, *maxl);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetGSType(CV_cvodemem, *gstype);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  CV_ls = CV_LS_SPGMR;
-}
-
-/***************************************************************************/
-
-void FCV_SPBCG(int *pretype, int *maxl, realtype *delt, int *ier)
-{
-  /* 
-     pretype    the preconditioner type
-     maxl       the maximum Krylov dimension
-     delt       the linear convergence tolerance factor 
-  */
-
-  *ier = CVSpbcg(CV_cvodemem, *pretype, *maxl);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  CV_ls = CV_LS_SPBCG;
-}
-
-/***************************************************************************/
-
-void FCV_SPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier)
-{
-  /* 
-     pretype    the preconditioner type
-     maxl       the maximum Krylov dimension
-     delt       the linear convergence tolerance factor 
-  */
-
-  *ier = CVSptfqmr(CV_cvodemem, *pretype, *maxl);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  CV_ls = CV_LS_SPTFQMR;
-}
-
-/***************************************************************************/
-
-void FCV_SPGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier)
-{
-  /* 
-     pretype    the preconditioner type
-     gstype     the Gram-Schmidt process type
-     delt       the linear convergence tolerance factor 
-  */
-
-  *ier = CVSpilsSetPrecType(CV_cvodemem, *pretype);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetGSType(CV_cvodemem, *gstype);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  CV_ls = CV_LS_SPGMR;
-}
-
-/***************************************************************************/
-
-void FCV_SPBCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier)
-{
-  /* 
-     pretype    the preconditioner type
-     maxl       the maximum Krylov subspace dimension
-     delt       the linear convergence tolerance factor 
-  */
-
-  *ier = CVSpilsSetPrecType(CV_cvodemem, *pretype);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetMaxl(CV_cvodemem, *maxl);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  CV_ls = CV_LS_SPBCG;
-}
-
-/***************************************************************************/
-
-void FCV_SPTFQMRREINIT(int *pretype, int *maxl, realtype *delt, int *ier)
-{
-  /* 
-     pretype    the preconditioner type
-     maxl       the maximum Krylov subspace dimension
-     delt       the linear convergence tolerance factor 
-  */
-
-  *ier = CVSpilsSetPrecType(CV_cvodemem, *pretype);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetMaxl(CV_cvodemem, *maxl);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  *ier = CVSpilsSetEpsLin(CV_cvodemem, *delt);
-  if (*ier != CVSPILS_SUCCESS) return;
-
-  CV_ls = CV_LS_SPTFQMR;
+  return;
 }
 
 /***************************************************************************/
@@ -489,28 +367,13 @@ void FCV_CVODE(realtype *tout, realtype *t, realtype *y, int *itask, int *ier)
     CVodeGetNumGEvals(CV_cvodemem, &CV_iout[11]);         /* NGE     */
   
   switch(CV_ls) {
-  case CV_LS_DENSE:
-  case CV_LS_BAND:
-  case CV_LS_LAPACKDENSE:
-  case CV_LS_LAPACKBAND:
+  case CV_LS_DIRECT:
     CVDlsGetWorkSpace(CV_cvodemem, &CV_iout[12], &CV_iout[13]);   /* LENRWLS,LENIWLS */
     CVDlsGetLastFlag(CV_cvodemem, &CV_iout[14]);                  /* LSTF */
     CVDlsGetNumRhsEvals(CV_cvodemem, &CV_iout[15]);               /* NFELS */
     CVDlsGetNumJacEvals(CV_cvodemem, &CV_iout[16]);               /* NJE */
     break;
-  case CV_LS_DIAG:
-    CVDiagGetWorkSpace(CV_cvodemem, &CV_iout[12], &CV_iout[13]);  /* LENRWLS,LENIWLS */
-    CVDiagGetLastFlag(CV_cvodemem, &CV_iout[14]);                 /* LSTF */
-    CVDiagGetNumRhsEvals(CV_cvodemem, &CV_iout[15]);              /* NFELS */
-    break;
-  case CV_LS_KLU:
-  case CV_LS_SUPERLUMT:
-    CVSlsGetLastFlag(CV_cvodemem, &CV_iout[14]);                  /* LSTF  */
-    CVSlsGetNumJacEvals(CV_cvodemem, &CV_iout[16]);               /* NJE   */
-    break;
-  case CV_LS_SPGMR:
-  case CV_LS_SPBCG:
-  case CV_LS_SPTFQMR:
+  case CV_LS_ITERATIVE:
     CVSpilsGetWorkSpace(CV_cvodemem, &CV_iout[12], &CV_iout[13]); /* LENRWLS,LENIWLS */
     CVSpilsGetLastFlag(CV_cvodemem, &CV_iout[14]);                /* LSTF */
     CVSpilsGetNumRhsEvals(CV_cvodemem, &CV_iout[15]);             /* NFELS */
@@ -519,6 +382,11 @@ void FCV_CVODE(realtype *tout, realtype *t, realtype *y, int *itask, int *ier)
     CVSpilsGetNumPrecSolves(CV_cvodemem, &CV_iout[18]);           /* NPS */
     CVSpilsGetNumLinIters(CV_cvodemem, &CV_iout[19]);             /* NLI */
     CVSpilsGetNumConvFails(CV_cvodemem, &CV_iout[20]);            /* NCFL */
+    break;
+  case CV_LS_DIAG:
+    CVDiagGetWorkSpace(CV_cvodemem, &CV_iout[12], &CV_iout[13]);  /* LENRWLS,LENIWLS */
+    CVDiagGetLastFlag(CV_cvodemem, &CV_iout[14]);                 /* LSTF */
+    CVDiagGetNumRhsEvals(CV_cvodemem, &CV_iout[15]);              /* NFELS */
   }
 }
 
@@ -584,12 +452,20 @@ void FCV_FREE ()
 
   cv_mem = (CVodeMem) CV_cvodemem;
 
+  if (cv_mem->cv_lfree)
+    cv_mem->cv_lfree(cv_mem);
+  cv_mem->cv_lmem = NULL;
+  
   free(cv_mem->cv_user_data); cv_mem->cv_user_data = NULL;
 
   CVodeFree(&CV_cvodemem);
 
   N_VSetArrayPointer(NULL, F2C_CVODE_vec);
   N_VDestroy(F2C_CVODE_vec);
+  if (F2C_CVODE_matrix)
+    SUNMatDestroy(F2C_CVODE_matrix);
+  if (F2C_CVODE_linsol)
+    SUNLinSolFree(F2C_CVODE_linsol);
 }
 
 /***************************************************************************/
diff --git a/src/cvode/fcmix/fcvode.h b/src/cvode/fcmix/fcvode.h
index 8552987..1cd9a4b 100644
--- a/src/cvode/fcmix/fcvode.h
+++ b/src/cvode/fcmix/fcvode.h
@@ -1,21 +1,21 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4795 $
- * $Date: 2016-07-01 15:10:25 -0700 (Fri, 01 Jul 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
- *                Ting Yan and Daniel R. Reynolds @ SMU
+ * Programmer(s): Daniel R. Reynolds and Ting Yan @ SMU
+ *    Alan C. Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This is the header file for FCVODE, the Fortran interface to
  * the CVODE package.                                            
@@ -35,69 +35,77 @@
  * This package provides the necessary interface to CVODE for both the
  * serial and the parallel NVECTOR implementations.
  * 
- * The user-callable functions, with the corresponding CVODE functions,
- * are as follows:
- * 
- *   FNVINITS and FNVINITP interface to N_VNew_Serial and
- *               N_VNew_Parallel, respectively
- *   FNVINITOMP               N_VNew_OpenMP
- *   FNVINITPTS               N_VNew_Pthreads
- * 
- *   FCVMALLOC  interfaces to CVodeCreate, CVodeSetUserData, and CVodeInit
- * 
- *   FCVREINIT  interfaces to CVReInit
+ * A summary of the user-callable functions, with the corresponding 
+ * CVODE functions, are as follows:
  * 
- *   FCVSETIIN and FCVSETRIN interface to CVodeSet*
+ *   Fortran                    CVODE
+ *   ---------------------      --------------------------------
+ *   FNVINITS                   N_VNew_Serial
+ *   FNVINITP                   N_VNew_Parallel
+ *   FNVINITOMP                 N_VNew_OpenMP
+ *   FNVINITPTS                 N_VNew_Pthreads
  *
- *   FCVEWTSET  interfaces to CVodeWFtolerances
- * 
- *   FCVDIAG    interfaces to CVDiag
- * 
- *   FCVDENSE   interfaces to CVDense
- *   FCVDENSESETJAC   interfaces to CVDenseSetJacFn
- * 
- *   FCVBAND    interfaces to CVBand
- *   FCVBANDSETJAC    interfaces to CVBandSetJacFn
+ *   FSUNBANDMATINIT            SUNBandMatrix
+ *   FSUNDENSEMATINIT           SUNDenseMatrix
+ *   FSUNSPARSEMATINIT          SUNSparseMatrix
  *
- *   FCVLAPACKDENSE   interfaces to CVLapackDense
- *   FCVLAPACKBAND    interfaces to CVLapackBand
- *   FCVLAPACKDENSESETJAC  interfaces to CVLapackSetJacFn
- *   FCVLAPACKBANDSETJAC   interfaces to CVLapackSetJacFn
+ *   FSUNBANDLINSOLINIT         SUNBandLinearSolver
+ *   FSUNDENSELINSOLINIT        SUNDenseLinearSolver
+ *   FSUNKLUINIT                SUNKLU
+ *   FSUNKLUREINIT              SUNKLUReinit
+ *   FSUNLAPACKBANDINIT         SUNLapackBand
+ *   FSUNLAPACKDENSEINIT        SUNLapackDense
+ *   FSUNPCGINIT                SUNPCG
+ *   FSUNSPBCGSINIT             SUNSPBCGS
+ *   FSUNSPFGMRINIT             SUNSPFGMR
+ *   FSUNSPGMRINIT              SUNSPGMR
+ *   FSUNSPTFQMRINIT            SUNSPTFQMR
+ *   FSUNSUPERLUMTINIT          SUNSuperLUMT
  *
- *   FCVKLU             interfaces to CVKLU
- *   FCVKLUReinit       interfaces to CVKLUReinit
- *   FCVSUPERLUMT       interfaces to CVSuperLUMT
- *   FCVSPARSESETJAC    interfaces to CVSlsSetSparseJacFn
+ *   FCVMALLOC                  CVodeCreate, CVodeSetUserData,
+ *                                 and CVodeInit
+ *   FCVREINIT                  CVReInit
+ *   FCVSETIIN                  CVodeSet* (integer arguments)
+ *   FCVSETRIN                  CVodeSet* (real arguments)
+ *   FCVEWTSET                  CVodeWFtolerances
  *
- *   FCVSPGMR and FCVSPGMRREINIT interface to CVSpgmr and CVSpilsSet*
- *   FCVSPBCG, FCVSPBCGREINIT interface to CVSpbcg and CVSpilsSet*
- *   FCVSPTFQMR, FCVSPTFQMRREINIT interface to CVSptfqmr and CVSpilsSet*
+ *   FCVDLSINIT                 CVDlsSetLinearSolver
+ *   FCVDENSESETJAC             CVDlsSetJacFn
+ *   FCVBANDSETJAC              CVDlsSetJacFn
+ *   FCVSPARSESETJAC            CVDlsSetJacFn
  *
- *   FCVSPILSSETJAC   interfaces to CVSpilsSetJacTimesVecFn
- *   FCVSPILSSETPREC  interfaces to CVSpilsSetPreconditioner
- * 
- *   FCVODE     interfaces to CVode, CVodeGet*, and CV*Get*
- * 
- *   FCVDKY     interfaces to CVodeGetDky
- * 
- *   FCVGETERRWEIGHTS  interfaces to CVodeGetErrWeights
+ *   FCVDIAG                    CVDiag
+ *
+ *   FCVSPILSINIT               CVSpilsSetLinearSolver
+ *   FCVSPILSSETEPSLIN          CVSpilsSetEpsLin
+ *   FCVSPILSSETJAC             CVSpilsSetJacTimes
+ *   FCVSPILSSETPREC            CVSpilsSetPreconditioner
  *
- *   FCVGETESTLOCALERR  interfaces to CVodeGetEstLocalErrors
+ *   FCVODE                     CVode, CVodeGet*, and CV*Get*
+ *   FCVDKY                     CVodeGetDky
+ * 
+ *   FCVGETERRWEIGHTS           CVodeGetErrWeights
+ *   FCVGETESTLOCALERR          CVodeGetEstLocalErrors
  *
- *   FCVFREE    interfaces to CVodeFree
+ *   FCVFREE                    CVodeFree
+ *   ---------------------      --------------------------------
  * 
  * The user-supplied functions, each listed with the corresponding interface
  * function which calls it (and its type within CVODE), are as follows:
- *   FCVFUN    is called by the interface function FCVf of type CVRhsFn
- *   FCVDJAC   is called by the interface fn. FCVDenseJac of type CVDenseJacFn
- *   FCVBJAC   is called by the interface fn. FCVBandJac of type CVBandJacFn
- *   FCVLDJAC  is called by the interface fn. FCVLapackDenseJac of type CVLapackJacFn
- *   FCVLBJAC  is called by the interface fn. FCVLapackBandJac of type CVLapackJacFn
- *   FCVPSOL   is called by the interface fn. FCVPSol of type CVSpilsPrecSolveFn
- *   FCVPSET   is called by the interface fn. FCVPSet of type CVSpilsPrecSetupFn
- *   FCVJTIMES is called by interface fn. FCVJtimes of type CVSpilsJacTimesVecFn
- *   FCVSPJAC  is called by interface fn. FCVSparseJac of type CVSlsSparseJacFn
- *   FCVEWT    is called by interface fn. FCVEwtSet of type CVEwtFn
+ *
+ *   Fortran:           Interface Fcn:           CVODE Type:
+ *   -------------      ------------------       -----------------------
+ *   FCVFUN             FCVf                     CVRhsFn
+ *   FCVDJAC            FCVDenseJac              CVDlsJacFn
+ *   FCVBJAC            FCVBandJac               CVDlsJacFn
+ *   FCVSPJAC           FCVSparseJac             CVDlsJacFn
+ *   FCVPSET            FCVPSet                  CVSpilsPrecSetupFn
+ *   FCVPSOL            FCVPSol                  CVSpilsPrecSolveFn
+ *   FCVJTSETUP         FCVJTSetup               CVSpilsJacTimesSetupFn
+ *   FCVJTIMES          FCVJtimes                CVSpilsJacTimesVecFn
+ *   FCVEWT             FCVEwtSet                CVEwtFn
+ *   -------------      ------------------       -----------------------
+ *
  * In contrast to the case of direct use of CVODE, and of most Fortran ODE
  * solvers, the names of all user-supplied routines here are fixed, in
  * order to maximize portability for the resulting mixed-language program.
@@ -112,7 +120,7 @@
  * 
  *                  Usage of the FCVODE Interface Package
  * 
- * The usage of FCVODE requires calls to five or more interface
+ * The usage of FCVODE requires calls to a variety of interface
  * functions, depending on the method options selected, and one or more
  * user-supplied routines which define the problem to be solved.  These
  * function calls and user routines are summarized separately below.
@@ -124,66 +132,146 @@
  * the documentation on the corresponding function in the CVODE package.
  * 
  * The number labels on the instructions below end with s for instructions
- * that apply to the serial version of CVODE only, and end with p for
- * those that apply to the parallel version only.
+ * that are specific to use with the serial/OpenMP/PThreads package; similarly 
+ * those that end with p are specific to use with the N_VParallel package.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ *                               Data Types
+ *
+ * Throughout this documentation, we will refer to data types according to 
+ * their usage in SUNDIALS.  The equivalent types to these may vary, 
+ * depending on your computer architecture and on how SUNDIALS was compiled.  
+ * A Fortran user should take care that all arguments passed through this 
+ * Fortran/C interface are declared of the appropriate type.
+ * 
+ * Integers: SUNDIALS uses 'int', 'long int' and 'sunindextype' types.  At 
+ * compilation, SUNDIALS allows the configuration of the 'index' type, that 
+ * accepts values of 32-bit signed and 64-bit signed.  This choice dictates 
+ * the size of a SUNDIALS 'sunindextype' variable.
+ *   int      -- equivalent to an INTEGER or INTEGER*4 in Fortran
+ *   long int -- equivalent to an INTEGER*8 in Fortran (Linux/UNIX/OSX), or 
+ *               equivalent to an INTEGER in Windows
+ *   sunindextype -- this will depend on the SUNDIALS configuration:
+ *               32-bit -- equivalent to an INTEGER or INTEGER*4 in Fortran
+ *               64-bit -- equivalent to an INTEGER*8 in Fortran
+ *	      
+ * Real numbers:  At compilation, SUNDIALS allows the configuration option 
+ * '--with-precision', that accepts values of 'single', 'double' or 
+ * 'extended' (the default is 'double').  This choice dictates the size of a 
+ * SUNDIALS 'realtype' variable.  The corresponding Fortran types for these 
+ * 'realtype' sizes are:
+ *   single   -- equivalent to a REAL or REAL*4 in Fortran
+ *   double   -- equivalent to a DOUBLE PRECISION or REAL*8 in Fortran
+ *   extended -- equivalent to a REAL*16 in Fortran
  *
  * -----------------------------------------------------------------------------
  *
  * (1) User-supplied right-hand side routine: FCVFUN
- * The user must in all cases supply the following Fortran routine
+ *
+ *   The user must in all cases supply the following Fortran routine
+ *
  *       SUBROUTINE FCVFUN (T, Y, YDOT, IPAR, RPAR, IER)
- *       DIMENSION Y(*), YDOT(*), IPAR(*), RPAR(*)
- * It must set the YDOT array to f(t,y), the right-hand side of the ODE 
- * system, as function of T = t and the array Y = y.  Here Y and YDOT
- * are distributed vectors. IPAR and RPAR are arrays of integer and real user 
- * data, respectively as passed to FCVMALLOC.
- * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred,
- * and IER < 0 if an unrecoverable error ocurred.
+ *
+ *   It must set the YDOT array to f(t,y), the right-hand side of the ODE 
+ *   system, as function of T = t and the array Y = y.
+ *
+ *   The arguments are:
+ *       Y    -- array containing state variables [realtype, input]
+ *       YDOT -- array containing state derivatives [realtype, output]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                 >0 if a recoverable error occurred,
+ *                 <0 if an unrecoverable error ocurred.
  * 
  * (2s) Optional user-supplied dense Jacobian approximation routine: FCVDJAC
- * As an option when using the DENSE linear solver, the user may supply a
- * routine that computes a dense approximation of the system Jacobian 
- * J = df/dy. If supplied, it must have the following form:
- *       SUBROUTINE FCVDJAC (NEQ, T, Y, FY, DJAC, H, IPAR, RPAR, WK1, WK2, WK3, IER)
- *       DIMENSION Y(*), FY(*), DJAC(NEQ,*), IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*)
- * Typically this routine will use only NEQ, T, Y, and DJAC. It must compute
- * the Jacobian and store it columnwise in DJAC.
- * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC.
- * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred,
- * and IER < 0 if an unrecoverable error ocurred.
+ *
+ *   As an option when using the DENSE or LAPACKDENSE linear solvers, the user may
+ *   supply a routine that computes a dense approximation of the system Jacobian 
+ *   J = df/dy. If supplied, it must have the following form:
+ *
+ *       SUBROUTINE FCVDJAC(NEQ, T, Y, FY, DJAC, H, IPAR, RPAR, WK1, WK2, WK3, IER)
+ *
+ *   Typically this routine will use only NEQ, T, Y, and DJAC. It must compute
+ *   the Jacobian and store it columnwise in DJAC.
+ *
+ *   The arguments are:
+ *       NEQ  -- number of rows in the matrix [long int, input]
+ *       T    -- current time [realtype, input]
+ *       Y    -- array containing state variables [realtype, input]
+ *       FY   -- array containing state derivatives [realtype, input]
+ *       DJAC -- 2D array containing the jacobian entries [realtype of size
+ *               (NEQ,NEQ), output]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       WK*  -- array containing temporary workspace of same size as Y 
+ *               [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                 >0 if a recoverable error occurred,
+ *                 <0 if an unrecoverable error ocurred.
  * 
- * (3s) Optional user-supplied band Jacobian approximation routine: FCVBJAC
- * As an option when using the BAND linear solver, the user may supply a
- * routine that computes a band approximation of the system Jacobian 
- * J = df/dy. If supplied, it must have the following form:
- *       SUBROUTINE FCVBJAC (NEQ, MU, ML, MDIM, T, Y, FY, BJAC, H,
- *      1                    IPAR, RPAR, WK1, WK2, WK3, IER)
- *       DIMENSION Y(*), FY(*), BJAC(MDIM,*), IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*)
- * Typically this routine will use only NEQ, MU, ML, T, Y, and BJAC. 
- * It must load the MDIM by N array BJAC with the Jacobian matrix at the
- * current (t,y) in band form.  Store in BJAC(k,j) the Jacobian element J(i,j)
- * with k = i - j + MU + 1 (k = 1 ... ML+MU+1) and j = 1 ... N.
- * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC.
- * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred,
- * and IER < 0 if an unrecoverable error ocurred.
+ * (2s) Optional user-supplied band Jacobian approximation routine: FCVBJAC
+ *
+ *   As an option when using the BAND or LAPACKBAND linear solvers, the user 
+ *   may supply a routine that computes a band approximation of the system 
+ *   Jacobian J = df/dy. If supplied, it must have the following form:
+ *
+ *       SUBROUTINE FCVBJAC(NEQ, MU, ML, MDIM, T, Y, FY, BJAC, H,
+ *      1                   IPAR, RPAR, WK1, WK2, WK3, IER)
+ *
+ *   Typically this routine will use only NEQ, MU, ML, T, Y, and BJAC. 
+ *   It must load the MDIM by N array BJAC with the Jacobian matrix at the
+ *   current (t,y) in band form.  Store in BJAC(k,j) the Jacobian element J(i,j)
+ *   with k = i - j + MU + 1 (k = 1 ... ML+MU+1) and j = 1 ... N.
+ *
+ *   The arguments are:
+ *       NEQ  -- number of rows in the matrix [long int, input]
+ *       MU   -- upper half-bandwidth of the matrix [long int, input]
+ *       ML   -- lower half-bandwidth of the matrix [long int, input]
+ *       MDIM -- leading dimension of BJAC array [long int, input]
+ *       T    -- current time [realtype, input]
+ *       Y    -- array containing state variables [realtype, input]
+ *       FY   -- array containing state derivatives [realtype, input]
+ *       BJAC -- 2D array containing the jacobian entries [realtype of size
+ *               (MDIM,NEQ), output]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       WK*  -- array containing temporary workspace of same size as Y 
+ *               [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                 >0 if a recoverable error occurred,
+ *                 <0 if an unrecoverable error ocurred.
+ *
  * 
- * (4s) User-supplied sparse Jacobian approximation routine: FCVSPJAC
+ * (2s) User-supplied sparse Jacobian approximation routine: FCVSPJAC
  *
- * Required when using the CVKLU or CVSuperLUMT linear solvers, the 
- * user must supply a routine that computes a compressed-sparse-column [or 
- * compressed-sparse-row] approximation of the system Jacobian J = dfi(t,y)/dy.  
- * If supplied, it must have the following form:
+ *   Required when using the KLU or SuperLUMT linear solvers, the 
+ *   user must supply a routine that computes a compressed-sparse-column [or 
+ *   compressed-sparse-row] approximation of the system Jacobian 
+ *   J = dfi(t,y)/dy.  If supplied, it must have the following form:
  *
- *       SUBROUTINE FCVSPJAC(T, Y, FY, N, NNZ, JDATA, JRVALS, 
- *      &                     JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
+ *       SUBROUTINE FCVSPJAC(T, Y, FY, N, NNZ, JDATA, JRVALS, JCPTRS, 
+ *      1                    H, IPAR, RPAR, WK1, WK2, WK3, IER)
  *
- * This routine must load the N by N compressed sparse column [or row] matrix 
- * with storage for NNZ nonzeros, stored in the arrays JDATA (nonzero
- * values), JRVALS (row [or column] indices for each nonzero), JCOLPTRS (indices 
- * for start of each column [or row]), with the Jacobian matrix at the current
- * (t,y) in CSC [or CSR] form (see sundials_sparse.h for more information).
+ *   This routine must load the N by N compressed sparse column [or row] matrix 
+ *   with storage for NNZ nonzeros, stored in the arrays JDATA (nonzero
+ *   values), JRVALS (row [or column] indices for each nonzero), JCOLPTRS (indices 
+ *   for start of each column [or row]), with the Jacobian matrix at the current
+ *   (t,y) in CSC [or CSR] form (see sunmatrix_sparse.h for more information).
  *
- * The arguments are:
+ *   The arguments are:
  *         T    -- current time [realtype, input]
  *         Y    -- array containing state variables [realtype, input]
  *         FY   -- array containing state derivatives [realtype, input]
@@ -192,7 +280,7 @@
  *        JDATA -- nonzero values in Jacobian
  *                 [realtype of length NNZ, output]
  *       JRVALS -- row [or column] indices for each nonzero in Jacobian
- *                  [int of length NNZ, output]
+ *                 [int of length NNZ, output]
  *       JCPTRS -- pointers to each Jacobian column [or row] in preceding arrays
  *                 [int of length N+1, output]
  *         H    -- current step size [realtype, input]
@@ -207,109 +295,316 @@
  *                   >0 if a recoverable error occurred,
  *                   <0 if an unrecoverable error ocurred.
  *
- * (5s) Optional user-supplied Lapack dense Jacobian routine: FCVLDJAC
- * See the description for FCVDJAC. NOTE: the dense Jacobian matrix
- * is NOT set to zero before calling the user's FCVLDJAC.
+ *   NOTE: this may ONLY be used if SUNDIALS has been configured with 
+ *   long int set to 64-bit integers.
+ * 
+ * (2) Optional user-supplied Jacobian-vector product setup routine: 
+ *   FCVJTSETUP
+ *
+ *   As an option when using the CVSpils iterative linear solver 
+ *   interface, the user may supply a routine that computes the product of 
+ *   the system Jacobian J = dfi(t,y)/dy and a given vector v, as well as 
+ *   a routine to set up any user data structures in preparation for the 
+ *   matrix-vector product.  If a 'setup' routine is supplied, it must 
+ *   have the following form:
+ *
+ *       SUBROUTINE FCVJTSETUP(T, Y, FY, H, IPAR, RPAR, IER)
  *
- * (6s) Optional user-supplied Lapack band Jacobian routine: FCVLBJAC
- * See the description for FCVBJAC. NOTE: the band Jacobian matrix
- * is NOT set to zero before calling the user's FCVLBJAC.
+ *   Typically this routine will use only T and Y.  It must perform any 
+ *   relevant preparations for subsequent calls to the user-provided 
+ *   FCVJTIMES routine (see below).  
+ *
+ *   The arguments are:
+ *       T    -- current time [realtype, input]
+ *       Y    -- array containing state variables [realtype, input]
+ *       FY   -- array containing state derivatives [realtype, input]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                  nonzero if an error.
+ * 
+ * (2) Optional user-supplied Jacobian-vector product routine: FCVJTIMES
+ *
+ *   As an option when using the SP* linear solver, the user may supply
+ *   a routine that computes the product of the system Jacobian J = df/dy and 
+ *   a given vector v.  If supplied, it must have the following form:
  *
- * (7) Optional user-supplied Jacobian-vector product routine: FCVJTIMES
- * As an option when using the SP* linear solver, the user may supply
- * a routine that computes the product of the system Jacobian J = df/dy and 
- * a given vector v.  If supplied, it must have the following form:
  *       SUBROUTINE FCVJTIMES (V, FJV, T, Y, FY, H, IPAR, RPAR, WORK, IER)
- *       DIMENSION V(*), FJV(*), Y(*), FY(*), IPAR(*), RPAR(*), WORK(*)
- * Typically this routine will use only NEQ, T, Y, V, and FJV.  It must
- * compute the product vector Jv where the vector v is stored in V, and store
- * the product in FJV.  On return, set IER = 0 if FCVJTIMES was successful,
- * and nonzero otherwise.
- * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC.
+ *
+ *   Typically this routine will use only NEQ, T, Y, V, and FJV.  It must
+ *   compute the product vector Jv where the vector v is stored in V, and store
+ *   the product in FJV.  
  * 
- * (8) Optional user-supplied error weight vector routine: FCVEWT
- * As an option to providing the relative and absolute tolerances, the user
- * may supply a routine that computes the weights used in the WRMS norms.
- * If supplied, it must have the following form:
+ *   The arguments are:
+ *       V    -- array containing vector to multiply [realtype, input]
+ *       JV   -- array containing product vector [realtype, output]
+ *       T    -- current time [realtype, input]
+ *       Y    -- array containing state variables [realtype, input]
+ *       FY   -- array containing state derivatives [realtype, input]
+ *       H    -- current step size [realtype, input]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       WORK -- array containing temporary workspace of same size as Y 
+ *               [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                  nonzero if an error.
+ *
+ * (3) Optional user-supplied preconditioner setup/solve routines: FCVPSET 
+ *   and FCVPSOL
+ *
+ *     As an option when using the CVSPILS linear solver interface, the 
+ *     user may supply routines to setup and apply the preconditioner.  
+ *     If supplied, these must have the following form:
+ *
+ *       SUBROUTINE FCVPSET(T,Y,FY,JOK,JCUR,GAMMA,H,IPAR,RPAR,IER)
+ *
+ *     This routine must set up the preconditioner P to be used in the 
+ *     subsequent call to FCVPSOL.  The preconditioner (or the product of 
+ *     the left and right preconditioners if using both) should be an 
+ *     approximation to the matrix  A = I - GAMMA*J  (J = Jacobian),
+ *
+ *     The arguments are:
+ *       T = current time [realtype, input]
+ *       Y = current state variable array [realtype, input]
+ *       FY = current state variable derivative array [realtype, input]
+ *       JOK = flag indicating whether Jacobian-related data needs to be 
+ *           recomputed [int, input]:
+ *                  0 = recompute, 
+ *		  1 = reuse with the current value of GAMMA
+ *       JCUR = return flag to denote if Jacobian data was recomputed
+ *           [realtype, output], 1=yes, 0=no
+ *       GAMMA = Jacobian scaling factor [realtype, input]
+ *       H = current time step [realtype, input]
+ *       IPAR = array of user integer data [long int, input/output]
+ *       RPAR = array with user real data [realtype, input/output]
+ *       IER  = return completion flag [int, output]:
+ *                  0 = SUCCESS,
+ *                 >0 = recoverable failure
+ *                 <0 = non-recoverable failure
+ *
+ *     The user-supplied routine FCVPSOL must have the form:
+ *
+ *       SUBROUTINE FCVPSOL(T,Y,FY,R,Z,GAMMA,DELTA,LR,IPAR,RPAR,IER)
+ *
+ *     Typically this routine will use only T, Y, GAMMA, R, LR, and Z.  It
+ *     must solve the preconditioner linear system Pz = r.  The preconditioner
+ *     (or the product of the left and right preconditioners if both are 
+ *     nontrivial) should be an approximation to the matrix  I - GAMMA*J  
+ *     (J = Jacobian).
+ *
+ *     The arguments are:
+ *       T = current time [realtype, input]
+ *       Y = current state variable array [realtype, input]
+ *       FY = current state variable derivative array [realtype, input]
+ *       R = right-hand side array [realtype, input]
+ *       Z = solution array [realtype, output]
+ *       GAMMA = Jacobian scaling factor [realtype, input]
+ *       DELTA = desired residual tolerance [realtype, input]
+ *       LR = flag denoting to solve the right or left preconditioner system
+ *                  1 = left preconditioner
+ *                  2 = right preconditioner
+ *       IPAR = array of user integer data [long int, input/output]
+ *       RPAR = array with user real data [realtype, input/output]
+ *       IER  = return completion flag [int, output]:
+ *                  0 = SUCCESS,
+ *                 >0 = recoverable failure
+ *                 <0 = non-recoverable failure
+ *
+ * (4) Optional user-supplied error weight vector routine: FCVEWT
+ *
+ *   As an option to providing the relative and absolute tolerances, the user
+ *   may supply a routine that computes the weights used in the WRMS norms.
+ *   If supplied, it must have the following form:
+ *
  *       SUBROUTINE FCVEWT (Y, EWT, IPAR, RPAR, IER)
- *       DIMENSION Y(*), EWT(*), IPAR(*), RPAR(*)
- * It must store the error weights in EWT, given the current solution vector Y.
- * On return, set IER = 0 if successful, and nonzero otherwise.
- * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC.
+ *
+ *   It must store the error weights in EWT, given the current solution vector Y.
+ *
+ *   The arguments are:
+ *       Y    -- array containing state variables [realtype, input]
+ *       EWT  -- array containing the error weight vector [realtype, output]
+ *       IPAR -- array containing integer user data that was passed to
+ *               FCVMALLOC [long int, input]
+ *       RPAR -- array containing real user data that was passed to
+ *               FCVMALLOC [realtype, input]
+ *       IER  -- return flag [int, output]:
+ *                  0 if successful, 
+ *                  nonzero if an error.
+ *
  *
  * -----------------------------------------------------------------------------
  *
- * (9) Initialization:  FNVINITS/FNVINITP/FNVINITOMP/FNVINITPTS, 
- *                      FCVMALLOC, FCVREINIT
- * 
- * (9.1s) To initialize the serial machine environment, the user must make
- * the following call:
- *        CALL FNVINITS (1, NEQ, IER)
- * where the first argument is the CVODE solver ID. The other arguments are:
- * NEQ     = size of vectors
- * IER     = return completion flag. Values are 0 = success, -1 = failure.
+ * (5) Initialization:  FNVINITS / FNVINITP / FNVINITOMP / FNVINITPTS, 
+ *                      FSUNBANDMATINIT / FSUNDENSEMATINIT / 
+ *                         FSUNSPARSEMATINIT,
+ *                      FSUNBANDLINSOLINIT / FSUNDENSELINSOLINIT / 
+ *                         FSUNKLUINIT / FSUNKLUREINIT /
+ *                         FSUNKLUSETORDERING / FSUNLAPACKBANDINIT / 
+ *                         FSUNLAPACKDENSEINIT / FSUNPCGINIT / 
+ *                         FSUNSPBCGSINIT / FSUNSPFGMRINIT / FSUNSPGMRINIT / 
+ *                         FSUNSPTFQMRINIT / FSUNSUPERLUMTINIT /
+ *                         FSUNSUPERLUMTSETORDERING,
+ *                      FCVMALLOC,
+ *                      FCVDLSINIT / FCVSPILSINIT,
+ *                      FCVREINIT
+ *
+ *   NOTE: the initialization order is important!  It *must* proceed as 
+ *   shown: vector, matrix (if used), linear solver (if used), CVode, 
+ *   CVDls/CVSpils, reinit.
  * 
- * (9.1p) To initialize the distributed memory parallel machine environment, 
- * the user must make the following call:
- *        CALL FNVINITP (1, NLOCAL, NGLOBAL, IER)
- * The arguments are:
- * NLOCAL  = local size of vectors on this processor
- * NGLOBAL = the system size, and the global size of vectors (the sum 
- *           of all values of NLOCAL)
- * IER     = return completion flag. Values are 0 = success, -1 = failure.
- * Note: If MPI was initialized by the user, the communicator must be
- * set to MPI_COMM_WORLD.  If not, this routine initializes MPI and sets
- * the communicator equal to MPI_COMM_WORLD.
+ * (5.1s) To initialize the a vector specification for storing the solution 
+ *   data, the user must make one of the following calls:
+ *
+ *       (serial)   
+ *          CALL FNVINITS(1, NEQ, IER)
+ *       (MPI parallel)
+ *          CALL FNVINITP(COMM, 1, NLOCAL, NGLOBAL, IER)
+ *       (OpenMP threaded)
+ *          CALL FNVINITOMP(1, NEQ, NUM_THREADS, IER)
+ *       (PThreads threaded)
+ *          CALL FNVINITPTS(1, NEQ, NUM_THREADS, IER)
+ *
+ *   In each of these, one argument is an int containing the CVODE solver 
+ *   ID (1). 
+ *
+ *   The other arguments are:
+ *        NEQ = size of vectors [long int, input]
+ *        COMM = the MPI communicator [int, input]
+ *        NLOCAL = local size of vectors on this processor 
+ *           [long int, input]
+ *        NGLOBAL = the system size, and the global size of vectors (the sum 
+ *           of all values of NLOCAL) [long int, input]
+ *        NUM_THREADS = number of threads
+ *        IER = return completion flag [int, output]:
+ *	          0 = success, 
+ *		 -1 = failure.
+ *
+ * (5.2) To initialize a band/dense/sparse matrix structure for 
+ *   storing the system Jacobian and for use within a direct linear solver,
+ *   the user must make one of the following calls:
  * 
- * (9.1omp) To initialize the openMP threaded vector kernel, 
- *          the user must make the following call:
+ *          CALL FSUNBANDMATINIT(1, N, MU, ML, SMU, IER)
+ *          CALL FSUNDENSEMATINIT(1, M, N, IER)
+ *          CALL FSUNSPARSEMATINIT(1, M, N, NNZ, SPARSETYPE, IER)
+ *
+ *   In each of these, one argument is an int containing the CVODE solver 
+ *   ID (1). 
+ *
+ *   The other arguments are:
+ *
+ *        M = the number of rows of the matrix [long int, input]
+ *        N = the number of columns of the matrix [long int, input]
+ *        MU = the number of upper bands (diagonal not included) in a banded 
+ *           matrix [long int, input]
+ *        ML = the number of lower bands (diagonal not included) in a banded 
+ *           matrix [long int, input]
+ *        SMU = the number of upper bands to store (diagonal not included) 
+ *           for factorization of a banded matrix [long int, input]
+ *        NNZ = the storage size (upper bound on the number of nonzeros) for 
+ *           a sparse matrix [long int, input]
+ *        SPARSETYPE = integer denoting use of CSC (0) vs CSR (1) storage 
+ *           for a sparse matrix [int, input]
+ *        IER = return completion flag [int, output]:
+ *	          0 = success, 
+ *		 -1 = failure.
+ *
+ * (5.3) To initialize a linear solver structure for solving linear systems 
+ *   arising from implicit treatment of the IVP, the user must make 
+ *   one of the following calls:
+ *
+ *          CALL FSUNBANDLINSOLINIT(1, IER)
+ *          CALL FSUNDENSELINSOLINIT(1, IER)
+ *          CALL FSUNKLUINIT(1, IER)
+ *          CALL FSUNLAPACKBANDINIT(1, IER)
+ *          CALL FSUNLAPACKDENSEINIT(1, IER)
+ *          CALL FSUNPCGINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPBCGSINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPFGMRINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPGMRINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSPTFQMRINIT(1, PRETYPE, MAXL, IER)
+ *          CALL FSUNSUPERLUMTINIT(1, NUM_THREADS, IER)
  *
- *          CALL FNVINITOMP (1, NEQ, NUM_THREADS, IER)
+ *   Or once these have been initialized, their solver parameters may be
+ *   modified via calls to the functions
  *
- *        The arguments are:
- *          NEQ = size of vectors
- *          NUM_THREADS = number of threads
- *          IER = return completion flag. Values are 0 = success, -1 = failure.
+ *          CALL FSUNKLUSETORDERING(1, ORD_CHOICE, IER)
+ *          CALL FSUNSUPERLUMTSETORDERING(1, ORD_CHOICE, IER)
  *
- * (9.1pts) To initialize the Pthreads threaded vector kernel, 
- *          the user must make the following call:
+ *          CALL FSUNPCGSETPRECTYPE(1, PRETYPE, IER)
+ *          CALL FSUNPCGSETMAXL(1, MAXL, IER)
+ *          CALL FSUNSPBCGSSETPRECTYPE(1, PRETYPE, IER)
+ *          CALL FSUNSPBCGSSETMAXL(1, MAXL, IER)
+ *          CALL FSUNSPFGMRSETGSTYPE(1, GSTYPE, IER)
+ *          CALL FSUNSPFGMRSETPRECTYPE(1, PRETYPE, IER)
+ *          CALL FSUNSPGMRSETGSTYPE(1, GSTYPE, IER)
+ *          CALL FSUNSPGMRSETPRECTYPE(1, PRETYPE, IER)
+ *          CALL FSUNSPTFQMRSETPRECTYPE(1, PRETYPE, IER)
+ *          CALL FSUNSPTFQMRSETMAXL(1, MAXL, IER)
  *
- *          CALL FNVINITOMP (1, NEQ, NUM_THREADS, IER)
+ *   In all of the above, one argument is an int containing the CVODE solver 
+ *   ID (1). 
  *
- *        The arguments are:
- *          NEQ = size of vectors
- *          NUM_THREADS = number of threads
- *          IER = return completion flag. Values are 0 = success, -1 = failure.
+ *   The other arguments are:
+ *
+ *        NNZ = the storage size (upper bound on the number of nonzeros) for 
+ *           a sparse matrix [long int, input]
+ *        ORD_CHOICE = integer denoting ordering choice (see 
+ *           SUNKLUSetOrdering and SUNSuperLUMTSetOrdering documentation 
+ *           for details) [int, input]
+ *        PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+ *           2=right, 3=both) [int, input]
+ *        MAXL = maximum Krylov subspace dimension [int, input]
+ *        GSTYPE = choice of Gram-Schmidt orthogonalization algorithm 
+ *           (0=modified, 1=classical) [int, input]
+ *        IER = return completion flag [int, output]:
+ *	          0 = success, 
+ *		 -1 = failure.
+ *
+ *
+ * (5.4) To set various problem and solution parameters and allocate
+ *   internal memory, make the following call:
  *
- * (9.2) To set various problem and solution parameters and allocate
- * internal memory, make the following call:
  *       CALL FCVMALLOC(T0, Y0, METH, ITMETH, IATOL, RTOL, ATOL,
  *      1               IOUT, ROUT, IPAR, RPAR, IER)
- * The arguments are:
- * T0     = initial value of t
- * Y0     = array of initial conditions
- * METH   = basic integration method: 1 = Adams (nonstiff), 2 = BDF (stiff)
- * ITMETH = nonlinear iteration method: 1=functional iteration, 2=Newton iter.
- * IATOL  = type for absolute tolerance ATOL: 1 = scalar, 2 = array.
- *          If IATOL = 3, then the user must supply a routine FCVEWT to compute
- *          the error weight vector.
- * RTOL   = relative tolerance (scalar)
- * ATOL   = absolute tolerance (scalar or array)
- * IOUT   = array of length 21 for integer optional outputs
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * ROUT   = array of length 6 for real optional outputs
- * IPAR   = array with user integer data
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * RPAR   = array with user real data
- * IER    = return completion flag.  Values are 0 = SUCCESS, and -1 = failure.
- *          See printed message for details in case of failure.
- *
- * The user data arrays IPAR and RPAR are passed unmodified to all subsequent
- * calls to user-provided routines. Modifications to either array inside a
- * user-provided routine will be propagated. Using these two arrays, the user
- * can dispense with Common blocks to pass data betwen user-provided routines.
+ *
+ *   The arguments are:
+ *      T0     = initial value of t [realtype, input]
+ *      Y0     = array of initial conditions [realtype, input]
+ *      METH   = flag denoting basic integration method [int, input]:
+ *                   1 = Adams (nonstiff), 
+ *                   2 = BDF (stiff)
+ *      ITMETH = flag denoting nonlinear iteration method [int, input]: 
+ *                   1 = functional iteration, 
+ *                   2 = Newton iter.
+ *      IATOL  = flag denoting type for absolute tolerance ATOL [int, input]: 
+ *                   1 = scalar, 
+ *                   2 = array.
+ *                   3 = user-supplied function; the user must supply a routine 
+ *                       FCVEWT to compute the error weight vector.
+ *      RTOL   = scalar relative tolerance [realtype, input]
+ *      ATOL   = scalar or array absolute tolerance [realtype, input]
+ *      IOUT   = array of length 21 for integer optional outputs 
+ *               [long int, output]
+ *      ROUT   = array of length 6 for real optional outputs [realtype, output]
+ *      IPAR   = array with user integer data [long int, input/output]
+ *      RPAR   = array with user real data [realtype, input/output]
+ *	IER    = return completion flag [int, output]:
+ *                  0 = SUCCESS,
+ *                 -1 = failure (see printed message for failure details).
+ *
+ *   The user data arrays IPAR and RPAR are passed unmodified to all subsequent
+ *   calls to user-provided routines. Modifications to either array inside a
+ *   user-provided routine will be propagated. Using these two arrays, the user
+ *   can dispense with Common blocks to pass data betwen user-provided routines.
  * 
- * The optional outputs are:
+ *   The optional outputs are:
  *           LENRW   = IOUT( 1) from CVodeGetWorkSpace
  *           LENIW   = IOUT( 2) from CVodeGetWorkSpace
  *           NST     = IOUT( 3) from CVodeGetNumSteps
@@ -329,379 +624,261 @@
  *           TCUR    = ROUT( 4) from CVodeGetCurrentTime
  *           TOLSF   = ROUT( 5) from CVodeGetTolScaleFactor
  *           UROUND  = ROUT( 6) from UNIT_ROUNDOFF
- * See the CVODE manual for details. 
+ *   See the CVODE manual for details. 
  *
- * If the user program includes the FCVEWT routine for the evaluation of the 
- * error weights, the following call must be made
- *       CALL FCVEWTSET(FLAG, IER)
- * with FLAG = 1 to specify that FCVEWT is provided.
- * The return flag IER is 0 if successful, and nonzero otherwise.
+ * (5.5) If a direct linear solver was created in step (5.3) then it must be 
+ *   attached to CVode.  If the user called any one of FSUNBANDLINSOLINIT, 
+ *   FSUNDENSELINSOLINIT, FSUNKLUINIT, FSUNLAPACKBANDINIT, 
+ *   FSUNLAPACKDENSEINIT, or FSUNSUPERLUMTINIT, then this must be 
+ *   attached to the CVDLS interface using the command:
  *
- * (9.3) To re-initialize the CVODE solver for the solution of a new problem
- * of the same size as one already solved, make the following call:
- *       CALL FCVREINIT(T0, Y0, IATOL, RTOL, ATOL, IER)
- * The arguments have the same names and meanings as those of FCVMALLOC,
- * except that METH and ITMETH  have been omitted from the argument list 
- * (being unchanged for the new problem).  
- * FCVREINIT performs the same initializations as FCVMALLOC, but does no memory 
- * allocation, using instead the existing internal memory created by the
- * previous  FCVMALLOC call.  The call to specify the linear system solution
- * method may or may not be needed; see paragraph (7) below.
- * 
- * (9.4) To set various integer optional inputs, make the folowing call:
- *       CALL FCVSETIIN(KEY, VALUE, IER)
- * to set the integer value VAL to the optional input specified by the
- * quoted character string KEY.
- * KEY is one of the following: MAX_ORD, MAX_NSTEPS, MAX_ERRFAIL, MAX_NITERS, 
- * MAX_CONVFAIL, HNIL_WARNS, STAB_LIM.
+ *       CALL FCVDLSINIT(IER)
  *
- * To set various real optional inputs, make the folowing call:
- *       CALL FCVSETRIN(KEY, VALUE, IER)
- * to set the real value VAL to the optional input specified by the
- * quoted character string KEY.
- * KEY is one of the following: INIT_STEP, MAX_STEP, MIN_STEP, STOP_TIME,
- * NLCONV_COEF.
+ *   The arguments are:
+ *	IER  = return completion flag [int, output]:
+ *                  0 = SUCCESS,
+ *                 -1 = failure (see printed message for failure details).
  *
- * FCVSETIIN and FCVSETRIN return IER = 0 if successful and IER < 0 if an 
- * error occured.
+ * (5.5) If an iterative linear solver was created in step (5.3) then it must 
+ *   be attached to CVode.  If the user called any one of FSUNPCGINIT, 
+ *   FSUNSPBCGSINIT, FSUNSPFGMRINIT, FSUNSPGMRINIT, or FSUNSPTFQMRINIT, 
+ *   then this must be attached to the CVSPILS interface using the command:
  *
- * -----------------------------------------------------------------------------
+ *       CALL FCVSPILSINIT(IER)
  *
- * (10) Specification of linear system solution method.
- * In the case of a stiff system, the implicit BDF method involves the solution
- * of linear systems related to the Jacobian J = df/dy of the ODE system.
- * CVODE presently includes four choices for the treatment of these systems,
- * and the user of FCVODE must call a routine with a specific name to make the
- * desired choice.
- * 
- * (10.1) Diagonal approximate Jacobian.
- * This choice is appropriate when the Jacobian can be well approximated by
- * a diagonal matrix.  The user must make the call:
+ *   The arguments are:
+ *	IER  = return completion flag [int, output]:
+ *                  0 = SUCCESS,
+ *                 -1 = failure (see printed message for failure details).
+ *
+ * (5.5) If the user instead wishes to use a diagonal approximate Jacobian for 
+ *   solving the Newton systems, then it must be created and attached to CVode.  
+ *   This choice is appropriate when the Jacobian can be well approximated by
+ *   a diagonal matrix.  The user must make the call:
  *       CALL FCVDIAG(IER)
- * IER is an error return flag: 0 = success, negative value = error.
- * There is no additional user-supplied routine.  
- *
- * Optional outputs specific to the DIAG case are:
- *        LENRWLS = IOUT(13) from CVDiagGetWorkSpace
- *        LENIWLS = IOUT(14) from CVDiagGetWorkSpace
- *        LSTF    = IOUT(15) from CVDiagGetLastFlag
- *        NFELS   = IOUT(16) from CVDiagGetNumRhsEvals
- * See the CVODE manual for descriptions.
- * 
- * (10.2s) DENSE treatment of the linear system.
- * The user must make the call
- *       CALL FCVDENSE(NEQ, IER)
- * The argument is:
- * IER = error return flag: 0 = success , negative value = an error occured
+ *
+ *   The arguments are:
+ *	IER  = return completion flag [int, output]:
+ *                  0 = SUCCESS,
+ *                 -1 = failure (see printed message for failure details).
+ *
+ * (5.6) If the user program includes the FCVEWT routine for the evaluation 
+ *   of the error weights, the following call must be made
+ *
+ *       CALL FCVEWTSET(FLAG, IER)
+ *
+ *   with FLAG = 1 to specify that FCVEWT is provided and 
+ *   should be used; FLAG = 0 resets to the default EWT formulation.
+ *   The return flag IER is 0 if successful, and nonzero otherwise.
+ *
+ * (5.7) If the user program includes the FCVBJAC routine for the 
+ *   evaluation of the band approximation to the Jacobian, then following 
+ *   the call to FCVDLSINIT, the following call must be made 
+ *
+ *       CALL FCVBANDSETJAC(FLAG, IER)
+ *
+ *   with the int FLAG=1 to specify that FCVBJAC is provided and should be 
+ *   used; FLAG=0 specifies a reset to the internal finite difference 
+ *   Jacobian approximation.  The int return flag IER=0 if successful, 
+ *   nonzero otherwise.
  * 
- * If the user program includes the FCVDJAC routine for the evaluation of the 
- * dense approximation to the Jacobian, the following call must be made
+ *   If the user program includes the FCVDJAC routine for the evaluation 
+ *   of the dense approximation to the Jacobian, then after the call to 
+ *   FCVDLSINIT, the following call must be made 
+ *
  *       CALL FCVDENSESETJAC(FLAG, IER)
- * with FLAG = 1 to specify that FCVDJAC is provided.  (FLAG = 0 specifies
- * using the internal finite differences approximation to the Jacobian.)
- * The return flag IER is 0 if successful, and nonzero otherwise.
- * 
- * Optional outputs specific to the DENSE case are:
- *        LENRWLS = IOUT(13) from CVDenseGetWorkSpace
- *        LENIWLS = IOUT(14) from CVDenseGetWorkSpace
- *        LSTF    = IOUT(15) from CVDenseGetLastFlag
- *        NFELS   = IOUT(16) from CVDenseGetNumRhsEvals
- *        NJED    = IOUT(17) from CVDenseGetNumJacEvals
- * See the CVODE manual for descriptions.
- * 
- * (10.3s) BAND treatment of the linear system
- * The user must make the call
- *       CALL FCVBAND(NEQ, MU, ML, IER)
- * The arguments are:
- * MU  = upper bandwidth
- * ML  = lower bandwidth
- * IER = error return flag: 0 = success , negative value = an error occured
+ *
+ *   with the int FLAG=1 to specify that FCVDJAC is provided and should be 
+ *   used; FLAG=0 specifies a reset to the internal finite difference 
+ *   Jacobian approximation.  The int return flag IER=0 if successful, and 
+ *   nonzero otherwise.
  * 
- * If the user program includes the FCVBJAC routine for the evaluation of the 
- * band approximation to the Jacobian, the following call must be made
- *       CALL FCVBANDSETJAC(FLAG, IER)
- * with FLAG = 1 to specify that FCVBJAC is provided.  (FLAG = 0 specifies
- * using the internal finite differences approximation to the Jacobian.)
- * The return flag IER is 0 if successful, and nonzero otherwise.
+ *   When using a sparse matrix and linear solver the user must provide the
+ *   FCVSPJAC routine for the evaluation of the sparse approximation to 
+ *   the Jacobian.  To indicate that this routine has been provided, after 
+ *   the call to FCVDLSINIT, the following call must be made 
+ *
+ *       CALL FCVSPARSESETJAC(IER)
+ *
+ *   The int return flag IER=0 if successful, and nonzero otherwise.
+ *
+ * (5.8) If the user program includes the FCVJTSETUP and FCVJTIMES 
+ *   routines for setup of a Jacobian-times-vector product (for use with 
+ *   the CVSpils interface), then after creating the CVSpils interface, 
+ *   the following call must be made:
+ *
+ *       CALL FCVSPILSSETJAC(FLAG, IER)
+ *
+ *   with the int FLAG=1 to specify that FCVJTSETUP and FCVJTIMES are 
+ *   provided and should be used; FLAG=0 specifies a reset to the internal 
+ *   finite difference approximation to this product).  The int return 
+ *   flag IER=0 if successful, and nonzero otherwise.
  * 
- * Optional outputs specific to the BAND case are:
- *        LENRWLS = IOUT(13) from CVBandGetWorkSpace
- *        LENIWLS = IOUT(14) from CVBandGetWorkSpace
- *        LSTF    = IOUT(15) from CVBandGetLastFlag
- *        NFELS   = IOUT(16) from CVBandGetNumRhsEvals
- *        NJEB    = IOUT(17) from CVBandGetNumJacEvals
- * See the CVODE manual for descriptions.
- *
- * (10.4s) LAPACK dense treatment of the linear system
- * The user must make the call
- *       CALL FCVLAPACKDENSE(NEQ, IER)
- * and, optionally
- *       CALL FCVLAPACKDENSESETJAC(FLAG, IER)
- * with FLAG=1 if the user provides the function FCVLDJAC. 
- * See (9.2s) for more details.
- *
- * (10.5s) LAPACK band treatment of the linear system
- * The user must make the call
- *       CALL FCVLAPACKBAND(NEQ, IER)
- * and, optionally
- *       CALL FCVLAPACKBANDSETJAC(FLAG, IER)
- * with FLAG=1 if the user provides the function FCVLBJAC. 
- * See (9.3s)
- *
- *  (10.6s) SPARSE treatment of the linear system using the KLU solver.
- *
- *     The user must make the call
- *
- *       CALL FCVKLU(NEQ, NNZ, SPARSETYPE, ORDERING, IER)
+ * (5.9) If the user program includes the FCVPSET and FCVPSOL routines 
+ *   for supplying a preconditioner to an iterative linear solver, then 
+ *   after creating the CVSpils interface, the following call must be made
  *
- *     The arguments are:
- *        NEQ = the problem size [int; input]
- *        NNZ = the maximum number of nonzeros [int; input]
- *        SPARSETYPE = choice between CSC and CSR format
- *           (0 = CSC, 1 = CSR) [int; input]
- *        ORDERING = the matrix ordering desired, possible values
- *           come from the KLU package (0 = AMD, 1 = COLAMD) [int; input]
- *        IER = error return flag [int, output]: 
- *	         0 = success, 
- *		 negative = error.
+ *       CALL FCVSPILSSETPREC(FLAG, IER)
  *
- *     When using the KLU solver the user must provide the FCVSPJAC routine for the 
- *     evalution of the sparse approximation to the Jacobian. To indicate that this
- *     routine has been provided, after the call to FCVKLU, the following call must 
- *     be made    
+ *   with the int FLAG=1.  If FLAG=0 then preconditioning with these 
+ *   routines will be disabled. The return flag IER=0 if successful, 
+ *   nonzero otherwise.
  *
- *       CALL FCVSPARSESETJAC(IER) 
+ * (5.10) If the user wishes to use one of CVode's built-in preconditioning 
+ *   modules, FCVBP or FCVBBD, then that should be initialized after 
+ *   creating the CVSpils interface using one of the calls
  *
- *     The int return flag IER=0 if successful, and nonzero otherwise.
+ *       CALL FCVBPINIT(NEQ, MU, ML, IER)
+ *       CALL FCVBBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER)
  *
- *  
- *     The CVODE KLU solver will reuse much of the factorization information from one
- *     nonlinear iteration to the next.  If at any time the user wants to force a full
- *     refactorization or if the number of nonzeros in the Jacobian matrix changes, the
- *     user should make the call
+ *   Detailed explanation of the inputs to these functions, as well as any 
+ *   requirements of user-supplied functions on which these preconditioning 
+ *   modules rely, may be found in the header files for each module, 
+ *   fcvbp.h or fcvbbd.h, respectively.
  *
- *       CALL FCVKLUREINIT(NEQ, NNZ, REINIT_TYPE)
  *
- *     The arguments are:
- *        NEQ = the problem size [int; input]
- *        NNZ = the maximum number of nonzeros [int; input]
- *	REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be destroyed and 
- *          a new one will be allocated with NNZ nonzeros.  For a value of 2, 
- *	  only symbolic and numeric factorizations will be completed. 
- * 
- *     When using FCVKLU, the user is required to supply the FCVSPJAC 
- *     routine for the evaluation of the sparse approximation to the 
- *     Jacobian, as discussed above with the other user-supplied routines.
- * 
- *     Optional outputs specific to the KLU case are:
- *        LSTF    = IOUT(14) from CVSlsGetLastFlag
- *        NJES    = IOUT(16) from CVSlsGetNumJacEvals
- *     See the CVODE manual for descriptions.
- * 
- * (10.7s) SPARSE treatment of the linear system using the SuperLUMT solver.
  *
- *     The user must make the call
+ * (5.11) To re-initialize the CVODE solver for the solution of a new problem
+ *   of the same size as one already solved, make the following call:
  *
- *       CALL FCVSUPERLUMT(NTHREADS, NEQ, NNZ, ORDERING, IER)
+ *       CALL FCVREINIT(T0, Y0, IATOL, RTOL, ATOL, IER)
  *
- *     The arguments are:
- *        NTHREADS = desired number of threads to use [int; input]
- *        NEQ = the problem size [int; input]
- *        NNZ = the maximum number of nonzeros [int; input]
- *	ORDERING = the matrix ordering desired, possible values
- *	   come from the SuperLU_MT package [int; input]
- *           0 = Natural
- *           1 = Minimum degree on A^T A
- *           2 = Minimum degree on A^T + A
- *           3 = COLAMD
- *	IER = error return flag [int, output]: 
- *	         0 = success, 
- *		 negative = error.
- *	 
- *     At this time, there is no reinitialization capability for the SUNDIALS 
- *     interfaces to the SuperLUMT solver.
- *
- *     When using the SuperLUMT solver the user must providing the FCVSPJAC routine
- *     for the evalution of the CSC approximation to the Jacobian (note: the current 
- *     SuperLU_MT interface in SUNDIALS does not support CSR matrices). To indicate 
- *     that this routine has been provided, after the call to FCVSUPERLUMT, the following
- *     call must be made    
- *
- *       CALL FCVSPARSESETJAC(IER) 
- *
- *     The int return flag IER=0 if successful, and nonzero otherwise.
- * 
- *     Optional outputs specific to the SUPERLUMT case are:
- *        LSTF    = IOUT(14) from CVSlsGetLastFlag
- *        NJES    = IOUT(16) from CVSlsGetNumJacEvals
- *     See the CVODE manual for descriptions.
- * 
- * (10.8) SPGMR treatment of the linear systems.
- * For the Scaled Preconditioned GMRES solution of the linear systems,
- * the user must make the following call:
- *       CALL FCVSPGMR(IPRETYPE, IGSTYPE, MAXL, DELT, IER)              
- * The arguments are:
- * IPRETYPE = preconditioner type: 
- *              0 = none 
- *              1 = left only
- *              2 = right only
- *              3 = both sides
- * IGSTYPE  = Gram-schmidt process type: 
- *              1 = modified G-S
- *              2 = classical G-S.
- * MAXL     = maximum Krylov subspace dimension; 0 indicates default.
- * DELT     = linear convergence tolerance factor; 0.0 indicates default.
- * IER      = error return flag: 0 = success; negative value = an error occured
+ *   The arguments have the same names and meanings as those of FCVMALLOC,
+ *   except that METH and ITMETH have been omitted from the argument list 
+ *   (being unchanged for the new problem).  
+ *   FCVREINIT performs the same initializations as FCVMALLOC, but does no memory 
+ *   allocation, using instead the existing internal memory created by the
+ *   previous FCVMALLOC call.  The subsequent calls to 
+ *   attach the linear system solver is only needed if that object has been re-created.
  * 
+ * (5.12) The SUNKLU solver will reuse much of the factorization information 
+ *   from one solve to the next.  If at any time the user wants to force a 
+ *   full refactorization or if the number of nonzeros in the Jacobian 
+ *   matrix changes, the user should make the call
+ *
+ *        CALL FSUNKLUREINIT(4, NNZ, REINIT_TYPE, IER)
+ *
+ *   The arguments are:
+ *        NNZ = the maximum number of nonzeros [int; input]
+ *        REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be 
+ *          destroyed and a new one will be allocated with NNZ nonzeros.  
+ *          For a value of 2, only symbolic and numeric factorizations will 
+ *          be completed. 
  * 
- * Optional outputs specific to the SPGMR case are:
- *        LENRWLS = IOUT(13) from CVSpgmrGetWorkSpace
- *        LENIWLS = IOUT(14) from CVSpgmrGetWorkSpace
- *        LSTF    = IOUT(15) from CVSpgmrGetLastFlag
- *        NFELS   = IOUT(16) from CVSpgmrGetRhsEvals
- *        NJTV    = IOUT(17) from CVSpgmrGetJtimesEvals
- *        NPE     = IOUT(18) from CVSpgmrGetPrecEvals
- *        NPS     = IOUT(19) from CVSpgmrGetPrecSolves
- *        NLI     = IOUT(20) from CVSpgmrGetLinIters
- *        NCFL    = IOUT(21) from CVSpgmrGetConvFails
- * See the CVODE manual for descriptions.
- * 
- * If a sequence of problems of the same size is being solved using the
- * SPGMR linear solver, then following the call to FCVREINIT, a call to the
- * FCVSPGMRREINIT routine is needed if any of IPRETYPE, IGSTYPE, DELT is
- * being changed.  In that case, call FCVSPGMRREINIT as follows:
- *       CALL FCVSPGMRREINIT(IPRETYPE, IGSTYPE, DELT, IER)              
- * The arguments have the same meanings as for FCVSPGMR.  If MAXL is being
- * changed, then call FCVSPGMR instead.
- * 
- * (10.9) SPBCG treatment of the linear systems.
- * For the Scaled Preconditioned Bi-CGSTAB solution of the linear systems,
- * the user must make the following call:
- *       CALL FCVSPBCG(IPRETYPE, MAXL, DELT, IER)              
- * The arguments are:
- * IPRETYPE = preconditioner type: 
- *              0 = none 
- *              1 = left only
- *              2 = right only
- *              3 = both sides
- * MAXL     = maximum Krylov subspace dimension; 0 indicates default.
- * DELT     = linear convergence tolerance factor; 0.0 indicates default.
- * IER      = error return flag: 0 = success; negative value = an error occured
- * 
- * Optional outputs specific to the SPBCG case are:
- *        LENRWLS = IOUT(13) from CVSpbcgGetWorkSpace
- *        LENIWLS = IOUT(14) from CVSpbcgGetWorkSpace
- *        LSTF    = IOUT(15) from CVSpbcgGetLastFlag
- *        NFELS   = IOUT(16) from CVSpbcgGetRhsEvals
- *        NJTV    = IOUT(17) from CVSpbcgGetJtimesEvals
- *        NPE     = IOUT(18) from CVSpbcgGetPrecEvals
- *        NPS     = IOUT(19) from CVSpbcgGetPrecSolves
- *        NLI     = IOUT(20) from CVSpbcgGetLinIters
- *        NCFL    = IOUT(21) from CVSpbcgGetConvFails
-  * See the CVODE manual for descriptions.
- * 
- * If a sequence of problems of the same size is being solved using the
- * SPBCG linear solver, then following the call to FCVREINIT, a call to the
- * FCVSPBCGREINIT routine is needed if any of its arguments is
- * being changed.  The call is:
- *       CALL FCVSPBCGREINIT(IPRETYPE, MAXL, DELT, IER)              
- * The arguments have the same meanings as for FCVSPBCG.
- *
- * (10.10) SPTFQMR treatment of the linear systems.
- * For the Scaled Preconditioned TFQMR solution of the linear systems,
- * the user must make the following call:
- *       CALL FCVSPTFQMR(IPRETYPE, MAXL, DELT, IER)              
- * The arguments are:
- * IPRETYPE = preconditioner type: 
- *              0 = none 
- *              1 = left only
- *              2 = right only
- *              3 = both sides
- * MAXL     = maximum Krylov subspace dimension; 0 indicates default.
- * DELT     = linear convergence tolerance factor; 0.0 indicates default.
- * IER      = error return flag: 0 = success; negative value = an error occured
- * 
- * Optional outputs specific to the SPTFQMR case are:
- *        LENRWLS = IOUT(13) from CVSptfqmrGetWorkSpace
- *        LENIWLS = IOUT(14) from CVSptfqmrGetWorkSpace
- *        LSTF    = IOUT(15) from CVSptfqmrGetLastFlag
- *        NFELS   = IOUT(16) from CVSptfqmrGetRhsEvals
- *        NJTV    = IOUT(17) from CVSptfqmrGetJtimesEvals
- *        NPE     = IOUT(18) from CVSptfqmrGetPrecEvals
- *        NPS     = IOUT(19) from CVSptfqmrGetPrecSolves
- *        NLI     = IOUT(20) from CVSptfqmrGetLinIters
- *        NCFL    = IOUT(21) from CVSptfqmrGetConvFails
- * See the CVODE manual for descriptions.
- *
- * If a sequence of problems of the same size is being solved using the
- * SPTFQMR linear solver, then following the call to FCVREINIT, a call to the
- * FCVSPTFQMRREINIT routine is needed if any of its arguments is
- * being changed.  The call is:
- *       CALL FCVSPTFQMRREINIT(IPRETYPE, MAXL, DELT, IER)              
- * The arguments have the same meanings as for FCVSPTFQMR.
- *
- * (10.11) Usage of user-supplied routines for the Krylov solvers
- *
- * If the user program includes the FCVJTIMES routine for the evaluation of the 
- * Jacobian vector product, the following call must be made
- *       CALL FCVSPILSSETJAC(FLAG, IER)
- * with FLAG = 1 to specify that FCVJTIMES is provided.  (FLAG = 0 specifies
- * using and internal finite difference approximation to this product.)
- * The return flag IER is 0 if successful, and nonzero otherwise.
+ * (5.13) To set various integer optional inputs, make the folowing call:
+ *
+ *       CALL FCVSETIIN(KEY, VALUE, IER)
+ *
+ *   to set the integer value VAL to the optional input specified by the
+ *   quoted character string KEY.  VALUE must be a Fortran integer of size 
+ *   commensurate with a C "long int".
+ *   KEY must be one of the following: MAX_ORD, MAX_NSTEPS, MAX_ERRFAIL, 
+ *   MAX_NITERS, MAX_CONVFAIL, HNIL_WARNS, STAB_LIM.  The int return flag 
+ *   IER is 0 if successful, and <0 otherwise.
+ *
+ * (5.14) To set various real optional inputs, make the folowing call:
+ *
+ *       CALL FCVSETRIN(KEY, VALUE, IER)
+ *
+ *   to set the real value VAL to the optional input specified by the
+ *   quoted character string KEY.  VALUE must be a Fortran real-valued 
+ *   number of size commensurate with the SUNDIALS "realtype".  KEY must 
+ *   be one of the following: INIT_STEP, MAX_STEP, MIN_STEP, STOP_TIME,
+ *   NLCONV_COEF.  The int return flag IER is 0 if successful, and <0 otherwise.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (6) Optional outputs from DLS and SPILS linear solvers (stored in the 
+ *   IOUT array that was passed to FCVMALLOC)
+ *
+ *   Optional outputs specific to the CVDLS interface:
+ *        LENRWLS  = IOUT(13) from CVDlsGetWorkSpace (realtype space)
+ *        LENIWLS  = IOUT(14) from CVDlsGetWorkSpace (integer space)
+ *        LSTF     = IOUT(15) from CVDlsGetLastFlag
+ *        NFELS    = IOUT(16) from CVDlsGetNumRhsEvals
+ *        NJED     = IOUT(17) from CVDlsGetNumJacEvals
+ *
+ *   Optional outputs specific to the CVSPILS interface:
+ *        LENRWLS  = IOUT(13) from CVSpilsGetWorkSpace
+ *        LENIWLS  = IOUT(14) from CVSpilsGetWorkSpace
+ *        LSTF     = IOUT(15) from CVSpilsGetLastFlag
+ *        NFELS    = IOUT(16) from CVSpilsGetNumRhsEvals
+ *        NJTV     = IOUT(17) from CVSpilsGetNumJtimesEvals
+ *        NPE      = IOUT(18) from CVSpilsGetNumPrecEvals
+ *        NPS      = IOUT(19) from CVSpilsGetNumPrecSolves
+ *        NLI      = IOUT(20) from CVSpilsGetNumLinIters
+ *        NCFL     = IOUT(21) from CVSpilsGetNumConvFails
+ *
+ *   Optional outputs specific to the DIAG case are:
+ *        LENRWLS  = IOUT(13) from CVDiagGetWorkSpace
+ *        LENIWLS  = IOUT(14) from CVDiagGetWorkSpace
+ *        LSTF     = IOUT(15) from CVDiagGetLastFlag
+ *        NFELS    = IOUT(16) from CVDiagGetNumRhsEvals
  * 
- * Usage of the user-supplied routines FCVPSOL and FCVPSET for solution of the 
- * preconditioner linear system requires the following call:
- *       CALL FCVSPILSSETPREC(FLAG, IER)
- * with FLAG = 1. The return flag IER is 0 if successful, nonzero otherwise.
- * The user-supplied routine FCVPSOL must have the form:
- *       SUBROUTINE FCVPSOL (T,Y,FY,R,Z,GAMMA,DELTA,LR,IPAR,RPAR,VT,IER)
- *       DIMENSION Y(*), FY(*), VT(*), R(*), Z(*), IPAR(*), RPAR(*)
- * Typically this routine will use only NEQ, T, Y, GAMMA, R, LR, and Z.  It
- * must solve the preconditioner linear system Pz = r, where r = R is input, 
- * and store the solution z in Z.  Here P is the left preconditioner if LR = 1
- * and the right preconditioner if LR = 2.  The preconditioner (or the product
- * of the left and right preconditioners if both are nontrivial) should be an 
- * approximation to the matrix I - GAMMA*J (I = identity, J = Jacobian).
- * IPAR and RPAR are user (integer and real) arrays passed to FCVMALLOC.
- * On return, set IER = 0 if successful, IER > 0 if a recoverable error occurred,
- * and IER < 0 if an unrecoverable error ocurred.
+ *   See the CVODE manual for more detailed descriptions of any of the 
+ *   above.
  *
  * -----------------------------------------------------------------------------
  *
- * (11) The integrator: FCVODE
- * Carrying out the integration is accomplished by making calls as follows:
+ * (7) The integrator: FCVODE
+ *
+ *   Carrying out the integration is accomplished by making calls as follows:
+ *
  *       CALL FCVODE (TOUT, T, Y, ITASK, IER)
- * The arguments are:
- * TOUT  = next value of t at which a solution is desired (input)
- * T     = value of t reached by the solver on output
- * Y     = array containing the computed solution on output
- * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate)
- *         2 = one-step mode (return after each internal step taken)
- *         3 = normal tstop mode (like 1, but integration never proceeds past 
- *             TSTOP, which must be specified through a call to FCVSETRIN
- *             using the key 'STOP_TIME')
- *         4 = one step tstop (like 2, but integration never goes past TSTOP)
- * IER   = completion flag: 0 = success, 1 = tstop return, 2 = root return, 
- *         values -1 ... -10 are various failure modes (see CVODE manual).
- * The current values of the optional outputs are available in IOUT and ROUT.
+ *
+ *   The arguments are:
+ *      TOUT  = next value of t at which a solution is desired [realtype, input]
+ *      T     = value of t reached by the solver on output [realtype, output]
+ *      Y     = array containing the computed solution on output [realtype, output]
+ *      ITASK = task indicator [int, input]: 
+ *              1 = normal mode (overshoot TOUT and interpolate)
+ *              2 = one-step mode (return after each internal step taken)
+ *              3 = normal tstop mode (like 1, but integration never proceeds past 
+ *                  TSTOP, which must be specified through a call to FCVSETRIN
+ *                  using the key 'STOP_TIME')
+ *              4 = one step tstop (like 2, but integration never goes past TSTOP)
+ *      IER   = completion flag [int, output]: 
+ *              0 = success, 
+ *              1 = tstop return, 
+ *              2 = root return, 
+ *              values -1 ... -10 are various failure modes (see CVODE manual).
+ *   The current values of the optional outputs are available in IOUT and ROUT.
  * 
  * -----------------------------------------------------------------------------
  *
- * (12) Computing solution derivatives: FCVDKY
- * To obtain a derivative of the solution, of order up to the current method
- * order, make the following call:
+ * (8) Computing solution derivatives: FCVDKY
+ *
+ *   To obtain a derivative of the solution, of order up to the current method
+ *   order, make the following call:
+ *
  *       CALL FCVDKY (T, K, DKY, IER)
- * The arguments are:
- * T   = value of t at which solution derivative is desired, in [TCUR-HU,TCUR].
- * K   = derivative order (0 .le. K .le. QU)
- * DKY = array containing computed K-th derivative of y on return
- * IER = return flag: = 0 for success, < 0 for illegal argument.
+ *
+ *   The arguments are:
+ *      T   = value of t at which solution derivative is desired, in
+ *             [TCUR-HU,TCUR], [realtype, input].
+ *      K   = derivative order (0 .le. K .le. QU) [int, input]
+ *      DKY = array containing computed K-th derivative of y [realtype, output]
+ *      IER = return flag [int, output]: = 0 for success, <0 for illegal argument
  * 
  * -----------------------------------------------------------------------------
  *
- * (13) Memory freeing: FCVFREE 
- * To free the internal memory created by the calls to FCVMALLOC and
- * FNVINITS or FNVINITP, make the call
+ * (9) Get the current error weight vector: FCVGETERRWEIGHTS
+ *
+ *   To obtain the current error weight vector, make the following call:
+ *
+ *       CALL FCVGETERRWEIGHTS(EWT, IER)
+ *
+ *   The arguments are:
+ *       EWT = array containing the error weight vector [realtype, output]
+ *       IER = return flag [int, output]: 0=success, nonzero if an error.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * (10) Memory freeing: FCVFREE 
+ *
+ *   To free the internal memory created by the calls to FCVMALLOC, 
+ *   FCVDLSINIT/FCVSPILSINIT and FNVINIT*, make the call
+ *
  *       CALL FCVFREE
  * 
  * =============================================================================
@@ -712,10 +889,10 @@
 
 /* header files  */
 #include <cvode/cvode.h>
-#include <sundials/sundials_direct.h>  /* definition of type DlsMat   */
-#include <sundials/sundials_sparse.h>  /* definition of type SlsMat   */
-#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
-#include <sundials/sundials_types.h>   /* definition of type realtype */
+#include <sundials/sundials_linearsolver.h>  /* definition of type SUNLinearSolver */
+#include <sundials/sundials_matrix.h>        /* definition of type SUNMatrix */
+#include <sundials/sundials_nvector.h>       /* definition of type N_Vector */
+#include <sundials/sundials_types.h>         /* definition of type realtype */
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -730,27 +907,14 @@ extern "C" {
 #define FCV_SETIIN         SUNDIALS_F77_FUNC(fcvsetiin, FCVSETIIN)
 #define FCV_SETRIN         SUNDIALS_F77_FUNC(fcvsetrin, FCVSETRIN)
 #define FCV_EWTSET         SUNDIALS_F77_FUNC(fcvewtset, FCVEWTSET)
-#define FCV_DIAG           SUNDIALS_F77_FUNC(fcvdiag, FCVDIAG)
-#define FCV_DENSE          SUNDIALS_F77_FUNC(fcvdense, FCVDENSE)
+#define FCV_DLSINIT        SUNDIALS_F77_FUNC(fcvdlsinit, FCVDLSINIT)
 #define FCV_DENSESETJAC    SUNDIALS_F77_FUNC(fcvdensesetjac, FCVDENSESETJAC)
-#define FCV_BAND           SUNDIALS_F77_FUNC(fcvband, FCVBAND)
 #define FCV_BANDSETJAC     SUNDIALS_F77_FUNC(fcvbandsetjac, FCVBANDSETJAC)
-#define FCV_LAPACKDENSE    SUNDIALS_F77_FUNC(fcvlapackdense, FCVLAPACKDENSE)
-#define FCV_LAPACKDENSESETJAC   SUNDIALS_F77_FUNC(fcvlapackdensesetjac, FCVLAPACKDENSESETJAC)
-#define FCV_LAPACKBAND     SUNDIALS_F77_FUNC(fcvlapackband, FCVLAPACKBAND)
-#define FCV_LAPACKBANDSETJAC    SUNDIALS_F77_FUNC(fcvlapackbandsetjac, FCVLAPACKBANDSETJAC)
-#define FCV_KLU            SUNDIALS_F77_FUNC(fcvklu, FCVKLU)
-#define FCV_KLUREINIT      SUNDIALS_F77_FUNC(fcvklureinit, FCVKLUREINIT)
-#define FCV_SUPERLUMT      SUNDIALS_F77_FUNC(fcvsuperlumt, FCVSUPERLUMT)
 #define FCV_SPARSESETJAC   SUNDIALS_F77_FUNC(fcvsparsesetjac, FCVSPARSESETJAC)  
-#define FCV_SPTFQMR        SUNDIALS_F77_FUNC(fcvsptfqmr, FCVSPTFQMR)
-#define FCV_SPTFQMRREINIT  SUNDIALS_F77_FUNC(fcvsptfqmrreinit, FCVSPTFQMRREINIT)
-#define FCV_SPBCG          SUNDIALS_F77_FUNC(fcvspbcg, FCVSPBCG)
-#define FCV_SPBCGREINIT    SUNDIALS_F77_FUNC(fcvspbcgreinit, FCVSPBCGREINIT)
-#define FCV_SPGMR          SUNDIALS_F77_FUNC(fcvspgmr, FCVSPGMR)
-#define FCV_SPGMRREINIT    SUNDIALS_F77_FUNC(fcvspgmrreinit, FCVSPGMRREINIT)
+#define FCV_SPILSINIT      SUNDIALS_F77_FUNC(fcvspilsinit, FCVSPILSINIT)
 #define FCV_SPILSSETJAC    SUNDIALS_F77_FUNC(fcvspilssetjac, FCVSPILSSETJAC)
 #define FCV_SPILSSETPREC   SUNDIALS_F77_FUNC(fcvspilssetprec, FCVSPILSSETPREC)
+#define FCV_DIAG           SUNDIALS_F77_FUNC(fcvdiag, FCVDIAG)
 #define FCV_CVODE          SUNDIALS_F77_FUNC(fcvode, FCVODE)
 #define FCV_DKY            SUNDIALS_F77_FUNC(fcvdky, FCVDKY)
 #define FCV_FREE           SUNDIALS_F77_FUNC(fcvfree, FCVFREE)
@@ -760,6 +924,7 @@ extern "C" {
 #define FCV_SPJAC          SUNDIALS_F77_FUNC(fcvspjac, FCVSPJAC)
 #define FCV_PSOL           SUNDIALS_F77_FUNC(fcvpsol, FCVPSOL)
 #define FCV_PSET           SUNDIALS_F77_FUNC(fcvpset, FCVPSET)
+#define FCV_JTSETUP        SUNDIALS_F77_FUNC(fcvjtsetup, FCVJTSETUP)
 #define FCV_JTIMES         SUNDIALS_F77_FUNC(fcvjtimes, FCVJTIMES)
 #define FCV_EWT            SUNDIALS_F77_FUNC(fcvewt, FCVEWT)
 #define FCV_GETERRWEIGHTS  SUNDIALS_F77_FUNC(fcvgeterrweights, FCVGETERRWEIGHTS)
@@ -772,27 +937,14 @@ extern "C" {
 #define FCV_SETIIN         fcvsetiin_
 #define FCV_SETRIN         fcvsetrin_
 #define FCV_EWTSET         fcvewtset_
-#define FCV_DIAG           fcvdiag_
-#define FCV_DENSE          fcvdense_
+#define FCV_DLSINIT        fcvdlsinit_
 #define FCV_DENSESETJAC    fcvdensesetjac_
-#define FCV_BAND           fcvband_
 #define FCV_BANDSETJAC     fcvbandsetjac_
-#define FCV_LAPACKDENSE    fcvlapackdense_
-#define FCV_LAPACKDENSESETJAC   fcvlapackdensesetjac_
-#define FCV_LAPACKBAND     fcvlapackband_
-#define FCV_LAPACKBANDSETJAC    fcvlapackbandsetjac_
-#define FCV_KLU            fcvklu_
-#define FCV_KLUREINIT      fcvklureinit_
-#define FCV_SUPERLUMT      fcvsuperlumt_
 #define FCV_SPARSESETJAC   fcvsparsesetjac_
-#define FCV_SPTFQMR        fcvsptfqmr_
-#define FCV_SPTFQMRREINIT  fcvsptfqmrreinit_
-#define FCV_SPBCG          fcvspbcg_
-#define FCV_SPBCGREINIT    fcvspbcgreinit_
-#define FCV_SPGMR          fcvspgmr_
-#define FCV_SPGMRREINIT    fcvspgmrreinit_
+#define FCV_SPILSINIT      fcvspilsinit_
 #define FCV_SPILSSETJAC    fcvspilssetjac_
 #define FCV_SPILSSETPREC   fcvspilssetprec_
+#define FCV_DIAG           fcvdiag_
 #define FCV_CVODE          fcvode_
 #define FCV_DKY            fcvdky_
 #define FCV_FREE           fcvfree_
@@ -802,6 +954,7 @@ extern "C" {
 #define FCV_SPJAC          fcvspjac_
 #define FCV_PSOL           fcvpsol_
 #define FCV_PSET           fcvpset_
+#define FCV_JTSETUP        fcvjtsetup_
 #define FCV_JTIMES         fcvjtimes_
 #define FCV_EWT            fcvewt_
 #define FCV_GETERRWEIGHTS  fcvgeterrweights_
@@ -835,36 +988,17 @@ extern "C" {
 
   void FCV_EWTSET(int *flag, int *ier);
 
-  void FCV_DIAG(int *ier);
-
-  void FCV_DENSE(long int *neq, int *ier);
+  void FCV_DLSINIT(int *ier);
   void FCV_DENSESETJAC(int *flag, int *ier);
-
-  void FCV_BAND(long int *neq, long int *mupper, long int *mlower, int *ier);
   void FCV_BANDSETJAC(int *flag, int *ier);
-
-  void FCV_LAPACKDENSE(int *neq, int *ier);
-  void FCV_LAPACKDENSESETJAC(int *flag, int *ier);
-  void FCV_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier);
-  void FCV_LAPACKBANDSETJAC(int *flag, int *ier);
-
-  void FCV_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier);
-  void FCV_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier);
-  void FCV_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier);
   void FCV_SPARSESETJAC(int *ier);
 
-  void FCV_SPGMR(int *pretype, int *gstype, int *maxl, realtype *delt, int *ier);
-  void FCV_SPGMRREINIT(int *pretype, int *gstype, realtype *delt, int *ier);
-
-  void FCV_SPBCG(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FCV_SPBCGREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
-
-  void FCV_SPTFQMR(int *pretype, int *maxl, realtype *delt, int *ier);
-  void FCV_SPTFQMRREINIT(int *pretype, int *maxl, realtype *delt, int *ier);
-
+  void FCV_SPILSINIT(int *ier);
   void FCV_SPILSSETJAC(int *flag, int *ier);
   void FCV_SPILSSETPREC(int *flag, int *ier);
   
+  void FCV_DIAG(int *ier);
+
   void FCV_CVODE(realtype *tout, realtype *t, realtype *y, int *itask, int *ier);
 
   void FCV_DKY(realtype *t, int *k, realtype *dky, int *ier);
@@ -879,37 +1013,27 @@ extern "C" {
   
   int FCVf(realtype t, N_Vector y, N_Vector ydot, void *user_data);
   
-  int FCVDenseJac(long int N, realtype t, 
-                  N_Vector y, N_Vector fy, 
-                  DlsMat J, void *user_data,
+  int FCVDenseJac(realtype t, N_Vector y, N_Vector fy, 
+                  SUNMatrix J, void *user_data,
                   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
   
-  int FCVBandJac(long int N, long int mupper, long int mlower,
-                 realtype t, N_Vector y, N_Vector fy,
-                 DlsMat J, void *user_data,
+  int FCVBandJac(realtype t, N_Vector y, N_Vector fy,
+                 SUNMatrix J, void *user_data,
                  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
   
-  int FCVLapackDenseJac(long int N, realtype t,
-                        N_Vector y, N_Vector fy, 
-                        DlsMat Jac, void *user_data,
-                        N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-  int FCVLapackBandJac(long int N, long int mupper, long int mlower,
-                       realtype t, N_Vector y, N_Vector fy, 
-                       DlsMat Jac, void *user_data,
-                       N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-  int FCVSparseJac(realtype t, N_Vector y, N_Vector fy, SlsMat J,
+  int FCVSparseJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
 		   void *user_data, N_Vector vtemp1,
 		   N_Vector vtemp2, N_Vector vtemp3);
 
   int FCVPSet(realtype tn, N_Vector y, N_Vector fy, booleantype jok,
-              booleantype *jcurPtr, realtype gamma, void *user_data,
-              N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+              booleantype *jcurPtr, realtype gamma, void *user_data);
   
   int FCVPSol(realtype tn, N_Vector y, N_Vector fy, 
               N_Vector r, N_Vector z,
               realtype gamma, realtype delta,
-              int lr, void *user_data, N_Vector vtemp);
+              int lr, void *user_data);
+  
+  int FCVJTSetup(realtype t, N_Vector y, N_Vector fy, void *user_data);
   
   int FCVJtimes(N_Vector v, N_Vector Jv, realtype t, 
                 N_Vector y, N_Vector fy,
@@ -919,7 +1043,9 @@ extern "C" {
 
   /* Declarations for global variables shared amongst various routines */
 
-  extern N_Vector F2C_CVODE_vec;   /* defined in FNVECTOR module */
+  extern N_Vector F2C_CVODE_vec;             /* defined in FNVECTOR module */
+  extern SUNMatrix F2C_CVODE_matrix;         /* defined in FSUNMATRIX module */
+  extern SUNLinearSolver F2C_CVODE_linsol;   /* defined in FSUNLINSOL module */
 
   extern void *CV_cvodemem;        /* defined in fcvode.c */
   extern long int *CV_iout;        /* defined in fcvode.c */
@@ -929,10 +1055,8 @@ extern "C" {
 
   /* Linear solver IDs */
 
-  enum { CV_LS_DENSE = 1, CV_LS_BAND = 2, CV_LS_DIAG = 3,
-         CV_LS_LAPACKDENSE = 4, CV_LS_LAPACKBAND = 5,
-	 CV_LS_KLU = 6, CV_LS_SUPERLUMT = 7, 
-	 CV_LS_SPGMR = 8, CV_LS_SPBCG = 9, CV_LS_SPTFQMR = 10 };
+  enum { CV_LS_ITERATIVE = 0, CV_LS_DIRECT = 1,
+         CV_LS_DIAG = 2, CV_LS_CUSTOM = 3 };
 
 #ifdef __cplusplus
 }
diff --git a/src/cvode/fcmix/fcvpreco.c b/src/cvode/fcmix/fcvpreco.c
index dcf4a80..43a8953 100644
--- a/src/cvode/fcmix/fcvpreco.c
+++ b/src/cvode/fcmix/fcvpreco.c
@@ -1,24 +1,26 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh, Radu Serban and
- *                Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *     Alan C. Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * The C function FCVPSet is to interface between the CVSP*
- * module and the user-supplied preconditioner setup routine FCVPSET.
- * Note the use of the generic name FCV_PSET below.
+ * The C functions FCVPSet and FCVPSol are to interface between the 
+ * CVSPILS module and the user-supplied preconditioner setup/solve
+ * routines FCVPSET and FCVPSOL. Note the use of the generic names
+ * FCV_PSET and FCV_PSOL below.
  * -----------------------------------------------------------------
  */
 
@@ -38,20 +40,16 @@
 extern "C" {
 #endif
 
-  extern void FCV_PSET(realtype*, realtype*, realtype*,  /* T, Y, FY */
-                       booleantype*, booleantype*,       /* JOK, JCUR */
-                       realtype*, realtype*,             /* GAMMA, H */
-                       long int*, realtype*,             /* IPAR, RPAR */
-                       realtype*, realtype*, realtype*,  /* W1, W2, W3 */
-                       int*);                            /* IER */
-
-  extern void FCV_PSOL(realtype*, realtype*, realtype*,  /* T, Y, FY */
-                       realtype*, realtype*,             /* R, Z */
-                       realtype*, realtype*,             /* GAMMA, DELTA */
-                       int*,                             /* LR */
-                       long int*, realtype*,             /* IPAR, RPAR */
-                       realtype*,                        /* WRK */
-                       int*);                            /* IER */
+  extern void FCV_PSET(realtype *T, realtype *Y, realtype *FY,
+			booleantype *JOK, booleantype *JCUR,
+			realtype *GAMMA, realtype *H,
+			long int *IPAR, realtype *RPAR, int *IER);
+
+  extern void FCV_PSOL(realtype *T, realtype *Y, realtype *FY,
+			realtype *R, realtype *Z, 
+			realtype *GAMMA, realtype *DELTA,
+			int *LR, long int *IPAR, realtype *RPAR, 
+                        int *IER);
 
 #ifdef __cplusplus
 }
@@ -80,11 +78,10 @@ void FCV_SPILSSETPREC(int *flag, int *ier)
 
 int FCVPSet(realtype t, N_Vector y, N_Vector fy, booleantype jok,
             booleantype *jcurPtr, realtype gamma,
-            void *user_data,
-            N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+            void *user_data)
 {
   int ier = 0;
-  realtype *ydata, *fydata, *v1data, *v2data, *v3data;
+  realtype *ydata, *fydata;
   realtype h;
   FCVUserData CV_userdata;
 
@@ -92,15 +89,11 @@ int FCVPSet(realtype t, N_Vector y, N_Vector fy, booleantype jok,
 
   ydata   = N_VGetArrayPointer(y);
   fydata  = N_VGetArrayPointer(fy);
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
 
   CV_userdata = (FCVUserData) user_data;
 
   FCV_PSET(&t, ydata, fydata, &jok, jcurPtr, &gamma, &h,
-           CV_userdata->ipar, CV_userdata->rpar,
-           v1data, v2data, v3data, &ier);
+           CV_userdata->ipar, CV_userdata->rpar, &ier);
 
   return(ier);
 }
@@ -117,22 +110,21 @@ int FCVPSet(realtype t, N_Vector y, N_Vector fy, booleantype jok,
 int FCVPSol(realtype t, N_Vector y, N_Vector fy, 
             N_Vector r, N_Vector z,
             realtype gamma, realtype delta,
-            int lr, void *user_data, N_Vector vtemp)
+            int lr, void *user_data)
 {
   int ier = 0;
-  realtype *ydata, *fydata, *vtdata, *rdata, *zdata;
+  realtype *ydata, *fydata, *rdata, *zdata;
   FCVUserData CV_userdata;
 
   ydata   = N_VGetArrayPointer(y);
   fydata  = N_VGetArrayPointer(fy);
-  vtdata  = N_VGetArrayPointer(vtemp);
   rdata   = N_VGetArrayPointer(r);
   zdata   = N_VGetArrayPointer(z);
 
   CV_userdata = (FCVUserData) user_data;
 
   FCV_PSOL(&t, ydata, fydata, rdata, zdata, &gamma, &delta, &lr, 
-           CV_userdata->ipar, CV_userdata->rpar, vtdata, &ier);
+           CV_userdata->ipar, CV_userdata->rpar, &ier);
 
   return(ier);
 }
diff --git a/src/cvode/fcmix/fcvroot.c b/src/cvode/fcmix/fcvroot.c
index 44eb352..34557d4 100644
--- a/src/cvode/fcmix/fcvroot.c
+++ b/src/cvode/fcmix/fcvroot.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -35,9 +32,9 @@
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
-  extern void FCV_ROOTFN(realtype *, realtype*, realtype*,  /* T, Y, G    */
-                         long int*, realtype*,              /* IPAR, RPAR */
-                         int *ier);                         /* IER        */
+  extern void FCV_ROOTFN(realtype *T, realtype *Y, realtype *G,
+                         long int *IPAR, realtype *RPAR,
+                         int *ier);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/cvode/fcmix/fcvroot.h b/src/cvode/fcmix/fcvroot.h
index 8ee21b0..e047679 100644
--- a/src/cvode/fcmix/fcvroot.h
+++ b/src/cvode/fcmix/fcvroot.h
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Aaron Collier @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -56,7 +53,7 @@
  *   T = independent variable value t  [input]
  *   Y = dependent variable vector y  [input]
  *   G = function values g(t,y)  [output]
- *   IPAR, RPAR = user (integer and real) data [input/output]
+ *   IPAR, RPAR = user (long int and realtype) data [input/output]
  *   IER = return flag (0 for success, a non-zero value if an error occurred.)
  *
  * 2. After calling FCVMALLOC but prior to calling FCVODE, the user must
diff --git a/src/cvode/fcmix/fcvsparse.c b/src/cvode/fcmix/fcvsparse.c
index 9dab7bc..21fb9b9 100644
--- a/src/cvode/fcmix/fcvsparse.c
+++ b/src/cvode/fcmix/fcvsparse.c
@@ -1,20 +1,21 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4815 $
- * $Date: 2016-07-20 16:51:55 -0700 (Wed, 20 Jul 2016) $
+ * Programmer(s): Daniel R. Reynolds and Ting Yan @ SMU
+ *     Carol Woodward @ LLNL
  * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL
- *                Ting Yan and Daniel R. Reynolds @ SMU
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  */
 
@@ -22,7 +23,8 @@
 #include <stdlib.h>
 #include "fcvode.h"
 #include "cvode_impl.h"
-#include <cvode/cvode_sparse.h>
+#include <cvode/cvode_direct.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
 /* Prototype of the Fortran routine */
  
@@ -31,12 +33,13 @@ extern "C" {
 #endif
  
 extern void FCV_SPJAC(realtype *T, realtype *Y, 
-		       realtype *FY, int *N, int *NNZ, 
-		       realtype *JDATA, int *JRVALS, 
-		       int *JCPTRS, realtype *H, 
-		       long int *IPAR, realtype *RPAR, 
-		       realtype *V1, realtype *V2, 
-		       realtype *V3, int *ier);
+                      realtype *FY, long int *N,
+                      long int *NNZ, realtype *JDATA,
+                      long int *JRVALS, 
+                      long int *JCPTRS, realtype *H, 
+		      long int *IPAR, realtype *RPAR, 
+                      realtype *V1, realtype *V2, 
+                      realtype *V3, int *ier);
  
 #ifdef __cplusplus
 }
@@ -48,7 +51,14 @@ extern void FCV_SPJAC(realtype *T, realtype *Y,
    fcvode.h for further information */
 void FCV_SPARSESETJAC(int *ier)
 {
-  *ier = CVSlsSetSparseJacFn(CV_cvodemem, FCVSparseJac);
+#if defined(SUNDIALS_INT32_T)
+  cvProcessError((CVodeMem) CV_cvodemem, CV_ILL_INPUT, "CVODE",
+                  "FCVSPARSESETJAC", 
+                  "Sparse Fortran users must configure SUNDIALS with 64-bit integers.");
+  *ier = 1;
+#else  
+  *ier = CVDlsSetJacFn(CV_cvodemem, FCVSparseJac);
+#endif
 }
 
 /*=============================================================*/
@@ -56,12 +66,13 @@ void FCV_SPARSESETJAC(int *ier)
 /* C interface to user-supplied Fortran routine FCVSPJAC; see 
    fcvode.h for additional information  */
 int FCVSparseJac(realtype t, N_Vector y, N_Vector fy, 
-		 SlsMat J, void *user_data, N_Vector vtemp1, 
+		 SUNMatrix J, void *user_data, N_Vector vtemp1, 
 		 N_Vector vtemp2, N_Vector vtemp3)
 {
   int ier;
-  realtype *ydata, *fydata, *v1data, *v2data, *v3data;
+  realtype *ydata, *fydata, *v1data, *v2data, *v3data, *Jdata;
   realtype h;
+  long int NP, NNZ, *indexvals, *indexptrs; 
   FCVUserData CV_userdata;
 
   CVodeGetLastStep(CV_cvodemem, &h);
@@ -71,11 +82,15 @@ int FCVSparseJac(realtype t, N_Vector y, N_Vector fy,
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
   CV_userdata = (FCVUserData) user_data;
+  NP = SUNSparseMatrix_NP(J);
+  NNZ = SUNSparseMatrix_NNZ(J);
+  Jdata = SUNSparseMatrix_Data(J);
+  indexvals = SUNSparseMatrix_IndexValues(J);
+  indexptrs = SUNSparseMatrix_IndexPointers(J);
 
-  FCV_SPJAC(&t, ydata, fydata, &(J->NP), &(J->NNZ),
-	    J->data, J->indexvals, J->indexptrs, &h, 
-	    CV_userdata->ipar, CV_userdata->rpar, v1data, 
-	    v2data, v3data, &ier); 
+  FCV_SPJAC(&t, ydata, fydata, &NP, &NNZ, Jdata, indexvals, 
+	    indexptrs, &h, CV_userdata->ipar, CV_userdata->rpar,
+            v1data, v2data, v3data, &ier); 
   return(ier);
 }
 
diff --git a/src/cvode/fcmix/fcvsuperlumt.c b/src/cvode/fcmix/fcvsuperlumt.c
deleted file mode 100644
index eec7fbd..0000000
--- a/src/cvode/fcmix/fcvsuperlumt.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4402 $
- * $Date: 2015-02-28 19:35:39 -0800 (Sat, 28 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the Fortran interface to
- * the CVSuperLUMT solver. See fcvode.h for usage.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "fcvode.h"
-#include "cvode_impl.h"
-#include <cvode/cvode_superlumt.h>
- 
-/*
- * ----------------------------------------------------------------
- * Function : FCV_SUPERLUMT
- * ----------------------------------------------------------------
- */
-
-void FCV_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier)
-{
-  *ier = CVSuperLUMT(CV_cvodemem, *nthreads, *neq, *nnz);
-  CVSuperLUMTSetOrdering(CV_cvodemem, *ordering);
-  CV_ls = CV_LS_SUPERLUMT;
-}
-
-
diff --git a/src/cvodes/CMakeLists.txt b/src/cvodes/CMakeLists.txt
index 38229df..77367bb 100644
--- a/src/cvodes/CMakeLists.txt
+++ b/src/cvodes/CMakeLists.txt
@@ -1,18 +1,20 @@
 # ---------------------------------------------------------------
-# $Revision: 4759 $
-# $Date: 2016-05-18 16:25:17 -0700 (Wed, 18 May 2016) $
+# Programmer(s):  Daniel R. Reynolds @ SMU
+#                 Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
-# ---------------------------------------------------------------
-# LLNS Copyright Start
-# Copyright (c) 2014, Lawrence Livermore National Security
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
 # This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
-# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
-# Produced at the Lawrence Livermore National Laboratory.
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
-# LLNS Copyright End
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the CVODES library
 
@@ -20,87 +22,65 @@ INSTALL(CODE "MESSAGE(\"\nInstall CVODES\n\")")
 
 # Add variable cvodes_SOURCES with the sources for the CVODES library
 SET(cvodes_SOURCES
-  cvodes.c
   cvodea.c
-  cvodes_io.c
   cvodea_io.c
-  cvodes_direct.c
-  cvodes_band.c
-  cvodes_dense.c
-  cvodes_diag.c
-  cvodes_sparse.c
-  cvodes_spils.c
-  cvodes_spbcgs.c
-  cvodes_spgmr.c
-  cvodes_sptfqmr.c
+  cvodes.c
   cvodes_bandpre.c
   cvodes_bbdpre.c
+  cvodes_io.c
+  cvodes_diag.c
+  cvodes_direct.c
+  cvodes_spils.c
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND cvodes_SOURCES cvodes_klu.c)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND cvodes_SOURCES cvodes_superlumt.c)
-ENDIF()
-
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the CVODES library
 SET(shared_SOURCES
-  sundials_nvector.c
-  sundials_math.c
-  sundials_direct.c
-  sundials_band.c
-  sundials_dense.c
-  sundials_iterative.c
-  sundials_sparse.c
-  sundials_spbcgs.c
-  sundials_spgmr.c
-  sundials_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_band.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_dense.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_direct.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_version.c
+  ${sundials_SOURCE_DIR}/src/nvec_ser/nvector_serial.c
   )
 
-# Add prefix with complete path to the common SUNDIALS sources
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the CVODES library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/sunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/sunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/sunmatrix_sparse.c
+  )
+
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the CVODES library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/sunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/sunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/sunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/sunlinsol_pcg.c
+  )
 
 # Add variable cvodes_HEADERS with the exported CVODES header files
 SET(cvodes_HEADERS
-  cvodes_band.h
+  cvodes.h
   cvodes_bandpre.h
   cvodes_bbdpre.h
-  cvodes_dense.h
   cvodes_diag.h
   cvodes_direct.h
-  cvodes.h
-  cvodes_sparse.h
-  cvodes_spbcgs.h
-  cvodes_spgmr.h
   cvodes_spils.h
-  cvodes_sptfqmr.h
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND cvodes_HEADERS cvodes_klu.h)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND cvodes_HEADERS cvodes_superlumt.h)
-ENDIF()
-
 # Add prefix with complete path to the CVODES header files
 ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvodes/ cvodes_HEADERS)
 
-# If Blas/Lapack support was enabled, set-up additional file lists
-IF(LAPACK_FOUND)
-  SET(cvodes_BL_SOURCES cvodes_lapack.c)
-  SET(cvodes_BL_HEADERS cvodes_lapack.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/cvodes/ cvodes_BL_HEADERS)
-ELSE(LAPACK_FOUND)
-  SET(cvodes_BL_SOURCES "")
-  SET(cvodes_BL_HEADERS "")
-ENDIF(LAPACK_FOUND)
-
-
 # Add source directories to include directories for access to
 # implementation only header files.
 INCLUDE_DIRECTORIES(.)
@@ -114,7 +94,7 @@ IF(BUILD_STATIC_LIBS)
 
   # Add the build target for the static CVODES library
   ADD_LIBRARY(sundials_cvodes_static STATIC 
-    ${cvodes_SOURCES}  ${cvodes_BL_SOURCES}  ${shared_SOURCES})
+    ${cvodes_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_cvodes_static
@@ -130,7 +110,11 @@ IF(BUILD_SHARED_LIBS)
 
   # Add the build target for the CVODES library
   ADD_LIBRARY(sundials_cvodes_shared SHARED 
-    ${cvodes_SOURCES}  ${cvodes_BL_SOURCES}  ${shared_SOURCES})
+    ${cvodes_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_cvodes_shared m)
+  ENDIF()
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_cvodes_shared
@@ -146,7 +130,7 @@ IF(BUILD_SHARED_LIBS)
 ENDIF(BUILD_SHARED_LIBS)
 
 # Install the CVODES header files
-INSTALL(FILES ${cvodes_HEADERS}  ${cvodes_BL_HEADERS} DESTINATION include/cvodes)
+INSTALL(FILES ${cvodes_HEADERS} DESTINATION include/cvodes)
 
 # Install the CVODES implementation header file
 INSTALL(FILES cvodes_impl.h DESTINATION include/cvodes)
diff --git a/src/cvodes/README b/src/cvodes/README
index cdebabc..78ce79e 100644
--- a/src/cvodes/README
+++ b/src/cvodes/README
@@ -1,5 +1,5 @@
                            CVODES 
-                 Release 2.9.0, September, 2016
+                 Release 3.1.0, November 2017
                Alan C. Hindmarsh and Radu Serban
           Center for Applied Scientific Computing, LLNL
 
@@ -72,6 +72,8 @@ C. References
 D. Releases
 -----------
 
+v. 3.1.0   - Nov. 2017
+v. 3.0.0   - Sep. 2017
 v. 2.9.0   - Sep. 2016
 v. 2.8.2   - Aug. 2015
 v. 2.8.1   - Mar. 2015
diff --git a/src/cvodes/cvodea.c b/src/cvodes/cvodea.c
index d218fe7..629ee1a 100644
--- a/src/cvodes/cvodea.c
+++ b/src/cvodes/cvodea.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4846 $
- * $Date: 2016-08-03 15:47:48 -0700 (Wed, 03 Aug 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -35,14 +35,6 @@
 
 /* 
  * =================================================================
- * MACRO DEFINITIONS
- * =================================================================
- */
-
-#define loop for(;;)
-
-/* 
- * =================================================================
  * CVODEA PRIVATE CONSTANTS
  * =================================================================
  */
@@ -216,16 +208,16 @@ int CVodeAdjInit(void *cvode_mem, long int steps, int interp)
 
   /* The interpolation module has not been initialized yet */
 
-  ca_mem->ca_IMmallocDone = FALSE;
+  ca_mem->ca_IMmallocDone = SUNFALSE;
 
   /* By default we will store but not interpolate sensitivities
-   *  - IMstoreSensi will be set in CVodeF to FALSE if FSA is not enabled
+   *  - IMstoreSensi will be set in CVodeF to SUNFALSE if FSA is not enabled
    *    or if the user can force this through CVodeSetAdjNoSensi 
-   *  - IMinterpSensi will be set in CVodeB to TRUE if IMstoreSensi is
-   *    TRUE and if at least one backward problem requires sensitivities */
+   *  - IMinterpSensi will be set in CVodeB to SUNTRUE if IMstoreSensi is
+   *    SUNTRUE and if at least one backward problem requires sensitivities */
 
-  ca_mem->ca_IMstoreSensi = TRUE;
-  ca_mem->ca_IMinterpSensi = FALSE;
+  ca_mem->ca_IMstoreSensi = SUNTRUE;
+  ca_mem->ca_IMinterpSensi = SUNFALSE;
 
   /* ------------------------------------
    * Initialize list of backward problems
@@ -239,17 +231,17 @@ int CVodeAdjInit(void *cvode_mem, long int steps, int interp)
    * CVodeF and CVodeB not called yet
    * -------------------------------- */
 
-  ca_mem->ca_firstCVodeFcall = TRUE;
-  ca_mem->ca_tstopCVodeFcall = FALSE;
+  ca_mem->ca_firstCVodeFcall = SUNTRUE;
+  ca_mem->ca_tstopCVodeFcall = SUNFALSE;
 
-  ca_mem->ca_firstCVodeBcall = TRUE;
+  ca_mem->ca_firstCVodeBcall = SUNTRUE;
 
   /* ---------------------------------------------
    * ASA initialized and allocated
    * --------------------------------------------- */
 
-  cv_mem->cv_adj = TRUE;
-  cv_mem->cv_adjMallocDone = TRUE;
+  cv_mem->cv_adj = SUNTRUE;
+  cv_mem->cv_adjMallocDone = SUNTRUE;
 
   return(CV_SUCCESS);
 } 
@@ -282,7 +274,7 @@ int CVodeAdjReInit(void *cvode_mem)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeAdjReInit", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -301,9 +293,9 @@ int CVodeAdjReInit(void *cvode_mem)
 
   /* CVodeF and CVodeB not called yet */
  
-  ca_mem->ca_firstCVodeFcall = TRUE;
-  ca_mem->ca_tstopCVodeFcall = FALSE;
-  ca_mem->ca_firstCVodeBcall = TRUE;
+  ca_mem->ca_firstCVodeFcall = SUNTRUE;
+  ca_mem->ca_tstopCVodeFcall = SUNFALSE;
+  ca_mem->ca_firstCVodeBcall = SUNTRUE;
 
   return(CV_SUCCESS);
 }
@@ -352,108 +344,6 @@ void CVodeAdjFree(void *cvode_mem)
 
 }
 
-/* 
- * -----------------------------------------------------------------
- * Readibility Constants
- * -----------------------------------------------------------------
- */
-
-#define tinitial    (ca_mem->ca_tinitial)
-#define tfinal      (ca_mem->ca_tfinal)
-#define nckpnts     (ca_mem->ca_nckpnts)
-#define nsteps      (ca_mem->ca_nsteps)
-#define nbckpbs     (ca_mem->ca_nbckpbs)
-#define ckpntData   (ca_mem->ca_ckpntData)
-#define np          (ca_mem->ca_np)
-#define ytmp        (ca_mem->ca_ytmp)
-#define yStmp       (ca_mem->ca_yStmp)
-#define Y           (ca_mem->ca_Y)
-#define YS          (ca_mem->ca_YS)
-#define T           (ca_mem->ca_T)
-
-#define IMmalloc      (ca_mem->ca_IMmalloc)
-#define IMfree        (ca_mem->ca_IMfree)
-#define IMget         (ca_mem->ca_IMget)
-#define IMstore       (ca_mem->ca_IMstore)
-#define IMmallocDone  (ca_mem->ca_IMmallocDone)
-#define IMstoreSensi  (ca_mem->ca_IMstoreSensi)
-#define IMinterpSensi (ca_mem->ca_IMinterpSensi)
-#define IMnewData     (ca_mem->ca_IMnewData)
-
-#define uround     (cv_mem->cv_uround)
-#define zn         (cv_mem->cv_zn)
-#define nst        (cv_mem->cv_nst)
-#define q          (cv_mem->cv_q)
-#define qu         (cv_mem->cv_qu)
-#define qprime     (cv_mem->cv_qprime)
-#define qwait      (cv_mem->cv_qwait)
-#define L          (cv_mem->cv_L)
-#define gammap     (cv_mem->cv_gammap)
-#define h          (cv_mem->cv_h)
-#define hprime     (cv_mem->cv_hprime)
-#define hscale     (cv_mem->cv_hscale)
-#define eta        (cv_mem->cv_eta)
-#define etamax     (cv_mem->cv_etamax)
-#define tn         (cv_mem->cv_tn)
-#define tretlast   (cv_mem->cv_tretlast)
-#define tau        (cv_mem->cv_tau)
-#define tq         (cv_mem->cv_tq)
-#define l          (cv_mem->cv_l)
-#define saved_tq5  (cv_mem->cv_saved_tq5)
-#define forceSetup (cv_mem->cv_forceSetup)
-#define f          (cv_mem->cv_f)
-#define lmm        (cv_mem->cv_lmm)
-#define iter       (cv_mem->cv_iter)
-#define reltol     (cv_mem->cv_reltol)
-#define user_data  (cv_mem->cv_user_data)
-#define errfp      (cv_mem->cv_errfp)
-#define h0u        (cv_mem->cv_h0u)
-#define tempv      (cv_mem->cv_tempv)
-
-#define quadr      (cv_mem->cv_quadr)
-#define errconQ    (cv_mem->cv_errconQ)
-#define znQ        (cv_mem->cv_znQ)
-#define tempvQ     (cv_mem->cv_tempvQ)
-
-#define sensi      (cv_mem->cv_sensi)
-#define Ns         (cv_mem->cv_Ns)
-#define errconS    (cv_mem->cv_errconS)
-#define znS        (cv_mem->cv_znS)
-
-#define quadr_sensi (cv_mem->cv_quadr_sensi)
-#define errconQS    (cv_mem->cv_errconQS)
-#define znQS        (cv_mem->cv_znQS)
-
-#define t0_        (ck_mem->ck_t0)
-#define t1_        (ck_mem->ck_t1)
-#define zn_        (ck_mem->ck_zn)
-#define znQ_       (ck_mem->ck_znQ)
-#define znS_       (ck_mem->ck_znS)
-#define znQS_      (ck_mem->ck_znQS)
-#define quadr_     (ck_mem->ck_quadr)
-#define sensi_     (ck_mem->ck_sensi)
-#define quadr_sensi_ (ck_mem->ck_quadr_sensi)
-#define Ns_        (ck_mem->ck_Ns)
-#define zqm_       (ck_mem->ck_zqm)
-#define nst_       (ck_mem->ck_nst)
-#define tretlast_  (ck_mem->ck_tretlast)
-#define q_         (ck_mem->ck_q)
-#define qprime_    (ck_mem->ck_qprime)
-#define qwait_     (ck_mem->ck_qwait)
-#define L_         (ck_mem->ck_L)
-#define gammap_    (ck_mem->ck_gammap)
-#define h_         (ck_mem->ck_h)
-#define hprime_    (ck_mem->ck_hprime)
-#define hscale_    (ck_mem->ck_hscale)
-#define eta_       (ck_mem->ck_eta)
-#define etamax_    (ck_mem->ck_etamax)
-#define tau_       (ck_mem->ck_tau)
-#define tq_        (ck_mem->ck_tq)
-#define l_         (ck_mem->ck_l)
-#define saved_tq5_ (ck_mem->ck_saved_tq5)
-#define next_      (ck_mem->ck_next)
-
-
 /*
  * CVodeF
  *
@@ -483,7 +373,7 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeF", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -514,14 +404,14 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
 
   /* If tstop is enabled, store some info */
   if (cv_mem->cv_tstopset) {
-    ca_mem->ca_tstopCVodeFcall = TRUE;
+    ca_mem->ca_tstopCVodeFcall = SUNTRUE;
     ca_mem->ca_tstopCVodeF = cv_mem->cv_tstop;
   }
 
   /* We will call CVode in CV_ONE_STEP mode, regardless
    * of what itask is, so flag if we need to return */
-  if (itask == CV_ONE_STEP) iret = TRUE;
-  else                      iret = FALSE;
+  if (itask == CV_ONE_STEP) iret = SUNTRUE;
+  else                      iret = SUNFALSE;
 
   /* On the first step:
    *   - set tinitial
@@ -532,7 +422,7 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
    */
   if ( ca_mem->ca_firstCVodeFcall ) {
 
-    tinitial = tn;
+    ca_mem->ca_tinitial = cv_mem->cv_tn;
 
     ca_mem->ck_mem = CVAckpntInit(cv_mem);
     if (ca_mem->ck_mem == NULL) {
@@ -540,50 +430,50 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
       return(CV_MEM_FAIL);
     }
 
-    if ( !IMmallocDone ) {
+    if ( !ca_mem->ca_IMmallocDone ) {
 
       /* Do we need to store sensitivities? */
-      if (!sensi) IMstoreSensi = FALSE;
+      if (!cv_mem->cv_sensi) ca_mem->ca_IMstoreSensi = SUNFALSE;
 
       /* Allocate space for interpolation data */
-      allocOK = IMmalloc(cv_mem);
+      allocOK = ca_mem->ca_IMmalloc(cv_mem);
       if (!allocOK) {
         cvProcessError(cv_mem, CV_MEM_FAIL, "CVODEA", "CVodeF", MSGCV_MEM_FAIL);
         return(CV_MEM_FAIL);
       }
 
       /* Rename zn and, if needed, znS for use in interpolation */
-      for (i=0;i<L_MAX;i++) Y[i] = zn[i];
-      if (IMstoreSensi) {
-        for (i=0;i<L_MAX;i++) YS[i] = znS[i];
+      for (i=0;i<L_MAX;i++) ca_mem->ca_Y[i] = cv_mem->cv_zn[i];
+      if (ca_mem->ca_IMstoreSensi) {
+        for (i=0;i<L_MAX;i++) ca_mem->ca_YS[i] = cv_mem->cv_znS[i];
       }
 
-      IMmallocDone = TRUE;
+      ca_mem->ca_IMmallocDone = SUNTRUE;
 
     }
 
     dt_mem[0]->t = ca_mem->ck_mem->ck_t0;
-    IMstore(cv_mem, dt_mem[0]);
+    ca_mem->ca_IMstore(cv_mem, dt_mem[0]);
 
-    ca_mem->ca_firstCVodeFcall = FALSE;
+    ca_mem->ca_firstCVodeFcall = SUNFALSE;
 
-  } else if ( (tn - tout)*h >= ZERO ) {
+  } else if ( (cv_mem->cv_tn - tout)*cv_mem->cv_h >= ZERO ) {
 
     /* If tout was passed, return interpolated solution. 
        No changes to ck_mem or dt_mem are needed. */
     *tret = tout;
     flag = CVodeGetDky(cv_mem, tout, 0, yout);
-    *ncheckPtr = nckpnts;
-    IMnewData = TRUE;
-    ckpntData = ca_mem->ck_mem;
-    np = nst % nsteps + 1;
+    *ncheckPtr = ca_mem->ca_nckpnts;
+    ca_mem->ca_IMnewData = SUNTRUE;
+    ca_mem->ca_ckpntData = ca_mem->ck_mem;
+    ca_mem->ca_np = cv_mem->cv_nst % ca_mem->ca_nsteps + 1;
 
     return(flag);
 
   }
 
   /* Integrate to tout (in CV_ONE_STEP mode) while loading check points */
-  loop {
+  for(;;) {
 
     /* Perform one step of the integration */
 
@@ -592,7 +482,7 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
 
     /* Test if a new check point is needed */
 
-    if ( nst % nsteps == 0 ) {
+    if ( cv_mem->cv_nst % ca_mem->ca_nsteps == 0 ) {
 
       ca_mem->ck_mem->ck_t1 = *tret;
 
@@ -605,18 +495,18 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
       }
       tmp->ck_next = ca_mem->ck_mem;
       ca_mem->ck_mem = tmp;
-      nckpnts++;
-      forceSetup = TRUE;
+      ca_mem->ca_nckpnts++;
+      cv_mem->cv_forceSetup = SUNTRUE;
       
       /* Reset i=0 and load dt_mem[0] */
       dt_mem[0]->t = ca_mem->ck_mem->ck_t0;
-      IMstore(cv_mem, dt_mem[0]);
+      ca_mem->ca_IMstore(cv_mem, dt_mem[0]);
 
     } else {
 
       /* Load next point in dt_mem */
-      dt_mem[nst%nsteps]->t = *tret;
-      IMstore(cv_mem, dt_mem[nst%nsteps]);
+      dt_mem[cv_mem->cv_nst % ca_mem->ca_nsteps]->t = *tret;
+      ca_mem->ca_IMstore(cv_mem, dt_mem[cv_mem->cv_nst % ca_mem->ca_nsteps]);
 
     }
 
@@ -626,13 +516,13 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
     ca_mem->ck_mem->ck_t1 = *tret;
 
     /* tfinal is now set to *tret */
-    tfinal = *tret;
+    ca_mem->ca_tfinal = *tret;
 
     /* Return if in CV_ONE_STEP mode */
     if (iret) break;
 
     /* Return if tout reached */
-    if ( (*tret - tout)*h >= ZERO ) {
+    if ( (*tret - tout)*cv_mem->cv_h >= ZERO ) {
       *tret = tout;
       CVodeGetDky(cv_mem, tout, 0, yout);
       /* Reset tretlast in cv_mem so that CVodeGetQuad and CVodeGetSens 
@@ -641,15 +531,15 @@ int CVodeF(void *cvode_mem, realtype tout, N_Vector yout,
       break;
     }
 
-  } /* end of loop() */
+  } /* end of for(;;)() */
 
   /* Get ncheck from ca_mem */ 
-  *ncheckPtr = nckpnts;
+  *ncheckPtr = ca_mem->ca_nckpnts;
 
   /* Data is available for the last interval */
-  IMnewData = TRUE;
-  ckpntData = ca_mem->ck_mem;
-  np = nst % nsteps + 1;
+  ca_mem->ca_IMnewData = SUNTRUE;
+  ca_mem->ca_ckpntData = ca_mem->ck_mem;
+  ca_mem->ca_np = cv_mem->cv_nst % ca_mem->ca_nsteps + 1;
 
   return(flag);
 }
@@ -678,7 +568,7 @@ int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeCreateB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   }
@@ -710,7 +600,7 @@ int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which)
 
   /* Set/initialize fields in the new CVodeBMem object, new_cvB_mem */
 
-  new_cvB_mem->cv_index   = nbckpbs;
+  new_cvB_mem->cv_index   = ca_mem->ca_nbckpbs;
 
   new_cvB_mem->cv_mem     = (CVodeMem) cvodeB_mem;
 
@@ -729,8 +619,8 @@ int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which)
 
   new_cvB_mem->cv_y       = NULL;
 
-  new_cvB_mem->cv_f_withSensi = FALSE;
-  new_cvB_mem->cv_fQ_withSensi = FALSE;
+  new_cvB_mem->cv_f_withSensi = SUNFALSE;
+  new_cvB_mem->cv_fQ_withSensi = SUNFALSE;
 
   /* Attach the new object to the linked list cvB_mem */
 
@@ -741,9 +631,9 @@ int CVodeCreateB(void *cvode_mem, int lmmB, int iterB, int *which)
    * This must be passed to CVodeInitB and to other ***B 
    * functions to set optional inputs for this backward problem */
 
-  *which = nbckpbs;
+  *which = ca_mem->ca_nbckpbs;
 
-  nbckpbs++;
+  ca_mem->ca_nbckpbs++;
 
   return(CV_SUCCESS);
 }
@@ -768,7 +658,7 @@ int CVodeInitB(void *cvode_mem, int which,
 
   /* Was ASA initialized? */
 
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeInitB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -776,7 +666,7 @@ int CVodeInitB(void *cvode_mem, int which,
 
   /* Check the value of which */
 
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeInitB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -799,7 +689,7 @@ int CVodeInitB(void *cvode_mem, int which,
 
   /* Copy fB function in cvB_mem */
 
-  cvB_mem->cv_f_withSensi = FALSE;
+  cvB_mem->cv_f_withSensi = SUNFALSE;
   cvB_mem->cv_f = fB;
 
   /* Allocate space and initialize the y Nvector in cvB_mem */
@@ -831,7 +721,7 @@ int CVodeInitBS(void *cvode_mem, int which,
 
   /* Was ASA initialized? */
 
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeInitBS", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -839,7 +729,7 @@ int CVodeInitBS(void *cvode_mem, int which,
 
   /* Check the value of which */
 
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeInitBS", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -862,7 +752,7 @@ int CVodeInitBS(void *cvode_mem, int which,
 
   /* Copy fBs function in cvB_mem */
 
-  cvB_mem->cv_f_withSensi = TRUE;
+  cvB_mem->cv_f_withSensi = SUNTRUE;
   cvB_mem->cv_fs = fBs;
 
   /* Allocate space and initialize the y Nvector in cvB_mem */
@@ -892,14 +782,14 @@ int CVodeReInitB(void *cvode_mem, int which,
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeReInitB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   }
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeReInitB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -939,7 +829,7 @@ int CVodeSStolerancesB(void *cvode_mem, int which, realtype reltolB, realtype ab
 
   /* Was ASA initialized? */
 
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSStolerancesB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -947,7 +837,7 @@ int CVodeSStolerancesB(void *cvode_mem, int which, realtype reltolB, realtype ab
 
   /* Check the value of which */
 
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSStolerancesB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -988,7 +878,7 @@ int CVodeSVtolerancesB(void *cvode_mem, int which, realtype reltolB, N_Vector ab
 
   /* Was ASA initialized? */
 
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSVtolerancesB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -996,7 +886,7 @@ int CVodeSVtolerancesB(void *cvode_mem, int which, realtype reltolB, N_Vector ab
 
   /* Check the value of which */
 
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSVtolerancesB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1036,14 +926,14 @@ int CVodeQuadInitB(void *cvode_mem, int which,
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadInitB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadInitB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1060,7 +950,7 @@ int CVodeQuadInitB(void *cvode_mem, int which,
   flag = CVodeQuadInit(cvodeB_mem, CVArhsQ, yQB0);
   if (flag != CV_SUCCESS) return(flag);
 
-  cvB_mem->cv_fQ_withSensi = FALSE;
+  cvB_mem->cv_fQ_withSensi = SUNFALSE;
   cvB_mem->cv_fQ = fQB;
 
   return(CV_SUCCESS);
@@ -1083,14 +973,14 @@ int CVodeQuadInitBS(void *cvode_mem, int which,
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadInitBS", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadInitBS", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1107,7 +997,7 @@ int CVodeQuadInitBS(void *cvode_mem, int which,
   flag = CVodeQuadInit(cvodeB_mem, CVArhsQ, yQB0);
   if (flag != CV_SUCCESS) return(flag);
 
-  cvB_mem->cv_fQ_withSensi = TRUE;
+  cvB_mem->cv_fQ_withSensi = SUNTRUE;
   cvB_mem->cv_fQs = fQBs;
 
   return(CV_SUCCESS);
@@ -1129,14 +1019,14 @@ int CVodeQuadReInitB(void *cvode_mem, int which, N_Vector yQB0)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadReInitB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadReInitB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1172,14 +1062,14 @@ int CVodeQuadSStolerancesB(void *cvode_mem, int which, realtype reltolQB, realty
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1214,14 +1104,14 @@ int CVodeQuadSVtolerancesB(void *cvode_mem, int which, realtype reltolQB, N_Vect
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeQuadSStolerancesB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1279,7 +1169,7 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
   /* Was ASA initialized? */
 
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   }
@@ -1287,7 +1177,7 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
   /* Check if any backward problem has been defined */
 
-  if ( nbckpbs == 0 ) {
+  if ( ca_mem->ca_nbckpbs == 0 ) {
     cvProcessError(cv_mem, CV_NO_BCK, "CVODEA", "CVodeB", MSGCV_NO_BCK);
     return(CV_NO_BCK);
   }
@@ -1299,7 +1189,7 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
     cvProcessError(cv_mem, CV_NO_FWD, "CVODEA", "CVodeB", MSGCV_NO_FWD);
     return(CV_NO_FWD);
   }
-  sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+  sign = (ca_mem->ca_tfinal - ca_mem->ca_tinitial > ZERO) ? 1 : -1;
 
   /* If this is the first call, loop over all backward problems and
    *   - check that tB0 is valid
@@ -1315,7 +1205,7 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
       tBn = tmp_cvB_mem->cv_mem->cv_tn;
 
-      if ( (sign*(tBn-tinitial) < ZERO) || (sign*(tfinal-tBn) < ZERO) ) {
+      if ( (sign*(tBn-ca_mem->ca_tinitial) < ZERO) || (sign*(ca_mem->ca_tfinal-tBn) < ZERO) ) {
         cvProcessError(cv_mem, CV_BAD_TB0, "CVODEA", "CVodeB", MSGCV_BAD_TB0,
                        tmp_cvB_mem->cv_index);
         return(CV_BAD_TB0);
@@ -1328,18 +1218,18 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
       }
 
       if ( tmp_cvB_mem->cv_f_withSensi || tmp_cvB_mem->cv_fQ_withSensi )
-          IMinterpSensi = TRUE;
+          ca_mem->ca_IMinterpSensi = SUNTRUE;
 
       tmp_cvB_mem = tmp_cvB_mem->cv_next;
 
     }
 
-    if ( IMinterpSensi && !IMstoreSensi) {
+    if ( ca_mem->ca_IMinterpSensi && !ca_mem->ca_IMstoreSensi) {
       cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_SENSI);
       return(CV_ILL_INPUT);
     }
 
-    ca_mem->ca_firstCVodeBcall = FALSE;
+    ca_mem->ca_firstCVodeBcall = SUNFALSE;
   }
 
   /* Check if itaskB is legal */
@@ -1351,10 +1241,10 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
   /* Check if tBout is legal */
 
-  if ( (sign*(tBout-tinitial) < ZERO) || (sign*(tfinal-tBout) < ZERO) ) {
-    tfuzz = HUNDRED*uround*(SUNRabs(tinitial) + SUNRabs(tfinal));
-    if ( (sign*(tBout-tinitial) < ZERO) && (SUNRabs(tBout-tinitial) < tfuzz) ) {
-      tBout = tinitial;
+  if ( (sign*(tBout-ca_mem->ca_tinitial) < ZERO) || (sign*(ca_mem->ca_tfinal-tBout) < ZERO) ) {
+    tfuzz = HUNDRED*cv_mem->cv_uround*(SUNRabs(ca_mem->ca_tinitial) + SUNRabs(ca_mem->ca_tfinal));
+    if ( (sign*(tBout-ca_mem->ca_tinitial) < ZERO) && (SUNRabs(tBout-ca_mem->ca_tinitial) < tfuzz) ) {
+      tBout = ca_mem->ca_tinitial;
     } else {
       cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeB", MSGCV_BAD_TBOUT);
       return(CV_ILL_INPUT);
@@ -1367,21 +1257,21 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
   ck_mem = ca_mem->ck_mem;
 
-  gotCheckpoint = FALSE;
+  gotCheckpoint = SUNFALSE;
 
-  loop {
+  for(;;) {
 
     tmp_cvB_mem = cvB_mem;
     while(tmp_cvB_mem != NULL) {
       tBn = tmp_cvB_mem->cv_mem->cv_tn;
 
-      if ( sign*(tBn-t0_) > ZERO ) {
-        gotCheckpoint = TRUE;
+      if ( sign*(tBn-ck_mem->ck_t0) > ZERO ) {
+        gotCheckpoint = SUNTRUE;
         break;
       }
 
-      if ( (itaskB==CV_NORMAL) && (tBn == t0_) && (sign*(tBout-t0_) >= ZERO) ) {
-        gotCheckpoint = TRUE;
+      if ( (itaskB==CV_NORMAL) && (tBn == ck_mem->ck_t0) && (sign*(tBout-ck_mem->ck_t0) >= ZERO) ) {
+        gotCheckpoint = SUNTRUE;
         break;
       }
 
@@ -1390,20 +1280,20 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
     if (gotCheckpoint) break;
 
-    if (next_ == NULL) break;
+    if (ck_mem->ck_next == NULL) break;
 
-    ck_mem = next_;
+    ck_mem = ck_mem->ck_next;
   }
 
   /* Starting with the current check point from above, loop over check points
      while propagating backward problems */
 
-  loop {
+  for(;;) {
 
     /* Store interpolation data if not available.
        This is the 2nd forward integration pass */
 
-    if (ck_mem != ckpntData) {
+    if (ck_mem != ca_mem->ca_ckpntData) {
       flag = CVAdataStore(cv_mem, ck_mem);
       if (flag != CV_SUCCESS) break;
     }
@@ -1416,14 +1306,14 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
       /* Decide if current backward problem is "active" in this check point */
 
-      isActive = TRUE;
+      isActive = SUNTRUE;
 
       tBn = tmp_cvB_mem->cv_mem->cv_tn;
 
-      if ( (tBn == t0_) && (sign*(tBout-t0_) < ZERO ) ) isActive = FALSE;
-      if ( (tBn == t0_) && (itaskB==CV_ONE_STEP) ) isActive = FALSE;
+      if ( (tBn == ck_mem->ck_t0) && (sign*(tBout-ck_mem->ck_t0) < ZERO ) ) isActive = SUNFALSE;
+      if ( (tBn == ck_mem->ck_t0) && (itaskB==CV_ONE_STEP) ) isActive = SUNFALSE;
 
-      if ( sign * (tBn - t0_) < ZERO ) isActive = FALSE;
+      if ( sign * (tBn - ck_mem->ck_t0) < ZERO ) isActive = SUNFALSE;
 
       if ( isActive ) {
 
@@ -1432,7 +1322,7 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
         ca_mem->ca_bckpbCrt = tmp_cvB_mem;
 
         /* Integrate current backward problem */
-        CVodeSetStopTime(tmp_cvB_mem->cv_mem, t0_);
+        CVodeSetStopTime(tmp_cvB_mem->cv_mem, ck_mem->ck_t0);
         flag = CVode(tmp_cvB_mem->cv_mem, tBout, tmp_cvB_mem->cv_y, &tBret, itaskB);
 
         /* Set the time at which we will report solution and/or quadratures */
@@ -1465,12 +1355,12 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
     /* If all backward problems have succesfully reached tBout, return now */
 
-    reachedTBout = TRUE;
+    reachedTBout = SUNTRUE;
 
     tmp_cvB_mem = cvB_mem;
     while(tmp_cvB_mem != NULL) {
       if ( sign*(tmp_cvB_mem->cv_tout - tBout) > ZERO ) {
-        reachedTBout = FALSE;
+        reachedTBout = SUNFALSE;
         break;
       }
       tmp_cvB_mem = tmp_cvB_mem->cv_next;
@@ -1480,7 +1370,7 @@ int CVodeB(void *cvode_mem, realtype tBout, int itaskB)
 
     /* Move check point in linked list to next one */
 
-    ck_mem = next_;
+    ck_mem = ck_mem->ck_next;
 
   } 
 
@@ -1502,7 +1392,7 @@ int CVodeGetB(void *cvode_mem, int which, realtype *tret, N_Vector yB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -1510,7 +1400,7 @@ int CVodeGetB(void *cvode_mem, int which, realtype *tret, N_Vector yB)
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeGetB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1550,7 +1440,7 @@ int CVodeGetQuadB(void *cvode_mem, int which, realtype *tret, N_Vector qB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetQuadB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -1558,7 +1448,7 @@ int CVodeGetQuadB(void *cvode_mem, int which, realtype *tret, N_Vector qB)
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeGetQuadB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -1611,88 +1501,88 @@ static CkpntMem CVAckpntInit(CVodeMem cv_mem)
   ck_mem = (CkpntMem) malloc(sizeof(struct CkpntMemRec));
   if (ck_mem == NULL) return(NULL);
 
-  zn_[0] = N_VClone(tempv);
-  if (zn_[0] == NULL) {
+  ck_mem->ck_zn[0] = N_VClone(cv_mem->cv_tempv);
+  if (ck_mem->ck_zn[0] == NULL) {
     free(ck_mem); ck_mem = NULL;
     return(NULL);
   }
   
-  zn_[1] = N_VClone(tempv);
-  if (zn_[1] == NULL) {
-    N_VDestroy(zn_[0]);
+  ck_mem->ck_zn[1] = N_VClone(cv_mem->cv_tempv);
+  if (ck_mem->ck_zn[1] == NULL) {
+    N_VDestroy(ck_mem->ck_zn[0]);
     free(ck_mem); ck_mem = NULL;
     return(NULL);
   }
 
-  /* zn_[qmax] was not allocated */
-  zqm_ = 0;
+  /* ck_mem->ck_zn[qmax] was not allocated */
+  ck_mem->ck_zqm = 0;
 
   /* Load ckdata from cv_mem */
-  N_VScale(ONE, zn[0], zn_[0]);
-  t0_    = tn;
-  nst_   = 0;
-  q_     = 1;
-  h_     = 0.0;
+  N_VScale(ONE, cv_mem->cv_zn[0], ck_mem->ck_zn[0]);
+  ck_mem->ck_t0    = cv_mem->cv_tn;
+  ck_mem->ck_nst   = 0;
+  ck_mem->ck_q     = 1;
+  ck_mem->ck_h     = 0.0;
   
   /* Do we need to carry quadratures */
-  quadr_ = quadr && errconQ;
+  ck_mem->ck_quadr = cv_mem->cv_quadr && cv_mem->cv_errconQ;
 
-  if (quadr_) {
+  if (ck_mem->ck_quadr) {
 
-    znQ_[0] = N_VClone(tempvQ);
-    if (znQ_[0] == NULL) {
-      N_VDestroy(zn_[0]);
-      N_VDestroy(zn_[1]);
+    ck_mem->ck_znQ[0] = N_VClone(cv_mem->cv_tempvQ);
+    if (ck_mem->ck_znQ[0] == NULL) {
+      N_VDestroy(ck_mem->ck_zn[0]);
+      N_VDestroy(ck_mem->ck_zn[1]);
       free(ck_mem); ck_mem = NULL;
       return(NULL);
     }
 
-    N_VScale(ONE, znQ[0], znQ_[0]);
+    N_VScale(ONE, cv_mem->cv_znQ[0], ck_mem->ck_znQ[0]);
 
   }
 
   /* Do we need to carry sensitivities? */
-  sensi_ = sensi;
+  ck_mem->ck_sensi = cv_mem->cv_sensi;
 
-  if (sensi_) {
+  if (ck_mem->ck_sensi) {
 
-    Ns_ = Ns;
+    ck_mem->ck_Ns = cv_mem->cv_Ns;
 
-    znS_[0] = N_VCloneVectorArray(Ns, tempv);
-    if (znS_[0] == NULL) {
-      N_VDestroy(zn_[0]);
-      N_VDestroy(zn_[1]);
-      if (quadr_) N_VDestroy(znQ_[0]);
+    ck_mem->ck_znS[0] = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
+    if (ck_mem->ck_znS[0] == NULL) {
+      N_VDestroy(ck_mem->ck_zn[0]);
+      N_VDestroy(ck_mem->ck_zn[1]);
+      if (ck_mem->ck_quadr) N_VDestroy(ck_mem->ck_znQ[0]);
       free(ck_mem); ck_mem = NULL;
       return(NULL);
     }
 
-    for (is=0; is<Ns; is++)
-      N_VScale(ONE, znS[0][is], znS_[0][is]);
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VScale(ONE, cv_mem->cv_znS[0][is], ck_mem->ck_znS[0][is]);
 
   }
 
   /* Do we need to carry quadrature sensitivities? */
-  quadr_sensi_ = quadr_sensi && errconQS;
-
-  if (quadr_sensi_) {
-    znQS_[0] = N_VCloneVectorArray(Ns, tempvQ);
-    if (znQS_[0] == NULL) {
-      N_VDestroy(zn_[0]);
-      N_VDestroy(zn_[1]);
-      if (quadr_) N_VDestroy(znQ_[0]);
-      N_VDestroyVectorArray(znS_[0], Ns);
+  ck_mem->ck_quadr_sensi = cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS;
+
+  if (ck_mem->ck_quadr_sensi) {
+    ck_mem->ck_znQS[0] = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempvQ);
+    if (ck_mem->ck_znQS[0] == NULL) {
+      N_VDestroy(ck_mem->ck_zn[0]);
+      N_VDestroy(ck_mem->ck_zn[1]);
+      if (ck_mem->ck_quadr) N_VDestroy(ck_mem->ck_znQ[0]);
+      N_VDestroyVectorArray(ck_mem->ck_znS[0], cv_mem->cv_Ns);
       free(ck_mem); ck_mem = NULL;
       return(NULL);
     }
     
-    for (is=0; is<Ns; is++)
-      N_VScale(ONE, znQS[0][is], znQS_[0][is]);
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VScale(ONE, cv_mem->cv_znQS[0][is], ck_mem->ck_znQS[0][is]);
 
   }
 
   /* Next in list */
-  next_  = NULL;
+  ck_mem->ck_next  = NULL;
 
   return(ck_mem);
 }
@@ -1721,48 +1611,48 @@ static CkpntMem CVAckpntNew(CVodeMem cv_mem)
    * NOTE: zn(qmax) may be needed for a hot restart, if an order
    * increase is deemed necessary at the first step after a check point */
   qmax = cv_mem->cv_qmax;
-  zqm_ = (q < qmax) ? qmax : 0;
+  ck_mem->ck_zqm = (cv_mem->cv_q < qmax) ? qmax : 0;
 
-  for (j=0; j<=q; j++) {
-    zn_[j] = N_VClone(tempv);
-    if (zn_[j] == NULL) {
-      for (jj=0; jj<j; jj++) N_VDestroy(zn_[jj]);
+  for (j=0; j<=cv_mem->cv_q; j++) {
+    ck_mem->ck_zn[j] = N_VClone(cv_mem->cv_tempv);
+    if (ck_mem->ck_zn[j] == NULL) {
+      for (jj=0; jj<j; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
       free(ck_mem); ck_mem = NULL;
       return(NULL);
     }
   }
 
-  if (q < qmax) {
-    zn_[qmax] = N_VClone(tempv);
-    if (zn_[qmax] == NULL) {
-      for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+  if (cv_mem->cv_q < qmax) {
+    ck_mem->ck_zn[qmax] = N_VClone(cv_mem->cv_tempv);
+    if (ck_mem->ck_zn[qmax] == NULL) {
+      for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
       free(ck_mem); ck_mem = NULL;
       return(NULL);
     }
   }
 
   /* Test if we need to carry quadratures */
-  quadr_ = quadr && errconQ;
+  ck_mem->ck_quadr = cv_mem->cv_quadr && cv_mem->cv_errconQ;
 
-  if (quadr_) {
+  if (ck_mem->ck_quadr) {
 
-    for (j=0; j<=q; j++) {
-      znQ_[j] = N_VClone(tempvQ);
-      if(znQ_[j] == NULL) {
-        for (jj=0; jj<j; jj++) N_VDestroy(znQ_[jj]);
-        if (q < qmax) N_VDestroy(zn_[qmax]);
-        for (jj=0; jj<=q; j++) N_VDestroy(zn_[jj]);
+    for (j=0; j<=cv_mem->cv_q; j++) {
+      ck_mem->ck_znQ[j] = N_VClone(cv_mem->cv_tempvQ);
+      if(ck_mem->ck_znQ[j] == NULL) {
+        for (jj=0; jj<j; jj++) N_VDestroy(ck_mem->ck_znQ[jj]);
+        if (cv_mem->cv_q < qmax) N_VDestroy(ck_mem->ck_zn[qmax]);
+        for (jj=0; jj<=cv_mem->cv_q; j++) N_VDestroy(ck_mem->ck_zn[jj]);
         free(ck_mem); ck_mem = NULL;
         return(NULL);
       }
     }
 
-    if (q < qmax) {
-      znQ_[qmax] = N_VClone(tempvQ);
-      if (znQ_[qmax] == NULL) {
-        for (jj=0; jj<=q; jj++) N_VDestroy(znQ_[jj]);
-        N_VDestroy(zn_[qmax]);
-        for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+    if (cv_mem->cv_q < qmax) {
+      ck_mem->ck_znQ[qmax] = N_VClone(cv_mem->cv_tempvQ);
+      if (ck_mem->ck_znQ[qmax] == NULL) {
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_znQ[jj]);
+        N_VDestroy(ck_mem->ck_zn[qmax]);
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
         free(ck_mem); ck_mem = NULL;
         return(NULL);
       }
@@ -1771,37 +1661,37 @@ static CkpntMem CVAckpntNew(CVodeMem cv_mem)
   }
 
   /* Test if we need to carry sensitivities */
-  sensi_ = sensi;
+  ck_mem->ck_sensi = cv_mem->cv_sensi;
 
-  if (sensi_) {
+  if (ck_mem->ck_sensi) {
 
-    Ns_ = Ns;
+    ck_mem->ck_Ns = cv_mem->cv_Ns;
 
-    for (j=0; j<=q; j++) {
-      znS_[j] = N_VCloneVectorArray(Ns, tempv);
-      if (znS_[j] == NULL) {
-        for (jj=0; jj<j; jj++) N_VDestroyVectorArray(znS_[jj], Ns);
-        if (quadr_) {
-          if (q < qmax) N_VDestroy(znQ_[qmax]);
-          for (jj=0; jj<=q; jj++) N_VDestroy(znQ_[jj]);
+    for (j=0; j<=cv_mem->cv_q; j++) {
+      ck_mem->ck_znS[j] = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
+      if (ck_mem->ck_znS[j] == NULL) {
+        for (jj=0; jj<j; jj++) N_VDestroyVectorArray(ck_mem->ck_znS[jj], cv_mem->cv_Ns);
+        if (ck_mem->ck_quadr) {
+          if (cv_mem->cv_q < qmax) N_VDestroy(ck_mem->ck_znQ[qmax]);
+          for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_znQ[jj]);
         }
-        if (q < qmax) N_VDestroy(zn_[qmax]);
-        for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+        if (cv_mem->cv_q < qmax) N_VDestroy(ck_mem->ck_zn[qmax]);
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
         free(ck_mem); ck_mem = NULL;
         return(NULL);
       }
     }
 
-    if ( q < qmax) {
-      znS_[qmax] = N_VCloneVectorArray(Ns, tempv);
-      if (znS_[qmax] == NULL) {
-        for (jj=0; jj<=q; jj++) N_VDestroyVectorArray(znS_[jj], Ns);
-        if (quadr_) {
-          N_VDestroy(znQ_[qmax]);
-          for (jj=0; jj<=q; jj++) N_VDestroy(znQ_[jj]);
+    if ( cv_mem->cv_q < qmax) {
+      ck_mem->ck_znS[qmax] = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
+      if (ck_mem->ck_znS[qmax] == NULL) {
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroyVectorArray(ck_mem->ck_znS[jj], cv_mem->cv_Ns);
+        if (ck_mem->ck_quadr) {
+          N_VDestroy(ck_mem->ck_znQ[qmax]);
+          for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_znQ[jj]);
         }
-        N_VDestroy(zn_[qmax]);
-        for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+        N_VDestroy(ck_mem->ck_zn[qmax]);
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
         free(ck_mem); ck_mem = NULL;
         return(NULL);
       }
@@ -1810,39 +1700,39 @@ static CkpntMem CVAckpntNew(CVodeMem cv_mem)
   }
 
   /* Test if we need to carry quadrature sensitivities */
-  quadr_sensi_ = quadr_sensi && errconQS;
-
-  if (quadr_sensi_) {
-
-    for (j=0; j<=q; j++) {
-      znQS_[j] = N_VCloneVectorArray(Ns, tempvQ);
-      if (znQS_[j] == NULL) {
-        for (jj=0; jj<j; jj++) N_VDestroyVectorArray(znQS_[jj], Ns);
-        if (q < qmax) N_VDestroyVectorArray(znS_[qmax], Ns);
-        for (jj=0; jj<=q; jj++) N_VDestroyVectorArray(znS_[jj], Ns);
-        if (quadr_) {
-          if (q < qmax) N_VDestroy(znQ_[qmax]);
-          for (jj=0; jj<=q; jj++) N_VDestroy(znQ_[jj]);
+  ck_mem->ck_quadr_sensi = cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS;
+
+  if (ck_mem->ck_quadr_sensi) {
+
+    for (j=0; j<=cv_mem->cv_q; j++) {
+      ck_mem->ck_znQS[j] = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempvQ);
+      if (ck_mem->ck_znQS[j] == NULL) {
+        for (jj=0; jj<j; jj++) N_VDestroyVectorArray(ck_mem->ck_znQS[jj], cv_mem->cv_Ns);
+        if (cv_mem->cv_q < qmax) N_VDestroyVectorArray(ck_mem->ck_znS[qmax], cv_mem->cv_Ns);
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroyVectorArray(ck_mem->ck_znS[jj], cv_mem->cv_Ns);
+        if (ck_mem->ck_quadr) {
+          if (cv_mem->cv_q < qmax) N_VDestroy(ck_mem->ck_znQ[qmax]);
+          for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_znQ[jj]);
         }
-        if (q < qmax) N_VDestroy(zn_[qmax]);
-        for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+        if (cv_mem->cv_q < qmax) N_VDestroy(ck_mem->ck_zn[qmax]);
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
         free(ck_mem); ck_mem = NULL;
         return(NULL);
       }
     }
 
-    if ( q < qmax) {
-      znQS_[qmax] = N_VCloneVectorArray(Ns, tempvQ);
-      if (znQS_[qmax] == NULL) {
-        for (jj=0; jj<=q; jj++) N_VDestroyVectorArray(znQS_[jj], Ns);
-        N_VDestroyVectorArray(znS_[qmax], Ns);
-        for (jj=0; jj<=q; jj++) N_VDestroyVectorArray(znS_[jj], Ns);
-        if (quadr_) {
-          N_VDestroy(znQ_[qmax]);
-          for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+    if ( cv_mem->cv_q < qmax) {
+      ck_mem->ck_znQS[qmax] = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempvQ);
+      if (ck_mem->ck_znQS[qmax] == NULL) {
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroyVectorArray(ck_mem->ck_znQS[jj], cv_mem->cv_Ns);
+        N_VDestroyVectorArray(ck_mem->ck_znS[qmax], cv_mem->cv_Ns);
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroyVectorArray(ck_mem->ck_znS[jj], cv_mem->cv_Ns);
+        if (ck_mem->ck_quadr) {
+          N_VDestroy(ck_mem->ck_znQ[qmax]);
+          for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
         }
-        N_VDestroy(zn_[qmax]);
-        for (jj=0; jj<=q; jj++) N_VDestroy(zn_[jj]);
+        N_VDestroy(ck_mem->ck_zn[qmax]);
+        for (jj=0; jj<=cv_mem->cv_q; jj++) N_VDestroy(ck_mem->ck_zn[jj]);
         free(ck_mem); ck_mem = NULL;
         return(NULL);
       }
@@ -1852,45 +1742,45 @@ static CkpntMem CVAckpntNew(CVodeMem cv_mem)
 
   /* Load check point data from cv_mem */
 
-  for (j=0; j<=q; j++) N_VScale(ONE, zn[j], zn_[j]);
-  if ( q < qmax ) N_VScale(ONE, zn[qmax], zn_[qmax]);
+  for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, cv_mem->cv_zn[j], ck_mem->ck_zn[j]);
+  if ( cv_mem->cv_q < qmax ) N_VScale(ONE, cv_mem->cv_zn[qmax], ck_mem->ck_zn[qmax]);
 
-  if (quadr_) {
-    for (j=0; j<=q; j++) N_VScale(ONE, znQ[j], znQ_[j]);
-    if ( q < qmax ) N_VScale(ONE, znQ[qmax], znQ_[qmax]);
+  if (ck_mem->ck_quadr) {
+    for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, cv_mem->cv_znQ[j], ck_mem->ck_znQ[j]);
+    if ( cv_mem->cv_q < qmax ) N_VScale(ONE, cv_mem->cv_znQ[qmax], ck_mem->ck_znQ[qmax]);
   }
 
-  if (sensi_) {
-    for (is=0; is<Ns; is++) {
-      for (j=0; j<=q; j++) N_VScale(ONE, znS[j][is], znS_[j][is]);
-      if ( q < qmax ) N_VScale(ONE, znS[qmax][is], znS_[qmax][is]);
+  if (ck_mem->ck_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, cv_mem->cv_znS[j][is], ck_mem->ck_znS[j][is]);
+      if ( cv_mem->cv_q < qmax ) N_VScale(ONE, cv_mem->cv_znS[qmax][is], ck_mem->ck_znS[qmax][is]);
     }
   }
 
-  if (quadr_sensi_) {
-    for (is=0; is<Ns; is++) {
-      for (j=0; j<=q; j++) N_VScale(ONE, znQS[j][is], znQS_[j][is]);
-      if ( q < qmax ) N_VScale(ONE, znQS[qmax][is], znQS_[qmax][is]);
+  if (ck_mem->ck_quadr_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, cv_mem->cv_znQS[j][is], ck_mem->ck_znQS[j][is]);
+      if ( cv_mem->cv_q < qmax ) N_VScale(ONE, cv_mem->cv_znQS[qmax][is], ck_mem->ck_znQS[qmax][is]);
     }
   }
 
-  for (j=0; j<=L_MAX; j++)     tau_[j] = tau[j];
-  for (j=0; j<=NUM_TESTS; j++) tq_[j] = tq[j];
-  for (j=0; j<=q; j++)         l_[j] = l[j];
-  nst_       = nst;
-  tretlast_  = tretlast;
-  q_         = q;
-  qprime_    = qprime;
-  qwait_     = qwait;
-  L_         = L;
-  gammap_    = gammap;
-  h_         = h;
-  hprime_    = hprime;
-  hscale_    = hscale;
-  eta_       = eta;
-  etamax_    = etamax;
-  t0_        = tn;
-  saved_tq5_ = saved_tq5;
+  for (j=0; j<=L_MAX; j++)        ck_mem->ck_tau[j] = cv_mem->cv_tau[j];
+  for (j=0; j<=NUM_TESTS; j++)    ck_mem->ck_tq[j] = cv_mem->cv_tq[j];
+  for (j=0; j<=cv_mem->cv_q; j++) ck_mem->ck_l[j] = cv_mem->cv_l[j];
+  ck_mem->ck_nst       = cv_mem->cv_nst;
+  ck_mem->ck_tretlast  = cv_mem->cv_tretlast;
+  ck_mem->ck_q         = cv_mem->cv_q;
+  ck_mem->ck_qprime    = cv_mem->cv_qprime;
+  ck_mem->ck_qwait     = cv_mem->cv_qwait;
+  ck_mem->ck_L         = cv_mem->cv_L;
+  ck_mem->ck_gammap    = cv_mem->cv_gammap;
+  ck_mem->ck_h         = cv_mem->cv_h;
+  ck_mem->ck_hprime    = cv_mem->cv_hprime;
+  ck_mem->ck_hscale    = cv_mem->cv_hscale;
+  ck_mem->ck_eta       = cv_mem->cv_eta;
+  ck_mem->ck_etamax    = cv_mem->cv_etamax;
+  ck_mem->ck_t0        = cv_mem->cv_tn;
+  ck_mem->ck_saved_tq5 = cv_mem->cv_saved_tq5;
 
   return(ck_mem);
 }
@@ -2038,34 +1928,34 @@ static int CVAdataStore(CVodeMem cv_mem, CkpntMem ck_mem)
     return(CV_REIFWD_FAIL);
 
   /* Set first structure in dt_mem[0] */
-  dt_mem[0]->t = t0_;
-  IMstore(cv_mem, dt_mem[0]);
+  dt_mem[0]->t = ck_mem->ck_t0;
+  ca_mem->ca_IMstore(cv_mem, dt_mem[0]);
 
   /* Decide whether TSTOP must be activated */
   if (ca_mem->ca_tstopCVodeFcall) {
     CVodeSetStopTime(cv_mem, ca_mem->ca_tstopCVodeF);
   }
 
-  sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+  sign = (ca_mem->ca_tfinal - ca_mem->ca_tinitial > ZERO) ? 1 : -1;
 
 
   /* Run CVode to set following structures in dt_mem[i] */
   i = 1;
   do {
 
-    flag = CVode(cv_mem, t1_, ytmp, &t, CV_ONE_STEP);
+    flag = CVode(cv_mem, ck_mem->ck_t1, ca_mem->ca_ytmp, &t, CV_ONE_STEP);
     if (flag < 0) return(CV_FWD_FAIL);
 
     dt_mem[i]->t = t;
-    IMstore(cv_mem, dt_mem[i]);
+    ca_mem->ca_IMstore(cv_mem, dt_mem[i]);
     i++;
 
-  } while ( sign*(t1_ - t) > ZERO );
+  } while ( sign*(ck_mem->ck_t1 - t) > ZERO );
 
 
-  IMnewData = TRUE;     /* New data is now available    */
-  ckpntData = ck_mem;   /* starting at this check point */
-  np = i;               /* and we have this many points */
+  ca_mem->ca_IMnewData = SUNTRUE;     /* New data is now available    */
+  ca_mem->ca_ckpntData = ck_mem;   /* starting at this check point */
+  ca_mem->ca_np = i;               /* and we have this many points */
 
   return(CV_SUCCESS);
 }
@@ -2081,29 +1971,29 @@ static int CVAckpntGet(CVodeMem cv_mem, CkpntMem ck_mem)
 {
   int flag, j, is, qmax;
 
-  if (next_ == NULL) {
+  if (ck_mem->ck_next == NULL) {
 
     /* In this case, we just call the reinitialization routine,
      * but make sure we use the same initial stepsize as on 
      * the first run. */
 
-    CVodeSetInitStep(cv_mem, h0u);
+    CVodeSetInitStep(cv_mem, cv_mem->cv_h0u);
 
-    flag = CVodeReInit(cv_mem, t0_, zn_[0]);
+    flag = CVodeReInit(cv_mem, ck_mem->ck_t0, ck_mem->ck_zn[0]);
     if (flag != CV_SUCCESS) return(flag);
 
-    if (quadr_) {
-      flag = CVodeQuadReInit(cv_mem, znQ_[0]);
+    if (ck_mem->ck_quadr) {
+      flag = CVodeQuadReInit(cv_mem, ck_mem->ck_znQ[0]);
       if (flag != CV_SUCCESS) return(flag);
     }
 
-    if (sensi_) {
-      flag = CVodeSensReInit(cv_mem, cv_mem->cv_ism, znS_[0]);
+    if (ck_mem->ck_sensi) {
+      flag = CVodeSensReInit(cv_mem, cv_mem->cv_ism, ck_mem->ck_znS[0]);
       if (flag != CV_SUCCESS) return(flag);
     }
 
-    if (quadr_sensi_) {
-      flag = CVodeQuadSensReInit(cv_mem, znQS_[0]);
+    if (ck_mem->ck_quadr_sensi) {
+      flag = CVodeQuadSensReInit(cv_mem, ck_mem->ck_znQS[0]);
       if (flag != CV_SUCCESS) return(flag);
     }
 
@@ -2113,52 +2003,52 @@ static int CVAckpntGet(CVodeMem cv_mem, CkpntMem ck_mem)
 
     /* Copy parameters from check point data structure */
 
-    nst       = nst_;
-    tretlast  = tretlast_;
-    q         = q_;
-    qprime    = qprime_;
-    qwait     = qwait_;
-    L         = L_;
-    gammap    = gammap_;
-    h         = h_;
-    hprime    = hprime_;
-    hscale    = hscale_;
-    eta       = eta_;
-    etamax    = etamax_;
-    tn        = t0_;
-    saved_tq5 = saved_tq5_;
+    cv_mem->cv_nst       = ck_mem->ck_nst;
+    cv_mem->cv_tretlast  = ck_mem->ck_tretlast;
+    cv_mem->cv_q         = ck_mem->ck_q;
+    cv_mem->cv_qprime    = ck_mem->ck_qprime;
+    cv_mem->cv_qwait     = ck_mem->ck_qwait;
+    cv_mem->cv_L         = ck_mem->ck_L;
+    cv_mem->cv_gammap    = ck_mem->ck_gammap;
+    cv_mem->cv_h         = ck_mem->ck_h;
+    cv_mem->cv_hprime    = ck_mem->ck_hprime;
+    cv_mem->cv_hscale    = ck_mem->ck_hscale;
+    cv_mem->cv_eta       = ck_mem->ck_eta;
+    cv_mem->cv_etamax    = ck_mem->ck_etamax;
+    cv_mem->cv_tn        = ck_mem->ck_t0;
+    cv_mem->cv_saved_tq5 = ck_mem->ck_saved_tq5;
     
     /* Copy the arrays from check point data structure */
 
-    for (j=0; j<=q; j++) N_VScale(ONE, zn_[j], zn[j]);
-    if ( q < qmax ) N_VScale(ONE, zn_[qmax], zn[qmax]);
+    for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, ck_mem->ck_zn[j], cv_mem->cv_zn[j]);
+    if ( cv_mem->cv_q < qmax ) N_VScale(ONE, ck_mem->ck_zn[qmax], cv_mem->cv_zn[qmax]);
 
-    if (quadr_) {
-      for (j=0; j<=q; j++) N_VScale(ONE, znQ_[j], znQ[j]);
-      if ( q < qmax ) N_VScale(ONE, znQ_[qmax], znQ[qmax]);
+    if (ck_mem->ck_quadr) {
+      for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, ck_mem->ck_znQ[j], cv_mem->cv_znQ[j]);
+      if ( cv_mem->cv_q < qmax ) N_VScale(ONE, ck_mem->ck_znQ[qmax], cv_mem->cv_znQ[qmax]);
     }
 
-    if (sensi_) {
-      for (is=0; is<Ns; is++) {
-        for (j=0; j<=q; j++) N_VScale(ONE, znS_[j][is], znS[j][is]);
-        if ( q < qmax ) N_VScale(ONE, znS_[qmax][is], znS[qmax][is]);
+    if (ck_mem->ck_sensi) {
+      for (is=0; is<cv_mem->cv_Ns; is++) {
+        for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, ck_mem->ck_znS[j][is], cv_mem->cv_znS[j][is]);
+        if ( cv_mem->cv_q < qmax ) N_VScale(ONE, ck_mem->ck_znS[qmax][is], cv_mem->cv_znS[qmax][is]);
       }
     }
 
-    if (quadr_sensi_) {
-      for (is=0; is<Ns; is++) {
-        for (j=0; j<=q; j++) N_VScale(ONE, znQS_[j][is], znQS[j][is]);
-        if ( q < qmax ) N_VScale(ONE, znQS_[qmax][is], znQS[qmax][is]);
+    if (ck_mem->ck_quadr_sensi) {
+      for (is=0; is<cv_mem->cv_Ns; is++) {
+        for (j=0; j<=cv_mem->cv_q; j++) N_VScale(ONE, ck_mem->ck_znQS[j][is], cv_mem->cv_znQS[j][is]);
+        if ( cv_mem->cv_q < qmax ) N_VScale(ONE, ck_mem->ck_znQS[qmax][is], cv_mem->cv_znQS[qmax][is]);
       }
     }
 
-    for (j=0; j<=L_MAX; j++)     tau[j] = tau_[j];
-    for (j=0; j<=NUM_TESTS; j++) tq[j] = tq_[j];
-    for (j=0; j<=q; j++)         l[j] = l_[j];
+    for (j=0; j<=L_MAX; j++)        cv_mem->cv_tau[j] = ck_mem->ck_tau[j];
+    for (j=0; j<=NUM_TESTS; j++)    cv_mem->cv_tq[j] = ck_mem->ck_tq[j];
+    for (j=0; j<=cv_mem->cv_q; j++) cv_mem->cv_l[j] = ck_mem->ck_l[j];
     
     /* Force a call to setup */
 
-    forceSetup = TRUE;
+    cv_mem->cv_forceSetup = SUNTRUE;
 
   }
 
@@ -2176,7 +2066,7 @@ static int CVAckpntGet(CVodeMem cv_mem, CkpntMem ck_mem)
  *
  * Finds the index in the array of data point strctures such that
  *     dt_mem[indx-1].t <= t < dt_mem[indx].t
- * If indx is changed from the previous invocation, then newpoint = TRUE
+ * If indx is changed from the previous invocation, then newpoint = SUNTRUE
  *
  * If t is beyond the leftmost limit, but close enough, indx=0.
  *
@@ -2196,16 +2086,16 @@ static int CVAfindIndex(CVodeMem cv_mem, realtype t,
   ca_mem = cv_mem->cv_adj_mem;
   dt_mem = ca_mem->dt_mem;
 
-  *newpoint = FALSE;
+  *newpoint = SUNFALSE;
 
   /* Find the direction of integration */
-  sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+  sign = (ca_mem->ca_tfinal - ca_mem->ca_tinitial > ZERO) ? 1 : -1;
 
   /* If this is the first time we use new data */
-  if (IMnewData) {
-    ilast     = np-1;
-    *newpoint = TRUE;
-    IMnewData   = FALSE;
+  if (ca_mem->ca_IMnewData) {
+    ilast     = ca_mem->ca_np-1;
+    *newpoint = SUNTRUE;
+    ca_mem->ca_IMnewData   = SUNFALSE;
   }
 
   /* Search for indx starting from ilast */
@@ -2215,10 +2105,10 @@ static int CVAfindIndex(CVodeMem cv_mem, realtype t,
   if ( to_left ) {
     /* look for a new indx to the left */
 
-    *newpoint = TRUE;
+    *newpoint = SUNTRUE;
     
     *indx = ilast;
-    loop {
+    for(;;) {
       if ( *indx == 0 ) break;
       if ( sign*(t - dt_mem[*indx-1]->t) <= ZERO ) (*indx)--;
       else                                         break;
@@ -2231,7 +2121,7 @@ static int CVAfindIndex(CVodeMem cv_mem, realtype t,
 
     if ( *indx == 0 ) {
       /* t is beyond leftmost limit. Is it too far? */  
-      if ( SUNRabs(t - dt_mem[0]->t) > FUZZ_FACTOR * uround ) {
+      if ( SUNRabs(t - dt_mem[0]->t) > FUZZ_FACTOR * cv_mem->cv_uround ) {
         return(CV_GETY_BADT);
       }
     }
@@ -2239,10 +2129,10 @@ static int CVAfindIndex(CVodeMem cv_mem, realtype t,
   } else if ( to_right ) {
     /* look for a new indx to the right */
 
-    *newpoint = TRUE;
+    *newpoint = SUNTRUE;
 
     *indx = ilast;
-    loop {
+    for(;;) {
       if ( sign*(t - dt_mem[*indx]->t) > ZERO) (*indx)++;
       else                                     break;
     }
@@ -2283,7 +2173,7 @@ int CVodeGetAdjY(void *cvode_mem, realtype t, N_Vector y)
 
   ca_mem = cv_mem->cv_adj_mem;
 
-  flag = IMget(cv_mem, t, y, NULL);
+  flag = ca_mem->ca_IMget(cv_mem, t, y, NULL);
 
   return(flag);
 }
@@ -2311,22 +2201,22 @@ static booleantype CVAhermiteMalloc(CVodeMem cv_mem)
   long int i, ii=0;
   booleantype allocOK;
 
-  allocOK = TRUE;
+  allocOK = SUNTRUE;
 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Allocate space for the vectors ytmp and yStmp */
 
-  ytmp = N_VClone(tempv);
-  if (ytmp == NULL) {
-    return(FALSE);
+  ca_mem->ca_ytmp = N_VClone(cv_mem->cv_tempv);
+  if (ca_mem->ca_ytmp == NULL) {
+    return(SUNFALSE);
   }
 
-  if (IMstoreSensi) {
-    yStmp = N_VCloneVectorArray(Ns, tempv);
-    if (yStmp == NULL) {
-      N_VDestroy(ytmp);
-      return(FALSE);
+  if (ca_mem->ca_IMstoreSensi) {
+    ca_mem->ca_yStmp = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
+    if (ca_mem->ca_yStmp == NULL) {
+      N_VDestroy(ca_mem->ca_ytmp);
+      return(SUNFALSE);
     }
   }
 
@@ -2334,53 +2224,53 @@ static booleantype CVAhermiteMalloc(CVodeMem cv_mem)
 
   dt_mem = ca_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=ca_mem->ca_nsteps; i++) {
 
     content = NULL;
     content = (HermiteDataMem) malloc(sizeof(struct HermiteDataMemRec));
     if (content == NULL) {
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    content->y = N_VClone(tempv);
+    content->y = N_VClone(cv_mem->cv_tempv);
     if (content->y == NULL) {
       free(content); content = NULL;
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    content->yd = N_VClone(tempv);
+    content->yd = N_VClone(cv_mem->cv_tempv);
     if (content->yd == NULL) {
       N_VDestroy(content->y);
       free(content); content = NULL;
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    if (IMstoreSensi) {
+    if (ca_mem->ca_IMstoreSensi) {
 
-      content->yS = N_VCloneVectorArray(Ns, tempv);
+      content->yS = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
       if (content->yS == NULL) {
         N_VDestroy(content->y);
         N_VDestroy(content->yd);
         free(content); content = NULL;
         ii = i;
-        allocOK = FALSE;
+        allocOK = SUNFALSE;
         break;
       }
 
-      content->ySd = N_VCloneVectorArray(Ns, tempv);
+      content->ySd = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
       if (content->ySd == NULL) {
         N_VDestroy(content->y);
         N_VDestroy(content->yd);
-        N_VDestroyVectorArray(content->yS, Ns);
+        N_VDestroyVectorArray(content->yS, cv_mem->cv_Ns);
         free(content); content = NULL;
         ii = i;
-        allocOK = FALSE;
+        allocOK = SUNFALSE;
         break;
       }
       
@@ -2394,19 +2284,19 @@ static booleantype CVAhermiteMalloc(CVodeMem cv_mem)
 
   if (!allocOK) {
 
-    N_VDestroy(ytmp);
+    N_VDestroy(ca_mem->ca_ytmp);
 
-    if (IMstoreSensi) {
-      N_VDestroyVectorArray(yStmp, Ns);
+    if (ca_mem->ca_IMstoreSensi) {
+      N_VDestroyVectorArray(ca_mem->ca_yStmp, cv_mem->cv_Ns);
     }
 
     for (i=0; i<ii; i++) {
       content = (HermiteDataMem) (dt_mem[i]->content);
       N_VDestroy(content->y);
       N_VDestroy(content->yd);
-      if (IMstoreSensi) {
-        N_VDestroyVectorArray(content->yS, Ns);
-        N_VDestroyVectorArray(content->ySd, Ns);
+      if (ca_mem->ca_IMstoreSensi) {
+        N_VDestroyVectorArray(content->yS, cv_mem->cv_Ns);
+        N_VDestroyVectorArray(content->ySd, cv_mem->cv_Ns);
       }
       free(dt_mem[i]->content); dt_mem[i]->content = NULL;
     }
@@ -2431,21 +2321,21 @@ static void CVAhermiteFree(CVodeMem cv_mem)
 
   ca_mem = cv_mem->cv_adj_mem;
 
-  N_VDestroy(ytmp);
+  N_VDestroy(ca_mem->ca_ytmp);
 
-  if (IMstoreSensi) {
-    N_VDestroyVectorArray(yStmp, Ns);
+  if (ca_mem->ca_IMstoreSensi) {
+    N_VDestroyVectorArray(ca_mem->ca_yStmp, cv_mem->cv_Ns);
   }
 
   dt_mem = ca_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=ca_mem->ca_nsteps; i++) {
     content = (HermiteDataMem) (dt_mem[i]->content);
     N_VDestroy(content->y);
     N_VDestroy(content->yd);
-    if (IMstoreSensi) {
-      N_VDestroyVectorArray(content->yS, Ns);
-      N_VDestroyVectorArray(content->ySd, Ns);
+    if (ca_mem->ca_IMstoreSensi) {
+      N_VDestroyVectorArray(content->yS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(content->ySd, cv_mem->cv_Ns);
     }
     free(dt_mem[i]->content); dt_mem[i]->content = NULL;
   }
@@ -2472,32 +2362,32 @@ static int CVAhermiteStorePnt(CVodeMem cv_mem, DtpntMem d)
 
   /* Load solution */
 
-  N_VScale(ONE, zn[0], content->y);
+  N_VScale(ONE, cv_mem->cv_zn[0], content->y);
   
-  if (IMstoreSensi) {
-    for (is=0; is<Ns; is++) 
-      N_VScale(ONE, znS[0][is], content->yS[is]);
+  if (ca_mem->ca_IMstoreSensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) 
+      N_VScale(ONE, cv_mem->cv_znS[0][is], content->yS[is]);
   }
 
   /* Load derivative */
 
-  if (nst == 0) {
+  if (cv_mem->cv_nst == 0) {
 
-    /* retval = */ f(tn, content->y, content->yd, user_data);
+    /* retval = */ cv_mem->cv_f(cv_mem->cv_tn, content->y, content->yd, cv_mem->cv_user_data);
 
-    if (IMstoreSensi) {
-      /* retval = */ cvSensRhsWrapper(cv_mem, tn, content->y, content->yd,
+    if (ca_mem->ca_IMstoreSensi) {
+      /* retval = */ cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, content->y, content->yd,
                                 content->yS, content->ySd,
                                 cv_mem->cv_tempv, cv_mem->cv_ftemp);
     }
 
   } else {
 
-    N_VScale(ONE/h, zn[1], content->yd);
+    N_VScale(ONE/cv_mem->cv_h, cv_mem->cv_zn[1], content->yd);
 
-    if (IMstoreSensi) {
-      for (is=0; is<Ns; is++) 
-        N_VScale(ONE/h, znS[1][is], content->ySd[is]);
+    if (ca_mem->ca_IMstoreSensi) {
+      for (is=0; is<cv_mem->cv_Ns; is++) 
+        N_VScale(ONE/cv_mem->cv_h, cv_mem->cv_znS[1][is], content->ySd[is]);
     }
 
   }
@@ -2538,7 +2428,7 @@ static int CVAhermiteGetY(CVodeMem cv_mem, realtype t,
  
   /* Local value of Ns */
  
-  NS = (IMinterpSensi && (yS != NULL)) ? Ns : 0;
+  NS = (ca_mem->ca_IMinterpSensi && (yS != NULL)) ? cv_mem->cv_Ns : 0;
 
   /* Get the index in dt_mem */
 
@@ -2564,7 +2454,7 @@ static int CVAhermiteGetY(CVodeMem cv_mem, realtype t,
   content0 = (HermiteDataMem) (dt_mem[indx-1]->content);
   y0  = content0->y;
   yd0 = content0->yd;
-  if (IMinterpSensi) {
+  if (ca_mem->ca_IMinterpSensi) {
     yS0  = content0->yS;
     ySd0 = content0->ySd;
   }
@@ -2578,20 +2468,20 @@ static int CVAhermiteGetY(CVodeMem cv_mem, realtype t,
     y1  = content1->y;
     yd1 = content1->yd;
 
-    N_VLinearSum(ONE, y1, -ONE, y0, Y[0]);
-    N_VLinearSum(ONE, yd1,  ONE, yd0, Y[1]);
-    N_VLinearSum(delta, Y[1], -TWO, Y[0], Y[1]);
-    N_VLinearSum(ONE, Y[0], -delta, yd0, Y[0]);
+    N_VLinearSum(ONE, y1, -ONE, y0, ca_mem->ca_Y[0]);
+    N_VLinearSum(ONE, yd1,  ONE, yd0, ca_mem->ca_Y[1]);
+    N_VLinearSum(delta, ca_mem->ca_Y[1], -TWO, ca_mem->ca_Y[0], ca_mem->ca_Y[1]);
+    N_VLinearSum(ONE, ca_mem->ca_Y[0], -delta, yd0, ca_mem->ca_Y[0]);
 
 
     yS1  = content1->yS;
     ySd1 = content1->ySd;
       
     for (is=0; is<NS; is++) {
-      N_VLinearSum(ONE, yS1[is], -ONE, yS0[is], YS[0][is]);
-      N_VLinearSum(ONE, ySd1[is],  ONE, ySd0[is], YS[1][is]);
-      N_VLinearSum(delta, YS[1][is], -TWO, YS[0][is], YS[1][is]);
-      N_VLinearSum(ONE, YS[0][is], -delta, ySd0[is], YS[0][is]);
+      N_VLinearSum(ONE, yS1[is], -ONE, yS0[is], ca_mem->ca_YS[0][is]);
+      N_VLinearSum(ONE, ySd1[is],  ONE, ySd0[is], ca_mem->ca_YS[1][is]);
+      N_VLinearSum(delta, ca_mem->ca_YS[1][is], -TWO, ca_mem->ca_YS[0][is], ca_mem->ca_YS[1][is]);
+      N_VLinearSum(ONE, ca_mem->ca_YS[0][is], -delta, ySd0[is], ca_mem->ca_YS[0][is]);
     }
 
   }
@@ -2606,13 +2496,13 @@ static int CVAhermiteGetY(CVodeMem cv_mem, realtype t,
   factor3 = factor2*(t-t1)/delta;
 
   N_VLinearSum(ONE, y0, factor1, yd0, y);
-  N_VLinearSum(ONE, y, factor2, Y[0], y);
-  N_VLinearSum(ONE, y, factor3, Y[1], y);
+  N_VLinearSum(ONE, y, factor2, ca_mem->ca_Y[0], y);
+  N_VLinearSum(ONE, y, factor3, ca_mem->ca_Y[1], y);
 
   for (is=0; is<NS; is++) {
     N_VLinearSum(ONE, yS0[is], factor1, ySd0[is], yS[is]);
-    N_VLinearSum(ONE, yS[is], factor2, YS[0][is], yS[is]);
-    N_VLinearSum(ONE, yS[is], factor3, YS[1][is], yS[is]);
+    N_VLinearSum(ONE, yS[is], factor2, ca_mem->ca_YS[0][is], yS[is]);
+    N_VLinearSum(ONE, yS[is], factor3, ca_mem->ca_YS[1][is], yS[is]);
   }
 
 
@@ -2642,22 +2532,22 @@ static booleantype CVApolynomialMalloc(CVodeMem cv_mem)
   long int i, ii=0;
   booleantype allocOK;
 
-  allocOK = TRUE;
+  allocOK = SUNTRUE;
 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Allocate space for the vectors ytmp and yStmp */
 
-  ytmp = N_VClone(tempv);
-  if (ytmp == NULL) {
-    return(FALSE);
+  ca_mem->ca_ytmp = N_VClone(cv_mem->cv_tempv);
+  if (ca_mem->ca_ytmp == NULL) {
+    return(SUNFALSE);
   }
 
-  if (IMstoreSensi) {
-    yStmp = N_VCloneVectorArray(Ns, tempv);
-    if (yStmp == NULL) {
-      N_VDestroy(ytmp);
-      return(FALSE);
+  if (ca_mem->ca_IMstoreSensi) {
+    ca_mem->ca_yStmp = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
+    if (ca_mem->ca_yStmp == NULL) {
+      N_VDestroy(ca_mem->ca_ytmp);
+      return(SUNFALSE);
     }
   }
 
@@ -2665,32 +2555,32 @@ static booleantype CVApolynomialMalloc(CVodeMem cv_mem)
 
   dt_mem = ca_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=ca_mem->ca_nsteps; i++) {
 
     content = NULL;
     content = (PolynomialDataMem) malloc(sizeof(struct PolynomialDataMemRec));
     if (content == NULL) {
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    content->y = N_VClone(tempv);
+    content->y = N_VClone(cv_mem->cv_tempv);
     if (content->y == NULL) {
       free(content); content = NULL;
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    if (IMstoreSensi) {
+    if (ca_mem->ca_IMstoreSensi) {
 
-      content->yS = N_VCloneVectorArray(Ns, tempv);
+      content->yS = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
       if (content->yS == NULL) {
         N_VDestroy(content->y);
         free(content); content = NULL;
         ii = i;
-        allocOK = FALSE;
+        allocOK = SUNFALSE;
         break;
       }
 
@@ -2704,17 +2594,17 @@ static booleantype CVApolynomialMalloc(CVodeMem cv_mem)
 
   if (!allocOK) {
 
-    N_VDestroy(ytmp);
+    N_VDestroy(ca_mem->ca_ytmp);
 
-    if (IMstoreSensi) {
-      N_VDestroyVectorArray(yStmp, Ns);
+    if (ca_mem->ca_IMstoreSensi) {
+      N_VDestroyVectorArray(ca_mem->ca_yStmp, cv_mem->cv_Ns);
     }
 
     for (i=0; i<ii; i++) {
       content = (PolynomialDataMem) (dt_mem[i]->content);
       N_VDestroy(content->y);
-      if (IMstoreSensi) {
-        N_VDestroyVectorArray(content->yS, Ns);
+      if (ca_mem->ca_IMstoreSensi) {
+        N_VDestroyVectorArray(content->yS, cv_mem->cv_Ns);
       }
       free(dt_mem[i]->content); dt_mem[i]->content = NULL;
     }
@@ -2740,19 +2630,19 @@ static void CVApolynomialFree(CVodeMem cv_mem)
 
   ca_mem = cv_mem->cv_adj_mem;
 
-  N_VDestroy(ytmp);
+  N_VDestroy(ca_mem->ca_ytmp);
 
-  if (IMstoreSensi) {
-    N_VDestroyVectorArray(yStmp, Ns);
+  if (ca_mem->ca_IMstoreSensi) {
+    N_VDestroyVectorArray(ca_mem->ca_yStmp, cv_mem->cv_Ns);
   }
 
   dt_mem = ca_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=ca_mem->ca_nsteps; i++) {
     content = (PolynomialDataMem) (dt_mem[i]->content);
     N_VDestroy(content->y);
-    if (IMstoreSensi) {
-      N_VDestroyVectorArray(content->yS, Ns);
+    if (ca_mem->ca_IMstoreSensi) {
+      N_VDestroyVectorArray(content->yS, cv_mem->cv_Ns);
     }
     free(dt_mem[i]->content); dt_mem[i]->content = NULL;
   }
@@ -2776,14 +2666,14 @@ static int CVApolynomialStorePnt(CVodeMem cv_mem, DtpntMem d)
 
   content = (PolynomialDataMem) d->content;
 
-  N_VScale(ONE, zn[0], content->y);
+  N_VScale(ONE, cv_mem->cv_zn[0], content->y);
 
-  if (IMstoreSensi) {
-    for (is=0; is<Ns; is++) 
-      N_VScale(ONE, znS[0][is], content->yS[is]);
+  if (ca_mem->ca_IMstoreSensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) 
+      N_VScale(ONE, cv_mem->cv_znS[0][is], content->yS[is]);
   }
 
-  content->order = qu;
+  content->order = cv_mem->cv_qu;
 
   return(0);
 }
@@ -2814,7 +2704,7 @@ static int CVApolynomialGetY(CVodeMem cv_mem, realtype t,
   
   /* Local value of Ns */
  
-  NS = (IMinterpSensi && (yS != NULL)) ? Ns : 0;
+  NS = (ca_mem->ca_IMinterpSensi && (yS != NULL)) ? cv_mem->cv_Ns : 0;
 
   /* Get the index in dt_mem */
 
@@ -2837,7 +2727,7 @@ static int CVApolynomialGetY(CVodeMem cv_mem, realtype t,
 
   /* Find the direction of the forward integration */
 
-  dir = (tfinal - tinitial > ZERO) ? 1 : -1;
+  dir = (ca_mem->ca_tfinal - ca_mem->ca_tinitial > ZERO) ? 1 : -1;
 
   /* Establish the base point depending on the integration direction.
      Modify the base if there are not enough points for the current order */
@@ -2851,7 +2741,7 @@ static int CVApolynomialGetY(CVodeMem cv_mem, realtype t,
     base = indx-1;
     content = (PolynomialDataMem) (dt_mem[base]->content);
     order = content->order;
-    if (np-indx > order) base -= indx+order-np;
+    if (ca_mem->ca_np-indx > order) base -= indx+order-ca_mem->ca_np;
   }
 
   /* Recompute Y (divided differences for Newton polynomial) if needed */
@@ -2861,38 +2751,38 @@ static int CVApolynomialGetY(CVodeMem cv_mem, realtype t,
     /* Store 0-th order DD */
     if (dir == 1) {
       for(j=0;j<=order;j++) {
-        T[j] = dt_mem[base-j]->t;
+        ca_mem->ca_T[j] = dt_mem[base-j]->t;
         content = (PolynomialDataMem) (dt_mem[base-j]->content);
-        N_VScale(ONE, content->y, Y[j]);
-        for (is=0; is<NS; is++) N_VScale(ONE, content->yS[is], YS[j][is]);
+        N_VScale(ONE, content->y, ca_mem->ca_Y[j]);
+        for (is=0; is<NS; is++) N_VScale(ONE, content->yS[is], ca_mem->ca_YS[j][is]);
       }
     } else {
       for(j=0;j<=order;j++) {
-        T[j] = dt_mem[base-1+j]->t;
+        ca_mem->ca_T[j] = dt_mem[base-1+j]->t;
         content = (PolynomialDataMem) (dt_mem[base-1+j]->content);
-        N_VScale(ONE, content->y, Y[j]);
-        for (is=0; is<NS; is++) N_VScale(ONE, content->yS[is], YS[j][is]);
+        N_VScale(ONE, content->y, ca_mem->ca_Y[j]);
+        for (is=0; is<NS; is++) N_VScale(ONE, content->yS[is], ca_mem->ca_YS[j][is]);
       }
     }
 
     /* Compute higher-order DD */
     for(i=1;i<=order;i++) {
       for(j=order;j>=i;j--) {
-        factor = dt/(T[j]-T[j-i]);
-        N_VLinearSum(factor, Y[j], -factor, Y[j-1], Y[j]);
-        for (is=0; is<NS; is++) N_VLinearSum(factor, YS[j][is], -factor, YS[j-1][is], YS[j][is]);
+        factor = dt/(ca_mem->ca_T[j]-ca_mem->ca_T[j-i]);
+        N_VLinearSum(factor, ca_mem->ca_Y[j], -factor, ca_mem->ca_Y[j-1], ca_mem->ca_Y[j]);
+        for (is=0; is<NS; is++) N_VLinearSum(factor, ca_mem->ca_YS[j][is], -factor, ca_mem->ca_YS[j-1][is], ca_mem->ca_YS[j][is]);
       }
     }
   }
 
   /* Perform the actual interpolation using nested multiplications */
 
-  N_VScale(ONE, Y[order], y);
-  for (is=0; is<NS; is++) N_VScale(ONE, YS[order][is], yS[is]);
+  N_VScale(ONE, ca_mem->ca_Y[order], y);
+  for (is=0; is<NS; is++) N_VScale(ONE, ca_mem->ca_YS[order][is], yS[is]);
   for (i=order-1; i>=0; i--) {
-    factor = (t-T[i])/dt;
-    N_VLinearSum(factor, y, ONE, Y[i], y);
-    for (is=0; is<NS; is++) N_VLinearSum(factor, yS[is], ONE, YS[i][is], yS[is]);
+    factor = (t-ca_mem->ca_T[i])/dt;
+    N_VLinearSum(factor, y, ONE, ca_mem->ca_Y[i], y);
+    for (is=0; is<NS; is++) N_VLinearSum(factor, yS[is], ONE, ca_mem->ca_YS[i][is], yS[is]);
   }
 
   return(CV_SUCCESS);
@@ -2927,10 +2817,10 @@ static int CVArhs(realtype t, N_Vector yB,
 
   /* Get forward solution from interpolation */
 
-  if (IMinterpSensi)
-    flag = IMget(cv_mem, t, ytmp, yStmp);
+  if (ca_mem->ca_IMinterpSensi)
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
   else 
-    flag = IMget(cv_mem, t, ytmp, NULL);
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
 
   if (flag != CV_SUCCESS) {
     cvProcessError(cv_mem, -1, "CVODEA", "CVArhs", MSGCV_BAD_TINTERP, t);
@@ -2940,9 +2830,9 @@ static int CVArhs(realtype t, N_Vector yB,
   /* Call the user's RHS function */
 
   if (cvB_mem->cv_f_withSensi)
-    retval = (cvB_mem->cv_fs)(t, ytmp, yStmp, yB, yBdot, cvB_mem->cv_user_data);
+    retval = (cvB_mem->cv_fs)(t, ca_mem->ca_ytmp, ca_mem->ca_yStmp, yB, yBdot, cvB_mem->cv_user_data);
   else
-    retval = (cvB_mem->cv_f)(t, ytmp, yB, yBdot, cvB_mem->cv_user_data);
+    retval = (cvB_mem->cv_f)(t, ca_mem->ca_ytmp, yB, yBdot, cvB_mem->cv_user_data);
 
   return(retval);
 }
@@ -2971,17 +2861,17 @@ static int CVArhsQ(realtype t, N_Vector yB,
 
   /* Get forward solution from interpolation */
 
-  if (IMinterpSensi)
-    /* flag = */ IMget(cv_mem, t, ytmp, yStmp);
+  if (ca_mem->ca_IMinterpSensi)
+    /* flag = */ ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
   else 
-    /* flag = */ IMget(cv_mem, t, ytmp, NULL);
+    /* flag = */ ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
 
   /* Call the user's RHS function */
 
   if (cvB_mem->cv_fQ_withSensi)
-    retval = (cvB_mem->cv_fQs)(t, ytmp, yStmp, yB, qBdot, cvB_mem->cv_user_data);
+    retval = (cvB_mem->cv_fQs)(t, ca_mem->ca_ytmp, ca_mem->ca_yStmp, yB, qBdot, cvB_mem->cv_user_data);
   else
-    retval = (cvB_mem->cv_fQ)(t, ytmp, yB, qBdot, cvB_mem->cv_user_data);
+    retval = (cvB_mem->cv_fQ)(t, ca_mem->ca_ytmp, yB, qBdot, cvB_mem->cv_user_data);
 
   return(retval);
 }
diff --git a/src/cvodes/cvodea_io.c b/src/cvodes/cvodea_io.c
index 7cb8fe2..f9ca4f1 100644
--- a/src/cvodes/cvodea_io.c
+++ b/src/cvodes/cvodea_io.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer: Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -48,23 +48,6 @@
 
 /* 
  * -----------------------------------------------------------------
- * Readibility Constants
- * -----------------------------------------------------------------
- */
-
-#define IMtype      (ca_mem->ca_IMtype)
-#define ckpntData   (ca_mem->ca_ckpntData)
-#define nbckpbs     (ca_mem->ca_nbckpbs)
-
-#define t0_         (ck_mem->ck_t0)
-#define t1_         (ck_mem->ck_t1)
-#define nst_        (ck_mem->ck_nst)
-#define q_          (ck_mem->ck_q)
-#define h_          (ck_mem->ck_h)
-#define next_       (ck_mem->ck_next)
-
-/* 
- * -----------------------------------------------------------------
  * Optional input functions for ASA
  * -----------------------------------------------------------------
  */
@@ -82,13 +65,13 @@ int CVodeSetAdjNoSensi(void *cvode_mem)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetAdjNoSensi", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
-  ca_mem->ca_IMstoreSensi = FALSE;
+  ca_mem->ca_IMstoreSensi = SUNFALSE;
 
   return(CV_SUCCESS);
 }
@@ -115,14 +98,14 @@ int CVodeSetIterTypeB(void *cvode_mem, int which, int iterB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetIterTypeB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetIterTypeB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -155,14 +138,14 @@ int CVodeSetUserDataB(void *cvode_mem, int which, void *user_dataB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetUserDataB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetUserDataB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -196,14 +179,14 @@ int CVodeSetMaxOrdB(void *cvode_mem, int which, int maxordB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMaxOrdB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxOrdB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -239,14 +222,14 @@ int CVodeSetMaxNumStepsB(void *cvode_mem, int which, long int mxstepsB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxNumStepsB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -281,14 +264,14 @@ int CVodeSetStabLimDetB(void *cvode_mem, int which, booleantype stldetB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetStabLimDetB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetStabLimDetB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -323,14 +306,14 @@ int CVodeSetInitStepB(void *cvode_mem, int which, realtype hinB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetInitStepB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetInitStepB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -365,14 +348,14 @@ int CVodeSetMinStepB(void *cvode_mem, int which, realtype hminB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMinStepB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMinStepB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -407,14 +390,14 @@ int CVodeSetMaxStepB(void *cvode_mem, int which, realtype hmaxB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetMaxStepB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetMaxStepB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -456,14 +439,14 @@ int CVodeSetQuadErrConB(void *cvode_mem, int which, booleantype errconQB)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeSetQuadErrConB", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVodeSetQuadErrConB", MSGCV_BAD_WHICH);
     return(CV_ILL_INPUT);
   }
@@ -512,14 +495,14 @@ void *CVodeGetAdjCVodeBmem(void *cvode_mem, int which)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_NO_ADJ);
     return(NULL);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
-  if ( which >= nbckpbs ) {
+  if ( which >= ca_mem->ca_nbckpbs ) {
     cvProcessError(cv_mem, 0, "CVODEA", "CVodeGetAdjCVodeBmem", MSGCV_BAD_WHICH);
     return(NULL);
   }
@@ -558,7 +541,7 @@ int CVodeGetAdjCheckPointsInfo(void *cvode_mem, CVadjCheckPointRec *ckpnt)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjCheckPointsInfo", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -571,14 +554,14 @@ int CVodeGetAdjCheckPointsInfo(void *cvode_mem, CVadjCheckPointRec *ckpnt)
   while (ck_mem != NULL) {
 
     ckpnt[i].my_addr = (void *) ck_mem;
-    ckpnt[i].next_addr = (void *) next_;
-    ckpnt[i].t0 = t0_;
-    ckpnt[i].t1 = t1_;
-    ckpnt[i].nstep = nst_;
-    ckpnt[i].order = q_;
-    ckpnt[i].step = h_;
-
-    ck_mem = next_;
+    ckpnt[i].next_addr = (void *) ck_mem->ck_next;
+    ckpnt[i].t0 = ck_mem->ck_t0;
+    ckpnt[i].t1 = ck_mem->ck_t1;
+    ckpnt[i].nstep = ck_mem->ck_nst;
+    ckpnt[i].order = ck_mem->ck_q;
+    ckpnt[i].step = ck_mem->ck_h;
+
+    ck_mem = ck_mem->ck_next;
     i++;
 
   }
@@ -610,7 +593,7 @@ int CVodeGetAdjDataPointHermite(void *cvode_mem, int which,
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjDataPointHermite", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -618,7 +601,7 @@ int CVodeGetAdjDataPointHermite(void *cvode_mem, int which,
 
   dt_mem = ca_mem->dt_mem;
 
-  if (IMtype != CV_HERMITE) {
+  if (ca_mem->ca_IMtype != CV_HERMITE) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVadjGetDataPointHermite", MSGCV_WRONG_INTERP);
     return(CV_ILL_INPUT);
   }
@@ -659,7 +642,7 @@ int CVodeGetAdjDataPointPolynomial(void *cvode_mem, int which,
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjDataPointPolynomial", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
@@ -667,7 +650,7 @@ int CVodeGetAdjDataPointPolynomial(void *cvode_mem, int which,
 
   dt_mem = ca_mem->dt_mem;
 
-  if (IMtype != CV_POLYNOMIAL) {
+  if (ca_mem->ca_IMtype != CV_POLYNOMIAL) {
     cvProcessError(cv_mem, CV_ILL_INPUT, "CVODEA", "CVadjGetDataPointPolynomial", MSGCV_WRONG_INTERP);
     return(CV_ILL_INPUT);
   }
@@ -709,13 +692,13 @@ int CVodeGetAdjCurrentCheckPoint(void *cvode_mem, void **addr)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_ADJ, "CVODEA", "CVodeGetAdjCurrentCheckPoint", MSGCV_NO_ADJ);
     return(CV_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
-  *addr = (void *) ckpntData;
+  *addr = (void *) ca_mem->ca_ckpntData;
 
   return(CV_SUCCESS);
 }
diff --git a/src/cvodes/cvodes.c b/src/cvodes/cvodes.c
index 44f2494..a46e64d 100644
--- a/src/cvodes/cvodes.c
+++ b/src/cvodes/cvodes.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4826 $
- * $Date: 2016-07-26 16:00:58 -0700 (Tue, 26 Jul 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -212,15 +212,6 @@
 
 /* 
  * =================================================================
- * MACRO DEFINITIONS
- * =================================================================
- */
-
-/* Macro: loop */
-#define loop for(;;)
-
-/* 
- * =================================================================
  * CVODES PRIVATE CONSTANTS
  * =================================================================
  */
@@ -673,7 +664,7 @@ void *CVodeCreate(int lmm, int iter)
   cv_mem->cv_f          = NULL;
   cv_mem->cv_user_data  = NULL;
   cv_mem->cv_itol       = CV_NN;
-  cv_mem->cv_user_efun  = FALSE;
+  cv_mem->cv_user_efun  = SUNFALSE;
   cv_mem->cv_efun       = NULL;
   cv_mem->cv_e_data     = NULL;
   cv_mem->cv_ehfun      = cvErrHandler;
@@ -682,11 +673,11 @@ void *CVodeCreate(int lmm, int iter)
   cv_mem->cv_qmax       = maxord;
   cv_mem->cv_mxstep     = MXSTEP_DEFAULT;
   cv_mem->cv_mxhnil     = MXHNIL_DEFAULT;
-  cv_mem->cv_sldeton    = FALSE;
+  cv_mem->cv_sldeton    = SUNFALSE;
   cv_mem->cv_hin        = ZERO;
   cv_mem->cv_hmin       = HMIN_DEFAULT;
   cv_mem->cv_hmax_inv   = HMAX_INV_DEFAULT;
-  cv_mem->cv_tstopset   = FALSE;
+  cv_mem->cv_tstopset   = SUNFALSE;
   cv_mem->cv_maxcor     = NLS_MAXCOR;
   cv_mem->cv_maxnef     = MXNEF;
   cv_mem->cv_maxncf     = MXNCF;
@@ -706,25 +697,25 @@ void *CVodeCreate(int lmm, int iter)
 
   /* Set default values for quad. optional inputs */
 
-  cv_mem->cv_quadr      = FALSE;
+  cv_mem->cv_quadr      = SUNFALSE;
   cv_mem->cv_fQ         = NULL;
-  cv_mem->cv_errconQ    = FALSE;
+  cv_mem->cv_errconQ    = SUNFALSE;
   cv_mem->cv_itolQ      = CV_NN;
 
   /* Set default values for sensi. optional inputs */
 
-  cv_mem->cv_sensi      = FALSE;
+  cv_mem->cv_sensi      = SUNFALSE;
   cv_mem->cv_fS_data    = NULL;
   cv_mem->cv_fS         = cvSensRhsInternalDQ;
   cv_mem->cv_fS1        = cvSensRhs1InternalDQ;
-  cv_mem->cv_fSDQ       = TRUE;
+  cv_mem->cv_fSDQ       = SUNTRUE;
   cv_mem->cv_ifS        = CV_ONESENS;
   cv_mem->cv_DQtype     = CV_CENTERED;
   cv_mem->cv_DQrhomax   = ZERO;
   cv_mem->cv_p          = NULL;
   cv_mem->cv_pbar       = NULL;
   cv_mem->cv_plist      = NULL;
-  cv_mem->cv_errconS    = FALSE;
+  cv_mem->cv_errconS    = SUNFALSE;
   cv_mem->cv_maxcorS    = NLS_MAXCOR;
   cv_mem->cv_ncfS1      = NULL;
   cv_mem->cv_ncfnS1     = NULL;
@@ -733,16 +724,16 @@ void *CVodeCreate(int lmm, int iter)
 
   /* Set default values for quad. sensi. optional inputs */
 
-  cv_mem->cv_quadr_sensi = FALSE;
+  cv_mem->cv_quadr_sensi = SUNFALSE;
   cv_mem->cv_fQS         = NULL;
   cv_mem->cv_fQS_data    = NULL;
-  cv_mem->cv_fQSDQ       = TRUE;
-  cv_mem->cv_errconQS    = FALSE;
+  cv_mem->cv_fQSDQ       = SUNTRUE;
+  cv_mem->cv_errconQS    = SUNFALSE;
   cv_mem->cv_itolQS      = CV_NN;
 
   /* Set default for ASA */
 
-  cv_mem->cv_adj         = FALSE;
+  cv_mem->cv_adj         = SUNFALSE;
   cv_mem->cv_adj_mem     = NULL;
 
   /* Set the saved values for qmax_alloc */
@@ -758,21 +749,21 @@ void *CVodeCreate(int lmm, int iter)
 
   /* No mallocs have been done yet */
 
-  cv_mem->cv_VabstolMallocDone   = FALSE;
-  cv_mem->cv_MallocDone          = FALSE;
+  cv_mem->cv_VabstolMallocDone   = SUNFALSE;
+  cv_mem->cv_MallocDone          = SUNFALSE;
 
-  cv_mem->cv_VabstolQMallocDone  = FALSE;
-  cv_mem->cv_QuadMallocDone      = FALSE;
+  cv_mem->cv_VabstolQMallocDone  = SUNFALSE;
+  cv_mem->cv_QuadMallocDone      = SUNFALSE;
 
-  cv_mem->cv_VabstolSMallocDone  = FALSE;
-  cv_mem->cv_SabstolSMallocDone  = FALSE;
-  cv_mem->cv_SensMallocDone      = FALSE;
+  cv_mem->cv_VabstolSMallocDone  = SUNFALSE;
+  cv_mem->cv_SabstolSMallocDone  = SUNFALSE;
+  cv_mem->cv_SensMallocDone      = SUNFALSE;
 
-  cv_mem->cv_VabstolQSMallocDone = FALSE;
-  cv_mem->cv_SabstolQSMallocDone = FALSE;
-  cv_mem->cv_QuadSensMallocDone  = FALSE;
+  cv_mem->cv_VabstolQSMallocDone = SUNFALSE;
+  cv_mem->cv_SabstolQSMallocDone = SUNFALSE;
+  cv_mem->cv_QuadSensMallocDone  = SUNFALSE;
 
-  cv_mem->cv_adjMallocDone       = FALSE;
+  cv_mem->cv_adjMallocDone       = SUNFALSE;
 
   /* Return pointer to CVODES memory block */
 
@@ -781,13 +772,6 @@ void *CVodeCreate(int lmm, int iter)
 
 /*-----------------------------------------------------------------*/
 
-#define iter (cv_mem->cv_iter)  
-#define lmm  (cv_mem->cv_lmm) 
-#define lrw  (cv_mem->cv_lrw)
-#define liw  (cv_mem->cv_liw)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeInit
  * 
@@ -801,13 +785,14 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
 {
   CVodeMem cv_mem;
   booleantype nvectorOK, allocOK;
-  long int lrw1, liw1;
+  sunindextype lrw1, liw1;
   int i,k;
 
   /* Check cvode_mem */
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
@@ -815,12 +800,14 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
   /* Check for legal input parameters */
 
   if (y0==NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit", MSGCV_NULL_Y0);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit",
+                   MSGCV_NULL_Y0);
     return(CV_ILL_INPUT);
   }
 
   if (f == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit", MSGCV_NULL_F);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit",
+                   MSGCV_NULL_F);
     return(CV_ILL_INPUT);
   }
 
@@ -828,7 +815,8 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
 
   nvectorOK = cvCheckNvector(y0);
   if(!nvectorOK) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit", MSGCV_BAD_NVECTOR);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeInit",
+                   MSGCV_BAD_NVECTOR);
     return(CV_ILL_INPUT);
   }
 
@@ -847,7 +835,8 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
 
   allocOK = cvAllocVectors(cv_mem, y0);
   if (!allocOK) {
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeInit", MSGCV_MEM_FAIL);
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
@@ -878,9 +867,9 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
   cv_mem->cv_lfree  = NULL;
   cv_mem->cv_lmem   = NULL;
 
-  /* Set forceSetup to FALSE */
+  /* Set forceSetup to SUNFALSE */
 
-  cv_mem->cv_forceSetup = FALSE;
+  cv_mem->cv_forceSetup = SUNFALSE;
 
   /* Initialize zn[0] in the history array */
 
@@ -919,18 +908,13 @@ int CVodeInit(void *cvode_mem, CVRhsFn f, realtype t0, N_Vector y0)
 
   /* Problem has been successfully initialized */
 
-  cv_mem->cv_MallocDone = TRUE;
+  cv_mem->cv_MallocDone = SUNTRUE;
 
   return(CV_SUCCESS);
 }
 
 /*-----------------------------------------------------------------*/
 
-#define lrw1 (cv_mem->cv_lrw1)
-#define liw1 (cv_mem->cv_liw1)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeReInit
  *
@@ -951,22 +935,25 @@ int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0)
   /* Check cvode_mem */
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeReInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeReInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Check if cvode_mem was allocated */
 
-  if (cv_mem->cv_MallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeReInit", MSGCV_NO_MALLOC);
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeReInit",
+                   MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
 
   /* Check for legal input parameters */
 
   if (y0 == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeReInit", MSGCV_NULL_Y0);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeReInit",
+                   MSGCV_NULL_Y0);
     return(CV_ILL_INPUT);
   }
   
@@ -985,9 +972,9 @@ int CVodeReInit(void *cvode_mem, realtype t0, N_Vector y0)
   cv_mem->cv_hu     = ZERO;
   cv_mem->cv_tolsf  = ONE;
 
-  /* Set forceSetup to FALSE */
+  /* Set forceSetup to SUNFALSE */
 
-  cv_mem->cv_forceSetup = FALSE;
+  cv_mem->cv_forceSetup = SUNFALSE;
 
   /* Initialize zn[0] in the history array */
 
@@ -1049,25 +1036,29 @@ int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol)
   CVodeMem cv_mem;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSStolerances", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", 
+                   "CVodeSStolerances", MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (cv_mem->cv_MallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeSStolerances", MSGCV_NO_MALLOC);
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES",
+                   "CVodeSStolerances", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
 
   /* Check inputs */
 
   if (reltol < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSStolerances", MSGCV_BAD_RELTOL);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSStolerances", MSGCV_BAD_RELTOL);
     return(CV_ILL_INPUT);
   }
 
   if (abstol < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSStolerances", MSGCV_BAD_ABSTOL);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSStolerances", MSGCV_BAD_ABSTOL);
     return(CV_ILL_INPUT);
   }
 
@@ -1078,7 +1069,7 @@ int CVodeSStolerances(void *cvode_mem, realtype reltol, realtype abstol)
 
   cv_mem->cv_itol = CV_SS;
 
-  cv_mem->cv_user_efun = FALSE;
+  cv_mem->cv_user_efun = SUNFALSE;
   cv_mem->cv_efun = cvEwtSet;
   cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
 
@@ -1091,25 +1082,29 @@ int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
   CVodeMem cv_mem;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSVtolerances", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeSVtolerances", MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (cv_mem->cv_MallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeSVtolerances", MSGCV_NO_MALLOC);
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES",
+                   "CVodeSVtolerances", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
 
   /* Check inputs */
 
   if (reltol < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSVtolerances", MSGCV_BAD_RELTOL);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSVtolerances", MSGCV_BAD_RELTOL);
     return(CV_ILL_INPUT);
   }
 
   if (N_VMin(abstol) < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSVtolerances", MSGCV_BAD_ABSTOL);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSVtolerances", MSGCV_BAD_ABSTOL);
     return(CV_ILL_INPUT);
   }
 
@@ -1117,9 +1112,9 @@ int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
   
   if ( !(cv_mem->cv_VabstolMallocDone) ) {
     cv_mem->cv_Vabstol = N_VClone(cv_mem->cv_ewt);
-    lrw += lrw1;
-    liw += liw1;
-    cv_mem->cv_VabstolMallocDone = TRUE;
+    cv_mem->cv_lrw += cv_mem->cv_lrw1;
+    cv_mem->cv_liw += cv_mem->cv_liw1;
+    cv_mem->cv_VabstolMallocDone = SUNTRUE;
   }
 
   cv_mem->cv_reltol = reltol;
@@ -1127,7 +1122,7 @@ int CVodeSVtolerances(void *cvode_mem, realtype reltol, N_Vector abstol)
 
   cv_mem->cv_itol = CV_SV;
 
-  cv_mem->cv_user_efun = FALSE;
+  cv_mem->cv_user_efun = SUNFALSE;
   cv_mem->cv_efun = cvEwtSet;
   cv_mem->cv_e_data = NULL; /* will be set to cvode_mem in InitialSetup */
 
@@ -1140,19 +1135,21 @@ int CVodeWFtolerances(void *cvode_mem, CVEwtFn efun)
   CVodeMem cv_mem;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeWFtolerances", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeWFtolerances", MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (cv_mem->cv_MallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVodeWFtolerances", MSGCV_NO_MALLOC);
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES",
+                   "CVodeWFtolerances", MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
 
   cv_mem->cv_itol = CV_WF;
 
-  cv_mem->cv_user_efun = TRUE;
+  cv_mem->cv_user_efun = SUNTRUE;
   cv_mem->cv_efun = efun;
   cv_mem->cv_e_data = NULL; /* will be set to user_data in InitialSetup */
 
@@ -1176,11 +1173,12 @@ int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0)
 {
   CVodeMem cv_mem;
   booleantype allocOK;
-  long int lrw1Q, liw1Q;
+  sunindextype lrw1Q, liw1Q;
 
   /* Check cvode_mem */
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
@@ -1193,7 +1191,8 @@ int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0)
   /* Allocate the vectors (using yQ0 as a template) */
   allocOK = cvQuadAllocVectors(cv_mem, yQ0);
   if (!allocOK) {
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeQuadInit", MSGCV_MEM_FAIL);
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES",
+                   "CVodeQuadInit", MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
@@ -1208,8 +1207,8 @@ int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0)
   cv_mem->cv_netfQ = 0;
 
   /* Quadrature integration turned ON */
-  cv_mem->cv_quadr = TRUE;
-  cv_mem->cv_QuadMallocDone = TRUE;
+  cv_mem->cv_quadr = SUNTRUE;
+  cv_mem->cv_QuadMallocDone = SUNTRUE;
 
   /* Quadrature initialization was successfull */
   return(CV_SUCCESS);
@@ -1217,11 +1216,6 @@ int CVodeQuadInit(void *cvode_mem, CVQuadRhsFn fQ, N_Vector yQ0)
 
 /*-----------------------------------------------------------------*/
 
-#define lrw1Q (cv_mem->cv_lrw1Q)
-#define liw1Q (cv_mem->cv_liw1Q)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeQuadReInit
  *
@@ -1241,14 +1235,16 @@ int CVodeQuadReInit(void *cvode_mem, N_Vector yQ0)
 
   /* Check cvode_mem */
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadReInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeQuadReInit", MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Ckeck if quadrature was initialized? */
-  if (cv_mem->cv_QuadMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeQuadReInit", MSGCV_NO_QUAD);
+  if (cv_mem->cv_QuadMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_QUAD, "CVODES",
+                   "CVodeQuadReInit", MSGCV_NO_QUAD);
     return(CV_NO_QUAD);
   }
 
@@ -1260,7 +1256,7 @@ int CVodeQuadReInit(void *cvode_mem, N_Vector yQ0)
   cv_mem->cv_netfQ = 0;
 
   /* Quadrature integration turned ON */
-  cv_mem->cv_quadr = TRUE;
+  cv_mem->cv_quadr = SUNTRUE;
 
   /* Quadrature re-initialization was successfull */
   return(CV_SUCCESS);
@@ -1288,27 +1284,31 @@ int CVodeQuadSStolerances(void *cvode_mem, realtype reltolQ, realtype abstolQ)
   CVodeMem cv_mem;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSStolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeQuadSStolerances", MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Ckeck if quadrature was initialized? */
 
-  if (cv_mem->cv_QuadMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeQuadSStolerances", MSGCV_NO_QUAD); 
+  if (cv_mem->cv_QuadMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_QUAD, "CVODES",
+                   "CVodeQuadSStolerances", MSGCV_NO_QUAD); 
     return(CV_NO_QUAD);
   }
 
   /* Test user-supplied tolerances */
 
   if (reltolQ < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSStolerances", MSGCV_BAD_RELTOLQ);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSStolerances", MSGCV_BAD_RELTOLQ);
     return(CV_ILL_INPUT);
   }
 
   if (abstolQ < 0) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSStolerances", MSGCV_BAD_ABSTOLQ);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSStolerances", MSGCV_BAD_ABSTOLQ);
     return(CV_ILL_INPUT);
   }
 
@@ -1327,32 +1327,37 @@ int CVodeQuadSVtolerances(void *cvode_mem, realtype reltolQ, N_Vector abstolQ)
   CVodeMem cv_mem;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSVtolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeQuadSVtolerances", MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Ckeck if quadrature was initialized? */
 
-  if (cv_mem->cv_QuadMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeQuadSVtolerances", MSGCV_NO_QUAD); 
+  if (cv_mem->cv_QuadMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_QUAD, "CVODES",
+                   "CVodeQuadSVtolerances", MSGCV_NO_QUAD); 
     return(CV_NO_QUAD);
   }
 
   /* Test user-supplied tolerances */
 
   if (reltolQ < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSVtolerances", MSGCV_BAD_RELTOLQ);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSVtolerances", MSGCV_BAD_RELTOLQ);
     return(CV_ILL_INPUT);
   }
 
   if (abstolQ == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSVtolerances", MSGCV_NULL_ABSTOLQ);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSVtolerances", MSGCV_NULL_ABSTOLQ);
     return(CV_ILL_INPUT);
   }
 
   if (N_VMin(abstolQ) < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSVtolerances", MSGCV_BAD_ABSTOLQ);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSVtolerances", MSGCV_BAD_ABSTOLQ);
     return(CV_ILL_INPUT);
   }
 
@@ -1364,9 +1369,9 @@ int CVodeQuadSVtolerances(void *cvode_mem, realtype reltolQ, N_Vector abstolQ)
 
   if ( !(cv_mem->cv_VabstolQMallocDone) ) {
     cv_mem->cv_VabstolQ = N_VClone(cv_mem->cv_tempvQ);
-    lrw += lrw1Q;
-    liw += liw1Q;
-    cv_mem->cv_VabstolQMallocDone = TRUE;
+    cv_mem->cv_lrw += cv_mem->cv_lrw1Q;
+    cv_mem->cv_liw += cv_mem->cv_liw1Q;
+    cv_mem->cv_VabstolQMallocDone = SUNTRUE;
   }
   
   N_VScale(ONE, abstolQ, cv_mem->cv_VabstolQ);
@@ -1377,13 +1382,6 @@ int CVodeQuadSVtolerances(void *cvode_mem, realtype reltolQ, N_Vector abstolQ)
 
 /*-----------------------------------------------------------------*/
 
-#define stgr1alloc   (cv_mem->cv_stgr1alloc)
-#define nniS1        (cv_mem->cv_nniS1)
-#define ncfnS1       (cv_mem->cv_ncfnS1)
-#define ncfS1        (cv_mem->cv_ncfS1)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeSensInit
  *
@@ -1404,7 +1402,8 @@ int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS
   /* Check cvode_mem */
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
@@ -1412,14 +1411,16 @@ int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS
   /* Check if CVodeSensInit or CVodeSensInit1 was already called */
 
   if (cv_mem->cv_SensMallocDone) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_SENSINIT_2);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit",
+                   MSGCV_SENSINIT_2);
     return(CV_ILL_INPUT);
   }
 
   /* Check if Ns is legal */
 
   if (Ns<=0) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_BAD_NS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit",
+                   MSGCV_BAD_NS);
     return(CV_ILL_INPUT);
   }
   cv_mem->cv_Ns = Ns;
@@ -1427,14 +1428,16 @@ int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS
   /* Check if ism is compatible */
 
   if (ism==CV_STAGGERED1) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_BAD_ISM_IFS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit",
+                   MSGCV_BAD_ISM_IFS);
     return(CV_ILL_INPUT);
   }
 
   /* Check if ism is legal */
 
   if ((ism!=CV_SIMULTANEOUS) && (ism!=CV_STAGGERED)) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_BAD_ISM);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit",
+                   MSGCV_BAD_ISM);
     return(CV_ILL_INPUT);
   }
   cv_mem->cv_ism = ism;
@@ -1442,7 +1445,8 @@ int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS
   /* Check if yS0 is non-null */
 
   if (yS0 == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit", MSGCV_NULL_YS0);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit",
+                   MSGCV_NULL_YS0);
     return(CV_ILL_INPUT);
   }
 
@@ -1453,13 +1457,13 @@ int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS
 
   if (fS == NULL) {
 
-    cv_mem->cv_fSDQ = TRUE;
+    cv_mem->cv_fSDQ = SUNTRUE;
     cv_mem->cv_fS   = cvSensRhsInternalDQ;
     cv_mem->cv_fS_data = cvode_mem;
 
   } else {
 
-    cv_mem->cv_fSDQ = FALSE;
+    cv_mem->cv_fSDQ = SUNFALSE;
     cv_mem->cv_fS   = fS;
     cv_mem->cv_fS_data = cv_mem->cv_user_data;
 
@@ -1467,13 +1471,14 @@ int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS
 
   /* No memory allocation for STAGGERED1 */
 
-  stgr1alloc = FALSE;
+  cv_mem->cv_stgr1alloc = SUNFALSE;
 
   /* Allocate the vectors (using yS0[0] as a template) */
 
   allocOK = cvSensAllocVectors(cv_mem, yS0[0]);
   if (!allocOK) {
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit", MSGCV_MEM_FAIL);
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
   
@@ -1504,8 +1509,8 @@ int CVodeSensInit(void *cvode_mem, int Ns, int ism, CVSensRhsFn fS, N_Vector *yS
 
   /* Sensitivities will be computed */
 
-  cv_mem->cv_sensi = TRUE;
-  cv_mem->cv_SensMallocDone = TRUE;
+  cv_mem->cv_sensi = SUNTRUE;
+  cv_mem->cv_SensMallocDone = SUNTRUE;
 
   /* Sensitivity initialization was successfull */
 
@@ -1532,7 +1537,8 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
   /* Check cvode_mem */
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit1", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensInit1",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
@@ -1540,14 +1546,16 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
   /* Check if CVodeSensInit or CVodeSensInit1 was already called */
 
   if (cv_mem->cv_SensMallocDone) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_SENSINIT_2);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1",
+                   MSGCV_SENSINIT_2);
     return(CV_ILL_INPUT);
   }
 
   /* Check if Ns is legal */
 
   if (Ns<=0) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_BAD_NS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1",
+                   MSGCV_BAD_NS);
     return(CV_ILL_INPUT);
   }
   cv_mem->cv_Ns = Ns;
@@ -1555,7 +1563,8 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
   /* Check if ism is legal */
 
   if ((ism!=CV_SIMULTANEOUS) && (ism!=CV_STAGGERED) && (ism!=CV_STAGGERED1)) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_BAD_ISM);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1",
+                   MSGCV_BAD_ISM);
     return(CV_ILL_INPUT);
   }
   cv_mem->cv_ism = ism;
@@ -1563,7 +1572,8 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
   /* Check if yS0 is non-null */
 
   if (yS0 == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1", MSGCV_NULL_YS0);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensInit1",
+                   MSGCV_NULL_YS0);
     return(CV_ILL_INPUT);
   }
 
@@ -1574,13 +1584,13 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
 
   if (fS1 == NULL) {
 
-    cv_mem->cv_fSDQ = TRUE;
+    cv_mem->cv_fSDQ = SUNTRUE;
     cv_mem->cv_fS1  = cvSensRhs1InternalDQ;
     cv_mem->cv_fS_data = cvode_mem;
 
   } else {
 
-    cv_mem->cv_fSDQ = FALSE;
+    cv_mem->cv_fSDQ = SUNFALSE;
     cv_mem->cv_fS1  = fS1;
     cv_mem->cv_fS_data = cv_mem->cv_user_data;
 
@@ -1589,31 +1599,35 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
   /* Allocate ncfS1, ncfnS1, and nniS1 if needed */
 
   if (ism == CV_STAGGERED1) {
-    stgr1alloc = TRUE;
-    ncfS1 = NULL;
-    ncfS1 = (int*)malloc(Ns*sizeof(int));
-    ncfnS1 = NULL;
-    ncfnS1 = (long int*)malloc(Ns*sizeof(long int));
-    nniS1 = NULL;
-    nniS1 = (long int*)malloc(Ns*sizeof(long int));
-    if ( (ncfS1 == NULL) || (ncfnS1 == NULL) || (nniS1 == NULL) ) {
-      cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit1", MSGCV_MEM_FAIL);
+    cv_mem->cv_stgr1alloc = SUNTRUE;
+    cv_mem->cv_ncfS1 = NULL;
+    cv_mem->cv_ncfS1 = (int*)malloc(Ns*sizeof(int));
+    cv_mem->cv_ncfnS1 = NULL;
+    cv_mem->cv_ncfnS1 = (long int*)malloc(Ns*sizeof(long int));
+    cv_mem->cv_nniS1 = NULL;
+    cv_mem->cv_nniS1 = (long int*)malloc(Ns*sizeof(long int));
+    if ( (cv_mem->cv_ncfS1 == NULL) ||
+         (cv_mem->cv_ncfnS1 == NULL) ||
+         (cv_mem->cv_nniS1 == NULL) ) {
+      cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit1",
+                     MSGCV_MEM_FAIL);
       return(CV_MEM_FAIL);
     }
   } else {
-    stgr1alloc = FALSE;
+    cv_mem->cv_stgr1alloc = SUNFALSE;
   }
 
   /* Allocate the vectors (using yS0[0] as a template) */
 
   allocOK = cvSensAllocVectors(cv_mem, yS0[0]);
   if (!allocOK) {
-    if (stgr1alloc) {
-      free(ncfS1); ncfS1 = NULL;
-      free(ncfnS1); ncfnS1 = NULL;
-      free(nniS1); nniS1 = NULL;
+    if (cv_mem->cv_stgr1alloc) {
+      free(cv_mem->cv_ncfS1);  cv_mem->cv_ncfS1 = NULL;
+      free(cv_mem->cv_ncfnS1); cv_mem->cv_ncfnS1 = NULL;
+      free(cv_mem->cv_nniS1);  cv_mem->cv_nniS1 = NULL;
     }
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit1", MSGCV_MEM_FAIL);
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensInit1",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
   
@@ -1636,8 +1650,8 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
   cv_mem->cv_nsetupsS = 0;
   if (ism==CV_STAGGERED1)
     for (is=0; is<Ns; is++) {
-      ncfnS1[is] = 0;
-      nniS1[is] = 0;
+      cv_mem->cv_ncfnS1[is] = 0;
+      cv_mem->cv_nniS1[is] = 0;
     }
 
   /* Set default values for plist and pbar */
@@ -1649,8 +1663,8 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
 
   /* Sensitivities will be computed */
 
-  cv_mem->cv_sensi = TRUE;
-  cv_mem->cv_SensMallocDone = TRUE;
+  cv_mem->cv_sensi = SUNTRUE;
+  cv_mem->cv_SensMallocDone = SUNTRUE;
 
   /* Sensitivity initialization was successfull */
 
@@ -1659,11 +1673,6 @@ int CVodeSensInit1(void *cvode_mem, int Ns, int ism, CVSensRhs1Fn fS1, N_Vector
 
 /*-----------------------------------------------------------------*/
 
-#define Ns  (cv_mem->cv_Ns)
-#define ifS (cv_mem->cv_ifS)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeSensReInit
  *
@@ -1687,29 +1696,33 @@ int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0)
   /* Check cvode_mem */
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensReInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensReInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was sensitivity initialized? */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensReInit", MSGCV_NO_SENSI);
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensReInit",
+                   MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
   /* Check if ism is compatible */
 
-  if ((ifS==CV_ALLSENS) && (ism==CV_STAGGERED1)) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensReInit", MSGCV_BAD_ISM_IFS);
+  if ((cv_mem->cv_ifS==CV_ALLSENS) && (ism==CV_STAGGERED1)) {
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSensReInit", MSGCV_BAD_ISM_IFS);
     return(CV_ILL_INPUT);
   }
   
   /* Check if ism is legal */
 
   if ((ism!=CV_SIMULTANEOUS) && (ism!=CV_STAGGERED) && (ism!=CV_STAGGERED1)) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensReInit", MSGCV_BAD_ISM);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSensReInit", MSGCV_BAD_ISM);
     return(CV_ILL_INPUT);
   }
   cv_mem->cv_ism = ism;
@@ -1717,22 +1730,26 @@ int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0)
   /* Check if yS0 is non-null */
 
   if (yS0 == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensReInit", MSGCV_NULL_YS0);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSensReInit", MSGCV_NULL_YS0);
     return(CV_ILL_INPUT);
   }  
 
   /* Allocate ncfS1, ncfnS1, and nniS1 if needed */
 
-  if ( (ism==CV_STAGGERED1) && (stgr1alloc==FALSE) ) {
-    stgr1alloc = TRUE;
-    ncfS1 = NULL;
-    ncfS1 = (int*)malloc(Ns*sizeof(int));
-    ncfnS1 = NULL;
-    ncfnS1 = (long int*)malloc(Ns*sizeof(long int));
-    nniS1 = NULL;
-    nniS1 = (long int*)malloc(Ns*sizeof(long int));
-    if ( (ncfS1==NULL) || (ncfnS1==NULL) || (nniS1==NULL) ) {
-      cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeSensReInit", MSGCV_MEM_FAIL);
+  if ( (ism==CV_STAGGERED1) && (cv_mem->cv_stgr1alloc==SUNFALSE) ) {
+    cv_mem->cv_stgr1alloc = SUNTRUE;
+    cv_mem->cv_ncfS1 = NULL;
+    cv_mem->cv_ncfS1 = (int*)malloc(cv_mem->cv_Ns*sizeof(int));
+    cv_mem->cv_ncfnS1 = NULL;
+    cv_mem->cv_ncfnS1 = (long int*)malloc(cv_mem->cv_Ns*sizeof(long int));
+    cv_mem->cv_nniS1 = NULL;
+    cv_mem->cv_nniS1 = (long int*)malloc(cv_mem->cv_Ns*sizeof(long int));
+    if ( (cv_mem->cv_ncfS1==NULL) ||
+         (cv_mem->cv_ncfnS1==NULL) ||
+         (cv_mem->cv_nniS1==NULL) ) {
+      cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES",
+                     "CVodeSensReInit", MSGCV_MEM_FAIL);
       return(CV_MEM_FAIL);
     }
   }
@@ -1743,7 +1760,7 @@ int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0)
 
   /* Initialize znS[0] in the history array */
 
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<cv_mem->cv_Ns; is++) 
     N_VScale(ONE, yS0[is], cv_mem->cv_znS[0][is]);
 
   /* Initialize all sensitivity related counters */
@@ -1755,14 +1772,14 @@ int CVodeSensReInit(void *cvode_mem, int ism, N_Vector *yS0)
   cv_mem->cv_nniS     = 0;
   cv_mem->cv_nsetupsS = 0;
   if (ism==CV_STAGGERED1)
-    for (is=0; is<Ns; is++) {
-      ncfnS1[is] = 0;
-      nniS1[is] = 0;
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      cv_mem->cv_ncfnS1[is] = 0;
+      cv_mem->cv_nniS1[is] = 0;
     }
 
   /* Problem has been successfully re-initialized */
 
-  cv_mem->cv_sensi = TRUE;
+  cv_mem->cv_sensi = SUNTRUE;
 
   return(CV_SUCCESS);
 }
@@ -1791,33 +1808,38 @@ int CVodeSensSStolerances(void *cvode_mem, realtype reltolS, realtype *abstolS)
   int is;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensSStolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensSStolerances",
+                   MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was sensitivity initialized? */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensSStolerances", MSGCV_NO_SENSI);
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensSStolerances",
+                   MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
   /* Test user-supplied tolerances */
     
   if (reltolS < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances", MSGCV_BAD_RELTOLS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances",
+                   MSGCV_BAD_RELTOLS);
     return(CV_ILL_INPUT);
   }
 
   if (abstolS == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances", MSGCV_NULL_ABSTOLS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances",
+                   MSGCV_NULL_ABSTOLS);
     return(CV_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<cv_mem->cv_Ns; is++)
     if (abstolS[is] < ZERO) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances", MSGCV_BAD_ABSTOLS);
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSStolerances",
+                     MSGCV_BAD_ABSTOLS);
       return(CV_ILL_INPUT);
     }
 
@@ -1829,12 +1851,12 @@ int CVodeSensSStolerances(void *cvode_mem, realtype reltolS, realtype *abstolS)
 
   if ( !(cv_mem->cv_SabstolSMallocDone) ) {
     cv_mem->cv_SabstolS = NULL;
-    cv_mem->cv_SabstolS = (realtype *)malloc(Ns*sizeof(realtype));
-    lrw += Ns;
-    cv_mem->cv_SabstolSMallocDone = TRUE;
+    cv_mem->cv_SabstolS = (realtype *)malloc(cv_mem->cv_Ns*sizeof(realtype));
+    cv_mem->cv_lrw += cv_mem->cv_Ns;
+    cv_mem->cv_SabstolSMallocDone = SUNTRUE;
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<cv_mem->cv_Ns; is++)
     cv_mem->cv_SabstolS[is] = abstolS[is];
 
   return(CV_SUCCESS);
@@ -1846,35 +1868,38 @@ int CVodeSensSVtolerances(void *cvode_mem,  realtype reltolS, N_Vector *abstolS)
   int is;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensSVtolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensSVtolerances",
+                   MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was sensitivity initialized? */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensSVtolerances", MSGCV_NO_SENSI);
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensSVtolerances",
+                   MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
-  Ns = cv_mem->cv_Ns;
-
   /* Test user-supplied tolerances */
     
   if (reltolS < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_BAD_RELTOLS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSensSVtolerances", MSGCV_BAD_RELTOLS);
     return(CV_ILL_INPUT);
   }
 
   if (abstolS == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLS);
     return(CV_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<cv_mem->cv_Ns; is++) 
     if (N_VMin(abstolS[is]) < ZERO) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_BAD_ABSTOLS);
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                     "CVodeSensSVtolerances", MSGCV_BAD_ABSTOLS);
       return(CV_ILL_INPUT);
     }
 
@@ -1885,13 +1910,13 @@ int CVodeSensSVtolerances(void *cvode_mem,  realtype reltolS, N_Vector *abstolS)
   cv_mem->cv_reltolS = reltolS;
 
   if ( !(cv_mem->cv_VabstolSMallocDone) ) {
-    cv_mem->cv_VabstolS = N_VCloneVectorArray(Ns, cv_mem->cv_tempv);
-    lrw += Ns*lrw1;
-    liw += Ns*liw1;
-    cv_mem->cv_VabstolSMallocDone = TRUE;
+    cv_mem->cv_VabstolS = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempv);
+    cv_mem->cv_lrw += cv_mem->cv_Ns*cv_mem->cv_lrw1;
+    cv_mem->cv_liw += cv_mem->cv_Ns*cv_mem->cv_liw1;
+    cv_mem->cv_VabstolSMallocDone = SUNTRUE;
   }
   
-  for (is=0; is<Ns; is++)    
+  for (is=0; is<cv_mem->cv_Ns; is++)    
     N_VScale(ONE, abstolS[is], cv_mem->cv_VabstolS[is]);
 
   return(CV_SUCCESS);
@@ -1903,15 +1928,17 @@ int CVodeSensEEtolerances(void *cvode_mem)
   CVodeMem cv_mem;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensEEtolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensEEtolerances",
+                   MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was sensitivity initialized? */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensEEtolerances", MSGCV_NO_SENSI);
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSensEEtolerances",
+                   MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
@@ -1936,27 +1963,31 @@ int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0)
 
   /* Check cvode_mem */
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Check if sensitivity analysis is active */
   if (!cv_mem->cv_sensi) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensInit", MSGCV_NO_SENSI);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensInit",
+                   MSGCV_NO_SENSI);
     return(CV_ILL_INPUT);
   }
 
   /* Check if yQS0 is non-null */
   if (yQS0 == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensInit", MSGCV_NULL_YQS0);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensInit",
+                   MSGCV_NULL_YQS0);
     return(CV_ILL_INPUT);
   }
 
   /* Allocate the vectors (using yQS0[0] as a template) */
   allocOK = cvQuadSensAllocVectors(cv_mem, yQS0[0]);
   if (!allocOK) {
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeQuadSensInit", MSGCV_MEM_FAIL);
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeQuadSensInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
@@ -1967,14 +1998,14 @@ int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0)
   /* Set fQS */
   if (fQS == NULL) {
 
-    cv_mem->cv_fQSDQ = TRUE;
+    cv_mem->cv_fQSDQ = SUNTRUE;
     cv_mem->cv_fQS = cvQuadSensRhsInternalDQ;
 
     cv_mem->cv_fQS_data = cvode_mem;
 
   } else {
 
-    cv_mem->cv_fQSDQ = FALSE;
+    cv_mem->cv_fQSDQ = SUNFALSE;
     cv_mem->cv_fQS = fQS;
 
     cv_mem->cv_fQS_data = cv_mem->cv_user_data;
@@ -1982,7 +2013,7 @@ int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0)
   }
 
   /* Initialize znQS[0] in the history array */
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<cv_mem->cv_Ns; is++) 
     N_VScale(ONE, yQS0[is], cv_mem->cv_znQS[0][is]);
 
   /* Initialize all sensitivity related counters */
@@ -1991,8 +2022,8 @@ int CVodeQuadSensInit(void *cvode_mem, CVQuadSensRhsFn fQS, N_Vector *yQS0)
   cv_mem->cv_netfQS = 0;
   
   /* Quadrature sensitivities will be computed */
-  cv_mem->cv_quadr_sensi = TRUE;
-  cv_mem->cv_QuadSensMallocDone = TRUE;
+  cv_mem->cv_quadr_sensi = SUNTRUE;
+  cv_mem->cv_QuadSensMallocDone = SUNTRUE;
 
   /* Sensitivity initialization was successfull */
   return(CV_SUCCESS);
@@ -2010,26 +2041,30 @@ int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0)
 
   /* Check cvode_mem */
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensReInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensReInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Check if sensitivity analysis is active */
   if (!cv_mem->cv_sensi) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensReInit", MSGCV_NO_SENSI);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSensReInit", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
   /* Was quadrature sensitivity initialized? */
-  if (cv_mem->cv_QuadSensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSensReInit", MSGCV_NO_QUADSENSI);
+  if (cv_mem->cv_QuadSensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES",
+                   "CVodeQuadSensReInit", MSGCV_NO_QUADSENSI);
     return(CV_NO_QUADSENS);
   } 
 
   /* Check if yQS0 is non-null */
   if (yQS0 == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensReInit", MSGCV_NULL_YQS0);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSensReInit", MSGCV_NULL_YQS0);
     return(CV_ILL_INPUT);
   }
 
@@ -2038,7 +2073,7 @@ int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0)
     -----------------------------------------------*/
 
   /* Initialize znQS[0] in the history array */
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<cv_mem->cv_Ns; is++) 
     N_VScale(ONE, yQS0[is], cv_mem->cv_znQS[0][is]);
 
   /* Initialize all sensitivity related counters */
@@ -2047,7 +2082,7 @@ int CVodeQuadSensReInit(void *cvode_mem, N_Vector *yQS0)
   cv_mem->cv_netfQS = 0;
 
   /* Quadrature sensitivities will be computed */
-  cv_mem->cv_quadr_sensi = TRUE;
+  cv_mem->cv_quadr_sensi = SUNTRUE;
 
   /* Problem has been successfully re-initialized */
   return(CV_SUCCESS);
@@ -2079,40 +2114,46 @@ int CVodeQuadSensSStolerances(void *cvode_mem, realtype reltolQS, realtype *abst
   int is;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensSStolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeQuadSensSStolerances", MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Check if sensitivity was initialized */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeQuadSensSStolerances", MSGCV_NO_SENSI);
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES",
+                   "CVodeQuadSensSStolerances", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
   /* Ckeck if quadrature sensitivity was initialized? */
 
-  if (cv_mem->cv_QuadSensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSSensSStolerances", MSGCV_NO_QUADSENSI); 
+  if (cv_mem->cv_QuadSensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES",
+                   "CVodeQuadSSensSStolerances", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUAD);
   }
 
   /* Test user-supplied tolerances */
     
   if (reltolQS < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSStolerances", MSGCV_BAD_RELTOLQS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSensSStolerances", MSGCV_BAD_RELTOLQS);
     return(CV_ILL_INPUT);
   }
 
   if (abstolQS == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSStolerances", MSGCV_NULL_ABSTOLQS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSensSStolerances", MSGCV_NULL_ABSTOLQS);
     return(CV_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<cv_mem->cv_Ns; is++)
     if (abstolQS[is] < ZERO) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSStolerances", MSGCV_BAD_ABSTOLQS);
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                     "CVodeQuadSensSStolerances", MSGCV_BAD_ABSTOLQS);
       return(CV_ILL_INPUT);
     }
 
@@ -2124,12 +2165,12 @@ int CVodeQuadSensSStolerances(void *cvode_mem, realtype reltolQS, realtype *abst
 
   if ( !(cv_mem->cv_SabstolQSMallocDone) ) {
     cv_mem->cv_SabstolQS = NULL;
-    cv_mem->cv_SabstolQS = (realtype *)malloc(Ns*sizeof(realtype));
-    lrw += Ns;
-    cv_mem->cv_SabstolQSMallocDone = TRUE;
+    cv_mem->cv_SabstolQS = (realtype *)malloc(cv_mem->cv_Ns*sizeof(realtype));
+    cv_mem->cv_lrw += cv_mem->cv_Ns;
+    cv_mem->cv_SabstolQSMallocDone = SUNTRUE;
   }
   
-  for (is=0; is<Ns; is++)
+  for (is=0; is<cv_mem->cv_Ns; is++)
     cv_mem->cv_SabstolQS[is] = abstolQS[is];
 
   return(CV_SUCCESS);
@@ -2141,42 +2182,46 @@ int CVodeQuadSensSVtolerances(void *cvode_mem,  realtype reltolQS, N_Vector *abs
   int is;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeQuadSensSVtolerances", MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* check if sensitivity was initialized */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_NO_SENSI);
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES",
+                   "CVodeQuadSensSVtolerances", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
   /* Ckeck if quadrature sensitivity was initialized? */
 
-  if (cv_mem->cv_QuadSensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_NO_QUADSENSI); 
+  if (cv_mem->cv_QuadSensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES",
+                   "CVodeQuadSensSVtolerances", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUAD);
   }
 
-  Ns = cv_mem->cv_Ns;
-
   /* Test user-supplied tolerances */
     
   if (reltolQS < ZERO) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_BAD_RELTOLQS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeQuadSensSVtolerances", MSGCV_BAD_RELTOLQS);
     return(CV_ILL_INPUT);
   }
 
   if (abstolQS == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLQS);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                   "CVodeSensSVtolerances", MSGCV_NULL_ABSTOLQS);
     return(CV_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<cv_mem->cv_Ns; is++) 
     if (N_VMin(abstolQS[is]) < ZERO) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeQuadSensSVtolerances", MSGCV_BAD_ABSTOLQS);
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES",
+                     "CVodeQuadSensSVtolerances", MSGCV_BAD_ABSTOLQS);
       return(CV_ILL_INPUT);
     }
 
@@ -2187,13 +2232,13 @@ int CVodeQuadSensSVtolerances(void *cvode_mem,  realtype reltolQS, N_Vector *abs
   cv_mem->cv_reltolQS = reltolQS;
 
   if ( !(cv_mem->cv_VabstolQSMallocDone) ) {
-    cv_mem->cv_VabstolQS = N_VCloneVectorArray(Ns, cv_mem->cv_tempvQ);
-    lrw += Ns*lrw1Q;
-    liw += Ns*liw1Q;
-    cv_mem->cv_VabstolQSMallocDone = TRUE;
+    cv_mem->cv_VabstolQS = N_VCloneVectorArray(cv_mem->cv_Ns, cv_mem->cv_tempvQ);
+    cv_mem->cv_lrw += cv_mem->cv_Ns*cv_mem->cv_lrw1Q;
+    cv_mem->cv_liw += cv_mem->cv_Ns*cv_mem->cv_liw1Q;
+    cv_mem->cv_VabstolQSMallocDone = SUNTRUE;
   }
   
-  for (is=0; is<Ns; is++)    
+  for (is=0; is<cv_mem->cv_Ns; is++)    
     N_VScale(ONE, abstolQS[is], cv_mem->cv_VabstolQS[is]);
 
   return(CV_SUCCESS);
@@ -2205,22 +2250,25 @@ int CVodeQuadSensEEtolerances(void *cvode_mem)
   CVodeMem cv_mem;
 
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeQuadSensEEtolerances", MSGCV_NO_MEM);    
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES",
+                   "CVodeQuadSensEEtolerances", MSGCV_NO_MEM);    
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* check if sensitivity was initialized */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeQuadSensEEtolerances", MSGCV_NO_SENSI);
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES",
+                   "CVodeQuadSensEEtolerances", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
   /* Ckeck if quadrature sensitivity was initialized? */
 
-  if (cv_mem->cv_QuadSensMallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeQuadSensEEtolerances", MSGCV_NO_QUADSENSI); 
+  if (cv_mem->cv_QuadSensMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES",
+                   "CVodeQuadSensEEtolerances", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUAD);
   }
 
@@ -2244,30 +2292,21 @@ int CVodeSensToggleOff(void *cvode_mem)
 
   /* Check cvode_mem */
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensToggleOff", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeSensToggleOff",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Disable sensitivities */
-  cv_mem->cv_sensi = FALSE;
-  cv_mem->cv_quadr_sensi = FALSE;
+  cv_mem->cv_sensi = SUNFALSE;
+  cv_mem->cv_quadr_sensi = SUNFALSE;
 
   return(CV_SUCCESS);
 }
 
 /*-----------------------------------------------------------------*/
 
-#define gfun    (cv_mem->cv_gfun)
-#define glo     (cv_mem->cv_glo)
-#define ghi     (cv_mem->cv_ghi)
-#define grout   (cv_mem->cv_grout)
-#define iroots  (cv_mem->cv_iroots)
-#define rootdir (cv_mem->cv_rootdir)
-#define gactive (cv_mem->cv_gactive)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * CVodeRootInit
  *
@@ -2285,7 +2324,8 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
 
   /* Check cvode_mem */
   if (cvode_mem==NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeRootInit", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeRootInit",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
@@ -2296,15 +2336,15 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
      functions (changing number of gfun components), then free
      currently held memory resources */
   if ((nrt != cv_mem->cv_nrtfn) && (cv_mem->cv_nrtfn > 0)) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
-    free(gactive); gactive = NULL;
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+    free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
+    free(cv_mem->cv_gactive); cv_mem->cv_gactive = NULL;
 
-    lrw -= 3 * (cv_mem->cv_nrtfn);
-    liw -= 3 * (cv_mem->cv_nrtfn);
+    cv_mem->cv_lrw -= 3 * (cv_mem->cv_nrtfn);
+    cv_mem->cv_liw -= 3 * (cv_mem->cv_nrtfn);
 
   }
 
@@ -2312,7 +2352,7 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
      zero and cv_gfun to NULL before returning */
   if (nrt == 0) {
     cv_mem->cv_nrtfn = nrt;
-    gfun = NULL;
+    cv_mem->cv_gfun = NULL;
     return(CV_SUCCESS);
   }
 
@@ -2322,23 +2362,24 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
   /* If g != NULL then return as currently reserved memory resources
      will suffice */
   if (nrt == cv_mem->cv_nrtfn) {
-    if (g != gfun) {
+    if (g != cv_mem->cv_gfun) {
       if (g == NULL) {
-	free(glo); glo = NULL;
-	free(ghi); ghi = NULL;
-	free(grout); grout = NULL;
-	free(iroots); iroots = NULL;
-        free(rootdir); rootdir = NULL;
-        free(gactive); gactive = NULL;
-
-        lrw -= 3*nrt;
-        liw -= 3*nrt;
-
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeRootInit", MSGCV_NULL_G);
+	free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+	free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+	free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+	free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+        free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
+        free(cv_mem->cv_gactive); cv_mem->cv_gactive = NULL;
+
+        cv_mem->cv_lrw -= 3*nrt;
+        cv_mem->cv_liw -= 3*nrt;
+
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeRootInit",
+                       MSGCV_NULL_G);
         return(CV_ILL_INPUT);
       }
       else {
-	gfun = g;
+	cv_mem->cv_gfun = g;
         return(CV_SUCCESS);
       }
     }
@@ -2348,259 +2389,92 @@ int CVodeRootInit(void *cvode_mem, int nrtfn, CVRootFn g)
   /* Set variable values in CVode memory block */
   cv_mem->cv_nrtfn = nrt;
   if (g == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeRootInit", MSGCV_NULL_G);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVodeRootInit",
+                   MSGCV_NULL_G);
     return(CV_ILL_INPUT);
   }
-  else gfun = g;
+  else cv_mem->cv_gfun = g;
 
   /* Allocate necessary memory and return */
-  glo = NULL;
-  glo = (realtype *) malloc(nrt*sizeof(realtype));
-  if (glo == NULL) {
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL);
+  cv_mem->cv_glo = NULL;
+  cv_mem->cv_glo = (realtype *) malloc(nrt*sizeof(realtype));
+  if (cv_mem->cv_glo == NULL) {
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
     
-  ghi = NULL;
-  ghi = (realtype *) malloc(nrt*sizeof(realtype));
-  if (ghi == NULL) {
-    free(glo); glo = NULL;
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL);
+  cv_mem->cv_ghi = NULL;
+  cv_mem->cv_ghi = (realtype *) malloc(nrt*sizeof(realtype));
+  if (cv_mem->cv_ghi == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
     
-  grout = NULL;
-  grout = (realtype *) malloc(nrt*sizeof(realtype));
-  if (grout == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL);
+  cv_mem->cv_grout = NULL;
+  cv_mem->cv_grout = (realtype *) malloc(nrt*sizeof(realtype));
+  if (cv_mem->cv_grout == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
-  iroots = NULL;
-  iroots = (int *) malloc(nrt*sizeof(int));
-  if (iroots == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL);
+  cv_mem->cv_iroots = NULL;
+  cv_mem->cv_iroots = (int *) malloc(nrt*sizeof(int));
+  if (cv_mem->cv_iroots == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL;
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
-  rootdir = NULL;
-  rootdir = (int *) malloc(nrt*sizeof(int));
-  if (rootdir == NULL) {
-    free(glo); glo = NULL; 
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL);
+  cv_mem->cv_rootdir = NULL;
+  cv_mem->cv_rootdir = (int *) malloc(nrt*sizeof(int));
+  if (cv_mem->cv_rootdir == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL; 
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
 
-  gactive = NULL;
-  gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
-  if (gactive == NULL) {
-    free(glo); glo = NULL; 
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
-    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit", MSGCV_MEM_FAIL);
+  cv_mem->cv_gactive = NULL;
+  cv_mem->cv_gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
+  if (cv_mem->cv_gactive == NULL) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL; 
+    free(cv_mem->cv_ghi); cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout); cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+    free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
+    cvProcessError(cv_mem, CV_MEM_FAIL, "CVODES", "CVodeRootInit",
+                   MSGCV_MEM_FAIL);
     return(CV_MEM_FAIL);
   }
 
 
   /* Set default values for rootdir (both directions) */
-  for(i=0; i<nrt; i++) rootdir[i] = 0;
+  for(i=0; i<nrt; i++) cv_mem->cv_rootdir[i] = 0;
 
   /* Set default values for gactive (all active) */
-  for(i=0; i<nrt; i++) gactive[i] = TRUE;
+  for(i=0; i<nrt; i++) cv_mem->cv_gactive[i] = SUNTRUE;
 
-  lrw += 3*nrt;
-  liw += 3*nrt;
+  cv_mem->cv_lrw += 3*nrt;
+  cv_mem->cv_liw += 3*nrt;
 
   return(CV_SUCCESS);
 }
 
 /* 
  * -----------------------------------------------------------------
- * Readibility Constants
- * -----------------------------------------------------------------
- */
-
-#define f              (cv_mem->cv_f)      
-#define user_data      (cv_mem->cv_user_data) 
-#define efun           (cv_mem->cv_efun)
-#define e_data         (cv_mem->cv_e_data) 
-#define qmax           (cv_mem->cv_qmax)
-#define mxstep         (cv_mem->cv_mxstep)
-#define mxhnil         (cv_mem->cv_mxhnil)
-#define sldeton        (cv_mem->cv_sldeton)
-#define hin            (cv_mem->cv_hin)
-#define hmin           (cv_mem->cv_hmin)
-#define hmax_inv       (cv_mem->cv_hmax_inv)
-#define tstop          (cv_mem->cv_tstop)
-#define tstopset       (cv_mem->cv_tstopset)
-#define maxnef         (cv_mem->cv_maxnef)
-#define maxncf         (cv_mem->cv_maxncf)
-#define maxcor         (cv_mem->cv_maxcor)
-#define nlscoef        (cv_mem->cv_nlscoef)
-#define itol           (cv_mem->cv_itol)         
-#define reltol         (cv_mem->cv_reltol)       
-#define Sabstol        (cv_mem->cv_Sabstol) 
-#define Vabstol        (cv_mem->cv_Vabstol) 
-
-#define fQ             (cv_mem->cv_fQ)
-#define errconQ        (cv_mem->cv_errconQ)
-#define itolQ          (cv_mem->cv_itolQ)
-#define reltolQ        (cv_mem->cv_reltolQ)
-#define SabstolQ       (cv_mem->cv_SabstolQ)
-#define VabstolQ       (cv_mem->cv_VabstolQ)
-
-#define ism            (cv_mem->cv_ism)
-#define fS             (cv_mem->cv_fS)
-#define fS1            (cv_mem->cv_fS1)
-#define fS_data        (cv_mem->cv_fS_data)
-#define fSDQ           (cv_mem->cv_fSDQ)
-#define DQtype         (cv_mem->cv_DQtype)
-#define DQrhomax       (cv_mem->cv_DQrhomax)
-#define pbar           (cv_mem->cv_pbar)
-#define errconS        (cv_mem->cv_errconS)
-#define maxcorS        (cv_mem->cv_maxcorS)
-#define itolS          (cv_mem->cv_itolS)
-#define reltolS        (cv_mem->cv_reltolS)
-#define SabstolS       (cv_mem->cv_SabstolS)
-#define VabstolS       (cv_mem->cv_VabstolS)
-#define p              (cv_mem->cv_p)
-#define plist          (cv_mem->cv_plist)
-
-#define fQS            (cv_mem->cv_fQS)
-#define fQS_data       (cv_mem->cv_fQS_data)
-#define fQSDQ          (cv_mem->cv_fQSDQ)
-#define errconQS       (cv_mem->cv_errconQS)
-#define itolQS         (cv_mem->cv_itolQS)
-#define reltolQS       (cv_mem->cv_reltolQS)
-#define SabstolQS      (cv_mem->cv_SabstolQS)
-#define VabstolQS      (cv_mem->cv_VabstolQS)
-
-#define uround         (cv_mem->cv_uround)  
-#define zn             (cv_mem->cv_zn) 
-#define ewt            (cv_mem->cv_ewt)  
-#define y              (cv_mem->cv_y)
-#define acor           (cv_mem->cv_acor)
-#define tempv          (cv_mem->cv_tempv)
-#define ftemp          (cv_mem->cv_ftemp) 
-#define q              (cv_mem->cv_q)
-#define qprime         (cv_mem->cv_qprime)
-#define next_q         (cv_mem->cv_next_q)
-#define qwait          (cv_mem->cv_qwait)
-#define L              (cv_mem->cv_L)
-#define h              (cv_mem->cv_h)
-#define hprime         (cv_mem->cv_hprime)
-#define next_h         (cv_mem->cv_next_h)
-#define eta            (cv_mem->cv_eta) 
-#define etaqm1         (cv_mem->cv_etaqm1) 
-#define etaq           (cv_mem->cv_etaq) 
-#define etaqp1         (cv_mem->cv_etaqp1) 
-#define nscon          (cv_mem->cv_nscon)
-#define hscale         (cv_mem->cv_hscale)
-#define tn             (cv_mem->cv_tn)
-#define tau            (cv_mem->cv_tau)
-#define tq             (cv_mem->cv_tq)
-#define l              (cv_mem->cv_l)
-#define rl1            (cv_mem->cv_rl1)
-#define gamma          (cv_mem->cv_gamma) 
-#define gammap         (cv_mem->cv_gammap) 
-#define gamrat         (cv_mem->cv_gamrat)
-#define crate          (cv_mem->cv_crate)
-#define acnrm          (cv_mem->cv_acnrm)
-#define mnewt          (cv_mem->cv_mnewt)
-#define etamax         (cv_mem->cv_etamax)
-#define nst            (cv_mem->cv_nst)
-#define nfe            (cv_mem->cv_nfe)
-#define ncfn           (cv_mem->cv_ncfn)
-#define netf           (cv_mem->cv_netf)
-#define nni            (cv_mem->cv_nni)
-#define nsetups        (cv_mem->cv_nsetups)
-#define nhnil          (cv_mem->cv_nhnil)
-#define linit          (cv_mem->cv_linit)
-#define lsetup         (cv_mem->cv_lsetup)
-#define lsolve         (cv_mem->cv_lsolve) 
-#define lfree          (cv_mem->cv_lfree) 
-#define lmem           (cv_mem->cv_lmem) 
-#define qu             (cv_mem->cv_qu)          
-#define nstlp          (cv_mem->cv_nstlp)  
-#define h0u            (cv_mem->cv_h0u)
-#define hu             (cv_mem->cv_hu)         
-#define saved_tq5      (cv_mem->cv_saved_tq5)  
-#define indx_acor      (cv_mem->cv_indx_acor)
-#define jcur           (cv_mem->cv_jcur)         
-#define tolsf          (cv_mem->cv_tolsf)      
-#define setupNonNull   (cv_mem->cv_setupNonNull) 
-#define forceSetup     (cv_mem->cv_forceSetup)
-#define nor            (cv_mem->cv_nor)
-#define ssdat          (cv_mem->cv_ssdat)
-
-#define nrtfn          (cv_mem->cv_nrtfn)
-#define tlo            (cv_mem->cv_tlo)
-#define thi            (cv_mem->cv_thi)
-#define tretlast       (cv_mem->cv_tretlast)
-#define toutc          (cv_mem->cv_toutc)
-#define trout          (cv_mem->cv_trout)
-#define ttol           (cv_mem->cv_ttol)
-#define taskc          (cv_mem->cv_taskc)
-#define irfnd          (cv_mem->cv_irfnd)
-#define nge            (cv_mem->cv_nge)
-
-#define quadr          (cv_mem->cv_quadr)
-#define znQ            (cv_mem->cv_znQ)
-#define ewtQ           (cv_mem->cv_ewtQ)
-#define acorQ          (cv_mem->cv_acorQ)
-#define yQ             (cv_mem->cv_yQ)
-#define tempvQ         (cv_mem->cv_tempvQ)
-#define acnrmQ         (cv_mem->cv_acnrmQ)
-#define nfQe           (cv_mem->cv_nfQe)
-#define netfQ          (cv_mem->cv_netfQ)
-#define QuadMallocDone (cv_mem->cv_QuadMallocDone)
-
-#define sensi          (cv_mem->cv_sensi)
-#define znS            (cv_mem->cv_znS)
-#define ewtS           (cv_mem->cv_ewtS)
-#define acorS          (cv_mem->cv_acorS)
-#define yS             (cv_mem->cv_yS)
-#define tempvS         (cv_mem->cv_tempvS)
-#define ftempS         (cv_mem->cv_ftempS)
-#define crateS         (cv_mem->cv_crateS)
-#define acnrmS         (cv_mem->cv_acnrmS)
-#define nfSe           (cv_mem->cv_nfSe)
-#define nfeS           (cv_mem->cv_nfeS)
-#define nniS           (cv_mem->cv_nniS)
-#define ncfnS          (cv_mem->cv_ncfnS)
-#define netfS          (cv_mem->cv_netfS)
-#define nsetupsS       (cv_mem->cv_nsetupsS)
-#define stgr1alloc     (cv_mem->cv_stgr1alloc)
-#define SensMallocDone (cv_mem->cv_SensMallocDone)
-
-#define quadr_sensi    (cv_mem->cv_quadr_sensi)
-#define znQS           (cv_mem->cv_znQS)
-#define ewtQS          (cv_mem->cv_ewtQS)
-#define acorQS         (cv_mem->cv_acorQS)
-#define yQS            (cv_mem->cv_yQS)
-#define tempvQS        (cv_mem->cv_tempvQS)
-#define ftempQ         (cv_mem->cv_ftempQ) 
-#define acnrmQS        (cv_mem->cv_acnrmQS)
-#define nfQSe          (cv_mem->cv_nfQSe)
-#define nfQeS          (cv_mem->cv_nfQeS)
-#define netfQS         (cv_mem->cv_netfQS)
-
-#define QuadSensMallocDone (cv_mem->cv_QuadSensMallocDone)
-
-
-/* 
- * -----------------------------------------------------------------
  * Main solver function
  * -----------------------------------------------------------------
  */
@@ -2639,37 +2513,42 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVode", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVode",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Check if cvode_mem was allocated */
-  if (cv_mem->cv_MallocDone == FALSE) {
-    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVode", MSGCV_NO_MALLOC);
+  if (cv_mem->cv_MallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CV_NO_MALLOC, "CVODES", "CVode",
+                   MSGCV_NO_MALLOC);
     return(CV_NO_MALLOC);
   }
   
   /* Check for yout != NULL */
-  if ((y = yout) == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_YOUT_NULL);
+  if ((cv_mem->cv_y = yout) == NULL) {
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                   MSGCV_YOUT_NULL);
     return(CV_ILL_INPUT);
   }
   
   /* Check for tret != NULL */
   if (tret == NULL) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_TRET_NULL);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                   MSGCV_TRET_NULL);
     return(CV_ILL_INPUT);
   }
 
   /* Check for valid itask */
   if ( (itask != CV_NORMAL) && (itask != CV_ONE_STEP) ) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_ITASK);
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                   MSGCV_BAD_ITASK);
     return(CV_ILL_INPUT);
   }
 
-  if (itask == CV_NORMAL) toutc = tout;
-  taskc = itask;
+  if (itask == CV_NORMAL) cv_mem->cv_toutc = tout;
+  cv_mem->cv_taskc = itask;
 
   /*
    * ----------------------------------------
@@ -2683,9 +2562,9 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
    * ----------------------------------------
    */
 
-  if (nst == 0) {
+  if (cv_mem->cv_nst == 0) {
 
-    tretlast = *tret = tn;
+    cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
 
     /* Check inputs for corectness */
 
@@ -2699,89 +2578,109 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
      * If computing quadr. sensi., call fQS at (t0,y0,yS0), set znQS[1][is] = yQS'(t0), is=1,...,Ns.
      */
 
-    retval = f(tn, zn[0], zn[1], user_data); 
-    nfe++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                          cv_mem->cv_zn[1], cv_mem->cv_user_data); 
+    cv_mem->cv_nfe++;
     if (retval < 0) {
-      cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODES", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+      cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODES", "CVode",
+                     MSGCV_RHSFUNC_FAILED, cv_mem->cv_tn);
       return(CV_RHSFUNC_FAIL);
     }
     if (retval > 0) {
-      cvProcessError(cv_mem, CV_FIRST_RHSFUNC_ERR, "CVODES", "CVode", MSGCV_RHSFUNC_FIRST);
+      cvProcessError(cv_mem, CV_FIRST_RHSFUNC_ERR, "CVODES", "CVode",
+                     MSGCV_RHSFUNC_FIRST);
       return(CV_FIRST_RHSFUNC_ERR);
     }
 
-    if (quadr) {
-      retval = fQ(tn, zn[0], znQ[1], user_data);
-      nfQe++;
+    if (cv_mem->cv_quadr) {
+      retval = cv_mem->cv_fQ(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                             cv_mem->cv_znQ[1], cv_mem->cv_user_data);
+      cv_mem->cv_nfQe++;
       if (retval < 0) {
-        cvProcessError(cv_mem, CV_QRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QRHSFUNC_FAILED, tn);
+        cvProcessError(cv_mem, CV_QRHSFUNC_FAIL, "CVODES", "CVode",
+                       MSGCV_QRHSFUNC_FAILED, cv_mem->cv_tn);
         return(CV_QRHSFUNC_FAIL);
       }
       if (retval > 0) {
-        cvProcessError(cv_mem, CV_FIRST_QRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QRHSFUNC_FIRST);
+        cvProcessError(cv_mem, CV_FIRST_QRHSFUNC_ERR, "CVODES",
+                       "CVode", MSGCV_QRHSFUNC_FIRST);
         return(CV_FIRST_QRHSFUNC_ERR);
       }
     }
 
-    if (sensi) {
-      retval = cvSensRhsWrapper(cv_mem, tn, zn[0], zn[1], znS[0], znS[1], tempv, ftemp);
+    if (cv_mem->cv_sensi) {
+      retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_zn[0],
+                                cv_mem->cv_zn[1], cv_mem->cv_znS[0],
+                                cv_mem->cv_znS[1], cv_mem->cv_tempv,
+                                cv_mem->cv_ftemp);
       if (retval < 0) {
-        cvProcessError(cv_mem, CV_SRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_SRHSFUNC_FAILED, tn);
+        cvProcessError(cv_mem, CV_SRHSFUNC_FAIL, "CVODES", "CVode",
+                       MSGCV_SRHSFUNC_FAILED, cv_mem->cv_tn);
         return(CV_SRHSFUNC_FAIL);
       } 
       if (retval > 0) {
-        cvProcessError(cv_mem, CV_FIRST_SRHSFUNC_ERR, "CVODES", "CVode", MSGCV_SRHSFUNC_FIRST);
+        cvProcessError(cv_mem, CV_FIRST_SRHSFUNC_ERR, "CVODES",
+                       "CVode", MSGCV_SRHSFUNC_FIRST);
         return(CV_FIRST_SRHSFUNC_ERR);
       }
     }
 
-    if (quadr_sensi) {
-      retval = fQS(Ns, tn, zn[0], znS[0], znQ[1], znQS[1], fQS_data, tempv, tempvQ); 
-      nfQSe++;
+    if (cv_mem->cv_quadr_sensi) {
+      retval = cv_mem->cv_fQS(cv_mem->cv_Ns, cv_mem->cv_tn, cv_mem->cv_zn[0],
+                              cv_mem->cv_znS[0], cv_mem->cv_znQ[1],
+                              cv_mem->cv_znQS[1], cv_mem->cv_fQS_data,
+                              cv_mem->cv_tempv, cv_mem->cv_tempvQ); 
+      cv_mem->cv_nfQSe++;
       if (retval < 0) {
-        cvProcessError(cv_mem, CV_QSRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QSRHSFUNC_FAILED, tn);
+        cvProcessError(cv_mem, CV_QSRHSFUNC_FAIL, "CVODES", "CVode",
+                       MSGCV_QSRHSFUNC_FAILED, cv_mem->cv_tn);
         return(CV_QSRHSFUNC_FAIL);
       } 
       if (retval > 0) {
-        cvProcessError(cv_mem, CV_FIRST_QSRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QSRHSFUNC_FIRST);
+        cvProcessError(cv_mem, CV_FIRST_QSRHSFUNC_ERR, "CVODES",
+                       "CVode", MSGCV_QSRHSFUNC_FIRST);
         return(CV_FIRST_QSRHSFUNC_ERR);
       }
     }
 
     /* Test input tstop for legality. */
 
-    if (tstopset) {
-      if ( (tstop - tn)*(tout - tn) <= ZERO ) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+    if (cv_mem->cv_tstopset) {
+      if ( (cv_mem->cv_tstop - cv_mem->cv_tn)*(tout - cv_mem->cv_tn) <= ZERO ) {
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                       MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn);
         return(CV_ILL_INPUT);
       }
     }
 
     /* Set initial h (from H0 or cvHin). */
     
-    h = hin;
-    if ( (h != ZERO) && ((tout-tn)*h < ZERO) ) {
+    cv_mem->cv_h = cv_mem->cv_hin;
+    if ( (cv_mem->cv_h != ZERO) && ((tout-cv_mem->cv_tn)*cv_mem->cv_h < ZERO) ) {
       cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_H0);
       return(CV_ILL_INPUT);
     }
-    if (h == ZERO) {
+    if (cv_mem->cv_h == ZERO) {
       tout_hin = tout;
-      if ( tstopset && (tout-tn)*(tout-tstop) > ZERO ) tout_hin = tstop; 
+      if ( cv_mem->cv_tstopset &&
+           (tout-cv_mem->cv_tn)*(tout-cv_mem->cv_tstop) > ZERO )
+        tout_hin = cv_mem->cv_tstop; 
       hflag = cvHin(cv_mem, tout_hin);
       if (hflag != CV_SUCCESS) {
         istate = cvHandleFailure(cv_mem, hflag);
         return(istate);
       }
     }
-    rh = SUNRabs(h)*hmax_inv;
-    if (rh > ONE) h /= rh;
-    if (SUNRabs(h) < hmin) h *= hmin/SUNRabs(h);
+    rh = SUNRabs(cv_mem->cv_h)*cv_mem->cv_hmax_inv;
+    if (rh > ONE) cv_mem->cv_h /= rh;
+    if (SUNRabs(cv_mem->cv_h) < cv_mem->cv_hmin)
+      cv_mem->cv_h *= cv_mem->cv_hmin/SUNRabs(cv_mem->cv_h);
 
     /* Check for approach to tstop */
 
-    if (tstopset) {
-      if ( (tn + h - tstop)*h > ZERO ) 
-        h = (tstop - tn)*(ONE-FOUR*uround);
+    if (cv_mem->cv_tstopset) {
+      if ( (cv_mem->cv_tn + cv_mem->cv_h - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) 
+        cv_mem->cv_h = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround);
     }
 
     /* 
@@ -2791,31 +2690,32 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
      * If computing quadrature sensitivities,  scale znQS[1][is] by h. 
      */
 
-    hscale = h;
-    h0u    = h;
-    hprime = h;
+    cv_mem->cv_hscale = cv_mem->cv_h;
+    cv_mem->cv_h0u    = cv_mem->cv_h;
+    cv_mem->cv_hprime = cv_mem->cv_h;
 
-    N_VScale(h, zn[1], zn[1]);
+    N_VScale(cv_mem->cv_h, cv_mem->cv_zn[1], cv_mem->cv_zn[1]);
     
-    if (quadr)
-      N_VScale(h, znQ[1], znQ[1]);
+    if (cv_mem->cv_quadr)
+      N_VScale(cv_mem->cv_h, cv_mem->cv_znQ[1], cv_mem->cv_znQ[1]);
 
-    if (sensi)
-      for (is=0; is<Ns; is++) 
-        N_VScale(h, znS[1][is], znS[1][is]);
+    if (cv_mem->cv_sensi)
+      for (is=0; is<cv_mem->cv_Ns; is++) 
+        N_VScale(cv_mem->cv_h, cv_mem->cv_znS[1][is], cv_mem->cv_znS[1][is]);
 
-    if (quadr_sensi)
-      for (is=0; is<Ns; is++) 
-        N_VScale(h, znQS[1][is], znQS[1][is]);
+    if (cv_mem->cv_quadr_sensi)
+      for (is=0; is<cv_mem->cv_Ns; is++) 
+        N_VScale(cv_mem->cv_h, cv_mem->cv_znQS[1][is], cv_mem->cv_znQS[1][is]);
     
     /* Check for zeros of root function g at and near t0. */
 
-    if (nrtfn > 0) {
+    if (cv_mem->cv_nrtfn > 0) {
 
       retval = cvRcheck1(cv_mem);
 
       if (retval == CV_RTFUNC_FAIL) {
-        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck1", MSGCV_RTFUNC_FAILED, tn);
+        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck1",
+                       MSGCV_RTFUNC_FAILED, cv_mem->cv_tn);
         return(CV_RTFUNC_FAIL);
       }
 
@@ -2835,52 +2735,56 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
    * -------------------------------------------------------
    */
 
-  if (nst > 0) {
+  if (cv_mem->cv_nst > 0) {
 
     /* Estimate an infinitesimal time interval to be used as
        a roundoff for time quantities (based on current time 
        and step size) */
-    troundoff = FUZZ_FACTOR*uround*(SUNRabs(tn) + SUNRabs(h));
+    troundoff = FUZZ_FACTOR * cv_mem->cv_uround *
+      (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h));
 
     /* First check for a root in the last step taken, other than the
        last root found, if any.  If itask = CV_ONE_STEP and y(tn) was not
        returned because of an intervening root, return y(tn) now.     */
-    if (nrtfn > 0) {
+    if (cv_mem->cv_nrtfn > 0) {
       
-      irfndp = irfnd;
+      irfndp = cv_mem->cv_irfnd;
       
       retval = cvRcheck2(cv_mem);
 
       if (retval == CLOSERT) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvRcheck2", MSGCV_CLOSE_ROOTS, tlo);
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvRcheck2",
+                       MSGCV_CLOSE_ROOTS, cv_mem->cv_tlo);
         return(CV_ILL_INPUT);
       } else if (retval == CV_RTFUNC_FAIL) {
-        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck2", MSGCV_RTFUNC_FAILED, tlo);
+        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck2",
+                       MSGCV_RTFUNC_FAILED, cv_mem->cv_tlo);
         return(CV_RTFUNC_FAIL);
       } else if (retval == RTFOUND) {
-        tretlast = *tret = tlo;
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tlo;
         return(CV_ROOT_RETURN);
       }
       
       /* If tn is distinct from tretlast (within roundoff),
          check remaining interval for roots */
-      if ( SUNRabs(tn - tretlast) > troundoff ) {
+      if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tretlast) > troundoff ) {
 
         retval = cvRcheck3(cv_mem);
 
         if (retval == CV_SUCCESS) {     /* no root found */
-          irfnd = 0;
+          cv_mem->cv_irfnd = 0;
           if ((irfndp == 1) && (itask == CV_ONE_STEP)) {
-            tretlast = *tret = tn;
-            N_VScale(ONE, zn[0], yout);
+            cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+            N_VScale(ONE, cv_mem->cv_zn[0], yout);
             return(CV_SUCCESS);
           }
         } else if (retval == RTFOUND) {  /* a new root was found */
-          irfnd = 1;
-          tretlast = *tret = tlo;
+          cv_mem->cv_irfnd = 1;
+          cv_mem->cv_tretlast = *tret = cv_mem->cv_tlo;
           return(CV_ROOT_RETURN);
         } else if (retval == CV_RTFUNC_FAIL) {  /* g failed */
-          cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck3", MSGCV_RTFUNC_FAILED, tlo);
+          cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck3", 
+                         MSGCV_RTFUNC_FAILED, cv_mem->cv_tlo);
           return(CV_RTFUNC_FAIL);
         }
 
@@ -2889,41 +2793,44 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     } /* end of root stop check */
     
     /* In CV_NORMAL mode, test if tout was reached */
-    if ( (itask == CV_NORMAL) && ((tn-tout)*h >= ZERO) ) {
-      tretlast = *tret = tout;
+    if ( (itask == CV_NORMAL) && ((cv_mem->cv_tn-tout)*cv_mem->cv_h >= ZERO) ) {
+      cv_mem->cv_tretlast = *tret = tout;
       ier =  CVodeGetDky(cv_mem, tout, 0, yout);
       if (ier != CV_SUCCESS) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TOUT, tout);
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                       MSGCV_BAD_TOUT, tout);
         return(CV_ILL_INPUT);
       }
       return(CV_SUCCESS);
     }
     
     /* In CV_ONE_STEP mode, test if tn was returned */
-    if ( itask == CV_ONE_STEP && SUNRabs(tn - tretlast) > troundoff ) {
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
+    if ( itask == CV_ONE_STEP &&
+         SUNRabs(cv_mem->cv_tn - cv_mem->cv_tretlast) > troundoff ) {
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
       return(CV_SUCCESS);
     }
     
     /* Test for tn at tstop or near tstop */
-    if ( tstopset ) {
+    if ( cv_mem->cv_tstopset ) {
       
-      if ( SUNRabs(tn - tstop) <= troundoff ) {
-        ier =  CVodeGetDky(cv_mem, tstop, 0, yout);
+      if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff ) {
+        ier =  CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout);
         if (ier != CV_SUCCESS) {
-          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_BAD_TSTOP, tstop, tn);
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                         MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn);
           return(CV_ILL_INPUT);
         }
-        tretlast = *tret = tstop;
-        tstopset = FALSE;
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop;
+        cv_mem->cv_tstopset = SUNFALSE;
         return(CV_TSTOP_RETURN);
       }
       
       /* If next step would overtake tstop, adjust stepsize */
-      if ( (tn + hprime - tstop)*h > ZERO ) {
-        hprime = (tstop - tn)*(ONE-FOUR*uround);
-        eta = hprime/h;
+      if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) {
+        cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround);
+        cv_mem->cv_eta = cv_mem->cv_hprime / cv_mem->cv_h;
       }
       
     }
@@ -2947,53 +2854,60 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
    */  
   
   nstloc = 0;
-  loop {
+  for(;;) {
    
-    next_h = h;
-    next_q = q;
+    cv_mem->cv_next_h = cv_mem->cv_h;
+    cv_mem->cv_next_q = cv_mem->cv_q;
     
     /* Reset and check ewt, ewtQ, ewtS */   
-    if (nst > 0) {
+    if (cv_mem->cv_nst > 0) {
 
-      ier = efun(zn[0], ewt, e_data);
+      ier = cv_mem->cv_efun(cv_mem->cv_zn[0], cv_mem->cv_ewt, cv_mem->cv_e_data);
       if(ier != 0) {
-        if (itol == CV_WF) cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWT_NOW_FAIL, tn);
-        else               cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWT_NOW_BAD, tn);
+        if (cv_mem->cv_itol == CV_WF)
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                         MSGCV_EWT_NOW_FAIL, cv_mem->cv_tn);
+        else
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                         MSGCV_EWT_NOW_BAD, cv_mem->cv_tn);
         istate = CV_ILL_INPUT;
-        tretlast = *tret = tn;
-        N_VScale(ONE, zn[0], yout);
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+        N_VScale(ONE, cv_mem->cv_zn[0], yout);
         break;
       }
 
-      if (quadr && errconQ) {
-        ier = cvQuadEwtSet(cv_mem, znQ[0], ewtQ);
+      if (cv_mem->cv_quadr && cv_mem->cv_errconQ) {
+        ier = cvQuadEwtSet(cv_mem, cv_mem->cv_znQ[0], cv_mem->cv_ewtQ);
         if(ier != 0) {
-          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTQ_NOW_BAD, tn);
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                         MSGCV_EWTQ_NOW_BAD, cv_mem->cv_tn);
           istate = CV_ILL_INPUT;
-          tretlast = *tret = tn;
-          N_VScale(ONE, zn[0], yout);
+          cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+          N_VScale(ONE, cv_mem->cv_zn[0], yout);
           break;
         }
       }
 
-      if (sensi) {
-        ier = cvSensEwtSet(cv_mem, znS[0], ewtS);
+      if (cv_mem->cv_sensi) {
+        ier = cvSensEwtSet(cv_mem, cv_mem->cv_znS[0], cv_mem->cv_ewtS);
         if (ier != 0) {
-          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTS_NOW_BAD, tn);
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                         MSGCV_EWTS_NOW_BAD, cv_mem->cv_tn);
           istate = CV_ILL_INPUT;
-          tretlast = *tret = tn;
-          N_VScale(ONE, zn[0], yout);
+          cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+          N_VScale(ONE, cv_mem->cv_zn[0], yout);
           break;
         }
       }
 
-      if (quadr_sensi && errconQS) {
-        ier = cvQuadSensEwtSet(cv_mem, znQS[0], ewtQS);
+      if (cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS) {
+        ier = cvQuadSensEwtSet(cv_mem, cv_mem->cv_znQS[0], cv_mem->cv_ewtQS);
         if (ier != 0) {
-          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", MSGCV_EWTQS_NOW_BAD, tn);
+          cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode",
+                         MSGCV_EWTQS_NOW_BAD, cv_mem->cv_tn);
           istate = CV_ILL_INPUT;
-          tretlast = *tret = tn;
-          N_VScale(ONE, zn[0], yout);
+          cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+          N_VScale(ONE, cv_mem->cv_zn[0], yout);
           break;
         }
       }
@@ -3001,43 +2915,46 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     }
 
     /* Check for too many steps */
-    if ( (mxstep>0) && (nstloc >= mxstep) ) {
-      cvProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODES", "CVode", MSGCV_MAX_STEPS, tn);
+    if ( (cv_mem->cv_mxstep>0) && (nstloc >= cv_mem->cv_mxstep) ) {
+      cvProcessError(cv_mem, CV_TOO_MUCH_WORK, "CVODES", "CVode",
+                     MSGCV_MAX_STEPS, cv_mem->cv_tn);
       istate = CV_TOO_MUCH_WORK;
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
       break;
     }
 
     /* Check for too much accuracy requested */
-    nrm = N_VWrmsNorm(zn[0], ewt);
-    if (quadr && errconQ) {
-      nrm = cvQuadUpdateNorm(cv_mem, nrm, znQ[0], ewtQ); 
+    nrm = N_VWrmsNorm(cv_mem->cv_zn[0], cv_mem->cv_ewt);
+    if (cv_mem->cv_quadr && cv_mem->cv_errconQ) {
+      nrm = cvQuadUpdateNorm(cv_mem, nrm, cv_mem->cv_znQ[0], cv_mem->cv_ewtQ); 
     }
-    if (sensi && errconS) {
-      nrm = cvSensUpdateNorm(cv_mem, nrm, znS[0], ewtS);
+    if (cv_mem->cv_sensi && cv_mem->cv_errconS) {
+      nrm = cvSensUpdateNorm(cv_mem, nrm, cv_mem->cv_znS[0], cv_mem->cv_ewtS);
     }
-    if (quadr_sensi && errconQS) {
-      nrm = cvQuadSensUpdateNorm(cv_mem, nrm, znQS[0], ewtQS);
+    if (cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS) {
+      nrm = cvQuadSensUpdateNorm(cv_mem, nrm, cv_mem->cv_znQS[0], cv_mem->cv_ewtQS);
     }
-    tolsf = uround * nrm;
-    if (tolsf > ONE) {
-      cvProcessError(cv_mem, CV_TOO_MUCH_ACC, "CVODES", "CVode", MSGCV_TOO_MUCH_ACC, tn);
+    cv_mem->cv_tolsf = cv_mem->cv_uround * nrm;
+    if (cv_mem->cv_tolsf > ONE) {
+      cvProcessError(cv_mem, CV_TOO_MUCH_ACC, "CVODES", "CVode",
+                     MSGCV_TOO_MUCH_ACC, cv_mem->cv_tn);
       istate = CV_TOO_MUCH_ACC;
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
-      tolsf *= TWO;
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
+      cv_mem->cv_tolsf *= TWO;
       break;
     } else {
-      tolsf = ONE;
+      cv_mem->cv_tolsf = ONE;
     }
     
     /* Check for h below roundoff level in tn */
-    if (tn + h == tn) {
-      nhnil++;
-      if (nhnil <= mxhnil) 
-        cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_HNIL, tn, h);
-      if (nhnil == mxhnil) 
+    if (cv_mem->cv_tn + cv_mem->cv_h == cv_mem->cv_tn) {
+      cv_mem->cv_nhnil++;
+      if (cv_mem->cv_nhnil <= cv_mem->cv_mxhnil) 
+        cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_HNIL,
+                       cv_mem->cv_tn, cv_mem->cv_h);
+      if (cv_mem->cv_nhnil == cv_mem->cv_mxhnil) 
         cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_HNIL_DONE);
     }
 
@@ -3047,31 +2964,34 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     /* Process failed step cases, and exit loop */
     if (kflag != CV_SUCCESS) {
       istate = cvHandleFailure(cv_mem, kflag);
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
       break;
     }
     
     nstloc++;
 
     /* If tstop is set and was reached, reset tn = tstop */
-    if ( tstopset ) {
-      troundoff = FUZZ_FACTOR*uround*(SUNRabs(tn) + SUNRabs(h));
-      if ( SUNRabs(tn - tstop) <= troundoff) tn = tstop;
+    if ( cv_mem->cv_tstopset ) {
+      troundoff = FUZZ_FACTOR * cv_mem->cv_uround *
+        (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h));
+      if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff)
+        cv_mem->cv_tn = cv_mem->cv_tstop;
     }
 
     /* Check for root in last step taken. */    
-    if (nrtfn > 0) {
+    if (cv_mem->cv_nrtfn > 0) {
       
       retval = cvRcheck3(cv_mem);
       
       if (retval == RTFOUND) {  /* A new root was found */
-        irfnd = 1;
+        cv_mem->cv_irfnd = 1;
         istate = CV_ROOT_RETURN;
-        tretlast = *tret = tlo;
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tlo;
         break;
       } else if (retval == CV_RTFUNC_FAIL) { /* g failed */
-        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck3", MSGCV_RTFUNC_FAILED, tlo);
+        cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "cvRcheck3",
+                       MSGCV_RTFUNC_FAILED, cv_mem->cv_tlo);
         istate = CV_RTFUNC_FAIL;
         break;
       }
@@ -3081,46 +3001,48 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
        * as this may indicate a user error in the implementation
        * of the root function. */
 
-      if (nst==1) {
-        inactive_roots = FALSE;
-        for (ir=0; ir<nrtfn; ir++) { 
-          if (!gactive[ir]) {
-            inactive_roots = TRUE;
+      if (cv_mem->cv_nst==1) {
+        inactive_roots = SUNFALSE;
+        for (ir=0; ir<cv_mem->cv_nrtfn; ir++) { 
+          if (!cv_mem->cv_gactive[ir]) {
+            inactive_roots = SUNTRUE;
             break;
           }
         }
         if ((cv_mem->cv_mxgnull > 0) && inactive_roots) {
-          cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode", MSGCV_INACTIVE_ROOTS);
+          cvProcessError(cv_mem, CV_WARNING, "CVODES", "CVode",
+                         MSGCV_INACTIVE_ROOTS);
         }
       }
 
     }
 
     /* In NORMAL mode, check if tout reached */
-    if ( (itask == CV_NORMAL) &&  (tn-tout)*h >= ZERO ) {
+    if ( (itask == CV_NORMAL) &&  (cv_mem->cv_tn-tout)*cv_mem->cv_h >= ZERO ) {
       istate = CV_SUCCESS;
-      tretlast = *tret = tout;
+      cv_mem->cv_tretlast = *tret = tout;
       (void) CVodeGetDky(cv_mem, tout, 0, yout);
-      next_q = qprime;
-      next_h = hprime;
+      cv_mem->cv_next_q = cv_mem->cv_qprime;
+      cv_mem->cv_next_h = cv_mem->cv_hprime;
       break;
     }
 
     /* Check if tn is at tstop, or about to pass tstop */
-    if ( tstopset ) {
-
-      troundoff = FUZZ_FACTOR*uround*(SUNRabs(tn) + SUNRabs(h));
-      if ( SUNRabs(tn - tstop) <= troundoff) {
-        (void) CVodeGetDky(cv_mem, tstop, 0, yout);
-        tretlast = *tret = tstop;
-        tstopset = FALSE;
+    if ( cv_mem->cv_tstopset ) {
+
+      troundoff = FUZZ_FACTOR * cv_mem->cv_uround *
+        (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h));
+      if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff) {
+        (void) CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout);
+        cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop;
+        cv_mem->cv_tstopset = SUNFALSE;
         istate = CV_TSTOP_RETURN;
         break;
       }
 
-      if ( (tn + hprime - tstop)*h > ZERO ) {
-        hprime = (tstop - tn)*(ONE-FOUR*uround);
-        eta = hprime/h;
+      if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) {
+        cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround);
+        cv_mem->cv_eta = cv_mem->cv_hprime / cv_mem->cv_h;
       }
 
     }
@@ -3128,22 +3050,22 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout,
     /* In ONE_STEP mode, copy y and exit loop */
     if (itask == CV_ONE_STEP) {
       istate = CV_SUCCESS;
-      tretlast = *tret = tn;
-      N_VScale(ONE, zn[0], yout);
-      next_q = qprime;
-      next_h = hprime;
+      cv_mem->cv_tretlast = *tret = cv_mem->cv_tn;
+      N_VScale(ONE, cv_mem->cv_zn[0], yout);
+      cv_mem->cv_next_q = cv_mem->cv_qprime;
+      cv_mem->cv_next_h = cv_mem->cv_hprime;
       break;
     }
 
   } /* end looping for internal steps */
   
   /* Load optional output */
-  if (sensi && (ism==CV_STAGGERED1)) { 
-    nniS  = 0;
-    ncfnS = 0;
-    for (is=0; is<Ns; is++) {
-      nniS  += nniS1[is];
-      ncfnS += ncfnS1[is];
+  if (cv_mem->cv_sensi && (cv_mem->cv_ism==CV_STAGGERED1)) { 
+    cv_mem->cv_nniS  = 0;
+    cv_mem->cv_ncfnS = 0;
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      cv_mem->cv_nniS  += cv_mem->cv_nniS1[is];
+      cv_mem->cv_ncfnS += cv_mem->cv_ncfnS1[is];
     }
   }
   
@@ -3193,35 +3115,37 @@ int CVodeGetDky(void *cvode_mem, realtype t, int k, N_Vector dky)
     return(CV_BAD_DKY);
   }
 
-  if ((k < 0) || (k > q)) {
+  if ((k < 0) || (k > cv_mem->cv_q)) {
     cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetDky", MSGCV_BAD_K);
     return(CV_BAD_K);
   }
   
   /* Allow for some slack */
-  tfuzz = FUZZ_FACTOR * uround * (SUNRabs(tn) + SUNRabs(hu));
-  if (hu < ZERO) tfuzz = -tfuzz;
-  tp = tn - hu - tfuzz;
-  tn1 = tn + tfuzz;
+  tfuzz = FUZZ_FACTOR * cv_mem->cv_uround *
+    (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_hu));
+  if (cv_mem->cv_hu < ZERO) tfuzz = -tfuzz;
+  tp = cv_mem->cv_tn - cv_mem->cv_hu - tfuzz;
+  tn1 = cv_mem->cv_tn + tfuzz;
   if ((t-tp)*(t-tn1) > ZERO) {
-    cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetDky", MSGCV_BAD_T, t, tn-hu, tn);
+    cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetDky", MSGCV_BAD_T,
+                   t, cv_mem->cv_tn-cv_mem->cv_hu, cv_mem->cv_tn);
     return(CV_BAD_T);
   }
 
   /* Sum the differentiated interpolating polynomial */
 
-  s = (t - tn) / h;
-  for (j=q; j >= k; j--) {
+  s = (t - cv_mem->cv_tn) / cv_mem->cv_h;
+  for (j=cv_mem->cv_q; j >= k; j--) {
     c = ONE;
     for (i=j; i >= j-k+1; i--) c *= i;
-    if (j == q) {
-      N_VScale(c, zn[q], dky);
+    if (j == cv_mem->cv_q) {
+      N_VScale(c, cv_mem->cv_zn[cv_mem->cv_q], dky);
     } else {
-      N_VLinearSum(c, zn[j], s, dky, dky);
+      N_VLinearSum(c, cv_mem->cv_zn[j], s, dky, dky);
     }
   }
   if (k == 0) return(CV_SUCCESS);
-  r = SUNRpowerI(h,-k);
+  r = SUNRpowerI(cv_mem->cv_h, -k);
   N_VScale(r, dky, dky);
   return(CV_SUCCESS);
 }
@@ -3245,9 +3169,9 @@ int CVodeGetQuad(void *cvode_mem, realtype *tret, N_Vector yQout)
   }
   cv_mem = (CVodeMem) cvode_mem;  
 
-  *tret = tretlast;
+  *tret = cv_mem->cv_tretlast;
   
-  flag = CVodeGetQuadDky(cvode_mem,tretlast,0,yQout);
+  flag = CVodeGetQuadDky(cvode_mem,cv_mem->cv_tretlast,0,yQout);
 
   return(flag);
 }
@@ -3281,7 +3205,7 @@ int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dkyQ)
   }
   cv_mem = (CVodeMem) cvode_mem;  
 
-  if(quadr != TRUE) {
+  if(cv_mem->cv_quadr != SUNTRUE) {
     cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadDky", MSGCV_NO_QUAD);
     return(CV_NO_QUAD);
   }
@@ -3291,16 +3215,17 @@ int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dkyQ)
     return(CV_BAD_DKY);
   }
   
-  if ((k < 0) || (k > q)) {
+  if ((k < 0) || (k > cv_mem->cv_q)) {
     cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetQuadDky", MSGCV_BAD_K);
     return(CV_BAD_K);
   }
   
   /* Allow for some slack */
-  tfuzz = FUZZ_FACTOR * uround * (SUNRabs(tn) + SUNRabs(hu));
-  if (hu < ZERO) tfuzz = -tfuzz;
-  tp = tn - hu - tfuzz;
-  tn1 = tn + tfuzz;
+  tfuzz = FUZZ_FACTOR * cv_mem->cv_uround *
+    (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_hu));
+  if (cv_mem->cv_hu < ZERO) tfuzz = -tfuzz;
+  tp = cv_mem->cv_tn - cv_mem->cv_hu - tfuzz;
+  tn1 = cv_mem->cv_tn + tfuzz;
   if ((t-tp)*(t-tn1) > ZERO) {
     cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetQuadDky", MSGCV_BAD_T);
     return(CV_BAD_T);
@@ -3308,18 +3233,18 @@ int CVodeGetQuadDky(void *cvode_mem, realtype t, int k, N_Vector dkyQ)
   
   /* Sum the differentiated interpolating polynomial */
   
-  s = (t - tn) / h;
-  for (j=q; j >= k; j--) {
+  s = (t - cv_mem->cv_tn) / cv_mem->cv_h;
+  for (j=cv_mem->cv_q; j >= k; j--) {
     c = ONE;
     for (i=j; i >= j-k+1; i--) c *= i;
-    if (j == q) {
-      N_VScale(c, znQ[q], dkyQ);
+    if (j == cv_mem->cv_q) {
+      N_VScale(c, cv_mem->cv_znQ[cv_mem->cv_q], dkyQ);
     } else {
-      N_VLinearSum(c, znQ[j], s, dkyQ, dkyQ);
+      N_VLinearSum(c, cv_mem->cv_znQ[j], s, dkyQ, dkyQ);
     }
   }
   if (k == 0) return(CV_SUCCESS);
-  r = SUNRpowerI(h,-k);
+  r = SUNRpowerI(cv_mem->cv_h, -k);
   N_VScale(r, dkyQ, dkyQ);
   return(CV_SUCCESS);
   
@@ -3344,9 +3269,9 @@ int CVodeGetSens(void *cvode_mem, realtype *tret, N_Vector *ySout)
   }
   cv_mem = (CVodeMem) cvode_mem;  
 
-  *tret = tretlast;
+  *tret = cv_mem->cv_tretlast;
 
-  flag = CVodeGetSensDky(cvode_mem,tretlast,0,ySout);
+  flag = CVodeGetSensDky(cvode_mem,cv_mem->cv_tretlast,0,ySout);
 
   return(flag);
 }
@@ -3370,9 +3295,9 @@ int CVodeGetSens1(void *cvode_mem, realtype *tret, int is, N_Vector ySout)
   }
   cv_mem = (CVodeMem) cvode_mem;  
 
-  *tret = tretlast;
+  *tret = cv_mem->cv_tretlast;
 
-  flag = CVodeGetSensDky1(cvode_mem,tretlast,0,is,ySout);
+  flag = CVodeGetSensDky1(cvode_mem,cv_mem->cv_tretlast,0,is,ySout);
 
   return(flag);
 }
@@ -3399,11 +3324,12 @@ int CVodeGetSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyS)
   cv_mem = (CVodeMem) cvode_mem;  
   
   if (dkyS == NULL) {
-    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky", MSGCV_NULL_DKYA);
+    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES",
+                   "CVodeGetSensDky", MSGCV_NULL_DKYA);
     return(CV_BAD_DKY);
   }
   
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<cv_mem->cv_Ns; is++) {
     ier = CVodeGetSensDky1(cvode_mem,t,k,is,dkyS[is]);
     if (ier!=CV_SUCCESS) break;
   }
@@ -3435,55 +3361,62 @@ int CVodeGetSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dkyS)
   /* Check all inputs for legality */
   
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensDky1", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetSensDky1",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;  
   
-  if(sensi != TRUE) {
-    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensDky1", MSGCV_NO_SENSI);
+  if(cv_mem->cv_sensi != SUNTRUE) {
+    cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensDky1",
+                   MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
   if (dkyS == NULL) {
-    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky1", MSGCV_NULL_DKY);
+    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky1",
+                   MSGCV_NULL_DKY);
     return(CV_BAD_DKY);
   }
   
-  if ((k < 0) || (k > q)) {
-    cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetSensDky1", MSGCV_BAD_K);
+  if ((k < 0) || (k > cv_mem->cv_q)) {
+    cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetSensDky1",
+                   MSGCV_BAD_K);
     return(CV_BAD_K);
   }
   
-  if ((is < 0) || (is > Ns-1)) {
-    cvProcessError(cv_mem, CV_BAD_IS, "CVODES", "CVodeGetSensDky1", MSGCV_BAD_IS);
+  if ((is < 0) || (is > cv_mem->cv_Ns-1)) {
+    cvProcessError(cv_mem, CV_BAD_IS, "CVODES", "CVodeGetSensDky1",
+                   MSGCV_BAD_IS);
     return(CV_BAD_IS);
   }
   
   /* Allow for some slack */
-  tfuzz = FUZZ_FACTOR * uround * (SUNRabs(tn) + SUNRabs(hu));
-  if (hu < ZERO) tfuzz = -tfuzz;
-  tp = tn - hu - tfuzz;
-  tn1 = tn + tfuzz;
+  tfuzz = FUZZ_FACTOR * cv_mem->cv_uround *
+    (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_hu));
+  if (cv_mem->cv_hu < ZERO) tfuzz = -tfuzz;
+  tp = cv_mem->cv_tn - cv_mem->cv_hu - tfuzz;
+  tn1 = cv_mem->cv_tn + tfuzz;
   if ((t-tp)*(t-tn1) > ZERO) {
-    cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetSensDky1", MSGCV_BAD_T);
+    cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetSensDky1",
+                   MSGCV_BAD_T);
     return(CV_BAD_T);
   }
   
   /* Sum the differentiated interpolating polynomial */
   
-  s = (t - tn) / h;
-  for (j=q; j >= k; j--) {
+  s = (t - cv_mem->cv_tn) / cv_mem->cv_h;
+  for (j=cv_mem->cv_q; j >= k; j--) {
     c = ONE;
     for (i=j; i >= j-k+1; i--) c *= i;
-    if (j == q) {
-      N_VScale(c, znS[q][is], dkyS);
+    if (j == cv_mem->cv_q) {
+      N_VScale(c, cv_mem->cv_znS[cv_mem->cv_q][is], dkyS);
     } else {
-      N_VLinearSum(c, znS[j][is], s, dkyS, dkyS);
+      N_VLinearSum(c, cv_mem->cv_znS[j][is], s, dkyS, dkyS);
     }
   }
   if (k == 0) return(CV_SUCCESS);
-  r = SUNRpowerI(h,-k);
+  r = SUNRpowerI(cv_mem->cv_h, -k);
   N_VScale(r, dkyS, dkyS);
   return(CV_SUCCESS);
   
@@ -3502,14 +3435,15 @@ int CVodeGetQuadSens(void *cvode_mem, realtype *tret, N_Vector *yQSout)
   int flag;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;  
 
-  *tret = tretlast;
+  *tret = cv_mem->cv_tretlast;
 
-  flag = CVodeGetQuadSensDky(cvode_mem,tretlast,0,yQSout);
+  flag = CVodeGetQuadSensDky(cvode_mem,cv_mem->cv_tretlast,0,yQSout);
 
   return(flag);
 }
@@ -3520,14 +3454,15 @@ int CVodeGetQuadSens1(void *cvode_mem, realtype *tret, int is, N_Vector yQSout)
   int flag;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens1", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSens1",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;  
 
-  *tret = tretlast;
+  *tret = cv_mem->cv_tretlast;
 
-  flag = CVodeGetQuadSensDky1(cvode_mem,tretlast,0,is,yQSout);
+  flag = CVodeGetQuadSensDky1(cvode_mem,cv_mem->cv_tretlast,0,is,yQSout);
 
   return(flag);
 }
@@ -3546,17 +3481,19 @@ int CVodeGetQuadSensDky(void *cvode_mem, realtype t, int k, N_Vector *dkyQS_all)
   CVodeMem cv_mem;
   
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensDky", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensDky",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;  
   
   if (dkyQS_all == NULL) {
-    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky", MSGCV_NULL_DKYA);
+    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetSensDky",
+                   MSGCV_NULL_DKYA);
     return(CV_BAD_DKY);
   }
   
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<cv_mem->cv_Ns; is++) {
     ier = CVodeGetQuadSensDky1(cvode_mem,t,k,is,dkyQS_all[is]);
     if (ier!=CV_SUCCESS) break;
   }
@@ -3574,55 +3511,62 @@ int CVodeGetQuadSensDky1(void *cvode_mem, realtype t, int k, int is, N_Vector dk
   /* Check all inputs for legality */
   
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensDky1", MSGCV_NO_MEM);
+    cvProcessError(NULL, CV_MEM_NULL, "CVODES", "CVodeGetQuadSensDky1",
+                   MSGCV_NO_MEM);
     return(CV_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;  
   
-  if(quadr_sensi != TRUE) {
-    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensDky1", MSGCV_NO_QUADSENSI);
+  if(cv_mem->cv_quadr_sensi != SUNTRUE) {
+    cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensDky1",
+                   MSGCV_NO_QUADSENSI);
     return(CV_NO_QUADSENS);
   }
 
   if (dkyQS == NULL) {
-    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetQuadSensDky1", MSGCV_NULL_DKY);
+    cvProcessError(cv_mem, CV_BAD_DKY, "CVODES", "CVodeGetQuadSensDky1",
+                   MSGCV_NULL_DKY);
     return(CV_BAD_DKY);
   }
   
-  if ((k < 0) || (k > q)) {
-    cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetQuadSensDky1", MSGCV_BAD_K);
+  if ((k < 0) || (k > cv_mem->cv_q)) {
+    cvProcessError(cv_mem, CV_BAD_K, "CVODES", "CVodeGetQuadSensDky1",
+                   MSGCV_BAD_K);
     return(CV_BAD_K);
   }
   
-  if ((is < 0) || (is > Ns-1)) {
-    cvProcessError(cv_mem, CV_BAD_IS, "CVODES", "CVodeGetQuadSensDky1", MSGCV_BAD_IS);
+  if ((is < 0) || (is > cv_mem->cv_Ns-1)) {
+    cvProcessError(cv_mem, CV_BAD_IS, "CVODES", "CVodeGetQuadSensDky1",
+                   MSGCV_BAD_IS);
     return(CV_BAD_IS);
   }
   
   /* Allow for some slack */
-  tfuzz = FUZZ_FACTOR * uround * (SUNRabs(tn) + SUNRabs(hu));
-  if (hu < ZERO) tfuzz = -tfuzz;
-  tp = tn - hu - tfuzz;
-  tn1 = tn + tfuzz;
+  tfuzz = FUZZ_FACTOR * cv_mem->cv_uround *
+    (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_hu));
+  if (cv_mem->cv_hu < ZERO) tfuzz = -tfuzz;
+  tp = cv_mem->cv_tn - cv_mem->cv_hu - tfuzz;
+  tn1 = cv_mem->cv_tn + tfuzz;
   if ((t-tp)*(t-tn1) > ZERO) {
-    cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetQuadSensDky1", MSGCV_BAD_T);
+    cvProcessError(cv_mem, CV_BAD_T, "CVODES", "CVodeGetQuadSensDky1",
+                   MSGCV_BAD_T);
     return(CV_BAD_T);
   }
   
   /* Sum the differentiated interpolating polynomial */
   
-  s = (t - tn) / h;
-  for (j=q; j >= k; j--) {
+  s = (t - cv_mem->cv_tn) / cv_mem->cv_h;
+  for (j=cv_mem->cv_q; j >= k; j--) {
     c = ONE;
     for (i=j; i >= j-k+1; i--) c *= i;
-    if (j == q) {
-      N_VScale(c, znQS[q][is], dkyQS);
+    if (j == cv_mem->cv_q) {
+      N_VScale(c, cv_mem->cv_znQS[cv_mem->cv_q][is], dkyQS);
     } else {
-      N_VLinearSum(c, znQS[j][is], s, dkyQS, dkyQS);
+      N_VLinearSum(c, cv_mem->cv_znQS[j][is], s, dkyQS, dkyQS);
     }
   }
   if (k == 0) return(CV_SUCCESS);
-  r = SUNRpowerI(h,-k);
+  r = SUNRpowerI(cv_mem->cv_h, -k);
   N_VScale(r, dkyQS, dkyQS);
   return(CV_SUCCESS);
 }
@@ -3661,15 +3605,15 @@ void CVodeFree(void **cvode_mem)
 
   CVodeAdjFree(cv_mem);
 
-  if (iter == CV_NEWTON && lfree != NULL) lfree(cv_mem);
+  if (cv_mem->cv_lfree != NULL) cv_mem->cv_lfree(cv_mem);
 
-  if (nrtfn > 0) {
-    free(glo); glo = NULL; 
-    free(ghi);  ghi = NULL;
-    free(grout);  grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
-    free(gactive); gactive = NULL;
+  if (cv_mem->cv_nrtfn > 0) {
+    free(cv_mem->cv_glo); cv_mem->cv_glo = NULL; 
+    free(cv_mem->cv_ghi);  cv_mem->cv_ghi = NULL;
+    free(cv_mem->cv_grout);  cv_mem->cv_grout = NULL;
+    free(cv_mem->cv_iroots); cv_mem->cv_iroots = NULL;
+    free(cv_mem->cv_rootdir); cv_mem->cv_rootdir = NULL;
+    free(cv_mem->cv_gactive); cv_mem->cv_gactive = NULL;
   }
 
   free(*cvode_mem);
@@ -3691,10 +3635,10 @@ void CVodeQuadFree(void *cvode_mem)
   if (cvode_mem == NULL) return;
   cv_mem = (CVodeMem) cvode_mem;
 
-  if(QuadMallocDone) {
+  if(cv_mem->cv_QuadMallocDone) {
     cvQuadFreeVectors(cv_mem);
-    QuadMallocDone = FALSE;
-    quadr = FALSE;
+    cv_mem->cv_QuadMallocDone = SUNFALSE;
+    cv_mem->cv_quadr = SUNFALSE;
   }
 }
 
@@ -3713,16 +3657,16 @@ void CVodeSensFree(void *cvode_mem)
   if (cvode_mem == NULL) return;
   cv_mem = (CVodeMem) cvode_mem;
 
-  if(SensMallocDone) {
-    if (stgr1alloc) {
-      free(ncfS1); ncfS1 = NULL;
-      free(ncfnS1); ncfnS1 = NULL;
-      free(nniS1); nniS1 = NULL;
-      stgr1alloc = FALSE;
+  if(cv_mem->cv_SensMallocDone) {
+    if (cv_mem->cv_stgr1alloc) {
+      free(cv_mem->cv_ncfS1);  cv_mem->cv_ncfS1 = NULL;
+      free(cv_mem->cv_ncfnS1); cv_mem->cv_ncfnS1 = NULL;
+      free(cv_mem->cv_nniS1);  cv_mem->cv_nniS1 = NULL;
+      cv_mem->cv_stgr1alloc = SUNFALSE;
     }
     cvSensFreeVectors(cv_mem);
-    SensMallocDone = FALSE;
-    sensi = FALSE;
+    cv_mem->cv_SensMallocDone = SUNFALSE;
+    cv_mem->cv_sensi = SUNFALSE;
   }
 }
 
@@ -3741,10 +3685,10 @@ void CVodeQuadSensFree(void *cvode_mem)
   if (cvode_mem == NULL) return;
   cv_mem = (CVodeMem) cvode_mem;
 
-  if(QuadSensMallocDone) {
+  if(cv_mem->cv_QuadSensMallocDone) {
     cvQuadSensFreeVectors(cv_mem);
-    QuadSensMallocDone = FALSE;
-    quadr_sensi = FALSE;
+    cv_mem->cv_QuadSensMallocDone = SUNFALSE;
+    cv_mem->cv_quadr_sensi = SUNFALSE;
   }
 }
 
@@ -3758,7 +3702,7 @@ void CVodeQuadSensFree(void *cvode_mem)
 /*
  * cvCheckNvector
  * This routine checks if all required vector operations are present.
- * If any of them is missing it returns FALSE.
+ * If any of them is missing it returns SUNFALSE.
  */
 
 static booleantype cvCheckNvector(N_Vector tmpl)
@@ -3776,9 +3720,9 @@ static booleantype cvCheckNvector(N_Vector tmpl)
      (tmpl->ops->nvmaxnorm   == NULL) ||
      (tmpl->ops->nvwrmsnorm  == NULL) ||
      (tmpl->ops->nvmin       == NULL))
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 /* 
@@ -3792,8 +3736,8 @@ static booleantype cvCheckNvector(N_Vector tmpl)
  *
  * This routine allocates the CVODES vectors ewt, acor, tempv, ftemp, and
  * zn[0], ..., zn[maxord].
- * If all memory allocations are successful, cvAllocVectors returns TRUE. 
- * Otherwise all allocated memory is freed and cvAllocVectors returns FALSE.
+ * If all memory allocations are successful, cvAllocVectors returns SUNTRUE. 
+ * Otherwise all allocated memory is freed and cvAllocVectors returns SUNFALSE.
  * This routine also sets the optional outputs lrw and liw, which are
  * (respectively) the lengths of the real and integer work spaces
  * allocated here.
@@ -3805,52 +3749,52 @@ static booleantype cvAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
 
   /* Allocate ewt, acor, tempv, ftemp */
   
-  ewt = N_VClone(tmpl);
-  if (ewt == NULL) return(FALSE);
+  cv_mem->cv_ewt = N_VClone(tmpl);
+  if (cv_mem->cv_ewt == NULL) return(SUNFALSE);
 
-  acor = N_VClone(tmpl);
-  if (acor == NULL) {
-    N_VDestroy(ewt);
-    return(FALSE);
+  cv_mem->cv_acor = N_VClone(tmpl);
+  if (cv_mem->cv_acor == NULL) {
+    N_VDestroy(cv_mem->cv_ewt);
+    return(SUNFALSE);
   }
 
-  tempv = N_VClone(tmpl);
-  if (tempv == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(acor);
-    return(FALSE);
+  cv_mem->cv_tempv = N_VClone(tmpl);
+  if (cv_mem->cv_tempv == NULL) {
+    N_VDestroy(cv_mem->cv_ewt);
+    N_VDestroy(cv_mem->cv_acor);
+    return(SUNFALSE);
   }
 
-  ftemp = N_VClone(tmpl);
-  if (ftemp == NULL) {
-    N_VDestroy(tempv);
-    N_VDestroy(ewt);
-    N_VDestroy(acor);
-    return(FALSE);
+  cv_mem->cv_ftemp = N_VClone(tmpl);
+  if (cv_mem->cv_ftemp == NULL) {
+    N_VDestroy(cv_mem->cv_tempv);
+    N_VDestroy(cv_mem->cv_ewt);
+    N_VDestroy(cv_mem->cv_acor);
+    return(SUNFALSE);
   }
 
   /* Allocate zn[0] ... zn[qmax] */
 
-  for (j=0; j <= qmax; j++) {
-    zn[j] = N_VClone(tmpl);
-    if (zn[j] == NULL) {
-      N_VDestroy(ewt);
-      N_VDestroy(acor);
-      N_VDestroy(tempv);
-      N_VDestroy(ftemp);
-      for (i=0; i < j; i++) N_VDestroy(zn[i]);
-      return(FALSE);
+  for (j=0; j <= cv_mem->cv_qmax; j++) {
+    cv_mem->cv_zn[j] = N_VClone(tmpl);
+    if (cv_mem->cv_zn[j] == NULL) {
+      N_VDestroy(cv_mem->cv_ewt);
+      N_VDestroy(cv_mem->cv_acor);
+      N_VDestroy(cv_mem->cv_tempv);
+      N_VDestroy(cv_mem->cv_ftemp);
+      for (i=0; i < j; i++) N_VDestroy(cv_mem->cv_zn[i]);
+      return(SUNFALSE);
     }
   }
 
   /* Update solver workspace lengths  */
-  lrw += (qmax + 5)*lrw1;
-  liw += (qmax + 5)*liw1;
+  cv_mem->cv_lrw += (cv_mem->cv_qmax + 5)*cv_mem->cv_lrw1;
+  cv_mem->cv_liw += (cv_mem->cv_qmax + 5)*cv_mem->cv_liw1;
 
   /* Store the value of qmax used here */
-  cv_mem->cv_qmax_alloc = qmax;
+  cv_mem->cv_qmax_alloc = cv_mem->cv_qmax;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*  
@@ -3865,30 +3809,30 @@ static void cvFreeVectors(CVodeMem cv_mem)
   
   maxord = cv_mem->cv_qmax_alloc;
 
-  N_VDestroy(ewt);
-  N_VDestroy(acor);
-  N_VDestroy(tempv);
-  N_VDestroy(ftemp);
-  for (j=0; j <= maxord; j++) N_VDestroy(zn[j]);
+  N_VDestroy(cv_mem->cv_ewt);
+  N_VDestroy(cv_mem->cv_acor);
+  N_VDestroy(cv_mem->cv_tempv);
+  N_VDestroy(cv_mem->cv_ftemp);
+  for (j=0; j <= maxord; j++) N_VDestroy(cv_mem->cv_zn[j]);
 
-  lrw -= (maxord + 5)*lrw1;
-  liw -= (maxord + 5)*liw1;
+  cv_mem->cv_lrw -= (maxord + 5)*cv_mem->cv_lrw1;
+  cv_mem->cv_liw -= (maxord + 5)*cv_mem->cv_liw1;
 
   if (cv_mem->cv_VabstolMallocDone) {
-    N_VDestroy(Vabstol);
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(cv_mem->cv_Vabstol);
+    cv_mem->cv_lrw -= cv_mem->cv_lrw1;
+    cv_mem->cv_liw -= cv_mem->cv_liw1;
   }
 }
 
 /*
  * CVodeQuadAllocVectors
  *
- * NOTE: Space for ewtQ is allocated even when errconQ=FALSE, 
+ * NOTE: Space for ewtQ is allocated even when errconQ=SUNFALSE, 
  * although in this case, ewtQ is never used. The reason for this
  * decision is to allow the user to re-initialize the quadrature
- * computation with errconQ=TRUE, after an initialization with
- * errconQ=FALSE, without new memory allocation within 
+ * computation with errconQ=SUNTRUE, after an initialization with
+ * errconQ=SUNFALSE, without new memory allocation within 
  * CVodeQuadReInit.
  */
 
@@ -3897,57 +3841,57 @@ static booleantype cvQuadAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
   int i, j;
 
   /* Allocate ewtQ */
-  ewtQ = N_VClone(tmpl);
-  if (ewtQ == NULL) {
-    return(FALSE);
+  cv_mem->cv_ewtQ = N_VClone(tmpl);
+  if (cv_mem->cv_ewtQ == NULL) {
+    return(SUNFALSE);
   }
   
   /* Allocate acorQ */
-  acorQ = N_VClone(tmpl);
-  if (acorQ == NULL) {
-    N_VDestroy(ewtQ);
-    return(FALSE);
+  cv_mem->cv_acorQ = N_VClone(tmpl);
+  if (cv_mem->cv_acorQ == NULL) {
+    N_VDestroy(cv_mem->cv_ewtQ);
+    return(SUNFALSE);
   }
 
   /* Allocate yQ */
-  yQ = N_VClone(tmpl);
-  if (yQ == NULL) {
-    N_VDestroy(ewtQ);
-    N_VDestroy(acorQ);
-    return(FALSE);
+  cv_mem->cv_yQ = N_VClone(tmpl);
+  if (cv_mem->cv_yQ == NULL) {
+    N_VDestroy(cv_mem->cv_ewtQ);
+    N_VDestroy(cv_mem->cv_acorQ);
+    return(SUNFALSE);
   }
 
   /* Allocate tempvQ */
-  tempvQ = N_VClone(tmpl);
-  if (tempvQ == NULL) {
-    N_VDestroy(ewtQ);
-    N_VDestroy(acorQ);
-    N_VDestroy(yQ);
-    return(FALSE);
+  cv_mem->cv_tempvQ = N_VClone(tmpl);
+  if (cv_mem->cv_tempvQ == NULL) {
+    N_VDestroy(cv_mem->cv_ewtQ);
+    N_VDestroy(cv_mem->cv_acorQ);
+    N_VDestroy(cv_mem->cv_yQ);
+    return(SUNFALSE);
   }
 
   /* Allocate zQn[0] ... zQn[maxord] */
 
-  for (j=0; j <= qmax; j++) {
-    znQ[j] = N_VClone(tmpl);
-    if (znQ[j] == NULL) {
-      N_VDestroy(ewtQ);
-      N_VDestroy(acorQ);
-      N_VDestroy(yQ);
-      N_VDestroy(tempvQ);
-      for (i=0; i < j; i++) N_VDestroy(znQ[i]);
-      return(FALSE);
+  for (j=0; j <= cv_mem->cv_qmax; j++) {
+    cv_mem->cv_znQ[j] = N_VClone(tmpl);
+    if (cv_mem->cv_znQ[j] == NULL) {
+      N_VDestroy(cv_mem->cv_ewtQ);
+      N_VDestroy(cv_mem->cv_acorQ);
+      N_VDestroy(cv_mem->cv_yQ);
+      N_VDestroy(cv_mem->cv_tempvQ);
+      for (i=0; i < j; i++) N_VDestroy(cv_mem->cv_znQ[i]);
+      return(SUNFALSE);
     }
   }
 
   /* Store the value of qmax used here */
-  cv_mem->cv_qmax_allocQ = qmax;
+  cv_mem->cv_qmax_allocQ = cv_mem->cv_qmax;
 
   /* Update solver workspace lengths */
-  lrw += (qmax + 5)*lrw1Q;
-  liw += (qmax + 5)*liw1Q;
+  cv_mem->cv_lrw += (cv_mem->cv_qmax + 5)*cv_mem->cv_lrw1Q;
+  cv_mem->cv_liw += (cv_mem->cv_qmax + 5)*cv_mem->cv_liw1Q;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -3962,23 +3906,23 @@ static void cvQuadFreeVectors(CVodeMem cv_mem)
   
   maxord = cv_mem->cv_qmax_allocQ;
 
-  N_VDestroy(ewtQ);
-  N_VDestroy(acorQ);
-  N_VDestroy(yQ);
-  N_VDestroy(tempvQ);
+  N_VDestroy(cv_mem->cv_ewtQ);
+  N_VDestroy(cv_mem->cv_acorQ);
+  N_VDestroy(cv_mem->cv_yQ);
+  N_VDestroy(cv_mem->cv_tempvQ);
   
-  for (j=0; j<=maxord; j++) N_VDestroy(znQ[j]);
+  for (j=0; j<=maxord; j++) N_VDestroy(cv_mem->cv_znQ[j]);
 
-  lrw -= (maxord + 5)*lrw1Q;
-  liw -= (maxord + 5)*liw1Q;
+  cv_mem->cv_lrw -= (maxord + 5)*cv_mem->cv_lrw1Q;
+  cv_mem->cv_liw -= (maxord + 5)*cv_mem->cv_liw1Q;
 
   if (cv_mem->cv_VabstolQMallocDone) {
-    N_VDestroy(VabstolQ);
-    lrw -= lrw1Q;
-    liw -= liw1Q;
+    N_VDestroy(cv_mem->cv_VabstolQ);
+    cv_mem->cv_lrw -= cv_mem->cv_lrw1Q;
+    cv_mem->cv_liw -= cv_mem->cv_liw1Q;
   }
 
-  cv_mem->cv_VabstolQMallocDone = FALSE;
+  cv_mem->cv_VabstolQMallocDone = SUNFALSE;
 }
 
 /*
@@ -3993,93 +3937,96 @@ static booleantype cvSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
   int i, j;
   
   /* Allocate yS */
-  yS = N_VCloneVectorArray(Ns, tmpl);
-  if (yS == NULL) {
-    return(FALSE);
+  cv_mem->cv_yS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_yS == NULL) {
+    return(SUNFALSE);
   }
 
   /* Allocate ewtS */
-  ewtS = N_VCloneVectorArray(Ns, tmpl);
-  if (ewtS == NULL) {
-    N_VDestroyVectorArray(yS, Ns);
-    return(FALSE);
+  cv_mem->cv_ewtS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_ewtS == NULL) {
+    N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+    return(SUNFALSE);
   }
   
   /* Allocate acorS */
-  acorS = N_VCloneVectorArray(Ns, tmpl);
-  if (acorS == NULL) {
-    N_VDestroyVectorArray(yS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    return(FALSE);
+  cv_mem->cv_acorS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_acorS == NULL) {
+    N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ewtS, cv_mem->cv_Ns);
+    return(SUNFALSE);
   }
   
   /* Allocate tempvS */
-  tempvS = N_VCloneVectorArray(Ns, tmpl);
-  if (tempvS == NULL) {
-    N_VDestroyVectorArray(yS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroyVectorArray(acorS, Ns);
-    return(FALSE);
+  cv_mem->cv_tempvS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_tempvS == NULL) {
+    N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ewtS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_acorS, cv_mem->cv_Ns);
+    return(SUNFALSE);
   }
     
   /* Allocate ftempS */
-  ftempS = N_VCloneVectorArray(Ns, tmpl);
-  if (ftempS == NULL) {
-    N_VDestroyVectorArray(yS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroyVectorArray(acorS, Ns);
-    N_VDestroyVectorArray(tempvS, Ns);
-    return(FALSE);
+  cv_mem->cv_ftempS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_ftempS == NULL) {
+    N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ewtS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_acorS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_tempvS, cv_mem->cv_Ns);
+    return(SUNFALSE);
   }
   
   /* Allocate znS */
-  for (j=0; j<=qmax; j++) {
-    znS[j] = N_VCloneVectorArray(Ns, tmpl);
-    if (znS[j] == NULL) {
-      N_VDestroyVectorArray(yS, Ns);
-      N_VDestroyVectorArray(ewtS, Ns);
-      N_VDestroyVectorArray(acorS, Ns);
-      N_VDestroyVectorArray(tempvS, Ns);
-      N_VDestroyVectorArray(ftempS, Ns);
-      for (i=0; i<j; i++) N_VDestroyVectorArray(znS[i], Ns);
-      return(FALSE);
+  for (j=0; j<=cv_mem->cv_qmax; j++) {
+    cv_mem->cv_znS[j] = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+    if (cv_mem->cv_znS[j] == NULL) {
+      N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(cv_mem->cv_ewtS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(cv_mem->cv_acorS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(cv_mem->cv_tempvS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(cv_mem->cv_ftempS, cv_mem->cv_Ns);
+      for (i=0; i<j; i++)
+        N_VDestroyVectorArray(cv_mem->cv_znS[i], cv_mem->cv_Ns);
+      return(SUNFALSE);
     }
   }
   
   /* Allocate space for pbar and plist */
-  pbar = NULL;
-  pbar = (realtype *)malloc(Ns*sizeof(realtype));
-  if (pbar == NULL) {
-    N_VDestroyVectorArray(yS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroyVectorArray(acorS, Ns);
-    N_VDestroyVectorArray(tempvS, Ns);
-    N_VDestroyVectorArray(ftempS, Ns);
-    for (i=0; i<=qmax; i++) N_VDestroyVectorArray(znS[i], Ns);
-    return(FALSE);
-  }
-
-  plist = NULL;
-  plist = (int *)malloc(Ns*sizeof(int));
-  if (plist == NULL) {
-    N_VDestroyVectorArray(yS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroyVectorArray(acorS, Ns);
-    N_VDestroyVectorArray(tempvS, Ns);
-    N_VDestroyVectorArray(ftempS, Ns);
-    for (i=0; i<=qmax; i++) N_VDestroyVectorArray(znS[i], Ns);
-    free(pbar); pbar = NULL;
-    return(FALSE);
+  cv_mem->cv_pbar = NULL;
+  cv_mem->cv_pbar = (realtype *)malloc(cv_mem->cv_Ns*sizeof(realtype));
+  if (cv_mem->cv_pbar == NULL) {
+    N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ewtS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_acorS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_tempvS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ftempS, cv_mem->cv_Ns);
+    for (i=0; i<=cv_mem->cv_qmax; i++)
+      N_VDestroyVectorArray(cv_mem->cv_znS[i], cv_mem->cv_Ns);
+    return(SUNFALSE);
+  }
+
+  cv_mem->cv_plist = NULL;
+  cv_mem->cv_plist = (int *)malloc(cv_mem->cv_Ns*sizeof(int));
+  if (cv_mem->cv_plist == NULL) {
+    N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ewtS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_acorS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_tempvS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ftempS, cv_mem->cv_Ns);
+    for (i=0; i<=cv_mem->cv_qmax; i++)
+      N_VDestroyVectorArray(cv_mem->cv_znS[i], cv_mem->cv_Ns);
+    free(cv_mem->cv_pbar); cv_mem->cv_pbar = NULL;
+    return(SUNFALSE);
   }
 
   /* Update solver workspace lengths */
-  lrw += (qmax + 6)*Ns*lrw1 + Ns;
-  liw += (qmax + 6)*Ns*liw1 + Ns;
+  cv_mem->cv_lrw += (cv_mem->cv_qmax + 6)*cv_mem->cv_Ns*cv_mem->cv_lrw1 + cv_mem->cv_Ns;
+  cv_mem->cv_liw += (cv_mem->cv_qmax + 6)*cv_mem->cv_Ns*cv_mem->cv_liw1 + cv_mem->cv_Ns;
   
   /* Store the value of qmax used here */
-  cv_mem->cv_qmax_allocS = qmax;
+  cv_mem->cv_qmax_allocS = cv_mem->cv_qmax;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -4094,31 +4041,32 @@ static void cvSensFreeVectors(CVodeMem cv_mem)
   
   maxord = cv_mem->cv_qmax_allocS;
 
-  N_VDestroyVectorArray(yS, Ns);
-  N_VDestroyVectorArray(ewtS, Ns);
-  N_VDestroyVectorArray(acorS, Ns);
-  N_VDestroyVectorArray(tempvS, Ns);
-  N_VDestroyVectorArray(ftempS, Ns);
+  N_VDestroyVectorArray(cv_mem->cv_yS, cv_mem->cv_Ns);
+  N_VDestroyVectorArray(cv_mem->cv_ewtS, cv_mem->cv_Ns);
+  N_VDestroyVectorArray(cv_mem->cv_acorS, cv_mem->cv_Ns);
+  N_VDestroyVectorArray(cv_mem->cv_tempvS, cv_mem->cv_Ns);
+  N_VDestroyVectorArray(cv_mem->cv_ftempS, cv_mem->cv_Ns);
   
-  for (j=0; j<=maxord; j++) N_VDestroyVectorArray(znS[j], Ns);  
+  for (j=0; j<=maxord; j++)
+    N_VDestroyVectorArray(cv_mem->cv_znS[j], cv_mem->cv_Ns);  
 
-  free(pbar); pbar = NULL;
-  free(plist); plist = NULL;
+  free(cv_mem->cv_pbar); cv_mem->cv_pbar = NULL;
+  free(cv_mem->cv_plist); cv_mem->cv_plist = NULL;
 
-  lrw -= (maxord + 6)*Ns*lrw1 + Ns;
-  liw -= (maxord + 6)*Ns*liw1 + Ns;
+  cv_mem->cv_lrw -= (maxord + 6)*cv_mem->cv_Ns*cv_mem->cv_lrw1 + cv_mem->cv_Ns;
+  cv_mem->cv_liw -= (maxord + 6)*cv_mem->cv_Ns*cv_mem->cv_liw1 + cv_mem->cv_Ns;
 
   if (cv_mem->cv_VabstolSMallocDone) {
-    N_VDestroyVectorArray(VabstolS, Ns);
-    lrw -= Ns*lrw1;
-    liw -= Ns*liw1;
+    N_VDestroyVectorArray(cv_mem->cv_VabstolS, cv_mem->cv_Ns);
+    cv_mem->cv_lrw -= cv_mem->cv_Ns*cv_mem->cv_lrw1;
+    cv_mem->cv_liw -= cv_mem->cv_Ns*cv_mem->cv_liw1;
   }
   if (cv_mem->cv_SabstolSMallocDone) {
-    free(SabstolS); SabstolS = NULL;
-    lrw -= Ns;
+    free(cv_mem->cv_SabstolS); cv_mem->cv_SabstolS = NULL;
+    cv_mem->cv_lrw -= cv_mem->cv_Ns;
   }
-  cv_mem->cv_VabstolSMallocDone = FALSE;
-  cv_mem->cv_SabstolSMallocDone = FALSE;
+  cv_mem->cv_VabstolSMallocDone = SUNFALSE;
+  cv_mem->cv_SabstolSMallocDone = SUNFALSE;
 }
 
 /*
@@ -4133,67 +4081,68 @@ static booleantype cvQuadSensAllocVectors(CVodeMem cv_mem, N_Vector tmpl)
   int i, j;
 
   /* Allocate ftempQ */
-  ftempQ = N_VClone(tmpl);
-  if (ftempQ == NULL) {
-    return(FALSE);
+  cv_mem->cv_ftempQ = N_VClone(tmpl);
+  if (cv_mem->cv_ftempQ == NULL) {
+    return(SUNFALSE);
   }
 
   /* Allocate yQS */
-  yQS = N_VCloneVectorArray(Ns, tmpl);
-  if (yQS == NULL) {
-    N_VDestroy(ftempQ);
-    return(FALSE);
+  cv_mem->cv_yQS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_yQS == NULL) {
+    N_VDestroy(cv_mem->cv_ftempQ);
+    return(SUNFALSE);
   }
 
   /* Allocate ewtQS */
-  ewtQS = N_VCloneVectorArray(Ns, tmpl);
-  if (ewtQS == NULL) {
-    N_VDestroy(ftempQ);
-    N_VDestroyVectorArray(yQS, Ns);
-    return(FALSE);
+  cv_mem->cv_ewtQS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_ewtQS == NULL) {
+    N_VDestroy(cv_mem->cv_ftempQ);
+    N_VDestroyVectorArray(cv_mem->cv_yQS, cv_mem->cv_Ns);
+    return(SUNFALSE);
   }
 
   /* Allocate acorQS */
-  acorQS = N_VCloneVectorArray(Ns, tmpl);
-  if (acorQS == NULL) {
-    N_VDestroy(ftempQ);
-    N_VDestroyVectorArray(yQS, Ns);
-    N_VDestroyVectorArray(ewtQS, Ns);
-    return(FALSE);
+  cv_mem->cv_acorQS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_acorQS == NULL) {
+    N_VDestroy(cv_mem->cv_ftempQ);
+    N_VDestroyVectorArray(cv_mem->cv_yQS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ewtQS, cv_mem->cv_Ns);
+    return(SUNFALSE);
   }
   
   /* Allocate tempvQS */
-  tempvQS = N_VCloneVectorArray(Ns, tmpl);
-  if (tempvQS == NULL) {
-    N_VDestroy(ftempQ);
-    N_VDestroyVectorArray(yQS, Ns);
-    N_VDestroyVectorArray(ewtQS, Ns);
-    N_VDestroyVectorArray(acorQS, Ns);
-    return(FALSE);
+  cv_mem->cv_tempvQS = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+  if (cv_mem->cv_tempvQS == NULL) {
+    N_VDestroy(cv_mem->cv_ftempQ);
+    N_VDestroyVectorArray(cv_mem->cv_yQS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_ewtQS, cv_mem->cv_Ns);
+    N_VDestroyVectorArray(cv_mem->cv_acorQS, cv_mem->cv_Ns);
+    return(SUNFALSE);
   }
 
   /* Allocate znQS */
-  for (j=0; j<=qmax; j++) {
-    znQS[j] = N_VCloneVectorArray(Ns, tmpl);
-    if (znQS[j] == NULL) {
-      N_VDestroy(ftempQ);
-      N_VDestroyVectorArray(yQS, Ns);
-      N_VDestroyVectorArray(ewtQS, Ns);
-      N_VDestroyVectorArray(acorQS, Ns);
-      N_VDestroyVectorArray(tempvQS, Ns);
-      for (i=0; i<j; i++) N_VDestroyVectorArray(znQS[i], Ns);
-      return(FALSE);
+  for (j=0; j<=cv_mem->cv_qmax; j++) {
+    cv_mem->cv_znQS[j] = N_VCloneVectorArray(cv_mem->cv_Ns, tmpl);
+    if (cv_mem->cv_znQS[j] == NULL) {
+      N_VDestroy(cv_mem->cv_ftempQ);
+      N_VDestroyVectorArray(cv_mem->cv_yQS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(cv_mem->cv_ewtQS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(cv_mem->cv_acorQS, cv_mem->cv_Ns);
+      N_VDestroyVectorArray(cv_mem->cv_tempvQS, cv_mem->cv_Ns);
+      for (i=0; i<j; i++)
+        N_VDestroyVectorArray(cv_mem->cv_znQS[i], cv_mem->cv_Ns);
+      return(SUNFALSE);
     }
   }
 
   /* Update solver workspace lengths */
-  lrw += (qmax + 5)*Ns*lrw1Q;
-  liw += (qmax + 5)*Ns*liw1Q;
+  cv_mem->cv_lrw += (cv_mem->cv_qmax + 5)*cv_mem->cv_Ns*cv_mem->cv_lrw1Q;
+  cv_mem->cv_liw += (cv_mem->cv_qmax + 5)*cv_mem->cv_Ns*cv_mem->cv_liw1Q;
 
   /* Store the value of qmax used here */
-  cv_mem->cv_qmax_allocQS = qmax;
+  cv_mem->cv_qmax_allocQS = cv_mem->cv_qmax;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -4208,29 +4157,30 @@ static void cvQuadSensFreeVectors(CVodeMem cv_mem)
   
   maxord = cv_mem->cv_qmax_allocQS;
 
-  N_VDestroy(ftempQ);
+  N_VDestroy(cv_mem->cv_ftempQ);
 
-  N_VDestroyVectorArray(yQS, Ns);
-  N_VDestroyVectorArray(ewtQS, Ns);
-  N_VDestroyVectorArray(acorQS, Ns);
-  N_VDestroyVectorArray(tempvQS, Ns);
+  N_VDestroyVectorArray(cv_mem->cv_yQS, cv_mem->cv_Ns);
+  N_VDestroyVectorArray(cv_mem->cv_ewtQS, cv_mem->cv_Ns);
+  N_VDestroyVectorArray(cv_mem->cv_acorQS, cv_mem->cv_Ns);
+  N_VDestroyVectorArray(cv_mem->cv_tempvQS, cv_mem->cv_Ns);
   
-  for (j=0; j<=maxord; j++) N_VDestroyVectorArray(znQS[j], Ns);  
+  for (j=0; j<=maxord; j++)
+    N_VDestroyVectorArray(cv_mem->cv_znQS[j], cv_mem->cv_Ns);  
 
-  lrw -= (maxord + 5)*Ns*lrw1Q;
-  liw -= (maxord + 5)*Ns*liw1Q;
+  cv_mem->cv_lrw -= (maxord + 5)*cv_mem->cv_Ns*cv_mem->cv_lrw1Q;
+  cv_mem->cv_liw -= (maxord + 5)*cv_mem->cv_Ns*cv_mem->cv_liw1Q;
 
   if (cv_mem->cv_VabstolQSMallocDone) {
-    N_VDestroyVectorArray(VabstolQS, Ns);
-    lrw -= Ns*lrw1Q;
-    liw -= Ns*liw1Q;
+    N_VDestroyVectorArray(cv_mem->cv_VabstolQS, cv_mem->cv_Ns);
+    cv_mem->cv_lrw -= cv_mem->cv_Ns*cv_mem->cv_lrw1Q;
+    cv_mem->cv_liw -= cv_mem->cv_Ns*cv_mem->cv_liw1Q;
   }
   if (cv_mem->cv_SabstolQSMallocDone) {
-    free(SabstolQS); SabstolQS = NULL;
-    lrw -= Ns;
+    free(cv_mem->cv_SabstolQS); cv_mem->cv_SabstolQS = NULL;
+    cv_mem->cv_lrw -= cv_mem->cv_Ns;
   }
-  cv_mem->cv_VabstolQSMallocDone = FALSE;
-  cv_mem->cv_SabstolQSMallocDone = FALSE;
+  cv_mem->cv_VabstolQSMallocDone = SUNFALSE;
+  cv_mem->cv_SabstolQSMallocDone = SUNFALSE;
 
 }
 
@@ -4285,11 +4235,11 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
 
   /* If tout is too close to tn, give up */
   
-  if ((tdiff = tout-tn) == ZERO) return(CV_TOO_CLOSE);
+  if ((tdiff = tout-cv_mem->cv_tn) == ZERO) return(CV_TOO_CLOSE);
   
   sign = (tdiff > ZERO) ? 1 : -1;
   tdist = SUNRabs(tdiff);
-  tround = uround * SUNMAX(SUNRabs(tn), SUNRabs(tout));
+  tround = cv_mem->cv_uround * SUNMAX(SUNRabs(cv_mem->cv_tn), SUNRabs(tout));
 
   if (tdist < TWO*tround) return(CV_TOO_CLOSE);
   
@@ -4305,21 +4255,21 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
   hg  = SUNRsqrt(hlb*hub);
 
   if (hub < hlb) {
-    if (sign == -1) h = -hg;
-    else            h =  hg;
+    if (sign == -1) cv_mem->cv_h = -hg;
+    else            cv_mem->cv_h =  hg;
     return(CV_SUCCESS);
   }
   
   /* Outer loop */
 
-  hnewOK = FALSE;
+  hnewOK = SUNFALSE;
   hs = hg;         /* safeguard against 'uninitialized variable' warning */
 
   for(count1 = 1; count1 <= MAX_ITERS; count1++) {
 
     /* Attempts to estimate ydd */
 
-    hgOK = FALSE;
+    hgOK = SUNFALSE;
 
     for (count2 = 1; count2 <= MAX_ITERS; count2++) {
       hgs = hg*sign;
@@ -4327,7 +4277,7 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
       /* If a RHS function failed unrecoverably, give up */
       if (retval < 0) return(retval);
       /* If successful, we can use ydd */
-      if (retval == CV_SUCCESS) {hgOK = TRUE; break;}
+      if (retval == CV_SUCCESS) {hgOK = SUNTRUE; break;}
       /* A RHS function failed recoverably; cut step size and test it again */
       hg *= POINT2;
     }
@@ -4358,13 +4308,13 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
     
     /* Accept hnew if it does not differ from hg by more than a factor of 2 */
     if ((hrat > HALF) && (hrat < TWO)) {
-      hnewOK = TRUE;
+      hnewOK = SUNTRUE;
     }
 
     /* After one pass, if ydd seems to be bad, use fall-back value. */
     if ((count1 > 1) && (hrat > TWO)) {
       hnew = hg;
-      hnewOK = TRUE;
+      hnewOK = SUNTRUE;
     }
 
     /* Send this value back through f() */
@@ -4378,7 +4328,7 @@ static int cvHin(CVodeMem cv_mem, realtype tout)
   if (h0 < hlb) h0 = hlb;
   if (h0 > hub) h0 = hub;
   if (sign == -1) h0 = -h0;
-  h = h0;
+  cv_mem->cv_h = h0;
 
   return(CV_SUCCESS);
 }
@@ -4405,32 +4355,32 @@ static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist)
    * factor is used as a safeguard against zero components in y0. 
    */
 
-  temp1 = tempv;
-  temp2 = acor;
+  temp1 = cv_mem->cv_tempv;
+  temp2 = cv_mem->cv_acor;
 
-  N_VAbs(zn[0], temp2);
-  efun(zn[0], temp1, e_data);
+  N_VAbs(cv_mem->cv_zn[0], temp2);
+  cv_mem->cv_efun(cv_mem->cv_zn[0], temp1, cv_mem->cv_e_data);
   N_VInv(temp1, temp1);
   N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1);
 
-  N_VAbs(zn[1], temp2);
+  N_VAbs(cv_mem->cv_zn[1], temp2);
 
   N_VDiv(temp2, temp1, temp1);
   hub_inv = N_VMaxNorm(temp1);
 
   /* Bound based on |yQ|/|yQ'| */
   
-  if (quadr && errconQ) {
+  if (cv_mem->cv_quadr && cv_mem->cv_errconQ) {
 
-    tempQ1 = tempvQ;
-    tempQ2 = acorQ;
+    tempQ1 = cv_mem->cv_tempvQ;
+    tempQ2 = cv_mem->cv_acorQ;
 
-    N_VAbs(znQ[0], tempQ2);
-    cvQuadEwtSet(cv_mem, znQ[0], tempQ1);
+    N_VAbs(cv_mem->cv_znQ[0], tempQ2);
+    cvQuadEwtSet(cv_mem, cv_mem->cv_znQ[0], tempQ1);
     N_VInv(tempQ1, tempQ1);
     N_VLinearSum(HUB_FACTOR, tempQ2, ONE, tempQ1, tempQ1);
     
-    N_VAbs(znQ[1], tempQ2);
+    N_VAbs(cv_mem->cv_znQ[1], tempQ2);
     
     N_VDiv(tempQ2, tempQ1, tempQ1);
     hubQ_inv = N_VMaxNorm(tempQ1);
@@ -4441,18 +4391,18 @@ static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist)
 
   /* Bound based on |yS|/|yS'| */
 
-  if (sensi && errconS) {
+  if (cv_mem->cv_sensi && cv_mem->cv_errconS) {
 
-    tempS1 = acorS;
-    cvSensEwtSet(cv_mem, znS[0], tempS1);
+    tempS1 = cv_mem->cv_acorS;
+    cvSensEwtSet(cv_mem, cv_mem->cv_znS[0], tempS1);
 
-    for (is=0; is<Ns; is++) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
 
-      N_VAbs(znS[0][is], temp2);
+      N_VAbs(cv_mem->cv_znS[0][is], temp2);
       N_VInv(tempS1[is], temp1);
       N_VLinearSum(HUB_FACTOR, temp2, ONE, temp1, temp1);
       
-      N_VAbs(znS[1][is], temp2);
+      N_VAbs(cv_mem->cv_znS[1][is], temp2);
       
       N_VDiv(temp2, temp1, temp1);
       hubS_inv = N_VMaxNorm(temp1);
@@ -4465,21 +4415,21 @@ static realtype cvUpperBoundH0(CVodeMem cv_mem, realtype tdist)
 
   /* Bound based on |yQS|/|yQS'| */
 
-  if (quadr_sensi && errconQS) {
+  if (cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS) {
 
-    tempQ1 = tempvQ;
-    tempQ2 = acorQ;
+    tempQ1 = cv_mem->cv_tempvQ;
+    tempQ2 = cv_mem->cv_acorQ;
 
-    tempQS1 = acorQS;
-    cvQuadSensEwtSet(cv_mem, znQS[0], tempQS1);
+    tempQS1 = cv_mem->cv_acorQS;
+    cvQuadSensEwtSet(cv_mem, cv_mem->cv_znQS[0], tempQS1);
 
-    for (is=0; is<Ns; is++) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
 
-      N_VAbs(znQS[0][is], tempQ2);
+      N_VAbs(cv_mem->cv_znQS[0][is], tempQ2);
       N_VInv(tempQS1[is], tempQ1);
       N_VLinearSum(HUB_FACTOR, tempQ2, ONE, tempQ1, tempQ1);
       
-      N_VAbs(znQS[1][is], tempQ2);
+      N_VAbs(cv_mem->cv_znQS[1][is], tempQ2);
       
       N_VDiv(tempQ2, tempQ1, tempQ1);
       hubQS_inv = N_VMaxNorm(tempQ1);
@@ -4521,40 +4471,48 @@ static int cvYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm)
   
   /* y <- h*y'(t) + y(t) */
   
-  N_VLinearSum(hg, zn[1], ONE, zn[0], y);
+  N_VLinearSum(hg, cv_mem->cv_zn[1], ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
   
-  if (sensi && errconS) 
-    for (is=0; is<Ns; is++)
-      N_VLinearSum(hg, znS[1][is], ONE, znS[0][is], yS[is]);
+  if (cv_mem->cv_sensi && cv_mem->cv_errconS) 
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VLinearSum(hg, cv_mem->cv_znS[1][is], ONE,
+                   cv_mem->cv_znS[0][is], cv_mem->cv_yS[is]);
   
   /* tempv <- f(t+h, h*y'(t)+y(t)) */
 
-  retval = f(tn+hg, y, tempv, user_data);
-  nfe++;
+  retval = cv_mem->cv_f(cv_mem->cv_tn+hg, cv_mem->cv_y,
+                        cv_mem->cv_tempv, cv_mem->cv_user_data);
+  cv_mem->cv_nfe++;
   if (retval < 0) return(CV_RHSFUNC_FAIL);
   if (retval > 0) return(RHSFUNC_RECVR);
 
-  if (quadr && errconQ) {
-    retval = fQ(tn+hg, y, tempvQ, user_data);
-    nfQe++;
+  if (cv_mem->cv_quadr && cv_mem->cv_errconQ) {
+    retval = cv_mem->cv_fQ(cv_mem->cv_tn+hg, cv_mem->cv_y,
+                           cv_mem->cv_tempvQ, cv_mem->cv_user_data);
+    cv_mem->cv_nfQe++;
     if (retval < 0) return(CV_QRHSFUNC_FAIL);
     if (retval > 0) return(QRHSFUNC_RECVR);
   }
 
-  if (sensi && errconS) {
-    wrk1 = ftemp;
-    wrk2 = acor;
-    retval = cvSensRhsWrapper(cv_mem, tn+hg, y, tempv, yS, tempvS, wrk1, wrk2);
+  if (cv_mem->cv_sensi && cv_mem->cv_errconS) {
+    wrk1 = cv_mem->cv_ftemp;
+    wrk2 = cv_mem->cv_acor;
+    retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn+hg, cv_mem->cv_y,
+                              cv_mem->cv_tempv, cv_mem->cv_yS,
+                              cv_mem->cv_tempvS, wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) return(SRHSFUNC_RECVR);
   }  
 
-  if (quadr_sensi && errconQS) {
-    wrk1 = ftemp;
-    wrk2 = acorQ;
-    retval = fQS(Ns, tn+hg, y, yS, tempvQ, tempvQS, fQS_data, wrk1, wrk2);
+  if (cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS) {
+    wrk1 = cv_mem->cv_ftemp;
+    wrk2 = cv_mem->cv_acorQ;
+    retval = cv_mem->cv_fQS(cv_mem->cv_Ns, cv_mem->cv_tn+hg,
+                            cv_mem->cv_y, cv_mem->cv_yS,
+                            cv_mem->cv_tempvQ, cv_mem->cv_tempvQS,
+                            cv_mem->cv_fQS_data, wrk1, wrk2);
 
-    nfQSe++;
+    cv_mem->cv_nfQSe++;
     if (retval < 0) return(CV_QSRHSFUNC_FAIL);
     if (retval > 0) return(QSRHSFUNC_RECVR);
   } 
@@ -4562,30 +4520,36 @@ static int cvYddNorm(CVodeMem cv_mem, realtype hg, realtype *yddnrm)
   /* Load estimate of ||y''|| into tempv:
    * tempv <-  (1/h) * f(t+h, h*y'(t)+y(t)) - y'(t) */
   
-  N_VLinearSum(ONE, tempv, -ONE, zn[1], tempv);
-  N_VScale(ONE/hg, tempv, tempv);
-  *yddnrm = N_VWrmsNorm(tempv, ewt);
+  N_VLinearSum(ONE, cv_mem->cv_tempv, -ONE, cv_mem->cv_zn[1], cv_mem->cv_tempv);
+  N_VScale(ONE/hg, cv_mem->cv_tempv, cv_mem->cv_tempv);
+  *yddnrm = N_VWrmsNorm(cv_mem->cv_tempv, cv_mem->cv_ewt);
 
-  if (quadr && errconQ) {
-    N_VLinearSum(ONE, tempvQ, -ONE, znQ[1], tempvQ);
-    N_VScale(ONE/hg, tempvQ, tempvQ);
-    *yddnrm = cvQuadUpdateNorm(cv_mem, *yddnrm, tempvQ, ewtQ);
+  if (cv_mem->cv_quadr && cv_mem->cv_errconQ) {
+    N_VLinearSum(ONE, cv_mem->cv_tempvQ, -ONE, 
+                 cv_mem->cv_znQ[1], cv_mem->cv_tempvQ);
+    N_VScale(ONE/hg, cv_mem->cv_tempvQ, cv_mem->cv_tempvQ);
+    *yddnrm = cvQuadUpdateNorm(cv_mem, *yddnrm, cv_mem->cv_tempvQ,
+                               cv_mem->cv_ewtQ);
   }
 
-  if (sensi && errconS) {
-    for (is=0; is<Ns; is++) {
-      N_VLinearSum(ONE, tempvS[is], -ONE, znS[1][is], tempvS[is]);
-      N_VScale(ONE/hg, tempvS[is], tempvS[is]);
+  if (cv_mem->cv_sensi && cv_mem->cv_errconS) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VLinearSum(ONE, cv_mem->cv_tempvS[is], -ONE,
+                   cv_mem->cv_znS[1][is], cv_mem->cv_tempvS[is]);
+      N_VScale(ONE/hg, cv_mem->cv_tempvS[is], cv_mem->cv_tempvS[is]);
     }
-    *yddnrm = cvSensUpdateNorm(cv_mem, *yddnrm, tempvS, ewtS);
+    *yddnrm = cvSensUpdateNorm(cv_mem, *yddnrm, cv_mem->cv_tempvS,
+                               cv_mem->cv_ewtS);
   }
 
-  if (quadr_sensi && errconQS) {
-    for (is=0; is<Ns; is++) {
-      N_VLinearSum(ONE, tempvQS[is], -ONE, znQS[1][is], tempvQS[is]);
-      N_VScale(ONE/hg, tempvQS[is], tempvQS[is]);
+  if (cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VLinearSum(ONE, cv_mem->cv_tempvQS[is], -ONE,
+                   cv_mem->cv_znQS[1][is], cv_mem->cv_tempvQS[is]);
+      N_VScale(ONE/hg, cv_mem->cv_tempvQS[is], cv_mem->cv_tempvQS[is]);
     }
-    *yddnrm = cvQuadSensUpdateNorm(cv_mem, *yddnrm, tempvQS, ewtQS);
+    *yddnrm = cvQuadSensUpdateNorm(cv_mem, *yddnrm, cv_mem->cv_tempvQS,
+                                   cv_mem->cv_ewtQS);
   }
 
   return(CV_SUCCESS);
@@ -4610,66 +4574,75 @@ static int cvInitialSetup(CVodeMem cv_mem)
   int ier;
 
   /* Did the user specify tolerances? */
-  if (itol == CV_NN) {
-    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NO_TOL);
+  if (cv_mem->cv_itol == CV_NN) {
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                   MSGCV_NO_TOL);
     return(CV_ILL_INPUT);
   }
 
   /* Set data for efun */
-  if (cv_mem->cv_user_efun) e_data = user_data;
-  else                      e_data = cv_mem;
+  if (cv_mem->cv_user_efun) cv_mem->cv_e_data = cv_mem->cv_user_data;
+  else                      cv_mem->cv_e_data = cv_mem;
 
   /* Load initial error weights */
-  ier = efun(zn[0], ewt, e_data);
+  ier = cv_mem->cv_efun(cv_mem->cv_zn[0], cv_mem->cv_ewt,
+                        cv_mem->cv_e_data);
   if (ier != 0) {
-    if (itol == CV_WF) 
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_EWT_FAIL);
+    if (cv_mem->cv_itol == CV_WF) 
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_EWT_FAIL);
     else
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_BAD_EWT);
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_BAD_EWT);
     return(CV_ILL_INPUT);
   }
   
   /* Quadrature initial setup */
 
-  if (quadr && errconQ) {
+  if (cv_mem->cv_quadr && cv_mem->cv_errconQ) {
 
     /* Did the user specify tolerances? */
-    if (itolQ == CV_NN) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NO_TOLQ);
+    if (cv_mem->cv_itolQ == CV_NN) {
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_NO_TOLQ);
       return(CV_ILL_INPUT);
     }
 
     /* Load ewtQ */
-    ier = cvQuadEwtSet(cv_mem, znQ[0], ewtQ);
+    ier = cvQuadEwtSet(cv_mem, cv_mem->cv_znQ[0], cv_mem->cv_ewtQ);
     if (ier != 0) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_BAD_EWTQ);
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_BAD_EWTQ);
       return(CV_ILL_INPUT);
     }
 
   }
 
-  if (!quadr) errconQ = FALSE;
+  if (!cv_mem->cv_quadr) cv_mem->cv_errconQ = SUNFALSE;
 
   /* Forward sensitivity initial setup */
 
-  if (sensi) {
+  if (cv_mem->cv_sensi) {
 
     /* Did the user specify tolerances? */
-    if (itolS == CV_NN) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NO_TOLS);
+    if (cv_mem->cv_itolS == CV_NN) {
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_NO_TOLS);
       return(CV_ILL_INPUT);
     }
 
     /* If using the internal DQ functions, we must have access to the problem parameters */
-    if(fSDQ && (p == NULL)) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NULL_P);
+    if(cv_mem->cv_fSDQ && (cv_mem->cv_p == NULL)) {
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_NULL_P);
       return(CV_ILL_INPUT);
     }
 
     /* Load ewtS */
-    ier = cvSensEwtSet(cv_mem, znS[0], ewtS);
+    ier = cvSensEwtSet(cv_mem, cv_mem->cv_znS[0], cv_mem->cv_ewtS);
     if (ier != 0) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_BAD_EWTS);
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_BAD_EWTS);
       return(CV_ILL_INPUT);
     }
 
@@ -4677,45 +4650,50 @@ static int cvInitialSetup(CVodeMem cv_mem)
 
   /* FSA of quadrature variables */
 
-  if (quadr_sensi) {
+  if (cv_mem->cv_quadr_sensi) {
 
     /* If using the internal DQ functions, we must have access to fQ
      * (i.e. quadrature integration must be enabled) and to the problem parameters */
 
-    if (fQSDQ) {
+    if (cv_mem->cv_fQSDQ) {
 
       /* Test if quadratures are defined, so we can use fQ */
-      if (!quadr) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NULL_FQ);
+      if (!cv_mem->cv_quadr) {
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                       MSGCV_NULL_FQ);
         return(CV_ILL_INPUT);
       }
 
       /* Test if we have the problem parameters */
-      if(p == NULL) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NULL_P);
+      if(cv_mem->cv_p == NULL) {
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                       MSGCV_NULL_P);
         return(CV_ILL_INPUT);
       }
 
     }
 
-    if (errconQS) {
+    if (cv_mem->cv_errconQS) {
       
       /* Did the user specify tolerances? */
-      if (itolQS == CV_NN) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NO_TOLQS);
+      if (cv_mem->cv_itolQS == CV_NN) {
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                       MSGCV_NO_TOLQS);
         return(CV_ILL_INPUT);
       }
 
       /* If needed, did the user provide quadrature tolerances? */
-      if ( (itolQS == CV_EE) && (itolQ == CV_NN) ) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_NO_TOLQ);
+      if ( (cv_mem->cv_itolQS == CV_EE) && (cv_mem->cv_itolQ == CV_NN) ) {
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                       MSGCV_NO_TOLQ);
         return(CV_ILL_INPUT);
       }
 
       /* Load ewtQS */
-      ier = cvQuadSensEwtSet(cv_mem, znQS[0], ewtQS);
+      ier = cvQuadSensEwtSet(cv_mem, cv_mem->cv_znQS[0], cv_mem->cv_ewtQS);
       if (ier != 0) {
-        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_BAD_EWTQS);
+        cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                       MSGCV_BAD_EWTQS);
         return(CV_ILL_INPUT);
       }
 
@@ -4723,20 +4701,22 @@ static int cvInitialSetup(CVodeMem cv_mem)
 
   } else {
 
-    errconQS = FALSE;
+    cv_mem->cv_errconQS = SUNFALSE;
 
   }
 
   /* Check if lsolve function exists (if needed) and call linit function (if it exists) */
-  if (iter == CV_NEWTON) {
-    if (lsolve == NULL) {
-      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup", MSGCV_LSOLVE_NULL);
+  if (cv_mem->cv_iter == CV_NEWTON) {
+    if (cv_mem->cv_lsolve == NULL) {
+      cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "cvInitialSetup",
+                     MSGCV_LSOLVE_NULL);
       return(CV_ILL_INPUT);
     }
-    if (linit != NULL) {
-      ier = linit(cv_mem);
+    if (cv_mem->cv_linit != NULL) {
+      ier = cv_mem->cv_linit(cv_mem);
       if (ier != 0) {
-        cvProcessError(cv_mem, CV_LINIT_FAIL, "CVODES", "cvInitialSetup", MSGCV_LINIT_FAIL);
+        cvProcessError(cv_mem, CV_LINIT_FAIL, "CVODES", "cvInitialSetup",
+                       MSGCV_LINIT_FAIL);
         return(CV_LINIT_FAIL);
       }
     }
@@ -4772,7 +4752,7 @@ int cvEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
   cv_mem = (CVodeMem) data;
 
-  switch(itol) {
+  switch(cv_mem->cv_itol) {
   case CV_SS:
     flag = cvEwtSetSS(cv_mem, ycur, weight);
     break;
@@ -4795,11 +4775,11 @@ int cvEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
 static int cvEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv);
-  N_VScale(reltol, tempv, tempv);
-  N_VAddConst(tempv, Sabstol, tempv);
-  if (N_VMin(tempv) <= ZERO) return(-1);
-  N_VInv(tempv, weight);
+  N_VAbs(ycur, cv_mem->cv_tempv);
+  N_VScale(cv_mem->cv_reltol, cv_mem->cv_tempv, cv_mem->cv_tempv);
+  N_VAddConst(cv_mem->cv_tempv, cv_mem->cv_Sabstol, cv_mem->cv_tempv);
+  if (N_VMin(cv_mem->cv_tempv) <= ZERO) return(-1);
+  N_VInv(cv_mem->cv_tempv, weight);
 
   return(0);
 }
@@ -4815,10 +4795,11 @@ static int cvEwtSetSS(CVodeMem cv_mem, N_Vector ycur, N_Vector weight)
 
 static int cvEwtSetSV(CVodeMem cv_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv);
-  N_VLinearSum(reltol, tempv, ONE, Vabstol, tempv);
-  if (N_VMin(tempv) <= ZERO) return(-1);
-  N_VInv(tempv, weight);
+  N_VAbs(ycur, cv_mem->cv_tempv);
+  N_VLinearSum(cv_mem->cv_reltol, cv_mem->cv_tempv, ONE,
+               cv_mem->cv_Vabstol, cv_mem->cv_tempv);
+  if (N_VMin(cv_mem->cv_tempv) <= ZERO) return(-1);
+  N_VInv(cv_mem->cv_tempv, weight);
   return(0);
 }
 
@@ -4831,7 +4812,7 @@ static int cvQuadEwtSet(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ)
 {
   int flag=0;
 
-  switch (itolQ) {
+  switch (cv_mem->cv_itolQ) {
   case CV_SS:
     flag = cvQuadEwtSetSS(cv_mem, qcur, weightQ);
     break;
@@ -4851,11 +4832,11 @@ static int cvQuadEwtSet(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ)
 
 static int cvQuadEwtSetSS(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ)
 {
-  N_VAbs(qcur, tempvQ);
-  N_VScale(reltolQ, tempvQ, tempvQ);
-  N_VAddConst(tempvQ, SabstolQ, tempvQ);
-  if (N_VMin(tempvQ) <= ZERO) return(-1);
-  N_VInv(tempvQ, weightQ);
+  N_VAbs(qcur, cv_mem->cv_tempvQ);
+  N_VScale(cv_mem->cv_reltolQ, cv_mem->cv_tempvQ, cv_mem->cv_tempvQ);
+  N_VAddConst(cv_mem->cv_tempvQ, cv_mem->cv_SabstolQ, cv_mem->cv_tempvQ);
+  if (N_VMin(cv_mem->cv_tempvQ) <= ZERO) return(-1);
+  N_VInv(cv_mem->cv_tempvQ, weightQ);
 
   return(0);
 }
@@ -4867,10 +4848,11 @@ static int cvQuadEwtSetSS(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ)
 
 static int cvQuadEwtSetSV(CVodeMem cv_mem, N_Vector qcur, N_Vector weightQ)
 {
-  N_VAbs(qcur, tempvQ);
-  N_VLinearSum(reltolQ, tempvQ, ONE, VabstolQ, tempvQ);
-  if (N_VMin(tempvQ) <= ZERO) return(-1);
-  N_VInv(tempvQ, weightQ);
+  N_VAbs(qcur, cv_mem->cv_tempvQ);
+  N_VLinearSum(cv_mem->cv_reltolQ, cv_mem->cv_tempvQ, ONE,
+               cv_mem->cv_VabstolQ, cv_mem->cv_tempvQ);
+  if (N_VMin(cv_mem->cv_tempvQ) <= ZERO) return(-1);
+  N_VInv(cv_mem->cv_tempvQ, weightQ);
 
   return(0);
 }
@@ -4884,7 +4866,7 @@ static int cvSensEwtSet(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS)
 {
   int flag=0;
 
-  switch (itolS) {
+  switch (cv_mem->cv_itolS) {
   case CV_EE:
     flag = cvSensEwtSetEE(cv_mem, yScur, weightS);
     break;
@@ -4918,13 +4900,13 @@ static int cvSensEwtSetEE(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS)
   int flag;
 
   /* Use tempvS[0] as temporary storage for the scaled sensitivity */
-  pyS = tempvS[0];
+  pyS = cv_mem->cv_tempvS[0];
 
-  for (is=0; is<Ns; is++) {
-    N_VScale(pbar[is], yScur[is], pyS);
-    flag = efun(pyS, weightS[is], e_data);
+  for (is=0; is<cv_mem->cv_Ns; is++) {
+    N_VScale(cv_mem->cv_pbar[is], yScur[is], pyS);
+    flag = cv_mem->cv_efun(pyS, weightS[is], cv_mem->cv_e_data);
     if (flag != 0) return(-1);
-    N_VScale(pbar[is], weightS[is], weightS[is]);
+    N_VScale(cv_mem->cv_pbar[is], weightS[is], weightS[is]);
   }
 
   return(0);
@@ -4939,12 +4921,12 @@ static int cvSensEwtSetSS(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS)
 {
   int is;
   
-  for (is=0; is<Ns; is++) {
-    N_VAbs(yScur[is], tempv);
-    N_VScale(reltolS, tempv, tempv);
-    N_VAddConst(tempv, SabstolS[is], tempv);
-    if (N_VMin(tempv) <= ZERO) return(-1);
-    N_VInv(tempv, weightS[is]);
+  for (is=0; is<cv_mem->cv_Ns; is++) {
+    N_VAbs(yScur[is], cv_mem->cv_tempv);
+    N_VScale(cv_mem->cv_reltolS, cv_mem->cv_tempv, cv_mem->cv_tempv);
+    N_VAddConst(cv_mem->cv_tempv, cv_mem->cv_SabstolS[is], cv_mem->cv_tempv);
+    if (N_VMin(cv_mem->cv_tempv) <= ZERO) return(-1);
+    N_VInv(cv_mem->cv_tempv, weightS[is]);
   }
   return(0);
 }
@@ -4958,11 +4940,12 @@ static int cvSensEwtSetSV(CVodeMem cv_mem, N_Vector *yScur, N_Vector *weightS)
 {
   int is;
   
-  for (is=0; is<Ns; is++) {
-    N_VAbs(yScur[is], tempv);
-    N_VLinearSum(reltolS, tempv, ONE, VabstolS[is], tempv);
-    if (N_VMin(tempv) <= ZERO) return(-1);
-    N_VInv(tempv, weightS[is]);
+  for (is=0; is<cv_mem->cv_Ns; is++) {
+    N_VAbs(yScur[is], cv_mem->cv_tempv);
+    N_VLinearSum(cv_mem->cv_reltolS, cv_mem->cv_tempv, ONE,
+                 cv_mem->cv_VabstolS[is], cv_mem->cv_tempv);
+    if (N_VMin(cv_mem->cv_tempv) <= ZERO) return(-1);
+    N_VInv(cv_mem->cv_tempv, weightS[is]);
   }
 
   return(0);
@@ -4977,7 +4960,7 @@ static int cvQuadSensEwtSet(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weightQ
 {
   int flag=0;
 
-  switch (itolQS) {
+  switch (cv_mem->cv_itolQS) {
   case CV_EE:
     flag = cvQuadSensEwtSetEE(cv_mem, yQScur, weightQS);
     break;
@@ -5011,13 +4994,13 @@ static int cvQuadSensEwtSetEE(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weigh
   int flag;
 
   /* Use tempvQS[0] as temporary storage for the scaled sensitivity */
-  pyS = tempvQS[0];
+  pyS = cv_mem->cv_tempvQS[0];
 
-  for (is=0; is<Ns; is++) {
-    N_VScale(pbar[is], yQScur[is], pyS);
+  for (is=0; is<cv_mem->cv_Ns; is++) {
+    N_VScale(cv_mem->cv_pbar[is], yQScur[is], pyS);
     flag = cvQuadEwtSet(cv_mem, pyS, weightQS[is]);
     if (flag != 0) return(-1);
-    N_VScale(pbar[is], weightQS[is], weightQS[is]);
+    N_VScale(cv_mem->cv_pbar[is], weightQS[is], weightQS[is]);
   }
 
   return(0);
@@ -5027,12 +5010,12 @@ static int cvQuadSensEwtSetSS(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weigh
 {
   int is;
 
-  for (is=0; is<Ns; is++) {
-    N_VAbs(yQScur[is], tempvQ);
-    N_VScale(reltolQS, tempvQ, tempvQ);
-    N_VAddConst(tempvQ, SabstolQS[is], tempvQ);
-    if (N_VMin(tempvQ) <= ZERO) return(-1);
-    N_VInv(tempvQ, weightQS[is]);
+  for (is=0; is<cv_mem->cv_Ns; is++) {
+    N_VAbs(yQScur[is], cv_mem->cv_tempvQ);
+    N_VScale(cv_mem->cv_reltolQS, cv_mem->cv_tempvQ, cv_mem->cv_tempvQ);
+    N_VAddConst(cv_mem->cv_tempvQ, cv_mem->cv_SabstolQS[is], cv_mem->cv_tempvQ);
+    if (N_VMin(cv_mem->cv_tempvQ) <= ZERO) return(-1);
+    N_VInv(cv_mem->cv_tempvQ, weightQS[is]);
   }
 
   return(0);
@@ -5042,11 +5025,12 @@ static int cvQuadSensEwtSetSV(CVodeMem cv_mem, N_Vector *yQScur, N_Vector *weigh
 {
   int is;
   
-  for (is=0; is<Ns; is++) {
-    N_VAbs(yQScur[is], tempvQ);
-    N_VLinearSum(reltolQS, tempvQ, ONE, VabstolQS[is], tempvQ);
-    if (N_VMin(tempvQ) <= ZERO) return(-1);
-    N_VInv(tempvQ, weightQS[is]);
+  for (is=0; is<cv_mem->cv_Ns; is++) {
+    N_VAbs(yQScur[is], cv_mem->cv_tempvQ);
+    N_VLinearSum(cv_mem->cv_reltolQS, cv_mem->cv_tempvQ, ONE,
+                 cv_mem->cv_VabstolQS[is], cv_mem->cv_tempvQ);
+    if (N_VMin(cv_mem->cv_tempvQ) <= ZERO) return(-1);
+    N_VInv(cv_mem->cv_tempvQ, weightQS[is]);
   }
 
   return(0);
@@ -5090,8 +5074,8 @@ static int cvStep(CVodeMem cv_mem)
 
   /* Are we computing sensitivities with a staggered approach? */
 
-  do_sensi_stg  = (sensi && (ism==CV_STAGGERED));
-  do_sensi_stg1 = (sensi && (ism==CV_STAGGERED1));
+  do_sensi_stg  = (cv_mem->cv_sensi && (cv_mem->cv_ism==CV_STAGGERED));
+  do_sensi_stg1 = (cv_mem->cv_sensi && (cv_mem->cv_ism==CV_STAGGERED1));
 
   /* Initialize local counters for convergence and error test failures */
 
@@ -5099,19 +5083,21 @@ static int cvStep(CVodeMem cv_mem)
   nefQ = nefQS = 0;
   ncfS = nefS = 0;
   if (do_sensi_stg1) {
-    for (is=0; is<Ns; is++) ncfS1[is] = 0;
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      cv_mem->cv_ncfS1[is] = 0;
   }
 
   /* If needed, adjust method parameters */
 
-  if ((nst > 0) && (hprime != h)) cvAdjustParams(cv_mem);
+  if ((cv_mem->cv_nst > 0) && (cv_mem->cv_hprime != cv_mem->cv_h))
+    cvAdjustParams(cv_mem);
 
   /* Looping point for attempts to take a step */
 
-  saved_t = tn;
+  saved_t = cv_mem->cv_tn;
   nflag = FIRST_CALL;
 
-  loop {  
+  for(;;) {  
 
     cvPredict(cv_mem);  
     cvSet(cv_mem);
@@ -5119,7 +5105,7 @@ static int cvStep(CVodeMem cv_mem)
     /* ------ Correct state variables ------ */
     
     nflag = cvNls(cv_mem, nflag);
-    kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &ncfn);
+    kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &(cv_mem->cv_ncfn));
 
     /* Go back in loop if we need to predict again (nflag=PREV_CONV_FAIL) */
     if (kflag == PREDICT_AGAIN) continue;
@@ -5128,7 +5114,8 @@ static int cvStep(CVodeMem cv_mem)
     if (kflag != DO_ERROR_TEST) return(kflag);
 
     /* Perform error test (nflag=CV_SUCCESS) */
-    eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrm, &nef, &netf, &dsm);
+    eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, cv_mem->cv_acnrm,
+                          &nef, &(cv_mem->cv_netf), &dsm);
 
     /* Go back in loop if we need to predict again (nflag=PREV_ERR_FAIL) */
     if (eflag == TRY_AGAIN) continue;
@@ -5140,20 +5127,21 @@ static int cvStep(CVodeMem cv_mem)
 
     /* ------ Correct the quadrature variables ------ */
 
-    if (quadr) {
+    if (cv_mem->cv_quadr) {
 
       ncf = nef = 0; /* reset counters for states */
 
       nflag = cvQuadNls(cv_mem);
-      kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &ncfn);
+      kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &(cv_mem->cv_ncfn));
 
       if (kflag == PREDICT_AGAIN) continue;
       if (kflag != DO_ERROR_TEST) return(kflag);
 
       /* Error test on quadratures */
-      if (errconQ) {
-        acnrmQ = N_VWrmsNorm(acorQ, ewtQ);
-        eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrmQ, &nefQ, &netfQ, &dsmQ);
+      if (cv_mem->cv_errconQ) {
+        cv_mem->cv_acnrmQ = N_VWrmsNorm(cv_mem->cv_acorQ, cv_mem->cv_ewtQ);
+        eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, cv_mem->cv_acnrmQ,
+                              &nefQ, &(cv_mem->cv_netfQ), &dsmQ);
 
         if (eflag == TRY_AGAIN) continue;
         if (eflag != CV_SUCCESS) return(eflag);
@@ -5169,14 +5157,15 @@ static int cvStep(CVodeMem cv_mem)
     if (do_sensi_stg || do_sensi_stg1) {
 
       ncf = nef = 0;        /* reset counters for states     */
-      if (quadr) nefQ = 0;  /* reset counter for quadratures */
+      if (cv_mem->cv_quadr) nefQ = 0;  /* reset counter for quadratures */
 
       /* Evaluate f at converged y, needed for future evaluations of sens. RHS 
        * If f() fails recoverably, treat it as a convergence failure and 
        * attempt the step again */
 
-      retval = f(tn, y, ftemp, user_data);
-      nfe++;
+      retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_y,
+                            cv_mem->cv_ftemp, cv_mem->cv_user_data);
+      cv_mem->cv_nfe++;
       if (retval < 0) return(CV_RHSFUNC_FAIL);
       if (retval > 0) {
         nflag = PREV_CONV_FAIL;
@@ -5186,12 +5175,15 @@ static int cvStep(CVodeMem cv_mem)
       if (do_sensi_stg) {
         /* Nonlinear solve for sensitivities (all-at-once) */
         nflag = cvStgrNls(cv_mem);
-        kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncfS, &ncfnS);
+        kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncfS,
+                              &(cv_mem->cv_ncfnS));
       } else {
         /* Nonlinear solve for sensitivities (one-by-one) */
-        for (is=0; is<Ns; is++) { 
+        for (is=0; is<cv_mem->cv_Ns; is++) { 
           nflag = cvStgr1Nls(cv_mem, is); 
-          kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncfS1[is], &ncfnS1[is]);
+          kflag = cvHandleNFlag(cv_mem, &nflag, saved_t,
+                                &(cv_mem->cv_ncfS1[is]),
+                                &(cv_mem->cv_ncfnS1[is]));
           if (kflag != DO_ERROR_TEST) break; 
         }
       }
@@ -5200,11 +5192,13 @@ static int cvStep(CVodeMem cv_mem)
       if (kflag != DO_ERROR_TEST) return(kflag);
 
       /* Error test on sensitivities */
-      if (errconS) {
+      if (cv_mem->cv_errconS) {
 
-        if (do_sensi_stg1) acnrmS = cvSensNorm(cv_mem, acorS, ewtS);
+        if (do_sensi_stg1)
+          cv_mem->cv_acnrmS = cvSensNorm(cv_mem, cv_mem->cv_acorS, cv_mem->cv_ewtS);
 
-        eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrmS, &nefS, &netfS, &dsmS);
+        eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, cv_mem->cv_acnrmS,
+                              &nefS, &(cv_mem->cv_netfS), &dsmS);
 
         if (eflag == TRY_AGAIN)  continue;
         if (eflag != CV_SUCCESS) return(eflag);
@@ -5218,14 +5212,15 @@ static int cvStep(CVodeMem cv_mem)
 
     /* ------ Correct the quadrature sensitivity variables ------ */
 
-    if (quadr_sensi) {
+    if (cv_mem->cv_quadr_sensi) {
 
       /* Reset local convergence and error test failure counters */
       ncf = nef = 0;
-      if (quadr) nefQ = 0;
+      if (cv_mem->cv_quadr) nefQ = 0;
       if (do_sensi_stg) ncfS = nefS = 0;
       if (do_sensi_stg1) {
-        for (is=0; is<Ns; is++) ncfS1[is] = 0;
+        for (is=0; is<cv_mem->cv_Ns; is++)
+          cv_mem->cv_ncfS1[is] = 0;
         nefS = 0;
       }
 
@@ -5233,15 +5228,17 @@ static int cvStep(CVodeMem cv_mem)
        * (stored in cvQuadNls) and can be used in evaluating fQS */
 
       nflag = cvQuadSensNls(cv_mem);
-      kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &ncfn);
+      kflag = cvHandleNFlag(cv_mem, &nflag, saved_t, &ncf, &(cv_mem->cv_ncfn));
 
       if (kflag == PREDICT_AGAIN) continue;
       if (kflag != DO_ERROR_TEST) return(kflag);
 
       /* Error test on quadrature sensitivities */
-      if (errconQS) {
-        acnrmQS = cvQuadSensNorm(cv_mem, acorQS, ewtQS);
-        eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, acnrmQS, &nefQS, &netfQS, &dsmQS);
+      if (cv_mem->cv_errconQS) {
+        cv_mem->cv_acnrmQS = cvQuadSensNorm(cv_mem, cv_mem->cv_acorQS,
+                                            cv_mem->cv_ewtQS);
+        eflag = cvDoErrorTest(cv_mem, &nflag, saved_t, cv_mem->cv_acnrmQS,
+                              &nefQS, &(cv_mem->cv_netfQS), &dsmQS);
 
         if (eflag == TRY_AGAIN) continue;
         if (eflag != CV_SUCCESS) return(eflag);
@@ -5269,25 +5266,25 @@ static int cvStep(CVodeMem cv_mem)
   /* If Stablilty Limit Detection is turned on, call stability limit
      detection routine for possible order reduction. */
 
-  if (sldeton) cvBDFStab(cv_mem);
+  if (cv_mem->cv_sldeton) cvBDFStab(cv_mem);
 
-  etamax = (nst <= SMALL_NST) ? ETAMX2 : ETAMX3;
+  cv_mem->cv_etamax = (cv_mem->cv_nst <= SMALL_NST) ? ETAMX2 : ETAMX3;
 
   /*  Finally, we rescale the acor array to be the 
       estimated local error vector. */
 
-  N_VScale(tq[2], acor, acor);
+  N_VScale(cv_mem->cv_tq[2], cv_mem->cv_acor, cv_mem->cv_acor);
 
-  if (quadr)
-    N_VScale(tq[2], acorQ, acorQ);
+  if (cv_mem->cv_quadr)
+    N_VScale(cv_mem->cv_tq[2], cv_mem->cv_acorQ, cv_mem->cv_acorQ);
 
-  if (sensi)
-    for (is=0; is<Ns; is++)
-      N_VScale(tq[2], acorS[is], acorS[is]);
+  if (cv_mem->cv_sensi)
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VScale(cv_mem->cv_tq[2], cv_mem->cv_acorS[is], cv_mem->cv_acorS[is]);
 
-  if (quadr_sensi)
-    for (is=0; is<Ns; is++)
-      N_VScale(tq[2], acorQS[is], acorQS[is]);
+  if (cv_mem->cv_quadr_sensi)
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VScale(cv_mem->cv_tq[2], cv_mem->cv_acorQS[is], cv_mem->cv_acorQS[is]);
 
   return(CV_SUCCESS);
       
@@ -5311,11 +5308,11 @@ static int cvStep(CVodeMem cv_mem)
 
 static void cvAdjustParams(CVodeMem cv_mem)
 {
-  if (qprime != q) {
-    cvAdjustOrder(cv_mem, qprime-q);
-    q = qprime;
-    L = q+1;
-    qwait = L;
+  if (cv_mem->cv_qprime != cv_mem->cv_q) {
+    cvAdjustOrder(cv_mem, cv_mem->cv_qprime-cv_mem->cv_q);
+    cv_mem->cv_q = cv_mem->cv_qprime;
+    cv_mem->cv_L = cv_mem->cv_q+1;
+    cv_mem->cv_qwait = cv_mem->cv_L;
   }
   cvRescale(cv_mem);
 }
@@ -5332,9 +5329,9 @@ static void cvAdjustParams(CVodeMem cv_mem)
 
 static void cvAdjustOrder(CVodeMem cv_mem, int deltaq)
 {
-  if ((q==2) && (deltaq != 1)) return;
+  if ((cv_mem->cv_q==2) && (deltaq != 1)) return;
   
-  switch(lmm){
+  switch(cv_mem->cv_lmm){
   case CV_ADAMS:
     cvAdjustAdams(cv_mem, deltaq);
     break;
@@ -5360,12 +5357,12 @@ static void cvAdjustAdams(CVodeMem cv_mem, int deltaq)
   /* On an order increase, set new column of zn to zero and return */
   
   if (deltaq==1) {
-    N_VConst(ZERO, zn[L]);
-    if (quadr)
-      N_VConst(ZERO, znQ[L]);
-    if (sensi)
-      for (is=0; is<Ns; is++)
-        N_VConst(ZERO, znS[L][is]);
+    N_VConst(ZERO, cv_mem->cv_zn[cv_mem->cv_L]);
+    if (cv_mem->cv_quadr)
+      N_VConst(ZERO, cv_mem->cv_znQ[cv_mem->cv_L]);
+    if (cv_mem->cv_sensi)
+      for (is=0; is<cv_mem->cv_Ns; is++)
+        N_VConst(ZERO, cv_mem->cv_znS[cv_mem->cv_L][is]);
     return;
   }
 
@@ -5378,28 +5375,33 @@ static void cvAdjustAdams(CVodeMem cv_mem, int deltaq)
    * where xi_j = [t_n - t_(n-j)]/h => xi_0 = 0
    */
 
-  for (i=0; i <= qmax; i++) l[i] = ZERO;
-  l[1] = ONE;
+  for (i=0; i <= cv_mem->cv_qmax; i++) cv_mem->cv_l[i] = ZERO;
+  cv_mem->cv_l[1] = ONE;
   hsum = ZERO;
-  for (j=1; j <= q-2; j++) {
-    hsum += tau[j];
-    xi = hsum / hscale;
-    for (i=j+1; i >= 1; i--) l[i] = l[i]*xi + l[i-1];
+  for (j=1; j <= cv_mem->cv_q-2; j++) {
+    hsum += cv_mem->cv_tau[j];
+    xi = hsum / cv_mem->cv_hscale;
+    for (i=j+1; i >= 1; i--)
+      cv_mem->cv_l[i] = cv_mem->cv_l[i]*xi + cv_mem->cv_l[i-1];
   }
   
-  for (j=1; j <= q-2; j++) l[j+1] = q * (l[j] / (j+1));
+  for (j=1; j <= cv_mem->cv_q-2; j++)
+    cv_mem->cv_l[j+1] = cv_mem->cv_q * (cv_mem->cv_l[j] / (j+1));
   
-  for (j=2; j < q; j++)
-    N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+  for (j=2; j < cv_mem->cv_q; j++)
+    N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_zn[cv_mem->cv_q], ONE,
+                 cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 
-  if (quadr)
-    for (j=2; j < q; j++)
-      N_VLinearSum(-l[j], znQ[q], ONE, znQ[j], znQ[j]);
+  if (cv_mem->cv_quadr)
+    for (j=2; j < cv_mem->cv_q; j++)
+      N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_znQ[cv_mem->cv_q], ONE,
+                   cv_mem->cv_znQ[j], cv_mem->cv_znQ[j]);
 
-  if (sensi)
-    for (is=0; is<Ns; is++)
-      for (j=2; j < q; j++)
-        N_VLinearSum(-l[j], znS[q][is], ONE, znS[j][is], znS[j][is]);
+  if (cv_mem->cv_sensi)
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      for (j=2; j < cv_mem->cv_q; j++)
+        N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_znS[cv_mem->cv_q][is],
+                     ONE, cv_mem->cv_znS[j][is], cv_mem->cv_znS[j][is]);
 
 }
 
@@ -5442,18 +5444,20 @@ static void cvIncreaseBDF(CVodeMem cv_mem)
   int i, j;
   int is;
 
-  for (i=0; i <= qmax; i++) l[i] = ZERO;
-  l[2] = alpha1 = prod = xiold = ONE;
+  for (i=0; i <= cv_mem->cv_qmax; i++)
+    cv_mem->cv_l[i] = ZERO;
+  cv_mem->cv_l[2] = alpha1 = prod = xiold = ONE;
   alpha0 = -ONE;
-  hsum = hscale;
-  if (q > 1) {
-    for (j=1; j < q; j++) {
-      hsum += tau[j+1];
-      xi = hsum / hscale;
+  hsum = cv_mem->cv_hscale;
+  if (cv_mem->cv_q > 1) {
+    for (j=1; j < cv_mem->cv_q; j++) {
+      hsum += cv_mem->cv_tau[j+1];
+      xi = hsum / cv_mem->cv_hscale;
       prod *= xi;
       alpha0 -= ONE / (j+1);
       alpha1 += ONE / xi;
-      for (i=j+2; i >= 2; i--) l[i] = l[i]*xiold + l[i-1];
+      for (i=j+2; i >= 2; i--)
+        cv_mem->cv_l[i] = cv_mem->cv_l[i]*xiold + cv_mem->cv_l[i-1];
       xiold = xi;
     }
   }
@@ -5467,29 +5471,35 @@ static void cvIncreaseBDF(CVodeMem cv_mem)
      A1 contains dbar = (1/xi* - 1/xi_q)/prod(xi_j)
   */
   
-  N_VScale(A1, zn[indx_acor], zn[L]);
-  for (j=2; j <= q; j++)
-    N_VLinearSum(l[j], zn[L], ONE, zn[j], zn[j]);
+  N_VScale(A1, cv_mem->cv_zn[cv_mem->cv_indx_acor], cv_mem->cv_zn[cv_mem->cv_L]);
+  for (j=2; j <= cv_mem->cv_q; j++)
+    N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_zn[cv_mem->cv_L],
+                 ONE, cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 
-  if (quadr) {
-    N_VScale(A1, znQ[indx_acor], znQ[L]);
-    for (j=2; j <= q; j++)
-      N_VLinearSum(l[j], znQ[L], ONE, znQ[j], znQ[j]);
+  if (cv_mem->cv_quadr) {
+    N_VScale(A1, cv_mem->cv_znQ[cv_mem->cv_indx_acor], cv_mem->cv_znQ[cv_mem->cv_L]);
+    for (j=2; j <= cv_mem->cv_q; j++)
+      N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_znQ[cv_mem->cv_L],
+                   ONE, cv_mem->cv_znQ[j], cv_mem->cv_znQ[j]);
   }
 
-  if (sensi) {
-    for (is=0; is<Ns; is++) {
-      N_VScale(A1, znS[indx_acor][is], znS[L][is]);
-      for (j=2; j <= q; j++)
-        N_VLinearSum(l[j], znS[L][is], ONE, znS[j][is], znS[j][is]);
+  if (cv_mem->cv_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VScale(A1, cv_mem->cv_znS[cv_mem->cv_indx_acor][is],
+               cv_mem->cv_znS[cv_mem->cv_L][is]);
+      for (j=2; j <= cv_mem->cv_q; j++)
+        N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_znS[cv_mem->cv_L][is],
+                     ONE, cv_mem->cv_znS[j][is], cv_mem->cv_znS[j][is]);
     }
   }
 
-  if (quadr_sensi) {
-    for (is=0; is<Ns; is++) {
-      N_VScale(A1, znQS[indx_acor][is], znQS[L][is]);
-      for (j=2; j <= q; j++)
-        N_VLinearSum(l[j], znQS[L][is], ONE, znQS[j][is], znQS[j][is]);
+  if (cv_mem->cv_quadr_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VScale(A1, cv_mem->cv_znQS[cv_mem->cv_indx_acor][is],
+               cv_mem->cv_znQS[cv_mem->cv_L][is]);
+      for (j=2; j <= cv_mem->cv_q; j++)
+        N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_znQS[cv_mem->cv_L][is],
+                     ONE, cv_mem->cv_znQS[j][is], cv_mem->cv_znQS[j][is]);
     }
   }
 
@@ -5511,33 +5521,39 @@ static void cvDecreaseBDF(CVodeMem cv_mem)
   int i, j;
   int is;
   
-  for (i=0; i <= qmax; i++) l[i] = ZERO;
-  l[2] = ONE;
+  for (i=0; i <= cv_mem->cv_qmax; i++)
+    cv_mem->cv_l[i] = ZERO;
+  cv_mem->cv_l[2] = ONE;
   hsum = ZERO;
-  for (j=1; j <= q-2; j++) {
-    hsum += tau[j];
-    xi = hsum /hscale;
-    for (i=j+2; i >= 2; i--) l[i] = l[i]*xi + l[i-1];
+  for (j=1; j <= cv_mem->cv_q-2; j++) {
+    hsum += cv_mem->cv_tau[j];
+    xi = hsum / cv_mem->cv_hscale;
+    for (i=j+2; i >= 2; i--)
+      cv_mem->cv_l[i] = cv_mem->cv_l[i]*xi + cv_mem->cv_l[i-1];
   }
   
-  for (j=2; j < q; j++)
-    N_VLinearSum(-l[j], zn[q], ONE, zn[j], zn[j]);
+  for (j=2; j < cv_mem->cv_q; j++)
+    N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_zn[cv_mem->cv_q],
+                 ONE, cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 
-  if (quadr) {
-    for (j=2; j < q; j++)
-      N_VLinearSum(-l[j], znQ[q], ONE, znQ[j], znQ[j]);
+  if (cv_mem->cv_quadr) {
+    for (j=2; j < cv_mem->cv_q; j++)
+      N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_znQ[cv_mem->cv_q],
+                   ONE, cv_mem->cv_znQ[j], cv_mem->cv_znQ[j]);
   }
 
-  if (sensi) {
-    for (is=0; is<Ns; is++) 
-      for (j=2; j < q; j++)
-        N_VLinearSum(-l[j], znS[q][is], ONE, znS[j][is], znS[j][is]);
+  if (cv_mem->cv_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) 
+      for (j=2; j < cv_mem->cv_q; j++)
+        N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_znS[cv_mem->cv_q][is],
+                     ONE, cv_mem->cv_znS[j][is], cv_mem->cv_znS[j][is]);
   }
 
-  if (quadr_sensi) {
-    for (is=0; is<Ns; is++) 
-      for (j=2; j < q; j++)
-        N_VLinearSum(-l[j], znQS[q][is], ONE, znQS[j][is], znQS[j][is]);
+  if (cv_mem->cv_quadr_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) 
+      for (j=2; j < cv_mem->cv_q; j++)
+        N_VLinearSum(-cv_mem->cv_l[j], cv_mem->cv_znQS[cv_mem->cv_q][is],
+                     ONE, cv_mem->cv_znQS[j][is], cv_mem->cv_znQS[j][is]);
   }
 }
 
@@ -5555,30 +5571,30 @@ static void cvRescale(CVodeMem cv_mem)
   int is;
   realtype factor;
 
-  factor = eta;
-  for (j=1; j <= q; j++) {
+  factor = cv_mem->cv_eta;
+  for (j=1; j <= cv_mem->cv_q; j++) {
 
-    N_VScale(factor, zn[j], zn[j]);
+    N_VScale(factor, cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 
-    if (quadr)
-      N_VScale(factor, znQ[j], znQ[j]);
+    if (cv_mem->cv_quadr)
+      N_VScale(factor, cv_mem->cv_znQ[j], cv_mem->cv_znQ[j]);
 
-    if (sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(factor, znS[j][is], znS[j][is]);
+    if (cv_mem->cv_sensi)
+      for (is=0; is<cv_mem->cv_Ns; is++)
+        N_VScale(factor, cv_mem->cv_znS[j][is], cv_mem->cv_znS[j][is]);
 
-    if (quadr_sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(factor, znQS[j][is], znQS[j][is]);
+    if (cv_mem->cv_quadr_sensi)
+      for (is=0; is<cv_mem->cv_Ns; is++)
+        N_VScale(factor, cv_mem->cv_znQS[j][is], cv_mem->cv_znQS[j][is]);
 
-    factor *= eta;
+    factor *= cv_mem->cv_eta;
 
   }
 
-  h = hscale * eta;
-  next_h = h;
-  hscale = h;
-  nscon = 0;
+  cv_mem->cv_h = cv_mem->cv_hscale * cv_mem->cv_eta;
+  cv_mem->cv_next_h = cv_mem->cv_h;
+  cv_mem->cv_hscale = cv_mem->cv_h;
+  cv_mem->cv_nscon = 0;
 
 }
 
@@ -5597,34 +5613,39 @@ static void cvPredict(CVodeMem cv_mem)
   int j, k;
   int is;
 
-  tn += h;
-  if (tstopset) {
-    if ((tn - tstop)*h > ZERO) tn = tstop;
+  cv_mem->cv_tn += cv_mem->cv_h;
+  if (cv_mem->cv_tstopset) {
+    if ((cv_mem->cv_tn - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO)
+      cv_mem->cv_tn = cv_mem->cv_tstop;
   }
 
-  for (k = 1; k <= q; k++)
-    for (j = q; j >= k; j--) 
-      N_VLinearSum(ONE, zn[j-1], ONE, zn[j], zn[j-1]); 
+  for (k = 1; k <= cv_mem->cv_q; k++)
+    for (j = cv_mem->cv_q; j >= k; j--) 
+      N_VLinearSum(ONE, cv_mem->cv_zn[j-1], ONE,
+                   cv_mem->cv_zn[j], cv_mem->cv_zn[j-1]); 
 
-  if (quadr) {
-    for (k = 1; k <= q; k++)
-      for (j = q; j >= k; j--) 
-        N_VLinearSum(ONE, znQ[j-1], ONE, znQ[j], znQ[j-1]);
+  if (cv_mem->cv_quadr) {
+    for (k = 1; k <= cv_mem->cv_q; k++)
+      for (j = cv_mem->cv_q; j >= k; j--) 
+        N_VLinearSum(ONE, cv_mem->cv_znQ[j-1], ONE,
+                     cv_mem->cv_znQ[j], cv_mem->cv_znQ[j-1]);
   }
 
-  if (sensi) {
-    for (is=0; is<Ns; is++) {
-      for (k = 1; k <= q; k++)
-        for (j = q; j >= k; j--) 
-          N_VLinearSum(ONE, znS[j-1][is], ONE, znS[j][is], znS[j-1][is]);
+  if (cv_mem->cv_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      for (k = 1; k <= cv_mem->cv_q; k++)
+        for (j = cv_mem->cv_q; j >= k; j--) 
+          N_VLinearSum(ONE, cv_mem->cv_znS[j-1][is], ONE,
+                       cv_mem->cv_znS[j][is], cv_mem->cv_znS[j-1][is]);
     }
   }
 
-  if (quadr_sensi) {
-    for (is=0; is<Ns; is++) {
-      for (k = 1; k <= q; k++)
-        for (j = q; j >= k; j--) 
-          N_VLinearSum(ONE, znQS[j-1][is], ONE, znQS[j][is], znQS[j-1][is]);
+  if (cv_mem->cv_quadr_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      for (k = 1; k <= cv_mem->cv_q; k++)
+        for (j = cv_mem->cv_q; j >= k; j--) 
+          N_VLinearSum(ONE, cv_mem->cv_znQS[j-1][is], ONE,
+                       cv_mem->cv_znQS[j][is], cv_mem->cv_znQS[j-1][is]);
     }
   }
 
@@ -5650,7 +5671,7 @@ static void cvPredict(CVodeMem cv_mem)
 
 static void cvSet(CVodeMem cv_mem)
 {
-  switch(lmm) {
+  switch(cv_mem->cv_lmm) {
   case CV_ADAMS:
     cvSetAdams(cv_mem);
     break;
@@ -5658,10 +5679,11 @@ static void cvSet(CVodeMem cv_mem)
     cvSetBDF(cv_mem);
     break;
   }
-  rl1 = ONE / l[1];
-  gamma = h * rl1;
-  if (nst == 0) gammap = gamma;
-  gamrat = (nst > 0) ? gamma / gammap : ONE;  /* protect x / x != 1.0 */
+  cv_mem->cv_rl1 = ONE / cv_mem->cv_l[1];
+  cv_mem->cv_gamma = cv_mem->cv_h * cv_mem->cv_rl1;
+  if (cv_mem->cv_nst == 0) cv_mem->cv_gammap = cv_mem->cv_gamma;
+  cv_mem->cv_gamrat = (cv_mem->cv_nst > 0) ?
+    cv_mem->cv_gamma / cv_mem->cv_gammap : ONE;  /* protect x / x != 1.0 */
 }
 
 /*
@@ -5686,18 +5708,18 @@ static void cvSetAdams(CVodeMem cv_mem)
 {
   realtype m[L_MAX], M[3], hsum;
   
-  if (q == 1) {
-    l[0] = l[1] = tq[1] = tq[5] = ONE;
-    tq[2] = HALF;
-    tq[3] = ONE/TWELVE;
-    tq[4] = nlscoef / tq[2];       /* = 0.1 / tq[2] */
+  if (cv_mem->cv_q == 1) {
+    cv_mem->cv_l[0] = cv_mem->cv_l[1] = cv_mem->cv_tq[1] = cv_mem->cv_tq[5] = ONE;
+    cv_mem->cv_tq[2] = HALF;
+    cv_mem->cv_tq[3] = ONE/TWELVE;
+    cv_mem->cv_tq[4] = cv_mem->cv_nlscoef / cv_mem->cv_tq[2];       /* = 0.1 / tq[2] */
     return;
   }
   
   hsum = cvAdamsStart(cv_mem, m);
   
-  M[0] = cvAltSum(q-1, m, 1);
-  M[1] = cvAltSum(q-1, m, 2);
+  M[0] = cvAltSum(cv_mem->cv_q-1, m, 1);
+  M[1] = cvAltSum(cv_mem->cv_q-1, m, 2);
   
   cvAdamsFinish(cv_mem, m, M, hsum);
 }
@@ -5714,17 +5736,18 @@ static realtype cvAdamsStart(CVodeMem cv_mem, realtype m[])
   realtype hsum, xi_inv, sum;
   int i, j;
   
-  hsum = h;
+  hsum = cv_mem->cv_h;
   m[0] = ONE;
-  for (i=1; i <= q; i++) m[i] = ZERO;
-  for (j=1; j < q; j++) {
-    if ((j==q-1) && (qwait == 1)) {
-      sum = cvAltSum(q-2, m, 2);
-      tq[1] = q * sum / m[q-2];
-    }
-    xi_inv = h / hsum;
-    for (i=j; i >= 1; i--) m[i] += m[i-1] * xi_inv;
-    hsum += tau[j];
+  for (i=1; i <= cv_mem->cv_q; i++) m[i] = ZERO;
+  for (j=1; j < cv_mem->cv_q; j++) {
+    if ((j==cv_mem->cv_q-1) && (cv_mem->cv_qwait == 1)) {
+      sum = cvAltSum(cv_mem->cv_q-2, m, 2);
+      cv_mem->cv_tq[1] = cv_mem->cv_q * sum / m[cv_mem->cv_q-2];
+    }
+    xi_inv = cv_mem->cv_h / hsum;
+    for (i=j; i >= 1; i--)
+      m[i] += m[i-1] * xi_inv;
+    hsum += cv_mem->cv_tau[j];
     /* The m[i] are coefficients of product(1 to j) (1 + x/xi_i) */
   }
   return(hsum);
@@ -5743,21 +5766,23 @@ static void cvAdamsFinish(CVodeMem cv_mem, realtype m[], realtype M[], realtype
   
   M0_inv = ONE / M[0];
   
-  l[0] = ONE;
-  for (i=1; i <= q; i++) l[i] = M0_inv * (m[i-1] / i);
-  xi = hsum / h;
+  cv_mem->cv_l[0] = ONE;
+  for (i=1; i <= cv_mem->cv_q; i++)
+    cv_mem->cv_l[i] = M0_inv * (m[i-1] / i);
+  xi = hsum / cv_mem->cv_h;
   xi_inv = ONE / xi;
   
-  tq[2] = M[1] * M0_inv / xi;
-  tq[5] = xi / l[q];
+  cv_mem->cv_tq[2] = M[1] * M0_inv / xi;
+  cv_mem->cv_tq[5] = xi / cv_mem->cv_l[cv_mem->cv_q];
 
-  if (qwait == 1) {
-    for (i=q; i >= 1; i--) m[i] += m[i-1] * xi_inv;
-    M[2] = cvAltSum(q, m, 2);
-    tq[3] = M[2] * M0_inv / L;
+  if (cv_mem->cv_qwait == 1) {
+    for (i=cv_mem->cv_q; i >= 1; i--)
+      m[i] += m[i-1] * xi_inv;
+    M[2] = cvAltSum(cv_mem->cv_q, m, 2);
+    cv_mem->cv_tq[3] = M[2] * M0_inv / cv_mem->cv_L;
   }
 
-  tq[4] = nlscoef / tq[2];
+  cv_mem->cv_tq[4] = cv_mem->cv_nlscoef / cv_mem->cv_tq[2];
 }
 
 /*  
@@ -5809,26 +5834,28 @@ static void cvSetBDF(CVodeMem cv_mem)
   realtype alpha0, alpha0_hat, xi_inv, xistar_inv, hsum;
   int i,j;
   
-  l[0] = l[1] = xi_inv = xistar_inv = ONE;
-  for (i=2; i <= q; i++) l[i] = ZERO;
+  cv_mem->cv_l[0] = cv_mem->cv_l[1] = xi_inv = xistar_inv = ONE;
+  for (i=2; i <= cv_mem->cv_q; i++) cv_mem->cv_l[i] = ZERO;
   alpha0 = alpha0_hat = -ONE;
-  hsum = h;
-  if (q > 1) {
-    for (j=2; j < q; j++) {
-      hsum += tau[j-1];
-      xi_inv = h / hsum;
+  hsum = cv_mem->cv_h;
+  if (cv_mem->cv_q > 1) {
+    for (j=2; j < cv_mem->cv_q; j++) {
+      hsum += cv_mem->cv_tau[j-1];
+      xi_inv = cv_mem->cv_h / hsum;
       alpha0 -= ONE / j;
-      for (i=j; i >= 1; i--) l[i] += l[i-1]*xi_inv;
+      for (i=j; i >= 1; i--)
+        cv_mem->cv_l[i] += cv_mem->cv_l[i-1]*xi_inv;
       /* The l[i] are coefficients of product(1 to j) (1 + x/xi_i) */
     }
     
     /* j = q */
-    alpha0 -= ONE / q;
-    xistar_inv = -l[1] - alpha0;
-    hsum += tau[q-1];
-    xi_inv = h / hsum;
-    alpha0_hat = -l[1] - xi_inv;
-    for (i=q; i >= 1; i--) l[i] += l[i-1]*xistar_inv;
+    alpha0 -= ONE / cv_mem->cv_q;
+    xistar_inv = -cv_mem->cv_l[1] - alpha0;
+    hsum += cv_mem->cv_tau[cv_mem->cv_q-1];
+    xi_inv = cv_mem->cv_h / hsum;
+    alpha0_hat = -cv_mem->cv_l[1] - xi_inv;
+    for (i=cv_mem->cv_q; i >= 1; i--)
+      cv_mem->cv_l[i] += cv_mem->cv_l[i-1]*xistar_inv;
   }
 
   cvSetTqBDF(cv_mem, hsum, alpha0, alpha0_hat, xi_inv, xistar_inv);
@@ -5848,26 +5875,26 @@ static void cvSetTqBDF(CVodeMem cv_mem, realtype hsum, realtype alpha0,
   realtype C, Cpinv, Cppinv;
   
   A1 = ONE - alpha0_hat + alpha0;
-  A2 = ONE + q * A1;
-  tq[2] = SUNRabs(A1 / (alpha0 * A2));
-  tq[5] = SUNRabs(A2 * xistar_inv / (l[q] * xi_inv));
-  if (qwait == 1) {
-    if (q > 1) {
-      C = xistar_inv / l[q];
-      A3 = alpha0 + ONE / q;
+  A2 = ONE + cv_mem->cv_q * A1;
+  cv_mem->cv_tq[2] = SUNRabs(A1 / (alpha0 * A2));
+  cv_mem->cv_tq[5] = SUNRabs(A2 * xistar_inv / (cv_mem->cv_l[cv_mem->cv_q] * xi_inv));
+  if (cv_mem->cv_qwait == 1) {
+    if (cv_mem->cv_q > 1) {
+      C = xistar_inv / cv_mem->cv_l[cv_mem->cv_q];
+      A3 = alpha0 + ONE / cv_mem->cv_q;
       A4 = alpha0_hat + xi_inv;
       Cpinv = (ONE - A4 + A3) / A3;
-      tq[1] = SUNRabs(C * Cpinv);
+      cv_mem->cv_tq[1] = SUNRabs(C * Cpinv);
     }
-    else tq[1] = ONE;
-    hsum += tau[q];
-    xi_inv = h / hsum;
-    A5 = alpha0 - (ONE / (q+1));
+    else cv_mem->cv_tq[1] = ONE;
+    hsum += cv_mem->cv_tau[cv_mem->cv_q];
+    xi_inv = cv_mem->cv_h / hsum;
+    A5 = alpha0 - (ONE / (cv_mem->cv_q+1));
     A6 = alpha0_hat - xi_inv;
     Cppinv = (ONE - A6 + A5) / A2;
-    tq[3] = SUNRabs(Cppinv / (xi_inv * (q+2) * A5));
+    cv_mem->cv_tq[3] = SUNRabs(Cppinv / (xi_inv * (cv_mem->cv_q+2) * A5));
   }
-  tq[4] = nlscoef / tq[2];
+  cv_mem->cv_tq[4] = cv_mem->cv_nlscoef / cv_mem->cv_tq[2];
 }
 
 /* 
@@ -5889,7 +5916,7 @@ static int cvNls(CVodeMem cv_mem, int nflag)
 {
   int flag = CV_SUCCESS;
 
-  switch(iter) {
+  switch(cv_mem->cv_iter) {
   case CV_FUNCTIONAL:
     flag = cvNlsFunctional(cv_mem);
     break;
@@ -5934,75 +5961,82 @@ static int cvNlsFunctional(CVodeMem cv_mem)
   N_Vector wrk1, wrk2;
 
   /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */
-  do_sensi_sim = (sensi && (ism==CV_SIMULTANEOUS));
+  do_sensi_sim = (cv_mem->cv_sensi && (cv_mem->cv_ism==CV_SIMULTANEOUS));
 
   /* Initialize counter and evaluate f at predicted y */
-  crate = ONE;
+  cv_mem->cv_crate = ONE;
   m = 0;
 
   /* Initialize delS and Delp to avoid compiler warning message */
   delS = Delp = ZERO;
 
-  retval = f(tn, zn[0], tempv, user_data);
-  nfe++;
+  retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                        cv_mem->cv_tempv, cv_mem->cv_user_data);
+  cv_mem->cv_nfe++;
   if (retval < 0) return(CV_RHSFUNC_FAIL);
   if (retval > 0) return(RHSFUNC_RECVR);
 
   if (do_sensi_sim) {
-    wrk1 = ftemp;
-    wrk2 = ftempS[0];
-    retval = cvSensRhsWrapper(cv_mem, tn, zn[0], tempv, znS[0], tempvS, wrk1, wrk2);
+    wrk1 = cv_mem->cv_ftemp;
+    wrk2 = cv_mem->cv_ftempS[0];
+    retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_zn[0],
+                              cv_mem->cv_tempv, cv_mem->cv_znS[0],
+                              cv_mem->cv_tempvS, wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) return(SRHSFUNC_RECVR);
   }
 
   /* Initialize correction to zero */
 
-  N_VConst(ZERO, acor);
+  N_VConst(ZERO, cv_mem->cv_acor);
   if (do_sensi_sim) {
-    for (is=0; is<Ns; is++)
-      N_VConst(ZERO,acorS[is]);
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VConst(ZERO, cv_mem->cv_acorS[is]);
   }
 
   /* Loop until convergence; accumulate corrections in acor */
 
-  loop {
+  for(;;) {
 
-    nni++;
+    cv_mem->cv_nni++;
 
     /* Correct y directly from the last f value */
 
-    N_VLinearSum(h, tempv, -ONE, zn[1], tempv);
-    N_VScale(rl1, tempv, tempv);
-    N_VLinearSum(ONE, zn[0], ONE, tempv, y);
+    N_VLinearSum(cv_mem->cv_h, cv_mem->cv_tempv, -ONE,
+                 cv_mem->cv_zn[1], cv_mem->cv_tempv);
+    N_VScale(cv_mem->cv_rl1, cv_mem->cv_tempv, cv_mem->cv_tempv);
+    N_VLinearSum(ONE, cv_mem->cv_zn[0], ONE, cv_mem->cv_tempv, cv_mem->cv_y);
 
     if (do_sensi_sim)
-      for (is=0; is<Ns; is++) {
-        N_VLinearSum(h, tempvS[is], -ONE, znS[1][is], tempvS[is]);
-        N_VScale(rl1, tempvS[is], tempvS[is]);
-        N_VLinearSum(ONE, znS[0][is], ONE, tempvS[is], yS[is]);
+      for (is=0; is<cv_mem->cv_Ns; is++) {
+        N_VLinearSum(cv_mem->cv_h, cv_mem->cv_tempvS[is], -ONE,
+                     cv_mem->cv_znS[1][is], cv_mem->cv_tempvS[is]);
+        N_VScale(cv_mem->cv_rl1, cv_mem->cv_tempvS[is], cv_mem->cv_tempvS[is]);
+        N_VLinearSum(ONE, cv_mem->cv_znS[0][is], ONE,
+                     cv_mem->cv_tempvS[is], cv_mem->cv_yS[is]);
       }
     
     /* Get WRMS norm of current correction to use in convergence test */
 
-    N_VLinearSum(ONE, tempv, -ONE, acor, acor);
+    N_VLinearSum(ONE, cv_mem->cv_tempv, -ONE, cv_mem->cv_acor, cv_mem->cv_acor);
     if (do_sensi_sim)
-      for (is=0; is<Ns; is++)
-        N_VLinearSum(ONE, tempvS[is], -ONE, acorS[is], acorS[is]);
+      for (is=0; is<cv_mem->cv_Ns; is++)
+        N_VLinearSum(ONE, cv_mem->cv_tempvS[is], -ONE,
+                     cv_mem->cv_acorS[is], cv_mem->cv_acorS[is]);
 
-    del = N_VWrmsNorm(acor, ewt);
+    del = N_VWrmsNorm(cv_mem->cv_acor, cv_mem->cv_ewt);
     if (do_sensi_sim)
-      delS = cvSensUpdateNorm(cv_mem, del, acorS, ewtS);
+      delS = cvSensUpdateNorm(cv_mem, del, cv_mem->cv_acorS, cv_mem->cv_ewtS);
 
-    N_VScale(ONE, tempv, acor);
+    N_VScale(ONE, cv_mem->cv_tempv, cv_mem->cv_acor);
     if (do_sensi_sim) 
-      for (is=0; is<Ns; is++)
-        N_VScale(ONE, tempvS[is], acorS[is]);
+      for (is=0; is<cv_mem->cv_Ns; is++)
+        N_VScale(ONE, cv_mem->cv_tempvS[is], cv_mem->cv_acorS[is]);
     
     /* Test for convergence.  If m > 0, an estimate of the convergence
        rate constant is stored in crate, and used in the test. 
 
-       Recall that, even when errconS=FALSE, all variables are used in the
+       Recall that, even when errconS=SUNFALSE, all variables are used in the
        convergence test. Hence, we use Del (and not del). However, acnrm
        is used in the error test and thus it has different forms
        depending on errconS (and this explains why we have to carry around
@@ -6010,17 +6044,20 @@ static int cvNlsFunctional(CVodeMem cv_mem)
     */
     
     Del = (do_sensi_sim) ? delS : del;
-    if (m > 0) crate = SUNMAX(CRDOWN * crate, Del / Delp);
-    dcon = Del * SUNMIN(ONE, crate) / tq[4];
+    if (m > 0) cv_mem->cv_crate = SUNMAX(CRDOWN * cv_mem->cv_crate, Del / Delp);
+    dcon = Del * SUNMIN(ONE, cv_mem->cv_crate) / cv_mem->cv_tq[4];
 
     if (dcon <= ONE) {
       if (m == 0)
-        if (do_sensi_sim && errconS) acnrm = delS;
-        else                         acnrm = del;
+        if (do_sensi_sim && cv_mem->cv_errconS)
+          cv_mem->cv_acnrm = delS;
+        else
+          cv_mem->cv_acnrm = del;
       else {
-        acnrm = N_VWrmsNorm(acor, ewt);
-        if (do_sensi_sim && errconS)
-          acnrm = cvSensUpdateNorm(cv_mem, acnrm, acorS, ewtS);
+        cv_mem->cv_acnrm = N_VWrmsNorm(cv_mem->cv_acor, cv_mem->cv_ewt);
+        if (do_sensi_sim && cv_mem->cv_errconS)
+          cv_mem->cv_acnrm = cvSensUpdateNorm(cv_mem, cv_mem->cv_acnrm,
+                                              cv_mem->cv_acorS, cv_mem->cv_ewtS);
       }
       return(CV_SUCCESS);  /* Convergence achieved */
     }
@@ -6028,21 +6065,25 @@ static int cvNlsFunctional(CVodeMem cv_mem)
     /* Stop at maxcor iterations or if iter. seems to be diverging */
 
     m++;
-    if ((m==maxcor) || ((m >= 2) && (Del > RDIV * Delp))) return(CONV_FAIL);
+    if ((m==cv_mem->cv_maxcor) || ((m >= 2) && (Del > RDIV * Delp)))
+      return(CONV_FAIL);
 
     /* Save norm of correction, evaluate f, and loop again */
 
     Delp = Del;
 
-    retval = f(tn, y, tempv, user_data);
-    nfe++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_y,
+                          cv_mem->cv_tempv, cv_mem->cv_user_data);
+    cv_mem->cv_nfe++;
     if (retval < 0) return(CV_RHSFUNC_FAIL);
     if (retval > 0) return(RHSFUNC_RECVR);
 
     if (do_sensi_sim) {
-      wrk1 = ftemp;
-      wrk2 = ftempS[0];
-      retval = cvSensRhsWrapper(cv_mem, tn, y, tempv, yS, tempvS, wrk1, wrk2);
+      wrk1 = cv_mem->cv_ftemp;
+      wrk2 = cv_mem->cv_ftempS[0];
+      retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                                cv_mem->cv_tempv, cv_mem->cv_yS,
+                                cv_mem->cv_tempvS, wrk1, wrk2);
       if (retval < 0) return(CV_SRHSFUNC_FAIL);
       if (retval > 0) return(SRHSFUNC_RECVR);
     }      
@@ -6091,76 +6132,82 @@ static int cvNlsNewton(CVodeMem cv_mem, int nflag)
   int retval, is;
   
   /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */
-  do_sensi_sim = (sensi && (ism==CV_SIMULTANEOUS));
+  do_sensi_sim = (cv_mem->cv_sensi && (cv_mem->cv_ism==CV_SIMULTANEOUS));
 
-  vtemp1 = acor;  /* rename acor as vtemp1 for readability  */
-  vtemp2 = y;     /* rename y as vtemp2 for readability     */
-  vtemp3 = tempv; /* rename tempv as vtemp3 for readability */
+  vtemp1 = cv_mem->cv_acor;  /* rename acor as vtemp1 for readability  */
+  vtemp2 = cv_mem->cv_y;     /* rename y as vtemp2 for readability     */
+  vtemp3 = cv_mem->cv_tempv; /* rename tempv as vtemp3 for readability */
   
   /* Set flag convfail, input to lsetup for its evaluation decision */
   convfail = ((nflag == FIRST_CALL) || (nflag == PREV_ERR_FAIL)) ?
     CV_NO_FAILURES : CV_FAIL_OTHER;
 
   /* Decide whether or not to call setup routine (if one exists) */
-  if (setupNonNull) {      
+  if (cv_mem->cv_lsetup) {      
     callSetup = (nflag == PREV_CONV_FAIL) || (nflag == PREV_ERR_FAIL) ||
-      (nst == 0) || (nst >= nstlp + MSBP) || (SUNRabs(gamrat-ONE) > DGMAX);
+      (cv_mem->cv_nst == 0) ||
+      (cv_mem->cv_nst >= cv_mem->cv_nstlp + MSBP) ||
+      (SUNRabs(cv_mem->cv_gamrat-ONE) > DGMAX);
 
     /* Decide whether to force a call to setup */
-    if (forceSetup) {
-      callSetup = TRUE;
+    if (cv_mem->cv_forceSetup) {
+      callSetup = SUNTRUE;
       convfail = CV_FAIL_OTHER;
     }
 
   } else {  
-    crate = ONE;
-    crateS = ONE;  /* if NO lsetup all conv. rates are set to ONE */
-    callSetup = FALSE;
+    cv_mem->cv_crate = ONE;
+    cv_mem->cv_crateS = ONE;  /* if NO lsetup all conv. rates are set to ONE */
+    callSetup = SUNFALSE;
   }
   
   /* Looping point for the solution of the nonlinear system.
      Evaluate f at the predicted y, call lsetup if indicated, and
      call cvNewtonIteration for the Newton iteration itself.      */
 
-  loop {
+  for(;;) {
 
-    retval = f(tn, zn[0], ftemp, user_data);
-    nfe++; 
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                          cv_mem->cv_ftemp, cv_mem->cv_user_data);
+    cv_mem->cv_nfe++; 
     if (retval < 0) return(CV_RHSFUNC_FAIL);
     if (retval > 0) return(RHSFUNC_RECVR);
 
     if (do_sensi_sim) {
-      wrk1 = tempv;
-      wrk2 = tempvS[0];
-      retval = cvSensRhsWrapper(cv_mem, tn, zn[0], ftemp, znS[0], ftempS, wrk1, wrk2);
+      wrk1 = cv_mem->cv_tempv;
+      wrk2 = cv_mem->cv_tempvS[0];
+      retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_zn[0],
+                                cv_mem->cv_ftemp, cv_mem->cv_znS[0],
+                                cv_mem->cv_ftempS, wrk1, wrk2);
       if (retval < 0) return(CV_SRHSFUNC_FAIL);
       if (retval > 0) return(SRHSFUNC_RECVR);
     }
 
     if (callSetup) {
-      ier = lsetup(cv_mem, convfail, zn[0], ftemp, &jcur, 
-                   vtemp1, vtemp2, vtemp3);
-      nsetups++;
-      callSetup = FALSE;
-      forceSetup = FALSE;
-      gamrat = ONE; 
-      gammap = gamma;
-      crate = ONE;
-      crateS = ONE; /* after lsetup all conv. rates are reset to ONE */
-      nstlp = nst;
+      ier = cv_mem->cv_lsetup(cv_mem, convfail, cv_mem->cv_zn[0],
+                              cv_mem->cv_ftemp, &(cv_mem->cv_jcur), 
+                              vtemp1, vtemp2, vtemp3);
+      cv_mem->cv_nsetups++;
+      callSetup = SUNFALSE;
+      cv_mem->cv_forceSetup = SUNFALSE;
+      cv_mem->cv_gamrat = ONE; 
+      cv_mem->cv_gammap = cv_mem->cv_gamma;
+      cv_mem->cv_crate = ONE;
+      cv_mem->cv_crateS = ONE; /* after lsetup all conv. rates are reset to ONE */
+      cv_mem->cv_nstlp = cv_mem->cv_nst;
       /* Return if lsetup failed */
       if (ier < 0) return(CV_LSETUP_FAIL);
       if (ier > 0) return(CONV_FAIL);
     }
 
     /* Set acor to zero and load prediction into y vector */
-    N_VConst(ZERO, acor);
-    N_VScale(ONE, zn[0], y);
+    N_VConst(ZERO, cv_mem->cv_acor);
+    N_VScale(ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
 
     if (do_sensi_sim)
-      for (is=0; is<Ns; is++) {
-        N_VConst(ZERO, acorS[is]);
-        N_VScale(ONE, znS[0][is], yS[is]);
+      for (is=0; is<cv_mem->cv_Ns; is++) {
+        N_VConst(ZERO, cv_mem->cv_acorS[is]);
+        N_VScale(ONE, cv_mem->cv_znS[0][is], cv_mem->cv_yS[is]);
       }
 
     /* Do the Newton iteration */
@@ -6171,7 +6218,7 @@ static int cvNlsNewton(CVodeMem cv_mem, int nflag)
        in which convfail=CV_FAIL_BAD_J.  Otherwise return.                 */
     if (ier != TRY_AGAIN) return(ier);
     
-    callSetup = TRUE;
+    callSetup = SUNTRUE;
     convfail = CV_FAIL_BAD_J;
   }
 }
@@ -6205,9 +6252,9 @@ static int cvNewtonIteration(CVodeMem cv_mem)
   int retval, is;
   
   /* Are we computing sensitivities with the CV_SIMULTANEOUS approach? */
-  do_sensi_sim = (sensi && (ism==CV_SIMULTANEOUS));
+  do_sensi_sim = (cv_mem->cv_sensi && (cv_mem->cv_ism==CV_SIMULTANEOUS));
 
-  mnewt = m = 0;
+  cv_mem->cv_mnewt = m = 0;
 
   /* Initialize delS and Delp to avoid compiler warning message */
   delS = Delp = ZERO;
@@ -6220,24 +6267,29 @@ static int cvNewtonIteration(CVodeMem cv_mem)
      yS     <- yS_n(0)                 */
 
   /* Looping point for Newton iteration */
-  loop {
+  for(;;) {
     
     /* Evaluate the residual of the nonlinear system */
-    N_VLinearSum(rl1, zn[1], ONE, acor, tempv);
-    N_VLinearSum(gamma, ftemp, -ONE, tempv, tempv);
+    N_VLinearSum(cv_mem->cv_rl1, cv_mem->cv_zn[1], ONE,
+                 cv_mem->cv_acor, cv_mem->cv_tempv);
+    N_VLinearSum(cv_mem->cv_gamma, cv_mem->cv_ftemp, -ONE,
+                 cv_mem->cv_tempv, cv_mem->cv_tempv);
 
     /* Call the lsolve function */
-    b = tempv;
-    retval = lsolve(cv_mem, b, ewt, y, ftemp); 
-    nni++;
+    b = cv_mem->cv_tempv;
+    retval = cv_mem->cv_lsolve(cv_mem, b, cv_mem->cv_ewt,
+                               cv_mem->cv_y, cv_mem->cv_ftemp); 
+    cv_mem->cv_nni++;
 
     if (retval < 0) return(CV_LSOLVE_FAIL);
     
     /* If lsolve had a recoverable failure and Jacobian data is
        not current, signal to try the solution again            */
     if (retval > 0) { 
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(CONV_FAIL);
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(CONV_FAIL);
     }
 
     /* Solve the sensitivity linear systems and do the same 
@@ -6245,32 +6297,39 @@ static int cvNewtonIteration(CVodeMem cv_mem)
  
     if (do_sensi_sim) {
 
-      for (is=0; is<Ns; is++) {
-        N_VLinearSum(rl1, znS[1][is], ONE, acorS[is], tempvS[is]);
-        N_VLinearSum(gamma, ftempS[is], -ONE, tempvS[is], tempvS[is]);
+      for (is=0; is<cv_mem->cv_Ns; is++) {
+        N_VLinearSum(cv_mem->cv_rl1, cv_mem->cv_znS[1][is], ONE,
+                     cv_mem->cv_acorS[is], cv_mem->cv_tempvS[is]);
+        N_VLinearSum(cv_mem->cv_gamma, cv_mem->cv_ftempS[is], -ONE,
+                     cv_mem->cv_tempvS[is], cv_mem->cv_tempvS[is]);
       }
-      bS = tempvS;
-      for (is=0; is<Ns; is++) {
-        retval = lsolve(cv_mem, bS[is], ewtS[is], y, ftemp);
+      bS = cv_mem->cv_tempvS;
+      for (is=0; is<cv_mem->cv_Ns; is++) {
+        retval = cv_mem->cv_lsolve(cv_mem, bS[is], cv_mem->cv_ewtS[is],
+                                   cv_mem->cv_y, cv_mem->cv_ftemp);
         if (retval < 0) return(CV_LSOLVE_FAIL);
         if (retval > 0) { 
-          if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-          else                           return(CONV_FAIL);
+          if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+            return(TRY_AGAIN);
+          else
+            return(CONV_FAIL);
         }
       }
     }
     
     /* Get WRMS norm of correction; add correction to acor and y */
 
-    del = N_VWrmsNorm(b, ewt);
-    N_VLinearSum(ONE, acor, ONE, b, acor);
-    N_VLinearSum(ONE, zn[0], ONE, acor, y);
+    del = N_VWrmsNorm(b, cv_mem->cv_ewt);
+    N_VLinearSum(ONE, cv_mem->cv_acor, ONE, b, cv_mem->cv_acor);
+    N_VLinearSum(ONE, cv_mem->cv_zn[0], ONE, cv_mem->cv_acor, cv_mem->cv_y);
 
     if (do_sensi_sim) {
-      delS = cvSensUpdateNorm(cv_mem, del, bS, ewtS);
-      for (is=0; is<Ns; is++) {
-        N_VLinearSum(ONE, acorS[is], ONE, bS[is], acorS[is]);
-        N_VLinearSum(ONE, znS[0][is], ONE, acorS[is], yS[is]);
+      delS = cvSensUpdateNorm(cv_mem, del, bS, cv_mem->cv_ewtS);
+      for (is=0; is<cv_mem->cv_Ns; is++) {
+        N_VLinearSum(ONE, cv_mem->cv_acorS[is], ONE,
+                     bS[is], cv_mem->cv_acorS[is]);
+        N_VLinearSum(ONE, cv_mem->cv_znS[0][is], ONE,
+                     cv_mem->cv_acorS[is], cv_mem->cv_yS[is]);
       }
     }
 
@@ -6278,50 +6337,63 @@ static int cvNewtonIteration(CVodeMem cv_mem)
        rate constant is stored in crate, and used in the test.        */
 
     Del = (do_sensi_sim) ? delS : del;
-    if (m > 0) crate = SUNMAX(CRDOWN * crate, Del/Delp);
-    dcon = Del * SUNMIN(ONE, crate) / tq[4];
+    if (m > 0)
+      cv_mem->cv_crate = SUNMAX(CRDOWN * cv_mem->cv_crate, Del/Delp);
+    dcon = Del * SUNMIN(ONE, cv_mem->cv_crate) / cv_mem->cv_tq[4];
     
     if (dcon <= ONE) {
       if (m == 0)
-        if (do_sensi_sim && errconS) acnrm = delS;
-        else                         acnrm = del;
+        if (do_sensi_sim && cv_mem->cv_errconS)
+          cv_mem->cv_acnrm = delS;
+        else
+          cv_mem->cv_acnrm = del;
       else {
-        acnrm = N_VWrmsNorm(acor, ewt);
-        if (do_sensi_sim && errconS)
-          acnrm = cvSensUpdateNorm(cv_mem, acnrm, acorS, ewtS);
+        cv_mem->cv_acnrm = N_VWrmsNorm(cv_mem->cv_acor, cv_mem->cv_ewt);
+        if (do_sensi_sim && cv_mem->cv_errconS)
+          cv_mem->cv_acnrm = cvSensUpdateNorm(cv_mem, cv_mem->cv_acnrm,
+                                              cv_mem->cv_acorS, cv_mem->cv_ewtS);
       }
-      jcur = FALSE;
+      cv_mem->cv_jcur = SUNFALSE;
       return(CV_SUCCESS);  /* Convergence achieved */
     }
 
-    mnewt = ++m;
+    cv_mem->cv_mnewt = ++m;
     
     /* Stop at maxcor iterations or if iter. seems to be diverging.
        If still not converged and Jacobian data is not current, 
        signal to try the solution again                            */
-    if ((m == maxcor) || ((m >= 2) && (Del > RDIV * Delp))) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(CONV_FAIL);
+    if ((m == cv_mem->cv_maxcor) || ((m >= 2) && (Del > RDIV * Delp))) {
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(CONV_FAIL);
     }
     
     /* Save norm of correction, evaluate f, and loop again */
     Delp = Del;
-    retval = f(tn, y, ftemp, user_data);
-    nfe++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_y,
+                          cv_mem->cv_ftemp, cv_mem->cv_user_data);
+    cv_mem->cv_nfe++;
     if (retval < 0) return(CV_RHSFUNC_FAIL);
     if (retval > 0) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(RHSFUNC_RECVR);
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(RHSFUNC_RECVR);
     }
 
     if (do_sensi_sim) {
-      wrk1 = tempv;
-      wrk2 = tempvS[0];
-      retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, yS, ftempS, wrk1, wrk2);
+      wrk1 = cv_mem->cv_tempv;
+      wrk2 = cv_mem->cv_tempvS[0];
+      retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                                cv_mem->cv_ftemp, cv_mem->cv_yS,
+                                cv_mem->cv_ftempS, wrk1, wrk2);
       if (retval < 0) return(CV_SRHSFUNC_FAIL);
       if (retval > 0) {
-        if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-        else                           return(SRHSFUNC_RECVR);
+        if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+          return(TRY_AGAIN);
+        else
+          return(SRHSFUNC_RECVR);
       }
     }
 
@@ -6350,22 +6422,24 @@ static int cvQuadNls(CVodeMem cv_mem)
   int retval;
 
   /* Save quadrature correction in acorQ */
-  retval = fQ(tn, y, acorQ, user_data);
-  nfQe++;
+  retval = cv_mem->cv_fQ(cv_mem->cv_tn, cv_mem->cv_y,
+                         cv_mem->cv_acorQ, cv_mem->cv_user_data);
+  cv_mem->cv_nfQe++;
   if (retval < 0) return(CV_QRHSFUNC_FAIL);
   if (retval > 0) return(QRHSFUNC_RECVR);
 
   /* If needed, save the value of yQdot = fQ into ftempQ
    * for use in evaluating fQS */
-  if (quadr_sensi) {
-    N_VScale(ONE, acorQ, ftempQ);
+  if (cv_mem->cv_quadr_sensi) {
+    N_VScale(ONE, cv_mem->cv_acorQ, cv_mem->cv_ftempQ);
   }
 
-  N_VLinearSum(h, acorQ, -ONE, znQ[1], acorQ);
-  N_VScale(rl1, acorQ, acorQ);
+  N_VLinearSum(cv_mem->cv_h, cv_mem->cv_acorQ, -ONE,
+               cv_mem->cv_znQ[1], cv_mem->cv_acorQ);
+  N_VScale(cv_mem->cv_rl1, cv_mem->cv_acorQ, cv_mem->cv_acorQ);
 
   /* Apply correction to quadrature variables */
-  N_VLinearSum(ONE, znQ[0], ONE, acorQ, yQ);
+  N_VLinearSum(ONE, cv_mem->cv_znQ[0], ONE, cv_mem->cv_acorQ, cv_mem->cv_yQ);
 
   return(CV_SUCCESS);
 }
@@ -6391,17 +6465,22 @@ static int cvQuadSensNls(CVodeMem cv_mem)
   int is, retval;
 
   /* Save quadrature correction in acorQ */
-  retval = fQS(Ns, tn, y, yS, ftempQ, acorQS, user_data, tempv, tempvQ);
-  nfQSe++;
+  retval = cv_mem->cv_fQS(cv_mem->cv_Ns, cv_mem->cv_tn, cv_mem->cv_y,
+                          cv_mem->cv_yS, cv_mem->cv_ftempQ,
+                          cv_mem->cv_acorQS, cv_mem->cv_user_data,
+                          cv_mem->cv_tempv, cv_mem->cv_tempvQ);
+  cv_mem->cv_nfQSe++;
   if (retval < 0) return(CV_QSRHSFUNC_FAIL);
   if (retval > 0) return(QSRHSFUNC_RECVR);
 
 
-  for (is=0; is<Ns; is++) {
-    N_VLinearSum(h, acorQS[is], -ONE, znQS[1][is], acorQS[is]);
-    N_VScale(rl1, acorQS[is], acorQS[is]);
+  for (is=0; is<cv_mem->cv_Ns; is++) {
+    N_VLinearSum(cv_mem->cv_h, cv_mem->cv_acorQS[is], -ONE,
+                 cv_mem->cv_znQS[1][is], cv_mem->cv_acorQS[is]);
+    N_VScale(cv_mem->cv_rl1, cv_mem->cv_acorQS[is], cv_mem->cv_acorQS[is]);
     /* Apply correction to quadrature sensitivity variables */
-    N_VLinearSum(ONE, znQS[0][is], ONE, acorQS[is], yQS[is]);
+    N_VLinearSum(ONE, cv_mem->cv_znQS[0][is], ONE,
+                 cv_mem->cv_acorQS[is], cv_mem->cv_yQS[is]);
   }
 
   return(CV_SUCCESS);
@@ -6421,7 +6500,7 @@ static int cvStgrNls(CVodeMem cv_mem)
 {
   int flag=CV_SUCCESS;
 
-  switch(iter) {
+  switch(cv_mem->cv_iter) {
   case CV_FUNCTIONAL:
     flag = cvStgrNlsFunctional(cv_mem);
     break;
@@ -6454,65 +6533,76 @@ static int cvStgrNlsFunctional(CVodeMem cv_mem)
   N_Vector wrk1, wrk2;
 
   /* Initialize estimated conv. rate and counter */
-  crateS = ONE;
+  cv_mem->cv_crateS = ONE;
   m = 0;
 
   /* Initialize Delp to avoid compiler warning message */
   Delp = ZERO;
 
   /* Evaluate fS at predicted yS but with converged y (and corresponding f) */
-  wrk1 = tempv;
-  wrk2 = ftempS[0];
-  retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, znS[0], tempvS, wrk1, wrk2);
+  wrk1 = cv_mem->cv_tempv;
+  wrk2 = cv_mem->cv_ftempS[0];
+  retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                            cv_mem->cv_ftemp, cv_mem->cv_znS[0],
+                            cv_mem->cv_tempvS, wrk1, wrk2);
   if (retval < 0) return(CV_SRHSFUNC_FAIL);
   if (retval > 0) return(SRHSFUNC_RECVR);
 
   /* Initialize correction to zero */
-  for (is=0; is<Ns; is++)
-    N_VConst(ZERO,acorS[is]);
+  for (is=0; is<cv_mem->cv_Ns; is++)
+    N_VConst(ZERO, cv_mem->cv_acorS[is]);
 
   /* Loop until convergence; accumulate corrections in acorS */
 
-  loop {
+  for(;;) {
     
-    nniS++;
+    cv_mem->cv_nniS++;
     
     /* Correct yS from last fS value */
-    for (is=0; is<Ns; is++) {
-      N_VLinearSum(h, tempvS[is], -ONE, znS[1][is], tempvS[is]);
-      N_VScale(rl1, tempvS[is], tempvS[is]);
-      N_VLinearSum(ONE, znS[0][is], ONE, tempvS[is], yS[is]);
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VLinearSum(cv_mem->cv_h, cv_mem->cv_tempvS[is], -ONE,
+                   cv_mem->cv_znS[1][is], cv_mem->cv_tempvS[is]);
+      N_VScale(cv_mem->cv_rl1, cv_mem->cv_tempvS[is],
+               cv_mem->cv_tempvS[is]);
+      N_VLinearSum(ONE, cv_mem->cv_znS[0][is], ONE,
+                   cv_mem->cv_tempvS[is], cv_mem->cv_yS[is]);
     }
     /* Get norm of current correction to use in convergence test */
-    for (is=0; is<Ns; is++)
-      N_VLinearSum(ONE, tempvS[is], -ONE, acorS[is], acorS[is]);
-    Del = cvSensNorm(cv_mem, acorS, ewtS);
-    for (is=0; is<Ns; is++)
-      N_VScale(ONE, tempvS[is], acorS[is]);
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VLinearSum(ONE, cv_mem->cv_tempvS[is], -ONE,
+                   cv_mem->cv_acorS[is], cv_mem->cv_acorS[is]);
+    Del = cvSensNorm(cv_mem, cv_mem->cv_acorS, cv_mem->cv_ewtS);
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      N_VScale(ONE, cv_mem->cv_tempvS[is], cv_mem->cv_acorS[is]);
 
     /* Test for convergence.  If m > 0, an estimate of the convergence
        rate constant is stored in crateS, and used in the test. 
        acnrmS contains the norm of the corrections (yS_n-yS_n(0)) and
-       will be used in the error test (if errconS==TRUE)              */
-    if (m > 0) crateS = SUNMAX(CRDOWN * crateS, Del / Delp);
-    dcon = Del * SUNMIN(ONE, crateS) / tq[4];
+       will be used in the error test (if errconS==SUNTRUE)              */
+    if (m > 0)
+      cv_mem->cv_crateS = SUNMAX(CRDOWN * cv_mem->cv_crateS, Del / Delp);
+    dcon = Del * SUNMIN(ONE, cv_mem->cv_crateS) / cv_mem->cv_tq[4];
     
     if (dcon <= ONE) {
-      if (errconS)
-        acnrmS = (m==0)? Del : cvSensNorm(cv_mem, acorS, ewtS);
+      if (cv_mem->cv_errconS)
+        cv_mem->cv_acnrmS = (m==0)?
+          Del : cvSensNorm(cv_mem, cv_mem->cv_acorS, cv_mem->cv_ewtS);
       return(CV_SUCCESS);  /* Convergence achieved */
     }
 
     /* Stop at maxcor iterations or if iter. seems to be diverging */
     m++;
-    if ((m==maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) return(CONV_FAIL);
+    if ((m==cv_mem->cv_maxcorS) || ((m >= 2) && (Del > RDIV * Delp)))
+      return(CONV_FAIL);
 
     /* Save norm of correction, evaluate f, and loop again */
     Delp = Del;
 
-    wrk1 = tempv;
-    wrk2 = ftempS[0];
-    retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, yS, tempvS, wrk1, wrk2);
+    wrk1 = cv_mem->cv_tempv;
+    wrk2 = cv_mem->cv_ftempS[0];
+    retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                              cv_mem->cv_ftemp, cv_mem->cv_yS,
+                              cv_mem->cv_tempvS, wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) return(SRHSFUNC_RECVR);
 
@@ -6547,18 +6637,20 @@ static int cvStgrNlsNewton(CVodeMem cv_mem)
   int convfail, ier;
   N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2;
 
-  loop {
+  for(;;) {
 
     /* Set acorS to zero and load prediction into yS vector */
-    for (is=0; is<Ns; is++) {
-      N_VConst(ZERO, acorS[is]);
-      N_VScale(ONE, znS[0][is], yS[is]);
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VConst(ZERO, cv_mem->cv_acorS[is]);
+      N_VScale(ONE, cv_mem->cv_znS[0][is], cv_mem->cv_yS[is]);
     }
  
     /* Evaluate fS at predicted yS but with converged y (and corresponding f) */
-    wrk1 = tempv;
-    wrk2 = tempvS[0];
-    retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, yS, ftempS, wrk1, wrk2);
+    wrk1 = cv_mem->cv_tempv;
+    wrk2 = cv_mem->cv_tempvS[0];
+    retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                              cv_mem->cv_ftemp, cv_mem->cv_yS,
+                              cv_mem->cv_ftempS, wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) return(SRHSFUNC_RECVR);
 
@@ -6576,20 +6668,21 @@ static int cvStgrNlsNewton(CVodeMem cv_mem)
     convfail = CV_FAIL_BAD_J;
 
     /* Rename some vectors for readibility */
-    vtemp1 = tempv;
-    vtemp2 = yS[0];
-    vtemp3 = ftempS[0];
+    vtemp1 = cv_mem->cv_tempv;
+    vtemp2 = cv_mem->cv_yS[0];
+    vtemp3 = cv_mem->cv_ftempS[0];
 
     /* Call linear solver setup at converged y */
-    ier = lsetup(cv_mem, convfail, y, ftemp, &jcur, 
-                 vtemp1, vtemp2, vtemp3);
-    nsetups++;
-    nsetupsS++;
-    gamrat = ONE;
-    gammap = gamma;
-    crate = ONE;
-    crateS = ONE; /* after lsetup all conv. rates are reset to ONE */
-    nstlp = nst;
+    ier = cv_mem->cv_lsetup(cv_mem, convfail, cv_mem->cv_y,
+                            cv_mem->cv_ftemp, &(cv_mem->cv_jcur), 
+                            vtemp1, vtemp2, vtemp3);
+    cv_mem->cv_nsetups++;
+    cv_mem->cv_nsetupsS++;
+    cv_mem->cv_gamrat = ONE;
+    cv_mem->cv_gammap = cv_mem->cv_gamma;
+    cv_mem->cv_crate = ONE;
+    cv_mem->cv_crateS = ONE; /* after lsetup all conv. rates are reset to ONE */
+    cv_mem->cv_nstlp = cv_mem->cv_nst;
 
     /* Return if lsetup failed */
     if (ier < 0) return(CV_LSETUP_FAIL);
@@ -6629,47 +6722,56 @@ static int cvStgrNewtonIteration(CVodeMem cv_mem)
      acorS  <- 0
      yS     <- yS_n(0)                   */
 
-  loop {
+  for(;;) {
 
     /* Evaluate the residual of the nonlinear systems */
-    for (is=0; is<Ns; is++) {
-      N_VLinearSum(rl1, znS[1][is], ONE, acorS[is], tempvS[is]);
-      N_VLinearSum(gamma, ftempS[is], -ONE, tempvS[is], tempvS[is]);
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VLinearSum(cv_mem->cv_rl1, cv_mem->cv_znS[1][is], ONE,
+                   cv_mem->cv_acorS[is], cv_mem->cv_tempvS[is]);
+      N_VLinearSum(cv_mem->cv_gamma, cv_mem->cv_ftempS[is], -ONE,
+                   cv_mem->cv_tempvS[is], cv_mem->cv_tempvS[is]);
     }
 
     /* Call the lsolve function */
-    bS = tempvS;
-    nniS++;
-    for (is=0; is<Ns; is++) {
+    bS = cv_mem->cv_tempvS;
+    cv_mem->cv_nniS++;
+    for (is=0; is<cv_mem->cv_Ns; is++) {
 
-      retval = lsolve(cv_mem, bS[is], ewtS[is], y, ftemp);
+      retval = cv_mem->cv_lsolve(cv_mem, bS[is], cv_mem->cv_ewtS[is],
+                                 cv_mem->cv_y, cv_mem->cv_ftemp);
 
       /* Unrecoverable error in lsolve */
       if (retval < 0) return(CV_LSOLVE_FAIL);
 
       /* Recoverable error in lsolve and Jacobian data not current */
       if (retval > 0) { 
-        if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-        else                           return(CONV_FAIL);
+        if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+          return(TRY_AGAIN);
+        else
+          return(CONV_FAIL);
       }
 
     }
  
     /* Get norm of correction; add correction to acorS and yS */
-    Del = cvSensNorm(cv_mem, bS, ewtS);
-    for (is=0; is<Ns; is++) {
-      N_VLinearSum(ONE, acorS[is], ONE, bS[is], acorS[is]);
-      N_VLinearSum(ONE, znS[0][is], ONE, acorS[is], yS[is]);
+    Del = cvSensNorm(cv_mem, bS, cv_mem->cv_ewtS);
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      N_VLinearSum(ONE, cv_mem->cv_acorS[is], ONE,
+                   bS[is], cv_mem->cv_acorS[is]);
+      N_VLinearSum(ONE, cv_mem->cv_znS[0][is], ONE,
+                   cv_mem->cv_acorS[is], cv_mem->cv_yS[is]);
     }
 
     /* Test for convergence.  If m > 0, an estimate of the convergence
        rate constant is stored in crateS, and used in the test.        */
-    if (m > 0) crateS = SUNMAX(CRDOWN * crateS, Del/Delp);
-    dcon = Del * SUNMIN(ONE, crateS) / tq[4];
+    if (m > 0)
+      cv_mem->cv_crateS = SUNMAX(CRDOWN * cv_mem->cv_crateS, Del/Delp);
+    dcon = Del * SUNMIN(ONE, cv_mem->cv_crateS) / cv_mem->cv_tq[4];
     if (dcon <= ONE) {
-      if (errconS)
-        acnrmS = (m==0) ? Del : cvSensNorm(cv_mem, acorS, ewtS);
-      jcur = FALSE;
+      if (cv_mem->cv_errconS)
+        cv_mem->cv_acnrmS = (m==0) ?
+          Del : cvSensNorm(cv_mem, cv_mem->cv_acorS, cv_mem->cv_ewtS);
+      cv_mem->cv_jcur = SUNFALSE;
       return(CV_SUCCESS);  /* Convergence achieved */
     }
 
@@ -6678,21 +6780,27 @@ static int cvStgrNewtonIteration(CVodeMem cv_mem)
     /* Stop at maxcor iterations or if iter. seems to be diverging.
        If still not converged and Jacobian data is not current, 
        signal to try the solution again                            */
-    if ((m == maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(CONV_FAIL);
+    if ((m == cv_mem->cv_maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) {
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(CONV_FAIL);
     }
     
     /* Save norm of correction, evaluate fS, and loop again */
     Delp = Del;
     
-    wrk1 = tempv;
-    wrk2 = tempvS[0];
-    retval = cvSensRhsWrapper(cv_mem, tn, y, ftemp, yS, ftempS, wrk1, wrk2);
+    wrk1 = cv_mem->cv_tempv;
+    wrk2 = cv_mem->cv_tempvS[0];
+    retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                              cv_mem->cv_ftemp, cv_mem->cv_yS,
+                              cv_mem->cv_ftempS, wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(SRHSFUNC_RECVR);
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(SRHSFUNC_RECVR);
     }
 
   } /* end loop */
@@ -6712,7 +6820,7 @@ static int cvStgr1Nls(CVodeMem cv_mem, int is)
 {
   int flag=CV_SUCCESS;
 
-  switch(iter) {
+  switch(cv_mem->cv_iter) {
   case CV_FUNCTIONAL:
     flag = cvStgr1NlsFunctional(cv_mem,is);
     break;
@@ -6744,43 +6852,49 @@ static int cvStgr1NlsFunctional(CVodeMem cv_mem, int is)
   N_Vector wrk1, wrk2;
 
   /* Initialize estimated conv. rate and counter */
-  crateS = ONE;
+  cv_mem->cv_crateS = ONE;
   m = 0;
 
   /* Initialize Delp to avoid compiler warning message */
   Delp = ZERO;
 
   /* Evaluate fS at predicted yS but with converged y (and corresponding f) */
-  wrk1 = tempv;
-  wrk2 = ftempS[0];
-  retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, znS[0][is], tempvS[is], wrk1, wrk2);
+  wrk1 = cv_mem->cv_tempv;
+  wrk2 = cv_mem->cv_ftempS[0];
+  retval = cvSensRhs1Wrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                             cv_mem->cv_ftemp, is, cv_mem->cv_znS[0][is],
+                             cv_mem->cv_tempvS[is], wrk1, wrk2);
   if (retval < 0) return(CV_SRHSFUNC_FAIL);
   if (retval > 0) return(SRHSFUNC_RECVR);
 
   /* Initialize correction to zero */
-  N_VConst(ZERO,acorS[is]);
+  N_VConst(ZERO, cv_mem->cv_acorS[is]);
 
   /* Loop until convergence; accumulate corrections in acorS */
 
-  loop {
+  for(;;) {
 
-    nniS1[is]++;
+    cv_mem->cv_nniS1[is]++;
 
     /* Correct yS from last fS value */
-    N_VLinearSum(h, tempvS[is], -ONE, znS[1][is], tempvS[is]);
-    N_VScale(rl1, tempvS[is], tempvS[is]);
-    N_VLinearSum(ONE, znS[0][is], ONE, tempvS[is], yS[is]);
+    N_VLinearSum(cv_mem->cv_h, cv_mem->cv_tempvS[is], -ONE,
+                 cv_mem->cv_znS[1][is], cv_mem->cv_tempvS[is]);
+    N_VScale(cv_mem->cv_rl1, cv_mem->cv_tempvS[is], cv_mem->cv_tempvS[is]);
+    N_VLinearSum(ONE, cv_mem->cv_znS[0][is], ONE,
+                 cv_mem->cv_tempvS[is], cv_mem->cv_yS[is]);
 
     /* Get WRMS norm of current correction to use in convergence test */
-    N_VLinearSum(ONE, tempvS[is], -ONE, acorS[is], acorS[is]);
-    Del = N_VWrmsNorm(acorS[is], ewtS[is]);
-    N_VScale(ONE, tempvS[is], acorS[is]);
+    N_VLinearSum(ONE, cv_mem->cv_tempvS[is], -ONE,
+                 cv_mem->cv_acorS[is], cv_mem->cv_acorS[is]);
+    Del = N_VWrmsNorm(cv_mem->cv_acorS[is], cv_mem->cv_ewtS[is]);
+    N_VScale(ONE, cv_mem->cv_tempvS[is], cv_mem->cv_acorS[is]);
 
     /* Test for convergence.  If m > 0, an estimate of the convergence
        rate constant is stored in crateS, and used in the test. */
 
-    if (m > 0) crateS = SUNMAX(CRDOWN * crateS, Del / Delp);
-    dcon = Del * SUNMIN(ONE, crateS) / tq[4];
+    if (m > 0)
+      cv_mem->cv_crateS = SUNMAX(CRDOWN * cv_mem->cv_crateS, Del / Delp);
+    dcon = Del * SUNMIN(ONE, cv_mem->cv_crateS) / cv_mem->cv_tq[4];
 
     if (dcon <= ONE) {
       return(CV_SUCCESS);  /* Convergence achieved */
@@ -6788,15 +6902,18 @@ static int cvStgr1NlsFunctional(CVodeMem cv_mem, int is)
 
     /* Stop at maxcor iterations or if iter. seems to be diverging */
     m++;
-    if ((m==maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) return(CONV_FAIL);
+    if ((m==cv_mem->cv_maxcorS) || ((m >= 2) && (Del > RDIV * Delp)))
+      return(CONV_FAIL);
 
     /* Save norm of correction, evaluate f, and loop again */
     Delp = Del;
 
-    wrk1 = tempv;
-    wrk2 = ftempS[0];
+    wrk1 = cv_mem->cv_tempv;
+    wrk2 = cv_mem->cv_ftempS[0];
 
-    retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, yS[is], tempvS[is], wrk1, wrk2);
+    retval = cvSensRhs1Wrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                               cv_mem->cv_ftemp, is, cv_mem->cv_yS[is], 
+                               cv_mem->cv_tempvS[is], wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) return(SRHSFUNC_RECVR);
 
@@ -6830,17 +6947,19 @@ static int cvStgr1NlsNewton(CVodeMem cv_mem, int is)
 {
   int convfail, retval, ier;
   N_Vector vtemp1, vtemp2, vtemp3, wrk1, wrk2;
-
-  loop {
+  
+  for(;;) {
 
     /* Set acorS to zero and load prediction into yS vector */
-    N_VConst(ZERO, acorS[is]);
-    N_VScale(ONE, znS[0][is], yS[is]);
+    N_VConst(ZERO, cv_mem->cv_acorS[is]);
+    N_VScale(ONE, cv_mem->cv_znS[0][is], cv_mem->cv_yS[is]);
  
     /* Evaluate fS at predicted yS but with converged y (and corresponding f) */
-    wrk1 = tempv;
-    wrk2 = tempvS[0];
-    retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, yS[is], ftempS[is], wrk1, wrk2);
+    wrk1 = cv_mem->cv_tempv;
+    wrk2 = cv_mem->cv_tempvS[0];
+    retval = cvSensRhs1Wrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                               cv_mem->cv_ftemp, is, cv_mem->cv_yS[is],
+                               cv_mem->cv_ftempS[is], wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) return(SRHSFUNC_RECVR);
   
@@ -6858,20 +6977,21 @@ static int cvStgr1NlsNewton(CVodeMem cv_mem, int is)
     convfail = CV_FAIL_BAD_J;
 
     /* Rename some vectors for readibility */
-    vtemp1 = tempv;
-    vtemp2 = yS[0];
-    vtemp3 = ftempS[0];
+    vtemp1 = cv_mem->cv_tempv;
+    vtemp2 = cv_mem->cv_yS[0];
+    vtemp3 = cv_mem->cv_ftempS[0];
 
     /* Call linear solver setup at converged y */
-    ier = lsetup(cv_mem, convfail, y, ftemp, &jcur, 
-                 vtemp1, vtemp2, vtemp3);
-    nsetups++;
-    nsetupsS++;
-    gamrat = ONE;
-    crate = ONE;
-    crateS = ONE; /* after lsetup all conv. rates are reset to ONE */
-    gammap = gamma;
-    nstlp = nst;
+    ier = cv_mem->cv_lsetup(cv_mem, convfail, cv_mem->cv_y,
+                            cv_mem->cv_ftemp, &(cv_mem->cv_jcur), 
+                            vtemp1, vtemp2, vtemp3);
+    cv_mem->cv_nsetups++;
+    cv_mem->cv_nsetupsS++;
+    cv_mem->cv_gamrat = ONE;
+    cv_mem->cv_crate = ONE;
+    cv_mem->cv_crateS = ONE; /* after lsetup all conv. rates are reset to ONE */
+    cv_mem->cv_gammap = cv_mem->cv_gamma;
+    cv_mem->cv_nstlp = cv_mem->cv_nst;
 
     /* Return if lsetup failed */
     if (ier < 0) return(CV_LSETUP_FAIL);
@@ -6911,39 +7031,47 @@ static int cvStgr1NewtonIteration(CVodeMem cv_mem, int is)
      acorS[is]  <- 0
      yS[is]     <- yS_n(0)[is]                 */
 
-  loop {
+  for(;;) {
 
     /* Evaluate the residual of the nonlinear systems */
-    N_VLinearSum(rl1, znS[1][is], ONE, acorS[is], tempvS[is]);
-    N_VLinearSum(gamma, ftempS[is], -ONE, tempvS[is], tempvS[is]);
+    N_VLinearSum(cv_mem->cv_rl1, cv_mem->cv_znS[1][is], ONE,
+                 cv_mem->cv_acorS[is], cv_mem->cv_tempvS[is]);
+    N_VLinearSum(cv_mem->cv_gamma, cv_mem->cv_ftempS[is], -ONE,
+                 cv_mem->cv_tempvS[is], cv_mem->cv_tempvS[is]);
 
     /* Call the lsolve function */
-    bS = tempvS;
+    bS = cv_mem->cv_tempvS;
 
-    nniS1[is]++;
+    cv_mem->cv_nniS1[is]++;
 
-    retval = lsolve(cv_mem, bS[is], ewtS[is], y, ftemp);
+    retval = cv_mem->cv_lsolve(cv_mem, bS[is], cv_mem->cv_ewtS[is],
+                               cv_mem->cv_y, cv_mem->cv_ftemp);
 
     /* Unrecoverable error in lsolve */
     if (retval < 0) return(CV_LSOLVE_FAIL);
 
     /* Recoverable error in lsolve and Jacobian data not current */
     if (retval > 0) { 
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(CONV_FAIL);
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(CONV_FAIL);
     }
 
     /* Get norm of correction; add correction to acorS and yS */
-    Del = N_VWrmsNorm(bS[is], ewtS[is]);
-    N_VLinearSum(ONE, acorS[is], ONE, bS[is], acorS[is]);
-    N_VLinearSum(ONE, znS[0][is], ONE, acorS[is], yS[is]);
+    Del = N_VWrmsNorm(bS[is], cv_mem->cv_ewtS[is]);
+    N_VLinearSum(ONE, cv_mem->cv_acorS[is], ONE,
+                 bS[is], cv_mem->cv_acorS[is]);
+    N_VLinearSum(ONE, cv_mem->cv_znS[0][is], ONE,
+                 cv_mem->cv_acorS[is], cv_mem->cv_yS[is]);
 
     /* Test for convergence.  If m > 0, an estimate of the convergence
        rate constant is stored in crateS, and used in the test.        */
-    if (m > 0) crateS = SUNMAX(CRDOWN * crateS, Del/Delp);
-    dcon = Del * SUNMIN(ONE, crateS) / tq[4];
+    if (m > 0)
+      cv_mem->cv_crateS = SUNMAX(CRDOWN * cv_mem->cv_crateS, Del/Delp);
+    dcon = Del * SUNMIN(ONE, cv_mem->cv_crateS) / cv_mem->cv_tq[4];
     if (dcon <= ONE) {
-      jcur = FALSE;
+      cv_mem->cv_jcur = SUNFALSE;
       return(CV_SUCCESS);  /* Convergence achieved */
     }
 
@@ -6952,21 +7080,27 @@ static int cvStgr1NewtonIteration(CVodeMem cv_mem, int is)
     /* Stop at maxcor iterations or if iter. seems to be diverging.
        If still not converged and Jacobian data is not current, 
        signal to try the solution again                            */
-    if ((m == maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(CONV_FAIL);
+    if ((m == cv_mem->cv_maxcorS) || ((m >= 2) && (Del > RDIV * Delp))) {
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(CONV_FAIL);
     }
 
     /* Save norm of correction, evaluate fS, and loop again */
     Delp = Del;
 
-    wrk1 = tempv;
-    wrk2 = tempvS[0];
-    retval = cvSensRhs1Wrapper(cv_mem, tn, y, ftemp, is, yS[is], ftempS[is], wrk1, wrk2);
+    wrk1 = cv_mem->cv_tempv;
+    wrk2 = cv_mem->cv_tempvS[0];
+    retval = cvSensRhs1Wrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_y,
+                               cv_mem->cv_ftemp, is, cv_mem->cv_yS[is], 
+                               cv_mem->cv_ftempS[is], wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) {
-      if ((!jcur) && (setupNonNull)) return(TRY_AGAIN);
-      else                           return(SRHSFUNC_RECVR);
+      if ((!cv_mem->cv_jcur) && (cv_mem->cv_lsetup))
+        return(TRY_AGAIN);
+      else
+        return(SRHSFUNC_RECVR);
     }
 
   } /* end loop */
@@ -7038,13 +7172,14 @@ static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
      increment ncf */
   
   (*ncfPtr)++;
-  etamax = ONE;
+  cv_mem->cv_etamax = ONE;
 
   /* If we had maxncf failures or |h| = hmin, 
      return CV_CONV_FAILURE, CV_REPTD_RHSFUNC_ERR, 
      CV_REPTD_QRHSFUNC_ERR, or CV_REPTD_SRHSFUNC_ERR */
 
-  if ((SUNRabs(h) <= hmin*ONEPSM) || (*ncfPtr == maxncf)) {
+  if ((SUNRabs(cv_mem->cv_h) <= cv_mem->cv_hmin*ONEPSM) ||
+      (*ncfPtr == cv_mem->cv_maxncf)) {
     if (nflag == CONV_FAIL)       return(CV_CONV_FAILURE);
     if (nflag == RHSFUNC_RECVR)   return(CV_REPTD_RHSFUNC_ERR);    
     if (nflag == QRHSFUNC_RECVR)  return(CV_REPTD_QRHSFUNC_ERR);    
@@ -7054,7 +7189,7 @@ static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
 
   /* Reduce step size; return to reattempt the step */
 
-  eta = SUNMAX(ETACF, hmin / SUNRabs(h));
+  cv_mem->cv_eta = SUNMAX(ETACF, cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h));
   *nflagPtr = PREV_CONV_FAIL;
   cvRescale(cv_mem);
 
@@ -7064,7 +7199,7 @@ static int cvHandleNFlag(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
 /*
  * cvRestore
  *
- * This routine restores the value of tn to saved_t and undoes the
+ * This routine restores the value of cv_mem->cv_tn to saved_t and undoes the
  * prediction.  After execution of cvRestore, the Nordsieck array zn has
  * the same values as before the call to cvPredict.
  */
@@ -7074,30 +7209,34 @@ static void cvRestore(CVodeMem cv_mem, realtype saved_t)
   int j, k;
   int is;
 
-  tn = saved_t;
-  for (k = 1; k <= q; k++)
-    for (j = q; j >= k; j--)
-      N_VLinearSum(ONE, zn[j-1], -ONE, zn[j], zn[j-1]);
+  cv_mem->cv_tn = saved_t;
+  for (k = 1; k <= cv_mem->cv_q; k++)
+    for (j = cv_mem->cv_q; j >= k; j--)
+      N_VLinearSum(ONE, cv_mem->cv_zn[j-1], -ONE,
+                   cv_mem->cv_zn[j], cv_mem->cv_zn[j-1]);
 
-  if (quadr) {
-    for (k = 1; k <= q; k++)
-      for (j = q; j >= k; j--)
-        N_VLinearSum(ONE, znQ[j-1], -ONE, znQ[j], znQ[j-1]);
+  if (cv_mem->cv_quadr) {
+    for (k = 1; k <= cv_mem->cv_q; k++)
+      for (j = cv_mem->cv_q; j >= k; j--)
+        N_VLinearSum(ONE, cv_mem->cv_znQ[j-1], -ONE,
+                     cv_mem->cv_znQ[j], cv_mem->cv_znQ[j-1]);
   }
 
-  if (sensi) {
-    for (is=0; is<Ns; is++) {
-      for (k = 1; k <= q; k++)
-        for (j = q; j >= k; j--)
-          N_VLinearSum(ONE, znS[j-1][is], -ONE, znS[j][is], znS[j-1][is]);
+  if (cv_mem->cv_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      for (k = 1; k <= cv_mem->cv_q; k++)
+        for (j = cv_mem->cv_q; j >= k; j--)
+          N_VLinearSum(ONE, cv_mem->cv_znS[j-1][is], -ONE,
+                       cv_mem->cv_znS[j][is], cv_mem->cv_znS[j-1][is]);
     }
   }
 
-  if (quadr_sensi) {
-    for (is=0; is<Ns; is++) {
-      for (k = 1; k <= q; k++)
-        for (j = q; j >= k; j--)
-          N_VLinearSum(ONE, znQS[j-1][is], -ONE, znQS[j][is], znQS[j-1][is]);
+  if (cv_mem->cv_quadr_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      for (k = 1; k <= cv_mem->cv_q; k++)
+        for (j = cv_mem->cv_q; j >= k; j--)
+          N_VLinearSum(ONE, cv_mem->cv_znQS[j-1][is], -ONE,
+                       cv_mem->cv_znQS[j][is], cv_mem->cv_znQS[j-1][is]);
     }
   }
 }
@@ -7145,7 +7284,7 @@ static int cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
   int retval, is;
   N_Vector wrk1, wrk2;
 
-  dsm = acor_nrm * tq[2];
+  dsm = acor_nrm * cv_mem->cv_tq[2];
 
   /* If est. local error norm dsm passes test, return CV_SUCCESS */  
   *dsmPtr = dsm; 
@@ -7158,83 +7297,94 @@ static int cvDoErrorTest(CVodeMem cv_mem, int *nflagPtr, realtype saved_t,
   cvRestore(cv_mem, saved_t);
 
   /* At maxnef failures or |h| = hmin, return CV_ERR_FAILURE */
-  if ((SUNRabs(h) <= hmin*ONEPSM) || (*nefPtr == maxnef)) return(CV_ERR_FAILURE);
+  if ((SUNRabs(cv_mem->cv_h) <= cv_mem->cv_hmin*ONEPSM) ||
+      (*nefPtr == cv_mem->cv_maxnef))
+    return(CV_ERR_FAILURE);
 
   /* Set etamax = 1 to prevent step size increase at end of this step */
-  etamax = ONE;
+  cv_mem->cv_etamax = ONE;
 
   /* Set h ratio eta from dsm, rescale, and return for retry of step */
   if (*nefPtr <= MXNEF1) {
-    eta = ONE / (SUNRpowerR(BIAS2*dsm,ONE/L) + ADDON);
-    eta = SUNMAX(ETAMIN, SUNMAX(eta, hmin / SUNRabs(h)));
-    if (*nefPtr >= SMALL_NEF) eta = SUNMIN(eta, ETAMXF);
+    cv_mem->cv_eta = ONE / (SUNRpowerR(BIAS2*dsm,ONE/cv_mem->cv_L) + ADDON);
+    cv_mem->cv_eta = SUNMAX(ETAMIN, SUNMAX(cv_mem->cv_eta,
+                                           cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h)));
+    if (*nefPtr >= SMALL_NEF)
+      cv_mem->cv_eta = SUNMIN(cv_mem->cv_eta, ETAMXF);
     cvRescale(cv_mem);
     return(TRY_AGAIN);
   }
   
   /* After MXNEF1 failures, force an order reduction and retry step */
-  if (q > 1) {
-    eta = SUNMAX(ETAMIN, hmin / SUNRabs(h));
+  if (cv_mem->cv_q > 1) {
+    cv_mem->cv_eta = SUNMAX(ETAMIN, cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h));
     cvAdjustOrder(cv_mem,-1);
-    L = q;
-    q--;
-    qwait = L;
+    cv_mem->cv_L = cv_mem->cv_q;
+    cv_mem->cv_q--;
+    cv_mem->cv_qwait = cv_mem->cv_L;
     cvRescale(cv_mem);
     return(TRY_AGAIN);
   }
 
   /* If already at order 1, restart: reload zn, znQ, znS, znQS from scratch */
-  eta = SUNMAX(ETAMIN, hmin / SUNRabs(h));
-  h *= eta;
-  next_h = h;
-  hscale = h;
-  qwait = LONG_WAIT;
-  nscon = 0;
-
-  retval = f(tn, zn[0], tempv, user_data);
-  nfe++;
+  cv_mem->cv_eta = SUNMAX(ETAMIN, cv_mem->cv_hmin / SUNRabs(cv_mem->cv_h));
+  cv_mem->cv_h *= cv_mem->cv_eta;
+  cv_mem->cv_next_h = cv_mem->cv_h;
+  cv_mem->cv_hscale = cv_mem->cv_h;
+  cv_mem->cv_qwait = LONG_WAIT;
+  cv_mem->cv_nscon = 0;
+
+  retval = cv_mem->cv_f(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                        cv_mem->cv_tempv, cv_mem->cv_user_data);
+  cv_mem->cv_nfe++;
   if (retval < 0) return(CV_RHSFUNC_FAIL);
   if (retval > 0) return(CV_UNREC_RHSFUNC_ERR);
 
-  N_VScale(h, tempv, zn[1]);
+  N_VScale(cv_mem->cv_h, cv_mem->cv_tempv, cv_mem->cv_zn[1]);
 
-  if (quadr) {
+  if (cv_mem->cv_quadr) {
 
-    retval = fQ(tn, zn[0], tempvQ, user_data);
-    nfQe++;
+    retval = cv_mem->cv_fQ(cv_mem->cv_tn, cv_mem->cv_zn[0],
+                           cv_mem->cv_tempvQ, cv_mem->cv_user_data);
+    cv_mem->cv_nfQe++;
     if (retval < 0) return(CV_QRHSFUNC_FAIL);
     if (retval > 0) return(CV_UNREC_QRHSFUNC_ERR);
 
-    N_VScale(h, tempvQ, znQ[1]);
+    N_VScale(cv_mem->cv_h, cv_mem->cv_tempvQ, cv_mem->cv_znQ[1]);
 
   }
 
-  if (sensi) {
+  if (cv_mem->cv_sensi) {
 
-    wrk1 = ftemp;
-    wrk2 = ftempS[0];
+    wrk1 = cv_mem->cv_ftemp;
+    wrk2 = cv_mem->cv_ftempS[0];
 
-    retval = cvSensRhsWrapper(cv_mem, tn, zn[0], tempv, znS[0], tempvS, wrk1, wrk2);
+    retval = cvSensRhsWrapper(cv_mem, cv_mem->cv_tn, cv_mem->cv_zn[0], 
+                              cv_mem->cv_tempv, cv_mem->cv_znS[0],
+                              cv_mem->cv_tempvS, wrk1, wrk2);
     if (retval < 0) return(CV_SRHSFUNC_FAIL);
     if (retval > 0) return(CV_UNREC_SRHSFUNC_ERR);
 
-    for (is=0; is<Ns; is++) 
-      N_VScale(h, tempvS[is], znS[1][is]);
+    for (is=0; is<cv_mem->cv_Ns; is++) 
+      N_VScale(cv_mem->cv_h, cv_mem->cv_tempvS[is], cv_mem->cv_znS[1][is]);
 
   }
 
-  if (quadr_sensi) {
+  if (cv_mem->cv_quadr_sensi) {
 
-    wrk1 = ftemp;
-    wrk2 = ftempQ;
+    wrk1 = cv_mem->cv_ftemp;
+    wrk2 = cv_mem->cv_ftempQ;
 
-    retval = fQS(Ns, tn, zn[0], znS[0], tempvQ, tempvQS, fQS_data, wrk1, wrk2);
-    nfQSe++;
+    retval = cv_mem->cv_fQS(cv_mem->cv_Ns, cv_mem->cv_tn,
+                            cv_mem->cv_zn[0], cv_mem->cv_znS[0], 
+                            cv_mem->cv_tempvQ, cv_mem->cv_tempvQS,
+                            cv_mem->cv_fQS_data, wrk1, wrk2);
+    cv_mem->cv_nfQSe++;
     if (retval < 0) return(CV_QSRHSFUNC_FAIL);
     if (retval > 0) return(CV_UNREC_QSRHSFUNC_ERR);
 
-    for (is=0; is<Ns; is++) 
-      N_VScale(h, tempvQS[is], znQS[1][is]);
+    for (is=0; is<cv_mem->cv_Ns; is++) 
+      N_VScale(cv_mem->cv_h, cv_mem->cv_tempvQS[is], cv_mem->cv_znQS[1][is]);
 
   }
 
@@ -7265,34 +7415,40 @@ static void cvCompleteStep(CVodeMem cv_mem)
   int i, j;
   int is;
   
-  nst++;
-  nscon++;
-  hu = h;
-  qu = q;
+  cv_mem->cv_nst++;
+  cv_mem->cv_nscon++;
+  cv_mem->cv_hu = cv_mem->cv_h;
+  cv_mem->cv_qu = cv_mem->cv_q;
 
-  for (i=q; i >= 2; i--)  tau[i] = tau[i-1];
-  if ((q==1) && (nst > 1)) tau[2] = tau[1];
-  tau[1] = h;
+  for (i=cv_mem->cv_q; i >= 2; i--)
+    cv_mem->cv_tau[i] = cv_mem->cv_tau[i-1];
+  if ((cv_mem->cv_q==1) && (cv_mem->cv_nst > 1))
+    cv_mem->cv_tau[2] = cv_mem->cv_tau[1];
+  cv_mem->cv_tau[1] = cv_mem->cv_h;
 
   /* Apply correction to column j of zn: l_j * Delta_n */
-  for (j=0; j <= q; j++) 
-    N_VLinearSum(l[j], acor, ONE, zn[j], zn[j]);
+  for (j=0; j <= cv_mem->cv_q; j++) 
+    N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_acor, ONE,
+                 cv_mem->cv_zn[j], cv_mem->cv_zn[j]);
 
-  if (quadr) {
-    for (j=0; j <= q; j++) 
-      N_VLinearSum(l[j], acorQ, ONE, znQ[j], znQ[j]);
+  if (cv_mem->cv_quadr) {
+    for (j=0; j <= cv_mem->cv_q; j++) 
+      N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_acorQ, ONE,
+                   cv_mem->cv_znQ[j], cv_mem->cv_znQ[j]);
   }
 
-  if (sensi) {
-    for (is=0; is<Ns; is++)
-      for (j=0; j <= q; j++) 
-        N_VLinearSum(l[j], acorS[is], ONE, znS[j][is], znS[j][is]);
+  if (cv_mem->cv_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      for (j=0; j <= cv_mem->cv_q; j++) 
+        N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_acorS[is], ONE,
+                     cv_mem->cv_znS[j][is], cv_mem->cv_znS[j][is]);
   }
 
-  if (quadr_sensi) {
-    for (is=0; is<Ns; is++)
-      for (j=0; j <= q; j++) 
-        N_VLinearSum(l[j], acorQS[is], ONE, znQS[j][is], znQS[j][is]);
+  if (cv_mem->cv_quadr_sensi) {
+    for (is=0; is<cv_mem->cv_Ns; is++)
+      for (j=0; j <= cv_mem->cv_q; j++) 
+        N_VLinearSum(cv_mem->cv_l[j], cv_mem->cv_acorQS[is], ONE,
+                     cv_mem->cv_znQS[j][is], cv_mem->cv_znQS[j][is]);
   }
 
 
@@ -7301,24 +7457,24 @@ static void cvCompleteStep(CVodeMem cv_mem)
    * the next to last step of order q before a possible one at order q+1
    */
 
-  qwait--;
-  if ((qwait == 1) && (q != qmax)) {
+  cv_mem->cv_qwait--;
+  if ((cv_mem->cv_qwait == 1) && (cv_mem->cv_q != cv_mem->cv_qmax)) {
     
-    N_VScale(ONE, acor, zn[qmax]);
+    N_VScale(ONE, cv_mem->cv_acor, cv_mem->cv_zn[cv_mem->cv_qmax]);
     
-    if (quadr)
-      N_VScale(ONE, acorQ, znQ[qmax]);
+    if (cv_mem->cv_quadr)
+      N_VScale(ONE, cv_mem->cv_acorQ, cv_mem->cv_znQ[cv_mem->cv_qmax]);
 
-    if (sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(ONE, acorS[is], znS[qmax][is]);
+    if (cv_mem->cv_sensi)
+      for (is=0; is<cv_mem->cv_Ns; is++)
+        N_VScale(ONE, cv_mem->cv_acorS[is], cv_mem->cv_znS[cv_mem->cv_qmax][is]);
     
-    if (quadr_sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(ONE, acorQS[is], znQS[qmax][is]);
+    if (cv_mem->cv_quadr_sensi)
+      for (is=0; is<cv_mem->cv_Ns; is++)
+        N_VScale(ONE, cv_mem->cv_acorQS[is], cv_mem->cv_znQS[cv_mem->cv_qmax][is]);
 
-    saved_tq5 = tq[5];
-    indx_acor = qmax;
+    cv_mem->cv_saved_tq5 = cv_mem->cv_tq[5];
+    cv_mem->cv_indx_acor = cv_mem->cv_qmax;
   }
 
 }
@@ -7335,21 +7491,21 @@ static void cvCompleteStep(CVodeMem cv_mem)
 static void cvPrepareNextStep(CVodeMem cv_mem, realtype dsm)
 {
   /* If etamax = 1, defer step size or order changes */
-  if (etamax == ONE) {
-    qwait = SUNMAX(qwait, 2);
-    qprime = q;
-    hprime = h;
-    eta = ONE;
+  if (cv_mem->cv_etamax == ONE) {
+    cv_mem->cv_qwait = SUNMAX(cv_mem->cv_qwait, 2);
+    cv_mem->cv_qprime = cv_mem->cv_q;
+    cv_mem->cv_hprime = cv_mem->cv_h;
+    cv_mem->cv_eta = ONE;
     return;
   }
 
   /* etaq is the ratio of new to old h at the current order */  
-  etaq = ONE /(SUNRpowerR(BIAS2*dsm,ONE/L) + ADDON);
+  cv_mem->cv_etaq = ONE /(SUNRpowerR(BIAS2*dsm,ONE/cv_mem->cv_L) + ADDON);
   
   /* If no order change, adjust eta and acor in cvSetEta and return */
-  if (qwait != 0) {
-    eta = etaq;
-    qprime = q;
+  if (cv_mem->cv_qwait != 0) {
+    cv_mem->cv_eta = cv_mem->cv_etaq;
+    cv_mem->cv_qprime = cv_mem->cv_q;
     cvSetEta(cv_mem);
     return;
   }
@@ -7357,9 +7513,9 @@ static void cvPrepareNextStep(CVodeMem cv_mem, realtype dsm)
   /* If qwait = 0, consider an order change.   etaqm1 and etaqp1 are 
      the ratios of new to old h at orders q-1 and q+1, respectively.
      cvChooseEta selects the largest; cvSetEta adjusts eta and acor */
-  qwait = 2;
-  etaqm1 = cvComputeEtaqm1(cv_mem);
-  etaqp1 = cvComputeEtaqp1(cv_mem);  
+  cv_mem->cv_qwait = 2;
+  cv_mem->cv_etaqm1 = cvComputeEtaqm1(cv_mem);
+  cv_mem->cv_etaqp1 = cvComputeEtaqp1(cv_mem);  
   cvChooseEta(cv_mem); 
   cvSetEta(cv_mem);
 }
@@ -7375,15 +7531,16 @@ static void cvSetEta(CVodeMem cv_mem)
 {
 
   /* If eta below the threshhold THRESH, reject a change of step size */
-  if (eta < THRESH) {
-    eta = ONE;
-    hprime = h;
+  if (cv_mem->cv_eta < THRESH) {
+    cv_mem->cv_eta = ONE;
+    cv_mem->cv_hprime = cv_mem->cv_h;
   } else {
     /* Limit eta by etamax and hmax, then set hprime */
-    eta = SUNMIN(eta, etamax);
-    eta /= SUNMAX(ONE, SUNRabs(h)*hmax_inv*eta);
-    hprime = h * eta;
-    if (qprime < q) nscon = 0;
+    cv_mem->cv_eta = SUNMIN(cv_mem->cv_eta, cv_mem->cv_etamax);
+    cv_mem->cv_eta /= SUNMAX(ONE, SUNRabs(cv_mem->cv_h) *
+                             cv_mem->cv_hmax_inv*cv_mem->cv_eta);
+    cv_mem->cv_hprime = cv_mem->cv_h * cv_mem->cv_eta;
+    if (cv_mem->cv_qprime < cv_mem->cv_q) cv_mem->cv_nscon = 0;
   }
 }
 
@@ -7398,26 +7555,29 @@ static realtype cvComputeEtaqm1(CVodeMem cv_mem)
 {
   realtype ddn;
   
-  etaqm1 = ZERO;
+  cv_mem->cv_etaqm1 = ZERO;
 
-  if (q > 1) {
+  if (cv_mem->cv_q > 1) {
 
-    ddn = N_VWrmsNorm(zn[q], ewt);
+    ddn = N_VWrmsNorm(cv_mem->cv_zn[cv_mem->cv_q], cv_mem->cv_ewt);
 
-    if ( quadr && errconQ )
-      ddn = cvQuadUpdateNorm(cv_mem, ddn, znQ[q], ewtQ);
+    if ( cv_mem->cv_quadr && cv_mem->cv_errconQ )
+      ddn = cvQuadUpdateNorm(cv_mem, ddn, cv_mem->cv_znQ[cv_mem->cv_q],
+                             cv_mem->cv_ewtQ);
 
-    if ( sensi && errconS )
-      ddn = cvSensUpdateNorm(cv_mem, ddn, znS[q], ewtS);
+    if ( cv_mem->cv_sensi && cv_mem->cv_errconS )
+      ddn = cvSensUpdateNorm(cv_mem, ddn, cv_mem->cv_znS[cv_mem->cv_q],
+                             cv_mem->cv_ewtS);
 
-    if ( quadr_sensi && errconQS )
-      ddn = cvQuadSensUpdateNorm(cv_mem, ddn, znQS[q], ewtQS);
+    if ( cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS )
+      ddn = cvQuadSensUpdateNorm(cv_mem, ddn, cv_mem->cv_znQS[cv_mem->cv_q],
+                                 cv_mem->cv_ewtQS);
 
-    ddn = ddn * tq[1];
-    etaqm1 = ONE/(SUNRpowerR(BIAS1*ddn, ONE/q) + ADDON);
+    ddn = ddn * cv_mem->cv_tq[1];
+    cv_mem->cv_etaqm1 = ONE/(SUNRpowerR(BIAS1*ddn, ONE/cv_mem->cv_q) + ADDON);
   }
 
-  return(etaqm1);
+  return(cv_mem->cv_etaqm1);
 }
 
 /*
@@ -7432,38 +7592,43 @@ static realtype cvComputeEtaqp1(CVodeMem cv_mem)
   realtype dup, cquot;
   int is;
   
-  etaqp1 = ZERO;
+  cv_mem->cv_etaqp1 = ZERO;
 
-  if (q != qmax) {
+  if (cv_mem->cv_q != cv_mem->cv_qmax) {
 
-    if (saved_tq5 == ZERO) return(etaqp1);
+    if (cv_mem->cv_saved_tq5 == ZERO) return(cv_mem->cv_etaqp1);
 
-    cquot = (tq[5] / saved_tq5) * SUNRpowerI(h/tau[2], L);
-    N_VLinearSum(-cquot, zn[qmax], ONE, acor, tempv);
-    dup = N_VWrmsNorm(tempv, ewt);
+    cquot = (cv_mem->cv_tq[5] / cv_mem->cv_saved_tq5) *
+      SUNRpowerI(cv_mem->cv_h/cv_mem->cv_tau[2], cv_mem->cv_L);
+    N_VLinearSum(-cquot, cv_mem->cv_zn[cv_mem->cv_qmax], ONE,
+                 cv_mem->cv_acor, cv_mem->cv_tempv);
+    dup = N_VWrmsNorm(cv_mem->cv_tempv, cv_mem->cv_ewt);
 
-    if ( quadr && errconQ ) {
-      N_VLinearSum(-cquot, znQ[qmax], ONE, acorQ, tempvQ);
-      dup = cvQuadUpdateNorm(cv_mem, dup, tempvQ, ewtQ);
+    if ( cv_mem->cv_quadr && cv_mem->cv_errconQ ) {
+      N_VLinearSum(-cquot, cv_mem->cv_znQ[cv_mem->cv_qmax], ONE,
+                   cv_mem->cv_acorQ, cv_mem->cv_tempvQ);
+      dup = cvQuadUpdateNorm(cv_mem, dup, cv_mem->cv_tempvQ, cv_mem->cv_ewtQ);
     }
 
-    if ( sensi && errconS ) {
-      for (is=0; is<Ns; is++) 
-        N_VLinearSum(-cquot, znS[qmax][is], ONE, acorS[is], tempvS[is]);
-      dup = cvSensUpdateNorm(cv_mem, dup, tempvS, ewtS);
+    if ( cv_mem->cv_sensi && cv_mem->cv_errconS ) {
+      for (is=0; is<cv_mem->cv_Ns; is++) 
+        N_VLinearSum(-cquot, cv_mem->cv_znS[cv_mem->cv_qmax][is], ONE,
+                     cv_mem->cv_acorS[is], cv_mem->cv_tempvS[is]);
+      dup = cvSensUpdateNorm(cv_mem, dup, cv_mem->cv_tempvS, cv_mem->cv_ewtS);
     }
 
-    if ( quadr_sensi && errconQS ) {
-      for (is=0; is<Ns; is++) 
-        N_VLinearSum(-cquot, znQS[qmax][is], ONE, acorQS[is], tempvQS[is]);
-      dup = cvSensUpdateNorm(cv_mem, dup, tempvQS, ewtQS);
+    if ( cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS ) {
+      for (is=0; is<cv_mem->cv_Ns; is++) 
+        N_VLinearSum(-cquot, cv_mem->cv_znQS[cv_mem->cv_qmax][is], ONE,
+                     cv_mem->cv_acorQS[is], cv_mem->cv_tempvQS[is]);
+      dup = cvSensUpdateNorm(cv_mem, dup, cv_mem->cv_tempvQS, cv_mem->cv_ewtQS);
     }
 
-    dup = dup * tq[3];
-    etaqp1 = ONE / (SUNRpowerR(BIAS3*dup, ONE/(L+1)) + ADDON);
+    dup = dup * cv_mem->cv_tq[3];
+    cv_mem->cv_etaqp1 = ONE / (SUNRpowerR(BIAS3*dup, ONE/(cv_mem->cv_L+1)) + ADDON);
   }
 
-  return(etaqp1);
+  return(cv_mem->cv_etaqp1);
 }
 
 /*
@@ -7483,30 +7648,30 @@ static void cvChooseEta(CVodeMem cv_mem)
   realtype etam;
   int is;
   
-  etam = SUNMAX(etaqm1, SUNMAX(etaq, etaqp1));
+  etam = SUNMAX(cv_mem->cv_etaqm1, SUNMAX(cv_mem->cv_etaq, cv_mem->cv_etaqp1));
   
   if (etam < THRESH) {
-    eta = ONE;
-    qprime = q;
+    cv_mem->cv_eta = ONE;
+    cv_mem->cv_qprime = cv_mem->cv_q;
     return;
   }
 
-  if (etam == etaq) {
+  if (etam == cv_mem->cv_etaq) {
 
-    eta = etaq;
-    qprime = q;
+    cv_mem->cv_eta = cv_mem->cv_etaq;
+    cv_mem->cv_qprime = cv_mem->cv_q;
 
-  } else if (etam == etaqm1) {
+  } else if (etam == cv_mem->cv_etaqm1) {
 
-    eta = etaqm1;
-    qprime = q - 1;
+    cv_mem->cv_eta = cv_mem->cv_etaqm1;
+    cv_mem->cv_qprime = cv_mem->cv_q - 1;
 
   } else {
 
-    eta = etaqp1;
-    qprime = q + 1;
+    cv_mem->cv_eta = cv_mem->cv_etaqp1;
+    cv_mem->cv_qprime = cv_mem->cv_q + 1;
 
-    if (lmm == CV_BDF) {
+    if (cv_mem->cv_lmm == CV_BDF) {
 
       /* 
        * Store Delta_n in zn[qmax] to be used in order increase 
@@ -7515,18 +7680,18 @@ static void cvChooseEta(CVodeMem cv_mem)
        * to order q+1, so it represents Delta_n in the ELTE at q+1
        */
       
-      N_VScale(ONE, acor, zn[qmax]);
+      N_VScale(ONE, cv_mem->cv_acor, cv_mem->cv_zn[cv_mem->cv_qmax]);
       
-      if (quadr && errconQ)
-        N_VScale(ONE, acorQ, znQ[qmax]);
+      if (cv_mem->cv_quadr && cv_mem->cv_errconQ)
+        N_VScale(ONE, cv_mem->cv_acorQ, cv_mem->cv_znQ[cv_mem->cv_qmax]);
       
-      if (sensi && errconS)
-        for (is=0; is<Ns; is++)
-          N_VScale(ONE, acorS[is], znS[qmax][is]);
+      if (cv_mem->cv_sensi && cv_mem->cv_errconS)
+        for (is=0; is<cv_mem->cv_Ns; is++)
+          N_VScale(ONE, cv_mem->cv_acorS[is], cv_mem->cv_znS[cv_mem->cv_qmax][is]);
 
-      if (quadr_sensi && errconQS)
-        for (is=0; is<Ns; is++)
-          N_VScale(ONE, acorQS[is], znQS[qmax][is]);
+      if (cv_mem->cv_quadr_sensi && cv_mem->cv_errconQS)
+        for (is=0; is<cv_mem->cv_Ns; is++)
+          N_VScale(ONE, cv_mem->cv_acorQS[is], cv_mem->cv_znQS[cv_mem->cv_qmax][is]);
 
     }
   }
@@ -7558,58 +7723,76 @@ static int cvHandleFailure(CVodeMem cv_mem, int flag)
   /* Depending on flag, print error message and return error flag */
   switch (flag) {
   case CV_ERR_FAILURE:
-    cvProcessError(cv_mem, CV_ERR_FAILURE, "CVODES", "CVode", MSGCV_ERR_FAILS, tn, h);
+    cvProcessError(cv_mem, CV_ERR_FAILURE, "CVODES", "CVode",
+                   MSGCV_ERR_FAILS, cv_mem->cv_tn, cv_mem->cv_h);
     break;
   case CV_CONV_FAILURE:
-    cvProcessError(cv_mem, CV_CONV_FAILURE, "CVODES", "CVode", MSGCV_CONV_FAILS, tn, h);
+    cvProcessError(cv_mem, CV_CONV_FAILURE, "CVODES", "CVode",
+                   MSGCV_CONV_FAILS, cv_mem->cv_tn, cv_mem->cv_h);
     break;
   case CV_LSETUP_FAIL:
-    cvProcessError(cv_mem, CV_LSETUP_FAIL, "CVODES", "CVode", MSGCV_SETUP_FAILED, tn);
+    cvProcessError(cv_mem, CV_LSETUP_FAIL, "CVODES", "CVode",
+                   MSGCV_SETUP_FAILED, cv_mem->cv_tn);
     break;
   case CV_LSOLVE_FAIL:
-    cvProcessError(cv_mem, CV_LSOLVE_FAIL, "CVODES", "CVode", MSGCV_SOLVE_FAILED, tn);
+    cvProcessError(cv_mem, CV_LSOLVE_FAIL, "CVODES", "CVode",
+                   MSGCV_SOLVE_FAILED, cv_mem->cv_tn);
     break;
   case CV_RHSFUNC_FAIL:
-    cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODES", "CVode", MSGCV_RHSFUNC_FAILED, tn);
+    cvProcessError(cv_mem, CV_RHSFUNC_FAIL, "CVODES", "CVode",
+                   MSGCV_RHSFUNC_FAILED, cv_mem->cv_tn);
     break;
   case CV_UNREC_RHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_UNREC_RHSFUNC_ERR, "CVODES", "CVode", MSGCV_RHSFUNC_UNREC, tn);
+    cvProcessError(cv_mem, CV_UNREC_RHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_RHSFUNC_UNREC, cv_mem->cv_tn);
     break;
   case CV_REPTD_RHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_REPTD_RHSFUNC_ERR, "CVODES", "CVode", MSGCV_RHSFUNC_REPTD, tn);
+    cvProcessError(cv_mem, CV_REPTD_RHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_RHSFUNC_REPTD, cv_mem->cv_tn);
     break;
   case CV_RTFUNC_FAIL:
-    cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "CVode", MSGCV_RTFUNC_FAILED, tn);
+    cvProcessError(cv_mem, CV_RTFUNC_FAIL, "CVODES", "CVode",
+                   MSGCV_RTFUNC_FAILED, cv_mem->cv_tn);
     break;
   case CV_QRHSFUNC_FAIL:
-    cvProcessError(cv_mem, CV_QRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QRHSFUNC_FAILED, tn);
+    cvProcessError(cv_mem, CV_QRHSFUNC_FAIL, "CVODES", "CVode",
+                   MSGCV_QRHSFUNC_FAILED, cv_mem->cv_tn);
     break;
   case CV_UNREC_QRHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_UNREC_QRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QRHSFUNC_UNREC, tn);
+    cvProcessError(cv_mem, CV_UNREC_QRHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_QRHSFUNC_UNREC, cv_mem->cv_tn);
     break;
   case CV_REPTD_QRHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_REPTD_QRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QRHSFUNC_REPTD, tn);
+    cvProcessError(cv_mem, CV_REPTD_QRHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_QRHSFUNC_REPTD, cv_mem->cv_tn);
     break;
   case CV_SRHSFUNC_FAIL:
-    cvProcessError(cv_mem, CV_SRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_SRHSFUNC_FAILED, tn);
+    cvProcessError(cv_mem, CV_SRHSFUNC_FAIL, "CVODES", "CVode",
+                   MSGCV_SRHSFUNC_FAILED, cv_mem->cv_tn);
     break;
   case CV_UNREC_SRHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_UNREC_SRHSFUNC_ERR, "CVODES", "CVode", MSGCV_SRHSFUNC_UNREC, tn);
+    cvProcessError(cv_mem, CV_UNREC_SRHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_SRHSFUNC_UNREC, cv_mem->cv_tn);
     break;
   case CV_REPTD_SRHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_REPTD_SRHSFUNC_ERR, "CVODES", "CVode", MSGCV_SRHSFUNC_REPTD, tn);
+    cvProcessError(cv_mem, CV_REPTD_SRHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_SRHSFUNC_REPTD, cv_mem->cv_tn);
     break;
   case CV_QSRHSFUNC_FAIL:
-    cvProcessError(cv_mem, CV_QSRHSFUNC_FAIL, "CVODES", "CVode", MSGCV_QSRHSFUNC_FAILED, tn);
+    cvProcessError(cv_mem, CV_QSRHSFUNC_FAIL, "CVODES", "CVode",
+                   MSGCV_QSRHSFUNC_FAILED, cv_mem->cv_tn);
     break;
   case CV_UNREC_QSRHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_UNREC_QSRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QSRHSFUNC_UNREC, tn);
+    cvProcessError(cv_mem, CV_UNREC_QSRHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_QSRHSFUNC_UNREC, cv_mem->cv_tn);
     break;
   case CV_REPTD_QSRHSFUNC_ERR:
-    cvProcessError(cv_mem, CV_REPTD_QSRHSFUNC_ERR, "CVODES", "CVode", MSGCV_QSRHSFUNC_REPTD, tn);
+    cvProcessError(cv_mem, CV_REPTD_QSRHSFUNC_ERR, "CVODES", "CVode",
+                   MSGCV_QSRHSFUNC_REPTD, cv_mem->cv_tn);
     break;
   case CV_TOO_CLOSE:
-    cvProcessError(cv_mem, CV_TOO_CLOSE, "CVODES", "CVode", MSGCV_TOO_CLOSE);
+    cvProcessError(cv_mem, CV_TOO_CLOSE, "CVODES", "CVode",
+                   MSGCV_TOO_CLOSE);
     break;
   default:
     return(CV_SUCCESS);
@@ -7644,44 +7827,48 @@ static void cvBDFStab(CVodeMem cv_mem)
   /* If order is 3 or greater, then save scaled derivative data,
      push old data down in i, then add current values to top.    */
 
-  if (q >= 3) {
+  if (cv_mem->cv_q >= 3) {
     for (k = 1; k <= 3; k++)
       for (i = 5; i >= 2; i--)
-        ssdat[i][k] = ssdat[i-1][k];
+        cv_mem->cv_ssdat[i][k] = cv_mem->cv_ssdat[i-1][k];
     factorial = 1;
-    for (i = 1; i <= q-1; i++) factorial *= i;
-    sq = factorial*q*(q+1)*acnrm/SUNMAX(tq[5],TINY);
-    sqm1 = factorial*q*N_VWrmsNorm(zn[q], ewt);
-    sqm2 = factorial*N_VWrmsNorm(zn[q-1], ewt);
-    ssdat[1][1] = sqm2*sqm2;
-    ssdat[1][2] = sqm1*sqm1;
-    ssdat[1][3] = sq*sq;
+    for (i = 1; i <= cv_mem->cv_q-1; i++) factorial *= i;
+    sq = factorial * cv_mem->cv_q * (cv_mem->cv_q+1) *
+      cv_mem->cv_acnrm / SUNMAX(cv_mem->cv_tq[5],TINY);
+    sqm1 = factorial * cv_mem->cv_q *
+      N_VWrmsNorm(cv_mem->cv_zn[cv_mem->cv_q], cv_mem->cv_ewt);
+    sqm2 = factorial *
+      N_VWrmsNorm(cv_mem->cv_zn[cv_mem->cv_q-1], cv_mem->cv_ewt);
+    cv_mem->cv_ssdat[1][1] = sqm2*sqm2;
+    cv_mem->cv_ssdat[1][2] = sqm1*sqm1;
+    cv_mem->cv_ssdat[1][3] = sq*sq;
   }  
 
-  if (qprime >= q) {
+  if (cv_mem->cv_qprime >= cv_mem->cv_q) {
 
     /* If order is 3 or greater, and enough ssdat has been saved,
        nscon >= q+5, then call stability limit detection routine.  */
 
-    if ( (q >= 3) && (nscon >= q+5) ) {
+    if ( (cv_mem->cv_q >= 3) && (cv_mem->cv_nscon >= cv_mem->cv_q+5) ) {
       ldflag = cvSLdet(cv_mem);
       if (ldflag > 3) {
         /* A stability limit violation is indicated by
            a return flag of 4, 5, or 6.
            Reduce new order.                     */
-        qprime = q-1;
-        eta = etaqm1; 
-        eta = SUNMIN(eta,etamax);
-        eta = eta/SUNMAX(ONE,SUNRabs(h)*hmax_inv*eta);
-        hprime = h*eta;
-        nor = nor + 1;
+        cv_mem->cv_qprime = cv_mem->cv_q-1;
+        cv_mem->cv_eta = cv_mem->cv_etaqm1; 
+        cv_mem->cv_eta = SUNMIN(cv_mem->cv_eta,cv_mem->cv_etamax);
+        cv_mem->cv_eta = cv_mem->cv_eta /
+          SUNMAX(ONE,SUNRabs(cv_mem->cv_h)*cv_mem->cv_hmax_inv*cv_mem->cv_eta);
+        cv_mem->cv_hprime = cv_mem->cv_h * cv_mem->cv_eta;
+        cv_mem->cv_nor = cv_mem->cv_nor + 1;
       }
     }
   }
   else {
     /* Otherwise, let order increase happen, and 
        reset stability limit counter, nscon.     */
-    nscon = 0;
+    cv_mem->cv_nscon = 0;
   }
 }
 
@@ -7754,12 +7941,12 @@ static int cvSLdet(CVodeMem cv_mem)
   /* get maxima, minima, and variances, and form quartic coefficients  */
 
   for (k=1; k<=3; k++) {
-    smink = ssdat[1][k];
+    smink = cv_mem->cv_ssdat[1][k];
     smaxk = ZERO;
     
     for (i=1; i<=5; i++) {
-      smink = SUNMIN(smink,ssdat[i][k]);
-      smaxk = SUNMAX(smaxk,ssdat[i][k]);
+      smink = SUNMIN(smink,cv_mem->cv_ssdat[i][k]);
+      smaxk = SUNMAX(smaxk,cv_mem->cv_ssdat[i][k]);
     }
     
     if (smink < TINY*smaxk) {
@@ -7772,18 +7959,22 @@ static int cvSLdet(CVodeMem cv_mem)
     sumrat = ZERO;
     sumrsq = ZERO;
     for (i=1; i<=4; i++) {
-      rat[i][k] = ssdat[i][k]/ssdat[i+1][k];
+      rat[i][k] = cv_mem->cv_ssdat[i][k] / cv_mem->cv_ssdat[i+1][k];
       sumrat = sumrat + rat[i][k];
       sumrsq = sumrsq + rat[i][k]*rat[i][k];
     } 
     rav[k] = FOURTH*sumrat;
     vrat[k] = SUNRabs(FOURTH*sumrsq - rav[k]*rav[k]);
 
-    qc[5][k] = ssdat[1][k]*ssdat[3][k] - ssdat[2][k]*ssdat[2][k];
-    qc[4][k] = ssdat[2][k]*ssdat[3][k] - ssdat[1][k]*ssdat[4][k];
+    qc[5][k] = cv_mem->cv_ssdat[1][k] * cv_mem->cv_ssdat[3][k] -
+      cv_mem->cv_ssdat[2][k] * cv_mem->cv_ssdat[2][k];
+    qc[4][k] = cv_mem->cv_ssdat[2][k] * cv_mem->cv_ssdat[3][k] -
+      cv_mem->cv_ssdat[1][k] * cv_mem->cv_ssdat[4][k];
     qc[3][k] = ZERO;
-    qc[2][k] = ssdat[2][k]*ssdat[5][k] - ssdat[3][k]*ssdat[4][k];
-    qc[1][k] = ssdat[4][k]*ssdat[4][k] - ssdat[3][k]*ssdat[5][k];
+    qc[2][k] = cv_mem->cv_ssdat[2][k] * cv_mem->cv_ssdat[5][k] -
+      cv_mem->cv_ssdat[3][k] * cv_mem->cv_ssdat[4][k];
+    qc[1][k] = cv_mem->cv_ssdat[4][k] * cv_mem->cv_ssdat[4][k] -
+      cv_mem->cv_ssdat[3][k] * cv_mem->cv_ssdat[5][k];
 
     for (i=1; i<=5; i++) {
       qco[i][k] = qc[i][k];
@@ -7928,10 +8119,10 @@ static int cvSLdet(CVodeMem cv_mem)
   /* All positive kflag drop to this section  */
   
   for (k=1; k<=3; k++) {
-    rsa = ssdat[1][k];
-    rsb = ssdat[2][k]*rr;
-    rsc = ssdat[3][k]*rr*rr;
-    rsd = ssdat[4][k]*rr*rr*rr;
+    rsa = cv_mem->cv_ssdat[1][k];
+    rsb = cv_mem->cv_ssdat[2][k]*rr;
+    rsc = cv_mem->cv_ssdat[3][k]*rr*rr;
+    rsd = cv_mem->cv_ssdat[4][k]*rr*rr*rr;
     rd1a = rsa - rsb;
     rd1b = rsb - rsc;
     rd1c = rsc - rsd;
@@ -7950,7 +8141,7 @@ static int cvSLdet(CVodeMem cv_mem)
       return(kflag);
     }
     corr1 = (rd2b/cest1)/(rr*rr);
-    sigsq[k] = ssdat[3][k] + corr1;
+    sigsq[k] = cv_mem->cv_ssdat[3][k] + corr1;
   }
   
   if (sigsq[2] < TINY) {
@@ -7960,8 +8151,8 @@ static int cvSLdet(CVodeMem cv_mem)
   
   ratp = sigsq[3]/sigsq[2];
   ratm = sigsq[1]/sigsq[2];
-  qfac1 = FOURTH*(q*q - ONE);
-  qfac2 = TWO/(q - ONE);
+  qfac1 = FOURTH*(cv_mem->cv_q*cv_mem->cv_q - ONE);
+  qfac2 = TWO/(cv_mem->cv_q - ONE);
   bb = ratp*ratm - ONE - qfac1*ratp;
   tem = ONE - qfac2*bb;
   
@@ -8014,39 +8205,43 @@ static int cvRcheck1(CVodeMem cv_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  tlo = tn;
-  ttol = (SUNRabs(tn) + SUNRabs(h))*uround*HUNDRED;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++)
+    cv_mem->cv_iroots[i] = 0;
+  cv_mem->cv_tlo = cv_mem->cv_tn;
+  cv_mem->cv_ttol = (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)) *
+    cv_mem->cv_uround*HUNDRED;
 
   /* Evaluate g at initial t and check for zero values. */
-  retval = gfun(tlo, zn[0], glo, user_data);
-  nge = 1;
+  retval = cv_mem->cv_gfun(cv_mem->cv_tlo, cv_mem->cv_zn[0],
+                           cv_mem->cv_glo, cv_mem->cv_user_data);
+  cv_mem->cv_nge = 1;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      gactive[i] = FALSE;
+  zroot = SUNFALSE;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (SUNRabs(cv_mem->cv_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      cv_mem->cv_gactive[i] = SUNFALSE;
     }
   }
   if (!zroot) return(CV_SUCCESS);
 
   /* Some g_i is zero at t0; look at g at t0+(small increment). */
-  hratio = SUNMAX(ttol/SUNRabs(h), PT1);
-  smallh = hratio*h;
-  tplus = tlo + smallh;
-  N_VLinearSum(ONE, zn[0], hratio, zn[1], y);
-  retval = gfun(tplus, y, ghi, user_data);
-  nge++;
+  hratio = SUNMAX(cv_mem->cv_ttol/SUNRabs(cv_mem->cv_h), PT1);
+  smallh = hratio*cv_mem->cv_h;
+  tplus = cv_mem->cv_tlo + smallh;
+  N_VLinearSum(ONE, cv_mem->cv_zn[0], hratio, cv_mem->cv_zn[1], cv_mem->cv_y);
+  retval = cv_mem->cv_gfun(tplus, cv_mem->cv_y,
+                           cv_mem->cv_ghi, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
   /* We check now only the components of g which were exactly 0.0 at t0
    * to see if we can 'activate' them. */
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i] && SUNRabs(ghi[i]) != ZERO) {
-      gactive[i] = TRUE;
-      glo[i] = ghi[i];
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (!cv_mem->cv_gactive[i] && SUNRabs(cv_mem->cv_ghi[i]) != ZERO) {
+      cv_mem->cv_gactive[i] = SUNTRUE;
+      cv_mem->cv_glo[i] = cv_mem->cv_ghi[i];
     }
   }
   return(CV_SUCCESS);
@@ -8079,49 +8274,54 @@ static int cvRcheck2(CVodeMem cv_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  if (irfnd == 0) return(CV_SUCCESS);
+  if (cv_mem->cv_irfnd == 0) return(CV_SUCCESS);
 
-  (void) CVodeGetDky(cv_mem, tlo, 0, y);
-  retval = gfun(tlo, y, glo, user_data);
-  nge++;
+  (void) CVodeGetDky(cv_mem, cv_mem->cv_tlo, 0, cv_mem->cv_y);
+  retval = cv_mem->cv_gfun(cv_mem->cv_tlo, cv_mem->cv_y,
+                           cv_mem->cv_glo, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++)
+    cv_mem->cv_iroots[i] = 0;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (!cv_mem->cv_gactive[i]) continue;
+    if (SUNRabs(cv_mem->cv_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      cv_mem->cv_iroots[i] = 1;
     }
   }
   if (!zroot) return(CV_SUCCESS);
 
   /* One or more g_i has a zero at tlo.  Check g at tlo+smallh. */
-  ttol = (SUNRabs(tn) + SUNRabs(h))*uround*HUNDRED;
-  smallh = (h > ZERO) ? ttol : -ttol;
-  tplus = tlo + smallh;
-  if ( (tplus - tn)*h >= ZERO) {
-    hratio = smallh/h;
-    N_VLinearSum(ONE, y, hratio, zn[1], y);
+  cv_mem->cv_ttol = (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)) *
+    cv_mem->cv_uround*HUNDRED;
+  smallh = (cv_mem->cv_h > ZERO) ? cv_mem->cv_ttol : -cv_mem->cv_ttol;
+  tplus = cv_mem->cv_tlo + smallh;
+  if ( (tplus - cv_mem->cv_tn)*cv_mem->cv_h >= ZERO) {
+    hratio = smallh/cv_mem->cv_h;
+    N_VLinearSum(ONE, cv_mem->cv_y, hratio, cv_mem->cv_zn[1], cv_mem->cv_y);
   } else {
-    (void) CVodeGetDky(cv_mem, tplus, 0, y);
+    (void) CVodeGetDky(cv_mem, tplus, 0, cv_mem->cv_y);
   }
-  retval = gfun(tplus, y, ghi, user_data);
-  nge++;
+  retval = cv_mem->cv_gfun(tplus, cv_mem->cv_y,
+                           cv_mem->cv_ghi, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
   /* Check for close roots (error return), for a new zero at tlo+smallh,
   and for a g_i that changed from zero to nonzero. */
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if (iroots[i] == 1) return(CLOSERT);
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    if (!cv_mem->cv_gactive[i]) continue;
+    if (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) {
+      if (cv_mem->cv_iroots[i] == 1) return(CLOSERT);
+      zroot = SUNTRUE;
+      cv_mem->cv_iroots[i] = 1;
     } else {
-      if (iroots[i] == 1) glo[i] = ghi[i];
+      if (cv_mem->cv_iroots[i] == 1)
+        cv_mem->cv_glo[i] = cv_mem->cv_ghi[i];
     }
   }
   if (zroot) return(RTFOUND);
@@ -8146,39 +8346,43 @@ static int cvRcheck3(CVodeMem cv_mem)
   int i, ier, retval;
 
   /* Set thi = tn or tout, whichever comes first; set y = y(thi). */
-  if (taskc == CV_ONE_STEP) {
-    thi = tn;
-    N_VScale(ONE, zn[0], y);
-  }
-  if (taskc == CV_NORMAL) {
-    if ( (toutc - tn)*h >= ZERO) {
-      thi = tn; 
-      N_VScale(ONE, zn[0], y);
+  if (cv_mem->cv_taskc == CV_ONE_STEP) {
+    cv_mem->cv_thi = cv_mem->cv_tn;
+    N_VScale(ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
+  }
+  if (cv_mem->cv_taskc == CV_NORMAL) {
+    if ( (cv_mem->cv_toutc - cv_mem->cv_tn)*cv_mem->cv_h >= ZERO) {
+      cv_mem->cv_thi = cv_mem->cv_tn; 
+      N_VScale(ONE, cv_mem->cv_zn[0], cv_mem->cv_y);
     } else {
-      thi = toutc;
-      (void) CVodeGetDky(cv_mem, thi, 0, y);
+      cv_mem->cv_thi = cv_mem->cv_toutc;
+      (void) CVodeGetDky(cv_mem, cv_mem->cv_thi, 0, cv_mem->cv_y);
     }
   }
 
   /* Set ghi = g(thi) and call cvRootfind to search (tlo,thi) for roots. */
-  retval = gfun(thi, y, ghi, user_data);
-  nge++;
+  retval = cv_mem->cv_gfun(cv_mem->cv_thi, cv_mem->cv_y,
+                           cv_mem->cv_ghi, cv_mem->cv_user_data);
+  cv_mem->cv_nge++;
   if (retval != 0) return(CV_RTFUNC_FAIL);
 
-  ttol = (SUNRabs(tn) + SUNRabs(h))*uround*HUNDRED;
+  cv_mem->cv_ttol = (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)) *
+    cv_mem->cv_uround*HUNDRED;
   ier = cvRootfind(cv_mem);
   if (ier == CV_RTFUNC_FAIL) return(CV_RTFUNC_FAIL);
-  for(i=0; i<nrtfn; i++) {
-    if(!gactive[i] && grout[i] != ZERO) gactive[i] = TRUE;
+  for(i=0; i<cv_mem->cv_nrtfn; i++) {
+    if(!cv_mem->cv_gactive[i] && cv_mem->cv_grout[i] != ZERO)
+      cv_mem->cv_gactive[i] = SUNTRUE;
   }
-  tlo = trout;
-  for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+  cv_mem->cv_tlo = cv_mem->cv_trout;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++)
+    cv_mem->cv_glo[i] = cv_mem->cv_grout[i];
 
   /* If no root found, return CV_SUCCESS. */  
   if (ier == CV_SUCCESS) return(CV_SUCCESS);
 
   /* If a root was found, interpolate to get y(trout) and return.  */
-  (void) CVodeGetDky(cv_mem, trout, 0, y);
+  (void) CVodeGetDky(cv_mem, cv_mem->cv_trout, 0, cv_mem->cv_y);
   return(RTFOUND);
 }
 
@@ -8212,10 +8416,10 @@ static int cvRcheck3(CVodeMem cv_mem)
  *
  * gactive  = array specifying whether a component of g should
  *            or should not be monitored. gactive[i] is initially
- *            set to TRUE for all i=0,...,nrtfn-1, but it may be
- *            reset to FALSE if at the first step g[i] is 0.0
+ *            set to SUNTRUE for all i=0,...,nrtfn-1, but it may be
+ *            reset to SUNFALSE if at the first step g[i] is 0.0
  *            both at the I.C. and at a small perturbation of them.
- *            gactive[i] is then set back on TRUE only after the 
+ *            gactive[i] is then set back on SUNTRUE only after the 
  *            corresponding g function moves away from 0.0.
  *
  * nge      = cumulative counter for gfun calls.
@@ -8269,19 +8473,20 @@ static int cvRootfind(CVodeMem cv_mem)
 
   /* First check for change in sign in ghi or for a zero in ghi. */
   maxfrac = ZERO;
-  zroot = FALSE;
-  sgnchg = FALSE;
-  for (i = 0;  i < nrtfn; i++) {
-    if(!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if(rootdir[i]*glo[i] <= ZERO) {
-        zroot = TRUE;
+  zroot = SUNFALSE;
+  sgnchg = SUNFALSE;
+  for (i = 0;  i < cv_mem->cv_nrtfn; i++) {
+    if(!cv_mem->cv_gactive[i]) continue;
+    if (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) {
+      if(cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) {
+        zroot = SUNTRUE;
       }
     } else {
-      if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-        gfrac = SUNRabs(ghi[i]/(ghi[i] - glo[i]));
+      if ( (cv_mem->cv_glo[i]*cv_mem->cv_ghi[i] < ZERO) &&
+           (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) ) {
+        gfrac = SUNRabs(cv_mem->cv_ghi[i]/(cv_mem->cv_ghi[i] - cv_mem->cv_glo[i]));
         if (gfrac > maxfrac) {
-          sgnchg = TRUE;
+          sgnchg = SUNTRUE;
           maxfrac = gfrac;
           imax = i;
         }
@@ -8292,14 +8497,16 @@ static int cvRootfind(CVodeMem cv_mem)
   /* If no sign change was found, reset trout and grout.  Then return
      CV_SUCCESS if no zero was found, or set iroots and return RTFOUND.  */ 
   if (!sgnchg) {
-    trout = thi;
-    for (i = 0; i < nrtfn; i++) grout[i] = ghi[i];
+    cv_mem->cv_trout = cv_mem->cv_thi;
+    for (i = 0; i < cv_mem->cv_nrtfn; i++)
+      cv_mem->cv_grout[i] = cv_mem->cv_ghi[i];
     if (!zroot) return(CV_SUCCESS);
-    for (i = 0; i < nrtfn; i++) {
-      iroots[i] = 0;
-      if(!gactive[i]) continue;
-      if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-        iroots[i] = glo[i] > 0 ? -1:1;
+    for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+      cv_mem->cv_iroots[i] = 0;
+      if(!cv_mem->cv_gactive[i]) continue;
+      if ( (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) &&
+           (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) )
+        cv_mem->cv_iroots[i] = cv_mem->cv_glo[i] > 0 ? -1:1;
     }
     return(RTFOUND);
   }
@@ -8310,10 +8517,10 @@ static int cvRootfind(CVodeMem cv_mem)
   /* A sign change was found.  Loop to locate nearest root. */
 
   side = 0;  sideprev = -1;
-  loop {                                    /* Looping point */
+  for(;;) {                                    /* Looping point */
 
     /* If interval size is already less than tolerance ttol, break. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo) <= cv_mem->cv_ttol) break;
 
     /* Set weight alph.
        On the first two passes, set alph = 1.  Thereafter, reset alph
@@ -8323,7 +8530,7 @@ static int cvRootfind(CVodeMem cv_mem)
        If the sides were the same, then double alph (if high side),
        or halve alph (if low side).
        The next guess tmid is the secant method value if alph = 1, but
-       is closer to tlo if alph < 1, and closer to thi if alph > 1.    */
+       is closer to cv_mem->cv_tlo if alph < 1, and closer to thi if alph > 1.    */
 
     if (sideprev == side) {
       alph = (side == 2) ? alph*TWO : alph*HALF;
@@ -8334,38 +8541,42 @@ static int cvRootfind(CVodeMem cv_mem)
     /* Set next root approximation tmid and get g(tmid).
        If tmid is too close to tlo or thi, adjust it inward,
        by a fractional distance that is between 0.1 and 0.5.  */
-    tmid = thi - (thi - tlo)*ghi[imax]/(ghi[imax] - alph*glo[imax]);
-    if (SUNRabs(tmid - tlo) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    tmid = cv_mem->cv_thi - (cv_mem->cv_thi - cv_mem->cv_tlo) *
+      cv_mem->cv_ghi[imax] / (cv_mem->cv_ghi[imax] - alph*cv_mem->cv_glo[imax]);
+    if (SUNRabs(tmid - cv_mem->cv_tlo) < HALF*cv_mem->cv_ttol) {
+      fracint = SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo)/cv_mem->cv_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = tlo + fracsub*(thi - tlo);
+      tmid = cv_mem->cv_tlo + fracsub*(cv_mem->cv_thi - cv_mem->cv_tlo);
     }
-    if (SUNRabs(thi - tmid) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    if (SUNRabs(cv_mem->cv_thi - tmid) < HALF*cv_mem->cv_ttol) {
+      fracint = SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo)/cv_mem->cv_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = thi - fracsub*(thi - tlo);
+      tmid = cv_mem->cv_thi - fracsub*(cv_mem->cv_thi - cv_mem->cv_tlo);
     }
 
-    (void) CVodeGetDky(cv_mem, tmid, 0, y);
-    retval = gfun(tmid, y, grout, user_data);
-    nge++;
+    (void) CVodeGetDky(cv_mem, tmid, 0, cv_mem->cv_y);
+    retval = cv_mem->cv_gfun(tmid, cv_mem->cv_y, cv_mem->cv_grout,
+                             cv_mem->cv_user_data);
+    cv_mem->cv_nge++;
     if (retval != 0) return(CV_RTFUNC_FAIL);
 
     /* Check to see in which subinterval g changes sign, and reset imax.
        Set side = 1 if sign change is on low side, or 2 if on high side.  */  
     maxfrac = ZERO;
-    zroot = FALSE;
-    sgnchg = FALSE;
+    zroot = SUNFALSE;
+    sgnchg = SUNFALSE;
     sideprev = side;
-    for (i = 0;  i < nrtfn; i++) {
-      if(!gactive[i]) continue;
-      if (SUNRabs(grout[i]) == ZERO) {
-        if(rootdir[i]*glo[i] <= ZERO) zroot = TRUE;
+    for (i = 0;  i < cv_mem->cv_nrtfn; i++) {
+      if(!cv_mem->cv_gactive[i]) continue;
+      if (SUNRabs(cv_mem->cv_grout[i]) == ZERO) {
+        if(cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) zroot = SUNTRUE;
       } else {
-        if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-          gfrac = SUNRabs(grout[i]/(grout[i] - glo[i]));
+        if ( (cv_mem->cv_glo[i]*cv_mem->cv_grout[i] < ZERO) &&
+             (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) ) {
+          gfrac = SUNRabs(cv_mem->cv_grout[i] /
+                          (cv_mem->cv_grout[i] - cv_mem->cv_glo[i]));
           if (gfrac > maxfrac) {
-            sgnchg = TRUE;
+            sgnchg = SUNTRUE;
             maxfrac = gfrac;
             imax = i;
           }
@@ -8374,41 +8585,46 @@ static int cvRootfind(CVodeMem cv_mem)
     }
     if (sgnchg) {
       /* Sign change found in (tlo,tmid); replace thi with tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      cv_mem->cv_thi = tmid;
+      for (i = 0; i < cv_mem->cv_nrtfn; i++)
+        cv_mem->cv_ghi[i] = cv_mem->cv_grout[i];
       side = 1;
       /* Stop at root thi if converged; otherwise loop. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo) <= cv_mem->cv_ttol) break;
       continue;  /* Return to looping point. */
     }
 
     if (zroot) {
       /* No sign change in (tlo,tmid), but g = 0 at tmid; return root tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      cv_mem->cv_thi = tmid;
+      for (i = 0; i < cv_mem->cv_nrtfn; i++)
+        cv_mem->cv_ghi[i] = cv_mem->cv_grout[i];
       break;
     }
 
     /* No sign change in (tlo,tmid), and no zero at tmid.
        Sign change must be in (tmid,thi).  Replace tlo with tmid. */
-    tlo = tmid;
-    for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+    cv_mem->cv_tlo = tmid;
+    for (i = 0; i < cv_mem->cv_nrtfn; i++)
+      cv_mem->cv_glo[i] = cv_mem->cv_grout[i];
     side = 2;
     /* Stop at root thi if converged; otherwise loop back. */
-    if (SUNRabs(thi - tlo) <= ttol) break;
+    if (SUNRabs(cv_mem->cv_thi - cv_mem->cv_tlo) <= cv_mem->cv_ttol) break;
 
   } /* End of root-search loop */
 
   /* Reset trout and grout, set iroots, and return RTFOUND. */
-  trout = thi;
-  for (i = 0; i < nrtfn; i++) {
-    grout[i] = ghi[i];
-    iroots[i] = 0;
-    if(!gactive[i]) continue;
-    if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-      iroots[i] = glo[i] > 0 ? -1:1;
-    if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) 
-      iroots[i] = glo[i] > 0 ? -1:1;
+  cv_mem->cv_trout = cv_mem->cv_thi;
+  for (i = 0; i < cv_mem->cv_nrtfn; i++) {
+    cv_mem->cv_grout[i] = cv_mem->cv_ghi[i];
+    cv_mem->cv_iroots[i] = 0;
+    if(!cv_mem->cv_gactive[i]) continue;
+    if ( (SUNRabs(cv_mem->cv_ghi[i]) == ZERO) &&
+         (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) )
+      cv_mem->cv_iroots[i] = cv_mem->cv_glo[i] > 0 ? -1:1;
+    if ( (cv_mem->cv_glo[i]*cv_mem->cv_ghi[i] < ZERO) &&
+         (cv_mem->cv_rootdir[i]*cv_mem->cv_glo[i] <= ZERO) ) 
+      cv_mem->cv_iroots[i] = cv_mem->cv_glo[i] > 0 ? -1:1;
   }
   return(RTFOUND);
 }
@@ -8453,7 +8669,7 @@ static realtype cvSensNorm(CVodeMem cv_mem, N_Vector *xS, N_Vector *wS)
   realtype nrm, snrm;
 
   nrm = N_VWrmsNorm(xS[0],wS[0]);
-  for (is=1; is<Ns; is++) {
+  for (is=1; is<cv_mem->cv_Ns; is++) {
     snrm = N_VWrmsNorm(xS[is],wS[is]);
     if ( snrm > nrm ) nrm = snrm;
   }
@@ -8494,7 +8710,7 @@ static realtype cvQuadSensNorm(CVodeMem cv_mem, N_Vector *xQS, N_Vector *wQS)
   realtype nrm, snrm;
 
   nrm = N_VWrmsNorm(xQS[0],wQS[0]);
-  for (is=1; is<Ns; is++) {
+  for (is=1; is<cv_mem->cv_Ns; is++) {
     snrm = N_VWrmsNorm(xQS[is],wQS[is]);
     if ( snrm > nrm ) nrm = snrm;
   }
@@ -8534,7 +8750,7 @@ static realtype cvQuadSensUpdateNorm(CVodeMem cv_mem, realtype old_nrm,
  *
  * CVSensRhs is called:
  *  (*) by CVode at the first step
- *  (*) by cvYddNorm if errcon=TRUE
+ *  (*) by cvYddNorm if errcon=SUNTRUE
  *  (*) by cvNlsFunctional, cvNlsNewton, and cvNewtonIteration
  *      if ism=CV_SIMULTANEOUS
  *  (*) by cvDoErrorTest when restarting from scratch
@@ -8552,15 +8768,15 @@ int cvSensRhsWrapper(CVodeMem cv_mem, realtype time,
 {
   int retval=0, is;
 
-  if (ifS==CV_ALLSENS) {
-    retval = fS(Ns, time, ycur, fcur, yScur, fScur, 
-                fS_data, temp1, temp2);
-    nfSe++;
+  if (cv_mem->cv_ifS==CV_ALLSENS) {
+    retval = cv_mem->cv_fS(cv_mem->cv_Ns, time, ycur, fcur, yScur, 
+                           fScur, cv_mem->cv_fS_data, temp1, temp2);
+    cv_mem->cv_nfSe++;
   } else {
-    for (is=0; is<Ns; is++) {
-      retval = fS1(Ns, time, ycur, fcur, is, yScur[is], fScur[is], 
-                   fS_data, temp1, temp2);
-      nfSe++;
+    for (is=0; is<cv_mem->cv_Ns; is++) {
+      retval = cv_mem->cv_fS1(cv_mem->cv_Ns, time, ycur, fcur, is, yScur[is], 
+                              fScur[is], cv_mem->cv_fS_data, temp1, temp2);
+      cv_mem->cv_nfSe++;
       if (retval != 0) break;
     }
   }
@@ -8588,9 +8804,9 @@ int cvSensRhs1Wrapper(CVodeMem cv_mem, realtype time,
 {
   int retval;
 
-  retval = fS1(Ns, time, ycur, fcur, is, yScur, fScur, 
-               fS_data, temp1, temp2);
-  nfSe++;
+  retval = cv_mem->cv_fS1(cv_mem->cv_Ns, time, ycur, fcur, is, yScur, 
+                          fScur, cv_mem->cv_fS_data, temp1, temp2);
+  cv_mem->cv_nfSe++;
 
   return(retval);
 }
@@ -8603,10 +8819,7 @@ int cvSensRhs1Wrapper(CVodeMem cv_mem, realtype time,
 
 /* Undefine Readibility Constants */
 
-#undef Ns
 #undef y
-#undef yS
-#undef ftemp
 
 /*
  * cvSensRhsInternalDQ   - internal CVSensRhsFn
@@ -8624,8 +8837,8 @@ int cvSensRhsInternalDQ(int Ns, realtype t,
   int is, retval;
   
   for (is=0; is<Ns; is++) {
-    retval = cvSensRhs1InternalDQ(Ns, t, y, ydot, is, yS[is], ySdot[is],
-                                  cvode_mem, ytemp, ftemp);
+    retval = cvSensRhs1InternalDQ(Ns, t, y, ydot, is, yS[is], 
+                                  ySdot[is], cvode_mem, ytemp, ftemp);
     if (retval!=0) return(retval);
   }
 
@@ -8661,31 +8874,31 @@ int cvSensRhs1InternalDQ(int Ns, realtype t,
   /* cvode_mem is passed here as user data */
   cv_mem = (CVodeMem) cvode_mem;
 
-  delta = SUNRsqrt(SUNMAX(reltol, uround));
+  delta = SUNRsqrt(SUNMAX(cv_mem->cv_reltol, cv_mem->cv_uround));
   rdelta = ONE/delta;
   
-  pbari = pbar[is];
+  pbari = cv_mem->cv_pbar[is];
 
-  which = plist[is];
+  which = cv_mem->cv_plist[is];
 
-  psave = p[which];
+  psave = cv_mem->cv_p[which];
   
   Deltap  = pbari * delta;
   rDeltap = ONE/Deltap;
-  norms   = N_VWrmsNorm(yS, ewt) * pbari;
+  norms   = N_VWrmsNorm(yS, cv_mem->cv_ewt) * pbari;
   rDeltay = SUNMAX(norms, rdelta) / pbari;
   Deltay  = ONE/rDeltay;
   
-  if (DQrhomax == ZERO) {
+  if (cv_mem->cv_DQrhomax == ZERO) {
     /* No switching */
-    method = (DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
+    method = (cv_mem->cv_DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
   } else {
     /* switch between simultaneous/separate DQ */
     ratio = Deltay * rDeltap;
-    if ( SUNMAX(ONE/ratio, ratio) <= DQrhomax )
-      method = (DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
+    if ( SUNMAX(ONE/ratio, ratio) <= cv_mem->cv_DQrhomax )
+      method = (cv_mem->cv_DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
     else
-      method = (DQtype==CV_CENTERED) ? CENTERED2 : FORWARD2;
+      method = (cv_mem->cv_DQtype==CV_CENTERED) ? CENTERED2 : FORWARD2;
   }
 
   switch(method) {
@@ -8696,16 +8909,16 @@ int cvSensRhs1InternalDQ(int Ns, realtype t,
     r2Delta = HALF/Delta;
     
     N_VLinearSum(ONE,y,Delta,yS,ytemp);
-    p[which] = psave + Delta;
+    cv_mem->cv_p[which] = psave + Delta;
 
-    retval = f(t, ytemp, ySdot, user_data);
+    retval = cv_mem->cv_f(t, ytemp, ySdot, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
     
     N_VLinearSum(ONE,y,-Delta,yS,ytemp);
-    p[which] = psave - Delta;
+    cv_mem->cv_p[which] = psave - Delta;
 
-    retval = f(t, ytemp, ftemp, user_data);
+    retval = cv_mem->cv_f(t, ytemp, ftemp, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
@@ -8720,25 +8933,25 @@ int cvSensRhs1InternalDQ(int Ns, realtype t,
     
     N_VLinearSum(ONE,y,Deltay,yS,ytemp);
 
-    retval = f(t, ytemp, ySdot, user_data);
+    retval = cv_mem->cv_f(t, ytemp, ySdot, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
     N_VLinearSum(ONE,y,-Deltay,yS,ytemp);
 
-    retval = f(t, ytemp, ftemp, user_data);
+    retval = cv_mem->cv_f(t, ytemp, ftemp, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
     N_VLinearSum(r2Deltay, ySdot, -r2Deltay, ftemp, ySdot);
     
-    p[which] = psave + Deltap;
-    retval = f(t, y, ytemp, user_data);
+    cv_mem->cv_p[which] = psave + Deltap;
+    retval = cv_mem->cv_f(t, y, ytemp, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
-    p[which] = psave - Deltap;
-    retval = f(t, y, ftemp, user_data);
+    cv_mem->cv_p[which] = psave - Deltap;
+    retval = cv_mem->cv_f(t, y, ftemp, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
@@ -8754,9 +8967,9 @@ int cvSensRhs1InternalDQ(int Ns, realtype t,
     rDelta = ONE/Delta;
     
     N_VLinearSum(ONE,y,Delta,yS,ytemp);
-    p[which] = psave + Delta;
+    cv_mem->cv_p[which] = psave + Delta;
 
-    retval = f(t, ytemp, ySdot, user_data);
+    retval = cv_mem->cv_f(t, ytemp, ySdot, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
     
@@ -8768,14 +8981,14 @@ int cvSensRhs1InternalDQ(int Ns, realtype t,
     
     N_VLinearSum(ONE,y,Deltay,yS,ytemp);
 
-    retval = f(t, ytemp, ySdot, user_data);
+    retval = cv_mem->cv_f(t, ytemp, ySdot, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
     N_VLinearSum(rDeltay, ySdot, -rDeltay, ydot, ySdot);
     
-    p[which] = psave + Deltap;
-    retval = f(t, y, ytemp, user_data);
+    cv_mem->cv_p[which] = psave + Deltap;
+    retval = cv_mem->cv_f(t, y, ytemp, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
@@ -8787,10 +9000,10 @@ int cvSensRhs1InternalDQ(int Ns, realtype t,
     
   }
   
-  p[which] = psave;
+  cv_mem->cv_p[which] = psave;
   
   /* Increment counter nfeS */
-  nfeS += nfel;
+  cv_mem->cv_nfeS += nfel;
   
   return(0);
 }
@@ -8841,21 +9054,21 @@ static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t,
   realtype Delta , rDelta , r2Delta ;
   realtype norms;
 
-  delta = SUNRsqrt(SUNMAX(reltol, uround));
+  delta = SUNRsqrt(SUNMAX(cv_mem->cv_reltol, cv_mem->cv_uround));
   rdelta = ONE/delta;
   
-  pbari = pbar[is];
+  pbari = cv_mem->cv_pbar[is];
 
-  which = plist[is];
+  which = cv_mem->cv_plist[is];
 
-  psave = p[which];
+  psave = cv_mem->cv_p[which];
   
   Deltap  = pbari * delta;
-  norms   = N_VWrmsNorm(yS, ewt) * pbari;
+  norms   = N_VWrmsNorm(yS, cv_mem->cv_ewt) * pbari;
   rDeltay = SUNMAX(norms, rdelta) / pbari;
   Deltay  = ONE/rDeltay;
   
-  method = (DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
+  method = (cv_mem->cv_DQtype==CV_CENTERED) ? CENTERED1 : FORWARD1;
 
   switch(method) {
 
@@ -8865,16 +9078,16 @@ static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t,
     r2Delta = HALF/Delta;
     
     N_VLinearSum(ONE, y, Delta, yS, tmp);
-    p[which] = psave + Delta;
+    cv_mem->cv_p[which] = psave + Delta;
 
-    retval = fQ(t, tmp, yQSdot, user_data);
+    retval = cv_mem->cv_fQ(t, tmp, yQSdot, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
     
     N_VLinearSum(ONE, y, -Delta, yS, tmp);
-    p[which] = psave - Delta;
+    cv_mem->cv_p[which] = psave - Delta;
 
-    retval = fQ(t, tmp, tmpQ, user_data);
+    retval = cv_mem->cv_fQ(t, tmp, tmpQ, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
@@ -8888,9 +9101,9 @@ static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t,
     rDelta = ONE/Delta;
     
     N_VLinearSum(ONE, y, Delta, yS, tmp);
-    p[which] = psave + Delta;
+    cv_mem->cv_p[which] = psave + Delta;
 
-    retval = fQ(t, tmp, yQSdot, user_data);
+    retval = cv_mem->cv_fQ(t, tmp, yQSdot, cv_mem->cv_user_data);
     nfel++;
     if (retval != 0) return(retval);
     
@@ -8900,10 +9113,10 @@ static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t,
 
   }
 
-  p[which] = psave;
+  cv_mem->cv_p[which] = psave;
   
   /* Increment counter nfQeS */
-  nfQeS += nfel;
+  cv_mem->cv_nfQeS += nfel;
   
   return(0);
 }
@@ -8923,9 +9136,6 @@ static int cvQuadSensRhs1InternalDQ(CVodeMem cv_mem, int is, realtype t,
  *   pointed to by cv_ehfun.
  */
 
-#define ehfun    (cv_mem->cv_ehfun)
-#define eh_data  (cv_mem->cv_eh_data)
-
 void cvProcessError(CVodeMem cv_mem, 
                     int error_code, const char *module, const char *fname, 
                     const char *msgfmt, ...)
@@ -8949,7 +9159,7 @@ void cvProcessError(CVodeMem cv_mem,
 #endif
 
   } else {                 /* We can call ehfun */
-    ehfun(error_code, module, fname, msg, eh_data);
+    cv_mem->cv_ehfun(error_code, module, fname, msg, cv_mem->cv_eh_data);
   }
 
   /* Finalize argument processing */
@@ -8963,8 +9173,6 @@ void cvProcessError(CVodeMem cv_mem,
  * It sends the error message to the stream pointed to by cv_errfp.
  */
 
-#define errfp    (cv_mem->cv_errfp)
-
 void cvErrHandler(int error_code, const char *module,
                   const char *function, char *msg, void *data)
 {
@@ -8981,9 +9189,9 @@ void cvErrHandler(int error_code, const char *module,
     sprintf(err_type,"ERROR");
 
 #ifndef NO_FPRINTF_OUTPUT
-  if (errfp!=NULL) {
-    fprintf(errfp,"\n[%s %s]  %s\n",module,err_type,function);
-    fprintf(errfp,"  %s\n\n",msg);
+  if (cv_mem->cv_errfp!=NULL) {
+    fprintf(cv_mem->cv_errfp,"\n[%s %s]  %s\n",module,err_type,function);
+    fprintf(cv_mem->cv_errfp,"  %s\n\n",msg);
   }
 #endif
 
diff --git a/src/cvodes/cvodes_band.c b/src/cvodes/cvodes_band.c
deleted file mode 100644
index ba46f4f..0000000
--- a/src/cvodes/cvodes_band.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSBAND linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvodes/cvodes_band.h>
-#include "cvodes_direct_impl.h"
-#include "cvodes_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* CVSBAND linit, lsetup, lsolve, and lfree routines */
-static int cvBandInit(CVodeMem cv_mem);
-static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                       N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                       N_Vector vtemp2, N_Vector vtemp3);
-static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                       N_Vector ycur, N_Vector fcur);
-static int cvBandFree(CVodeMem cv_mem);
-
-/* CVSBAND lfreeB function */
-static int cvBandFreeB(CVodeBMem cvB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-
-/* Readability Replacements */
-
-#define lmm       (cv_mem->cv_lmm)
-#define f         (cv_mem->cv_f)
-#define nst       (cv_mem->cv_nst)
-#define tn        (cv_mem->cv_tn)
-#define h         (cv_mem->cv_h)
-#define gamma     (cv_mem->cv_gamma)
-#define gammap    (cv_mem->cv_gammap)
-#define gamrat    (cv_mem->cv_gamrat)
-#define ewt       (cv_mem->cv_ewt)
-#define nfe       (cv_mem->cv_nfe)
-#define linit     (cv_mem->cv_linit)
-#define lsetup    (cv_mem->cv_lsetup)
-#define lsolve    (cv_mem->cv_lsolve)
-#define lfree     (cv_mem->cv_lfree)
-#define lmem      (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define mtype      (cvdls_mem->d_type)
-#define n          (cvdls_mem->d_n)
-#define jacDQ      (cvdls_mem->d_jacDQ)
-#define jac        (cvdls_mem->d_bjac)
-#define M          (cvdls_mem->d_M)
-#define mu         (cvdls_mem->d_mu)
-#define ml         (cvdls_mem->d_ml)
-#define smu        (cvdls_mem->d_smu)
-#define lpivots    (cvdls_mem->d_lpivots)
-#define savedJ     (cvdls_mem->d_savedJ)
-#define nstlj      (cvdls_mem->d_nstlj)
-#define nje        (cvdls_mem->d_nje)
-#define nfeDQ      (cvdls_mem->d_nfeDQ)
-#define J_data     (cvdls_mem->d_J_data)
-#define last_flag  (cvdls_mem->d_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * CVBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module.  CVBand first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
- * to be cvBandInit, cvBandSetup, cvBandSolve, and cvBandFree,
- * respectively.  It allocates memory for a structure of type
- * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure.  It sets setupNonNull in (*cvode_mem) to be
- * TRUE, b_mu to be mupper, b_ml to be mlower, and the b_jac field to be 
- * CVBandDQJac.
- * Finally, it allocates memory for M, savedJ, and lpivots.  The CVBand
- * return value is SUCCESS = 0, LMEM_FAIL = -1, or LIN_ILL_INPUT = -2.
- *
- * NOTE: The band linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-                  
-int CVBand(void *cvode_mem, long int N, long int mupper, long int mlower)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSBAND", "CVBand", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSBAND", "CVBand", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */  
-  linit  = cvBandInit;
-  lsetup = cvBandSetup;
-  lsolve = cvBandSolve;
-  lfree  = cvBandFree;
-  
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-
-  /* Initialize Jacobian-related data */
-  jacDQ = TRUE;
-  jac = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-
-  cvDlsInitializeCounters(cvdls_mem);  
-
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = N;
-
-  /* Load half-bandwiths in cvdls_mem */
-  ml = mlower;
-  mu = mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSBAND", "CVBand", MSGD_BAD_SIZES);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = SUNMIN(N-1, mu + ml);
-
-  /* Allocate memory for M, savedJ, and pivot arrays */
-  M = NULL;
-  M = NewBandMat(N, mu, ml, smu);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NULL;
-  savedJ = NewBandMat(N, mu, ml, mu);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  lpivots = NULL;
-  lpivots = NewLintArray(N);
-  if (lpivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyMat(savedJ);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the band
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvBandInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  cvDlsInitializeCounters(cvdls_mem);  
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    jac = cvDlsBandDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the band linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy.  In any case, it constructs the Newton matrix 
- * M = I - gamma*J, updates counters, and calls the band LU 
- * factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int cvBandSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                       N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                       N_Vector vtemp2, N_Vector vtemp3)
-{
-  CVDlsMem cvdls_mem;
-  booleantype jbad, jok;
-  realtype dgamma;
-  int retval;
-  long int ier;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    BandCopy(savedJ, M, mu, ml);
-
-  } else {
-
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M); 
-
-    retval = jac(n, mu, ml, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSBAND", "cvBandSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    BandCopy(M, savedJ, mu, ml);
-
-  }
-  
-  /* Scale and add I to get M = I - gamma*J */
-  BandScale(-gamma, M);
-  AddIdentity(M);
-
-  /* Do LU factorization of M */
-  ier = BandGBTRF(M, lpivots);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  if (ier > 0) {
-    last_flag = ier;
-    return(1);
-  }
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandSolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the band linear solver
- * by calling the band backsolve routine.  The return value is 0.
- * -----------------------------------------------------------------
- */
-
-static int cvBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                       N_Vector ycur, N_Vector fcur)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  bd = N_VGetArrayPointer(b);
-
-  BandGBTRS(M, lpivots, bd);
-
-  /* If CV_BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvBandFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the band linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvBandFree(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  DestroyMat(M);
-  DestroyMat(savedJ);
-  DestroyArray(lpivots);
-  free(cvdls_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * CVBandB is a wrapper around CVBand. It attaches the CVSBAND linear solver
- * to the backward problem memory block.
- */
-
-int CVBandB(void *cvode_mem, int which,
-            long int nB, long int mupperB, long int mlowerB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVDlsMemB cvdlsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSBAND", "CVBandB", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSBAND", "CVBandB", MSGD_NO_ADJ);
-    return(CVDLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSBAND", "CVBandB", MSGCV_BAD_WHICH);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVDlsMemRecB */
-  cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB));
-  if (cvdlsB_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSBAND", "CVBandB", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* set matrix type */
-  cvdlsB_mem->d_typeB = SUNDIALS_BAND;
-
-  /* initialize Jacobian function */
-  cvdlsB_mem->d_bjacB = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvdlsB_mem;
-  cvB_mem->cv_lfree = cvBandFreeB;
-
-  flag = CVBand(cvodeB_mem, nB, mupperB, mlowerB);
-
-  if (flag != CVDLS_SUCCESS) {
-    free(cvdlsB_mem);
-    cvdlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * cvBandFreeB frees the memory associated with the CVSBAND linear
- * solver for backward integration.
- */
-
-static int cvBandFreeB(CVodeBMem cvB_mem)
-{
-  CVDlsMemB cvdlsB_mem;
-
-  cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
-
-  free(cvdlsB_mem);
-
-  return(0);
-}
-
diff --git a/src/cvodes/cvodes_bandpre.c b/src/cvodes/cvodes_bandpre.c
index 8b63137..386d0e5 100644
--- a/src/cvodes/cvodes_bandpre.c
+++ b/src/cvodes/cvodes_bandpre.c
@@ -1,23 +1,25 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This file contains implementations of the banded difference
  * quotient Jacobian-based preconditioner and solver routines for
- * use with the CVSPILS linear solvers.
+ * use with the CVSPILS linear solver interface.
  * -----------------------------------------------------------------
  */
 
@@ -27,11 +29,6 @@
 #include "cvodes_impl.h"
 #include "cvodes_bandpre_impl.h"
 #include "cvodes_spils_impl.h"
-
-#include <cvodes/cvodes_sptfqmr.h>
-#include <cvodes/cvodes_spbcgs.h>
-#include <cvodes/cvodes_spgmr.h>
-
 #include <sundials/sundials_math.h>
 
 #define MIN_INC_MULT RCONST(1000.0)
@@ -39,79 +36,71 @@
 #define ONE          RCONST(1.0)
 
 /* Prototypes of cvBandPrecSetup and cvBandPrecSolve */
-  
 static int cvBandPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                            booleantype jok, booleantype *jcurPtr, 
-                           realtype gamma, void *bp_data,
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
+                           realtype gamma, void *bp_data);
 static int cvBandPrecSolve(realtype t, N_Vector y, N_Vector fy, 
                            N_Vector r, N_Vector z, 
                            realtype gamma, realtype delta,
-                           int lr, void *bp_data, N_Vector tmp);
+                           int lr, void *bp_data);
 
 /* Prototype for cvBandPrecFree */
-
 static int cvBandPrecFree(CVodeMem cv_mem);
 
 /* Prototype for difference quotient Jacobian calculation routine */
-
-static int cvBandPrecDQJac(CVBandPrecData pdata, 
-                           realtype t, N_Vector y, N_Vector fy, 
-                           N_Vector ftemp, N_Vector ytemp);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Redability replacements */
-
-#define vec_tmpl (cv_mem->cv_tempv)
-
-/*
- * -----------------------------------------------------------------
- * Initialization, Free, and Get Functions
- * NOTE: The band linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVBandPrecInit will
- *       first test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml)
+static int cvBandPrecDQJac(CVBandPrecData pdata, realtype t, N_Vector y, 
+                           N_Vector fy, N_Vector ftemp, N_Vector ytemp);
+
+
+/*================================================================
+  PART I - Forward Problems
+  ================================================================*/
+
+/*-----------------------------------------------------------------
+  Initialization, Free, and Get Functions
+  NOTE: The band linear solver assumes a serial/OpenMP/Pthreads 
+        implementation of the NVECTOR package. Therefore, 
+        CVBandPrecInit will first test for a compatible N_Vector 
+        internal representation by checking that the function 
+        N_VGetArrayPointer exists.
+  -----------------------------------------------------------------*/
+int CVBandPrecInit(void *cvode_mem, sunindextype N,
+                   sunindextype mu, sunindextype ml)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBandPrecData pdata;
-  long int mup, mlp, storagemu;
+  sunindextype mup, mlp, storagemu;
   int flag;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been attached */
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecInit", MSGBP_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecInit", MSGBP_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  /* Test if the NVECTOR package is compatible with the BAND preconditioner */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE", "CVBandPrecInit", MSGBP_BAD_NVECTOR);
+  /* Test compatibility of NVECTOR package with the BAND preconditioner */
+  if(cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSBANDPRE",
+                   "CVBandPrecInit", MSGBP_BAD_NVECTOR);
     return(CVSPILS_ILL_INPUT);
   }
 
+  /* Allocate data memory */
   pdata = NULL;
-  pdata = (CVBandPrecData) malloc(sizeof *pdata);  /* Allocate data memory */
+  pdata = (CVBandPrecData) malloc(sizeof *pdata);
   if (pdata == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
@@ -126,90 +115,154 @@ int CVBandPrecInit(void *cvode_mem, long int N, long int mu, long int ml)
 
   /* Allocate memory for saved banded Jacobian approximation. */
   pdata->savedJ = NULL;
-  pdata->savedJ = NewBandMat(N, mup, mlp, mup);
+  pdata->savedJ = SUNBandMatrix(N, mup, mlp, mup);
   if (pdata->savedJ == NULL) {
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
-
   /* Allocate memory for banded preconditioner. */
   storagemu = SUNMIN(N-1, mup+mlp);
   pdata->savedP = NULL;
-  pdata->savedP = NewBandMat(N, mup, mlp, storagemu);
+  pdata->savedP = SUNBandMatrix(N, mup, mlp, storagemu);
   if (pdata->savedP == NULL) {
-    DestroyMat(pdata->savedJ);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
-  /* Allocate memory for pivot array. */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(N);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->savedP);
-    DestroyMat(pdata->savedJ);
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(cv_mem->cv_tempv, pdata->savedP);
+  if (pdata->LS == NULL) {
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBANDPRE", "CVBandPrecInit", MSGBP_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBANDPRE",
+                   "CVBandPrecInit", MSGBP_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
-  /* make sure s_P_data is free from any previous allocations */
-  if (cvspils_mem->s_pfree != NULL) {
-    cvspils_mem->s_pfree(cv_mem);
+  /* allocate memory for temporary N_Vectors */
+  pdata->tmp1 = NULL;
+  pdata->tmp1 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp1 == NULL) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBANDPRE", 
+                    "CVBandPrecInit", MSGBP_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp2 = NULL;
+  pdata->tmp2 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp2 == NULL) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    N_VDestroy(pdata->tmp1);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBANDPRE", 
+                    "CVBandPrecInit", MSGBP_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
   }
 
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    SUNLinSolFree(pdata->LS);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSBANDPRE", 
+                    "CVBandPrecInit", MSGBP_SUNLS_FAIL);
+    return(CVSPILS_SUNLS_FAIL);
+  }
+  
+  /* make sure P_data is free from any previous allocations */
+  if (cvspils_mem->pfree)
+    cvspils_mem->pfree(cv_mem);
+
   /* Point to the new P_data field in the SPILS memory */
-  cvspils_mem->s_P_data = pdata;
+  cvspils_mem->P_data = pdata;
 
   /* Attach the pfree function */
-  cvspils_mem->s_pfree = cvBandPrecFree;
+  cvspils_mem->pfree = cvBandPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = CVSpilsSetPreconditioner(cvode_mem, cvBandPrecSetup, cvBandPrecSolve);
-
+  flag = CVSpilsSetPreconditioner(cvode_mem,
+                                  cvBandPrecSetup,
+                                  cvBandPrecSolve);
   return(flag);
 }
 
-int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwBP, long int *leniwBP)
+
+int CVBandPrecGetWorkSpace(void *cvode_mem, long int *lenrwBP,
+                           long int *leniwBP)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBandPrecData pdata;
-  long int N, ml, mu, smu;
-
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
   
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecGetWorkSpace", MSGBP_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecGetWorkSpace", MSGBP_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetWorkSpace", MSGBP_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecGetWorkSpace", MSGBP_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBandPrecData) cvspils_mem->s_P_data;
-
-  N   = pdata->N;
-  mu  = pdata->mu;
-  ml  = pdata->ml;
-  smu = SUNMIN( N-1, mu + ml);
-
-  *leniwBP = pdata->N;
-  *lenrwBP = N * ( 2*ml + smu + mu + 2 );
+  pdata = (CVBandPrecData) cvspils_mem->P_data;
+
+  /* sum space requirements for all objects in pdata */
+  *leniwBP = 4;
+  *lenrwBP = 0;
+  if (cv_mem->cv_tempv->ops->nvspace) {
+    N_VSpace(cv_mem->cv_tempv, &lrw1, &liw1);
+    *leniwBP += 2*liw1;
+    *lenrwBP += 2*lrw1;
+  }
+  if (pdata->savedJ->ops->space) {
+    flag = SUNMatSpace(pdata->savedJ, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
+  if (pdata->savedP->ops->space) {
+    flag = SUNMatSpace(pdata->savedP, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    *leniwBP += liw;
+    *lenrwBP += lrw;
+  }
 
   return(CVSPILS_SUCCESS);
 }
 
+
 int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP)
 {
   CVodeMem cv_mem;
@@ -217,178 +270,181 @@ int CVBandPrecGetNumRhsEvals(void *cvode_mem, long int *nfevalsBP)
   CVBandPrecData pdata;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecGetNumRhsEvals", MSGBP_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecGetNumRhsEvals", MSGBP_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBANDPRE", "CVBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecGetNumRhsEvals", MSGBP_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBandPrecData) cvspils_mem->P_data;
 
   *nfevalsBP = pdata->nfeBP;
 
   return(CVSPILS_SUCCESS);
 }
 
-/* Readability Replacements */
-
-#define N       (pdata->N)
-#define mu      (pdata->mu)
-#define ml      (pdata->ml)
-#define lpivots (pdata->lpivots)
-#define savedJ  (pdata->savedJ)
-#define savedP  (pdata->savedP)
-#define nfeBP   (pdata->nfeBP)
-
-/*
- * -----------------------------------------------------------------
- * cvBandPrecSetup
- * -----------------------------------------------------------------
- * Together cvBandPrecSetup and cvBandPrecSolve use a banded
- * difference quotient Jacobian to create a preconditioner.
- * cvBandPrecSetup calculates a new J, if necessary, then
- * calculates P = I - gamma*J, and does an LU factorization of P.
- *
- * The parameters of cvBandPrecSetup are as follows:
- *
- * t       is the current value of the independent variable.
- *
- * y       is the current value of the dependent variable vector,
- *         namely the predicted value of y(t).
- *
- * fy      is the vector f(t,y).
- *
- * jok     is an input flag indicating whether Jacobian-related
- *         data needs to be recomputed, as follows:
- *           jok == FALSE means recompute Jacobian-related data
- *                  from scratch.
- *           jok == TRUE means that Jacobian data from the
- *                  previous PrecSetup call will be reused
- *                  (with the current value of gamma).
- *         A cvBandPrecSetup call with jok == TRUE should only
- *         occur after a call with jok == FALSE.
- *
- * *jcurPtr is a pointer to an output integer flag which is
- *          set by CVBandPrecond as follows:
- *            *jcurPtr = TRUE if Jacobian data was recomputed.
- *            *jcurPtr = FALSE if Jacobian data was not recomputed,
- *                       but saved data was reused.
- *
- * gamma   is the scalar appearing in the Newton matrix.
- *
- * bp_data is a pointer to preconditoner data (set by CVBandPrecInit)
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated
- *           for vectors of length N for work space. This
- *           routine uses only tmp1 and tmp2.
- *
- * The value to be returned by the cvBandPrecSetup function is
- *   0  if successful, or
- *   1  if the band factorization failed.
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  cvBandPrecSetup
+  -----------------------------------------------------------------
+  Together cvBandPrecSetup and cvBandPrecSolve use a banded
+  difference quotient Jacobian to create a preconditioner.
+  cvBandPrecSetup calculates a new J, if necessary, then
+  calculates P = I - gamma*J, and does an LU factorization of P.
+ 
+  The parameters of cvBandPrecSetup are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+          namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  jok     is an input flag indicating whether Jacobian-related
+          data needs to be recomputed, as follows:
+            jok == SUNFALSE means recompute Jacobian-related data
+                   from scratch.
+            jok == SUNTRUE means that Jacobian data from the
+                   previous PrecSetup call will be reused
+                   (with the current value of gamma).
+          A cvBandPrecSetup call with jok == SUNTRUE should only
+          occur after a call with jok == SUNFALSE.
+ 
+  *jcurPtr is a pointer to an output integer flag which is
+           set by cvBandPrecSetup as follows:
+             *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+             *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
+                        but saved data was reused.
+ 
+  gamma   is the scalar appearing in the Newton matrix.
+ 
+  bp_data is a pointer to preconditoner data (set by cvBandPrecInit)
+ 
+  The value to be returned by the cvBandPrecSetup function is
+    0  if successful, or
+    1  if the band factorization failed.
+  -----------------------------------------------------------------*/
 static int cvBandPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                            booleantype jok, booleantype *jcurPtr, 
-                           realtype gamma, void *bp_data,
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+                           realtype gamma, void *bp_data)
 {
   CVBandPrecData pdata;
   CVodeMem cv_mem;
   int retval;
-  long int ier;
+  sunindextype ier;
 
   /* Assume matrix and lpivots have already been allocated. */
   pdata = (CVBandPrecData) bp_data;
-
   cv_mem = (CVodeMem) pdata->cvode_mem;
 
   if (jok) {
 
-    /* If jok = TRUE, use saved copy of J. */
-    *jcurPtr = FALSE;
-    BandCopy(savedJ, savedP, mu, ml);
+    /* If jok = SUNTRUE, use saved copy of J. */
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "cvBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   } else {
 
-    /* If jok = FALSE, call cvBandPrecDQJac for new J value. */
-    *jcurPtr = TRUE;
-    SetToZero(savedJ);
+    /* If jok = SUNFALSE, call CVBandPDQJac for new J value. */
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(pdata->savedJ);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "cvBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    retval = cvBandPrecDQJac(pdata, t, y, fy, tmp1, tmp2);
+    retval = cvBandPrecDQJac(pdata, t, y, fy, 
+                             pdata->tmp1, pdata->tmp2);
     if (retval < 0) {
-      cvProcessError(cv_mem, -1, "CVBANDPRE", "cvBandPrecSetup", MSGBP_RHSFUNC_FAILED);
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "cvBandPrecSetup", MSGBP_RHSFUNC_FAILED);
       return(-1);
     }
     if (retval > 0) {
       return(1);
     }
 
-    BandCopy(savedJ, savedP, mu, ml);
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                     "cvBandPrecSetup", MSGBP_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   }
   
-  /* Scale and add I to get savedP = I - gamma*J. */
-  BandScale(-gamma, savedP);
-  AddIdentity(savedP);
- 
-  /* Do LU factorization of matrix. */
-  ier = BandGBTRF(savedP, lpivots);
- 
-  /* Return 0 if the LU was complete; otherwise return 1. */
-  if (ier > 0) return(1);
-  return(0);
+  /* Scale and add identity to get savedP = I - gamma*J. */
+  retval = SUNMatScaleAddI(-gamma, pdata->savedP);
+  if (retval) {
+    cvProcessError(cv_mem, -1, "CVBANDPRE", 
+                   "cvBandPrecSetup", MSGBP_SUNMAT_FAIL);
+    return(-1);
+  }
+
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->savedP);
+  return(ier);
 }
 
-/*
- * -----------------------------------------------------------------
- * cvBandPrecSolve
- * -----------------------------------------------------------------
- * cvBandPrecSolve solves a linear system P z = r, where P is the
- * matrix computed by CVBandPrecond.
- *
- * The parameters of cvBandPrecSolve used here are as follows:
- *
- * r       is the right-hand side vector of the linear system.
- *
- * bp_data is a pointer to preconditoner data (set by CVBandPrecInit)
- *
- * z       is the output vector computed by cvBandPrecSolve.
- *
- * The value returned by the cvBandPrecSolve function is always 0,
- * indicating success.
- * -----------------------------------------------------------------
- */ 
 
+/*-----------------------------------------------------------------
+  cvBandPrecSolve
+  -----------------------------------------------------------------
+  cvBandPrecSolve solves a linear system P z = r, where P is the
+  matrix computed by cvBandPrecond.
+ 
+  The parameters of cvBandPrecSolve used here are as follows:
+ 
+  r       is the right-hand side vector of the linear system.
+ 
+  bp_data is a pointer to preconditoner data (set by CVBandPrecInit)
+ 
+  z       is the output vector computed by cvBandPrecSolve.
+ 
+  The value returned by the cvBandPrecSolve function is always 0,
+  indicating success.
+  -----------------------------------------------------------------*/ 
 static int cvBandPrecSolve(realtype t, N_Vector y, N_Vector fy, 
-                           N_Vector r, N_Vector z, 
-                           realtype gamma, realtype delta,
-                           int lr, void *bp_data, N_Vector tmp)
+                           N_Vector r, N_Vector z, realtype gamma, 
+                           realtype delta, int lr, void *bp_data)
 {
   CVBandPrecData pdata;
-  realtype *zd;
+  int retval;
 
   /* Assume matrix and lpivots have already been allocated. */
   pdata = (CVBandPrecData) bp_data;
 
-  /* Copy r to z. */
-  N_VScale(ONE, r, z);
-
-  /* Do band backsolve on the vector z. */
-  zd = N_VGetArrayPointer(z);
-
-  BandGBTRS(savedP, lpivots, zd);
-
-  return(0);
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->savedP, z, r, ZERO);
+  return(retval);
 }
 
 
@@ -400,12 +456,14 @@ static int cvBandPrecFree(CVodeMem cv_mem)
   if (cv_mem->cv_lmem == NULL) return(0);
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
   
-  if (cvspils_mem->s_P_data == NULL) return(0);
-  pdata = (CVBandPrecData) cvspils_mem->s_P_data;
+  if (cvspils_mem->P_data == NULL) return(0);
+  pdata = (CVBandPrecData) cvspils_mem->P_data;
 
-  DestroyMat(savedJ);
-  DestroyMat(savedP);
-  DestroyArray(lpivots);
+  SUNLinSolFree(pdata->LS);
+  SUNMatDestroy(pdata->savedP);
+  SUNMatDestroy(pdata->savedJ);
+  N_VDestroy(pdata->tmp1);
+  N_VDestroy(pdata->tmp2);
 
   free(pdata);
   pdata = NULL;
@@ -414,39 +472,30 @@ static int cvBandPrecFree(CVodeMem cv_mem)
 }
 
 
-#define ewt       (cv_mem->cv_ewt)
-#define uround    (cv_mem->cv_uround)
-#define h         (cv_mem->cv_h)
-#define f         (cv_mem->cv_f)
-#define user_data (cv_mem->cv_user_data)
-
-/*
- * -----------------------------------------------------------------
- * cvBandPrecDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation to
- * the Jacobian of f(t,y). It assumes that a band matrix of type
- * BandMat is stored column-wise, and that elements within each column
- * are contiguous. This makes it possible to get the address of a column
- * of J via the macro BAND_COL and to write a simple for loop to set
- * each of the elements of a column in succession.
- * -----------------------------------------------------------------
- */
-
-static int cvBandPrecDQJac(CVBandPrecData pdata, 
-                           realtype t, N_Vector y, N_Vector fy, 
-                           N_Vector ftemp, N_Vector ytemp)
+/*-----------------------------------------------------------------
+  cvBandPrecDQJac
+  -----------------------------------------------------------------
+  This routine generates a banded difference quotient approximation 
+  to the Jacobian of f(t,y). It assumes that a band SUNMatrix is 
+  stored column-wise, and that elements within each column are 
+  contiguous. This makes it possible to get the address of a column
+  of J via the accessor function SUNBandMatrix_Column() and to 
+  write a simple for loop to set each of the elements of a column 
+  in succession.
+  -----------------------------------------------------------------*/
+static int cvBandPrecDQJac(CVBandPrecData pdata, realtype t, N_Vector y,
+                           N_Vector fy, N_Vector ftemp, N_Vector ytemp)
 {
   CVodeMem cv_mem;
   realtype fnorm, minInc, inc, inc_inv, srur;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
   int retval;
 
   cv_mem = (CVodeMem) pdata->cvode_mem;
 
   /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp. */
-  ewt_data   = N_VGetArrayPointer(ewt);
+  ewt_data   = N_VGetArrayPointer(cv_mem->cv_ewt);
   fy_data    = N_VGetArrayPointer(fy);
   ftemp_data = N_VGetArrayPointer(ftemp);
   y_data     = N_VGetArrayPointer(y);
@@ -456,62 +505,55 @@ static int cvBandPrecDQJac(CVBandPrecData pdata,
   N_VScale(ONE, y, ytemp);
 
   /* Set minimum increment based on uround and norm of f. */
-  srur = SUNRsqrt(uround);
-  fnorm = N_VWrmsNorm(fy, ewt);
+  srur = SUNRsqrt(cv_mem->cv_uround);
+  fnorm = N_VWrmsNorm(fy, cv_mem->cv_ewt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) * cv_mem->cv_uround * pdata->N * fnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing. */
-  width = ml + mu + 1;
-  ngroups = SUNMIN(width, N);
+  width = pdata->ml + pdata->mu + 1;
+  ngroups = SUNMIN(width, pdata->N);
   
   for (group = 1; group <= ngroups; group++) {
     
     /* Increment all y_j in group. */
-    for(j = group-1; j < N; j += width) {
+    for(j = group-1; j < pdata->N; j += width) {
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       ytemp_data[j] += inc;
     }
 
     /* Evaluate f with incremented y. */
-
-    retval = f(t, ytemp, ftemp, user_data);
-    nfeBP++;
+    retval = cv_mem->cv_f(t, ytemp, ftemp, cv_mem->cv_user_data);
+    pdata->nfeBP++;
     if (retval != 0) return(retval);
 
     /* Restore ytemp, then form and load difference quotients. */
-    for (j = group-1; j < N; j += width) {
+    for (j = group-1; j < pdata->N; j += width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(savedJ,j);
+      col_j = SUNBandMatrix_Column(pdata->savedJ,j);
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
-      i1 = SUNMAX(0, j-mu);
-      i2 = SUNMIN(j+ml, N-1);
+      i1 = SUNMAX(0, j-pdata->mu);
+      i2 = SUNMIN(j + pdata->ml, pdata->N - 1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) =
-          inc_inv * (ftemp_data[i] - fy_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
     }
   }
 
   return(0);
 }
 
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
 
-/*
- * CVBandPrecInitB, CVBPSp*B
- *
- * Wrappers for the backward phase around the corresponding 
- * CVODES functions
- */
+/*================================================================
+  PART II - Backward Problems
+  ================================================================*/
 
-int CVBandPrecInitB(void *cvode_mem, int which, long int nB, long int muB, long int mlB)
+/*---------------------------------------------------------------
+  User-Callable initialization function: wrapper for the backward
+  phase around the corresponding CVODES functions
+  ---------------------------------------------------------------*/
+int CVBandPrecInitB(void *cvode_mem, int which, sunindextype nB,
+                    sunindextype muB, sunindextype mlB)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -521,21 +563,24 @@ int CVBandPrecInitB(void *cvode_mem, int which, long int nB, long int muB, long
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBANDPRE", "CVBandPrecInitB", MSGBP_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBANDPRE",
+                   "CVBandPrecInitB", MSGBP_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVBANDPRE", "CVBandPrecInitB", MSGBP_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSBANDPRE",
+                   "CVBandPrecInitB", MSGBP_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBANDPRE", "CVBandPrecInitB", MSGBP_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSBANDPRE",
+                   "CVBandPrecInitB", MSGBP_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -543,15 +588,16 @@ int CVBandPrecInitB(void *cvode_mem, int which, long int nB, long int muB, long
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
-  cvB_mem->cv_pfree = NULL;
-
+  /* cv_mem corresponding to 'which' problem. */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
+  /* Set pfree */
+  cvB_mem->cv_pfree = NULL;
+ 
+  /* Initialize the band preconditioner for this backward problem. */
   flag = CVBandPrecInit(cvodeB_mem, nB, muB, mlB);
-
   return(flag);
 }
-
diff --git a/src/cvodes/cvodes_bandpre_impl.h b/src/cvodes/cvodes_bandpre_impl.h
index dd752c2..0b0155e 100644
--- a/src/cvodes/cvodes_bandpre_impl.h
+++ b/src/cvodes/cvodes_bandpre_impl.h
@@ -1,21 +1,23 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Implementation header file for the CVBANDPRE module.
+ * Implementation header file for the CVSBANDPRE module.
  * -----------------------------------------------------------------
  */
 
@@ -23,52 +25,49 @@
 #define _CVSBANDPRE_IMPL_H
 
 #include <cvodes/cvodes_bandpre.h>
-#include <sundials/sundials_band.h>
-#include <sundials/sundials_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * Type: CVBandPrecData
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type: CVBandPrecData
+  -----------------------------------------------------------------*/
 
 typedef struct CVBandPrecDataRec {
 
   /* Data set by user in CVBandPrecInit */
-
-  long int N;
-  long int ml, mu;
+  sunindextype N;
+  sunindextype ml, mu;
 
   /* Data set by CVBandPrecSetup */
-
-  DlsMat savedJ;
-  DlsMat savedP;
-  long int *lpivots;
+  SUNMatrix savedJ;
+  SUNMatrix savedP;
+  SUNLinearSolver LS;
+  N_Vector tmp1;
+  N_Vector tmp2;
 
   /* Rhs calls */
-
   long int nfeBP;
 
   /* Pointer to cvode_mem */
-
   void *cvode_mem;
 
 } *CVBandPrecData;
 
-/*
- * -----------------------------------------------------------------
- * CVBANDPRE error messages
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  CVBANDPRE error messages
+  -----------------------------------------------------------------*/
 
 #define MSGBP_MEM_NULL       "Integrator memory is NULL."
 #define MSGBP_LMEM_NULL      "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBP_MEM_FAIL       "A memory request failed."
 #define MSGBP_BAD_NVECTOR    "A required vector operation is not implemented."
+#define MSGBP_SUNMAT_FAIL    "An error arose from a SUNBandMatrix routine."
+#define MSGBP_SUNLS_FAIL     "An error arose from a SUNBandLinearSolver routine."
 #define MSGBP_PMEM_NULL      "Band preconditioner memory is NULL. CVBandPrecInit must be called."
 #define MSGBP_RHSFUNC_FAILED "The right-hand side routine failed in an unrecoverable manner."
 
diff --git a/src/cvodes/cvodes_bbdpre.c b/src/cvodes/cvodes_bbdpre.c
index 1d472ed..6ac051c 100644
--- a/src/cvodes/cvodes_bbdpre.c
+++ b/src/cvodes/cvodes_bbdpre.c
@@ -1,24 +1,26 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This file contains implementations of routines for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with CVODE, a CVSPILS linear
- * solver, and the parallel implementation of NVECTOR.
+ * matrix with banded blocks, for use with CVODE, the CVSPILS linear
+ * solver interface, and the MPI-parallel implementation of NVECTOR.
  * -----------------------------------------------------------------
  */
 
@@ -28,91 +30,79 @@
 #include "cvodes_impl.h"
 #include "cvodes_bbdpre_impl.h"
 #include "cvodes_spils_impl.h"
-
-#include <cvodes/cvodes_sptfqmr.h>
-#include <cvodes/cvodes_spbcgs.h>
-#include <cvodes/cvodes_spgmr.h>
-
 #include <sundials/sundials_math.h>
+#include <nvector/nvector_serial.h>
 
 #define MIN_INC_MULT RCONST(1000.0)
-
 #define ZERO         RCONST(0.0)
 #define ONE          RCONST(1.0)
 
 /* Prototypes of functions cvBBDPrecSetup and cvBBDPrecSolve */
 static int cvBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                           booleantype jok, booleantype *jcurPtr, 
-                          realtype gamma, void *bbd_data, 
-                          N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+                          realtype gamma, void *bbd_data);
 static int cvBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, 
                           N_Vector r, N_Vector z, 
                           realtype gamma, realtype delta,
-                          int lr, void *bbd_data, N_Vector tmp);
+                          int lr, void *bbd_data);
 
 /* Prototype for cvBBDPrecFree */
 static int cvBBDPrecFree(CVodeMem cv_mem);
 
 /* Wrapper functions for adjoint code */
-static int cvGlocWrapper(long int NlocalB, realtype t, N_Vector yB, N_Vector gB, 
+static int cvGlocWrapper(sunindextype NlocalB, realtype t,
+                         N_Vector yB, N_Vector gB, 
                          void *cvadj_mem);
-static int cvCfnWrapper(long int NlocalB, realtype t, N_Vector yB, void *cvadj_mem);
+static int cvCfnWrapper(sunindextype NlocalB, realtype t,
+                        N_Vector yB, void *cvadj_mem);
 
 /* Prototype for difference quotient Jacobian calculation routine */
 static int cvBBDDQJac(CVBBDPrecData pdata, realtype t, 
                       N_Vector y, N_Vector gy, 
                       N_Vector ytemp, N_Vector gtemp);
 
-/* Prototype for the pfree routine */
+/* Prototype for the backward pfree routine */
 static int CVBBDPrecFreeB(CVodeBMem cvB_mem);
 
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
 
-/* Redability replacements */
+/*================================================================
+  PART I - forward problems
+  ================================================================*/
 
-#define uround   (cv_mem->cv_uround)
-#define vec_tmpl (cv_mem->cv_tempv)
-
-/*
- * -----------------------------------------------------------------
- * User-Callable Functions: initialization, reinit and free
- * -----------------------------------------------------------------
- */
-
-int CVBBDPrecInit(void *cvode_mem, long int Nlocal, 
-                  long int mudq, long int mldq,
-                  long int mukeep, long int mlkeep, 
-                  realtype dqrely, 
-                  CVLocalFn gloc, CVCommFn cfn)
+/*-----------------------------------------------------------------
+  User-Callable Functions: initialization, reinit and free
+  -----------------------------------------------------------------*/
+int CVBBDPrecInit(void *cvode_mem, sunindextype Nlocal, 
+                  sunindextype mudq, sunindextype mldq,
+                  sunindextype mukeep, sunindextype mlkeep, 
+                  realtype dqrely, CVLocalFn gloc, CVCommFn cfn)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
-  long int muk, mlk, storage_mu;
+  sunindextype muk, mlk, storage_mu, lrw1, liw1;
+  long int lrw, liw;
   int flag;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the CVSPILS linear solver interface has been created */
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  /* Test if the NVECTOR package is compatible with the BLOCK BAND preconditioner */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_BAD_NVECTOR);
+  /* Test compatibility of NVECTOR package with the BBD preconditioner */
+  if(cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_BAD_NVECTOR);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -120,7 +110,8 @@ int CVBBDPrecInit(void *cvode_mem, long int Nlocal,
   pdata = NULL;
   pdata = (CVBBDPrecData) malloc(sizeof *pdata);  
   if (pdata == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
@@ -136,91 +127,207 @@ int CVBBDPrecInit(void *cvode_mem, long int Nlocal,
   pdata->mlkeep = mlk;
 
   /* Allocate memory for saved Jacobian */
-  pdata->savedJ = NewBandMat(Nlocal, muk, mlk, muk);
+  pdata->savedJ = SUNBandMatrix(Nlocal, muk, mlk, muk);
   if (pdata->savedJ == NULL) { 
     free(pdata); pdata = NULL; 
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL); 
   }
 
   /* Allocate memory for preconditioner matrix */
   storage_mu = SUNMIN(Nlocal-1, muk + mlk);
   pdata->savedP = NULL;
-  pdata->savedP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+  pdata->savedP = SUNBandMatrix(Nlocal, muk, mlk, storage_mu);
   if (pdata->savedP == NULL) {
-    DestroyMat(pdata->savedJ);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE",
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  
+  /* Allocate memory for temporary N_Vectors */
+  pdata->zlocal = NULL;
+  pdata->zlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->zlocal == NULL) {
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
-  /* Allocate memory for lpivots */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(Nlocal);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->savedP);
-    DestroyMat(pdata->savedJ);
+  pdata->rlocal = NULL;
+  pdata->rlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->rlocal == NULL) {
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
     free(pdata); pdata = NULL;
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp1 = NULL;
+  pdata->tmp1 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp1 == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp2 = NULL;
+  pdata->tmp2 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp2 == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+  pdata->tmp3 = NULL;
+  pdata->tmp3 = N_VClone(cv_mem->cv_tempv);
+  if (pdata->tmp3 == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(pdata->rlocal, pdata->savedP);
+  if (pdata->LS == NULL) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->tmp3);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    N_VDestroy(pdata->tmp1);
+    N_VDestroy(pdata->tmp2);
+    N_VDestroy(pdata->tmp3);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->savedP);
+    SUNMatDestroy(pdata->savedJ);
+    SUNLinSolFree(pdata->LS);
+    free(pdata); pdata = NULL;
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSBBDPRE", 
+                   "CVBBDPrecInit", MSGBBD_SUNLS_FAIL);
+    return(CVSPILS_SUNLS_FAIL);
+  }
+
   /* Set pdata->dqrely based on input dqrely (0 implies default). */
-  pdata->dqrely = (dqrely > ZERO) ? dqrely : SUNRsqrt(uround);
+  pdata->dqrely = (dqrely > ZERO) ?
+    dqrely : SUNRsqrt(cv_mem->cv_uround);
 
   /* Store Nlocal to be used in CVBBDPrecSetup */
   pdata->n_local = Nlocal;
 
   /* Set work space sizes and initialize nge */
-  pdata->rpwsize = Nlocal*(muk + 2*mlk + storage_mu + 2);
-  pdata->ipwsize = Nlocal;
+  pdata->rpwsize = 0;
+  pdata->ipwsize = 0;
+  if (cv_mem->cv_tempv->ops->nvspace) {
+    N_VSpace(cv_mem->cv_tempv, &lrw1, &liw1);
+    pdata->rpwsize += 3*lrw1;
+    pdata->ipwsize += 3*liw1;
+  }
+  if (pdata->rlocal->ops->nvspace) {
+    N_VSpace(pdata->rlocal, &lrw1, &liw1);
+    pdata->rpwsize += 2*lrw1;
+    pdata->ipwsize += 2*liw1;
+  }
+  if (pdata->savedJ->ops->space) {
+    flag = SUNMatSpace(pdata->savedJ, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->savedP->ops->space) {
+    flag = SUNMatSpace(pdata->savedP, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
   pdata->nge = 0;
 
   /* make sure s_P_data is free from any previous allocations */
-  if (cvspils_mem->s_pfree != NULL) {
-    cvspils_mem->s_pfree(cv_mem);
-  }
+  if (cvspils_mem->pfree)
+    cvspils_mem->pfree(cv_mem);
 
   /* Point to the new P_data field in the SPILS memory */
-  cvspils_mem->s_P_data = pdata;
+  cvspils_mem->P_data = pdata;
 
   /* Attach the pfree function */
-  cvspils_mem->s_pfree = cvBBDPrecFree;
+  cvspils_mem->pfree = cvBBDPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = CVSpilsSetPreconditioner(cvode_mem, cvBBDPrecSetup, cvBBDPrecSolve);
-
+  flag = CVSpilsSetPreconditioner(cvode_mem,
+                                  cvBBDPrecSetup,
+                                  cvBBDPrecSolve);
   return(flag);
 }
 
 
-int CVBBDPrecReInit(void *cvode_mem, 
-                    long int mudq, long int mldq, 
-                    realtype dqrely)
+int CVBBDPrecReInit(void *cvode_mem, sunindextype mudq, 
+                    sunindextype mldq, realtype dqrely)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
-  long int Nlocal;
+  sunindextype Nlocal;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecReInit", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecReInit", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
   /* Test if the preconditioner data is non-NULL */
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecReInit", MSGBBD_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecReInit", MSGBBD_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
 
   /* Load half-bandwidths */
   Nlocal = pdata->n_local;
@@ -228,7 +335,8 @@ int CVBBDPrecReInit(void *cvode_mem,
   pdata->mldq = SUNMIN(Nlocal-1, SUNMAX(0,mldq));
 
   /* Set pdata->dqrely based on input dqrely (0 implies default). */
-  pdata->dqrely = (dqrely > ZERO) ? dqrely : SUNRsqrt(uround);
+  pdata->dqrely = (dqrely > ZERO) ?
+    dqrely : SUNRsqrt(cv_mem->cv_uround);
 
   /* Re-initialize nge */
   pdata->nge = 0;
@@ -236,29 +344,35 @@ int CVBBDPrecReInit(void *cvode_mem,
   return(CVSPILS_SUCCESS);
 }
 
-int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwBBDP, long int *leniwBBDP)
+
+int CVBBDPrecGetWorkSpace(void *cvode_mem,
+                          long int *lenrwBBDP,
+                          long int *leniwBBDP)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
 
   *lenrwBBDP = pdata->rpwsize;
   *leniwBBDP = pdata->ipwsize;
@@ -266,194 +380,205 @@ int CVBBDPrecGetWorkSpace(void *cvode_mem, long int *lenrwBBDP, long int *leniwB
   return(CVSPILS_SUCCESS);
 }
 
-int CVBBDPrecGetNumGfnEvals(void *cvode_mem, long int *ngevalsBBDP)
+
+int CVBBDPrecGetNumGfnEvals(void *cvode_mem,
+                            long int *ngevalsBBDP)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   CVBBDPrecData pdata;
 
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (cvspils_mem->s_P_data == NULL) {
-    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVBBDPRE", "CVBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
+  if (cvspils_mem->P_data == NULL) {
+    cvProcessError(cv_mem, CVSPILS_PMEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
     return(CVSPILS_PMEM_NULL);
   } 
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
 
   *ngevalsBBDP = pdata->nge;
 
   return(CVSPILS_SUCCESS);
 }
 
-/* Readability Replacements */
-
-#define Nlocal  (pdata->n_local)
-#define mudq    (pdata->mudq)
-#define mldq    (pdata->mldq)
-#define mukeep  (pdata->mukeep)
-#define mlkeep  (pdata->mlkeep)
-#define dqrely  (pdata->dqrely)
-#define gloc    (pdata->gloc)
-#define cfn     (pdata->cfn)
-#define savedJ  (pdata->savedJ)
-#define savedP  (pdata->savedP)
-#define lpivots (pdata->lpivots)
-#define nge     (pdata->nge)
-
-/*
- * -----------------------------------------------------------------
- * Function : cvBBDPrecSetup                                      
- * -----------------------------------------------------------------
- * cvBBDPrecSetup generates and factors a banded block of the
- * preconditioner matrix on each processor, via calls to the
- * user-supplied gloc and cfn functions. It uses difference
- * quotient approximations to the Jacobian elements.
- *
- * cvBBDPrecSetup calculates a new J,if necessary, then calculates
- * P = I - gamma*J, and does an LU factorization of P.
- *
- * The parameters of cvBBDPrecSetup used here are as follows:
- *
- * t       is the current value of the independent variable.
- *
- * y       is the current value of the dependent variable vector,
- *         namely the predicted value of y(t).
- *
- * fy      is the vector f(t,y).
- *
- * jok     is an input flag indicating whether Jacobian-related
- *         data needs to be recomputed, as follows:
- *           jok == FALSE means recompute Jacobian-related data
- *                  from scratch.
- *           jok == TRUE  means that Jacobian data from the
- *                  previous CVBBDPrecon call can be reused
- *                  (with the current value of gamma).
- *         A CVBBDPrecon call with jok == TRUE should only occur
- *         after a call with jok == FALSE.
- *
- * jcurPtr is a pointer to an output integer flag which is
- *         set by CVBBDPrecon as follows:
- *           *jcurPtr = TRUE if Jacobian data was recomputed.
- *           *jcurPtr = FALSE if Jacobian data was not recomputed,
- *                      but saved data was reused.
- *
- * gamma   is the scalar appearing in the Newton matrix.
- *
- * bbd_data is a pointer to the preconditioner data set by
- *          CVBBDPrecInit
- *
- * tmp1, tmp2, and tmp3 are pointers to memory allocated
- *           for NVectors which are be used by cvBBDPrecSetup
- *           as temporary storage or work space.
- *
- * Return value:
- * The value returned by this cvBBDPrecSetup function is the int
- *   0  if successful,
- *   1  for a recoverable error (step will be retried).
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  Function : cvBBDPrecSetup                                      
+  -----------------------------------------------------------------
+  cvBBDPrecSetup generates and factors a banded block of the
+  preconditioner matrix on each processor, via calls to the
+  user-supplied gloc and cfn functions. It uses difference
+  quotient approximations to the Jacobian elements.
+ 
+  cvBBDPrecSetup calculates a new J,if necessary, then calculates
+  P = I - gamma*J, and does an LU factorization of P.
+ 
+  The parameters of cvBBDPrecSetup used here are as follows:
+ 
+  t       is the current value of the independent variable.
+ 
+  y       is the current value of the dependent variable vector,
+          namely the predicted value of y(t).
+ 
+  fy      is the vector f(t,y).
+ 
+  jok     is an input flag indicating whether Jacobian-related
+          data needs to be recomputed, as follows:
+            jok == SUNFALSE means recompute Jacobian-related data
+                   from scratch.
+            jok == SUNTRUE  means that Jacobian data from the
+                   previous CVBBDPrecon call can be reused
+                   (with the current value of gamma).
+          A cvBBDPrecSetup call with jok == SUNTRUE should only occur
+          after a call with jok == SUNFALSE.
+ 
+  jcurPtr is a pointer to an output integer flag which is
+          set by cvBBDPrecSetup as follows:
+            *jcurPtr = SUNTRUE if Jacobian data was recomputed.
+            *jcurPtr = SUNFALSE if Jacobian data was not recomputed,
+                       but saved data was reused.
+ 
+  gamma   is the scalar appearing in the Newton matrix.
+ 
+  bbd_data is a pointer to the preconditioner data set by
+           CVBBDPrecInit
+ 
+  Return value:
+  The value returned by this cvBBDPrecSetup function is the int
+    0  if successful,
+    1  for a recoverable error (step will be retried).
+  -----------------------------------------------------------------*/
 static int cvBBDPrecSetup(realtype t, N_Vector y, N_Vector fy, 
                           booleantype jok, booleantype *jcurPtr, 
-                          realtype gamma, void *bbd_data, 
-                          N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+                          realtype gamma, void *bbd_data)
 {
+  sunindextype ier;
   CVBBDPrecData pdata;
   CVodeMem cv_mem;
   int retval;
-  long int ier;
 
   pdata = (CVBBDPrecData) bbd_data;
-
   cv_mem = (CVodeMem) pdata->cvode_mem;
 
+  /* If jok = SUNTRUE, use saved copy of J */
   if (jok) {
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                     "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    BandCopy(savedJ, savedP, mukeep, mlkeep);
-
+  /* Otherwise call cvBBDDQJac for new J value */
   } else {
 
-    /* Otherwise call cvBBDDQJac for new J value */
-    *jcurPtr = TRUE;
-    SetToZero(savedJ);
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(pdata->savedJ);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                     "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
-    retval = cvBBDDQJac(pdata, t, y, tmp1, tmp2, tmp3);
+    retval = cvBBDDQJac(pdata, t, y, pdata->tmp1, 
+                        pdata->tmp2, pdata->tmp3);
     if (retval < 0) {
-      cvProcessError(cv_mem, -1, "CVBBDPRE", "cvBBDPrecSetup", MSGBBD_FUNC_FAILED);
+      cvProcessError(cv_mem, -1, "CVBBDPRE", "CVBBDPrecSetup", 
+                     MSGBBD_FUNC_FAILED);
       return(-1);
     }
     if (retval > 0) {
       return(1);
     }
 
-    BandCopy(savedJ, savedP, mukeep, mlkeep);
+    retval = SUNMatCopy(pdata->savedJ, pdata->savedP);
+    if (retval < 0) {
+      cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                     "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+      return(-1);
+    }
+    if (retval > 0) {
+      return(1);
+    }
 
   }
   
   /* Scale and add I to get P = I - gamma*J */
-  BandScale(-gamma, savedP);
-  AddIdentity(savedP);
- 
-  /* Do LU factorization of P in place */
-  ier = BandGBTRF(savedP, lpivots);
+  retval = SUNMatScaleAddI(-gamma, pdata->savedP);
+  if (retval) {
+    cvProcessError(cv_mem, -1, "CVBBDPRE", 
+                   "CVBBDPrecSetup", MSGBBD_SUNMAT_FAIL);
+    return(-1);
+  }
  
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  if (ier > 0) return(1);
-  return(0);
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->savedP);
+  return(ier);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : cvBBDPrecSolve
- * -----------------------------------------------------------------
- * cvBBDPrecSolve solves a linear system P z = r, with the
- * band-block-diagonal preconditioner matrix P generated and
- * factored by cvBBDPrecSetup.
- *
- * The parameters of cvBBDPrecSolve used here are as follows:
- *
- * r is the right-hand side vector of the linear system.
- *
- * bbd_data is a pointer to the preconditioner data set by
- *   CVBBDPrecInit.
- *
- * z is the output vector computed by cvBBDPrecSolve.
- *
- * The value returned by the cvBBDPrecSolve function is always 0,
- * indicating success.
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  Function : cvBBDPrecSolve
+  -----------------------------------------------------------------
+  cvBBDPrecSolve solves a linear system P z = r, with the
+  band-block-diagonal preconditioner matrix P generated and
+  factored by cvBBDPrecSetup.
+ 
+  The parameters of cvBBDPrecSolve used here are as follows:
+ 
+  r is the right-hand side vector of the linear system.
+ 
+  bbd_data is a pointer to the preconditioner data set by
+    CVBBDPrecInit.
+ 
+  z is the output vector computed by cvBBDPrecSolve.
+ 
+  The value returned by the cvBBDPrecSolve function is always 0,
+  indicating success.
+  -----------------------------------------------------------------*/
 static int cvBBDPrecSolve(realtype t, N_Vector y, N_Vector fy, 
                           N_Vector r, N_Vector z, 
                           realtype gamma, realtype delta,
-                          int lr, void *bbd_data, N_Vector tmp)
+                          int lr, void *bbd_data)
 {
+  int retval;
   CVBBDPrecData pdata;
-  realtype *zd;
 
   pdata = (CVBBDPrecData) bbd_data;
 
-  /* Copy r to z, then do backsolve and return */
-  N_VScale(ONE, r, z);
+  /* Attach local data arrays for r and z to rlocal and zlocal */
+  N_VSetArrayPointer(N_VGetArrayPointer(r), pdata->rlocal);
+  N_VSetArrayPointer(N_VGetArrayPointer(z), pdata->zlocal);
   
-  zd = N_VGetArrayPointer(z);
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->savedP, pdata->zlocal, 
+                          pdata->rlocal, ZERO);
 
-  BandGBTRS(savedP, lpivots, zd);
+  /* Detach local data arrays from rlocal and zlocal */
+  N_VSetArrayPointer(NULL, pdata->rlocal);
+  N_VSetArrayPointer(NULL, pdata->zlocal);
 
-  return(0);
+  return(retval);
 }
 
 
@@ -465,12 +590,17 @@ static int cvBBDPrecFree(CVodeMem cv_mem)
   if (cv_mem->cv_lmem == NULL) return(0);
   cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
   
-  if (cvspils_mem->s_P_data == NULL) return(0);
-  pdata = (CVBBDPrecData) cvspils_mem->s_P_data;
-
-  DestroyMat(savedJ);
-  DestroyMat(savedP);
-  DestroyArray(lpivots);
+  if (cvspils_mem->P_data == NULL) return(0);
+  pdata = (CVBBDPrecData) cvspils_mem->P_data;
+
+  SUNLinSolFree(pdata->LS);
+  N_VDestroy(pdata->tmp1);
+  N_VDestroy(pdata->tmp2);
+  N_VDestroy(pdata->tmp3);
+  N_VDestroy(pdata->zlocal);
+  N_VDestroy(pdata->rlocal);
+  SUNMatDestroy(pdata->savedP);
+  SUNMatDestroy(pdata->savedJ);
 
   free(pdata);
   pdata = NULL;
@@ -479,35 +609,26 @@ static int cvBBDPrecFree(CVodeMem cv_mem)
 }
 
 
-
-#define ewt       (cv_mem->cv_ewt)
-#define h         (cv_mem->cv_h)
-#define user_data (cv_mem->cv_user_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : cvBBDDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation
- * to the local block of the Jacobian of g(t,y). It assumes that a
- * band matrix of type BandMat is stored columnwise, and that elements
- * within each column are contiguous. All matrix elements are generated
- * as difference quotients, by way of calls to the user routine gloc.
- * By virtue of the band structure, the number of these calls is
- * bandwidth + 1, where bandwidth = mldq + mudq + 1.
- * But the band matrix kept has bandwidth = mlkeep + mukeep + 1.
- * This routine also assumes that the local elements of a vector are
- * stored contiguously.
- * -----------------------------------------------------------------
- */
-
-static int cvBBDDQJac(CVBBDPrecData pdata, realtype t, 
-                      N_Vector y, N_Vector gy, 
-                      N_Vector ytemp, N_Vector gtemp)
+/*-----------------------------------------------------------------
+  Function : cvBBDDQJac
+  -----------------------------------------------------------------
+  This routine generates a banded difference quotient approximation
+  to the local block of the Jacobian of g(t,y). It assumes that a
+  band SUNMatrix is stored columnwise, and that elements within each 
+  column are contiguous. All matrix elements are generated as 
+  difference quotients, by way of calls to the user routine gloc.
+  By virtue of the band structure, the number of these calls is
+  bandwidth + 1, where bandwidth = mldq + mudq + 1.
+  But the band matrix kept has bandwidth = mlkeep + mukeep + 1.
+  This routine also assumes that the local elements of a vector are
+  stored contiguously.
+  -----------------------------------------------------------------*/
+static int cvBBDDQJac(CVBBDPrecData pdata, realtype t, N_Vector y, 
+                      N_Vector gy, N_Vector ytemp, N_Vector gtemp)
 {
   CVodeMem cv_mem;
   realtype gnorm, minInc, inc, inc_inv;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *y_data, *ewt_data, *gy_data, *gtemp_data, *ytemp_data, *col_j;
   int retval;
 
@@ -517,55 +638,58 @@ static int cvBBDDQJac(CVBBDPrecData pdata, realtype t,
   N_VScale(ONE, y, ytemp);
 
   /* Call cfn and gloc to get base value of g(t,y) */
-  if (cfn != NULL) {
-    retval = cfn(Nlocal, t, y, user_data);
+  if (pdata->cfn != NULL) {
+    retval = pdata->cfn(pdata->n_local, t, y, cv_mem->cv_user_data);
     if (retval != 0) return(retval);
   }
 
-  retval = gloc(Nlocal, t, ytemp, gy, user_data);
-  nge++;
+  retval = pdata->gloc(pdata->n_local, t, ytemp, gy,
+                       cv_mem->cv_user_data);
+  pdata->nge++;
   if (retval != 0) return(retval);
 
   /* Obtain pointers to the data for various vectors */
   y_data     =  N_VGetArrayPointer(y);
   gy_data    =  N_VGetArrayPointer(gy);
-  ewt_data   =  N_VGetArrayPointer(ewt);
+  ewt_data   =  N_VGetArrayPointer(cv_mem->cv_ewt);
   ytemp_data =  N_VGetArrayPointer(ytemp);
   gtemp_data =  N_VGetArrayPointer(gtemp);
 
   /* Set minimum increment based on uround and norm of g */
-  gnorm = N_VWrmsNorm(gy, ewt);
+  gnorm = N_VWrmsNorm(gy, cv_mem->cv_ewt);
   minInc = (gnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * Nlocal * gnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) *
+     cv_mem->cv_uround * pdata->n_local * gnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing */
-  width = mldq + mudq + 1;
-  ngroups = SUNMIN(width, Nlocal);
+  width = pdata->mldq + pdata->mudq + 1;
+  ngroups = SUNMIN(width, pdata->n_local);
 
   /* Loop over groups */  
   for (group=1; group <= ngroups; group++) {
     
     /* Increment all y_j in group */
-    for(j=group-1; j < Nlocal; j+=width) {
-      inc = SUNMAX(dqrely*SUNRabs(y_data[j]), minInc/ewt_data[j]);
+    for(j=group-1; j < pdata->n_local; j+=width) {
+      inc = SUNMAX(pdata->dqrely * SUNRabs(y_data[j]), minInc/ewt_data[j]);
       ytemp_data[j] += inc;
     }
 
     /* Evaluate g with incremented y */
-    retval = gloc(Nlocal, t, ytemp, gtemp, user_data);
-    nge++;
+    retval = pdata->gloc(pdata->n_local, t, ytemp, gtemp,
+                         cv_mem->cv_user_data);
+    pdata->nge++;
     if (retval != 0) return(retval);
 
     /* Restore ytemp, then form and load difference quotients */
-    for (j=group-1; j < Nlocal; j+=width) {
+    for (j=group-1; j < pdata->n_local; j+=width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(savedJ,j);
-      inc = SUNMAX(dqrely*SUNRabs(y_data[j]), minInc/ewt_data[j]);
+      col_j = SUNBandMatrix_Column(pdata->savedJ,j);
+      inc = SUNMAX(pdata->dqrely * SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
-      i1 = SUNMAX(0, j-mukeep);
-      i2 = SUNMIN(j+mlkeep, Nlocal-1);
+      i1 = SUNMAX(0, j-pdata->mukeep);
+      i2 = SUNMIN(j + pdata->mlkeep, pdata->n_local-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) =
+        SM_COLUMN_ELEMENT_B(col_j,i,j) =
           inc_inv * (gtemp_data[i] - gy_data[i]);
     }
   }
@@ -574,60 +698,45 @@ static int cvBBDDQJac(CVBBDPrecData pdata, realtype t,
 }
 
 
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-
-/* Additional readability replacements */
-
-#define ytmp  (ca_mem->ca_ytmp)
-#define yStmp (ca_mem->ca_yStmp)
-#define IMget (ca_mem->ca_IMget)
-
-#define gloc_B     (cvbbdB_mem->glocB)
-#define cfn_B      (cvbbdB_mem->cfnB)
-
-/*
- * CVBBDPrecInitB, CVBPSp*B
- *
- * Wrappers for the backward phase around the corresponding CVODES functions
- */
+/*================================================================
+  PART II - Backward Problems
+  ================================================================*/
 
-int CVBBDPrecInitB(void *cvode_mem, int which, long int NlocalB, 
-                   long int mudqB, long int mldqB,
-                   long int mukeepB, long int mlkeepB, 
-                   realtype dqrelyB,
-                   CVLocalFnB glocB, CVCommFnB cfnB)
+/*---------------------------------------------------------------
+  User-Callable Functions: initialization, reinit and free
+  ---------------------------------------------------------------*/
+int CVBBDPrecInitB(void *cvode_mem, int which, sunindextype NlocalB, 
+                   sunindextype mudqB, sunindextype mldqB,
+                   sunindextype mukeepB, sunindextype mlkeepB, 
+                   realtype dqrelyB, CVLocalFnB glocB, CVCommFnB cfnB)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
   CVodeBMem cvB_mem;
-  void *cvodeB_mem;
   CVBBDPrecDataB cvbbdB_mem;
+  void *cvodeB_mem;
   int flag;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecInitB", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSBBDPRE",
+                   "CVBBDPrecInitB", MSGBBD_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSBBDPRE",
+                   "CVBBDPrecInitB", MSGBBD_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -635,43 +744,41 @@ int CVBBDPrecInitB(void *cvode_mem, int which, long int NlocalB,
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
+  /* cv_mem corresponding to 'which' problem. */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
-  /* Initialize the BBD preconditioner */
-  flag = CVBBDPrecInit(cvodeB_mem, NlocalB, 
-                       mudqB, mldqB,
-                       mukeepB, mlkeepB, 
-                       dqrelyB, 
-                       cvGlocWrapper, cvCfnWrapper);
-
+  /* Initialize the BBD preconditioner for this backward problem. */
+  flag = CVBBDPrecInit(cvodeB_mem, NlocalB, mudqB, mldqB, mukeepB, 
+                       mlkeepB, dqrelyB, cvGlocWrapper, cvCfnWrapper);
   if (flag != CV_SUCCESS) return(flag);
 
-
-  /* Get memory for CVBBDPrecDataB to store the user-provided
-   * functions which will be called from the wrappers */
+  /* Allocate memory for CVBBDPrecDataB to store the user-provided
+     functions which will be called from the wrappers */
   cvbbdB_mem = NULL;
   cvbbdB_mem = (CVBBDPrecDataB) malloc(sizeof(* cvbbdB_mem));
   if (cvbbdB_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVBBDPRE", "CVBBDPrecInitB", MSGBBD_MEM_FAIL);
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSBBDPRE",
+                   "CVBBDPrecInitB", MSGBBD_MEM_FAIL);
     return(CVSPILS_MEM_FAIL);
   }
 
-  gloc_B = glocB;
-  cfn_B  = cfnB;
+  /* set pointers to user-provided functions */
+  cvbbdB_mem->glocB = glocB;
+  cvbbdB_mem->cfnB  = cfnB;
 
-  /* attach pmem and pfree */
-  cvB_mem->cv_pmem = cvbbdB_mem;
+  /* Attach pmem and pfree */
+  cvB_mem->cv_pmem  = cvbbdB_mem;
   cvB_mem->cv_pfree = CVBBDPrecFreeB;
 
   return(CVSPILS_SUCCESS);
 }
 
-int CVBBDPrecReInitB(void *cvode_mem, int which, 
-                     long int mudqB, long int mldqB,
-                     realtype dqrelyB)
+
+int CVBBDPrecReInitB(void *cvode_mem, int which, sunindextype mudqB, 
+                     sunindextype mldqB, realtype dqrelyB)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -681,21 +788,24 @@ int CVBBDPrecReInitB(void *cvode_mem, int which,
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVBBDPRE", "CVBBDPrecReInitB", MSGBBD_MEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSBBDPRE",
+                   "CVBBDPrecReInitB", MSGBBD_MEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVBBDPRE", "CVBBDPrecReInitB", MSGBBD_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSBBDPRE",
+                   "CVBBDPrecReInitB", MSGBBD_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVBBDPRE", "CVBBDPrecReInitB", MSGBBD_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSBBDPRE",
+                   "CVBBDPrecReInitB", MSGBBD_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -703,13 +813,14 @@ int CVBBDPrecReInitB(void *cvode_mem, int which,
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
+  /* cv_mem corresponding to 'which' backward problem. */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
   
+  /* ReInitialize the BBD preconditioner for this backward problem. */
   flag = CVBBDPrecReInit(cvodeB_mem, mudqB, mldqB, dqrelyB);
-
   return(flag);
 }
 
@@ -722,77 +833,64 @@ static int CVBBDPrecFreeB(CVodeBMem cvB_mem)
 }
 
 
-/*
- * cvGlocWrapper
- *
- * This routine interfaces to the CVLocalFnB routine 
- * provided by the user.
- */
+/*----------------------------------------------------------------
+  Wrapper functions
+  ----------------------------------------------------------------*/
 
-static int cvGlocWrapper(long int NlocalB, realtype t, N_Vector yB, N_Vector gB, void *cvode_mem)
+/* cvGlocWrapper interfaces to the CVLocalFnB routine provided by the user */
+static int cvGlocWrapper(sunindextype NlocalB, realtype t, N_Vector yB,
+                         N_Vector gB, void *cvode_mem)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
   CVodeBMem cvB_mem;
   CVBBDPrecDataB cvbbdB_mem;
-  int retval, flag;
+  int flag;
 
   cv_mem = (CVodeMem) cvode_mem;
-
   ca_mem = cv_mem->cv_adj_mem;
-
   cvB_mem = ca_mem->ca_bckpbCrt;
-
   cvbbdB_mem = (CVBBDPrecDataB) (cvB_mem->cv_pmem);
 
-  /* Forward solution from interpolation */
-  flag = IMget(cv_mem, t, ytmp, NULL);
+  /* Get forward solution from interpolation */
+  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVBBDPRE", "cvGlocWrapper", MSGBBD_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSBBDPRE", "cvGlocWrapper",
+                   MSGBBD_BAD_TINTERP);
     return(-1);
   } 
 
   /* Call user's adjoint glocB routine */
-  retval = gloc_B(NlocalB, t, ytmp, yB, gB, cvB_mem->cv_user_data);
-
-  return(retval);
+  return cvbbdB_mem->glocB(NlocalB, t, ca_mem->ca_ytmp, yB,
+                           gB, cvB_mem->cv_user_data);
 }
 
-/*
- * cvCfnWrapper
- *
- * This routine interfaces to the CVCommFnB routine 
- * provided by the user.
- */
 
-static int cvCfnWrapper(long int NlocalB, realtype t, N_Vector yB, void *cvode_mem)
+/* cvCfnWrapper interfaces to the CVCommFnB routine provided by the user */
+static int cvCfnWrapper(sunindextype NlocalB, realtype t,
+                        N_Vector yB, void *cvode_mem)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
   CVodeBMem cvB_mem;
   CVBBDPrecDataB cvbbdB_mem;
-  int retval, flag;
+  int flag;
 
   cv_mem = (CVodeMem) cvode_mem;
-
   ca_mem = cv_mem->cv_adj_mem;
-
   cvB_mem = ca_mem->ca_bckpbCrt;
-
   cvbbdB_mem = (CVBBDPrecDataB) (cvB_mem->cv_pmem);
+  if (cvbbdB_mem->cfnB == NULL) return(0);
 
-  if (cfn_B == NULL) return(0);
-
-  /* Forward solution from interpolation */
-  flag = IMget(cv_mem, t, ytmp, NULL);
+  /* Get forward solution from interpolation */
+  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVBBDPRE", "cvCfnWrapper", MSGBBD_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSBBDPRE", "cvCfnWrapper",
+                   MSGBBD_BAD_TINTERP);
     return(-1);
   } 
 
   /* Call user's adjoint cfnB routine */
-  retval = cfn_B(NlocalB, t, ytmp, yB, cvB_mem->cv_user_data);
-
-  return(retval);
+  return cvbbdB_mem->cfnB(NlocalB, t, ca_mem->ca_ytmp,
+                          yB, cvB_mem->cv_user_data);
 }
-
diff --git a/src/cvodes/cvodes_bbdpre_impl.h b/src/cvodes/cvodes_bbdpre_impl.h
index 67327e9..4edc5f5 100644
--- a/src/cvodes/cvodes_bbdpre_impl.h
+++ b/src/cvodes/cvodes_bbdpre_impl.h
@@ -1,19 +1,21 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * Implementation header file for the CVBBDPRE module.
  * -----------------------------------------------------------------
@@ -23,55 +25,52 @@
 #define _CVSBBDPRE_IMPL_H
 
 #include <cvodes/cvodes_bbdpre.h>
-#include <sundials/sundials_band.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * Type: CVBBDPrecData
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type: CVBBDPrecData
+  -----------------------------------------------------------------*/
 
 typedef struct CVBBDPrecDataRec {
 
-  /* passed by user to CVBBDPrecAlloc and used by PrecSetup/PrecSolve */
-
-  long int mudq, mldq, mukeep, mlkeep;
+  /* passed by user to CVBBDPrecInit and used by PrecSetup/PrecSolve */
+  sunindextype mudq, mldq, mukeep, mlkeep;
   realtype dqrely;
   CVLocalFn gloc;
   CVCommFn cfn;
 
   /* set by CVBBDPrecSetup and used by CVBBDPrecSolve */
-
-  DlsMat savedJ;
-  DlsMat savedP;
-  long int *lpivots;
-
-  /* set by CVBBDPrecAlloc and used by CVBBDPrecSetup */
-
-  long int n_local;
+  SUNMatrix savedJ;
+  SUNMatrix savedP;
+  SUNLinearSolver LS;
+  N_Vector tmp1;
+  N_Vector tmp2;
+  N_Vector tmp3;
+  N_Vector zlocal;
+  N_Vector rlocal;
+
+  /* set by CVBBDPrecInit and used by CVBBDPrecSetup */
+  sunindextype n_local;
 
   /* available for optional output */
-
   long int rpwsize;
   long int ipwsize;
   long int nge;
 
   /* pointer to cvode_mem */
-
   void *cvode_mem;
 
 } *CVBBDPrecData;
 
 
-/*
- * -----------------------------------------------------------------
- * Type: CVBBDPrecDataB
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Type: CVBBDPrecDataB
+  -----------------------------------------------------------------*/
 
 typedef struct CVBBDPrecDataRecB {
 
@@ -81,16 +80,17 @@ typedef struct CVBBDPrecDataRecB {
 
 } *CVBBDPrecDataB;
 
-/*
- * -----------------------------------------------------------------
- * CVBBDPRE error messages
- * -----------------------------------------------------------------
- */
+
+/*-----------------------------------------------------------------
+  CVBBDPRE error messages
+  -----------------------------------------------------------------*/
 
 #define MSGBBD_MEM_NULL    "Integrator memory is NULL."
 #define MSGBBD_LMEM_NULL   "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBBD_MEM_FAIL    "A memory request failed."
 #define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGBBD_SUNMAT_FAIL "An error arose from a SUNBandMatrix routine."
+#define MSGBBD_SUNLS_FAIL  "An error arose from a SUNBandLinearSolver routine."
 #define MSGBBD_PMEM_NULL   "BBD peconditioner memory is NULL. CVBBDPrecInit must be called."
 #define MSGBBD_FUNC_FAILED "The gloc or cfn routine failed in an unrecoverable manner."
 
diff --git a/src/cvodes/cvodes_dense.c b/src/cvodes/cvodes_dense.c
deleted file mode 100644
index beb64cb..0000000
--- a/src/cvodes/cvodes_dense.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4951 $
- * $Date: 2016-09-22 10:21:00 -0700 (Thu, 22 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSDENSE linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvodes/cvodes_dense.h>
-#include "cvodes_direct_impl.h"
-#include "cvodes_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* CVSDENSE linit, lsetup, lsolve, and lfree routines */
-static int cvDenseInit(CVodeMem cv_mem);
-static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, 
-                        N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector fcur);
-static int cvDenseFree(CVodeMem cv_mem);
-
-/* CVSDENSE lfreeB function */
-static int cvDenseFreeB(CVodeBMem cvb_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-
-/* Readability Replacements */
-
-#define lmm       (cv_mem->cv_lmm)
-#define f         (cv_mem->cv_f)
-#define nst       (cv_mem->cv_nst)
-#define tn        (cv_mem->cv_tn)
-#define h         (cv_mem->cv_h)
-#define gamma     (cv_mem->cv_gamma)
-#define gammap    (cv_mem->cv_gammap)
-#define gamrat    (cv_mem->cv_gamrat)
-#define ewt       (cv_mem->cv_ewt)
-#define linit     (cv_mem->cv_linit)
-#define lsetup    (cv_mem->cv_lsetup)
-#define lsolve    (cv_mem->cv_lsolve)
-#define lfree     (cv_mem->cv_lfree)
-#define lmem      (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define mtype     (cvdls_mem->d_type)
-#define n         (cvdls_mem->d_n)
-#define jacDQ     (cvdls_mem->d_jacDQ)
-#define jac       (cvdls_mem->d_djac)
-#define M         (cvdls_mem->d_M)
-#define lpivots   (cvdls_mem->d_lpivots)
-#define savedJ    (cvdls_mem->d_savedJ)
-#define nstlj     (cvdls_mem->d_nstlj)
-#define nje       (cvdls_mem->d_nje)
-#define nfeDQ     (cvdls_mem->d_nfeDQ)
-#define J_data    (cvdls_mem->d_J_data)
-#define last_flag (cvdls_mem->d_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * CVDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the dense linear solver module.  CVDense first
- * calls the existing lfree routine if this is not NULL.  Then it sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be cvDenseInit, cvDenseSetup, cvDenseSolve, and cvDenseFree,
- * respectively.  It allocates memory for a structure of type
- * CVDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure.  It sets setupNonNull in (*cvode_mem) to
- * TRUE, and the d_jac field to the default CVDenseDQJac.
- * Finally, it allocates memory for M, savedJ, and lpivots.
- * The return value is SUCCESS = 0, or LMEM_FAIL = -1.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVDense will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-int CVDense(void *cvode_mem, long int N)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDENSE", "CVDense", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL ||
-      vec_tmpl->ops->nvsetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDENSE", "CVDense", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = cvDenseInit;
-  lsetup = cvDenseSetup;
-  lsolve = cvDenseSolve;
-  lfree  = cvDenseFree;
-
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Initialize Jacobian-related data */
-  jacDQ = TRUE;
-  jac = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-
-  cvDlsInitializeCounters(cvdls_mem);  
-
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = N;
-
-  /* Allocate memory for M, savedJ, and pivot array */
-
-  M = NULL;
-  M = NewDenseMat(N, N);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NULL;
-  savedJ = NewDenseMat(N, N);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  lpivots = NULL;
-  lpivots = NewLintArray(N);
-  if (lpivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyMat(savedJ);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the dense
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  cvDlsInitializeCounters(cvdls_mem);  
-
-  /*
-   nje   = 0;
-   nfeDQ = 0;
-   nstlj = 0;
-  */
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    jac = cvDlsDenseDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the dense linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy.  In any case, it constructs the Newton matrix 
- * M = I - gamma*J, updates counters, and calls the dense LU 
- * factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, 
-                        N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  CVDlsMem cvdls_mem;
-  booleantype jbad, jok;
-  realtype dgamma;
-  int retval;
-  long int ier;
-
-  cvdls_mem = (CVDlsMem) lmem;
- 
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
- 
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
- 
-  if (jok) {
-
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    DenseCopy(savedJ, M);
-
-  } else {
-
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M);
-
-    retval = jac(n, tn, ypred, fpred, M, J_data, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSDENSE", "cvDenseSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    DenseCopy(M, savedJ);
-
-  }
-  
-  /* Scale and add I to get M = I - gamma*J */
-  DenseScale(-gamma, M);
-  AddIdentity(M);
-
-  /* Do LU factorization of M */
-  ier = DenseGETRF(M, lpivots); 
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseSolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.  The returned value is 0.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector fcur)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  bd = N_VGetArrayPointer(b);
-
-  DenseGETRS(M, lpivots, bd);
-
-  /* If CV_BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-  
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * cvDenseFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the dense linear solver.
- * -----------------------------------------------------------------
- */
-
-static int cvDenseFree(CVodeMem cv_mem)
-{
-  CVDlsMem  cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  DestroyMat(M);
-  DestroyMat(savedJ);
-  DestroyArray(lpivots);
-  free(cvdls_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * CVDenseB is a wrapper around CVDense. It attaches the CVSDENSE linear solver
- * to the backward problem memory block.
- */
-
-int CVDenseB(void *cvode_mem, int which, long int nB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVDlsMemB cvdlsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDENSE", "CVDenseB", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDENSE", "CVDenseB", MSGD_NO_ADJ);
-    return(CVDLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDENSE", "CVDenseB", MSGD_BAD_WHICH);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVDlsMemRecB */
-  cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB));
-  if (cvdlsB_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDENSE", "CVDenseB", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* set matrix type */
-  cvdlsB_mem->d_typeB = SUNDIALS_DENSE;
-
-  /* initialize Jacobian function */
-  cvdlsB_mem->d_djacB = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvdlsB_mem;
-  cvB_mem->cv_lfree = cvDenseFreeB;
-
-  flag = CVDense(cvodeB_mem, nB);
-
-  if (flag != CVDLS_SUCCESS) {
-    free(cvdlsB_mem);
-    cvdlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * cvDenseFreeB frees the memory associated with the CVSDENSE linear
- * solver for backward integration.
- */
-
-static int cvDenseFreeB(CVodeBMem cvB_mem)
-{
-  CVDlsMemB cvdlsB_mem;
-
-  cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
-
-  free(cvdlsB_mem);
-
-  return(0);
-}
-
diff --git a/src/cvodes/cvodes_diag.c b/src/cvodes/cvodes_diag.c
index e04b173..342a431 100644
--- a/src/cvodes/cvodes_diag.c
+++ b/src/cvodes/cvodes_diag.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -94,7 +91,7 @@ static int CVDiagFree(CVodeMem cv_mem);
  * respectively.  It allocates memory for a structure of type
  * CVDiagMemRec and sets the cv_lmem field in (*cvode_mem) to the
  * address of this structure.  It sets setupNonNull in (*cvode_mem) to
- * TRUE.  Finally, it allocates memory for M, bit, and bitcomp.
+ * SUNTRUE.  Finally, it allocates memory for M, bit, and bitcomp.
  * The CVDiag return value is SUCCESS = 0, LMEM_FAIL = -1, or 
  * LIN_ILL_INPUT=-2.
  * -----------------------------------------------------------------
@@ -137,9 +134,6 @@ int CVDiag(void *cvode_mem)
 
   last_flag = CVDIAG_SUCCESS;
 
-  /* Set flag setupNonNull = TRUE */
-  setupNonNull = TRUE;
-
   /* Allocate memory for M, bit, and bitcomp */
     
   M = N_VClone(vec_tmpl);
@@ -383,8 +377,8 @@ static int CVDiagSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
     return(1);
   }
 
-  /* Set jcur = TRUE, save gamma in gammasv, and return */
-  *jcurPtr = TRUE;
+  /* Set jcur = SUNTRUE, save gamma in gammasv, and return */
+  *jcurPtr = SUNTRUE;
   gammasv = gamma;
   last_flag = CVDIAG_SUCCESS;
   return(0);
@@ -487,7 +481,7 @@ int CVDiagB(void *cvode_mem, int which)
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CVDIAG_NO_ADJ, "CVSDIAG", "CVDiagB", MSGDG_NO_ADJ);
     return(CVDIAG_NO_ADJ);
   } 
diff --git a/src/cvodes/cvodes_diag_impl.h b/src/cvodes/cvodes_diag_impl.h
index bd84ab4..abb1717 100644
--- a/src/cvodes/cvodes_diag_impl.h
+++ b/src/cvodes/cvodes_diag_impl.h
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
diff --git a/src/cvodes/cvodes_direct.c b/src/cvodes/cvodes_direct.c
index 8575679..825b1c6 100644
--- a/src/cvodes/cvodes_direct.c
+++ b/src/cvodes/cvodes_direct.c
@@ -1,29 +1,30 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
  * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the implementation file for the CVSDLS linear solvers
+ * This is the implementation file for the CVSDLS linear solver 
+ * interface
  * -----------------------------------------------------------------
  */
 
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
+/*=================================================================
+  IMPORTED HEADER FILES
+  =================================================================*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,12 +32,13 @@
 #include "cvodes_impl.h"
 #include "cvodes_direct_impl.h"
 #include <sundials/sundials_math.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
+/*=================================================================
+  FUNCTION SPECIFIC CONSTANTS
+  =================================================================*/
 
 /* Constant for DQ Jacobian approximation */
 #define MIN_INC_MULT RCONST(1000.0)
@@ -45,226 +47,262 @@
 #define ONE          RCONST(1.0)
 #define TWO          RCONST(2.0)
 
-/* 
- * =================================================================
- * PRIVATE FUNCTION PROTOTYPES
- * =================================================================
- */
-
-static int cvDlsDenseJacBWrapper(long int nB, realtype t,
-                                 N_Vector yB, N_Vector fyB, 
-                                 DlsMat JB, void *cvode_mem,
-                                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-static int cvDlsDenseJacBSWrapper(long int nB, realtype t,
-                                 N_Vector yB, N_Vector fyB, 
-                                 DlsMat JB, void *cvode_mem,
-                                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-static int cvDlsBandJacBWrapper(long int nB, long int mupperB, long int mlowerB, 
-                                realtype t, N_Vector yB, N_Vector fyB, 
-                                DlsMat Jac, void *cvode_mem, 
-                                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+/*=================================================================
+  PRIVATE FUNCTION PROTOTYPES
+  =================================================================*/
 
-static int cvDlsBandJacBSWrapper(long int nB, long int mupperB, long int mlowerB, 
-                                realtype t, N_Vector yB, N_Vector fyB, 
-                                DlsMat Jac, void *cvode_mem, 
-                                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+static int cvDlsJacBWrapper(realtype t, N_Vector yB, N_Vector fyB, 
+                            SUNMatrix JB, void *cvode_mem,
+                            N_Vector tmp1B, N_Vector tmp2B,
+                            N_Vector tmp3B);
 
+static int cvDlsJacBSWrapper(realtype t, N_Vector yB, N_Vector fyB, 
+                             SUNMatrix JB, void *cvode_mem,
+                             N_Vector tmp1B, N_Vector tmp2B,
+                             N_Vector tmp3B);
 
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
 
-#define f              (cv_mem->cv_f)
-#define user_data      (cv_mem->cv_user_data)
-#define uround         (cv_mem->cv_uround)
-#define nst            (cv_mem->cv_nst)
-#define tn             (cv_mem->cv_tn)
-#define h              (cv_mem->cv_h)
-#define gamma          (cv_mem->cv_gamma)
-#define gammap         (cv_mem->cv_gammap)
-#define gamrat         (cv_mem->cv_gamrat)
-#define ewt            (cv_mem->cv_ewt)
-
-#define lmem           (cv_mem->cv_lmem)
-
-#define mtype          (cvdls_mem->d_type)
-#define n              (cvdls_mem->d_n)
-#define ml             (cvdls_mem->d_ml)
-#define mu             (cvdls_mem->d_mu)
-#define smu            (cvdls_mem->d_smu)
-#define jacDQ          (cvdls_mem->d_jacDQ)
-#define djac           (cvdls_mem->d_djac)
-#define bjac           (cvdls_mem->d_bjac)
-#define M              (cvdls_mem->d_M)
-#define savedJ         (cvdls_mem->d_savedJ)
-#define pivots         (cvdls_mem->d_pivots)
-#define nstlj          (cvdls_mem->d_nstlj)
-#define nje            (cvdls_mem->d_nje)
-#define nfeDQ          (cvdls_mem->d_nfeDQ)
-#define last_flag      (cvdls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS (FORWARD INTEGRATION)
- * =================================================================
- */
+/*=================================================================
+  EXPORTED FUNCTIONS (FORWARD INTEGRATION) -- REQUIRED
+  =================================================================*/
 
-/*
- * CVDlsSetDenseJacFn specifies the dense Jacobian function.
- */
-int CVDlsSetDenseJacFn(void *cvode_mem, CVDlsDenseJacFn jac)
+/*---------------------------------------------------------------
+ CVDlsSetLinearSolver specifies the direct linear solver.
+---------------------------------------------------------------*/
+int CVDlsSetLinearSolver(void *cvode_mem, SUNLinearSolver LS,
+                         SUNMatrix A)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", 
+                   "CVDlsSetLinearSolver", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
+  if ( (LS == NULL)  || (A == NULL) ) {
+    cvProcessError(NULL, CVDLS_ILL_INPUT, "CVSDLS", 
+                   "CVDlsSetLinearSolver",
+                    "Both LS and A must be non-NULL");
+    return(CVDLS_ILL_INPUT);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetDenseJacFn", MSGD_LMEM_NULL);
-    return(CVDLS_LMEM_NULL);
+  /* Test if solver and vector are compatible with DLS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
+    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", 
+                   "CVDlsSetLinearSolver", 
+                   "Non-direct LS supplied to CVDls interface");
+    return(CVDLS_ILL_INPUT);
+  }
+  if (cv_mem->cv_tempv->ops->nvgetarraypointer == NULL ||
+      cv_mem->cv_tempv->ops->nvsetarraypointer == NULL) {
+    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", 
+                   "CVDlsSetLinearSolver", MSGD_BAD_NVECTOR);
+    return(CVDLS_ILL_INPUT);
   }
-  cvdls_mem = (CVDlsMem) lmem;
 
-  if (jac != NULL) {
-    jacDQ = FALSE;
-    djac = jac;
-  } else {
-    jacDQ = TRUE;
+  /* free any existing system solver attached to CVode */
+  if (cv_mem->cv_lfree)  cv_mem->cv_lfree(cv_mem);
+
+  /* Set four main system linear solver function fields in cv_mem */
+  cv_mem->cv_linit  = cvDlsInitialize;
+  cv_mem->cv_lsetup = cvDlsSetup;
+  cv_mem->cv_lsolve = cvDlsSolve;
+  cv_mem->cv_lfree  = cvDlsFree;
+  
+  /* Get memory for CVDlsMemRec */
+  cvdls_mem = NULL;
+  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
+  if (cvdls_mem == NULL) {
+    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDLS", 
+                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
+    return(CVDLS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer */
+  cvdls_mem->LS = LS;
+  
+  /* Initialize Jacobian-related data */
+  cvdls_mem->jacDQ = SUNTRUE;
+  cvdls_mem->jac = cvDlsDQJac;
+  cvdls_mem->J_data = cv_mem;
+  cvdls_mem->last_flag = CVDLS_SUCCESS;
+
+  /* Initialize counters */
+  cvDlsInitializeCounters(cvdls_mem);
+
+  /* Store pointer to A and create saved_J */
+  cvdls_mem->A = A;
+  cvdls_mem->savedJ = SUNMatClone(A);
+  if (cvdls_mem->savedJ == NULL) {
+    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDLS", 
+                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
+    free(cvdls_mem); cvdls_mem = NULL;
+    return(CVDLS_MEM_FAIL);
   }
 
+  /* Allocate memory for x */
+  cvdls_mem->x = N_VClone(cv_mem->cv_tempv);
+  if (cvdls_mem->x == NULL) {
+    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDLS", 
+                    "CVDlsSetLinearSolver", MSGD_MEM_FAIL);
+    SUNMatDestroy(cvdls_mem->savedJ);
+    free(cvdls_mem); cvdls_mem = NULL;
+    return(CVDLS_MEM_FAIL);
+  }
+  /* Attach linear solver memory to integrator memory */
+  cv_mem->cv_lmem = cvdls_mem;
+
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsSetBandJacFn specifies the band Jacobian function.
- */
-int CVDlsSetBandJacFn(void *cvode_mem, CVDlsBandJacFn jac)
+
+/*=================================================================
+  EXPORTED FUNCTIONS (FORWARD INTEGRATION) -- OPTIONAL
+  =================================================================*/
+
+/* CVDlsSetJacFn specifies the Jacobian function. */
+int CVDlsSetJacFn(void *cvode_mem, CVDlsJacFn jac)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsSetJacFn", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVDLS", "CVDlsSetBandJacFn", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS",
+                   "CVDlsSetJacFn", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
   if (jac != NULL) {
-    jacDQ = FALSE;
-    bjac = jac;
+    cvdls_mem->jacDQ  = SUNFALSE;
+    cvdls_mem->jac    = jac;
+    cvdls_mem->J_data = cv_mem->cv_user_data;
   } else {
-    jacDQ = TRUE;
+    cvdls_mem->jacDQ  = SUNTRUE;
+    cvdls_mem->jac    = cvDlsDQJac;
+    cvdls_mem->J_data = cv_mem;
   }
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetWorkSpace returns the length of workspace allocated for the
- * CVDLS linear solver.
- */
-int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+
+/* CVDlsGetWorkSpace returns the length of workspace allocated for the
+   CVDLS linear solver. */
+int CVDlsGetWorkSpace(void *cvode_mem, long int *lenrwLS,
+                      long int *leniwLS)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetWorkSpace", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsGetWorkSpace", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetWorkSpace", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS",
+                   "CVDlsGetWorkSpace", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  if (mtype == SUNDIALS_DENSE) {
-    *lenrwLS = 2*n*n;
-    *leniwLS = n;
-  } else if (mtype == SUNDIALS_BAND) {
-    *lenrwLS = n*(smu + mu + 2*ml + 2);
-    *leniwLS = n;
+  /* initialize outputs with requirements from CVDlsMem structure */
+  *lenrwLS = 0;
+  *leniwLS = 4;
+
+  /* add NVector size */
+  if (cvdls_mem->x->ops->nvspace) {
+    N_VSpace(cvdls_mem->x, &lrw1, &liw1);
+    *lenrwLS = lrw1;
+    *leniwLS = liw1;
+  }
+  
+  /* add SUNMatrix size (only account for the one owned by Dls interface) */
+  if (cvdls_mem->savedJ->ops->space) {
+    flag = SUNMatSpace(cvdls_mem->savedJ, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
+  }
+
+  /* add LS sizes */
+  if (cvdls_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(cvdls_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
+/* CVDlsGetNumJacEvals returns the number of Jacobian evaluations. */
 int CVDlsGetNumJacEvals(void *cvode_mem, long int *njevals)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetNumJacEvals", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsGetNumJacEvals", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetNumJacEvals", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS",
+                   "CVDlsGetNumJacEvals", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  *njevals = nje;
+  *njevals = cvdls_mem->nje;
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetNumRhsEvals returns the number of calls to the ODE function
- * needed for the DQ Jacobian approximation.
- */
+/* CVDlsGetNumRhsEvals returns the number of calls to the ODE function
+   needed for the DQ Jacobian approximation. */
 int CVDlsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetNumRhsEvals", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsGetNumRhsEvals", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetNumRhsEvals", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS",
+                   "CVDlsGetNumRhsEvals", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  *nfevalsLS = nfeDQ;
+  *nfevalsLS = cvdls_mem->nfeDQ;
 
   return(CVDLS_SUCCESS);
 }
 
-/*
- * CVDlsGetReturnFlagName returns the name associated with a CVDLS
- * return value.
- */
+/* CVDlsGetReturnFlagName returns the name associated with a CVDLS
+   return value. */
 char *CVDlsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -293,6 +331,9 @@ char *CVDlsGetReturnFlagName(long int flag)
   case CVDLS_JACFUNC_RECVR:
     sprintf(name,"CVDLS_JACFUNC_RECVR");
     break;
+  case CVDLS_SUNMAT_FAIL:
+    sprintf(name,"CVDLS_SUNMAT_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -300,100 +341,133 @@ char *CVDlsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * CVDlsGetLastFlag returns the last flag set in a CVDLS function.
- */
+/* CVDlsGetLastFlag returns the last flag set in a CVDLS function. */
 int CVDlsGetLastFlag(void *cvode_mem, long int *flag)
 {
   CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsGetLastFlag", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsGetLastFlag", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", "CVDlsGetLastFlag", MSGD_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS",
+                   "CVDlsGetLastFlag", MSGD_LMEM_NULL);
     return(CVDLS_LMEM_NULL);
   }
-  cvdls_mem = (CVDlsMem) lmem;
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  *flag = last_flag;
+  *flag = cvdls_mem->last_flag;
 
   return(CVDLS_SUCCESS);
 }
 
-/* 
- * =================================================================
- * DQ JACOBIAN APPROXIMATIONS
- * =================================================================
- */
 
-/*
- * -----------------------------------------------------------------
- * cvDlsDenseDQJac 
- * -----------------------------------------------------------------
- * This routine generates a dense difference quotient approximation to
- * the Jacobian of f(t,y). It assumes that a dense matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. The address of the jth column of J is obtained via
- * the macro DENSE_COL and this pointer is associated with an N_Vector
- * using the N_VGetArrayPointer/N_VSetArrayPointer functions. 
- * Finally, the actual computation of the jth column of the Jacobian is 
- * done with a call to N_VLinearSum.
- * -----------------------------------------------------------------
- */ 
+/*=================================================================
+  CVSDLS PRIVATE FUNCTIONS (FORWARD INTEGRATION)
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  cvDlsDQJac 
+  -----------------------------------------------------------------
+  This routine is a wrapper for the Dense and Band
+  implementations of the difference quotient Jacobian 
+  approximation routines.
+  ---------------------------------------------------------------*/
+int cvDlsDQJac(realtype t, N_Vector y, N_Vector fy, 
+               SUNMatrix Jac, void *cvode_mem, N_Vector tmp1, 
+               N_Vector tmp2, N_Vector tmp3)
+{
+  int retval;
+  CVodeMem cv_mem;
+  cv_mem = (CVodeMem) cvode_mem;
+
+  /* verify that Jac is non-NULL */
+  if (Jac == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", 
+		    "cvDlsDQJac", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+
+  if (SUNMatGetID(Jac) == SUNMATRIX_DENSE) {
+    retval = cvDlsDenseDQJac(t, y, fy, Jac, cv_mem, tmp1);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_BAND) {
+    retval = cvDlsBandDQJac(t, y, fy, Jac, cv_mem, tmp1, tmp2);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_SPARSE) {
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVSDLS", 
+                   "cvDlsDQJac", 
+                   "cvDlsDQJac not implemented for SUNMATRIX_SPARSE");
+    retval = CV_ILL_INPUT;
+  } else {
+    cvProcessError(cv_mem, CV_ILL_INPUT, "CVSDLS", 
+                   "cvDlsDQJac", 
+                   "unrecognized matrix type for cvDlsDQJac");
+    retval = CV_ILL_INPUT;
+  }
+  return(retval);
+}
+
 
-int cvDlsDenseDQJac(long int N, realtype t,
-                    N_Vector y, N_Vector fy, 
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+/*-----------------------------------------------------------------
+  cvDlsDenseDQJac 
+  -----------------------------------------------------------------
+  This routine generates a dense difference quotient approximation 
+  to the Jacobian of f(t,y). It assumes that a dense SUNMatrix is 
+  stored column-wise, and that elements within each column are 
+  contiguous. The address of the jth column of J is obtained via
+  the accessor function SUNDenseMatrix_Column, and this pointer 
+  is associated with an N_Vector using the N_VSetArrayPointer
+  function.  Finally, the actual computation of the jth column of 
+  the Jacobian is done with a call to N_VLinearSum.
+  -----------------------------------------------------------------*/ 
+int cvDlsDenseDQJac(realtype t, N_Vector y, N_Vector fy, 
+                    SUNMatrix Jac, CVodeMem cv_mem, N_Vector tmp1)
 {
   realtype fnorm, minInc, inc, inc_inv, yjsaved, srur;
-  realtype *tmp2_data, *y_data, *ewt_data;
+  realtype *y_data, *ewt_data;
   N_Vector ftemp, jthCol;
-  long int j;
+  sunindextype j, N;
   int retval = 0;
-
-  CVodeMem cv_mem;
   CVDlsMem cvdls_mem;
 
-  /* data points to cvode_mem */
-  cv_mem = (CVodeMem) data;
-  cvdls_mem = (CVDlsMem) lmem;
+  /* access DlsMem interface structure */
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  /* Save pointer to the array in tmp2 */
-  tmp2_data = N_VGetArrayPointer(tmp2);
+  /* access matrix dimension */
+  N = SUNDenseMatrix_Rows(Jac);
 
-  /* Rename work vectors for readibility */
-  ftemp = tmp1; 
-  jthCol = tmp2;
+  /* Rename work vector for readibility */
+  ftemp = tmp1;
+
+  /* Create an empty vector for matrix column calculations */
+  jthCol = N_VCloneEmpty(tmp1);
 
   /* Obtain pointers to the data for ewt, y */
-  ewt_data = N_VGetArrayPointer(ewt);
+  ewt_data = N_VGetArrayPointer(cv_mem->cv_ewt);
   y_data   = N_VGetArrayPointer(y);
 
   /* Set minimum increment based on uround and norm of f */
-  srur = SUNRsqrt(uround);
-  fnorm = N_VWrmsNorm(fy, ewt);
+  srur = SUNRsqrt(cv_mem->cv_uround);
+  fnorm = N_VWrmsNorm(fy, cv_mem->cv_ewt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) * cv_mem->cv_uround * N * fnorm) : ONE;
 
   for (j = 0; j < N; j++) {
 
     /* Generate the jth col of J(tn,y) */
 
-    N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol);
+    N_VSetArrayPointer(SUNDenseMatrix_Column(Jac,j), jthCol);
 
     yjsaved = y_data[j];
     inc = SUNMAX(srur*SUNRabs(yjsaved), minInc/ewt_data[j]);
     y_data[j] += inc;
 
-    retval = f(t, y, ftemp, user_data);
-    nfeDQ++;
+    retval = cv_mem->cv_f(t, y, ftemp, cv_mem->cv_user_data);
+    cvdls_mem->nfeDQ++;
     if (retval != 0) break;
     
     y_data[j] = yjsaved;
@@ -401,52 +475,53 @@ int cvDlsDenseDQJac(long int N, realtype t,
     inc_inv = ONE/inc;
     N_VLinearSum(inc_inv, ftemp, -inc_inv, fy, jthCol);
 
-    DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);
+    /* DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol); */  /* UNNECESSARY? */
   }
 
-  /* Restore original array pointer in tmp2 */
-  N_VSetArrayPointer(tmp2_data, tmp2);
+  /* Destroy jthCol vector */
+  N_VSetArrayPointer(NULL, jthCol);  /* SHOULDN'T BE NEEDED */
+  N_VDestroy(jthCol);
 
   return(retval);
 }
 
-/*
- * -----------------------------------------------------------------
- * cvDlsBandDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation to
- * the Jacobian of f(t,y).  It assumes that a band matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. This makes it possible to get the address of a column
- * of J via the macro BAND_COL and to write a simple for loop to set
- * each of the elements of a column in succession.
- * -----------------------------------------------------------------
- */
 
-int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
-                   realtype t, N_Vector y, N_Vector fy, 
-                   DlsMat Jac, void *data,
-                   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+/*-----------------------------------------------------------------
+  cvDlsBandDQJac
+  -----------------------------------------------------------------
+  This routine generates a banded difference quotient approximation 
+  to the Jacobian of f(t,y).  It assumes that a band SUNMatrix is 
+  stored column-wise, and that elements within each column are 
+  contiguous. This makes it possible to get the address of a column
+  of J via the accessor function SUNBandMatrix_Column, and to write 
+  a simple for loop to set each of the elements of a column in 
+  succession.
+  -----------------------------------------------------------------*/
+int cvDlsBandDQJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix Jac,
+                   CVodeMem cv_mem, N_Vector tmp1, N_Vector tmp2)
 {
   N_Vector ftemp, ytemp;
   realtype fnorm, minInc, inc, inc_inv, srur;
   realtype *col_j, *ewt_data, *fy_data, *ftemp_data, *y_data, *ytemp_data;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   int retval = 0;
-
-  CVodeMem cv_mem;
+  sunindextype N, mupper, mlower;
   CVDlsMem cvdls_mem;
 
-  /* data points to cvode_mem */
-  cv_mem = (CVodeMem) data;
-  cvdls_mem = (CVDlsMem) lmem;
+  /* access DlsMem interface structure */
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+
+  /* access matrix dimensions */
+  N = SUNBandMatrix_Columns(Jac);
+  mupper = SUNBandMatrix_UpperBandwidth(Jac);
+  mlower = SUNBandMatrix_LowerBandwidth(Jac);
 
   /* Rename work vectors for use as temporary values of y and f */
   ftemp = tmp1;
   ytemp = tmp2;
 
   /* Obtain pointers to the data for ewt, fy, ftemp, y, ytemp */
-  ewt_data   = N_VGetArrayPointer(ewt);
+  ewt_data   = N_VGetArrayPointer(cv_mem->cv_ewt);
   fy_data    = N_VGetArrayPointer(fy);
   ftemp_data = N_VGetArrayPointer(ftemp);
   y_data     = N_VGetArrayPointer(y);
@@ -456,10 +531,10 @@ int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
   N_VScale(ONE, y, ytemp);
 
   /* Set minimum increment based on uround and norm of f */
-  srur = SUNRsqrt(uround);
-  fnorm = N_VWrmsNorm(fy, ewt);
+  srur = SUNRsqrt(cv_mem->cv_uround);
+  fnorm = N_VWrmsNorm(fy, cv_mem->cv_ewt);
   minInc = (fnorm != ZERO) ?
-           (MIN_INC_MULT * SUNRabs(h) * uround * N * fnorm) : ONE;
+    (MIN_INC_MULT * SUNRabs(cv_mem->cv_h) * cv_mem->cv_uround * N * fnorm) : ONE;
 
   /* Set bandwidth and number of column groups for band differencing */
   width = mlower + mupper + 1;
@@ -475,21 +550,20 @@ int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
     }
 
     /* Evaluate f with incremented y */
-
-    retval = f(tn, ytemp, ftemp, user_data);
-    nfeDQ++;
+    retval = cv_mem->cv_f(cv_mem->cv_tn, ytemp, ftemp, cv_mem->cv_user_data);
+    cvdls_mem->nfeDQ++;
     if (retval != 0) break;
 
     /* Restore ytemp, then form and load difference quotients */
     for (j=group-1; j < N; j+=width) {
       ytemp_data[j] = y_data[j];
-      col_j = BAND_COL(Jac,j);
+      col_j = SUNBandMatrix_Column(Jac, j);
       inc = SUNMAX(srur*SUNRabs(y_data[j]), minInc/ewt_data[j]);
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-mupper);
       i2 = SUNMIN(j+mlower, N-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (ftemp_data[i] - fy_data[i]);
     }
   }
   
@@ -497,126 +571,279 @@ int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
 }
 
 
-int cvDlsInitializeCounters(CVDlsMem cvdls_mem)
+/*-----------------------------------------------------------------
+  cvDlsInitialize
+  -----------------------------------------------------------------
+  This routine performs remaining initializations specific
+  to the direct linear solver interface (and solver itself)
+  -----------------------------------------------------------------*/
+int cvDlsInitialize(CVodeMem cv_mem)
 {
-  cvdls_mem->d_nje   = 0;
-  cvdls_mem->d_nfeDQ = 0;
-  cvdls_mem->d_nstlj = 0;
-  
-  return(0);
+  CVDlsMem cvdls_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", 
+                    "cvDlsInitialize", MSGD_CVMEM_NULL);
+    return(CVDLS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", 
+                    "cvDlsInitialize", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+ 
+  cvDlsInitializeCounters(cvdls_mem);
+
+  /* Set Jacobian function and data, depending on jacDQ (in case 
+     it has changed based on user input) */
+  if (cvdls_mem->jacDQ) {
+    cvdls_mem->jac    = cvDlsDQJac;
+    cvdls_mem->J_data = cv_mem;
+  } else {
+    cvdls_mem->J_data = cv_mem->cv_user_data;
+  }
+
+  /* Call LS initialize routine */
+  cvdls_mem->last_flag = SUNLinSolInitialize(cvdls_mem->LS);
+  return(cvdls_mem->last_flag);
 }
 
 
-/* 
- * =================================================================
- * BACKWARD INTEGRATION SUPPORT
- * =================================================================
- */
+/*-----------------------------------------------------------------
+  cvDlsSetup
+  -----------------------------------------------------------------
+  This routine determines whether to update a Jacobian matrix (or
+  use a stored version), based on heuristics regarding previous 
+  convergence issues, the number of time steps since it was last
+  updated, etc.; it then creates the system matrix from this, the
+  'gamma' factor and the identity matrix, 
+    A = I-gamma*J.
+  This routine then calls the LS 'setup' routine with A.
+  -----------------------------------------------------------------*/
+int cvDlsSetup(CVodeMem cv_mem, int convfail, N_Vector y, 
+               N_Vector fy, booleantype *jcurPtr, 
+               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+{
+  booleantype jbad, jok;
+  realtype dgamma;
+  CVDlsMem cvdls_mem;
+  int retval;
 
-/*
- * -----------------------------------------------------------------
- * Additional readability replacements 
- * -----------------------------------------------------------------
- */
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", 
+                    "cvDlsSetup", MSGD_CVMEM_NULL);
+    return(CVDLS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", 
+                    "cvDlsSetup", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
+
+  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
+  dgamma = SUNRabs((cv_mem->cv_gamma/cv_mem->cv_gammap) - ONE);
+  jbad = (cv_mem->cv_nst == 0) || 
+    (cv_mem->cv_nst > cvdls_mem->nstlj + CVD_MSBJ) ||
+    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
+    (convfail == CV_FAIL_OTHER);
+  jok = !jbad;
+ 
+  /* If jok = SUNTRUE, use saved copy of J */
+  if (jok) {
+    *jcurPtr = SUNFALSE;
+    retval = SUNMatCopy(cvdls_mem->savedJ, cvdls_mem->A);
+    if (retval) {
+      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVSDLS", 
+                      "cvDlsSetup",  MSGD_MATCOPY_FAILED);
+      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+      return(-1);
+    }
 
-#define ytmp  (ca_mem->ca_ytmp)
-#define yStmp (ca_mem->ca_yStmp)
-#define IMget (ca_mem->ca_IMget)
-#define IMinterpSensi (ca_mem->ca_IMinterpSensi)
+  /* If jok = SUNFALSE, call jac routine for new J value */
+  } else {
+    cvdls_mem->nje++;
+    cvdls_mem->nstlj = cv_mem->cv_nst;
+    *jcurPtr = SUNTRUE;
+    retval = SUNMatZero(cvdls_mem->A);
+    if (retval) {
+      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVSDLS", 
+                      "cvDlsSetup",  MSGD_MATZERO_FAILED);
+      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+      return(-1);
+    }
 
-#define mtypeB     (cvdlsB_mem->d_typeB)
-#define djacB      (cvdlsB_mem->d_djacB)
-#define djacBS     (cvdlsB_mem->d_djacBS)
-#define bjacB      (cvdlsB_mem->d_bjacB)
-#define bjacBS     (cvdlsB_mem->d_bjacBS)
+    retval = cvdls_mem->jac(cv_mem->cv_tn, y, fy, cvdls_mem->A, 
+                            cvdls_mem->J_data, tmp1, tmp2, tmp3);
+    if (retval < 0) {
+      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSDLS", 
+                      "cvDlsSetup",  MSGD_JACFUNC_FAILED);
+      cvdls_mem->last_flag = CVDLS_JACFUNC_UNRECVR;
+      return(-1);
+    }
+    if (retval > 0) {
+      cvdls_mem->last_flag = CVDLS_JACFUNC_RECVR;
+      return(1);
+    }
 
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS
- * -----------------------------------------------------------------
- */
+    retval = SUNMatCopy(cvdls_mem->A, cvdls_mem->savedJ);
+    if (retval) {
+      cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVSDLS", 
+                      "cvDlsSetup",  MSGD_MATCOPY_FAILED);
+      cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+      return(-1);
+    }
 
-int CVDlsSetDenseJacFnB(void *cvode_mem, int which, CVDlsDenseJacFnB jacB)
+  }
+  
+  /* Scale and add I to get A = I - gamma*J */
+  retval = SUNMatScaleAddI(-cv_mem->cv_gamma, cvdls_mem->A);
+  if (retval) {
+    cvProcessError(cv_mem, CVDLS_SUNMAT_FAIL, "CVSDLS", 
+                   "cvDlsSetup",  MSGD_MATSCALEADDI_FAILED);
+    cvdls_mem->last_flag = CVDLS_SUNMAT_FAIL;
+    return(-1);
+  }
+
+  /* Call generic linear solver 'setup' with this system matrix, and
+     return success/failure flag */
+  cvdls_mem->last_flag = SUNLinSolSetup(cvdls_mem->LS, cvdls_mem->A);
+  return(cvdls_mem->last_flag);
+}
+
+
+/*-----------------------------------------------------------------
+  cvDlsSolve
+  -----------------------------------------------------------------
+  This routine interfaces between CVode and the generic 
+  SUNLinearSolver object LS, by calling the solver and scaling 
+  the solution appropriately when gamrat != 1.
+  -----------------------------------------------------------------*/
+int cvDlsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+               N_Vector ycur, N_Vector fcur)
 {
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  CVDlsMemB cvdlsB_mem;
-  void *cvodeB_mem;
-  int flag;
+  int retval;
+  CVDlsMem cvdls_mem;
 
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_CVMEM_NULL);
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", 
+		    "cvDlsSolve", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
-  cv_mem = (CVodeMem) cvode_mem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEM_NULL, "CVSDLS", 
+		    "cvDlsSolve", MSGD_LMEM_NULL);
+    return(CVDLS_LMEM_NULL);
+  }
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_NO_ADJ);
-    return(CVDLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
+  /* call the generic linear system solver, and copy b to x */
+  retval = SUNLinSolSolve(cvdls_mem->LS, cvdls_mem->A, cvdls_mem->x, b, ZERO);
+  N_VScale(ONE, cvdls_mem->x, b);
+  
+  /* scale the correction to account for change in gamma */
+  if ((cv_mem->cv_lmm == CV_BDF) && (cv_mem->cv_gamrat != ONE))
+    N_VScale(TWO/(ONE + cv_mem->cv_gamrat), b, b);
+  
+  /* store solver return value and return */
+  cvdls_mem->last_flag = retval;
+  return(retval);
+}
 
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_BAD_WHICH);
-    return(CVDLS_ILL_INPUT);
-  }
 
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
+/*-----------------------------------------------------------------
+  cvDlsFree
+  -----------------------------------------------------------------
+  This routine frees memory associates with the CVDls solver 
+  interface.
+  -----------------------------------------------------------------*/
+int cvDlsFree(CVodeMem cv_mem)
+{
+  CVDlsMem cvdls_mem;
 
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL)  return (CVDLS_SUCCESS);
+  if (cv_mem->cv_lmem == NULL)  return(CVDLS_SUCCESS);
+  cvdls_mem = (CVDlsMem) cv_mem->cv_lmem;
 
-  if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetDenseJacFnB", MSGD_LMEMB_NULL);
-    return(CVDLS_LMEMB_NULL);
+  /* Free x vector */
+  if (cvdls_mem->x) {
+    N_VDestroy(cvdls_mem->x);
+    cvdls_mem->x = NULL;
   }
-  cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
 
-  djacB = jacB;
-
-  if (jacB != NULL) {
-    flag = CVDlsSetDenseJacFn(cvodeB_mem, cvDlsDenseJacBWrapper);
-  } else {
-    flag = CVDlsSetDenseJacFn(cvodeB_mem, NULL);
+  /* Free savedJ memory */
+  if (cvdls_mem->savedJ) {
+    SUNMatDestroy(cvdls_mem->savedJ);
+    cvdls_mem->savedJ = NULL;
   }
 
-  return(flag);
+  /* Nullify other SUNMatrix pointer */
+  cvdls_mem->A = NULL;
+
+  /* free CVDls interface structure */
+  free(cv_mem->cv_lmem);
+  
+  return(CVDLS_SUCCESS);
 }
 
-int CVDlsSetDenseJacFnBS(void *cvode_mem, int which, CVDlsDenseJacFnBS jacBS)
+
+/*-----------------------------------------------------------------
+  cvDlsInitializeCounters
+  -----------------------------------------------------------------
+  This routine resets the counters inside the CVDlsMem object.
+  -----------------------------------------------------------------*/
+int cvDlsInitializeCounters(CVDlsMem cvdls_mem)
+{
+  cvdls_mem->nje   = 0;
+  cvdls_mem->nfeDQ = 0;
+  cvdls_mem->nstlj = 0;
+  return(0);
+}
+
+
+/*=================================================================
+  BACKWARD INTEGRATION SUPPORT
+  =================================================================*/
+
+/*---------------------------------------------------------------
+  CVDlsSetLinearSolverB specifies the direct linear solver for 
+  backward integration.
+  ---------------------------------------------------------------*/
+int CVDlsSetLinearSolverB(void *cvode_mem, int which,
+                          SUNLinearSolver LS, SUNMatrix A)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
   CVodeBMem cvB_mem;
-  CVDlsMemB cvdlsB_mem;
   void *cvodeB_mem;
+  CVDlsMemB cvdlsB_mem;
   int flag;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetDenseJacFnBS", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsSetLinearSolverB", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS", "CVDlsSetDenseJacFnBS", MSGD_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS",
+                   "CVDlsSetLinearSolverB", MSGD_NO_ADJ);
     return(CVDLS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", "CVDlsSetDenseJacFnBS", MSGD_BAD_WHICH);
+    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS",
+                   "CVDlsSetLinearSolverB", MSGD_BAD_WHICH);
     return(CVDLS_ILL_INPUT);
   }
 
@@ -627,26 +854,42 @@ int CVDlsSetDenseJacFnBS(void *cvode_mem, int which, CVDlsDenseJacFnBS jacBS)
     cvB_mem = cvB_mem->cv_next;
   }
 
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetDenseJacFnBS", MSGD_LMEMB_NULL);
-    return(CVDLS_LMEMB_NULL);
+  /* Get memory for CVDlsMemRecB */
+  cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB));
+  if (cvdlsB_mem == NULL) {
+    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSDLS",
+                   "CVDlsSetLinearSolverB", MSGD_MEM_FAIL);
+    return(CVDLS_MEM_FAIL);
   }
-  cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
 
-  djacBS = jacBS;
+  /* free any existing system solver attached to cvB */
+  if (cvB_mem->cv_lfree)  cvB_mem->cv_lfree(cvB_mem);
 
-  if (jacBS != NULL) {
-    flag = CVDlsSetDenseJacFn(cvodeB_mem, cvDlsDenseJacBSWrapper);
-  } else {
-    flag = CVDlsSetDenseJacFn(cvodeB_mem, NULL);
+  /* Attach lmemB data and lfreeB function. */
+  cvB_mem->cv_lmem  = cvdlsB_mem;
+  cvB_mem->cv_lfree = cvDlsFreeB;
+
+  /* initialize jacB and jacBS pointers */
+  cvdlsB_mem->jacB  = NULL;
+  cvdlsB_mem->jacBS = NULL;
+
+  /* set the linear solver for this backward problem */
+  cvodeB_mem = (void *) (cvB_mem->cv_mem);
+  flag = CVDlsSetLinearSolver(cvodeB_mem, LS, A);
+  if (flag != CVDLS_SUCCESS) {
+    free(cvdlsB_mem);
+    cvdlsB_mem = NULL;
   }
 
   return(flag);
 }
 
-int CVDlsSetBandJacFnB(void *cvode_mem, int which, CVDlsBandJacFnB jacB)
+
+/*-----------------------------------------------------------------
+  EXPORTED FUNCTIONS
+  -----------------------------------------------------------------*/
+
+int CVDlsSetJacFnB(void *cvode_mem, int which, CVDlsJacFnB jacB)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -657,21 +900,24 @@ int CVDlsSetBandJacFnB(void *cvode_mem, int which, CVDlsBandJacFnB jacB)
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsSetJacFnB", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS",
+                   "CVDlsSetJacFnB", MSGD_NO_ADJ);
     return(CVDLS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_BAD_WHICH);
+    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS",
+                   "CVDlsSetJacFnB", MSGD_BAD_WHICH);
     return(CVDLS_ILL_INPUT);
   }
 
@@ -685,23 +931,25 @@ int CVDlsSetBandJacFnB(void *cvode_mem, int which, CVDlsBandJacFnB jacB)
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
   if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetBandJacFnB", MSGD_LMEMB_NULL);
+    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS",
+                   "CVDlsSetJacFnB", MSGD_LMEMB_NULL);
     return(CVDLS_LMEMB_NULL);
   }
   cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
 
-  bjacB = jacB;
+  cvdlsB_mem->jacB = jacB;
 
   if (jacB != NULL) {
-    flag = CVDlsSetBandJacFn(cvodeB_mem, cvDlsBandJacBWrapper);
+    flag = CVDlsSetJacFn(cvodeB_mem, cvDlsJacBWrapper);
   } else {
-    flag = CVDlsSetBandJacFn(cvodeB_mem, NULL);
+    flag = CVDlsSetJacFn(cvodeB_mem, NULL);
   }
 
   return(flag);
 }
 
-int CVDlsSetBandJacFnBS(void *cvode_mem, int which, CVDlsBandJacFnBS jacBS)
+
+int CVDlsSetJacFnBS(void *cvode_mem, int which, CVDlsJacFnBS jacBS)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -712,21 +960,24 @@ int CVDlsSetBandJacFnBS(void *cvode_mem, int which, CVDlsBandJacFnBS jacBS)
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS", "CVDlsSetBandJacFnBS", MSGD_CVMEM_NULL);
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "CVDlsSetJacFnBS", MSGD_CVMEM_NULL);
     return(CVDLS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS", "CVDlsSetBandJacFnBS", MSGD_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS",
+                   "CVDlsSetJacFnBS", MSGD_NO_ADJ);
     return(CVDLS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS", "CVDlsSetBandJacFnBS", MSGD_BAD_WHICH);
+    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSDLS",
+                   "CVDlsSetJacFnBS", MSGD_BAD_WHICH);
     return(CVDLS_ILL_INPUT);
   }
 
@@ -740,82 +991,50 @@ int CVDlsSetBandJacFnBS(void *cvode_mem, int which, CVDlsBandJacFnBS jacBS)
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
   if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS", "CVDlsSetBandJacFnBS", MSGD_LMEMB_NULL);
+    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS",
+                   "CVDlsSetJacFnBS", MSGD_LMEMB_NULL);
     return(CVDLS_LMEMB_NULL);
   }
   cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
 
-  bjacBS = jacBS;
+  cvdlsB_mem->jacBS = jacBS;
 
   if (jacBS != NULL) {
-    flag = CVDlsSetBandJacFn(cvodeB_mem, cvDlsBandJacBSWrapper);
+    flag = CVDlsSetJacFn(cvodeB_mem, cvDlsJacBSWrapper);
   } else {
-    flag = CVDlsSetBandJacFn(cvodeB_mem, NULL);
+    flag = CVDlsSetJacFn(cvodeB_mem, NULL);
   }
 
   return(flag);
 }
 
 
-/*
- * -----------------------------------------------------------------
- * PRIVATE INTERFACE FUNCTIONS
- * -----------------------------------------------------------------
- */
-
-/*
- * cvDlsDenseJacBWrapper
- *
- * This routine interfaces to the CVDlsDenseJacFnB routine provided 
- * by the user. cvDlsDenseJacBWrapper is of type CVDlsDenseJacFn.
- * NOTE: data here contains cvode_mem
- */
+/*-----------------------------------------------------------------
+  PRIVATE INTERFACE FUNCTIONS
+  -----------------------------------------------------------------*/
 
-static int cvDlsDenseJacBWrapper(long int nB, realtype t,
-                                 N_Vector yB, N_Vector fyB, 
-                                 DlsMat JB, void *cvode_mem,
-                                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+int cvDlsFreeB(CVodeBMem cvB_mem)
 {
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
   CVDlsMemB cvdlsB_mem;
-  int retval, flag;
-
-  cv_mem = (CVodeMem) cvode_mem;
-
-  ca_mem = cv_mem->cv_adj_mem;
-
-  cvB_mem = ca_mem->ca_bckpbCrt;
 
+  /* Return immediately if IDAB_mem or IDAB_mem->ida_lmem are NULL */
+  if (cvB_mem == NULL)  return (CVDLS_SUCCESS);
+  if (cvB_mem->cv_lmem == NULL)  return(CVDLS_SUCCESS);
   cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
 
-  /* Forward solution from interpolation */
-  flag = IMget(cv_mem, t, ytmp, NULL);
-  if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsDenseJacBWrapper", MSGD_BAD_TINTERP);
-    return(-1);
-  }
-
-  /* Call user's adjoint dense djacB routine (of type CVDlsDenseJacFnB) */
-  retval = djacB(nB, t, ytmp, yB, fyB, JB, cvB_mem->cv_user_data, 
-                 tmp1B, tmp2B, tmp3B);
-
-  return(retval);
+  /* free CVDlsMemB interface structure */
+  free(cvdlsB_mem);
+  
+  return(CVDLS_SUCCESS);
 }
 
-/*
- * cvDlsDenseJacBSWrapper
- *
- * This routine interfaces to the CVDlsDenseJacFnBS routine provided 
- * by the user. cvDlsDenseJacBSWrapper is of type CVDlsDenseJacFn.
- * NOTE: data here contains cvode_mem
- */
 
-static int cvDlsDenseJacBSWrapper(long int nB, realtype t,
-                                 N_Vector yB, N_Vector fyB, 
-                                 DlsMat JB, void *cvode_mem,
-                                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+/* cvDlsJacBWrapper interfaces to the CVDlsJacFnB routine provided 
+   by the user. cvDlsJacBWrapper is of type CVDlsJacFn.
+   NOTE: data here contains cvode_mem */
+static int cvDlsJacBWrapper(realtype t, N_Vector yB, N_Vector fyB, 
+                            SUNMatrix JB, void *cvode_mem,
+                            N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -823,85 +1042,57 @@ static int cvDlsDenseJacBSWrapper(long int nB, realtype t,
   CVDlsMemB cvdlsB_mem;
   int retval, flag;
 
-  cv_mem = (CVodeMem) cvode_mem;
-
-  ca_mem = cv_mem->cv_adj_mem;
-
-  cvB_mem = ca_mem->ca_bckpbCrt;
-
-  cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
-
-  /* Forward solution from interpolation */
-  if (IMinterpSensi)
-    flag = IMget(cv_mem, t, ytmp, yStmp);
-  else 
-    flag = IMget(cv_mem, t, ytmp, NULL);
-  if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsDenseJacBSWrapper", MSGD_BAD_TINTERP);
-    return(-1);
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "cvDlsJacBWrapper", MSGD_CVMEM_NULL);
+    return(CVDLS_MEM_NULL);
   }
-
-  /* Call user's adjoint dense djacBS routine (of type CVDlsDenseJacFnBS) */
-  retval = djacBS(nB, t, ytmp, yStmp, yB, fyB, JB, cvB_mem->cv_user_data, 
-                  tmp1B, tmp2B, tmp3B);
-
-  return(retval);
-}
-
-
-/*
- * cvDlsBandJacBWrapper
- *
- * This routine interfaces to the CVBandJacFnB routine provided 
- * by the user. cvDlsBandJacBWrapper is of type CVDlsBandJacFn.
- * NOTE: data here contains cvode_mem
- */
-
-static int cvDlsBandJacBWrapper(long int nB, long int mupperB, long int mlowerB, 
-                                realtype t, N_Vector yB, N_Vector fyB, 
-                                DlsMat JB, void *cvode_mem, 
-                                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  CVDlsMemB cvdlsB_mem;
-  int retval, flag;
-
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS",
+                   "cvDlsJacBWrapper", MSGD_NO_ADJ);
+    return(CVDLS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS",
+                   "cvDlsJacBWrapper", MSGD_LMEMB_NULL);
+    return(CVDLS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS",
+                   "cvDlsJacBWrapper", MSGD_LMEMB_NULL);
+    return(CVDLS_LMEMB_NULL);
+  }
   cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
 
   /* Forward solution from interpolation */
-  flag = IMget(cv_mem, t, ytmp, NULL);
+  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsBandJacBWrapper", MSGD_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsJacBWrapper",
+                   MSGD_BAD_TINTERP);
     return(-1);
   }
 
-  /* Call user's adjoint band bjacB routine (of type CVDlsBandJacFnB) */
-  retval = bjacB(nB, mupperB, mlowerB, t, ytmp, yB, fyB, JB, cvB_mem->cv_user_data,
-                 tmp1B, tmp2B, tmp3B);
-
+  /* Call user's adjoint jacB routine (of type CVDlsJacFnB) */
+  retval = cvdlsB_mem->jacB(t, ca_mem->ca_ytmp, yB, fyB,
+                            JB, cvB_mem->cv_user_data,
+                            tmp1B, tmp2B, tmp3B);
   return(retval);
 }
 
-/*
- * cvDlsBandJacBSWrapper
- *
- * This routine interfaces to the CVBandJacFnBS routine provided 
- * by the user. cvDlsBandJacBSWrapper is of type CVDlsBandJacFn.
- * NOTE: data here contains cvode_mem
- */
-
-static int cvDlsBandJacBSWrapper(long int nB, long int mupperB, long int mlowerB, 
-                                realtype t, N_Vector yB, N_Vector fyB, 
-                                DlsMat JB, void *cvode_mem, 
-                                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+/* cvDlsJacBSWrapper interfaces to the CVDlsJacFnBS routine provided 
+   by the user. cvDlsJacBSWrapper is of type CVDlsJacFn.
+   NOTE: data here contains cvode_mem */
+static int cvDlsJacBSWrapper(realtype t, N_Vector yB, N_Vector fyB, 
+                             SUNMatrix JB, void *cvode_mem,
+                             N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -909,28 +1100,50 @@ static int cvDlsBandJacBSWrapper(long int nB, long int mupperB, long int mlowerB
   CVDlsMemB cvdlsB_mem;
   int retval, flag;
 
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSDLS",
+                   "cvDlsJacBSWrapper", MSGD_CVMEM_NULL);
+    return(CVDLS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSDLS",
+                   "cvDlsJacBSWrapper", MSGD_NO_ADJ);
+    return(CVDLS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS",
+                   "cvDlsJacBSWrapper", MSGD_LMEMB_NULL);
+    return(CVDLS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVDLS_LMEMB_NULL, "CVSDLS",
+                   "cvDlsJacBSWrapper", MSGD_LMEMB_NULL);
+    return(CVDLS_LMEMB_NULL);
+  }
   cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
 
   /* Forward solution from interpolation */
-  if (IMinterpSensi)
-    flag = IMget(cv_mem, t, ytmp, yStmp);
+  if (ca_mem->ca_IMinterpSensi)
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
   else 
-    flag = IMget(cv_mem, t, ytmp, NULL);
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsBandJacBSWrapper", MSGD_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSDLS", "cvDlsJacBSWrapper",
+                   MSGD_BAD_TINTERP);
     return(-1);
   }
 
-  /* Call user's adjoint band bjacBS routine (of type CVDlsBandJacFnBS) */
-  retval = bjacBS(nB, mupperB, mlowerB, t, ytmp, yStmp, yB, fyB, JB,
-                  cvB_mem->cv_user_data, tmp1B, tmp2B, tmp3B);
-
+  /* Call user's adjoint dense djacBS routine (of type CVDlsDenseJacFnBS) */
+  retval = cvdlsB_mem->jacBS(t, ca_mem->ca_ytmp, ca_mem->ca_yStmp,
+                             yB, fyB, JB, cvB_mem->cv_user_data, 
+                             tmp1B, tmp2B, tmp3B);
   return(retval);
 }
-
diff --git a/src/cvodes/cvodes_direct_impl.h b/src/cvodes/cvodes_direct_impl.h
index 2fa8a7d..f863d72 100644
--- a/src/cvodes/cvodes_direct_impl.h
+++ b/src/cvodes/cvodes_direct_impl.h
@@ -1,21 +1,23 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common implementation header file for the CVDLS linear solvers.
+ * Implementation header file for the CVSDLS linear solver interface
  * -----------------------------------------------------------------
  */
 
@@ -23,126 +25,121 @@
 #define _CVSDLS_IMPL_H
 
 #include <cvodes/cvodes_direct.h>
+#include "cvodes_impl.h"
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * =================================================================
- * C V S D I R E C T    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
+/*=================================================================
+  CVSDLS Internal Constants
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- * CVDLS solver constants
- * -----------------------------------------------------------------
- * CVD_MSBJ   maximum number of steps between Jacobian evaluations
- * CVD_DGMAX  maximum change in gamma between Jacobian evaluations
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  CVDLS solver constants
+  -----------------------------------------------------------------
+  CVD_MSBJ   maximum number of steps between Jacobian evaluations
+  CVD_DGMAX  maximum change in gamma between Jacobian evaluations
+  -----------------------------------------------------------------*/
 
 #define CVD_MSBJ  50
 #define CVD_DGMAX RCONST(0.2)
 
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
+  
+/*=================================================================
+  PART I:  Forward Problems
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- * Types: CVDlsMemRec, CVDlsMem                             
- * -----------------------------------------------------------------
- * CVDlsMem is pointer to a CVDlsMemRec structure.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types: CVDlsMemRec, CVDlsMem                             
+  -----------------------------------------------------------------
+  CVDlsMem is pointer to a CVDlsMemRec structure.
+  -----------------------------------------------------------------*/
 
 typedef struct CVDlsMemRec {
 
-  int d_type;             /* SUNDIALS_DENSE or SUNDIALS_BAND              */
-
-  long int d_n;           /* problem dimension                            */
+  booleantype jacDQ;    /* SUNTRUE if using internal DQ Jacobian approx. */
+  CVDlsJacFn jac;       /* Jacobian routine to be called                 */
+  void *J_data;         /* data pointer passed to jac                    */
 
-  long int d_ml;          /* lower bandwidth of Jacobian                  */
-  long int d_mu;          /* upper bandwidth of Jacobian                  */ 
-  long int d_smu;         /* upper bandwith of M = MIN(N-1,d_mu+d_ml)     */
+  SUNMatrix A;          /* A = I - gamma * df/dy                         */
+  SUNMatrix savedJ;     /* savedJ = old Jacobian                         */
 
-  booleantype d_jacDQ;    /* TRUE if using internal DQ Jacobian approx.   */
-  CVDlsDenseJacFn d_djac; /* dense Jacobian routine to be called          */
-  CVDlsBandJacFn d_bjac;  /* band Jacobian routine to be called           */
-  void *d_J_data;         /* data pointer passed to djac or bjac          */
+  SUNLinearSolver LS;   /* generic direct linear solver object           */
 
-  DlsMat d_M;             /* M = I - gamma * df/dy                        */
-  DlsMat d_savedJ;        /* savedJ = old Jacobian                        */
-
-  int *d_pivots;          /* pivots = int pivot array for PM = LU         */
-  long int *d_lpivots;    /* lpivots = long int pivot array for PM = LU   */
+  N_Vector x;           /* solution vector used by SUNLinearSolver       */
   
-  long int  d_nstlj;      /* nstlj = nst at last Jacobian eval.           */
+  long int nstlj;       /* nstlj = nst at last Jacobian eval.            */
 
-  long int d_nje;         /* nje = no. of calls to jac                    */
+  long int nje;         /* nje = no. of calls to jac                     */
 
-  long int d_nfeDQ;       /* no. of calls to f due to DQ Jacobian approx. */
+  long int nfeDQ;       /* no. of calls to f due to DQ Jacobian approx.  */
+
+  long int last_flag;   /* last error return flag                        */
 
-  long int d_last_flag;   /* last error return flag                       */
-  
 } *CVDlsMem;
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  PRIVATE FUNCTIONS 
+  -----------------------------------------------------------------*/
+
+/* difference-quotient Jacobian approximation routines */
+int cvDlsDQJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix Jac,
+               void *data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+  
+int cvDlsDenseDQJac(realtype t, N_Vector y, N_Vector fy, 
+                    SUNMatrix Jac, CVodeMem cv_mem, N_Vector tmp1);
+  
+int cvDlsBandDQJac(realtype t, N_Vector y, N_Vector fy, SUNMatrix Jac,
+                   CVodeMem cv_mem, N_Vector tmp1, N_Vector tmp2);
+  
+/* generic linit/lsetup/lsolve/lfree interface routines for CVode to call */
+int cvDlsInitialize(CVodeMem cv_mem);
 
-int cvDlsDenseDQJac(long int N, realtype t,
-                    N_Vector y, N_Vector fy, 
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+int cvDlsSetup(CVodeMem cv_mem, int convfail, N_Vector y, 
+               N_Vector fy, booleantype *jcurPtr, 
+               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); 
   
-int cvDlsBandDQJac(long int N, long int mupper, long int mlower,
-                   realtype t, N_Vector y, N_Vector fy, 
-                   DlsMat Jac, void *data,
-                   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+int cvDlsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+               N_Vector ycur, N_Vector fcur);
+
+int cvDlsFree(CVodeMem cv_mem);
 
 /* Auxilliary functions */
 int cvDlsInitializeCounters(CVDlsMem cvdls_mem);
 
 
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
+/*=================================================================
+  PART II:  Backward Problems
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- * Types : CVDlsMemRecB, CVDlsMemB       
- * -----------------------------------------------------------------
- * A CVDLS linear solver's specification function attaches such
- * a structure to the lmemB filed of CVodeBMem
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types : CVDlsMemRecB, CVDlsMemB       
+  -----------------------------------------------------------------
+  A CVDLS linear solver's specification function attaches such
+  a structure to the lmemB filed of CVodeBMem
+  -----------------------------------------------------------------*/
 
 typedef struct CVDlsMemRecB {
 
-  int d_typeB;
-
-  CVDlsDenseJacFnB d_djacB;
-  CVDlsDenseJacFnBS d_djacBS;
-  CVDlsBandJacFnB d_bjacB;
-  CVDlsBandJacFnBS d_bjacBS;
+  CVDlsJacFnB jacB;
+  CVDlsJacFnBS jacBS;
 
 } *CVDlsMemB;
 
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
 
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
+int cvDlsFreeB(CVodeBMem cvb_mem);
+
+/*=================================================================
+  Error Messages
+  =================================================================*/
 
 #define MSGD_CVMEM_NULL "Integrator memory is NULL."
 #define MSGD_BAD_NVECTOR "A required vector operation is not implemented."
@@ -150,7 +147,9 @@ typedef struct CVDlsMemRecB {
 #define MSGD_MEM_FAIL "A memory request failed."
 #define MSGD_LMEM_NULL "Linear solver memory is NULL."
 #define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
-
+#define MSGD_MATCOPY_FAILED "The SUNMatCopy routine failed in an unrecoverable manner."
+#define MSGD_MATZERO_FAILED "The SUNMatZero routine failed in an unrecoverable manner."
+#define MSGD_MATSCALEADDI_FAILED "The SUNMatScaleAddI routine failed in an unrecoverable manner."
 
 #define MSGD_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc."
 #define MSGD_BAD_WHICH "Illegal value for which."
diff --git a/src/cvodes/cvodes_impl.h b/src/cvodes/cvodes_impl.h
index 41409b0..657e5cd 100644
--- a/src/cvodes/cvodes_impl.h
+++ b/src/cvodes/cvodes_impl.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -80,46 +80,46 @@ typedef struct CVodeBMemRec *CVodeBMem;
   
 typedef struct CVodeMemRec {
     
-  realtype cv_uround;         /* machine unit roundoff                        */   
+  realtype cv_uround;         /* machine unit roundoff                         */   
 
   /*-------------------------- 
     Problem Specification Data 
     --------------------------*/
 
-  CVRhsFn cv_f;               /* y' = f(t,y(t))                               */
-  void *cv_user_data;         /* user pointer passed to f                     */
+  CVRhsFn cv_f;               /* y' = f(t,y(t))                                */
+  void *cv_user_data;         /* user pointer passed to f                      */
 
-  int cv_lmm;                 /* lmm = ADAMS or BDF                           */
-  int cv_iter;                /* iter = FUNCTIONAL or NEWTON                  */
+  int cv_lmm;                 /* lmm = ADAMS or BDF                            */
+  int cv_iter;                /* iter = FUNCTIONAL or NEWTON                   */
 
-  int cv_itol;                /* itol = CV_SS, CV_SV, or CV_WF, or CV_NN      */
-  realtype cv_reltol;         /* relative tolerance                           */
-  realtype cv_Sabstol;        /* scalar absolute tolerance                    */
-  N_Vector cv_Vabstol;        /* vector absolute tolerance                    */
-  booleantype cv_user_efun;   /* TRUE if user sets efun                       */
-  CVEwtFn cv_efun;            /* function to set ewt                          */
-  void *cv_e_data;            /* user pointer passed to efun                  */
+  int cv_itol;                /* itol = CV_SS, CV_SV, or CV_WF, or CV_NN       */
+  realtype cv_reltol;         /* relative tolerance                            */
+  realtype cv_Sabstol;        /* scalar absolute tolerance                     */
+  N_Vector cv_Vabstol;        /* vector absolute tolerance                     */
+  booleantype cv_user_efun;   /* SUNTRUE if user sets efun                     */
+  CVEwtFn cv_efun;            /* function to set ewt                           */
+  void *cv_e_data;            /* user pointer passed to efun                   */
 
   /*-----------------------
     Quadrature Related Data 
     -----------------------*/
 
-  booleantype cv_quadr;       /* TRUE if integrating quadratures              */
+  booleantype cv_quadr;       /* SUNTRUE if integrating quadratures            */
 
-  CVQuadRhsFn cv_fQ;          /* q' = fQ(t, y(t))                             */
+  CVQuadRhsFn cv_fQ;          /* q' = fQ(t, y(t))                              */
 
-  booleantype cv_errconQ;     /* TRUE if quadrs. are included in error test   */
+  booleantype cv_errconQ;     /* SUNTRUE if quadrs. are included in error test */
 
-  int cv_itolQ;               /* itolQ = CV_SS or CV_SV                       */
-  realtype cv_reltolQ;        /* relative tolerance for quadratures           */
-  realtype cv_SabstolQ;       /* scalar absolute tolerance for quadratures    */
-  N_Vector cv_VabstolQ;       /* vector absolute tolerance for quadratures    */
+  int cv_itolQ;               /* itolQ = CV_SS or CV_SV                        */
+  realtype cv_reltolQ;        /* relative tolerance for quadratures            */
+  realtype cv_SabstolQ;       /* scalar absolute tolerance for quadratures     */
+  N_Vector cv_VabstolQ;       /* vector absolute tolerance for quadratures     */
 
   /*------------------------
     Sensitivity Related Data 
     ------------------------*/
 
-  booleantype cv_sensi;       /* TRUE if computing sensitivities              */
+  booleantype cv_sensi;       /* SUNTRUE if computing sensitivities           */
 
   int cv_Ns;                  /* Number of sensitivities                      */
 
@@ -128,7 +128,7 @@ typedef struct CVodeMemRec {
   CVSensRhsFn cv_fS;          /* fS = (df/dy)*yS + (df/dp)                    */
   CVSensRhs1Fn cv_fS1;        /* fS1 = (df/dy)*yS_i + (df/dp)                 */
   void *cv_fS_data;           /* data pointer passed to fS                    */
-  booleantype cv_fSDQ;        /* TRUE if using internal DQ functions          */
+  booleantype cv_fSDQ;        /* SUNTRUE if using internal DQ functions       */
   int cv_ifS;                 /* ifS = ALLSENS or ONESENS                     */
 
   realtype *cv_p;             /* parameters in f(t,y,p)                       */
@@ -137,7 +137,7 @@ typedef struct CVodeMemRec {
   int cv_DQtype;              /* central/forward finite differences           */
   realtype cv_DQrhomax;       /* cut-off value for separate/simultaneous FD   */
 
-  booleantype cv_errconS;     /* TRUE if yS are considered in err. control    */
+  booleantype cv_errconS;     /* SUNTRUE if yS are considered in err. control */
 
   int cv_itolS;
   realtype cv_reltolS;        /* relative tolerance for sensitivities         */
@@ -148,13 +148,13 @@ typedef struct CVodeMemRec {
     Quadrature Sensitivity Related Data 
     -----------------------------------*/
 
-  booleantype cv_quadr_sensi; /* TRUE if computing sensitivties of quadrs.    */
+  booleantype cv_quadr_sensi; /* SUNTRUE if computing sensitivties of quadrs. */
 
   CVQuadSensRhsFn cv_fQS;     /* fQS = (dfQ/dy)*yS + (dfQ/dp)                 */
   void *cv_fQS_data;          /* data pointer passed to fQS                   */
-  booleantype cv_fQSDQ;       /* TRUE if using internal DQ functions          */
+  booleantype cv_fQSDQ;       /* SUNTRUE if using internal DQ functions       */
 
-  booleantype cv_errconQS;    /* TRUE if yQS are considered in err. con.      */
+  booleantype cv_errconQS;    /* SUNTRUE if yQS are considered in err. con.   */
 
   int cv_itolQS;
   realtype cv_reltolQS;       /* relative tolerance for yQS                   */
@@ -283,7 +283,7 @@ typedef struct CVodeMemRec {
 			      user that t + h == t for the next internal step */
   int cv_maxnef;           /* maximum number of error test failures           */
   int cv_maxncf;           /* maximum number of nonlinear conv. failures      */
-
+  
   realtype cv_hmin;        /* |h| >= hmin                                     */
   realtype cv_hmax_inv;    /* |h| <= 1/hmax_inv                               */
   realtype cv_etamax;      /* eta <= etamax                                   */
@@ -325,12 +325,12 @@ typedef struct CVodeMemRec {
     Space requirements for CVODES 
     -----------------------------*/
 
-  long int cv_lrw1;        /* no. of realtype words in 1 N_Vector y           */ 
-  long int cv_liw1;        /* no. of integer words in 1 N_Vector y            */ 
-  long int cv_lrw1Q;       /* no. of realtype words in 1 N_Vector yQ          */ 
-  long int cv_liw1Q;       /* no. of integer words in 1 N_Vector yQ           */ 
-  long int cv_lrw;         /* no. of realtype words in CVODES work vectors    */
-  long int cv_liw;         /* no. of integer words in CVODES work vectors     */
+  sunindextype cv_lrw1;        /* no. of realtype words in 1 N_Vector y           */ 
+  sunindextype cv_liw1;        /* no. of integer words in 1 N_Vector y            */ 
+  sunindextype cv_lrw1Q;       /* no. of realtype words in 1 N_Vector yQ          */ 
+  sunindextype cv_liw1Q;       /* no. of integer words in 1 N_Vector yQ           */ 
+  long int cv_lrw;             /* no. of realtype words in CVODES work vectors    */
+  long int cv_liw;             /* no. of integer words in CVODES work vectors     */
 
   /*----------------
     Step size ratios
@@ -375,13 +375,13 @@ typedef struct CVodeMemRec {
   realtype cv_hu;              /* last successful h value used                */
   realtype cv_saved_tq5;       /* saved value of tq[5]                        */
   booleantype cv_jcur;         /* is Jacobian info for linear solver current? */
+  int cv_convfail;             /* flag storing previous solver failure mode   */
   realtype cv_tolsf;           /* tolerance scale factor                      */
   int cv_qmax_alloc;           /* qmax used when allocating mem               */
   int cv_qmax_allocQ;          /* qmax used when allocating quad. mem         */
   int cv_qmax_allocS;          /* qmax used when allocating sensi. mem        */
   int cv_qmax_allocQS;         /* qmax used when allocating quad. sensi. mem  */
   int cv_indx_acor;            /* index of zn vector in which acor is saved   */
-  booleantype cv_setupNonNull; /* Does setup do something?                    */
 
   /*--------------------------------------------------------------------
     Flags turned ON by CVodeInit, CVodeSensMalloc, and CVodeQuadMalloc 
@@ -445,7 +445,7 @@ typedef struct CVodeMemRec {
     Adjoint sensitivity data
     ------------------------*/
 
-  booleantype cv_adj;             /* TRUE if performing ASA                   */
+  booleantype cv_adj;             /* SUNTRUE if performing ASA                */
 
   struct CVadjMemRec *cv_adj_mem; /* Pointer to adjoint memory structure      */
 
@@ -825,12 +825,12 @@ struct CVadjMemRec {
  * fpred - f(tn, ypred).
  *
  * jcurPtr - a pointer to a boolean to be filled in by cv_lsetup.
- *           The function should set *jcurPtr=TRUE if its Jacobian
+ *           The function should set *jcurPtr=SUNTRUE if its Jacobian
  *           data is current after the call and should set
- *           *jcurPtr=FALSE if its Jacobian data is not current.
+ *           *jcurPtr=SUNFALSE if its Jacobian data is not current.
  *           Note: If cv_lsetup calls for re-evaluation of
  *           Jacobian data (based on convfail and CVODE state
- *           data), it should return *jcurPtr=TRUE always;
+ *           data), it should return *jcurPtr=SUNTRUE always;
  *           otherwise an infinite loop can result.
  *
  * vtemp1 - temporary N_Vector provided for use by cv_lsetup.
diff --git a/src/cvodes/cvodes_io.c b/src/cvodes/cvodes_io.c
index 8468429..a4dc6fd 100644
--- a/src/cvodes/cvodes_io.c
+++ b/src/cvodes/cvodes_io.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4272 $
- * $Date: 2014-12-02 11:19:41 -0800 (Tue, 02 Dec 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -375,7 +375,7 @@ int CVodeSetStopTime(void *cvode_mem, realtype tstop)
   }
 
   cv_mem->cv_tstop = tstop;
-  cv_mem->cv_tstopset = TRUE;
+  cv_mem->cv_tstopset = SUNTRUE;
 
   return(CV_SUCCESS);
 }
@@ -631,7 +631,7 @@ int CVodeSetSensParams(void *cvode_mem, realtype *p, realtype *pbar, int *plist)
 
   /* Was sensitivity initialized? */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSetSensParams", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
@@ -687,14 +687,14 @@ int CVodeSetQuadSensErrCon(void *cvode_mem, booleantype errconQS)
 
   /* Was sensitivity initialized? */
 
-  if (cv_mem->cv_SensMallocDone == FALSE) {
+  if (cv_mem->cv_SensMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeSetQuadSensTolerances", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   } 
 
   /* Ckeck if quadrature sensitivity was initialized? */
 
-  if (cv_mem->cv_QuadSensMallocDone == FALSE) {
+  if (cv_mem->cv_QuadSensMallocDone == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeSetQuadSensErrCon", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUAD);
   }
@@ -710,33 +710,6 @@ int CVodeSetQuadSensErrCon(void *cvode_mem, booleantype errconQS)
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define nst            (cv_mem->cv_nst)
-#define nfe            (cv_mem->cv_nfe)
-#define ncfn           (cv_mem->cv_ncfn)
-#define netf           (cv_mem->cv_netf)
-#define nni            (cv_mem->cv_nni)
-#define nsetups        (cv_mem->cv_nsetups)
-#define qu             (cv_mem->cv_qu)
-#define next_q         (cv_mem->cv_next_q)
-#define ewt            (cv_mem->cv_ewt)  
-#define hu             (cv_mem->cv_hu)
-#define next_h         (cv_mem->cv_next_h)
-#define h0u            (cv_mem->cv_h0u)
-#define tolsf          (cv_mem->cv_tolsf)  
-#define acor           (cv_mem->cv_acor)
-#define lrw            (cv_mem->cv_lrw)
-#define liw            (cv_mem->cv_liw)
-#define nge            (cv_mem->cv_nge)
-#define iroots         (cv_mem->cv_iroots)
-#define nor            (cv_mem->cv_nor)
-#define sldeton        (cv_mem->cv_sldeton)
-#define tn             (cv_mem->cv_tn)
-#define efun           (cv_mem->cv_efun)
-
 /*
  * CVodeGetNumSteps
  *
@@ -754,7 +727,7 @@ int CVodeGetNumSteps(void *cvode_mem, long int *nsteps)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nsteps = nst;
+  *nsteps = cv_mem->cv_nst;
 
   return(CV_SUCCESS);
 }
@@ -776,7 +749,7 @@ int CVodeGetNumRhsEvals(void *cvode_mem, long int *nfevals)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nfevals = nfe;
+  *nfevals = cv_mem->cv_nfe;
 
   return(CV_SUCCESS);
 }
@@ -798,7 +771,7 @@ int CVodeGetNumLinSolvSetups(void *cvode_mem, long int *nlinsetups)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nlinsetups = nsetups;
+  *nlinsetups = cv_mem->cv_nsetups;
 
   return(CV_SUCCESS);
 }
@@ -820,7 +793,7 @@ int CVodeGetNumErrTestFails(void *cvode_mem, long int *netfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *netfails = netf;
+  *netfails = cv_mem->cv_netf;
 
   return(CV_SUCCESS);
 }
@@ -842,7 +815,7 @@ int CVodeGetLastOrder(void *cvode_mem, int *qlast)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *qlast = qu;
+  *qlast = cv_mem->cv_qu;
 
   return(CV_SUCCESS);
 }
@@ -864,7 +837,7 @@ int CVodeGetCurrentOrder(void *cvode_mem, int *qcur)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *qcur = next_q;
+  *qcur = cv_mem->cv_next_q;
 
   return(CV_SUCCESS);
 }
@@ -887,10 +860,10 @@ int CVodeGetNumStabLimOrderReds(void *cvode_mem, long int *nslred)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sldeton==FALSE)
+  if (cv_mem->cv_sldeton==SUNFALSE)
     *nslred = 0;
   else
-    *nslred = nor;
+    *nslred = cv_mem->cv_nor;
 
   return(CV_SUCCESS);
 }
@@ -912,7 +885,7 @@ int CVodeGetActualInitStep(void *cvode_mem, realtype *hinused)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *hinused = h0u;
+  *hinused = cv_mem->cv_h0u;
 
   return(CV_SUCCESS);
 }
@@ -934,7 +907,7 @@ int CVodeGetLastStep(void *cvode_mem, realtype *hlast)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *hlast = hu;
+  *hlast = cv_mem->cv_hu;
 
   return(CV_SUCCESS);
 }
@@ -956,7 +929,7 @@ int CVodeGetCurrentStep(void *cvode_mem, realtype *hcur)
 
   cv_mem = (CVodeMem) cvode_mem;
   
-  *hcur = next_h;
+  *hcur = cv_mem->cv_next_h;
 
   return(CV_SUCCESS);
 }
@@ -978,7 +951,7 @@ int CVodeGetCurrentTime(void *cvode_mem, realtype *tcur)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *tcur = tn;
+  *tcur = cv_mem->cv_tn;
 
   return(CV_SUCCESS);
 }
@@ -1000,7 +973,7 @@ int CVodeGetTolScaleFactor(void *cvode_mem, realtype *tolsfact)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *tolsfact = tolsf;
+  *tolsfact = cv_mem->cv_tolsf;
 
   return(CV_SUCCESS);
 }
@@ -1022,7 +995,7 @@ int CVodeGetErrWeights(void *cvode_mem, N_Vector eweight)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  N_VScale(ONE, ewt, eweight);
+  N_VScale(ONE, cv_mem->cv_ewt, eweight);
 
   return(CV_SUCCESS);
 }
@@ -1044,7 +1017,7 @@ int CVodeGetEstLocalErrors(void *cvode_mem, N_Vector ele)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  N_VScale(ONE, acor, ele);
+  N_VScale(ONE, cv_mem->cv_acor, ele);
 
   return(CV_SUCCESS);
 }
@@ -1066,8 +1039,8 @@ int CVodeGetWorkSpace(void *cvode_mem, long int *lenrw, long int *leniw)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *leniw = liw;
-  *lenrw = lrw;
+  *leniw = cv_mem->cv_liw;
+  *lenrw = cv_mem->cv_lrw;
 
   return(CV_SUCCESS);
 }
@@ -1092,16 +1065,16 @@ int CVodeGetIntegratorStats(void *cvode_mem, long int *nsteps, long int *nfevals
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nsteps = nst;
-  *nfevals = nfe;
-  *nlinsetups = nsetups;
-  *netfails = netf;
-  *qlast = qu;
-  *qcur = next_q;
-  *hinused = h0u;
-  *hlast = hu;
-  *hcur = next_h;
-  *tcur = tn;
+  *nsteps = cv_mem->cv_nst;
+  *nfevals = cv_mem->cv_nfe;
+  *nlinsetups = cv_mem->cv_nsetups;
+  *netfails = cv_mem->cv_netf;
+  *qlast = cv_mem->cv_qu;
+  *qcur = cv_mem->cv_next_q;
+  *hinused = cv_mem->cv_h0u;
+  *hlast = cv_mem->cv_hu;
+  *hcur = cv_mem->cv_next_h;
+  *tcur = cv_mem->cv_tn;
 
   return(CV_SUCCESS);
 }
@@ -1123,7 +1096,7 @@ int CVodeGetNumGEvals(void *cvode_mem, long int *ngevals)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *ngevals = nge;
+  *ngevals = cv_mem->cv_nge;
 
   return(CV_SUCCESS);
 }
@@ -1148,7 +1121,7 @@ int CVodeGetRootInfo(void *cvode_mem, int *rootsfound)
 
   nrt = cv_mem->cv_nrtfn;
 
-  for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+  for (i=0; i<nrt; i++) rootsfound[i] = cv_mem->cv_iroots[i];
 
   return(CV_SUCCESS);
 }
@@ -1171,7 +1144,7 @@ int CVodeGetNumNonlinSolvIters(void *cvode_mem, long int *nniters)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nniters = nni;
+  *nniters = cv_mem->cv_nni;
 
   return(CV_SUCCESS);
 }
@@ -1194,7 +1167,7 @@ int CVodeGetNumNonlinSolvConvFails(void *cvode_mem, long int *nncfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nncfails = ncfn;
+  *nncfails = cv_mem->cv_ncfn;
 
   return(CV_SUCCESS);
 }
@@ -1217,8 +1190,8 @@ int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters,
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  *nniters = nni;
-  *nncfails = ncfn;
+  *nniters = cv_mem->cv_nni;
+  *nncfails = cv_mem->cv_ncfn;
 
   return(CV_SUCCESS);
 }
@@ -1230,16 +1203,6 @@ int CVodeGetNonlinSolvStats(void *cvode_mem, long int *nniters,
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define quadr          (cv_mem->cv_quadr)
-#define nfQe           (cv_mem->cv_nfQe)
-#define netfQ          (cv_mem->cv_netfQ)
-#define ewtQ           (cv_mem->cv_ewtQ)
-#define errconQ        (cv_mem->cv_errconQ)
-
 /*-----------------------------------------------------------------*/
 
 int CVodeGetQuadNumRhsEvals(void *cvode_mem, long int *nfQevals)
@@ -1253,12 +1216,12 @@ int CVodeGetQuadNumRhsEvals(void *cvode_mem, long int *nfQevals)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr==FALSE) {
+  if (cv_mem->cv_quadr==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadNumRhsEvals", MSGCV_NO_QUAD); 
     return(CV_NO_QUAD);
   }
 
-  *nfQevals = nfQe;
+  *nfQevals = cv_mem->cv_nfQe;
 
   return(CV_SUCCESS);
 }
@@ -1276,12 +1239,12 @@ int CVodeGetQuadNumErrTestFails(void *cvode_mem, long int *nQetfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr==FALSE) {
+  if (cv_mem->cv_quadr==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadNumErrTestFails", MSGCV_NO_QUAD); 
     return(CV_NO_QUAD);
   }
 
-  *nQetfails = netfQ;
+  *nQetfails = cv_mem->cv_netfQ;
 
   return(CV_SUCCESS);
 }
@@ -1299,12 +1262,12 @@ int CVodeGetQuadErrWeights(void *cvode_mem, N_Vector eQweight)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr==FALSE) {
+  if (cv_mem->cv_quadr==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadErrWeights", MSGCV_NO_QUAD); 
     return(CV_NO_QUAD);
   }
 
-  if(errconQ) N_VScale(ONE, ewtQ, eQweight);
+  if(cv_mem->cv_errconQ) N_VScale(ONE, cv_mem->cv_ewtQ, eQweight);
 
   return(CV_SUCCESS);
 }
@@ -1322,13 +1285,13 @@ int CVodeGetQuadStats(void *cvode_mem, long int *nfQevals, long int *nQetfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr==FALSE) {
+  if (cv_mem->cv_quadr==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUAD, "CVODES", "CVodeGetQuadStats", MSGCV_NO_QUAD); 
     return(CV_NO_QUAD);
   }
 
-  *nfQevals = nfQe;
-  *nQetfails = netfQ;
+  *nfQevals = cv_mem->cv_nfQe;
+  *nQetfails = cv_mem->cv_netfQ;
 
   return(CV_SUCCESS);
 }
@@ -1339,16 +1302,6 @@ int CVodeGetQuadStats(void *cvode_mem, long int *nfQevals, long int *nQetfails)
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define quadr_sensi    (cv_mem->cv_quadr_sensi)
-#define nfQSe          (cv_mem->cv_nfQSe)
-#define netfQS         (cv_mem->cv_netfQS)
-#define ewtQS          (cv_mem->cv_ewtQS)
-#define errconQS       (cv_mem->cv_errconQS)
-
 /*-----------------------------------------------------------------*/
 
 int CVodeGetQuadSensNumRhsEvals(void *cvode_mem, long int *nfQSevals)
@@ -1362,12 +1315,12 @@ int CVodeGetQuadSensNumRhsEvals(void *cvode_mem, long int *nfQSevals)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (cv_mem->cv_quadr_sensi == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensNumRhsEvals", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUADSENS);
   }
 
-  *nfQSevals = nfQSe;
+  *nfQSevals = cv_mem->cv_nfQSe;
 
   return(CV_SUCCESS);
 }
@@ -1385,12 +1338,12 @@ int CVodeGetQuadSensNumErrTestFails(void *cvode_mem, long int *nQSetfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (cv_mem->cv_quadr_sensi == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensNumErrTestFails", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUADSENS);
   }
 
-  *nQSetfails = netfQS;
+  *nQSetfails = cv_mem->cv_netfQS;
 
   return(CV_SUCCESS);
 }
@@ -1409,15 +1362,15 @@ int CVodeGetQuadSensErrWeights(void *cvode_mem, N_Vector *eQSweight)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (cv_mem->cv_quadr_sensi == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensErrWeights", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUADSENS);
   }
   Ns = cv_mem->cv_Ns;
 
-  if (errconQS)
+  if (cv_mem->cv_errconQS)
     for (is=0; is<Ns; is++)
-      N_VScale(ONE, ewtQS[is], eQSweight[is]);
+      N_VScale(ONE, cv_mem->cv_ewtQS[is], eQSweight[is]);
 
   return(CV_SUCCESS);
 }
@@ -1435,13 +1388,13 @@ int CVodeGetQuadSensStats(void *cvode_mem, long int *nfQSevals, long int *nQSetf
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (cv_mem->cv_quadr_sensi == SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_QUADSENS, "CVODES", "CVodeGetQuadSensStats", MSGCV_NO_QUADSENSI); 
     return(CV_NO_QUADSENS);
   }
 
-  *nfQSevals = nfQSe;
-  *nQSetfails = netfQS;
+  *nfQSevals = cv_mem->cv_nfQSe;
+  *nQSetfails = cv_mem->cv_netfQS;
 
   return(CV_SUCCESS);
 }
@@ -1453,23 +1406,6 @@ int CVodeGetQuadSensStats(void *cvode_mem, long int *nfQSevals, long int *nQSetf
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define sensi          (cv_mem->cv_sensi)
-#define ism            (cv_mem->cv_ism)
-#define ewtS           (cv_mem->cv_ewtS)
-#define nfSe           (cv_mem->cv_nfSe)
-#define nfeS           (cv_mem->cv_nfeS)
-#define nniS           (cv_mem->cv_nniS)
-#define ncfnS          (cv_mem->cv_ncfnS)
-#define netfS          (cv_mem->cv_netfS)
-#define nsetupsS       (cv_mem->cv_nsetupsS)
-#define nniS1          (cv_mem->cv_nniS1)
-#define ncfnS1         (cv_mem->cv_ncfnS1)
-#define ncfS1          (cv_mem->cv_ncfS1)
-
 /*-----------------------------------------------------------------*/
 
 int CVodeGetSensNumRhsEvals(void *cvode_mem, long int *nfSevals)
@@ -1483,12 +1419,12 @@ int CVodeGetSensNumRhsEvals(void *cvode_mem, long int *nfSevals)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumRhsEvals", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nfSevals = nfSe;
+  *nfSevals = cv_mem->cv_nfSe;
 
   return(CV_SUCCESS);
 }
@@ -1506,12 +1442,12 @@ int CVodeGetNumRhsEvalsSens(void *cvode_mem, long int *nfevalsS)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetNumRhsEvalsSens", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nfevalsS = nfeS;
+  *nfevalsS = cv_mem->cv_nfeS;
 
   return(CV_SUCCESS);
 }
@@ -1529,12 +1465,12 @@ int CVodeGetSensNumErrTestFails(void *cvode_mem, long int *nSetfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumErrTestFails", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nSetfails = netfS;
+  *nSetfails = cv_mem->cv_netfS;
 
   return(CV_SUCCESS);
 }
@@ -1552,12 +1488,12 @@ int CVodeGetSensNumLinSolvSetups(void *cvode_mem, long int *nlinsetupsS)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumLinSolvSetups", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nlinsetupsS = nsetupsS;
+  *nlinsetupsS = cv_mem->cv_nsetupsS;
 
   return(CV_SUCCESS);
 }
@@ -1576,7 +1512,7 @@ int CVodeGetSensErrWeights(void *cvode_mem, N_Vector *eSweight)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensErrWeights", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
@@ -1584,7 +1520,7 @@ int CVodeGetSensErrWeights(void *cvode_mem, N_Vector *eSweight)
   Ns = cv_mem->cv_Ns;
 
   for (is=0; is<Ns; is++)
-    N_VScale(ONE, ewtS[is], eSweight[is]);
+    N_VScale(ONE, cv_mem->cv_ewtS[is], eSweight[is]);
 
   return(CV_SUCCESS);
 }
@@ -1603,15 +1539,15 @@ int CVodeGetSensStats(void *cvode_mem, long int *nfSevals, long int *nfevalsS,
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensStats", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nfSevals = nfSe;
-  *nfevalsS = nfeS;
-  *nSetfails = netfS;
-  *nlinsetupsS = nsetupsS;
+  *nfSevals = cv_mem->cv_nfSe;
+  *nfevalsS = cv_mem->cv_nfeS;
+  *nSetfails = cv_mem->cv_netfS;
+  *nlinsetupsS = cv_mem->cv_nsetupsS;
 
   return(CV_SUCCESS);
 }
@@ -1629,12 +1565,12 @@ int CVodeGetSensNumNonlinSolvIters(void *cvode_mem, long int *nSniters)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumNonlinSolvIters", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nSniters = nniS;
+  *nSniters = cv_mem->cv_nniS;
 
   return(CV_SUCCESS);
 }
@@ -1652,12 +1588,12 @@ int CVodeGetSensNumNonlinSolvConvFails(void *cvode_mem, long int *nSncfails)
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNumNonlinSolvConvFails", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nSncfails = ncfnS;
+  *nSncfails = cv_mem->cv_ncfnS;
 
   return(CV_SUCCESS);
 }
@@ -1678,13 +1614,13 @@ int CVodeGetStgrSensNumNonlinSolvIters(void *cvode_mem, long int *nSTGR1niters)
 
   Ns = cv_mem->cv_Ns;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetStgrSensNumNonlinSolvIters", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  if(ism==CV_STAGGERED1) 
-    for(is=0; is<Ns; is++) nSTGR1niters[is] = nniS1[is];
+  if(cv_mem->cv_ism==CV_STAGGERED1) 
+    for(is=0; is<Ns; is++) nSTGR1niters[is] = cv_mem->cv_nniS1[is];
 
   return(CV_SUCCESS);
 }
@@ -1705,13 +1641,13 @@ int CVodeGetStgrSensNumNonlinSolvConvFails(void *cvode_mem, long int *nSTGR1ncfa
 
   Ns = cv_mem->cv_Ns;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetStgrSensNumNonlinSolvConvFails", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  if(ism==CV_STAGGERED1) 
-    for(is=0; is<Ns; is++) nSTGR1ncfails[is] = ncfnS1[is];
+  if(cv_mem->cv_ism==CV_STAGGERED1) 
+    for(is=0; is<Ns; is++) nSTGR1ncfails[is] = cv_mem->cv_ncfnS1[is];
 
   return(CV_SUCCESS);
 }
@@ -1730,13 +1666,13 @@ int CVodeGetSensNonlinSolvStats(void *cvode_mem, long int *nSniters,
 
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (sensi==FALSE) {
+  if (cv_mem->cv_sensi==SUNFALSE) {
     cvProcessError(cv_mem, CV_NO_SENS, "CVODES", "CVodeGetSensNonlinSolvStats", MSGCV_NO_SENSI);
     return(CV_NO_SENS);
   }
 
-  *nSniters = nniS;
-  *nSncfails = ncfnS;
+  *nSniters = cv_mem->cv_nniS;
+  *nSncfails = cv_mem->cv_ncfnS;
 
   return(CV_SUCCESS);
 }
diff --git a/src/cvodes/cvodes_klu.c b/src/cvodes/cvodes_klu.c
deleted file mode 100644
index 575cd82..0000000
--- a/src/cvodes/cvodes_klu.c
+++ /dev/null
@@ -1,818 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4951 $
- * $Date: 2016-09-22 10:21:00 -0700 (Thu, 22 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVKLU linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cvodes/cvodes_klu.h"
-#include "cvodes_impl.h"
-#include "cvodes_sparse_impl.h"
-#include "sundials/sundials_klu_impl.h"
-#include "sundials/sundials_math.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-#define TWOTHIRDS    RCONST(0.6666666666666667)
-
-/* CVKLU linit, lsetup, lsolve, and lfree routines */
- 
-static int cvKLUInit(CVodeMem cv_mem);
-
-static int cvKLUSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-		      N_Vector fpred, booleantype *jcurPtr,
-		      N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int cvKLUSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-		      N_Vector ycur, N_Vector fcur);
-
-static int cvKLUFree(CVodeMem cv_mem);
-
-/* CVKLU lfreeB function */
-static int cvKLUFreeB(CVodeBMem cvb_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-
-/*
- * -----------------------------------------------------------------
- * CVKLU
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the CVODE / KLU linear solver module.  
- * CVKLU first calls the existing lfree routine if this is not NULL.
- * Then it sets the cv_linit, cv_lsetup, cv_lsolve, cv_lperf, and
- * cv_lfree fields in (*cv_mem) to be CVKLUInit, CVKLUSetup,
- * CVKLUSolve, NULL, and CVKLUFree, respectively.
- * It allocates memory for a structure of type CVkluMemRec and sets
- * the cv_lmem field in (*cvode_mem) to the address of this structure.
- * It sets setupNonNull in (*cvode_mem) to TRUE.
- * Finally, it allocates memory for KLU.
- * The return value is CVSLS_SUCCESS = 0, CVSLS_LMEM_FAIL = -1,
- * or CVSLS_ILL_INPUT = -2.
- *
- * NOTE: The KLU linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVKLU will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int CVKLU(void *cvode_mem, int n, int nnz, int sparsetype)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-  int flag;
-
-  /* Return immediately if cv_mem is NULL. */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "cvKLU", 
-                   MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSLS", "cvKLU", 
-                   MSGSP_BAD_NVECTOR);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  if (cv_mem->cv_lfree != NULL) cv_mem->cv_lfree(cv_mem);
-
-  /* Set five main function fields in cv_mem. */
-  cv_mem->cv_linit  = cvKLUInit;
-  cv_mem->cv_lsetup = cvKLUSetup;
-  cv_mem->cv_lsolve = cvKLUSolve;
-  cv_mem->cv_lfree  = cvKLUFree;
-
-  /* Get memory for CVSlsMemRec. */
-  cvsls_mem = (CVSlsMem) malloc(sizeof(struct CVSlsMemRec));
-  if (cvsls_mem == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Get memory for KLUData. */
-  klu_data = (KLUData)malloc(sizeof(struct KLUDataRec));
-  if (klu_data == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  cv_mem->cv_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  cvsls_mem->s_jaceval = NULL;
-  cvsls_mem->s_jacdata = NULL;
-  cvsls_mem->sparsetype = sparsetype;
-
-  /* Allocate memory for the sparse Jacobian */
-  cvsls_mem->s_JacMat = SparseNewMat(n, n, nnz, sparsetype);
-  if (cvsls_mem->s_JacMat == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Allocate memory for saved sparse Jacobian */
-  cvsls_mem->s_savedJ = SparseNewMat(n, n, nnz, sparsetype);
-  if (cvsls_mem->s_savedJ == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_MEM_FAIL);
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Initialize KLU structures */
-  switch (sparsetype) {
-    case CSC_MAT:
-      klu_data->sun_klu_solve = &klu_solve;
-      break;
-    case CSR_MAT:
-      klu_data->sun_klu_solve = &klu_tsolve;
-      break;
-    default:
-      SparseDestroyMat(cvsls_mem->s_JacMat);
-      SparseDestroyMat(cvsls_mem->s_savedJ);
-      free(klu_data);
-      free(cvsls_mem);
-      return(CVSLS_ILL_INPUT);
-  }
-  klu_data->s_Symbolic = NULL;
-  klu_data->s_Numeric = NULL;
-
-  /* Set default parameters for KLU */
-  flag = klu_defaults(&klu_data->s_Common);
-  if (flag == 0) {
-    cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "cvKLU", 
-                   MSGSP_PACKAGE_FAIL);
-    return(CVSLS_PACKAGE_FAIL);
-  }
-
-  /* Set ordering to COLAMD as the cvode default use.
-     Users can set a different value with CVKLUSetOrdering,
-     and the user-set value is loaded before any call to klu_analyze in
-     CVKLUSetup.  */
-  klu_data->s_ordering = 1;
-  klu_data->s_Common.ordering = klu_data->s_ordering;
-
-  /* Attach linear solver memory to the integrator memory */
-  cvsls_mem->s_solver_data = (void *) klu_data;
-  cv_mem->cv_lmem = cvsls_mem;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to CVKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is CVSLS_SUCCESS = 0, CVSLS_MEM_NULL = -1,
- * CVSLS_LMEM_NULL = -2, CVSLS_ILL_INPUT = -3, or CVSLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-int CVKLUReInit(void *cvode_mem, int n, int nnz, int reinit_type)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if cv_mem is NULL. */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVKLUReInit", 
-                   MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Return immediately if cv_lmem is NULL. */
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(NULL, CVSLS_LMEM_NULL, "CVSLS", "CVKLUReInit", 
-                   MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) (cv_mem->cv_lmem);
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  /* Return if reinit_type is not valid */
-  if ((reinit_type != 1) && (reinit_type != 2)) {
-    cvProcessError(NULL, CVSLS_ILL_INPUT, "CVSLS", "CVKLUReInit", 
-                   MSGSP_ILL_INPUT);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  if (reinit_type == 1) {
-
-    /* Destroy previous Jacobian information */
-    if (cvsls_mem->s_JacMat) {
-      SparseDestroyMat(cvsls_mem->s_JacMat);
-    }
-
-    /* Allocate memory for the sparse Jacobian */
-    cvsls_mem->s_JacMat = SparseNewMat(n, n, nnz, cvsls_mem->sparsetype);
-    if (cvsls_mem->s_JacMat == NULL) {
-      cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "CVKLU", 
-                     MSGSP_MEM_FAIL);
-      return(CVSLS_MEM_FAIL);
-    }
-  }
-
-  /* Free the prior factorazation and reset for first factorization */
-  if( klu_data->s_Symbolic != NULL)
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  if( klu_data->s_Numeric != NULL)
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  cvsls_mem->s_first_factorize = 1;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVKLU interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the CVKLU
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int cvKLUInit(CVodeMem cv_mem)
-{
-  CVSlsMem cvsls_mem;
-
-  cvsls_mem = (CVSlsMem)cv_mem->cv_lmem;
-
-  cvsls_mem->s_jacdata = cv_mem->cv_user_data;
-
-  cvsls_mem->s_nje = 0;
-  /* This forces factorization for every call to CVODE */
-  cvsls_mem->s_first_factorize = 1;
-  cvsls_mem->s_nstlj = 0;
-
-  cvsls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the CVKLU linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     CVSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int cvKLUSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-		      N_Vector fpred, booleantype *jcurPtr,
-		      N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  int retval;
-  long int nst, nstlj;
-  realtype tn, gamma, gammap, dgamma;
-  CVSlsMem cvsls_mem;
-  CVSlsSparseJacFn jaceval;
-  KLUData klu_data;
-  SlsMat JacMat, savedJ;
-  void *jacdata;
-  
-  realtype uround_twothirds;
-
-  uround_twothirds = SUNRpowerR(cv_mem->cv_uround,TWOTHIRDS);
-
-  cvsls_mem = (CVSlsMem) (cv_mem->cv_lmem);
-  tn = cv_mem->cv_tn; 
-  gamma = cv_mem->cv_gamma;
-  gammap = cv_mem->cv_gammap;
-  nst = cv_mem->cv_nst;
-
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  jaceval = cvsls_mem->s_jaceval;
-  jacdata = cvsls_mem->s_jacdata;
-  JacMat = cvsls_mem->s_JacMat;
-  savedJ = cvsls_mem->s_savedJ;
-  nstlj = cvsls_mem->s_nstlj;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    cvProcessError(cv_mem, CVSLS_JAC_NOSET, "CVSLS", "cvKLUSetup", 
-		    MSGSP_JAC_NOSET);
-    free(cvsls_mem); cvsls_mem = NULL;
-    return(CVSLS_JAC_NOSET);
-  }
-
-  /* Determine whether Jacobian needs to be recalculated */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVS_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVS_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    SparseCopyMat(savedJ, JacMat);
-  } else {
-    /* If jok = FALSE, call jac routine for new J value */
-    cvsls_mem->s_nje++;
-    cvsls_mem->s_nstlj = nst;
-    *jcurPtr = TRUE;
-    SparseSetMatToZero(JacMat);
-    retval = jaceval(tn, ypred, fpred, JacMat, jacdata, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVSLS_JACFUNC_UNRECVR, "CVSLS", "cvKLUSetup", MSGSP_JACFUNC_FAILED);
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    SparseCopyMat(JacMat, savedJ);
-  }
-
-  /* Scale and add I to get M = I - gamma*J */
-  SparseScaleMat(-gamma, JacMat);
-  SparseAddIdentityMat(JacMat);
-
-  if (cvsls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get the symbolic factorization
-       ------------------------------------------------------------*/ 
-    /* Update the ordering option with any user-updated values from 
-       calls to CVKLUSetOrdering */
-    klu_data->s_Common.ordering = klu_data->s_ordering;
-
-     if (klu_data->s_Symbolic != NULL) {
-       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-     }
-     klu_data->s_Symbolic = klu_analyze(JacMat->NP, JacMat->indexptrs, 
-				       JacMat->indexvals, &(klu_data->s_Common));
-    if (klu_data->s_Symbolic == NULL) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-
-    /* ------------------------------------------------------------
-       Compute the LU factorization of  the Jacobian.
-       ------------------------------------------------------------*/
-    /* If klu_factor previously called, free data */
-    if( klu_data->s_Numeric != NULL) {
-       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    }
-    klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-				     JacMat->data, 
-				     klu_data->s_Symbolic, &(klu_data->s_Common));
-
-    if (klu_data->s_Numeric == NULL) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		     MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-
-    cvsls_mem->s_first_factorize = 0;
-  }
-  else {
-    
-    retval = klu_refactor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
-			  klu_data->s_Symbolic, klu_data->s_Numeric,
-			  &(klu_data->s_Common));
-    if (retval == 0) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "cvKLUSetup", 
-		     MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-    
-    /*-----------------------------------------------------------
-      Check if a cheap estimate of the reciprocal of the condition 
-      number is getting too small.  If so, delete
-      the prior numeric factorization and recompute it.
-      -----------------------------------------------------------*/
-    
-    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
-		       &(klu_data->s_Common));
-    if (retval == 0) {
-      cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		     MSGSP_PACKAGE_FAIL);
-      return(CVSLS_PACKAGE_FAIL);
-    }
-
-    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
-      
-      /* Condition number may be getting large.  
-	 Compute more accurate estimate */
-      retval = klu_condest(JacMat->indexptrs, JacMat->data, 
-			   klu_data->s_Symbolic, klu_data->s_Numeric,
-			   &(klu_data->s_Common));
-      if (retval == 0) {
-	cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-		       MSGSP_PACKAGE_FAIL);
-	return(CVSLS_PACKAGE_FAIL);
-      }
-      
-      if ( (klu_data->s_Common.condest) > 
-	   (1.0/uround_twothirds) ) {
-
-	/* More accurate estimate also says condition number is 
-	   large, so recompute the numeric factorization */
-
-	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-	
-	klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-					 JacMat->data, klu_data->s_Symbolic, 
-					 &(klu_data->s_Common));
-
-	if (klu_data->s_Numeric == NULL) {
-	  cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSetup", 
-			 MSGSP_PACKAGE_FAIL);
-	  return(CVSLS_PACKAGE_FAIL);
-	}
-      }
-    }
-  }
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-  
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the CVKLU linear
-  solver module.  It calls the KLU solve routine,
-  then returns CVSLS_SUCCESS = 0.
-*/
-
-static int cvKLUSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-		      N_Vector ycur, N_Vector fcur)
-{
-  int flag, lmm;
-  realtype gamrat;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-  SlsMat JacMat;
-  realtype *bd;
-  
-  gamrat = cv_mem->cv_gamrat;
-  lmm = cv_mem->cv_lmm;
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  JacMat = cvsls_mem->s_JacMat;
-
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  bd = N_VGetArrayPointer(b);
-
-  /* Call KLU to solve the linear system */
-  flag = klu_data->sun_klu_solve(klu_data->s_Symbolic, klu_data->s_Numeric, JacMat->NP, 1, bd, 
-                                 &(klu_data->s_Common));
-  if (flag == 0) {
-    cvProcessError(cv_mem, CVSLS_PACKAGE_FAIL, "CVSLS", "CVKLUSolve", 
-		    MSGSP_PACKAGE_FAIL);
-    return(CVSLS_PACKAGE_FAIL);
-  }
-
-  /* Scale the correction to account for change in gamma. */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-  return(CVSLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the CVKLU linear solver.
-*/
-
-static int cvKLUFree(CVodeMem cv_mem)
-{
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-  
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  if( klu_data->s_Numeric != NULL)
-  {
-     klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  }
-  if( klu_data->s_Symbolic != NULL)
-  {
-     klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  }
-
-  if (cvsls_mem->s_JacMat) {
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    cvsls_mem->s_JacMat = NULL;
-  }
-
-  if (cvsls_mem->s_savedJ) {
-    SparseDestroyMat(cvsls_mem->s_savedJ);
-    cvsls_mem->s_savedJ = NULL;
-  }
-
-  free(klu_data); 
-  free(cv_mem->cv_lmem); 
-
-  return(0);
-}
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in CVODE is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int CVKLUSetOrdering(void *cv_mem_v, int ordering_choice)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  KLUData klu_data;
-
- /* Return immediately if cv_mem is NULL */
-  if (cv_mem_v == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVKLUSetOrdering",
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cv_mem_v;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) ) {
-    cvProcessError(NULL, CVSLS_ILL_INPUT, "CVSLS", "CVKLUSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  klu_data = (KLUData) cvsls_mem->s_solver_data;
-
-  klu_data->s_ordering = ordering_choice;
-
-  return(CVSLS_SUCCESS);
-}
-
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * CVKLUB is a wrapper around CVKLU. It attaches the CVKLU linear solver
- * to the backward problem memory block.
- */
-
-int CVKLUB(void *cvode_mem, int which, int n, int nnz, int sparsetype)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVSlsMemB cvslsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSKLU", "CVKLUB", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSLS_NO_ADJ, "CVSKLU", "CVKLUB", MSGSP_NO_ADJ);
-    return(CVSLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSKLU", "CVKLUB", MSGSP_BAD_WHICH);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVSlsMemRecB */
-  cvslsB_mem = (CVSlsMemB) malloc(sizeof(struct CVSlsMemRecB));
-  if (cvslsB_mem == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSKLU", "CVKLUB", MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* initialize Jacobian function */
-  cvslsB_mem->s_djacB = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvslsB_mem;
-  cvB_mem->cv_lfree = cvKLUFreeB;
-
-  flag = CVKLU(cvodeB_mem, n, nnz, sparsetype);
-
-  if (flag != CVSLS_SUCCESS) {
-    free(cvslsB_mem);
-    cvslsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-
-/*
- * CVKLUReInitB is a wrapper around CVKLUReInit. 
- * CVKLUReInitB pulls off the memory block associated with the
- * which parameter and reinitializes the KLU solver associated with that block.
- * The 'which' argument is the int returned by CVodeCreateB.
- */
-int CVKLUReInitB(void *cvode_mem, int which, int n, int nnz, int reinit_type)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  /* CVSlsMemB cvslsB_mem; */
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSKLU", "CVKLUReInitB", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSLS_NO_ADJ, "CVSKLU", "CVKLUReInitB", MSGSP_NO_ADJ);
-    return(CVSLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSKLU", "CVKLUReInitB", MSGSP_BAD_WHICH);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  flag = CVKLUReInit(cvodeB_mem, n, nnz, reinit_type);
-
-  return(flag);
-}
-
-/*
- * CVKLUSetOrderingB is a wrapper around CVKLUSetOrdering. 
- * CVKLUSetOrderingB pulls off the memory block associated with the
- * which parameter and sets the ordering for the solver associated with that block.
- */
-int CVKLUSetOrderingB(void *cvode_mem, int which, int ordering_choice)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  /* CVSlsMemB cvslsB_mem; */
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSKLU", "CVKLUSetOrderingB", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSLS_NO_ADJ, "CVSKLU", "CVKLUSetOrderingB", MSGSP_NO_ADJ);
-    return(CVSLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSKLU", "CVKLUSetOrderingB", MSGSP_BAD_WHICH);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  flag = CVKLUSetOrdering(cvodeB_mem, ordering_choice);
-
-  return(flag);
-}
-
-
-/*
- * cvKLUFreeB frees the memory associated with the CVSKLU linear
- * solver for backward integration.
- */
-
-static int cvKLUFreeB(CVodeBMem cvB_mem)
-{
-  CVSlsMemB cvslsB_mem;
-
-  cvslsB_mem = (CVSlsMemB) (cvB_mem->cv_lmem);
-
-  free(cvslsB_mem);
-
-  return(0);
-}
-
diff --git a/src/cvodes/cvodes_lapack.c b/src/cvodes/cvodes_lapack.c
deleted file mode 100644
index 5209b5d..0000000
--- a/src/cvodes/cvodes_lapack.c
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for a dense or banded CVODES 
- * linear solver using BLAS and LAPACK functions.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvodes/cvodes_lapack.h>
-#include "cvodes_direct_impl.h"
-#include "cvodes_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/* CVSLAPACK DENSE linit, lsetup, lsolve, and lfree routines */ 
-static int cvLapackDenseInit(CVodeMem cv_mem);
-static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail, 
-                              N_Vector yP, N_Vector fctP, 
-                              booleantype *jcurPtr,
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector fctC);
-static int cvLapackDenseFree(CVodeMem cv_mem);
-
-/* CVSLAPACK BAND linit, lsetup, lsolve, and lfree routines */ 
-static int cvLapackBandInit(CVodeMem cv_mem);
-static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, 
-                             N_Vector yP, N_Vector fctP, 
-                             booleantype *jcurPtr,
-                             N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                             N_Vector yC, N_Vector fctC);
-static int cvLapackBandFree(CVodeMem cv_mem);
-
-/* CVSLAPACK lfreeB functions */
-static int cvLapackDenseFreeB(CVodeBMem cvB_mem);
-static int cvLapackBandFreeB(CVodeBMem cvB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define lmm            (cv_mem->cv_lmm)
-#define f              (cv_mem->cv_f)
-#define uround         (cv_mem->cv_uround)
-#define nst            (cv_mem->cv_nst)
-#define tn             (cv_mem->cv_tn)
-#define h              (cv_mem->cv_h)
-#define gamma          (cv_mem->cv_gamma)
-#define gammap         (cv_mem->cv_gammap)
-#define gamrat         (cv_mem->cv_gamrat)
-#define ewt            (cv_mem->cv_ewt)
-
-#define linit          (cv_mem->cv_linit)
-#define lsetup         (cv_mem->cv_lsetup)
-#define lsolve         (cv_mem->cv_lsolve)
-#define lfree          (cv_mem->cv_lfree)
-#define lmem           (cv_mem->cv_lmem)
-#define tempv          (cv_mem->cv_tempv)
-#define setupNonNull   (cv_mem->cv_setupNonNull)
-
-#define mtype          (cvdls_mem->d_type)
-#define n              (cvdls_mem->d_n)
-#define jacDQ          (cvdls_mem->d_jacDQ)
-#define djac           (cvdls_mem->d_djac)
-#define bjac           (cvdls_mem->d_bjac)
-#define M              (cvdls_mem->d_M)
-#define mu             (cvdls_mem->d_mu)
-#define ml             (cvdls_mem->d_ml)
-#define smu            (cvdls_mem->d_smu)
-#define pivots         (cvdls_mem->d_pivots)
-#define savedJ         (cvdls_mem->d_savedJ)
-#define nstlj          (cvdls_mem->d_nstlj)
-#define nje            (cvdls_mem->d_nje)
-#define nfeDQ          (cvdls_mem->d_nfeDQ)
-#define J_data         (cvdls_mem->d_J_data)
-#define last_flag      (cvdls_mem->d_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * CVLapackDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the linear solver module.  CVLapackDense first
- * calls the existing lfree routine if this is not NULL.  Then it sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be cvLapackDenseInit, cvLapackDenseSetup, cvLapackDenseSolve, 
- * and cvLapackDenseFree, respectively.  It allocates memory for a 
- * structure of type CVDlsMemRec and sets the cv_lmem field in 
- * (*cvode_mem) to the address of this structure.  It sets setupNonNull 
- * in (*cvode_mem) to TRUE, and the d_jac field to the default 
- * cvDlsDenseDQJac. Finally, it allocates memory for M, pivots, and 
- * (if needed) savedJ.
- * The return value is SUCCESS = 0, or LMEM_FAIL = -1.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVLapackDense will first 
- *       test for a compatible N_Vector internal representation 
- *       by checking that N_VGetArrayPointer and N_VSetArrayPointer 
- *       exist.
- * -----------------------------------------------------------------
- */
-int CVLapackDense(void *cvode_mem, int N)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackDense", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the CVSLAPACK solver */
-  if (tempv->ops->nvgetarraypointer == NULL ||
-      tempv->ops->nvsetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackDense", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = cvLapackDenseInit;
-  lsetup = cvLapackDenseSetup;
-  lsolve = cvLapackDenseSolve;
-  lfree  = cvLapackDenseFree;
-
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Initialize Jacobian-related data */
-  jacDQ  = TRUE;
-  djac   = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-  cvDlsInitializeCounters(cvdls_mem);  
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = (long int) N;
-
-  /* Allocate memory for M, pivot array, and (if needed) savedJ */
-  M = NULL;
-  pivots = NULL;
-  savedJ = NULL;
-
-  M = NewDenseMat(n, n);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NewDenseMat(n, n);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyArray(pivots);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVLapackBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module. It first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
- * to be cvLapackBandInit, cvLapackBandSetup, cvLapackBandSolve, 
- * and cvLapackBandFree, respectively.  It allocates memory for a 
- * structure of type CVLapackBandMemRec and sets the cv_lmem field in 
- * (*cvode_mem) to the address of this structure.  It sets setupNonNull 
- * in (*cvode_mem) to be TRUE, mu to be mupper, ml to be mlower, and 
- * the jacE and jacI field to NULL.
- * Finally, it allocates memory for M, pivots, and (if needed) savedJ.  
- * The CVLapackBand return value is CVDLS_SUCCESS = 0, 
- * CVDLS_MEM_FAIL = -1, or CVDLS_ILL_INPUT = -2.
- *
- * NOTE: The CVSLAPACK linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVLapackBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */                  
-int CVLapackBand(void *cvode_mem, int N, int mupper, int mlower)
-{
-  CVodeMem cv_mem;
-  CVDlsMem cvdls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackBand", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (tempv->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackBand", MSGD_BAD_NVECTOR);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */  
-  linit  = cvLapackBandInit;
-  lsetup = cvLapackBandSetup;
-  lsolve = cvLapackBandSolve;
-  lfree  = cvLapackBandFree;
-  
-  /* Get memory for CVDlsMemRec */
-  cvdls_mem = NULL;
-  cvdls_mem = (CVDlsMem) malloc(sizeof(struct CVDlsMemRec));
-  if (cvdls_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-
-  /* Initialize Jacobian-related data */
-  jacDQ  = TRUE;
-  bjac   = NULL;
-  J_data = NULL;
-
-  last_flag = CVDLS_SUCCESS;
-  cvDlsInitializeCounters(cvdls_mem);  
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = (long int) N;
-
-  /* Load half-bandwiths in cvdls_mem */
-  ml = (long int) mlower;
-  mu = (long int) mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= n) || (mu >= n)) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackBand", MSGD_BAD_SIZES);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = mu + ml;
-
-  /* Allocate memory for M, savedJ, and pivot arrays */
-  M = NULL;
-  pivots = NULL;
-  savedJ = NULL;
-
-  M = NewBandMat(n, mu, ml, smu);
-  if (M == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }  
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-  savedJ = NewBandMat(n, mu, ml, smu);
-  if (savedJ == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(M);
-    DestroyArray(pivots);
-    free(cvdls_mem); cvdls_mem = NULL;
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvdls_mem;
-
-  return(CVDLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS
- * =================================================================
- */
-
-/*
- * cvLapackDenseInit does remaining initializations specific to the dense
- * linear solver.
- */
-static int cvLapackDenseInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  cvDlsInitializeCounters(cvdls_mem);  
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    djac = cvDlsDenseDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackDenseSetup does the setup operations for the dense linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J
- * updates counters, and calls the dense LU factorization routine.
- */
-static int cvLapackDenseSetup(CVodeMem cv_mem, int convfail,
-                              N_Vector yP, N_Vector fctP,
-                              booleantype *jcurPtr,
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  CVDlsMem cvdls_mem;
-  realtype dgamma, fact;
-  booleantype jbad, jok;
-  int ier, retval, one = 1;
-  int intn, lenmat;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  intn = (int) n;
-  lenmat = M->ldata;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-    (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    dcopy_f77(&lenmat, savedJ->data, &one, M->data, &one);
-    
-  } else {
-    
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M);
-
-    retval = djac(n, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3);
-    if (retval == 0) {
-      dcopy_f77(&lenmat, M->data, &one, savedJ->data, &one);
-    } else if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSLAPACK", "cvLapackDenseSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    } else if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-    
-  }
-
-  /* Scale J by - gamma */
-  fact = -gamma;
-  dscal_f77(&lenmat, &fact, M->data, &one);
-  
-  /* Add identity to get M = I - gamma*J*/
-  AddIdentity(M);
-
-  /* Do LU factorization of M */
-  dgetrf_f77(&intn, &intn, M->data, &intn, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-/*
- * cvLapackDenseSolve handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.
- */
-static int cvLapackDenseSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector fctC)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  intn = (int) n;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgetrs_f77("N", &intn, &one, M->data, &intn, pivots, bd, &intn, &ier, 1); 
-  if (ier > 0) return(1);
-
-  /* For BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    fact = TWO/(ONE + gamrat);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-  
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackDenseFree frees memory specific to the dense linear solver.
- */
-static int cvLapackDenseFree(CVodeMem cv_mem)
-{
-  CVDlsMem  cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  DestroyMat(M);
-  DestroyArray(pivots);
-  DestroyMat(savedJ);
-  free(cvdls_mem); 
-  cvdls_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS
- * =================================================================
- */
-
-/*
- * cvLapackBandInit does remaining initializations specific to the band
- * linear solver.
- */
-static int cvLapackBandInit(CVodeMem cv_mem)
-{
-  CVDlsMem cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  cvDlsInitializeCounters(cvdls_mem);  
-
-  /* Set Jacobian function and data, depending on jacDQ */
-  if (jacDQ) {
-    bjac = cvDlsBandDQJac;
-    J_data = cv_mem;
-  } else {
-    J_data = cv_mem->cv_user_data;
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackBandSetup does the setup operations for the band linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy. In any case, it constructs the Newton matrix M = I - gamma*J, 
- * updates counters, and calls the band LU factorization routine.
- */
-static int cvLapackBandSetup(CVodeMem cv_mem, int convfail, 
-                             N_Vector yP, N_Vector fctP, 
-                             booleantype *jcurPtr,
-                             N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  CVDlsMem cvdls_mem;
-  realtype dgamma, fact;
-  booleantype jbad, jok;
-  int ier, retval, one = 1;
-  int intn, iml, imu, lenmat, ldmat;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  lenmat = M->ldata;
-  ldmat = M->ldim;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVD_MSBJ) ||
-    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVD_DGMAX)) ||
-    (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    dcopy_f77(&lenmat, savedJ->data, &one, M->data, &one);
-    
-  } else {
-    
-    /* If jok = FALSE, call jac routine for new J value */
-    nje++;
-    nstlj = nst;
-    *jcurPtr = TRUE;
-    SetToZero(M); 
-
-    retval = bjac(n, mu, ml, tn, yP, fctP, M, J_data, tmp1, tmp2, tmp3);
-    if (retval == 0) {
-      dcopy_f77(&lenmat, M->data, &one, savedJ->data, &one);
-    } else if (retval < 0) {
-      cvProcessError(cv_mem, CVDLS_JACFUNC_UNRECVR, "CVSLAPACK", "cvLapackBandSetup", MSGD_JACFUNC_FAILED);
-      last_flag = CVDLS_JACFUNC_UNRECVR;
-      return(-1);
-    } else if (retval > 0) {
-      last_flag = CVDLS_JACFUNC_RECVR;
-      return(1);
-    }
-    
-  }
-  
-  /* Scale J by - gamma */
-  fact = -gamma;
-  dscal_f77(&lenmat, &fact, M->data, &one);
-  
-  /* Add identity to get M = I - gamma*J*/
-  AddIdentity(M);
-  
-  /* Do LU factorization of M */
-  dgbtrf_f77(&intn, &intn, &iml, &imu, M->data, &ldmat, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-
-}
-
-/*
- * cvLapackBandSolve handles the solve operation for the band linear solver
- * by calling the band backsolve routine.
- */
-static int cvLapackBandSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                             N_Vector yC, N_Vector fctC)
-{
-  CVDlsMem cvdls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn, iml, imu, ldmat;
-
-  cvdls_mem = (CVDlsMem) lmem;
-
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = M->ldim;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgbtrs_f77("N", &intn, &iml, &imu, &one, M->data, &ldmat, pivots, bd, &intn, &ier, 1);
-  if (ier > 0) return(1);
-
-  /* For BDF, scale the correction to account for change in gamma */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    fact = TWO/(ONE + gamrat);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-
-  last_flag = CVDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * cvLapackBandFree frees memory specific to the band linear solver.
- */
-static int cvLapackBandFree(CVodeMem cv_mem)
-{
-  CVDlsMem  cvdls_mem;
-
-  cvdls_mem = (CVDlsMem) lmem;
-  
-  DestroyMat(M);
-  DestroyArray(pivots);
-  DestroyMat(savedJ);
-  free(cvdls_mem); 
-  cvdls_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * CVLapackDenseB is a wrapper around CVLapackDense. It attaches the
- * dense CVSLAPACK linear solver to the backward problem memory block.
- */
-
-int CVLapackDenseB(void *cvode_mem, int which, int nB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVDlsMemB cvdlsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackDenseB", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSLAPACK", "CVLapackDenseB", MSGD_NO_ADJ);
-    return(CVDLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackDenseB", MSGCV_BAD_WHICH);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVDlsMemRecB */
-  cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB));
-  if (cvdlsB_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackDenseB", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* set matrix type */
-  cvdlsB_mem->d_typeB = SUNDIALS_DENSE;
-
-  /* initialize Jacobian function */
-  cvdlsB_mem->d_djacB = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvdlsB_mem;
-  cvB_mem->cv_lfree = cvLapackDenseFreeB;
-
-  flag = CVLapackDense(cvodeB_mem, nB);
-
-  if (flag != CVDLS_SUCCESS) {
-    free(cvdlsB_mem);
-    cvdlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * cvLapackDenseFreeB frees the memory associated with the dense CVSLAPACK
- * linear solver for backward integration.
- */
-
-static int cvLapackDenseFreeB(CVodeBMem cvB_mem)
-{
-  CVDlsMemB cvdlsB_mem;
-
-  cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
-
-  free(cvdlsB_mem);
-
-  return(0);
-}
-
-/*
- * CVLapackBandB is a wrapper around CVLapackBand. It attaches the band
- * CVSLAPACK linear solver to the backward problem memory block.
- */
-
-int CVLapackBandB(void *cvode_mem, int which,
-                  int nB, int mupperB, int mlowerB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVDlsMemB cvdlsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVDLS_MEM_NULL, "CVSLAPACK", "CVLapackBandB", MSGD_CVMEM_NULL);
-    return(CVDLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVDLS_NO_ADJ, "CVSLAPACK", "CVLapackBandB", MSGD_NO_ADJ);
-    return(CVDLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVDLS_ILL_INPUT, "CVSLAPACK", "CVLapackBandB", MSGCV_BAD_WHICH);
-    return(CVDLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVDlsMemRecB */
-  cvdlsB_mem = (CVDlsMemB) malloc(sizeof(struct CVDlsMemRecB));
-  if (cvdlsB_mem == NULL) {
-    cvProcessError(cv_mem, CVDLS_MEM_FAIL, "CVSLAPACK", "CVLapackBandB", MSGD_MEM_FAIL);
-    return(CVDLS_MEM_FAIL);
-  }
-
-  /* set matrix type */
-  cvdlsB_mem->d_typeB = SUNDIALS_BAND;
-
-  /* initialize Jacobian function */
-  cvdlsB_mem->d_bjacB = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvdlsB_mem;
-  cvB_mem->cv_lfree = cvLapackBandFreeB;
-
-  flag = CVLapackBand(cvodeB_mem, nB, mupperB, mlowerB);
-
-  if (flag != CVDLS_SUCCESS) {
-    free(cvdlsB_mem);
-    cvdlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * cvLapackBandFreeB frees the memory associated with the band CVSLAPACK
- * linear solver for backward integration.
- */
-
-static int cvLapackBandFreeB(CVodeBMem cvB_mem)
-{
-  CVDlsMemB cvdlsB_mem;
-
-  cvdlsB_mem = (CVDlsMemB) (cvB_mem->cv_lmem);
-
-  free(cvdlsB_mem);
-
-  return(0);
-}
diff --git a/src/cvodes/cvodes_sparse.c b/src/cvodes/cvodes_sparse.c
deleted file mode 100644
index b1d35e3..0000000
--- a/src/cvodes/cvodes_sparse.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4086 $
- * $Date: 2014-04-30 16:04:45 -0700 (Wed, 30 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for an CVSLS linear solver.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cvodes_impl.h"
-#include "cvodes_sparse_impl.h"
-#include <sundials/sundials_math.h>
-
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PRIVATE FUNCTION PROTOTYPES
- * =================================================================
- */
-
-static int cvSlsSparseJacBWrapper(realtype t,
-				  N_Vector yB, N_Vector fyB, 
-				  SlsMat JB, void *cvode_mem,
-				  N_Vector tmp1B, N_Vector tmp2B, 
-				  N_Vector tmp3B);
-
-static int cvSlsSparseJacBSWrapper(realtype t,
-				   N_Vector yB, N_Vector fyB, 
-				   SlsMat JB, void *cvode_mem,
-				   N_Vector tmp1B, N_Vector tmp2B, 
-				   N_Vector tmp3B);
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * CVSlsSetSparseJacFn specifies the sparse Jacobian function.
- */
-int CVSlsSetSparseJacFn(void *cvode_mem, CVSlsSparseJacFn jac)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSlsSetSparseJacFn", 
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEM_NULL, "CVSLS", 
-		    "CVSlsSetSparseJacFn", MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  cvsls_mem->s_jaceval = jac;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * CVSlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
-int CVSlsGetNumJacEvals(void *cvode_mem, long int *njevals)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSlsGetNumJacEvals", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEM_NULL, "CVSLS", 
-		    "CVSlsGetNumJacEvals", MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  *njevals = cvsls_mem->s_nje;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * CVSlsGetReturnFlagName returns the name associated with a CVSLS
- * return value.
- */
-char *CVSlsGetReturnFlagName(long int flag)
-{
-  char *name;
-
-  name = (char *)malloc(30*sizeof(char));
-
-  switch(flag) {
-  case CVSLS_SUCCESS:
-    sprintf(name,"CVSLS_SUCCESS");
-    break;   
-  case CVSLS_MEM_NULL:
-    sprintf(name,"CVSLS_MEM_NULL");
-    break;
-  case CVSLS_LMEM_NULL:
-    sprintf(name,"CVSLS_LMEM_NULL");
-    break;
-  case CVSLS_ILL_INPUT:
-    sprintf(name,"CVSLS_ILL_INPUT");
-    break;
-  case CVSLS_MEM_FAIL:
-    sprintf(name,"CVSLS_MEM_FAIL");
-    break;
-  case CVSLS_JAC_NOSET:
-    sprintf(name,"CVSLS_JAC_NOSET");
-    break;
-  case CVSLS_JACFUNC_UNRECVR:
-    sprintf(name,"CVSLS_JACFUNC_UNRECVR");
-    break;
-  case CVSLS_JACFUNC_RECVR:
-    sprintf(name,"CVSLS_JACFUNC_RECVR");
-    break;
-  default:
-    sprintf(name,"NONE");
-  }
-
-  return(name);
-}
-
-/*
- * CVSlsGetLastFlag returns the last flag set in a CVSLS function.
- */
-int CVSlsGetLastFlag(void *cvode_mem, long int *flag)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSlsGetLastFlag", 
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  if (cv_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEM_NULL, "CVSLS", 
-		    "CVSlsGetLastFlag", MSGSP_LMEM_NULL);
-    return(CVSLS_LMEM_NULL);
-  }
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  *flag = cvsls_mem->s_last_flag;
-
-  return(CVSLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- * BACKWARD INTEGRATION SUPPORT
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS
- * -----------------------------------------------------------------
- */
-
-int CVSlsSetSparseJacFnB(void *cvode_mem, int which, CVSlsSparseJacFnB jacB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  CVSlsMemB cvslsB_mem;
-  void *cvodeB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSSLS", "CVSlsSetSparseJacFnB", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSLS_NO_ADJ, "CVSSLS", "CVSlsSetSparseJacFnB", MSGSP_NO_ADJ);
-    return(CVSLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSSLS", "CVSlsSetSparseJacFnB", MSGSP_BAD_WHICH);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEMB_NULL, "CVSSLS", "CVSlsSetSparseJacFnB", MSGSP_LMEMB_NULL);
-    return(CVSLS_LMEMB_NULL);
-  }
-  cvslsB_mem = (CVSlsMemB) (cvB_mem->cv_lmem);
-
-  cvslsB_mem->s_djacB = jacB;
-
-  if (jacB != NULL) {
-    flag = CVSlsSetSparseJacFn(cvodeB_mem, cvSlsSparseJacBWrapper);
-  } else {
-    flag = CVSlsSetSparseJacFn(cvodeB_mem, NULL);
-  }
-
-  return(flag);
-}
-
-int CVSlsSetSparseJacFnBS(void *cvode_mem, int which, CVSlsSparseJacFnBS jacBS)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  CVSlsMemB cvslsB_mem;
-  void *cvodeB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSSLS", "CVSlsSetSparseJacFnBS", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSLS_NO_ADJ, "CVSSLS", "CVSlsSetSparseJacFnBS", MSGSP_NO_ADJ);
-    return(CVSLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSSLS", "CVSlsSetSparseJacFnBS", MSGSP_BAD_WHICH);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSLS_LMEMB_NULL, "CVSSLS", "CVSlsSetSparseJacFnBS", MSGSP_LMEMB_NULL);
-    return(CVSLS_LMEMB_NULL);
-  }
-  cvslsB_mem = (CVSlsMemB) (cvB_mem->cv_lmem);
-
-  cvslsB_mem->s_djacBS = jacBS;
-
-  if (jacBS != NULL) {
-    flag = CVSlsSetSparseJacFn(cvodeB_mem, cvSlsSparseJacBSWrapper);
-  } else {
-    flag = CVSlsSetSparseJacFn(cvodeB_mem, NULL);
-  }
-
-  return(flag);
-}
-
-/*
- * -----------------------------------------------------------------
- * PRIVATE INTERFACE FUNCTIONS
- * -----------------------------------------------------------------
- */
-
-/*
- * cvSlsSparseJacBWrapper
- *
- * This routine interfaces to the CVSlsSparseJacFnB routine provided 
- * by the user. cvSlsSparseJacBWrapper is of type CVSlsSparseJacFn.
- * NOTE: data here contains cvode_mem
- */
-
-static int cvSlsSparseJacBWrapper(realtype t,
-				  N_Vector yB, N_Vector fyB, 
-				  SlsMat JB, void *cvode_mem,
-				  N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  CVSlsMemB cvslsB_mem;
-  int retval, flag;
-
-  cv_mem = (CVodeMem) cvode_mem;
-
-  ca_mem = cv_mem->cv_adj_mem;
-
-  cvB_mem = ca_mem->ca_bckpbCrt;
-
-  cvslsB_mem = (CVSlsMemB) (cvB_mem->cv_lmem);
-
-  /* Forward solution from interpolation */
-  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
-  if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSSLS", "cvSlsSparseJacBWrapper", MSGSP_BAD_TINTERP);
-    return(-1);
-  }
-
-  /* Call user's adjoint dense djacB routine (of type CVSlsSparseJacFnB) */
-  retval = cvslsB_mem->s_djacB(t, ca_mem->ca_ytmp, yB, fyB, JB, 
-			       cvB_mem->cv_user_data, 
-			       tmp1B, tmp2B, tmp3B);
-
-  return(retval);
-}
-
-/*
- * cvSlsSparseJacBSWrapper
- *
- * This routine interfaces to the CVSlsSparseJacFnBS routine provided 
- * by the user. cvSlsSparseJacBSWrapper is of type CVSlsSparseJacFn.
- * NOTE: data here contains cvode_mem
- */
-
-static int cvSlsSparseJacBSWrapper(realtype t,
-				   N_Vector yB, N_Vector fyB, 
-				   SlsMat JB, void *cvode_mem,
-				   N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  CVSlsMemB cvslsB_mem;
-  int retval, flag;
-
-  cv_mem = (CVodeMem) cvode_mem;
-
-  ca_mem = cv_mem->cv_adj_mem;
-
-  cvB_mem = ca_mem->ca_bckpbCrt;
-
-  cvslsB_mem = (CVSlsMemB) (cvB_mem->cv_lmem);
-
-  /* Forward solution from interpolation */
-  if (ca_mem->ca_IMinterpSensi)
-    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
-  else 
-    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
-  if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSSLS", "cvSlsSparseJacBSWrapper", MSGSP_BAD_TINTERP);
-    return(-1);
-  }
-
-  /* Call user's adjoint dense djacBS routine (of type CVSlsSparseJacFnBS) */
-  retval = cvslsB_mem->s_djacBS(t, ca_mem->ca_ytmp, ca_mem->ca_yStmp, 
-				yB, fyB, JB, cvB_mem->cv_user_data, 
-				tmp1B, tmp2B, tmp3B);
-
-  return(retval);
-}
diff --git a/src/cvodes/cvodes_sparse_impl.h b/src/cvodes/cvodes_sparse_impl.h
deleted file mode 100644
index b526278..0000000
--- a/src/cvodes/cvodes_sparse_impl.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Implementation header file for the CVSLS linear solvers.
- * -----------------------------------------------------------------
- */
-
-#ifndef _CVSSPARSE_IMPL_H
-#define _CVSSPARSE_IMPL_H
-
-#include "cvodes/cvodes_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * C V S P A R S E    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * CVSLS solver constants
- * -----------------------------------------------------------------
- * CVS_MSBJ   maximum number of steps between Jacobian evaluations
- * CVS_DGMAX  maximum change in gamma between Jacobian evaluations
- * -----------------------------------------------------------------
- */
- 
-#define CVS_MSBJ  50
-#define CVS_DGMAX RCONST(0.2)
- 
-/*
- * -----------------------------------------------------------------
- * Types : CVSlsMemRec, CVSlsMem                             
- * -----------------------------------------------------------------
- * CVSlsMem is pointer to a CVSlsMemRec structure.
- * -----------------------------------------------------------------
- */
-
-typedef struct CVSlsMemRec {
-
-  CVSlsSparseJacFn s_jaceval; /* user Jacobian evaluation routine 
-				  to be called */
-  void *s_jacdata;           /* J_data is passed to djac or bjac */
-
-  long int s_nje;           /* nje = no. of calls to jac */
-
-  long int s_last_flag;     /* last error return flag */
-
-  int s_first_factorize;    /* flag telling whether the first 
-			       factorization needs to happen */
-
-  int s_nstlj;              /* time step of last Jacobian evaluation */
-
-  SlsMat s_JacMat;          /* M = I - gamma * df/dy */
-
-  SlsMat s_savedJ;          /* saved copy of Jacobian */
-
-  int sparsetype;           /* matrix type: compressed sparse column or row */
-
-  void *s_solver_data;      /* structure for solver-specific data */
-  
-
-} *CVSlsMem;
-
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-  
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : CVSlsMemRecB, CVSlsMemB       
- * -----------------------------------------------------------------
- * A CVSLS linear solver's specification function attaches such
- * a structure to the lmemB filed of CVodeBMem
- * -----------------------------------------------------------------
- */
-
-typedef struct CVSlsMemRecB {
-
-  CVSlsSparseJacFnB s_djacB;
-  CVSlsSparseJacFnBS s_djacBS;
-
-} *CVSlsMemB;
-
-
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
-
-#define MSGSP_CVMEM_NULL "Integrator memory is NULL."
-#define MSGSP_BAD_NVECTOR "A required vector operation is not implemented."
-#define MSGSP_MEM_FAIL "A memory request failed."
-#define MSGSP_LMEM_NULL "Linear solver memory is NULL."
-#define MSGSP_ILL_INPUT "Invalid input detected."
-#define MSGSP_JAC_NOSET "Jacobian evaluation function has not been set."
-#define MSGSP_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
-#define MSGSP_PACKAGE_FAIL "A call to an external package failed."
-
-#define MSGSP_NO_ADJ "Illegal attempt to call before calling CVodeAdjMalloc."
-#define MSGSP_BAD_WHICH "Illegal value for which."
-#define MSGSP_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
-#define MSGSP_BAD_TINTERP "Bad t for interpolation."
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/cvodes/cvodes_spbcgs.c b/src/cvodes/cvodes_spbcgs.c
deleted file mode 100644
index 2153de5..0000000
--- a/src/cvodes/cvodes_spbcgs.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSPBCG linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvodes/cvodes_spbcgs.h>
-#include "cvodes_spils_impl.h"
-#include "cvodes_impl.h"
-
-#include <sundials/sundials_spbcgs.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* CVSPBCG linit, lsetup, lsolve, and lfree routines */
-
-static int CVSpbcgInit(CVodeMem cv_mem);
-
-static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3);
-
-static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow);
-
-static int CVSpbcgFree(CVodeMem cv_mem);
-
-/* CVSPBCG lfreeB function */
-
-static int CVSpbcgFreeB(CVodeBMem cvB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define tq           (cv_mem->cv_tq)
-#define nst          (cv_mem->cv_nst)
-#define tn           (cv_mem->cv_tn)
-#define gamma        (cv_mem->cv_gamma)
-#define gammap       (cv_mem->cv_gammap)
-#define f            (cv_mem->cv_f)
-#define user_data    (cv_mem->cv_user_data)
-#define ewt          (cv_mem->cv_ewt)
-#define errfp        (cv_mem->cv_errfp)
-#define mnewt        (cv_mem->cv_mnewt)
-#define linit        (cv_mem->cv_linit)
-#define lsetup       (cv_mem->cv_lsetup)
-#define lsolve       (cv_mem->cv_lsolve)
-#define lfree        (cv_mem->cv_lfree)
-#define lmem         (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define sqrtN     (cvspils_mem->s_sqrtN)   
-#define ytemp     (cvspils_mem->s_ytemp)
-#define x         (cvspils_mem->s_x)
-#define ycur      (cvspils_mem->s_ycur)
-#define fcur      (cvspils_mem->s_fcur)
-#define delta     (cvspils_mem->s_delta)
-#define deltar    (cvspils_mem->s_deltar)
-#define npe       (cvspils_mem->s_npe)
-#define nli       (cvspils_mem->s_nli)
-#define nps       (cvspils_mem->s_nps)
-#define ncfl      (cvspils_mem->s_ncfl)
-#define nstlpre   (cvspils_mem->s_nstlpre)
-#define njtimes   (cvspils_mem->s_njtimes)
-#define nfes      (cvspils_mem->s_nfes)
-#define spils_mem (cvspils_mem->s_spils_mem)
-
-#define jtimesDQ  (cvspils_mem->s_jtimesDQ)
-#define jtimes    (cvspils_mem->s_jtimes)
-#define j_data    (cvspils_mem->s_j_data)
-
-#define last_flag (cvspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcg
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the Spbcg linear solver module. CVSpbcg first
- * calls the existing lfree routine if this is not NULL. It then sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be CVSpbcgInit, CVSpbcgSetup, CVSpbcgSolve, and CVSpbcgFree,
- * respectively. It allocates memory for a structure of type
- * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure. It sets setupNonNull in (*cvode_mem),
- * and sets various fields in the CVSpilsMemRec structure.
- * Finally, CVSpbcg allocates memory for ytemp and x, and calls
- * SpbcgMalloc to allocate memory for the Spbcg solver.
- * -----------------------------------------------------------------
- */
-
-int CVSpbcg(void *cvode_mem, int pretype, int maxl)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-  int mxl;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPBCG", "CVSpbcg", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_NVECTOR);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = CVSpbcgInit;
-  lsetup = CVSpbcgSetup;
-  lsolve = CVSpbcgSolve;
-  lfree  = CVSpbcgFree;
-
-  /* Get memory for CVSpilsMemRec */
-  cvspils_mem = NULL;
-  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
-  if (cvspils_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  cvspils_mem->s_type = SPILS_SPBCG;
-
-  /* Set Spbcg parameters that have been passed in call sequence */
-  cvspils_mem->s_pretype = pretype;
-  mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  cvspils_mem->s_pset   = NULL;
-  cvspils_mem->s_psolve = NULL;
-  cvspils_mem->s_pfree  = NULL;
-  cvspils_mem->s_P_data = cv_mem->cv_user_data;
-
-  /* Set default values for the rest of the Spbcg parameters */
-  cvspils_mem->s_eplifac = CVSPILS_EPLIN;
-
-  cvspils_mem->s_last_flag = CVSPILS_SUCCESS;
-
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcg", MSGS_BAD_PRETYPE);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  x = N_VClone(vec_tmpl);
-  if (x == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SpbcgMalloc to allocate workspace for Spbcg */
-  spbcg_mem = NULL;
-  spbcg_mem = SpbcgMalloc(mxl, vec_tmpl);
-  if (spbcg_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(x);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPBCG memory to spils memory structure */
-  spils_mem = (void *) spbcg_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvspils_mem;
-
-  return(CVSPILS_SUCCESS);
-}
-
-
-
-/* Additional readability replacements */
-
-#define pretype (cvspils_mem->s_pretype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define pset    (cvspils_mem->s_pset)
-#define P_data  (cvspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the Spbcg
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgInit(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-
-  /* Initialize counters */
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((pretype != PREC_NONE) && (psolve == NULL)) {
-    cvProcessError(cv_mem, -1, "CVSPBCG", "CVSpbcgInit", MSGS_PSOLVE_REQ);
-    last_flag = CVSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  setupNonNull = (pretype != PREC_NONE) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = CVSpilsDQJtimes;
-    j_data = cv_mem;
-  } else {
-    j_data = user_data;
-  }
-
-  /*  Set maxl in the SPBCG memory in case it was changed by the user */
-  spbcg_mem->l_max  = maxl;
-
-  last_flag = CVSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the Spbcg linear solver.
- * It makes a decision as to whether or not to signal for reevaluation
- * of Jacobian data in the pset routine, based on various state
- * variables, then it calls pset. If we signal for reevaluation,
- * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output.
- * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  CVSpilsMem cvspils_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) ||
-      ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
-      (convfail == CV_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, 
-                vtemp1, vtemp2, vtemp3);
-  if (retval < 0) {
-    cvProcessError(cv_mem, SPBCG_PSET_FAIL_UNREC, "CVSPBCG", "CVSpbcgSetup", MSGS_PSET_FAILED);
-    last_flag = SPBCG_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    last_flag = SPBCG_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    npe++;
-    nstlpre = nst;
-  }
-
-  last_flag = SPBCG_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic solver SpbcgSolve
- * for the solution of the linear system Ax = b with the SPBCG method.
- * The solution x is returned in the vector b.
- *
- * If the WRMS norm of b is small, we return x = b (if this is the first
- * Newton iteration) or x = 0 (if a later Newton iteration).
- *
- * Otherwise, we set the tolerance parameter and initial guess (x = 0),
- * call SpbcgSolve, and copy the solution x into b. The x-scaling and
- * b-scaling arrays are both equal to weight.
- *
- * The counters nli, nps, and ncfl are incremented, and the return value
- * is set according to the success of SpbcgSolve. The success flag is
- * returned if SpbcgSolve converged, or if this is the first Newton
- * iteration and the residual norm was reduced below its initial value.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-  int nli_inc, nps_inc, retval;
-  
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  deltar = eplifac * tq[4]; 
-
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= deltar) {
-    if (mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  ycur = ynow;
-  fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SpbcgSolve */  
-  delta = deltar * sqrtN;
-  N_VConst(ZERO, x);
-  
-  /* Call SpbcgSolve and copy x to b */
-  retval = SpbcgSolve(spbcg_mem, cv_mem, x, b, pretype, delta,
-                      cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve,
-                      &res_norm, &nli_inc, &nps_inc);
-
-  N_VScale(ONE, x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPBCG_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpbcgSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPBCG_SUCCESS:
-    return(0);
-    break;
-  case SPBCG_RES_REDUCED:
-    if (mnewt == 0) return(0);
-    else            return(1);
-    break;
-  case SPBCG_CONV_FAIL:
-    return(1);
-    break;
-  case SPBCG_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_MEM_NULL:
-    return(-1);
-    break;
-  case SPBCG_ATIMES_FAIL_UNREC:
-    cvProcessError(cv_mem, SPBCG_ATIMES_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPBCG_PSOLVE_FAIL_UNREC:
-    cvProcessError(cv_mem, SPBCG_PSOLVE_FAIL_UNREC, "CVSPBCG", "CVSpbcgSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);  
-
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSpbcgFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the Spbcg linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpbcgFree(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SpbcgMem spbcg_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(x);
-
-  spbcg_mem = (SpbcgMem) spils_mem;
-  SpbcgFree(spbcg_mem);
-
-  if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem);
-
-  free(cvspils_mem);
-  cv_mem->cv_lmem = NULL;
-  
-  return(0);
-}
-
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-
-/* Additional readability replacements */
-
-#define pset_B      (cvspilsB_mem->s_psetB)
-#define psolve_B    (cvspilsB_mem->s_psolveB)
-#define jtimes_B    (cvspilsB_mem->s_jtimesB)
-#define P_data_B    (cvspilsB_mem->s_P_dataB)
-
-/*
- * CVSpbcgB
- *
- * Wrapper for the backward phase
- */
-
-int CVSpbcgB(void *cvode_mem, int which, int pretypeB, int maxlB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVSpilsMemB cvspilsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPBCG", "CVSpbcgB", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPBCG", "CVSpbcgB", MSGS_NO_ADJ);
-    return(CVSPILS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPBCG", "CVSpbcgB", MSGS_BAD_WHICH);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVSpilsMemRecB */
-  cvspilsB_mem = NULL;
-  cvspilsB_mem = (CVSpilsMemB) malloc(sizeof(struct CVSpilsMemRecB));
-  if (cvspilsB_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPBCG", "CVSpbcgB", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  pset_B = NULL;
-  psolve_B = NULL;
-  P_data_B = NULL;
-
-  /* initialize Jacobian function */
-  jtimes_B = NULL;
-
-  /* attach lmemB and lfree */
-  cvB_mem->cv_lmem = cvspilsB_mem;
-  cvB_mem->cv_lfree = CVSpbcgFreeB;
-
-  flag = CVSpbcg(cvodeB_mem, pretypeB, maxlB);
-
-  if (flag != CVSPILS_SUCCESS) {
-    free(cvspilsB_mem);
-    cvspilsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * CVSpbcgFreeB 
- */
-
-
-static int CVSpbcgFreeB(CVodeBMem cvB_mem)
-{
-  CVSpilsMemB cvspilsB_mem;
-
-  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
-
-  free(cvspilsB_mem);
-
-  return(0);
-}
diff --git a/src/cvodes/cvodes_spgmr.c b/src/cvodes/cvodes_spgmr.c
deleted file mode 100644
index c18d3da..0000000
--- a/src/cvodes/cvodes_spgmr.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSPGMR linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvodes/cvodes_spgmr.h>
-#include "cvodes_spils_impl.h"
-#include "cvodes_impl.h"
-
-#include <sundials/sundials_spgmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* CVSPGMR linit, lsetup, lsolve, and lfree routines */
-
-static int CVSpgmrInit(CVodeMem cv_mem);
-
-static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3);
-
-static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow);
-
-static int CVSpgmrFree(CVodeMem cv_mem);
-
-/* CVSPGMR lfreeB function */
-
-static int CVSpgmrFreeB(CVodeBMem cvB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-
-/* Readability Replacements */
-
-#define tq           (cv_mem->cv_tq)
-#define nst          (cv_mem->cv_nst)
-#define tn           (cv_mem->cv_tn)
-#define h            (cv_mem->cv_h)
-#define gamma        (cv_mem->cv_gamma)
-#define gammap       (cv_mem->cv_gammap)   
-#define f            (cv_mem->cv_f)
-#define user_data    (cv_mem->cv_user_data)
-#define ewt          (cv_mem->cv_ewt)
-#define mnewt        (cv_mem->cv_mnewt)
-#define ropt         (cv_mem->cv_ropt)
-#define linit        (cv_mem->cv_linit)
-#define lsetup       (cv_mem->cv_lsetup)
-#define lsolve       (cv_mem->cv_lsolve)
-#define lfree        (cv_mem->cv_lfree)
-#define lmem         (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define sqrtN     (cvspils_mem->s_sqrtN)   
-#define ytemp     (cvspils_mem->s_ytemp)
-#define x         (cvspils_mem->s_x)
-#define ycur      (cvspils_mem->s_ycur)
-#define fcur      (cvspils_mem->s_fcur)
-#define delta     (cvspils_mem->s_delta)
-#define deltar    (cvspils_mem->s_deltar)
-#define npe       (cvspils_mem->s_npe)
-#define nli       (cvspils_mem->s_nli)
-#define nps       (cvspils_mem->s_nps)
-#define ncfl      (cvspils_mem->s_ncfl)
-#define nstlpre   (cvspils_mem->s_nstlpre)
-#define njtimes   (cvspils_mem->s_njtimes)
-#define nfes      (cvspils_mem->s_nfes)
-#define spils_mem (cvspils_mem->s_spils_mem)
-
-#define jtimesDQ  (cvspils_mem->s_jtimesDQ)
-#define jtimes    (cvspils_mem->s_jtimes)
-#define j_data    (cvspils_mem->s_j_data)
-
-#define last_flag (cvspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmr
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the Spgmr linear solver module. CVSpgmr first
- * calls the existing lfree routine if this is not NULL.  It then sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be CVSpgmrInit, CVSpgmrSetup, CVSpgmrSolve, and CVSpgmrFree,
- * respectively.  It allocates memory for a structure of type
- * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure. It sets setupNonNull in (*cvode_mem),
- * and sets various fields in the CVSpilsMemRec structure.
- * Finally, CVSpgmr allocates memory for ytemp and x, and calls
- * SpgmrMalloc to allocate memory for the Spgmr solver.
- * -----------------------------------------------------------------
- */
-
-int CVSpgmr(void *cvode_mem, int pretype, int maxl)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-  SpgmrMem spgmr_mem;
-  int mxl;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPGMR", "CVSpgmr", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Check if N_VDotProd is present */
-  if(vec_tmpl->ops->nvdotprod == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_NVECTOR);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = CVSpgmrInit;
-  lsetup = CVSpgmrSetup;
-  lsolve = CVSpgmrSolve;
-  lfree  = CVSpgmrFree;
-
-  /* Get memory for CVSpilsMemRec */
-  cvspils_mem = NULL;
-  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
-  if (cvspils_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  cvspils_mem->s_type = SPILS_SPGMR;
-
-  /* Set Spgmr parameters that have been passed in call sequence */
-  cvspils_mem->s_pretype    = pretype;
-  mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  cvspils_mem->s_pset   = NULL;
-  cvspils_mem->s_psolve = NULL;
-  cvspils_mem->s_pfree  = NULL;
-  cvspils_mem->s_P_data = cv_mem->cv_user_data;
-
-  /* Set default values for the rest of the Spgmr parameters */
-  cvspils_mem->s_gstype     = MODIFIED_GS;
-  cvspils_mem->s_eplifac    = CVSPILS_EPLIN;
-  
-  cvspils_mem->s_last_flag  = CVSPILS_SUCCESS;
-
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmr", MSGS_BAD_PRETYPE);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  x = N_VClone(vec_tmpl);
-  if (x == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt( N_VDotProd(ytemp, ytemp) );
-
-  /* Call SpgmrMalloc to allocate workspace for Spgmr */
-  spgmr_mem = NULL;
-  spgmr_mem = SpgmrMalloc(mxl, vec_tmpl);
-  if (spgmr_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(x);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPGMR memory to spils memory structure */
-  spils_mem = (void *) spgmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvspils_mem;
-
-  return(CVSPILS_SUCCESS);
-}
-
-
-/* Additional readability Replacements */
-
-#define pretype (cvspils_mem->s_pretype)
-#define gstype  (cvspils_mem->s_gstype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define pset    (cvspils_mem->s_pset)
-#define P_data  (cvspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the Spgmr 
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrInit(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Initialize counters */
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((pretype != PREC_NONE) && (psolve == NULL)) {
-    cvProcessError(cv_mem, -1, "CVSPGMR", "CVSpgmrInit", MSGS_PSOLVE_REQ);
-    last_flag = CVSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning (pretype != PREC_NONE)
-     and there is a preconditioning setup phase (pset != NULL)             */
-  setupNonNull = (pretype != PREC_NONE) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = CVSpilsDQJtimes;
-    j_data = cv_mem;
-  } else {
-    j_data = user_data;
-  }
-
-  last_flag = CVSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the Spgmr linear solver.
- * It makes a decision as to whether or not to signal for re-evaluation
- * of Jacobian data in the pset routine, based on various state
- * variables, then it calls pset.  If we signal for re-evaluation,
- * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output.
- * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                        N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                        N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  CVSpilsMem cvspils_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) ||
-    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
-    (convfail == CV_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, 
-                vtemp1, vtemp2, vtemp3);
-  if (retval < 0) {
-    cvProcessError(cv_mem, SPGMR_PSET_FAIL_UNREC, "CVSPGMR", "CVSpgmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPGMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    last_flag = SPGMR_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    npe++;
-    nstlpre = nst;
-  }
-
-  last_flag = SPGMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic solver SpgmrSolve
- * for the solution of the linear system Ax = b with the SPGMR method,
- * without restarts.  The solution x is returned in the vector b.
- *
- * If the WRMS norm of b is small, we return x = b (if this is the first
- * Newton iteration) or x = 0 (if a later Newton iteration).
- *
- * Otherwise, we set the tolerance parameter and initial guess (x = 0),
- * call SpgmrSolve, and copy the solution x into b.  The x-scaling and
- * b-scaling arrays are both equal to weight, and no restarts are allowed.
- *
- * The counters nli, nps, and ncfl are incremented, and the return value
- * is set according to the success of SpgmrSolve.  The success flag is
- * returned if SpgmrSolve converged, or if this is the first Newton
- * iteration and the residual norm was reduced below its initial value.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                        N_Vector ynow, N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  CVSpilsMem cvspils_mem;
-  SpgmrMem spgmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  deltar = eplifac*tq[4]; 
-
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= deltar) {
-    if (mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  ycur = ynow;
-  fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SpgmrSolve */  
-  delta = deltar * sqrtN;
-  N_VConst(ZERO, x);
-  
-  /* Call SpgmrSolve and copy x to b */
-  retval = SpgmrSolve(spgmr_mem, cv_mem, x, b, pretype, gstype, delta, 0,
-                   cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve,
-                   &res_norm, &nli_inc, &nps_inc);
-
-  N_VScale(ONE, x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPGMR_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPGMR_SUCCESS:
-    return(0);
-    break;
-  case SPGMR_RES_REDUCED:
-    if (mnewt == 0) return(0);
-    else            return(1);
-    break;
-  case SPGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPGMR_ATIMES_FAIL_UNREC:
-    cvProcessError(cv_mem, SPGMR_ATIMES_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPGMR_PSOLVE_FAIL_UNREC:
-    cvProcessError(cv_mem, SPGMR_PSOLVE_FAIL_UNREC, "CVSPGMR", "CVSpgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);  
-
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpgmrFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the Spgmr linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSpgmrFree(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SpgmrMem spgmr_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-  
-  N_VDestroy(ytemp);
-  N_VDestroy(x);
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-  SpgmrFree(spgmr_mem);
-
-  if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem);
-
-  free(cvspils_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-
-/* Additional readability replacements */
-
-#define pset_B      (cvspilsB_mem->s_psetB)
-#define psolve_B    (cvspilsB_mem->s_psolveB)
-#define jtimes_B    (cvspilsB_mem->s_jtimesB)
-#define P_data_B    (cvspilsB_mem->s_P_dataB)
-
-/*
- * CVSpgmrB
- *
- * Wrapper for the backward phase
- *
- */
-
-int CVSpgmrB(void *cvode_mem, int which, int pretypeB, int maxlB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVSpilsMemB cvspilsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPGMR", "CVSpgmrB", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPGMR", "CVSpgmrB", MSGS_NO_ADJ);
-    return(CVSPILS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPGMR", "CVSpgmrB", MSGS_BAD_WHICH);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVSpilsMemRecB */
-  cvspilsB_mem = NULL;
-  cvspilsB_mem = (CVSpilsMemB) malloc(sizeof(struct CVSpilsMemRecB));
-  if (cvspilsB_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPGMR", "CVSpgmrB", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  pset_B = NULL;
-  psolve_B = NULL;
-  P_data_B = NULL;
-
-  /* initialize Jacobian function */
-  jtimes_B = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvspilsB_mem;
-  cvB_mem->cv_lfree = CVSpgmrFreeB;
-  
-  flag = CVSpgmr(cvodeB_mem, pretypeB, maxlB);
-
-  if (flag != CVSPILS_SUCCESS) {
-    free(cvspilsB_mem);
-    cvspilsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-
-/*
- * CVSpgmrFreeB 
- */
-
-
-static int CVSpgmrFreeB(CVodeBMem cvB_mem)
-{
-  CVSpilsMemB cvspilsB_mem;
-
-  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
-
-  free(cvspilsB_mem);
-
-  return(0);
-}
diff --git a/src/cvodes/cvodes_spils.c b/src/cvodes/cvodes_spils.c
index 559b44b..dc867ce 100644
--- a/src/cvodes/cvodes_spils.c
+++ b/src/cvodes/cvodes_spils.c
@@ -1,24 +1,29 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s):Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the implementation file for the CVSPILS linear solvers.
+ * This is the implementation file for the CVSPILS linear solver
+ * interface.
+ *
+ * Part I contains routines for using CVSPILS on forward problems.
  *
- * Part II contains wrappers for using the CVODES iterative linear 
- * solvers on adjoint (backward) problems.
+ * Part II contains wrappers for using CVSPILS on adjoint 
+ * (backward) problems.
  * -----------------------------------------------------------------
  */
 
@@ -27,6 +32,7 @@
 
 #include "cvodes_impl.h"
 #include "cvodes_spils_impl.h"
+#include <sundials/sundials_math.h>
 
 /* Private constants */
 
@@ -38,579 +44,556 @@
 
 #define MAX_ITERS  3  /* max. number of attempts to recover in DQ J*v */
 
-/* 
- * =================================================================
- * PRIVATE FUNCTION PROTOTYPES
- * =================================================================
- */
-
-/*
- * cvSpilsPrecSetupBWrapper and cvSpilsPrecSetupBSWrapper have type
- * CVSpilsPrecSetupFn, and wrap around user-provided functions of
- * type CVSpilsPrecSetupFnB and CVSpilsPrecSetupFnBS, respectively.
- */
-
-static int cvSpilsPrecSetupBWrapper(realtype t, N_Vector yB,
-                                    N_Vector fyB, booleantype jokB,
-                                    booleantype *jcurPtrB, realtype gammaB,
-                                    void *cvode_mem,
-                                    N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-static int cvSpilsPrecSetupBSWrapper(realtype t, N_Vector yB,
-                                     N_Vector fyB, booleantype jokB,
-                                     booleantype *jcurPtrB, realtype gammaB,
-                                     void *cvode_mem,
-                                     N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * cvSpilsPrecSolveBWrapper and cvSpilsPrecSolveBSWrapper have type
- * CVSpilsPrecSolveFn, and wrap around user-provided functions of
- * type CVSpilsPrecSolveFnB and CVSpilsPrecSolveFnBS, respectively.
- */
-
+/*=================================================================
+  PRIVATE FUNCTION PROTOTYPES
+  =================================================================*/
+
+/* cvSpilsPrecSetupBWrapper and cvSpilsPrecSetupBSWrapper have type
+   CVSpilsPrecSetupFn, and wrap around user-provided functions of
+   type CVSpilsPrecSetupFnB and CVSpilsPrecSetupFnBS, respectively */
+static int cvSpilsPrecSetupBWrapper(realtype t, N_Vector yB, N_Vector fyB, 
+                                    booleantype jokB, booleantype *jcurPtrB, 
+                                    realtype gammaB, void *cvode_mem);
+static int cvSpilsPrecSetupBSWrapper(realtype t, N_Vector yB, N_Vector fyB, 
+                                     booleantype jokB, booleantype *jcurPtrB, 
+                                     realtype gammaB, void *cvode_mem);
+
+/* cvSpilsPrecSolveBWrapper and cvSpilsPrecSolveBSWrapper have type
+   CVSpilsPrecSolveFn, and wrap around user-provided functions of
+   type CVSpilsPrecSolveFnB and CVSpilsPrecSolveFnBS, respectively */
 static int cvSpilsPrecSolveBWrapper(realtype t, N_Vector yB, N_Vector fyB,
                                     N_Vector rB, N_Vector zB,
                                     realtype gammaB, realtype deltaB,
-                                    int lrB, void *cvode_mem, N_Vector tmpB);
-  
+                                    int lrB, void *cvode_mem);
 static int cvSpilsPrecSolveBSWrapper(realtype t, N_Vector yB, N_Vector fyB,
                                      N_Vector rB, N_Vector zB,
                                      realtype gammaB, realtype deltaB,
-                                     int lrB, void *cvode_mem, N_Vector tmpB);
-  
-/*
- * cvSpilsJacTimesVecBWrapper and cvSpilsJacTimesVecBSWrapper have type
- * CVSpilsJacTimesVecFn, and wrap around user-provided functions of
- * type CVSpilsJacTimesVecFnB and CVSpilsJacTimesVecFnBS, respectively.
- */
-
+                                     int lrB, void *cvode_mem);
+
+/* cvSpilsJacTimesSetupBWrapper and cvSpilsJacTimesSetupBSWrapper have type
+   CVSpilsJacTimesSetupFn, and wrap around user-provided functions of
+   type CVSpilsJacTimesSetupFnB and CVSpilsJacTimesSetupFnBS, respectively */
+static int cvSpilsJacTimesSetupBWrapper(realtype t, N_Vector yB,
+                                        N_Vector fyB, void *cvode_mem);
+static int cvSpilsJacTimesSetupBSWrapper(realtype t, N_Vector yB,
+                                         N_Vector fyB, void *cvode_mem);
+
+/* cvSpilsJacTimesVecBWrapper and cvSpilsJacTimesVecBSWrapper have type
+   CVSpilsJacTimesVecFn, and wrap around user-provided functions of
+   type CVSpilsJacTimesVecFnB and CVSpilsJacTimesVecFnBS, respectively */
 static int cvSpilsJacTimesVecBWrapper(N_Vector vB, N_Vector JvB, realtype t, 
                                       N_Vector yB, N_Vector fyB, 
                                       void *cvode_mem, N_Vector tmpB);
-
 static int cvSpilsJacTimesVecBSWrapper(N_Vector vB, N_Vector JvB, realtype t, 
                                        N_Vector yB, N_Vector fyB, 
                                        void *cvode_mem, N_Vector tmpB);
 
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define lrw1      (cv_mem->cv_lrw1)
-#define liw1      (cv_mem->cv_liw1)
-#define tq        (cv_mem->cv_tq)
-#define tn        (cv_mem->cv_tn)
-#define h         (cv_mem->cv_h)
-#define gamma     (cv_mem->cv_gamma)
-#define nfe       (cv_mem->cv_nfe)
-#define f         (cv_mem->cv_f)
-#define user_data (cv_mem->cv_user_data)
-#define ewt       (cv_mem->cv_ewt)
-#define lmem      (cv_mem->cv_lmem)
-
-#define ils_type (cvspils_mem->s_type)
-#define sqrtN    (cvspils_mem->s_sqrtN)   
-#define ytemp    (cvspils_mem->s_ytemp)
-#define x        (cvspils_mem->s_x)
-#define ycur     (cvspils_mem->s_ycur)
-#define fcur     (cvspils_mem->s_fcur)
-#define delta    (cvspils_mem->s_delta)
-#define npe      (cvspils_mem->s_npe)
-#define nli      (cvspils_mem->s_nli)
-#define nps      (cvspils_mem->s_nps)
-#define ncfl     (cvspils_mem->s_ncfl)
-#define njtimes  (cvspils_mem->s_njtimes)
-#define nfes     (cvspils_mem->s_nfes)
-
-#define jtimesDQ (cvspils_mem->s_jtimesDQ)
-#define jtimes   (cvspils_mem->s_jtimes)
-#define j_data   (cvspils_mem->s_j_data)
-
-#define last_flag (cvspils_mem->s_last_flag)
-
-
-/*
- * -----------------------------------------------------------------
- * OPTIONAL INPUT and OUTPUT FUNCTIONS
- * -----------------------------------------------------------------
- */
 
+/*================================================================
+  PART I - forward problems
+  ================================================================*/
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetPrecType
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Required functions
+  -----------------------------------------------------------------*/
 
-int CVSpilsSetPrecType(void *cvode_mem, int pretype)
+/*---------------------------------------------------------------
+ CVSpilsSetLinearSolver specifies the iterative linear solver.
+---------------------------------------------------------------*/
+int CVSpilsSetLinearSolver(void *cvode_mem, SUNLinearSolver LS)
 {
+  int retval;
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+		    "CVSpilsSetLinearSolver", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
+  if (LS == NULL) {
+    cvProcessError(NULL, CVSPILS_ILL_INPUT, "CVSSPILS", 
+		    "CVSpilsSetLinearSolver", 
+                    "LS must be non-NULL");
+    return(CVSPILS_ILL_INPUT);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPrecType", MSGS_LMEM_NULL);
-    return(CVSPILS_LMEM_NULL);
+  /* Test if solver and vector are compatible with SPILS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_ITERATIVE) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS", 
+                    "CVSpilsSetLinearSolver", 
+                    "Non-iterative LS supplied to CVSpils interface");
+    return(CVSPILS_ILL_INPUT);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPrecType", MSGS_BAD_PRETYPE);
+  if ( (cv_mem->cv_tempv->ops->nvlinearsum == NULL) ||
+       (cv_mem->cv_tempv->ops->nvconst == NULL) ||
+       (cv_mem->cv_tempv->ops->nvdotprod == NULL) ){
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_BAD_NVECTOR);
     return(CVSPILS_ILL_INPUT);
   }
 
-  cvspils_mem->s_pretype = pretype;
+  /* free any existing system solver attached to CVode */
+  if (cv_mem->cv_lfree)  cv_mem->cv_lfree(cv_mem);
+
+  /* Set four main system linear solver function fields in cv_mem */
+  cv_mem->cv_linit  = cvSpilsInitialize;
+  cv_mem->cv_lsetup = cvSpilsSetup;
+  cv_mem->cv_lsolve = cvSpilsSolve;
+  cv_mem->cv_lfree  = cvSpilsFree;
+  
+  /* Get memory for CVSpilsMemRec */
+  cvspils_mem = NULL;
+  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
+  if (cvspils_mem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer */
+  cvspils_mem->LS = LS;
+  
+  /* Set defaults for Jacobian-related fields */
+  cvspils_mem->jtimesDQ = SUNTRUE;
+  cvspils_mem->jtsetup = NULL;
+  cvspils_mem->jtimes = CVSpilsDQJtimes;
+  cvspils_mem->j_data = cv_mem;
+
+  /* Set defaults for preconditioner-related fields */
+  cvspils_mem->pset   = NULL;
+  cvspils_mem->psolve = NULL;
+  cvspils_mem->pfree  = NULL;
+  cvspils_mem->P_data = cv_mem->cv_user_data;
+
+  /* Initialize counters */
+  cvSpilsInitializeCounters(cvspils_mem);
+
+  /* Set default values for the rest of the SPILS parameters */
+  cvspils_mem->jbad = SUNTRUE;
+  cvspils_mem->eplifac = CVSPILS_EPLIN;
+  cvspils_mem->last_flag = CVSPILS_SUCCESS;
+
+  /* Attach default CVSpils interface routines to iterative LS */
+  retval = SUNLinSolSetATimes(LS, cv_mem, CVSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSSPILS", 
+                    "CVSpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetATimes");
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_SUNLS_FAIL);
+  }
+  retval = SUNLinSolSetPreconditioner(LS, cv_mem, NULL, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSSPILS", 
+                    "CVSpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_SUNLS_FAIL);
+  }
+
+  /* Allocate memory for ytemp and x */
+  cvspils_mem->ytemp = N_VClone(cv_mem->cv_tempv);
+  if (cvspils_mem->ytemp == NULL) {
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_MEM_FAIL);
+  }
+
+  cvspils_mem->x = N_VClone(cv_mem->cv_tempv);
+  if (cvspils_mem->x == NULL) {
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSSPILS", 
+                    "CVSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    N_VDestroy(cvspils_mem->ytemp);
+    free(cvspils_mem); cvspils_mem = NULL;
+    return(CVSPILS_MEM_FAIL);
+  }
+
+  /* Compute sqrtN from a dot product */
+  N_VConst(ONE, cvspils_mem->ytemp);
+  cvspils_mem->sqrtN = SUNRsqrt( N_VDotProd(cvspils_mem->ytemp, 
+                                            cvspils_mem->ytemp) );
+
+  /* Attach linear solver memory to integrator memory */
+  cv_mem->cv_lmem = cvspils_mem;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetGSType
- * -----------------------------------------------------------------
- */
 
-int CVSpilsSetGSType(void *cvode_mem, int gstype)
+/*-----------------------------------------------------------------
+  OPTIONAL INPUT and OUTPUT FUNCTIONS
+  -----------------------------------------------------------------*/
+
+
+int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetEpsLin", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetGSType", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsSetEpsLin", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  if (ils_type != SPILS_SPGMR) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_LSTYPE);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Check for legal gstype */
-  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSType", MSGS_BAD_GSTYPE);
+  /* Check for legal eplifac */
+  if(eplifac < ZERO) {
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS",
+                   "CVSpilsSetEpsLin", MSGS_BAD_EPLIN);
     return(CVSPILS_ILL_INPUT);
   }
 
-  cvspils_mem->s_gstype = gstype;
+  cvspils_mem->eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : CVSpilsSetMaxl
- * -----------------------------------------------------------------
- */
 
-int CVSpilsSetMaxl(void *cvode_mem, int maxl)
+int CVSpilsSetPreconditioner(void *cvode_mem,
+                             CVSpilsPrecSetupFn psetup,
+                             CVSpilsPrecSolveFn psolve)
 {
+  int retval;
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
-  int mxl;
+  PSetupFn cvspils_psetup;
+  PSolveFn cvspils_psolve;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetPreconditioner", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(NULL, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetMaxl", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsSetPreconditioner", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  if (ils_type == SPILS_SPGMR) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetMaxl", MSGS_BAD_LSTYPE);
-    return(CVSPILS_ILL_INPUT);
-  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  mxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-  cvspils_mem->s_maxl = mxl;
+  /* store function pointers for user-supplied routines in CVSpils interface */
+  cvspils_mem->pset   = psetup;
+  cvspils_mem->psolve = psolve;
 
-  /*  spbcg_mem->l_max  = mxl; */
+  /* notify iterative linear solver to call CVSpils interface routines */
+  cvspils_psetup = (psetup == NULL) ? NULL : CVSpilsPSetup;
+  cvspils_psolve = (psolve == NULL) ? NULL : CVSpilsPSolve;
+  retval = SUNLinSolSetPreconditioner(cvspils_mem->LS, cv_mem, 
+                                      cvspils_psetup, cvspils_psolve);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSSPILS", 
+                   "CVSpilsSetPreconditioner", 
+                   "Error in calling SUNLinSolSetPreconditioner");
+    return(CVSPILS_SUNLS_FAIL);
+  }
 
   return(CVSPILS_SUCCESS);
 }
 
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetEpsLin
- * -----------------------------------------------------------------
- */
-
-int CVSpilsSetEpsLin(void *cvode_mem, realtype eplifac)
+int CVSpilsSetJacTimes(void *cvode_mem,
+                       CVSpilsJacTimesSetupFn jtsetup,
+                       CVSpilsJacTimesVecFn jtimes)
 {
+  int retval;
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetJacTimesVecFn", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetEpsLin", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  /* Check for legal eplifac */
-  if(eplifac < ZERO) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetEpsLin", MSGS_BAD_EPLIN);
-    return(CVSPILS_ILL_INPUT);
+  /* store function pointers for user-supplied routines in CVSpils 
+     interface (NULL jtimes implies use of DQ default) */
+  if (jtimes != NULL) {
+    cvspils_mem->jtimesDQ = SUNFALSE;
+    cvspils_mem->jtimes   = jtimes;
+  } else {
+    cvspils_mem->jtimesDQ = SUNTRUE;
   }
+  cvspils_mem->jtsetup = jtsetup;
 
-  cvspils_mem->s_eplifac = (eplifac == ZERO) ? CVSPILS_EPLIN : eplifac;
+  /* notify iterative linear solver to call CVSpils interface routines */
+  retval = SUNLinSolSetATimes(cvspils_mem->LS, cv_mem, CVSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSSPILS", 
+                    "CVSpilsSetJacTimes", 
+                    "Error in calling SUNLinSolSetATimes");
+    return(CVSPILS_SUNLS_FAIL);
+  }
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetPrecSetupFn
- * -----------------------------------------------------------------
- */
 
-int CVSpilsSetPreconditioner(void *cvode_mem,
-                             CVSpilsPrecSetupFn pset, CVSpilsPrecSolveFn psolve)
+int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS,
+                        long int *leniwLS)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetWorkSpace", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetPreconditioner", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetWorkSpace", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  cvspils_mem->s_pset = pset;
-  cvspils_mem->s_psolve = psolve;
+  /* start with fixed sizes plus NVectors */
+  *lenrwLS = 4;
+  *leniwLS = 10;
 
-  return(CVSPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSpilsSetJacTimesVecFn
- * -----------------------------------------------------------------
- */
-
-int CVSpilsSetJacTimesVecFn(void *cvode_mem, CVSpilsJacTimesVecFn jtv)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
+  /* add NVector sizes */
+  if (cv_mem->cv_tempv->ops->nvspace) {
+    N_VSpace(cv_mem->cv_tempv, &lrw1, &liw1);
+    *lenrwLS += 2*lrw1;
+    *leniwLS += 2*liw1;
   }
-  cv_mem = (CVodeMem) cvode_mem;
 
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
-    return(CVSPILS_LMEM_NULL);
-  }
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  if (jtv != NULL) {
-    jtimesDQ = FALSE;
-    jtimes = jtv;
-  } else {
-    jtimesDQ = TRUE;
+  /* add LS sizes */
+  if (cvspils_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(cvspils_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetWorkSpace
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetWorkSpace(void *cvode_mem, long int *lenrwLS, long int *leniwLS)
+int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
-  int maxl;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumPrecEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetWorkSpace", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  
-  switch(ils_type) {
-  case SPILS_SPGMR:
-    maxl = cvspils_mem->s_maxl;
-    *lenrwLS = lrw1*(maxl + 5) + maxl*(maxl + 4) + 1;
-    *leniwLS = liw1*(maxl + 5);
-    break;
-  case SPILS_SPBCG:
-    *lenrwLS = lrw1 * 9;
-    *leniwLS = liw1 * 9;
-    break;
-  case SPILS_SPTFQMR:
-    *lenrwLS = lrw1*11;
-    *leniwLS = liw1*11;
-    break;
-  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
+  *npevals = cvspils_mem->npe;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumPrecEvals
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumPrecEvals(void *cvode_mem, long int *npevals)
+int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumPrecSolves", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *npevals = npe;
+  *npsolves = cvspils_mem->nps;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumPrecSolves
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumPrecSolves(void *cvode_mem, long int *npsolves)
+int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumLinIters", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumLinIters", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *npsolves = nps;
+  *nliters = cvspils_mem->nli;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumLinIters
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumLinIters(void *cvode_mem, long int *nliters)
+int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumConvFails", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumLinIters", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumConvFails", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *nliters = nli;
+  *nlcfails = cvspils_mem->ncfl;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumConvFails
- * -----------------------------------------------------------------
- */
 
-int CVSpilsGetNumConvFails(void *cvode_mem, long int *nlcfails)
+int CVSpilsGetNumJTSetupEvals(void *cvode_mem, long int *njtsetups)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumJTSetupEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumConvFails", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumJTSetupEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *nlcfails = ncfl;
+  *njtsetups = cvspils_mem->njtsetup;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumJtimesEvals
- * -----------------------------------------------------------------
- */
 
 int CVSpilsGetNumJtimesEvals(void *cvode_mem, long int *njvevals)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumJtimesEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *njvevals = njtimes;
+  *njvevals = cvspils_mem->njtimes;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetNumRhsEvals
- * -----------------------------------------------------------------
- */
 
 int CVSpilsGetNumRhsEvals(void *cvode_mem, long int *nfevalsLS)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumRhsEvals", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetNumRhsEvals", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetNumRhsEvals", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *nfevalsLS = nfes;
+  *nfevalsLS = cvspils_mem->nfes;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetLastFlag
- * -----------------------------------------------------------------
- */
 
 int CVSpilsGetLastFlag(void *cvode_mem, long int *flag)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
 
-  /* Return immediately if cvode_mem is NULL */
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsGetLastFlag", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
-
-  if (lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSPILS", "CVSpilsGetLastFlag", MSGS_LMEM_NULL);
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS",
+                   "CVSpilsGetLastFlag", MSGS_LMEM_NULL);
     return(CVSPILS_LMEM_NULL);
   }
-  cvspils_mem = (CVSpilsMem) lmem;
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  *flag = last_flag;
+  *flag = cvspils_mem->last_flag;
 
   return(CVSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsGetReturnFlagName
- * -----------------------------------------------------------------
- */
 
 char *CVSpilsGetReturnFlagName(long int flag)
 {
@@ -637,6 +620,9 @@ char *CVSpilsGetReturnFlagName(long int flag)
   case CVSPILS_PMEM_NULL:
     sprintf(name,"CVSPILS_PMEM_NULL");
     break;
+  case CVSPILS_SUNLS_FAIL:
+    sprintf(name,"CVSPILS_SUNLS_FAIL");
+    break;
   case CVSPILS_NO_ADJ:
     sprintf(name,"CVSPILS_NO_ADJ");
     break;
@@ -650,107 +636,172 @@ char *CVSpilsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSPILS private functions
- * -----------------------------------------------------------------
- */
-
-
-/* Additional readability Replacements */
+/*-----------------------------------------------------------------
+  CVSSPILS private functions
+  -----------------------------------------------------------------*/
 
-#define pretype (cvspils_mem->s_pretype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define P_data  (cvspils_mem->s_P_data)
+/*-----------------------------------------------------------------
+  CVSpilsATimes
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsAtimes
- * -----------------------------------------------------------------
- * This routine generates the matrix-vector product z = Mv, where
- * M = I - gamma*J. The product J*v is obtained by calling the jtimes 
- * routine. It is then scaled by -gamma and added to v to obtain M*v.
- * The return value is the same as the value returned by jtimes --
- * 0 if successful, nonzero otherwise.
- * -----------------------------------------------------------------
- */
-
-int CVSpilsAtimes(void *cvode_mem, N_Vector v, N_Vector z)
+  This routine generates the matrix-vector product z = Mv, where
+  M = I - gamma*J. The product J*v is obtained by calling the jtimes 
+  routine. It is then scaled by -gamma and added to v to obtain M*v.
+  The return value is the same as the value returned by jtimes --
+  0 if successful, nonzero otherwise.
+  -----------------------------------------------------------------*/
+int CVSpilsATimes(void *cvode_mem, N_Vector v, N_Vector z)
 {
   CVodeMem   cv_mem;
   CVSpilsMem cvspils_mem;
-  int retval;
+  int jtflag;
 
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+                   "CVSpilsATimes", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
-  cvspils_mem = (CVSpilsMem) lmem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS", 
+                   "CVSpilsATimes", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  retval = jtimes(v, z, tn, ycur, fcur, j_data, ytemp);
-  njtimes++;
-  if (retval != 0) return(retval);
+  jtflag = cvspils_mem->jtimes(v, z, cv_mem->cv_tn,
+                               cvspils_mem->ycur,
+                               cvspils_mem->fcur,
+                               cvspils_mem->j_data,
+                               cvspils_mem->ytemp);
+  cvspils_mem->njtimes++;
+  if (jtflag != 0) return(jtflag);
 
-  N_VLinearSum(ONE, v, -gamma, z, z);
+  N_VLinearSum(ONE, v, -cv_mem->cv_gamma, z, z);
 
   return(0);
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsPSolve
- * -----------------------------------------------------------------
- * This routine interfaces between the generic Sp***Solve routine
- * (within the SPGMR, SPBCG, or SPTFQMR solver) and the
- * user's psolve routine.  It passes to psolve all required state 
- * information from cvode_mem.  Its return value is the same as that
- * returned by psolve. Note that the generic SP*** solver guarantees
- * that CVSpilsPSolve will not be called in the case in which
- * preconditioning is not done. This is the only case in which the
- * user's psolve routine is allowed to be NULL.
- * -----------------------------------------------------------------
- */
 
-int CVSpilsPSolve(void *cvode_mem, N_Vector r, N_Vector z, int lr)
+/*---------------------------------------------------------------
+ CVSpilsPSetup:
+
+ This routine interfaces between the generic iterative linear 
+ solvers and the user's psetup routine.  It passes to psetup all 
+ required state information from cvode_mem.  Its return value 
+ is the same as that returned by psetup. Note that the generic
+ iterative linear solvers guarantee that CVSpilsPSetup will only
+ be called in the case that the user's psetup routine is non-NULL.
+---------------------------------------------------------------*/
+int CVSpilsPSetup(void *cvode_mem)
 {
+  int        retval;
   CVodeMem   cv_mem;
   CVSpilsMem cvspils_mem;
-  int retval;
 
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+                   "CVSpilsPSetup", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
-  cvspils_mem = (CVSpilsMem)lmem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS", 
+                   "CVSpilsPSetup", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* Call user pset routine to update preconditioner and possibly 
+     reset jcur (pass !jbad as update suggestion) */
+  retval = cvspils_mem->pset(cv_mem->cv_tn, 
+                             cvspils_mem->ycur, 
+                             cvspils_mem->fcur, 
+                             !(cvspils_mem->jbad),
+                             &cv_mem->cv_jcur,
+                             cv_mem->cv_gamma, 
+                             cvspils_mem->P_data);
+  return(retval);     
+}
+
+
+/*-----------------------------------------------------------------
+  CVSpilsPSolve
+
+  This routine interfaces between the generic SUNLinSolSolve 
+  routine and the user's psolve routine.  It passes to psolve all
+  required state information from cvode_mem.  Its return value is 
+  the same as that returned by psolve. Note that the generic 
+  SUNLinSol solver guarantees that CVSpilsPSolve will not be called 
+  in the case in which preconditioning is not done. This is the 
+  only case in which the user's psolve routine is allowed to be 
+  NULL.
+  -----------------------------------------------------------------*/
+int CVSpilsPSolve(void *cvode_mem, N_Vector r, N_Vector z,
+                  realtype tol, int lr)
+{
+  CVodeMem   cv_mem;
+  CVSpilsMem cvspils_mem;
+  int retval;
 
-  /* This call is counted in nps within the CVSp***Solve routine */
-  retval = psolve(tn, ycur, fcur, r, z, gamma, delta, lr, P_data, ytemp);
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+                   "CVSpilsPSolve", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  cv_mem = (CVodeMem) cvode_mem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS", 
+                   "CVSpilsPSolve", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
+  /* call the user-supplied psolve routine, and accumulate count */
+  retval = cvspils_mem->psolve(cv_mem->cv_tn, cvspils_mem->ycur,
+                               cvspils_mem->fcur, r, z,
+                               cv_mem->cv_gamma, tol, lr,
+                               cvspils_mem->P_data);
+  cvspils_mem->nps++;
   return(retval);     
 }
 
-/*
- * -----------------------------------------------------------------
- * CVSpilsDQJtimes
- * -----------------------------------------------------------------
- * This routine generates a difference quotient approximation to
- * the Jacobian times vector f_y(t,y) * v. The approximation is 
- * Jv = vnrm[f(y + v/vnrm) - f(y)], where vnrm = (WRMS norm of v) is
- * input, i.e. the WRMS norm of v/vnrm is 1.
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  CVSpilsDQJtimes
+
+  This routine generates a difference quotient approximation to
+  the Jacobian times vector f_y(t,y) * v. The approximation is 
+  Jv = vnrm[f(y + v/vnrm) - f(y)], where vnrm = (WRMS norm of v) is
+  input, i.e. the WRMS norm of v/vnrm is 1.
+  -----------------------------------------------------------------*/
 int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t, 
                     N_Vector y, N_Vector fy,
-                    void *data, N_Vector work)
+                    void *cvode_mem, N_Vector work)
 {
   CVodeMem cv_mem;
   CVSpilsMem cvspils_mem;
   realtype sig, siginv;
   int iter, retval;
 
-  /* data is cvode_mem */
-  cv_mem = (CVodeMem) data;
-  cvspils_mem = (CVSpilsMem) lmem;
+  /* Return immediately if cvode_mem or cv_mem->cv_lmem are NULL */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+                   "CVSpilsDQJtimes", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  cv_mem = (CVodeMem) cvode_mem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS", 
+                   "CVSpilsDQJtimes", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
   /* Initialize perturbation to 1/||v|| */
-  sig = ONE/N_VWrmsNorm(v, ewt);
+  sig = ONE/N_VWrmsNorm(v, cv_mem->cv_ewt);
 
   for (iter=0; iter<MAX_ITERS; iter++) {
 
@@ -758,8 +809,8 @@ int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
     N_VLinearSum(sig, v, ONE, y, work);
 
     /* Set Jv = f(tn, y+sig*v) */
-    retval = f(t, work, Jv, user_data); 
-    nfes++;
+    retval = cv_mem->cv_f(t, work, Jv, cv_mem->cv_user_data); 
+    cvspils_mem->nfes++;
     if (retval == 0) break;
     if (retval < 0)  return(-1);
 
@@ -776,157 +827,333 @@ int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
 }
 
 
-int cvSpilsInitializeCounters(CVSpilsMem cvspils_mem)
-{
-  cvspils_mem->s_npe     = 0;
-  cvspils_mem->s_nli     = 0;
-  cvspils_mem->s_nps     = 0;
-  cvspils_mem->s_ncfl    = 0;
-  cvspils_mem->s_nstlpre = 0;
-  cvspils_mem->s_njtimes = 0;
-  cvspils_mem->s_nfes    = 0;
+/*-----------------------------------------------------------------
+  cvSpilsInitialize
 
-  return(0);
-}
+  This routine performs remaining initializations specific
+  to the iterative linear solver interface (and solver itself)
+  -----------------------------------------------------------------*/
+int cvSpilsInitialize(CVodeMem cv_mem)
+{
+  CVSpilsMem cvspils_mem;
 
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+                   "cvSpilsInitialize", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS", 
+                   "cvSpilsInitialize", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+  
+  cvSpilsInitializeCounters(cvspils_mem);
 
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
+  /* Set Jacobian-related fields, based on jtimesDQ */
+  if (cvspils_mem->jtimesDQ) {
+    cvspils_mem->jtsetup = NULL;
+    cvspils_mem->jtimes = CVSpilsDQJtimes;
+    cvspils_mem->j_data = cv_mem;
+  } else {
+    cvspils_mem->j_data = cv_mem->cv_user_data;
+  }
 
-/* Readability replacements */
+  /* if psetup is not present, then cvSpilsSetup does not need to be 
+     called, so set the lsetup function to NULL */
+  if (cvspils_mem->pset == NULL)  cv_mem->cv_lsetup = NULL;
 
-#define ytmp  (ca_mem->ca_ytmp)
-#define yStmp (ca_mem->ca_yStmp)
-#define IMget (ca_mem->ca_IMget)
-#define IMinterpSensi (ca_mem->ca_IMinterpSensi)
+  /* Call LS initialize routine */
+  cvspils_mem->last_flag = SUNLinSolInitialize(cvspils_mem->LS);
+  return(cvspils_mem->last_flag);
+}
 
-#define pset_B     (cvspilsB_mem->s_psetB)
-#define pset_BS     (cvspilsB_mem->s_psetBS)
-#define psolve_B   (cvspilsB_mem->s_psolveB)
-#define psolve_BS   (cvspilsB_mem->s_psolveBS)
-#define jtimes_B   (cvspilsB_mem->s_jtimesB)
-#define jtimes_BS   (cvspilsB_mem->s_jtimesBS)
 
-/*
- * -----------------------------------------------------------------
- * OPTIONAL INPUT and OUTPUT FUNCTIONS
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  cvSpilsSetup
 
-int CVSpilsSetPrecTypeB(void *cvode_mem, int which, int pretypeB)
+  This routine calls the LS 'setup' routine.
+  -----------------------------------------------------------------*/
+int cvSpilsSetup(CVodeMem cv_mem, int convfail, N_Vector y, 
+                 N_Vector fy, booleantype *jcurPtr, 
+                 N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
 {
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  int flag;
+  realtype dgamma;
+  int  retval;
+  CVSpilsMem cvspils_mem;
 
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPrecTypeB", MSGS_CVMEM_NULL);
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+                   "cvSpilsSetup", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
-  cv_mem = (CVodeMem) cvode_mem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS", 
+                   "cvSpilsSetup", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
 
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetPrecTypeB", MSGS_NO_ADJ);
-    return(CVSPILS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
+  /* Set CVSpils N_Vector pointers to current solution and rhs */
+  cvspils_mem->ycur = y;
+  cvspils_mem->fcur = fy;
 
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPrecTypeB", MSGS_BAD_WHICH);
-    return(CVSPILS_ILL_INPUT);
-  }
+  /* Use nst, gamma/gammap, and convfail to set J/P eval. flag jok */
+  dgamma = SUNRabs((cv_mem->cv_gamma/cv_mem->cv_gammap) - ONE);
+  cvspils_mem->jbad = (cv_mem->cv_nst == 0) || 
+    (cv_mem->cv_nst > cvspils_mem->nstlpre + CVSPILS_MSBPRE) ||
+    ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
+    (convfail == CV_FAIL_OTHER);
+  *jcurPtr = cvspils_mem->jbad;
+  
+  /* Call LS setup routine -- the LS will call CVSpilsPSetup, who will 
+     pass the heuristic suggestions above to the user code(s) */
+  retval = SUNLinSolSetup(cvspils_mem->LS, NULL);
 
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
+  /* If user set jcur to SUNTRUE, increment npe and save nst value */
+  if (*jcurPtr) {
+    cvspils_mem->npe++;
+    cvspils_mem->nstlpre = cv_mem->cv_nst;
   }
+  
+  /* Update jcur flag if we suggested an update */
+  if (cvspils_mem->jbad) *jcurPtr = SUNTRUE;
 
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
+  return(retval);
+}
 
-  flag = CVSpilsSetPrecType(cvodeB_mem, pretypeB);
 
-  return(flag);
-}
+/*-----------------------------------------------------------------
+  cvSpilsSolve
 
-int CVSpilsSetGSTypeB(void *cvode_mem, int which, int gstypeB)
+  This routine interfaces between CVode and the generic 
+  SUNLinearSolver object LS, by setting the appropriate tolerance 
+  and scaling vectors, calling the solver, and accumulating 
+  statistics from the solve for use/reporting by CVode.
+  -----------------------------------------------------------------*/
+int cvSpilsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+                 N_Vector ynow, N_Vector fnow)
 {
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetGSTypeB", MSGS_CVMEM_NULL);
+  realtype bnorm;
+  CVSpilsMem cvspils_mem;
+  int nli_inc, retval;
+  
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS", 
+                   "cvSpilsSolve", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
-  cv_mem = (CVodeMem) cvode_mem;
+  if (cv_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEM_NULL, "CVSSPILS", 
+                   "cvSpilsSolve", MSGS_LMEM_NULL);
+    return(CVSPILS_LMEM_NULL);
+  }
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* Test norm(b); if small, return x = 0 or x = b */
+  cvspils_mem->deltar = cvspils_mem->eplifac * cv_mem->cv_tq[4]; 
+  bnorm = N_VWrmsNorm(b, weight);
+  if (bnorm <= cvspils_mem->deltar) {
+    if (cv_mem->cv_mnewt > 0) N_VConst(ZERO, b); 
+    return(0);
+  }
+
+  /* Set vectors ycur and fcur for use by the Atimes and Psolve 
+     interface routines */
+  cvspils_mem->ycur = ynow;
+  cvspils_mem->fcur = fnow;
+
+  /* Set input tolerance and initial guess x = 0 to LS */  
+  cvspils_mem->delta = cvspils_mem->deltar * cvspils_mem->sqrtN;
+  N_VConst(ZERO, cvspils_mem->x);
+
+  /* Set scaling vectors for LS to use */
+  retval = SUNLinSolSetScalingVectors(cvspils_mem->LS,
+                                      weight,
+                                      weight);
+  if (retval != SUNLS_SUCCESS) {
+    cvProcessError(cv_mem, CVSPILS_SUNLS_FAIL, "CVSPILS", "cvSpilsSolve", 
+                    "Error in calling SUNLinSolSetScalingVectors");
+    return(CVSPILS_SUNLS_FAIL);
+  }
+
+  /* If a user-provided jtsetup routine is supplied, call that here */
+  if (cvspils_mem->jtsetup) {
+    retval = cvspils_mem->jtsetup(cv_mem->cv_tn, ynow, fnow, 
+                                  cvspils_mem->j_data);
+    cvspils_mem->njtsetup++;
+    if (retval != 0) {
+      cvProcessError(cv_mem, retval, "CVSSPILS", 
+                      "cvSpilsSolve", MSGS_JTSETUP_FAILED);
+      return(retval);
+    }
+  }
+  
+  /* Call solver, and copy x to b */
+  retval = SUNLinSolSolve(cvspils_mem->LS, NULL, cvspils_mem->x,
+                          b, cvspils_mem->delta);
+  N_VScale(ONE, cvspils_mem->x, b);
 
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetGSTypeB", MSGS_NO_ADJ);
-    return(CVSPILS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
+  /* Retrieve solver statistics */
+  nli_inc = SUNLinSolNumIters(cvspils_mem->LS);
+  
+  /* Increment counters nli and ncfl */
+  cvspils_mem->nli += nli_inc;
+  if (retval != SUNLS_SUCCESS) cvspils_mem->ncfl++;
 
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetGSTypeB", MSGS_BAD_WHICH);
-    return(CVSPILS_ILL_INPUT);
+  /* Interpret solver return value  */
+  cvspils_mem->last_flag = retval;
+
+  switch(retval) {
+
+  case SUNLS_SUCCESS:
+    return(0);
+    break;
+  case SUNLS_RES_REDUCED:
+    /* allow reduction but not solution on first Newton iteration, 
+       otherwise return with a recoverable failure */
+    if (cv_mem->cv_mnewt == 0) return(0);
+    else                       return(1);
+    break;
+  case SUNLS_CONV_FAIL:
+  case SUNLS_ATIMES_FAIL_REC:
+  case SUNLS_PSOLVE_FAIL_REC:
+  case SUNLS_PACKAGE_FAIL_REC:
+  case SUNLS_QRFACT_FAIL:
+  case SUNLS_LUFACT_FAIL:
+    return(1);
+    break;
+  case SUNLS_MEM_NULL:
+  case SUNLS_ILL_INPUT:
+  case SUNLS_MEM_FAIL:
+  case SUNLS_GS_FAIL:
+  case SUNLS_QRSOL_FAIL:
+    return(-1);
+    break;
+  case SUNLS_PACKAGE_FAIL_UNREC:
+    cvProcessError(cv_mem, SUNLS_PACKAGE_FAIL_UNREC, "CVSSPILS", 
+                   "cvSpilsSolve",
+                    "Failure in SUNLinSol external package");
+    return(-1);
+    break;
+  case SUNLS_ATIMES_FAIL_UNREC:
+    cvProcessError(cv_mem, SUNLS_ATIMES_FAIL_UNREC, "CVSSPILS", 
+                   "cvSpilsSolve", MSGS_JTIMES_FAILED);    
+    return(-1);
+    break;
+  case SUNLS_PSOLVE_FAIL_UNREC:
+    cvProcessError(cv_mem, SUNLS_PSOLVE_FAIL_UNREC, "CVSSPILS", 
+                   "cvSpilsSolve", MSGS_PSOLVE_FAILED);
+    return(-1);
+    break;
   }
+  
+  return(0); 
+}
 
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
+
+/*-----------------------------------------------------------------
+  cvSpilsFree
+
+  This routine frees memory associates with the CVSpils system
+  solver interface.
+  -----------------------------------------------------------------*/
+int cvSpilsFree(CVodeMem cv_mem)
+{
+  CVSpilsMem cvspils_mem;
+
+  /* Return immediately if cv_mem or cv_mem->cv_lmem are NULL */
+  if (cv_mem == NULL)  return (CVSPILS_SUCCESS);
+  if (cv_mem->cv_lmem == NULL)  return(CVSPILS_SUCCESS);
+  cvspils_mem = (CVSpilsMem) cv_mem->cv_lmem;
+
+  /* Free N_Vector memory */
+  if (cvspils_mem->ytemp) {
+    N_VDestroy(cvspils_mem->ytemp);
+    cvspils_mem->ytemp = NULL;
+  }
+  if (cvspils_mem->x) {
+    N_VDestroy(cvspils_mem->x);
+    cvspils_mem->x = NULL;
   }
 
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
+  /* Nullify other N_Vector pointers */
+  cvspils_mem->ycur = NULL;
+  cvspils_mem->fcur = NULL;
+
+  /* Free preconditioner memory (if applicable) */
+  if (cvspils_mem->pfree)  cvspils_mem->pfree(cv_mem);
+  
+  /* free CVSpils interface structure */
+  free(cv_mem->cv_lmem);
+  
+  return(CVSPILS_SUCCESS);
+}
+
 
-  flag = CVSpilsSetGSType(cvodeB_mem,gstypeB);
+/*-----------------------------------------------------------------
+  cvSpilsInitializeCounters
 
-  return(flag);
+  This routine resets all counters from an CVSpilsMem structure.
+  -----------------------------------------------------------------*/
+int cvSpilsInitializeCounters(CVSpilsMem cvspils_mem)
+{
+  cvspils_mem->npe      = 0;
+  cvspils_mem->nli      = 0;
+  cvspils_mem->nps      = 0;
+  cvspils_mem->ncfl     = 0;
+  cvspils_mem->nstlpre  = 0;
+  cvspils_mem->njtsetup = 0;
+  cvspils_mem->njtimes  = 0;
+  cvspils_mem->nfes     = 0;
+  return(0);
 }
 
-int CVSpilsSetEpsLinB(void *cvode_mem, int which, realtype eplifacB)
+
+/*================================================================
+  PART II - Backward Problems
+  ================================================================*/
+
+/*---------------------------------------------------------------
+  CVSSPILS Exported functions -- Required
+  ---------------------------------------------------------------*/
+
+/* CVSpilsSetLinearSolverB specifies the iterative linear solver 
+   for backward integration */
+int CVSpilsSetLinearSolverB(void *cvode_mem, int which,
+                            SUNLinearSolver LS)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
   CVodeBMem cvB_mem;
   void *cvodeB_mem;
+  CVSpilsMemB cvspilsB_mem;
   int flag;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetEpsLinB", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetLinearSolverB", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetEpsLinB", MSGS_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "CVSpilsSetLinearSolverB", MSGS_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetEpsLinB", MSGS_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS",
+                   "CVSpilsSetLinearSolverB", MSGS_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -937,38 +1164,76 @@ int CVSpilsSetEpsLinB(void *cvode_mem, int which, realtype eplifacB)
     cvB_mem = cvB_mem->cv_next;
   }
 
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
+  /* Get memory for CVSpilsMemRecB */
+  cvspilsB_mem = NULL;
+  cvspilsB_mem = (CVSpilsMemB) malloc(sizeof(struct CVSpilsMemRecB));
+  if (cvspilsB_mem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSSPILS",
+                   "CVSpilsSetLinearSolverB", MSGS_MEM_FAIL);
+    return(CVSPILS_MEM_FAIL);
+  }
+
+  /* initialize Jacobian and preconditioner functions */
+  cvspilsB_mem->jtsetupB  = NULL;
+  cvspilsB_mem->jtsetupBS = NULL;
+  cvspilsB_mem->jtimesB   = NULL;
+  cvspilsB_mem->jtimesBS  = NULL;
+  cvspilsB_mem->psetB     = NULL;
+  cvspilsB_mem->psetBS    = NULL;
+  cvspilsB_mem->psolveB   = NULL;
+  cvspilsB_mem->psolveBS  = NULL;
+  cvspilsB_mem->P_dataB   = NULL;
+
+  /* free any existing system solver attached to cvB */
+  if (cvB_mem->cv_lfree)  cvB_mem->cv_lfree(cvB_mem);
+  
+  /* Attach lmemB data and lfreeB function. */
+  cvB_mem->cv_lmem  = cvspilsB_mem;
+  cvB_mem->cv_lfree = cvSpilsFreeB;
 
-  flag = CVSpilsSetEpsLin(cvodeB_mem,eplifacB);
+  /* set the linear solver for this backward problem */
+  cvodeB_mem = (void *) (cvB_mem->cv_mem);
+  flag = CVSpilsSetLinearSolver(cvodeB_mem, LS);
+  if (flag != CVSPILS_SUCCESS) {
+    free(cvspilsB_mem);
+    cvspilsB_mem = NULL;
+  }
 
   return(flag);
 }
 
-int CVSpilsSetMaxlB(void *cvode_mem, int which, int maxlB)
+
+/*---------------------------------------------------------------
+  CVSSPILS Exported functions -- Optional input/output
+  ---------------------------------------------------------------*/
+
+int CVSpilsSetEpsLinB(void *cvode_mem, int which, realtype eplifacB)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
   CVodeBMem cvB_mem;
   void *cvodeB_mem;
-  int flag;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetMaxlB", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetEpsLinB", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetMaxlB", MSGS_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "CVSpilsSetEpsLinB", MSGS_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetMaxlB", MSGS_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS",
+                   "CVSpilsSetEpsLinB", MSGS_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -976,44 +1241,49 @@ int CVSpilsSetMaxlB(void *cvode_mem, int which, int maxlB)
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
+  /* cv_mem corresponding to 'which' problem. */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
-  flag = CVSpilsSetMaxl(cvodeB_mem,maxlB);
-
-  return(flag);
+  /* Call the corresponding Set* function for the backward problem */
+  return CVSpilsSetEpsLin(cvodeB_mem,eplifacB);
 }
 
+
 int CVSpilsSetPreconditionerB(void *cvode_mem, int which, 
-                              CVSpilsPrecSetupFnB psetB,
+                              CVSpilsPrecSetupFnB psetupB,
                               CVSpilsPrecSolveFnB psolveB)
 {
-  CVodeMem cv_mem;
   CVadjMem ca_mem;
+  CVodeMem cv_mem;
   CVodeBMem cvB_mem;
-  CVSpilsMemB cvspilsB_mem; 
   void *cvodeB_mem;
-  int flag;
+  CVSpilsMemB cvspilsB_mem; 
+  CVSpilsPrecSetupFn cvspils_psetup;
+  CVSpilsPrecSolveFn cvspils_psolve;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconditionerB", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetPreconditionerB", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetPreconditionerB", MSGS_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "CVSpilsSetPreconditionerB", MSGS_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPreconditionerB", MSGS_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS",
+                   "CVSpilsSetPreconditionerB", MSGS_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -1021,57 +1291,64 @@ int CVSpilsSetPreconditionerB(void *cvode_mem, int which,
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
+  /* cv_mem corresponding to 'which' problem. */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
   if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetPreconditionerB", MSGS_LMEMB_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "CVSpilsSetPreconditionerB", MSGS_LMEMB_NULL);
     return(CVSPILS_LMEMB_NULL);
   }
-  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  pset_B   = psetB;
-  psolve_B = psolveB;
+  /* Get the CVSpilsMemB data */
+  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  if (psetB == NULL) {
-    flag = CVSpilsSetPreconditioner(cvodeB_mem, NULL, cvSpilsPrecSolveBWrapper);
-  } else {
-    flag = CVSpilsSetPreconditioner(cvodeB_mem, cvSpilsPrecSetupBWrapper, cvSpilsPrecSolveBWrapper);
-  }
+  /* Set preconditioners for the backward problem. */
+  cvspilsB_mem->psetB   = psetupB;
+  cvspilsB_mem->psolveB = psolveB;
 
-  return(flag);
+  /* Call the corresponding "set" routine for the backward problem */
+  cvspils_psetup = (psetupB == NULL) ? NULL : cvSpilsPrecSetupBWrapper;
+  cvspils_psolve = (psolveB == NULL) ? NULL : cvSpilsPrecSolveBWrapper;
+  return CVSpilsSetPreconditioner(cvodeB_mem, cvspils_psetup, cvspils_psolve);
 }
 
+
 int CVSpilsSetPreconditionerBS(void *cvode_mem, int which, 
-                               CVSpilsPrecSetupFnBS psetBS,
+                               CVSpilsPrecSetupFnBS psetupBS,
                                CVSpilsPrecSolveFnBS psolveBS)
 {
-  CVodeMem cv_mem;
   CVadjMem ca_mem;
+  CVodeMem cv_mem;
   CVodeBMem cvB_mem;
-  CVSpilsMemB cvspilsB_mem; 
   void *cvodeB_mem;
-  int flag;
+  CVSpilsMemB cvspilsB_mem; 
+  CVSpilsPrecSetupFn cvspils_psetup;
+  CVSpilsPrecSolveFn cvspils_psolve;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetPreconditionerBS", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetPreconditionerBS", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetPreconditionerBS", MSGS_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "CVSpilsSetPreconditionerBS", MSGS_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetPreconditionerBS", MSGS_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS",
+                   "CVSpilsSetPreconditionerBS", MSGS_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -1079,55 +1356,64 @@ int CVSpilsSetPreconditionerBS(void *cvode_mem, int which,
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
+  /* cv_mem corresponding to 'which' problem. */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
   if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetPreconditionerBS", MSGS_LMEMB_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "CVSpilsSetPreconditionerBS", MSGS_LMEMB_NULL);
     return(CVSPILS_LMEMB_NULL);
   }
-  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  pset_BS   = psetBS;
-  psolve_BS = psolveBS;
+  /* Get the CVSpilsMemB data */
+  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  if (psetBS == NULL) {
-    flag = CVSpilsSetPreconditioner(cvodeB_mem, NULL, cvSpilsPrecSolveBSWrapper);
-  } else {
-    flag = CVSpilsSetPreconditioner(cvodeB_mem, cvSpilsPrecSetupBSWrapper, cvSpilsPrecSolveBSWrapper);
-  }
+  /* Set preconditioners for the backward problem. */
+  cvspilsB_mem->psetBS   = psetupBS;
+  cvspilsB_mem->psolveBS = psolveBS;
 
-  return(flag);
+  /* Call the corresponding "set" routine for the backward problem */
+  cvspils_psetup = (psetupBS == NULL) ? NULL : cvSpilsPrecSetupBSWrapper;
+  cvspils_psolve = (psolveBS == NULL) ? NULL : cvSpilsPrecSolveBSWrapper;
+  return CVSpilsSetPreconditioner(cvodeB_mem, cvspils_psetup, cvspils_psolve);
 }
 
-int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which, CVSpilsJacTimesVecFnB jtvB)
+
+int CVSpilsSetJacTimesB(void *cvode_mem, int which,
+                        CVSpilsJacTimesSetupFnB jtsetupB,
+                        CVSpilsJacTimesVecFnB jtimesB)
 {
-  CVodeMem cv_mem;
   CVadjMem ca_mem;
+  CVodeMem cv_mem;
   CVodeBMem cvB_mem;
-  CVSpilsMemB cvspilsB_mem; 
   void *cvodeB_mem;
-  int flag;
+  CVSpilsMemB cvspilsB_mem; 
+  CVSpilsJacTimesSetupFn cvspils_jtsetup;
+  CVSpilsJacTimesVecFn cvspils_jtimes;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetJacTimesB", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "CVSpilsSetJacTimesB", MSGS_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS",
+                   "CVSpilsSetJacTimesB", MSGS_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -1135,54 +1421,64 @@ int CVSpilsSetJacTimesVecFnB(void *cvode_mem, int which, CVSpilsJacTimesVecFnB j
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
+  /* cv_mem corresponding to 'which' problem */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
   if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnB", MSGS_LMEMB_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "CVSpilsSetJacTimesB", MSGS_LMEMB_NULL);
     return(CVSPILS_LMEMB_NULL);
   }
+  
+  /* Get the CVSpilsMemB data */
   cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  jtimes_B = jtvB;
-
-  if (jtvB != NULL) {
-    flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, cvSpilsJacTimesVecBWrapper);
-  } else {
-    flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, NULL);
-  }
+  /* Set jacobian routines for the backward problem. */
+  cvspilsB_mem->jtsetupB = jtsetupB;
+  cvspilsB_mem->jtimesB = jtimesB;
 
-  return(flag);
+  /* Call the corresponding "set" routine for the backward problem */
+  cvspils_jtsetup = (jtsetupB == NULL) ? NULL : cvSpilsJacTimesSetupBWrapper;
+  cvspils_jtimes  = (jtimesB == NULL)  ? NULL : cvSpilsJacTimesVecBWrapper;
+  return CVSpilsSetJacTimes(cvodeB_mem, cvspils_jtsetup, cvspils_jtimes);
 }
 
-int CVSpilsSetJacTimesVecFnBS(void *cvode_mem, int which, CVSpilsJacTimesVecFnBS jtvBS)
+
+int CVSpilsSetJacTimesSetupFnBS(void *cvode_mem, int which,
+                                CVSpilsJacTimesSetupFnBS jtsetupBS,
+                                CVSpilsJacTimesVecFnBS jtimesBS)
 {
-  CVodeMem cv_mem;
   CVadjMem ca_mem;
+  CVodeMem cv_mem;
   CVodeBMem cvB_mem;
-  CVSpilsMemB cvspilsB_mem; 
   void *cvodeB_mem;
-  int flag;
+  CVSpilsMemB cvspilsB_mem; 
+  CVSpilsJacTimesSetupFn cvspils_jtsetup;
+  CVSpilsJacTimesVecFn cvspils_jtimes;
 
   /* Check if cvode_mem exists */
   if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnBS", MSGS_CVMEM_NULL);
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "CVSpilsSetJacTimesBS", MSGS_CVMEM_NULL);
     return(CVSPILS_MEM_NULL);
   }
   cv_mem = (CVodeMem) cvode_mem;
 
   /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPILS", "CVSpilsSetJacTimesVecFnBS", MSGS_NO_ADJ);
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "CVSpilsSetJacTimesBS", MSGS_NO_ADJ);
     return(CVSPILS_NO_ADJ);
   } 
   ca_mem = cv_mem->cv_adj_mem;
 
   /* Check which */
   if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPILS", "CVSpilsSetJacTimesVecFnBS", MSGS_BAD_WHICH);
+    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSSPILS",
+                   "CVSpilsSetJacTimesBS", MSGS_BAD_WHICH);
     return(CVSPILS_ILL_INPUT);
   }
 
@@ -1190,47 +1486,41 @@ int CVSpilsSetJacTimesVecFnBS(void *cvode_mem, int which, CVSpilsJacTimesVecFnBS
   cvB_mem = ca_mem->cvB_mem;
   while (cvB_mem != NULL) {
     if ( which == cvB_mem->cv_index ) break;
+    /* advance */
     cvB_mem = cvB_mem->cv_next;
   }
-
+  /* cv_mem corresponding to 'which' problem. */
   cvodeB_mem = (void *) (cvB_mem->cv_mem);
 
   if (cvB_mem->cv_lmem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSPILS", "CVSpilsSetJacTimesVecFnBS", MSGS_LMEMB_NULL);
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "CVSpilsSetJacTimesBS", MSGS_LMEMB_NULL);
     return(CVSPILS_LMEMB_NULL);
   }
-  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  jtimes_BS = jtvBS;
+  /* Get the CVSpilsMemB data */
+  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  if (jtvBS != NULL) {
-    flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, cvSpilsJacTimesVecBSWrapper);
-  } else {
-    flag = CVSpilsSetJacTimesVecFn(cvodeB_mem, NULL);
-  }
+  /* Set jacobian routines for the backward problem. */
+  cvspilsB_mem->jtsetupBS = jtsetupBS;
+  cvspilsB_mem->jtimesBS  = jtimesBS;
 
-  return(flag);
+  /* Call the corresponding "set" routine for the backward problem */
+  cvspils_jtsetup = (jtsetupBS == NULL) ? NULL : cvSpilsJacTimesSetupBSWrapper;
+  cvspils_jtimes  = (jtimesBS == NULL)  ? NULL : cvSpilsJacTimesVecBSWrapper;
+  return CVSpilsSetJacTimes(cvodeB_mem, cvspils_jtsetup, cvspils_jtimes);
 }
 
 
-/*
- * -----------------------------------------------------------------
- * CVSPILS private functions
- * -----------------------------------------------------------------
- */
-
-/*
- * cvSpilsPrecSetupBWrapper
- *
- * This routine interfaces to the CVSpilsPrecSetupFnB routine 
- * provided by the user.
- */
+/*-----------------------------------------------------------------
+  CVSSPILS private functions
+  -----------------------------------------------------------------*/
 
-static int cvSpilsPrecSetupBWrapper(realtype t, N_Vector yB, 
-                                    N_Vector fyB, booleantype jokB, 
-                                    booleantype *jcurPtrB, realtype gammaB,
-                                    void *cvode_mem,
-                                    N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+/* cvSpilsPrecSetupBWrapper interfaces to the CVSpilsPrecSetupFnB 
+   routine provided by the user */
+static int cvSpilsPrecSetupBWrapper(realtype t, N_Vector yB, N_Vector fyB,  
+                                    booleantype jokB, booleantype *jcurPtrB, 
+                                    realtype gammaB, void *cvode_mem)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -1238,40 +1528,57 @@ static int cvSpilsPrecSetupBWrapper(realtype t, N_Vector yB,
   CVSpilsMemB cvspilsB_mem;
   int retval, flag;
 
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsPrecSetupBWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsPrecSetupBWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsPrecSetupBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsPrecSetupBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
-  /* Forward solution from interpolation */
-  flag = IMget(cv_mem, t, ytmp, NULL);
+  /* Get forward solution from interpolation */
+  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsPrecSetupBWrapper", MSGS_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSSPILS",
+                   "cvSpilsPrecSetupBWrapper", MSGS_BAD_TINTERP);
     return(-1);
   } 
 
   /* Call user's adjoint precondB routine */
-  retval = pset_B(t, ytmp, yB, fyB, jokB, jcurPtrB, gammaB,
-                  cvB_mem->cv_user_data, tmp1B, tmp2B, tmp3B);
-
+  retval = cvspilsB_mem->psetB(t, ca_mem->ca_ytmp, yB, fyB, jokB,
+                               jcurPtrB, gammaB, cvB_mem->cv_user_data);
   return(retval);
 }
 
-/*
- * cvSpilsPrecSetupBSWrapper
- *
- * This routine interfaces to the CVSpilsPrecSetupFnBS routine 
- * provided by the user.
- */
-
-static int cvSpilsPrecSetupBSWrapper(realtype t, N_Vector yB, 
-                                     N_Vector fyB, booleantype jokB, 
-                                     booleantype *jcurPtrB, realtype gammaB,
-                                     void *cvode_mem,
-                                     N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+/* cvSpilsPrecSetupBSWrapper interfaces to the CVSpilsPrecSetupFnBS routine 
+   provided by the user */
+static int cvSpilsPrecSetupBSWrapper(realtype t, N_Vector yB, N_Vector fyB, 
+                                     booleantype jokB, booleantype *jcurPtrB, 
+                                     realtype gammaB, void *cvode_mem)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -1279,42 +1586,63 @@ static int cvSpilsPrecSetupBSWrapper(realtype t, N_Vector yB,
   CVSpilsMemB cvspilsB_mem;
   int retval, flag;
 
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsPrecSetupBSWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsPrecSetupBSWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsPrecSetupBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsPrecSetupBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
   /* Forward solution from interpolation */
-  if (IMinterpSensi)
-    flag = IMget(cv_mem, t, ytmp, yStmp);
+  if (ca_mem->ca_IMinterpSensi)
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
   else
-    flag = IMget(cv_mem, t, ytmp, NULL);
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsPrecSetupBSWrapper", MSGS_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSSPILS", "cvSpilsPrecSetupBSWrapper",
+                   MSGS_BAD_TINTERP);
     return(-1);
   } 
 
   /* Call user's adjoint precondB routine */
-  retval = pset_BS(t, ytmp, yStmp, yB, fyB, jokB, jcurPtrB, gammaB,
-                   cvB_mem->cv_user_data, tmp1B, tmp2B, tmp3B);
-
+  retval = cvspilsB_mem->psetBS(t, ca_mem->ca_ytmp, ca_mem->ca_yStmp,
+                                yB, fyB, jokB, jcurPtrB, gammaB,
+                                cvB_mem->cv_user_data);
   return(retval);
 }
 
-/*
- * cvSpilsPrecSolveBWrapper
- *
- * This routine interfaces to the CVSpilsPrecSolveFnB routine 
- * provided by the user.
- */
 
+/* cvSpilsPrecSolveBWrapper interfaces to the CVSpilsPrecSolveFnB routine 
+   provided by the user */
 static int cvSpilsPrecSolveBWrapper(realtype t, N_Vector yB, N_Vector fyB,
                                     N_Vector rB, N_Vector zB,
                                     realtype gammaB, realtype deltaB,
-                                    int lrB, void *cvode_mem, N_Vector tmpB)
+                                    int lrB, void *cvode_mem)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -1322,39 +1650,59 @@ static int cvSpilsPrecSolveBWrapper(realtype t, N_Vector yB, N_Vector fyB,
   CVSpilsMemB cvspilsB_mem;
   int retval, flag;
 
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsPrecSolveBWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsPrecSolveBWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsPrecSolveBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsPrecSolveBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
   /* Forward solution from interpolation */
-  flag = IMget(cv_mem, t, ytmp, NULL);
+  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsPrecSolveBWrapper", MSGS_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSSPILS", "cvSpilsPrecSolveBWrapper",
+                   MSGS_BAD_TINTERP);
     return(-1);
   }
 
   /* Call user's adjoint psolveB routine */
-  retval = psolve_B(t, ytmp, yB, fyB, rB, zB, gammaB, deltaB, 
-                    lrB, cvB_mem->cv_user_data, tmpB);
-
+  retval = cvspilsB_mem->psolveB(t, ca_mem->ca_ytmp, yB, fyB, rB, zB,
+                                 gammaB, deltaB, lrB, cvB_mem->cv_user_data);
   return(retval);
 }
 
-/*
- * cvSpilsPrecSolveBSWrapper
- *
- * This routine interfaces to the CVSpilsPrecSolveFnBS routine 
- * provided by the user.
- */
 
+/* cvSpilsPrecSolveBSWrapper interfaces to the CVSpilsPrecSolveFnBS routine 
+   provided by the user */
 static int cvSpilsPrecSolveBSWrapper(realtype t, N_Vector yB, N_Vector fyB,
                                      N_Vector rB, N_Vector zB,
                                      realtype gammaB, realtype deltaB,
-                                     int lrB, void *cvode_mem, N_Vector tmpB)
+                                     int lrB, void *cvode_mem)
 {
   CVodeMem cv_mem;
   CVadjMem ca_mem;
@@ -1362,38 +1710,179 @@ static int cvSpilsPrecSolveBSWrapper(realtype t, N_Vector yB, N_Vector fyB,
   CVSpilsMemB cvspilsB_mem;
   int retval, flag;
 
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsPrecSolveBSWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsPrecSolveBSWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsPrecSolveBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsPrecSolveBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
   /* Forward solution from interpolation */
-  if (IMinterpSensi)
-    flag = IMget(cv_mem, t, ytmp, yStmp);
+  if (ca_mem->ca_IMinterpSensi)
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
   else
-    flag = IMget(cv_mem, t, ytmp, NULL);
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsPrecSolveBSWrapper", MSGS_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSSPILS", "cvSpilsPrecSolveBSWrapper",
+                   MSGS_BAD_TINTERP);
     return(-1);
   }
 
   /* Call user's adjoint psolveBS routine */
-  retval = psolve_BS(t, ytmp, yStmp, yB, fyB, rB, zB, gammaB, deltaB, 
-                     lrB, cvB_mem->cv_user_data, tmpB);
+  retval = cvspilsB_mem->psolveBS(t, ca_mem->ca_ytmp, ca_mem->ca_yStmp, 
+                                  yB, fyB, rB, zB, gammaB, deltaB, 
+                                  lrB, cvB_mem->cv_user_data);
+  return(retval);
+}
+
+
+/* cvSpilsJacTimesSetupBWrapper interfaces to the CVSpilsJacTimesSetupFnB 
+   routine provided by the user */
+static int cvSpilsJacTimesSetupBWrapper(realtype t, N_Vector yB,
+                                        N_Vector fyB, void *cvode_mem)
+{
+  CVodeMem cv_mem;
+  CVadjMem ca_mem;
+  CVodeBMem cvB_mem;
+  CVSpilsMemB cvspilsB_mem;
+  int retval, flag;
+
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesSetupBWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  cv_mem = (CVodeMem) cvode_mem;
+
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsJacTimesSetupBWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
+  ca_mem = cv_mem->cv_adj_mem;
+
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsJacTimesSetupBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
+  cvB_mem = ca_mem->ca_bckpbCrt;
+
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesSetupBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
+  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+  /* Forward solution from interpolation */
+  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
+  if (flag != CV_SUCCESS) {
+    cvProcessError(cv_mem, -1, "CVSSPILS", "cvSpilsJacTimesVecBWrapper",
+                   MSGS_BAD_TINTERP);
+    return(-1);
+  } 
 
+  /* Call user's adjoint jtsetupB routine */
+  retval = cvspilsB_mem->jtsetupB(t, ca_mem->ca_ytmp, yB,
+                                  fyB, cvB_mem->cv_user_data);
   return(retval);
 }
 
-/*
- * cvSpilsJacTimesVecBWrapper
- *
- * This routine interfaces to the CVSpilsJacTimesVecFnB routine 
- * provided by the user.
- */
 
+/* cvSpilsJacTimesSetupBSWrapper interfaces to the CVSpilsJacTimesSetupFnBS 
+   routine provided by the user */
+static int cvSpilsJacTimesSetupBSWrapper(realtype t, N_Vector yB,
+                                         N_Vector fyB, void *cvode_mem)
+{
+  CVodeMem cv_mem;
+  CVadjMem ca_mem;
+  CVodeBMem cvB_mem;
+  CVSpilsMemB cvspilsB_mem;
+  int retval, flag;
+
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesSetupBSWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
+  cv_mem = (CVodeMem) cvode_mem;
+
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsJacTimesSetupBSWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
+  ca_mem = cv_mem->cv_adj_mem;
+
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsJacTimesSetupBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
+  cvB_mem = ca_mem->ca_bckpbCrt;
+
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesSetupBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
+  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+  /* Forward solution from interpolation */
+  if (ca_mem->ca_IMinterpSensi)
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
+  else
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
+  if (flag != CV_SUCCESS) {
+    cvProcessError(cv_mem, -1, "CVSSPILS", "cvSpilsJacTimesVecBSWrapper",
+                   MSGS_BAD_TINTERP);
+    return(-1);
+  } 
+
+  /* Call user's adjoint jtsetupBS routine */
+  retval = cvspilsB_mem->jtsetupBS(t, ca_mem->ca_ytmp,
+                                   ca_mem->ca_yStmp, yB, fyB,
+                                   cvB_mem->cv_user_data);
+  return(retval);
+}
+
+
+/* cvSpilsJacTimesVecBWrapper interfaces to the CVSpilsJacTimesVecFnB routine 
+   provided by the user */
 static int cvSpilsJacTimesVecBWrapper(N_Vector vB, N_Vector JvB, realtype t, 
                                       N_Vector yB, N_Vector fyB, 
                                       void *cvode_mem, N_Vector tmpB)
@@ -1404,34 +1893,55 @@ static int cvSpilsJacTimesVecBWrapper(N_Vector vB, N_Vector JvB, realtype t,
   CVSpilsMemB cvspilsB_mem;
   int retval, flag;
 
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesVecBWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsJacTimesVecBWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsJacTimesVecBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesVecBWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
   /* Forward solution from interpolation */
-  flag = IMget(cv_mem, t, ytmp, NULL);
+  flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsJacTimesVecBWrapper", MSGS_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSSPILS", "cvSpilsJacTimesVecBWrapper",
+                   MSGS_BAD_TINTERP);
     return(-1);
   } 
 
   /* Call user's adjoint jtimesB routine */
-  retval = jtimes_B(vB, JvB, t, ytmp, yB, fyB, cvB_mem->cv_user_data, tmpB);
-
+  retval = cvspilsB_mem->jtimesB(vB, JvB, t, ca_mem->ca_ytmp, yB,
+                                 fyB, cvB_mem->cv_user_data, tmpB);
   return(retval);
 }
 
-/*
- * cvSpilsJacTimesVecBSWrapper
- *
- * This routine interfaces to the CVSpilsJacTimesVecFnBS routine 
- * provided by the user.
- */
 
+/* cvSpilsJacTimesVecBSWrapper interfaces to the CVSpilsJacTimesVecFnBS 
+   routine provided by the user */
 static int cvSpilsJacTimesVecBSWrapper(N_Vector vB, N_Vector JvB, realtype t, 
                                        N_Vector yB, N_Vector fyB, 
                                        void *cvode_mem, N_Vector tmpB)
@@ -1442,26 +1952,70 @@ static int cvSpilsJacTimesVecBSWrapper(N_Vector vB, N_Vector JvB, realtype t,
   CVSpilsMemB cvspilsB_mem;
   int retval, flag;
 
+  /* Check if cvode_mem exists */
+  if (cvode_mem == NULL) {
+    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesVecBSWrapper", MSGS_CVMEM_NULL);
+    return(CVSPILS_MEM_NULL);
+  }
   cv_mem = (CVodeMem) cvode_mem;
 
+  /* Was ASA initialized? */
+  if (cv_mem->cv_adjMallocDone == SUNFALSE) {
+    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSSPILS",
+                   "cvSpilsJacTimesVecBSWrapper", MSGS_NO_ADJ);
+    return(CVSPILS_NO_ADJ);
+  } 
   ca_mem = cv_mem->cv_adj_mem;
 
+  /* Get current backward problem. */
+  if (ca_mem->ca_bckpbCrt == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILLS",
+                   "cvSpilsJacTimesVecBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvB_mem = ca_mem->ca_bckpbCrt;
 
+  /* Get linear solver's data for this backward problem. */
+  if (cvB_mem->cv_lmem == NULL) {
+    cvProcessError(cv_mem, CVSPILS_LMEMB_NULL, "CVSSPILS",
+                   "cvSpilsJacTimesVecBSWrapper", MSGS_LMEMB_NULL);
+    return(CVSPILS_LMEMB_NULL);
+  }
   cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
 
   /* Forward solution from interpolation */
-  if (IMinterpSensi)
-    flag = IMget(cv_mem, t, ytmp, yStmp);
+  if (ca_mem->ca_IMinterpSensi)
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, ca_mem->ca_yStmp);
   else
-    flag = IMget(cv_mem, t, ytmp, NULL);
+    flag = ca_mem->ca_IMget(cv_mem, t, ca_mem->ca_ytmp, NULL);
   if (flag != CV_SUCCESS) {
-    cvProcessError(cv_mem, -1, "CVSPILS", "cvSpilsJacTimesVecBSWrapper", MSGS_BAD_TINTERP);
+    cvProcessError(cv_mem, -1, "CVSSPILS", "cvSpilsJacTimesVecBSWrapper",
+                   MSGS_BAD_TINTERP);
     return(-1);
   } 
 
   /* Call user's adjoint jtimesBS routine */
-  retval = jtimes_BS(vB, JvB, t, ytmp, yStmp, yB, fyB, cvB_mem->cv_user_data, tmpB);
+  retval = cvspilsB_mem->jtimesBS(vB, JvB, t, ca_mem->ca_ytmp,
+                                  ca_mem->ca_yStmp, yB, fyB,
+                                  cvB_mem->cv_user_data, tmpB);
 
   return(retval);
 }
+
+
+/* cvSpilsFreeB frees memory associated with the CVSSPILS wrapper */
+int cvSpilsFreeB(CVodeBMem cvB_mem)
+{
+  CVSpilsMemB cvspilsB_mem;
+
+  /* Return immediately if cvB_mem or cvB_mem->cv_lmem are NULL */
+  if (cvB_mem == NULL)  return (CVSPILS_SUCCESS);
+  if (cvB_mem->cv_lmem == NULL)  return(CVSPILS_SUCCESS);
+  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
+
+  /* free CVSpilsMemB interface structure */
+  free(cvspilsB_mem);
+  
+  return(CVSPILS_SUCCESS);
+}
diff --git a/src/cvodes/cvodes_spils_impl.h b/src/cvodes/cvodes_spils_impl.h
index 57313f8..fff8d82 100644
--- a/src/cvodes/cvodes_spils_impl.h
+++ b/src/cvodes/cvodes_spils_impl.h
@@ -1,22 +1,24 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * Common implementation header file for the scaled, preconditioned
- * iterative linear solvers
+ * Implementation header file for the scaled, preconditioned
+ * linear solver interface.
  * -----------------------------------------------------------------
  */
 
@@ -30,59 +32,40 @@
 extern "C" {
 #endif
 
-/*
- * =================================================================
- * C V S P I L S    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/* Types of iterative linear solvers */
+/*=================================================================
+  PART I:  Forward Problems
+  =================================================================*/
 
-#define SPILS_SPGMR   1
-#define SPILS_SPBCG   2
-#define SPILS_SPTFQMR 3
-
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : CVSpilsMemRec, CVSpilsMem
- * -----------------------------------------------------------------
- * The type CVSpilsMem is pointer to a CVSpilsMemRec.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types : CVSpilsMemRec, CVSpilsMem
+  -----------------------------------------------------------------
+  The type CVSpilsMem is pointer to a CVSpilsMemRec.
+  -----------------------------------------------------------------*/
 
 typedef struct CVSpilsMemRec {
 
-  int s_type;           /* type of scaled preconditioned iterative LS   */
-
-  int  s_pretype;       /* type of preconditioning                      */
-  int  s_gstype;        /* type of Gram-Schmidt orthogonalization       */
-  realtype s_sqrtN;     /* sqrt(N)                                      */
-  realtype s_eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
-  realtype s_deltar;    /* deltar = delt * tq4                          */
-  realtype s_delta;     /* delta = deltar * sqrtN                       */
-  int  s_maxl;          /* maxl = maximum dimension of the Krylov space */
-
-  long int s_nstlpre;   /* value of nst at the last pset call           */
-  long int s_npe;       /* npe = total number of pset calls             */
-  long int s_nli;       /* nli = total number of linear iterations      */
-  long int s_nps;       /* nps = total number of psolve calls           */
-  long int s_ncfl;      /* ncfl = total number of convergence failures  */
-  long int s_njtimes;   /* njtimes = total number of calls to jtimes    */
-  long int s_nfes;      /* nfeSG = total number of calls to f for     
-			   difference quotient Jacobian-vector products */
-
-  N_Vector s_ytemp;     /* temp vector passed to jtimes and psolve      */
-  N_Vector s_x;         /* temp vector used by CVSpilsSolve             */
-  N_Vector s_ycur;      /* CVODE current y vector in Newton Iteration   */
-  N_Vector s_fcur;      /* fcur = f(tn, ycur)                           */
-
-  void* s_spils_mem;    /* memory used by the generic solver            */
+  realtype sqrtN;     /* sqrt(N)                                      */
+  realtype eplifac;   /* eplifac = user specified or EPLIN_DEFAULT    */
+  realtype deltar;    /* deltar = delt * tq4                          */
+  realtype delta;     /* delta = deltar * sqrtN                       */
+
+  booleantype jbad;   /* heuristic suggestion for pset/jtsetup        */
+  long int nstlpre;   /* value of nst at the last pset call           */
+  long int npe;       /* npe = total number of pset calls             */
+  long int nli;       /* nli = total number of linear iterations      */
+  long int nps;       /* nps = total number of psolve calls           */
+  long int ncfl;      /* ncfl = total number of convergence failures  */
+  long int njtsetup;  /* njtsetup = total number of calls to jtsetup  */
+  long int njtimes;   /* njtimes = total number of calls to jtimes    */
+  long int nfes;      /* nfeSG = total number of calls to f for     
+                         difference quotient Jacobian-vector products */
+
+  SUNLinearSolver LS; /* generic iterative linear solver object       */
+  
+  N_Vector ytemp;     /* temp vector passed to jtimes and psolve      */
+  N_Vector x;         /* temp vector used by CVSpilsSolve             */
+  N_Vector ycur;      /* CVODE current y vector in Newton Iteration   */
+  N_Vector fcur;      /* fcur = f(tn, ycur)                           */
 
   /* Preconditioner computation
    * (a) user-provided:
@@ -90,84 +73,91 @@ typedef struct CVSpilsMemRec {
    *     - pfree == NULL (the user dealocates memory for user_data)
    * (b) internal preconditioner module
    *     - P_data == cvode_mem
-   *     - pfree == set by the prec. module and called in CVodeFree
-   */
-  CVSpilsPrecSetupFn s_pset;
-  CVSpilsPrecSolveFn s_psolve;
-  int (*s_pfree)(CVodeMem cv_mem);
-  void *s_P_data;
+   *     - pfree == set by the prec. module and called in CVodeFree */
+  CVSpilsPrecSetupFn pset;
+  CVSpilsPrecSolveFn psolve;
+  int (*pfree)(CVodeMem cv_mem);
+  void *P_data;
 
   /* Jacobian times vector compuation
    * (a) jtimes function provided by the user:
    *     - j_data == user_data
-   *     - jtimesDQ == FALSE
+   *     - jtimesDQ == SUNFALSE
    * (b) internal jtimes
    *     - j_data == cvode_mem
-   *     - jtimesDQ == TRUE
-   */
-  booleantype s_jtimesDQ;
-  CVSpilsJacTimesVecFn s_jtimes;
-  void *s_j_data;
+   *     - jtimesDQ == SUNTRUE  */
+  booleantype jtimesDQ;
+  CVSpilsJacTimesSetupFn jtsetup;
+  CVSpilsJacTimesVecFn jtimes;
+  void *j_data;
 
-  long int s_last_flag;    /* last error flag returned by any function   */
+  long int last_flag;    /* last error flag returned by any function   */
 
 } *CVSpilsMem;
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-
-/* Atimes and PSolve routines called by generic solver */
-
-int CVSpilsAtimes(void *cv_mem, N_Vector v, N_Vector z);
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
 
-int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z, int lr);
+/* Interface routines called by system SUNLinearSolver */
+int CVSpilsATimes(void *cv_mem, N_Vector v, N_Vector z);
+int CVSpilsPSetup(void *cv_mem);
+int CVSpilsPSolve(void *cv_mem, N_Vector r, N_Vector z,
+                  realtype tol, int lr);
 
 /* Difference quotient approximation for Jac times vector */
-
 int CVSpilsDQJtimes(N_Vector v, N_Vector Jv, realtype t,
                     N_Vector y, N_Vector fy, void *data,
                     N_Vector work);
 
+/* Generic linit/lsetup/lsolve/lfree interface routines for CVode to call */
+int cvSpilsInitialize(CVodeMem cv_mem);
+int cvSpilsSetup(CVodeMem cv_mem, int convfail, N_Vector y, 
+                 N_Vector fy, booleantype *jcurPtr, 
+                 N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); 
+int cvSpilsSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
+                 N_Vector ycur, N_Vector fcur);
+int cvSpilsFree(CVodeMem cv_mem);
+
 /* Auxilliary functions */
 int cvSpilsInitializeCounters(CVSpilsMem cvspils_mem);
 
 
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
+/*=================================================================
+  PART II:  Backward Problems
+  =================================================================*/
 
-/*
- * -----------------------------------------------------------------
- * Types : CVSpilsMemRecB, CVSpilsMemB       
- * -----------------------------------------------------------------
- * CVSpgmrB, CVSpbcgB, and CVSptfqmr attach such a structure to the 
- * lmemB filed of CVodeBMem
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types : CVSpilsMemRecB, CVSpilsMemB       
+  -----------------------------------------------------------------
+  CVSpgmrB, CVSpbcgB, and CVSptfqmr attach such a structure to the 
+  lmemB filed of CVodeBMem
+  -----------------------------------------------------------------*/
 
 typedef struct CVSpilsMemRecB {
 
-  CVSpilsJacTimesVecFnB s_jtimesB;
-  CVSpilsJacTimesVecFnBS s_jtimesBS;
-  CVSpilsPrecSetupFnB s_psetB;
-  CVSpilsPrecSetupFnBS s_psetBS;
-  CVSpilsPrecSolveFnB s_psolveB;
-  CVSpilsPrecSolveFnBS s_psolveBS;
-  void *s_P_dataB;
+  CVSpilsJacTimesSetupFnB jtsetupB;
+  CVSpilsJacTimesSetupFnBS jtsetupBS;
+  CVSpilsJacTimesVecFnB jtimesB;
+  CVSpilsJacTimesVecFnBS jtimesBS;
+  CVSpilsPrecSetupFnB psetB;
+  CVSpilsPrecSetupFnBS psetBS;
+  CVSpilsPrecSolveFnB psolveB;
+  CVSpilsPrecSolveFnBS psolveBS;
+  void *P_dataB;
 
 } *CVSpilsMemB;
 
 
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
+
+int cvSpilsFreeB(CVodeBMem cvb_mem);
+
+/*=================================================================
+  Error Messages
+  =================================================================*/
 
 #define MSGS_CVMEM_NULL  "Integrator memory is NULL."
 #define MSGS_MEM_FAIL    "A memory request failed."
@@ -181,6 +171,7 @@ typedef struct CVSpilsMemRecB {
   
 #define MSGS_PSET_FAILED   "The preconditioner setup routine failed in an unrecoverable manner."
 #define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner."
+#define MSGS_JTSETUP_FAILED "The Jacobian x vector setup routine failed in an unrecoverable manner."
 #define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
 
 #define MSGS_NO_ADJ      "Illegal attempt to call before calling CVodeAdjMalloc."
diff --git a/src/cvodes/cvodes_sptfqmr.c b/src/cvodes/cvodes_sptfqmr.c
deleted file mode 100644
index 90c2169..0000000
--- a/src/cvodes/cvodes_sptfqmr.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4923 $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSPTFQMR linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <cvodes/cvodes_sptfqmr.h>
-#include "cvodes_spils_impl.h"
-#include "cvodes_impl.h"
-
-#include <sundials/sundials_sptfqmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-
-/* CVSPTFQMR linit, lsetup, lsolve, and lfree routines */
-
-static int CVSptfqmrInit(CVodeMem cv_mem);
-
-static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-                          N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-                          N_Vector vtemp2, N_Vector vtemp3);
-
-static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-                          N_Vector ynow, N_Vector fnow);
-
-static int CVSptfqmrFree(CVodeMem cv_mem);
-
-/* CVSPTFQMR lfreeB function */
-
-static int CVSptfqmrFreeB(CVodeBMem cvB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define tq           (cv_mem->cv_tq)
-#define nst          (cv_mem->cv_nst)
-#define tn           (cv_mem->cv_tn)
-#define gamma        (cv_mem->cv_gamma)
-#define gammap       (cv_mem->cv_gammap)
-#define f            (cv_mem->cv_f)
-#define user_data    (cv_mem->cv_user_data)
-#define ewt          (cv_mem->cv_ewt)
-#define errfp        (cv_mem->cv_errfp)
-#define mnewt        (cv_mem->cv_mnewt)
-#define linit        (cv_mem->cv_linit)
-#define lsetup       (cv_mem->cv_lsetup)
-#define lsolve       (cv_mem->cv_lsolve)
-#define lfree        (cv_mem->cv_lfree)
-#define lmem         (cv_mem->cv_lmem)
-#define vec_tmpl     (cv_mem->cv_tempv)
-#define setupNonNull (cv_mem->cv_setupNonNull)
-
-#define sqrtN       (cvspils_mem->s_sqrtN)   
-#define ytemp       (cvspils_mem->s_ytemp)
-#define x           (cvspils_mem->s_x)
-#define ycur        (cvspils_mem->s_ycur)
-#define fcur        (cvspils_mem->s_fcur)
-#define delta       (cvspils_mem->s_delta)
-#define deltar      (cvspils_mem->s_deltar)
-#define npe         (cvspils_mem->s_npe)
-#define nli         (cvspils_mem->s_nli)
-#define nps         (cvspils_mem->s_nps)
-#define ncfl        (cvspils_mem->s_ncfl)
-#define nstlpre     (cvspils_mem->s_nstlpre)
-#define njtimes     (cvspils_mem->s_njtimes)
-#define nfes        (cvspils_mem->s_nfes)
-#define spils_mem   (cvspils_mem->s_spils_mem)
-
-#define jtimesDQ    (cvspils_mem->s_jtimesDQ)
-#define jtimes      (cvspils_mem->s_jtimes)
-#define j_data      (cvspils_mem->s_j_data)
-
-#define last_flag   (cvspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmr
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the Sptfqmr linear solver module. CVSptfqmr first
- * calls the existing lfree routine if this is not NULL. It then sets
- * the cv_linit, cv_lsetup, cv_lsolve, cv_lfree fields in (*cvode_mem)
- * to be CVSptfqmrInit, CVSptfqmrSetup, CVSptfqmrSolve, and CVSptfqmrFree,
- * respectively. It allocates memory for a structure of type
- * CVSpilsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure. It sets setupNonNull in (*cvode_mem),
- * and sets various fields in the CVSpilsMemRec structure.
- * Finally, CVSptfqmr allocates memory for ytemp and x, and calls
- * SptfqmrMalloc to allocate memory for the Sptfqmr solver.
- * -----------------------------------------------------------------
- */
-
-int CVSptfqmr(void *cvode_mem, int pretype, int maxl)
-{
-  CVodeMem cv_mem;
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int mxl;
-
-  /* Return immediately if cvode_mem is NULL */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPTFQMR", "CVSptfqmr", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_NVECTOR);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(cv_mem);
-
-  /* Set four main function fields in cv_mem */
-  linit  = CVSptfqmrInit;
-  lsetup = CVSptfqmrSetup;
-  lsolve = CVSptfqmrSolve;
-  lfree  = CVSptfqmrFree;
-
-  /* Get memory for CVSpilsMemRec */
-  cvspils_mem = NULL;
-  cvspils_mem = (CVSpilsMem) malloc(sizeof(struct CVSpilsMemRec));
-  if (cvspils_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  cvspils_mem->s_type = SPILS_SPTFQMR;
-
-  /* Set Sptfqmr parameters that have been passed in call sequence */
-  cvspils_mem->s_pretype = pretype;
-  mxl = cvspils_mem->s_maxl = (maxl <= 0) ? CVSPILS_MAXL : maxl;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  j_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  cvspils_mem->s_pset   = NULL;
-  cvspils_mem->s_psolve = NULL;
-  cvspils_mem->s_pfree  = NULL;
-  cvspils_mem->s_P_data = cv_mem->cv_user_data;
-
-  /* Set default values for the rest of the Sptfqmr parameters */
-  cvspils_mem->s_eplifac   = CVSPILS_EPLIN;
-
-  cvspils_mem->s_last_flag = CVSPILS_SUCCESS;
-
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  setupNonNull = FALSE;
-
-  /* Check for legal pretype */ 
-  if ((pretype != PREC_NONE) && (pretype != PREC_LEFT) &&
-      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmr", MSGS_BAD_PRETYPE);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Allocate memory for ytemp and x */
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  x = N_VClone(vec_tmpl);
-  if (x == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */
-  sptfqmr_mem = NULL;
-  sptfqmr_mem = SptfqmrMalloc(mxl, vec_tmpl);
-  if (sptfqmr_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(x);
-    free(cvspils_mem); cvspils_mem = NULL;
-    return(CVSPILS_MEM_FAIL);
-  }
-  
-  /* Attach SPTFQMR memory to spils memory structure */
-  spils_mem = (void *) sptfqmr_mem;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = cvspils_mem;
-
-  return(CVSPILS_SUCCESS);
-}
-
-/* Additional readability replacements */
-
-#define pretype (cvspils_mem->s_pretype)
-#define eplifac (cvspils_mem->s_eplifac)
-#define maxl    (cvspils_mem->s_maxl)
-#define psolve  (cvspils_mem->s_psolve)
-#define pset    (cvspils_mem->s_pset)
-#define P_data  (cvspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the Sptfqmr
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrInit(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-
-  /* Initialize counters */
-  cvSpilsInitializeCounters(cvspils_mem);
-
-  /* Check for legal combination pretype - psolve */
-  if ((pretype != PREC_NONE) && (psolve == NULL)) {
-    cvProcessError(cv_mem, -1, "CVSPTFQMR", "CVSptfqmrInit", MSGS_PSOLVE_REQ);
-    last_flag = CVSPILS_ILL_INPUT;
-    return(-1);
-  }
-
-  /* Set setupNonNull = TRUE iff there is preconditioning
-     (pretype != PREC_NONE)  and there is a preconditioning
-     setup phase (pset != NULL) */
-  setupNonNull = (pretype != PREC_NONE) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = CVSpilsDQJtimes;
-    j_data = cv_mem;
-  } else {
-    j_data = user_data;
-  }
-
-  /*  Set maxl in the SPTFQMR memory in case it was changed by the user */
-  sptfqmr_mem->l_max  = maxl;
-
-  last_flag = CVSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the Sptfqmr linear solver.
- * It makes a decision as to whether or not to signal for reevaluation
- * of Jacobian data in the pset routine, based on various state
- * variables, then it calls pset. If we signal for reevaluation,
- * then we reset jcur = *jcurPtr to TRUE, regardless of the pset output.
- * In any case, if jcur == TRUE, we increment npe and save nst in nstlpre.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrSetup(CVodeMem cv_mem, int convfail, N_Vector ypred,
-			  N_Vector fpred, booleantype *jcurPtr, N_Vector vtemp1,
-			  N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  realtype dgamma;
-  int  retval;
-  CVSpilsMem cvspils_mem;
-
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  /* Use nst, gamma/gammap, and convfail to set J eval. flag jok */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlpre + CVSPILS_MSBPRE) ||
-      ((convfail == CV_FAIL_BAD_J) && (dgamma < CVSPILS_DGMAX)) ||
-      (convfail == CV_FAIL_OTHER);
-  *jcurPtr = jbad;
-  jok = !jbad;
-
-  /* Call pset routine and possibly reset jcur */
-  retval = pset(tn, ypred, fpred, jok, jcurPtr, gamma, P_data, 
-                vtemp1, vtemp2, vtemp3);
-  if (retval < 0) {
-    cvProcessError(cv_mem, SPTFQMR_PSET_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPTFQMR_PSET_FAIL_UNREC;
-  }
-  if (retval > 0) {
-    last_flag = SPTFQMR_PSET_FAIL_REC;
-  }
-
-  if (jbad) *jcurPtr = TRUE;
-
-  /* If jcur = TRUE, increment npe and save nst value */
-  if (*jcurPtr) {
-    npe++;
-    nstlpre = nst;
-  }
-
-  last_flag = SPTFQMR_SUCCESS;
-
-  /* Return the same value that pset returned */
-  return(retval);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic solver SptfqmrSolve
- * for the solution of the linear system Ax = b with the SPTFQMR method.
- * The solution x is returned in the vector b.
- *
- * If the WRMS norm of b is small, we return x = b (if this is the first
- * Newton iteration) or x = 0 (if a later Newton iteration).
- *
- * Otherwise, we set the tolerance parameter and initial guess (x = 0),
- * call SptfqmrSolve, and copy the solution x into b. The x-scaling and
- * b-scaling arrays are both equal to weight.
- *
- * The counters nli, nps, and ncfl are incremented, and the return value
- * is set according to the success of SptfqmrSolve. The success flag is
- * returned if SptfqmrSolve converged, or if this is the first Newton
- * iteration and the residual norm was reduced below its initial value.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-			  N_Vector ynow, N_Vector fnow)
-{
-  realtype bnorm, res_norm;
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int nli_inc, nps_inc, retval;
-  
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-
-  /* Test norm(b); if small, return x = 0 or x = b */
-  deltar = eplifac * tq[4]; 
-
-  bnorm = N_VWrmsNorm(b, weight);
-  if (bnorm <= deltar) {
-    if (mnewt > 0) N_VConst(ZERO, b); 
-    return(0);
-  }
-
-  /* Set vectors ycur and fcur for use by the Atimes and Psolve routines */
-  ycur = ynow;
-  fcur = fnow;
-
-  /* Set inputs delta and initial guess x = 0 to SptfqmrSolve */  
-  delta = deltar * sqrtN;
-  N_VConst(ZERO, x);
-  
-  /* Call SptfqmrSolve and copy x to b */
-  retval = SptfqmrSolve(sptfqmr_mem, cv_mem, x, b, pretype, delta,
-                        cv_mem, weight, weight, CVSpilsAtimes, CVSpilsPSolve,
-                        &res_norm, &nli_inc, &nps_inc);
-
-  N_VScale(ONE, x, b);
-  
-  /* Increment counters nli, nps, and ncfl */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPTFQMR_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPTFQMR_SUCCESS:
-    return(0);
-    break;
-  case SPTFQMR_RES_REDUCED:
-    if (mnewt == 0) return(0);
-    else            return(1);
-    break;
-  case SPTFQMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_UNREC:
-    cvProcessError(cv_mem, SPTFQMR_ATIMES_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_UNREC:
-    cvProcessError(cv_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "CVSPTFQMR", "CVSptfqmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);  
-
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : CVSptfqmrFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the Sptfqmr linear solver.
- * -----------------------------------------------------------------
- */
-
-static int CVSptfqmrFree(CVodeMem cv_mem)
-{
-  CVSpilsMem cvspils_mem;
-  SptfqmrMem sptfqmr_mem;
-    
-  cvspils_mem = (CVSpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(x);
-
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-  SptfqmrFree(sptfqmr_mem);
-
-  if (cvspils_mem->s_pfree != NULL) (cvspils_mem->s_pfree)(cv_mem);
-
-  free(cvspils_mem);
-  cv_mem->cv_lmem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-      
-/* Additional readability replacements */
-
-#define pset_B      (cvspilsB_mem->s_psetB)
-#define psolve_B    (cvspilsB_mem->s_psolveB)
-#define jtimes_B    (cvspilsB_mem->s_jtimesB)
-#define P_data_B    (cvspilsB_mem->s_P_dataB)
-
-/*
- * CVSptfqmrB
- *
- * Wrapper for the backward phase
- */
-
-int CVSptfqmrB(void *cvode_mem, int which, int pretypeB, int maxlB)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVSpilsMemB cvspilsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSPILS_MEM_NULL, "CVSPTFQMR", "CVSptfqmrB", MSGS_CVMEM_NULL);
-    return(CVSPILS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSPILS_NO_ADJ, "CVSPTFQMR", "CVSptfqmrB", MSGS_NO_ADJ);
-    return(CVSPILS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSPILS_ILL_INPUT, "CVSPTFQMR", "CVSptfqmrB", MSGS_BAD_WHICH);
-    return(CVSPILS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVSpilsMemRecB */
-  cvspilsB_mem = NULL;
-  cvspilsB_mem = (CVSpilsMemB) malloc(sizeof(struct CVSpilsMemRecB));
-  if (cvspilsB_mem == NULL) {
-    cvProcessError(cv_mem, CVSPILS_MEM_FAIL, "CVSPTFQMR", "CVSptfqmrB", MSGS_MEM_FAIL);
-    return(CVSPILS_MEM_FAIL);
-  }
-
-  pset_B = NULL;
-  psolve_B = NULL;
-  P_data_B = NULL;
-
-  /* initialize Jacobian function */
-  jtimes_B = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvspilsB_mem;
-  cvB_mem->cv_lfree = CVSptfqmrFreeB;
-
-  flag = CVSptfqmr(cvodeB_mem, pretypeB, maxlB);
-
-  if (flag != CVSPILS_SUCCESS) {
-    free(cvspilsB_mem); 
-    cvspilsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * CVSptfqmrFreeB 
- */
-
-
-static int CVSptfqmrFreeB(CVodeBMem cvB_mem)
-{
-  CVSpilsMemB cvspilsB_mem;
-
-  cvspilsB_mem = (CVSpilsMemB) (cvB_mem->cv_lmem);
-
-  free(cvspilsB_mem);
-
-  return(0);
-}
diff --git a/src/cvodes/cvodes_superlumt.c b/src/cvodes/cvodes_superlumt.c
deleted file mode 100644
index 0f73c7f..0000000
--- a/src/cvodes/cvodes_superlumt.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Rev $
- * $Date: 2016-09-19 14:35:51 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the CVSUPERLUMT linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "cvodes_impl.h"
-#include "cvodes_sparse_impl.h"
-#include "cvodes/cvodes_superlumt.h"
-#include "sundials/sundials_superlumt_impl.h"
-#include "sundials/sundials_math.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* CVSUPERLUMT linit, lsetup, lsolve, and lfree routines */
- 
-static int cvSuperLUMTInit(CVodeMem cv_mem);
-
-static int cvSuperLUMTSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-			    N_Vector fpred, booleantype *jcurPtr,
-			    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int cvSuperLUMTSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-			    N_Vector ycur, N_Vector fcur);
-
-static int cvSuperLUMTFree(CVodeMem cv_mem);
-
-/* CVKLU lfreeB function */
-static int cvSuperLUMTFreeB(CVodeBMem cvb_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-
-/*
- * -----------------------------------------------------------------
- * CVSuperLUMT
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the CVODE / SuperLUMT linear solver module.  
- * CVSUPERLUMT first calls the existing lfree routine if this is not NULL.
- * Then it sets the cv_linit, cv_lsetup, cv_lsolve, and
- * cv_lfree fields in (*cv_mem) to be cvSuperLUMTInit, cvSuperLUMTSetup,
- * cvSuperLUMTSolve, and cvSuperLUMTFree, respectively.
- * It allocates memory for a structure of type CVsluMemRec and sets
- * the cv_lmem field in (*cvode_mem) to the address of this structure.
- * It sets setupNonNull in (*cvode_mem) to TRUE.
- * Finally, it allocates memory for SuperLUMT.
- * The return value is CVSLS_SUCCESS = 0, CVSLS_LMEM_FAIL = -1,
- * or CVSLS_ILL_INPUT = -2.
- *
- * NOTE: The SuperLUMT linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, CVSuperLUMT will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int CVSuperLUMT(void *cvode_mem, int num_threads, int n, int nnz)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-  int *perm_c, *perm_r;
-  int nrhs, panel_size, relax;
-  double *bd;
-  SuperMatrix *B;
-
-  /* Return immediately if cv_mem is NULL. */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (cv_mem->cv_tempv->ops->nvgetarraypointer == NULL) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_BAD_NVECTOR);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  if (cv_mem->cv_lfree != NULL) cv_mem->cv_lfree(cv_mem);
-
-  /* Set five main function fields in cv_mem. */
-  cv_mem->cv_linit  = cvSuperLUMTInit;
-  cv_mem->cv_lsetup = cvSuperLUMTSetup;
-  cv_mem->cv_lsolve = cvSuperLUMTSolve;
-  cv_mem->cv_lfree  = cvSuperLUMTFree;
-
-  /* Get memory for CVSlsMemRec. */
-  cvsls_mem = (CVSlsMem) malloc(sizeof(struct CVSlsMemRec));
-  if (cvsls_mem == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Get memory for SLUMT_data. */
-  slumt_data = (SLUMTData)malloc(sizeof(struct SLUMTDataRec));
-  if (slumt_data == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  cv_mem->cv_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  cvsls_mem->s_jaceval = NULL;
-  cvsls_mem->s_jacdata = cv_mem->cv_user_data;
-
-  /* Allocate memory for the sparse Jacobian */
-  cvsls_mem->s_JacMat = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (cvsls_mem->s_JacMat == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Allocate memory for saved sparse Jacobian */
-  cvsls_mem->s_savedJ = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (cvsls_mem->s_savedJ == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    free(cvsls_mem);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* Set up memory for the permutations */
-  perm_r = (int *)malloc(n*sizeof(int));
-  if (perm_r == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		   MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-  perm_c = (int *)malloc(n*sizeof(int));
-  if (perm_c == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSLS", "cvSuperLUMT", 
-		   MSGSP_MEM_FAIL);
-    free(perm_r);
-    return(CVSLS_MEM_FAIL);
-  }
-  slumt_data->perm_r = perm_r;
-  slumt_data->perm_c = perm_c;
-
-  /* Set default parameters for SuperLU */
-  slumt_data->num_threads = num_threads;
-  slumt_data->diag_pivot_thresh = 1.0;
-
-  /* Allocate structures for SuperLU */
-  slumt_data->Gstat = (Gstat_t *)malloc(sizeof(Gstat_t));
-  slumt_data->s_A = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_AC = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_L = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_U = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_A->Store  = NULL;
-  slumt_data->s_AC->Store = NULL;
-  slumt_data->s_L->Store  = NULL;
-  slumt_data->s_U->Store  = NULL;
-  slumt_data->superlumt_options = (superlumt_options_t *)malloc(sizeof(superlumt_options_t));
-
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  StatAlloc(cvsls_mem->s_JacMat->N, num_threads, panel_size, relax, 
-	    slumt_data->Gstat);
-  
-  /* Create RHS matrix */
-  nrhs = 1;
-  bd = NULL;
-  B = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  B->Store = NULL;
-  dCreate_Dense_Matrix(B, n, nrhs, bd, n, 
-		       SLU_DN, SLU_D, SLU_GE);
-  slumt_data->s_B = B;
-
-  /* Set ordering to COLAMD as the cvode default use.
-     Users can set a different value with CVSuperLUMTSetOrdering,
-     and the user-set value is loaded before any call to factorize the
-     matrix in cvSuperLUMTSetup.  */
-  slumt_data->s_ordering = 3;
-
-  /* Attach linear solver memory to the integrator memory */
-  cvsls_mem->s_solver_data = (void *) slumt_data;
-  cv_mem->cv_lmem = cvsls_mem;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(CVSLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * CVSuperLUMT interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the CVSuperLUMT
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int cvSuperLUMTInit(CVodeMem cv_mem)
-{
-  int num_threads, n;
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-
-  cvsls_mem = (CVSlsMem)cv_mem->cv_lmem;
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  cvsls_mem->s_nje = 0;
-  cvsls_mem->s_first_factorize = 1;
-  cvsls_mem->s_nstlj = 0;
-
-  /* ------------------------------------------------------------
-     Allocate storage and initialize statistics variables. 
-     ------------------------------------------------------------*/
-  n = cvsls_mem->s_JacMat->N;
-  num_threads = slumt_data->num_threads;
-
-  StatInit(n, num_threads, slumt_data->Gstat);
-
-  cvsls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the CVSuperLUMT linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     CVSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int cvSuperLUMTSetup(CVodeMem cv_mem, int convfail, N_Vector ypred, 
-			   N_Vector fpred, booleantype *jcurPtr,
-			   N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  booleantype jbad, jok;
-  int retval, info;
-  int nprocs, panel_size, relax, permc_spec, lwork;
-  int *perm_r, *perm_c;
-  long int nst, nstlj;
-  realtype tn, gamma, gammap, dgamma;
-  double diag_pivot_thresh, drop_tol;
-  fact_t fact;
-  trans_t trans;
-  yes_no_t refact, usepr;
-  CVSlsMem cvsls_mem;
-  CVSlsSparseJacFn jaceval;
-  SuperMatrix *A, *AC, *L, *U;
-  Gstat_t *Gstat;
-  superlumt_options_t *superlumt_options;
-  SLUMTData slumt_data;
-  SlsMat JacMat, savedJ;
-  void *jacdata;
-  void *work;
-  
-  cvsls_mem = (CVSlsMem) (cv_mem->cv_lmem);
-  tn = cv_mem->cv_tn; 
-  gamma = cv_mem->cv_gamma;
-  gammap = cv_mem->cv_gammap;
-  nst = cv_mem->cv_nst;
-
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  jaceval = cvsls_mem->s_jaceval;
-  jacdata = cvsls_mem->s_jacdata;
-  JacMat = cvsls_mem->s_JacMat;
-  savedJ = cvsls_mem->s_savedJ;
-  nstlj = cvsls_mem->s_nstlj;
-
-  superlumt_options = slumt_data->superlumt_options;
-  A = slumt_data->s_A;
-  AC = slumt_data->s_AC;
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  Gstat = slumt_data->Gstat;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  nprocs = slumt_data->num_threads;
-  diag_pivot_thresh = slumt_data->diag_pivot_thresh;
-
-  /* Set option values for SuperLU_MT */
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  fact = EQUILIBRATE;
-  trans = NOTRANS;
-  usepr = NO;
-  drop_tol = 0.0;
-  lwork = 0;
-  work = NULL;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    cvProcessError(cv_mem, CVSLS_JAC_NOSET, "CVSLS", "cvSuperLUMTSetup", 
-		    MSGSP_JAC_NOSET);
-    free(cvsls_mem); cvsls_mem = NULL;
-    return(CVSLS_JAC_NOSET);
-  }
-
-  /* Determine whether Jacobian needs to be recalculated */
-  dgamma = SUNRabs((gamma/gammap) - ONE);
-  jbad = (nst == 0) || (nst > nstlj + CVS_MSBJ) ||
-         ((convfail == CV_FAIL_BAD_J) && (dgamma < CVS_DGMAX)) ||
-         (convfail == CV_FAIL_OTHER);
-  jok = !jbad;
-  
-  if (jok) {
-    /* If jok = TRUE, use saved copy of J */
-    *jcurPtr = FALSE;
-    SparseCopyMat(savedJ, JacMat);
-  } else {
-    /* If jok = FALSE, call jac routine for new J value */
-    cvsls_mem->s_nje++;
-    cvsls_mem->s_nstlj = nst;
-    *jcurPtr = TRUE;
-    SparseSetMatToZero(JacMat);
-    retval = jaceval(tn, ypred, fpred, JacMat, jacdata, vtemp1, vtemp2, vtemp3);
-    if (retval < 0) {
-      cvProcessError(cv_mem, CVSLS_JACFUNC_UNRECVR, "CVSLS", "cvSuperLUMTSetup", MSGSP_JACFUNC_FAILED);
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_UNRECVR;
-      return(-1);
-    }
-    if (retval > 0) {
-      cvsls_mem->s_last_flag = CVSLS_JACFUNC_RECVR;
-      return(1);
-    }
-
-    SparseCopyMat(JacMat, savedJ);
-  }
-
-  /* Scale and add I to get M = I - gamma*J */
-  SparseScaleMat(-gamma, JacMat);
-  SparseAddIdentityMat(JacMat);
-
-  if (A->Store) {
-    SUPERLU_FREE(A->Store);
-  }
-  dCreate_CompCol_Matrix(A, JacMat->M, JacMat->N, JacMat->NNZ, 
-			 JacMat->data, JacMat->indexvals, JacMat->indexptrs, 
-			 SLU_NC, SLU_D, SLU_GE);
-
-  if (cvsls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get column permutation vector perm_c[], according to permc_spec:
-       permc_spec = 3: approximate minimum degree for unsymmetric matrices
-       ------------------------------------------------------------*/ 
-    permc_spec = slumt_data->s_ordering;
-    get_perm_c(permc_spec, A, perm_c);
-
-    refact= NO;
-    cvsls_mem->s_first_factorize = 0;
-  }
-  else {
-    /* ------------------------------------------------------------
-       Re-initialize statistics variables 
-       ------------------------------------------------------------*/
-    StatInit(JacMat->N, nprocs, Gstat);
-    Destroy_CompCol_Permuted(AC);
-    refact= YES;
-  }
-
-  /* ------------------------------------------------------------
-     Initialize the option structure superlumt_options using the
-     user-input parameters;  Subsequent calls will re-initialize
-     options.
-     Apply perm_c to the columns of original A to form AC.
-     ------------------------------------------------------------*/
-  pdgstrf_init(nprocs, fact, trans, refact, panel_size, relax,
-	       diag_pivot_thresh, usepr, drop_tol, perm_c, perm_r,
-	       work, lwork, A, AC, superlumt_options, Gstat);
-  /* ------------------------------------------------------------
-     Compute the LU factorization of A.
-     The following routine will create nprocs threads.
-     ------------------------------------------------------------*/
-  pdgstrf(superlumt_options, AC, perm_r, L, U, Gstat, &info);
-    
-  if (info != 0) {
-    cvsls_mem->s_last_flag = info;
-    return(+1);
-  }
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the CVSuperLUMT linear
-  solver module.  It calls the SuperLU_MT solve routine,
-  then returns CVSLS_SUCCESS = 0.
-*/
-
-static int cvSuperLUMTSolve(CVodeMem cv_mem, N_Vector b, N_Vector weight,
-			    N_Vector ycur, N_Vector fcur)
-{
-  int info, trans, lmm;
-  int *perm_r, *perm_c;
-  realtype gamrat;
-  CVSlsMem cvsls_mem;
-  SuperMatrix *L, *U, *B;
-  Gstat_t *Gstat;
-  DNformat *Bstore;
-  SLUMTData slumt_data;
-  realtype *bd;
-  
-  gamrat = cv_mem->cv_gamrat;
-  lmm = cv_mem->cv_lmm;
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  Gstat = slumt_data->Gstat;
-  B = slumt_data->s_B;
-   
-  bd = N_VGetArrayPointer(b);
-  Bstore = (DNformat *) (B->Store);
-  Bstore->nzval = bd;
-
-  /* Call SuperLUMT to solve the linear system using L and U */
-  trans = NOTRANS;
-  dgstrs(trans, L, U, perm_r, perm_c, B, Gstat, &info);
-
-  /* Scale the correction to account for change in gamma. */
-  if ((lmm == CV_BDF) && (gamrat != ONE)) {
-    N_VScale(TWO/(ONE + gamrat), b, b);
-  }
-
-  Bstore->nzval = NULL;
-
-  cvsls_mem->s_last_flag = CVSLS_SUCCESS;
-  return(CVSLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the CVSuperLUMT linear solver.
-*/
-
-static int cvSuperLUMTFree(CVodeMem cv_mem)
-{
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-  
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  pxgstrf_finalize(slumt_data->superlumt_options, slumt_data->s_AC);
-
-  free(slumt_data->perm_r);
-  free(slumt_data->perm_c);
-  free(slumt_data->superlumt_options);
-  Destroy_SuperNode_SCP( (slumt_data->s_L) );
-  Destroy_CompCol_NCP( (slumt_data->s_U) );
-  StatFree( (slumt_data->Gstat) );
-  free(slumt_data->Gstat);
-  
-  Destroy_SuperMatrix_Store(slumt_data->s_B);
-  SUPERLU_FREE(slumt_data->s_A->Store);
-  if (cvsls_mem->s_JacMat) {
-    SparseDestroyMat(cvsls_mem->s_JacMat);
-    cvsls_mem->s_JacMat = NULL;
-  }
-  if (cvsls_mem->s_savedJ) {
-    SparseDestroyMat(cvsls_mem->s_savedJ);
-    cvsls_mem->s_savedJ = NULL;
-  }
-
-  free(slumt_data->s_B);
-  free(slumt_data->s_A);
-  free(slumt_data->s_AC);
-  free(slumt_data->s_L);
-  free(slumt_data->s_U);
-
-  free(slumt_data); 
-  slumt_data = NULL;
-  free(cv_mem->cv_lmem); 
-
-  return(0);
-}
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * CVSuperLUMTSetOrdering sets the ordering used by SuperLUMT for reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int CVSuperLUMTSetOrdering(void *cv_mem_v, int ordering_choice)
-{
-  CVodeMem cv_mem;
-  CVSlsMem cvsls_mem;
-  SLUMTData slumt_data;
-
- /* Return immediately if cv_mem is NULL */
-  if (cv_mem_v == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSLS", "CVSuperLUMTSetOrdering",
-		    MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cv_mem_v;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) && (ordering_choice != 3) ) {
-    cvProcessError(NULL, CVSLS_ILL_INPUT, "CVSLS", "CVSuperLUMTSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  cvsls_mem = (CVSlsMem) cv_mem->cv_lmem;
-  slumt_data = (SLUMTData) cvsls_mem->s_solver_data;
-
-  slumt_data->s_ordering = ordering_choice;
-
-  return(CVSLS_SUCCESS);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * CVSuperLUMTB is a wrapper around CVSuperLUMT. It attaches the CVSuperLUMT 
- * linear solver to the backward problem memory block.
- */
-
-int CVSuperLUMTB(void *cvode_mem, int which, int num_threads, 
-		 int n, int nnz)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  CVSlsMemB cvslsB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSSuperLUMT", "CVSuperLUMTB", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSLS_NO_ADJ, "CVSSuperLUMT", "CVSuperLUMTB", MSGSP_NO_ADJ);
-    return(CVSLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSSuperLUMT", "CVSuperLUMTB", MSGSP_BAD_WHICH);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  /* Get memory for CVSlsMemRecB */
-  cvslsB_mem = (CVSlsMemB) malloc(sizeof(struct CVSlsMemRecB));
-  if (cvslsB_mem == NULL) {
-    cvProcessError(cv_mem, CVSLS_MEM_FAIL, "CVSSuperLUMT", "CVSuperLUMTB", MSGSP_MEM_FAIL);
-    return(CVSLS_MEM_FAIL);
-  }
-
-  /* initialize Jacobian function */
-  cvslsB_mem->s_djacB = NULL;
-
-  /* attach lmemB and lfreeB */
-  cvB_mem->cv_lmem = cvslsB_mem;
-  cvB_mem->cv_lfree = cvSuperLUMTFreeB;
-
-  flag = CVSuperLUMT(cvodeB_mem, num_threads, n, nnz);
-
-  if (flag != CVSLS_SUCCESS) {
-    free(cvslsB_mem);
-    cvslsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * CVSuperLUMTSetOrderingB is a wrapper around CVSuperLUMTSetOrdering. 
- * CVSuperLUMTSetOrderingB pulls off the memory block associated with the
- * which parameter and sets the ordering for the solver associated with that block.
- */
-
-int CVSuperLUMTSetOrderingB(void *cvode_mem, int which, int ordering_choice)
-{
-  CVodeMem cv_mem;
-  CVadjMem ca_mem;
-  CVodeBMem cvB_mem;
-  void *cvodeB_mem;
-  int flag;
-
-  /* Check if cvode_mem exists */
-  if (cvode_mem == NULL) {
-    cvProcessError(NULL, CVSLS_MEM_NULL, "CVSSuperLUMT", "CVSuperLUMTSetOrderingB", MSGSP_CVMEM_NULL);
-    return(CVSLS_MEM_NULL);
-  }
-  cv_mem = (CVodeMem) cvode_mem;
-
-  /* Was ASA initialized? */
-  if (cv_mem->cv_adjMallocDone == FALSE) {
-    cvProcessError(cv_mem, CVSLS_NO_ADJ, "CVSSuperLUMT", "CVSuperLUMTSetOrderingB", MSGSP_NO_ADJ);
-    return(CVSLS_NO_ADJ);
-  } 
-  ca_mem = cv_mem->cv_adj_mem;
-
-  /* Check which */
-  if ( which >= ca_mem->ca_nbckpbs ) {
-    cvProcessError(cv_mem, CVSLS_ILL_INPUT, "CVSSuperLUMT", "CVSuperLUMTSetOrderingB", MSGSP_BAD_WHICH);
-    return(CVSLS_ILL_INPUT);
-  }
-
-  /* Find the CVodeBMem entry in the linked list corresponding to which */
-  cvB_mem = ca_mem->cvB_mem;
-  while (cvB_mem != NULL) {
-    if ( which == cvB_mem->cv_index ) break;
-    cvB_mem = cvB_mem->cv_next;
-  }
-
-  cvodeB_mem = (void *) (cvB_mem->cv_mem);
-
-  flag = CVSuperLUMTSetOrdering(cvodeB_mem, ordering_choice);
-
-  return(flag);
-}
-
-/*
- * cvSuperLUMTFreeB frees the memory associated with the CVSSuperLUMT linear
- * solver for backward integration.
- */
-
-static int cvSuperLUMTFreeB(CVodeBMem cvB_mem)
-{
-  CVSlsMemB cvslsB_mem;
-
-  cvslsB_mem = (CVSlsMemB) (cvB_mem->cv_lmem);
-
-  free(cvslsB_mem);
-
-  return(0);
-}
-
diff --git a/src/ida/CMakeLists.txt b/src/ida/CMakeLists.txt
index 7aa8c84..f169012 100644
--- a/src/ida/CMakeLists.txt
+++ b/src/ida/CMakeLists.txt
@@ -1,18 +1,20 @@
 # ---------------------------------------------------------------
-# $Revision: 4961 $
-# $Date: 2016-09-26 07:58:48 -0700 (Mon, 26 Sep 2016) $
+# Programmer:  Daniel R. Reynolds @ SMU
+#              Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
-# ---------------------------------------------------------------
-# LLNS Copyright Start
-# Copyright (c) 2014, Lawrence Livermore National Security
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
 # This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
-# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
-# Produced at the Lawrence Livermore National Laboratory.
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
-# LLNS Copyright End
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the IDA library
 
@@ -21,26 +23,47 @@ INSTALL(CODE "MESSAGE(\"\nInstall IDA\n\")")
 # Add variable ida_SOURCES with the sources for the IDA library
 SET(ida_SOURCES
   ida.c
-  ida_io.c
-  ida_ic.c
+  ida_bbdpre.c
   ida_direct.c
-  ida_band.c
-  ida_dense.c
-  ida_sparse.c
+  ida_ic.c
+  ida_io.c
   ida_spils.c
-  ida_spbcgs.c
-  ida_spgmr.c
-  ida_sptfqmr.c
-  ida_bbdpre.c
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND ida_SOURCES ida_klu.c)
-ENDIF()
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the IDA library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_band.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_dense.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_direct.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_version.c
+  ${sundials_SOURCE_DIR}/src/nvec_ser/nvector_serial.c
+  )
 
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND ida_SOURCES ida_superlumt.c)
-ENDIF()
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the IDA library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/sunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/sunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/sunmatrix_sparse.c
+  )
+
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the IDA library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/sunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/sunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/sunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/sunlinsol_pcg.c
+  )
 
 # IF(PETSC_FOUND)
 #    # use MPI_MPICC as the compiler
@@ -48,62 +71,17 @@ ENDIF()
 #    LIST(APPEND ida_SOURCES ida_petsc.c)
 # ENDIF()
 
-# Add variable shared_SOURCES with the common SUNDIALS sources which will
-# also be included in the IDA library
-SET(shared_SOURCES
-  sundials_nvector.c
-  sundials_math.c
-  sundials_direct.c
-  sundials_band.c
-  sundials_dense.c
-  sundials_iterative.c
-  sundials_sparse.c
-  sundials_spbcgs.c
-  sundials_spgmr.c
-  sundials_sptfqmr.c
-  )
-
-# Add prefix with complete path to the common SUNDIALS sources
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
-
 # Add variable ida_HEADERS with the exported IDA header files
 SET(ida_HEADERS
-  ida_band.h
+  ida.h
   ida_bbdpre.h
-  ida_dense.h
   ida_direct.h
-  ida.h
-  ida_spbcgs.h
-  ida_spgmr.h
   ida_spils.h
-  ida_sptfqmr.h
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND ida_HEADERS ida_klu.h ida_sparse.h)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND ida_HEADERS ida_superlumt.h ida_sparse.h)
-ENDIF()
-
-# IF(PETSC_FOUND)
-#     LIST(APPEND ida_HEADERS ida_petsc.h)
-# ENDIF()
-
 # Add prefix with complete path to the IDA header files
 ADD_PREFIX(${sundials_SOURCE_DIR}/include/ida/ ida_HEADERS)
 
-# If Blas/Lapack support was enabled, set-up additional file lists
-IF(LAPACK_FOUND)
-  SET(ida_BL_SOURCES ida_lapack.c)
-  SET(ida_BL_HEADERS ida_lapack.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/ida/ ida_BL_HEADERS)
-ELSE(LAPACK_FOUND)
-  SET(ida_BL_SOURCES "")
-  SET(ida_BL_HEADERS "")
-ENDIF(LAPACK_FOUND)
-
 # Add source directories to include directories for access to
 # implementation only header files.
 INCLUDE_DIRECTORIES(.)
@@ -117,7 +95,7 @@ IF(BUILD_STATIC_LIBS)
 
   # Add the build target for the static IDA library
   ADD_LIBRARY(sundials_ida_static STATIC 
-    ${ida_SOURCES}  ${ida_BL_SOURCES}  ${shared_SOURCES})
+    ${ida_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_ida_static
@@ -133,7 +111,11 @@ IF(BUILD_SHARED_LIBS)
 
   # Add the build target for the IDA library
   ADD_LIBRARY(sundials_ida_shared SHARED
-    ${ida_SOURCES}  ${ida_BL_SOURCES} ${shared_SOURCES})
+    ${ida_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_ida_shared m)
+  ENDIF()
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_ida_shared
@@ -149,7 +131,7 @@ IF(BUILD_SHARED_LIBS)
 ENDIF(BUILD_SHARED_LIBS)
 
 # Install the IDA header files
-INSTALL(FILES ${ida_HEADERS} ${ida_BL_HEADERS} DESTINATION include/ida)
+INSTALL(FILES ${ida_HEADERS} DESTINATION include/ida)
 
 # Install the IDA implementation header file
 INSTALL(FILES ida_impl.h DESTINATION include/ida)
diff --git a/src/ida/README b/src/ida/README
index f11af32..55415f5 100644
--- a/src/ida/README
+++ b/src/ida/README
@@ -1,5 +1,5 @@
                                IDA
-                    Release 2.9.0, September 2016
+                    Release 3.1.0, November 2017
                  Alan C. Hindmarsh and Radu Serban 
             Center for Applied Scientific Computing, LLNL
 
@@ -84,6 +84,8 @@ C. References
 D. Releases
 -----------
 
+v. 3.1.0   - Nov. 2017
+v. 3.0.0   - Sep. 2017
 v. 2.9.0   - Sep. 2016
 v. 2.8.2   - Aug. 2015
 v. 2.8.1   - Mar. 2015
diff --git a/src/ida/fcmix/CMakeLists.txt b/src/ida/fcmix/CMakeLists.txt
index 1a4944b..d995ccd 100644
--- a/src/ida/fcmix/CMakeLists.txt
+++ b/src/ida/fcmix/CMakeLists.txt
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
 # CMakeLists.txt file for the FIDA library
 
 # Add variable fida_SOURCES with the sources for the FIDA library
@@ -10,31 +27,54 @@ SET(fida_SOURCES
   fidajtimes.c
   fidapreco.c
   fidaroot.c
+  fidasparse.c
+  )
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the ARKODE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/nvec_ser/fnvector_serial.c
+  )
+
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the ARKODE library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/fsunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/fsunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/fsunmatrix_sparse.c
+  )
+
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the ARKODE library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/fsunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/fsunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/fsunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/fsunlinsol_pcg.c
   )
 
-IF(LAPACK_FOUND)
-  SET(fida_BL_SOURCES fidalapack.c fidalapdense.c fidalapband.c)
-ELSE(LAPACK_FOUND)
-  SET(fida_BL_SOURCES "")
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND OR SUPERLUMT_FOUND)
-  SET(fida_SPARSE_SOURCES fidasparse.c)
-ELSE(SPARSE_FOUND)
-  SET(fida_SPARSE_SOURCES "")
-ENDIF(KLU_FOUND OR SUPERLUMT_FOUND)
- 
 IF(KLU_FOUND)
-  SET(fida_KLU_SOURCES fidaklu.c)
-ELSE(KLU_FOUND)
-  SET(fida_KLU_SOURCES "")
-ENDIF(KLU_FOUND)
- 
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_klu/fsunlinsol_klu.c
+    )
+ENDIF()
+
 IF(SUPERLUMT_FOUND)
-  SET(fida_SUPERLUMT_SOURCES fidasuperlumt.c)
-ELSE(SUPERLUMT_FOUND)
-  SET(fida_SUPERLUMT_SOURCES "")
-ENDIF(SUPERLUMT_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_superlumt/fsunlinsol_superlumt.c
+    )
+ENDIF()
+
+IF(LAPACK_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackband/fsunlinsol_lapackband.c
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c
+    )
+ENDIF()
+
 
 # Add source directories to include directories for access to
 # implementation only header files (both for fida and ida)
@@ -49,7 +89,8 @@ ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
 # coming from inexistent user-provided functions)
 
 # Add the build target for the FIDA library
-ADD_LIBRARY(sundials_fida_static STATIC ${fida_SOURCES} ${fida_BL_SOURCES} ${fida_SPARSE_SOURCES} ${fida_KLU_SOURCES} ${fida_SUPERLUMT_SOURCES})
+ADD_LIBRARY(sundials_fida_static STATIC
+  ${fida_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
 # Set the library name and make sure it is not deleted
 SET_TARGET_PROPERTIES(sundials_fida_static
diff --git a/src/ida/fcmix/fida.c b/src/ida/fcmix/fida.c
index e504d19..5e7522b 100644
--- a/src/ida/fcmix/fida.c
+++ b/src/ida/fcmix/fida.c
@@ -1,41 +1,34 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4825 $
- * $Date: 2016-07-26 15:56:58 -0700 (Tue, 26 Jul 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Aaron Collier and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
  * This is the implementation file for the Fortran interface to
  * the IDA package. See fida.h for usage.
  * NOTE: Some routines are necessarily stored elsewhere to avoid
  * linking problems.
- * -----------------------------------------------------------------
- */
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-
 #include "fida.h"            /* function names, prototypes, global variables   */
 #include "ida_impl.h"        /* definition of IDAMem type                      */
-
-#include <ida/ida_band.h>    /* prototypes for IDABAND interface routines      */
-#include <ida/ida_dense.h>   /* prototypes for IDADENSE interface routines     */
-#include <ida/ida_klu.h>     /* prototypes for IDAKLU interface routines       */
-#include <ida/ida_superlumt.h> /* prototypes for IDASUPERLUMT interface routines */
-#include <ida/ida_sptfqmr.h> /* prototypes for IDASPTFQMR interface routines   */
-#include <ida/ida_spbcgs.h>  /* prototypes for IDASPBCG interface routines     */
-#include <ida/ida_spgmr.h>   /* prototypes for IDASPGMR interface routines     */
+#include <ida/ida_direct.h>  /* prototypes for IDADLS interface routines       */
+#include <ida/ida_spils.h>   /* prototypes for IDASPILS interface routines     */
 
 /*************************************************/
 
@@ -79,8 +72,7 @@ extern "C" {
 void FIDA_MALLOC(realtype *t0, realtype *yy0, realtype *yp0,
                  int *iatol, realtype *rtol, realtype *atol,
                  long int *iout, realtype *rout, 
-                 long int *ipar, realtype *rpar,
-                 int *ier)
+                 long int *ipar, realtype *rpar, int *ier)
 {
   N_Vector Vatol;
   FIDAUserData IDA_userdata;
@@ -91,7 +83,7 @@ void FIDA_MALLOC(realtype *t0, realtype *yy0, realtype *yp0,
   if ((F2C_IDA_vec->ops->nvgetarraypointer == NULL) ||
       (F2C_IDA_vec->ops->nvsetarraypointer == NULL)) {
     *ier = -1;
-    printf("A required vector operation is not implemented.\n\n");
+    fprintf(stderr, "A required vector operation is not implemented.\n\n");
     return;
   }
 
@@ -256,7 +248,7 @@ void FIDA_SETIIN(char key_name[], long int *ival, int *ier)
   if (!strncmp(key_name,"MAX_ORD",7))
     *ier = IDASetMaxOrd(IDA_idamem, (int) *ival);
   else if (!strncmp(key_name,"MAX_NSTEPS",10))
-    *ier = IDASetMaxNumSteps(IDA_idamem, (int) *ival);
+    *ier = IDASetMaxNumSteps(IDA_idamem, (long int) *ival);
   else if (!strncmp(key_name,"MAX_ERRFAIL",11))
     *ier = IDASetMaxErrTestFails(IDA_idamem, (int) *ival);
   else if (!strncmp(key_name,"MAX_NITERS",10))
@@ -264,7 +256,7 @@ void FIDA_SETIIN(char key_name[], long int *ival, int *ier)
   else if (!strncmp(key_name,"MAX_CONVFAIL",12))
     *ier = IDASetMaxConvFails(IDA_idamem, (int) *ival);
   else if (!strncmp(key_name,"SUPPRESS_ALG",12))
-    *ier = IDASetSuppressAlg(IDA_idamem, (int) *ival);
+    *ier = IDASetSuppressAlg(IDA_idamem, (booleantype) *ival);
   else if (!strncmp(key_name,"MAX_NSTEPS_IC",13))
     *ier = IDASetMaxNumStepsIC(IDA_idamem, (int) *ival);
   else if (!strncmp(key_name,"MAX_NITERS_IC",13)) 
@@ -272,10 +264,10 @@ void FIDA_SETIIN(char key_name[], long int *ival, int *ier)
   else if (!strncmp(key_name,"MAX_NJE_IC",10))
     *ier = IDASetMaxNumJacsIC(IDA_idamem, (int) *ival);
   else if (!strncmp(key_name,"LS_OFF_IC",9))
-    *ier = IDASetLineSearchOffIC(IDA_idamem, (int) *ival);
+    *ier = IDASetLineSearchOffIC(IDA_idamem, (booleantype) *ival);
   else {
     *ier = -99;
-    printf("FIDASETIIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FIDASETIIN: Unrecognized key.\n\n");
   }
 
 }
@@ -299,7 +291,7 @@ void FIDA_SETRIN(char key_name[], realtype *rval, int *ier)
     *ier = IDASetStepToleranceIC(IDA_idamem, *rval);
   else {
     *ier = -99;
-    printf("FIDASETRIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FIDASETRIN: Unrecognized key.\n\n");
   }
 
 }
@@ -334,7 +326,7 @@ void FIDA_SETVIN(char key_name[], realtype *vval, int *ier)
     N_VDestroy(Vec);
   } else {
     *ier = -99;
-    printf("FIDASETVIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FIDASETVIN: Unrecognized key.\n\n");
   }
 
 }
@@ -375,204 +367,55 @@ void FIDA_CALCIC(int *icopt, realtype *tout1, int *ier)
 
 /*************************************************/
 
-void FIDA_SPTFQMR(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier)
-{
-
-  *ier = 0;
-
-  *ier = IDASptfqmr(IDA_idamem, *maxl);
-  if (*ier != IDASPILS_SUCCESS) return;
-
-  if (*eplifac != ZERO) {
-    *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*dqincfac != ZERO) {
-    *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac);
-    if (*ier != IDASPILS_SUCCESS) return;
+/* Fortran interface to C routine IDADlsSetLinearSolver; see 
+   fida.h for further details */
+void FIDA_DLSINIT(int *ier) {
+  if ( (IDA_idamem == NULL) || (F2C_IDA_linsol == NULL) || 
+       (F2C_IDA_matrix == NULL) ) {
+    *ier = -1;
+    return;
   }
-
-  IDA_ls = IDA_LS_SPTFQMR;
-
+  *ier = IDADlsSetLinearSolver(IDA_idamem, F2C_IDA_linsol, 
+                               F2C_IDA_matrix);
+  IDA_ls = IDA_LS_DIRECT;
   return;
 }
 
-/*************************************************/
-
-void FIDA_SPBCG(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier)
-{
-
-  *ier = 0;
-
-  *ier = IDASpbcg(IDA_idamem, *maxl);
-  if (*ier != IDASPILS_SUCCESS) return;
-
-  if (*eplifac != ZERO) {
-    *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*dqincfac != ZERO) {
-    *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  IDA_ls = IDA_LS_SPBCG;
-
-  return;
-}
 
 /*************************************************/
 
-void FIDA_SPGMR(int *maxl, int *gstype, int *maxrs,
-		realtype *eplifac, realtype *dqincfac, int *ier)
-{
-
-  *ier = 0;
-
-  *ier = IDASpgmr(IDA_idamem, *maxl);
-  if (*ier != IDASPILS_SUCCESS) return;
-
-  if (*gstype != 0) {
-    *ier = IDASpilsSetGSType(IDA_idamem, *gstype);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*maxrs != 0) {
-    *ier = IDASpilsSetMaxRestarts(IDA_idamem, *maxrs);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*eplifac != ZERO) {
-    *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*dqincfac != ZERO) {
-    *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac);
-    if (*ier != IDASPILS_SUCCESS) return;
+/* Fortran interface to C routine IDASpilsSetLinearSolver; see 
+   fida.h for further details */
+void FIDA_SPILSINIT(int *ier) {
+  if ( (IDA_idamem == NULL) || (F2C_IDA_linsol == NULL) ) {
+    *ier = -1;
+    return;
   }
-
-  IDA_ls = IDA_LS_SPGMR;
-
-  return;
-}
-
-/*************************************************/
-
-void FIDA_DENSE(long int *neq, int *ier)
-{
-
-  *ier = 0;
-
-  *ier = IDADense(IDA_idamem, *neq);
-
-  IDA_ls = IDA_LS_DENSE;
-
-  return;
-}
-
-/*************************************************/
-
-void FIDA_BAND(long int *neq, long int *mupper, long int *mlower, int *ier)
-{
-
-  *ier = 0;
-
-  *ier = IDABand(IDA_idamem, *neq, *mupper, *mlower);
-
-  IDA_ls = IDA_LS_BAND;
-
+  *ier = IDASpilsSetLinearSolver(IDA_idamem, F2C_IDA_linsol);
+  IDA_ls = IDA_LS_ITERATIVE;
   return;
 }
 
 /*************************************************/
 
-void FIDA_SPTFQMRREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier)
-{
-
-  *ier = 0;
-
-  if (*maxl > 0) {
-    *ier = IDASpilsSetMaxl(IDA_idamem, *maxl);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*eplifac != ZERO) {
+/* Fortran interfaces to C "set" routines for the IDASpils solver; 
+   see fida.h for further details */
+void FIDA_SPILSSETEPSLIN(realtype *eplifac, int *ier) {
+  if (IDA_ls == IDA_LS_ITERATIVE)
     *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*dqincfac != ZERO) {
-    *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  IDA_ls = IDA_LS_SPTFQMR;
-
+  else
+    *ier = 1;
   return;
 }
 
-/*************************************************/
-
-void FIDA_SPBCGREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier)
-{
-
-  *ier = 0;
-
-  if (*maxl > 0) {
-    *ier = IDASpilsSetMaxl(IDA_idamem, *maxl);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*eplifac != ZERO) {
-    *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*dqincfac != ZERO) {
+void FIDA_SPILSSETINCREMENTFACTOR(realtype *dqincfac, int *ier) {
+  if (IDA_ls == IDA_LS_ITERATIVE)
     *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  IDA_ls = IDA_LS_SPBCG;
-
+  else
+    *ier = 1;
   return;
 }
 
-/*************************************************/
-
-void FIDA_SPGMRREINIT(int *gstype, int *maxrs, realtype *eplifac,
-		      realtype *dqincfac, int *ier)
-{
-
-  *ier = 0;
-
-  if (*gstype != 0) {
-    *ier = IDASpilsSetGSType(IDA_idamem, *gstype);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*maxrs != 0) {
-    *ier = IDASpilsSetMaxRestarts(IDA_idamem, *maxrs);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*eplifac != ZERO) {
-    *ier = IDASpilsSetEpsLin(IDA_idamem, *eplifac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  if (*dqincfac != ZERO) {
-    *ier = IDASpilsSetIncrementFactor(IDA_idamem, *dqincfac);
-    if (*ier != IDASPILS_SUCCESS) return;
-  }
-
-  IDA_ls = IDA_LS_SPGMR;
-
-  return;
-}
 
 /*************************************************/
 
@@ -625,23 +468,13 @@ void FIDA_SOLVE(realtype *tout, realtype *tret, realtype *yret,
     IDAGetNumGEvals(IDA_idamem, &IDA_iout[11]); /* NGE */
   
   switch(IDA_ls) {
-  case IDA_LS_DENSE:
-  case IDA_LS_BAND:
-  case IDA_LS_LAPACKDENSE:
-  case IDA_LS_LAPACKBAND:
+  case IDA_LS_DIRECT:
     IDADlsGetWorkSpace(IDA_idamem, &IDA_iout[12], &IDA_iout[13]);   /* LENRWLS, LENIWLS */
     IDADlsGetLastFlag(IDA_idamem, &IDA_iout[14]);                   /* LSTF */
     IDADlsGetNumResEvals(IDA_idamem, &IDA_iout[15]);                /* NRE */
     IDADlsGetNumJacEvals(IDA_idamem, &IDA_iout[16]);                /* NJE */
     break;
-  case IDA_LS_KLU:
-  case IDA_LS_SUPERLUMT:
-    IDASlsGetLastFlag(IDA_idamem, &IDA_iout[14]);                  /* LSTF  */
-    IDASlsGetNumJacEvals(IDA_idamem, &IDA_iout[16]);               /* NJE   */
-    break;
-  case IDA_LS_SPGMR:
-  case IDA_LS_SPBCG:
-  case IDA_LS_SPTFQMR:
+  case IDA_LS_ITERATIVE:
     IDASpilsGetWorkSpace(IDA_idamem, &IDA_iout[12], &IDA_iout[13]); /* LENRWLS, LENIWLS */
     IDASpilsGetLastFlag(IDA_idamem, &IDA_iout[14]);                 /* LSTF */
     IDASpilsGetNumResEvals(IDA_idamem, &IDA_iout[15]);              /* NRE */
@@ -722,22 +555,32 @@ void FIDA_FREE(void)
 
   ida_mem = (IDAMem) IDA_idamem;
 
-  free(ida_mem->ida_user_data); ida_mem->ida_user_data = NULL;
+  /* free DLS/SPILS interface */
+  if (ida_mem->ida_lfree)
+    ida_mem->ida_lfree(ida_mem);
+  ida_mem->ida_lmem = NULL;
 
+  /* free user_data structure */
+  if (ida_mem->ida_user_data)
+    free(ida_mem->ida_user_data);
+  ida_mem->ida_user_data = NULL;
+
+  /* free main integrator memory structure */
   IDAFree(&IDA_idamem);
 
-  /* Free F2C_IDA_vec */
+  /* free interface vectors / matrices / linear solvers */
   N_VSetArrayPointer(NULL, F2C_IDA_vec);
   N_VDestroy(F2C_IDA_vec);
-
-  /* Free F2C_IDA_ypvec */
   N_VSetArrayPointer(NULL, F2C_IDA_ypvec);
   N_VDestroy(F2C_IDA_ypvec);
-
-  /* Free F2C_IDA_ewtvec */
-  if (F2C_IDA_ewtvec != NULL) 
+  if (F2C_IDA_ewtvec != NULL) {
+    N_VSetArrayPointer(NULL, F2C_IDA_ewtvec);
     N_VDestroy(F2C_IDA_ewtvec);
-
+  }
+  if (F2C_IDA_matrix)
+    SUNMatDestroy(F2C_IDA_matrix);
+  if (F2C_IDA_linsol)
+    SUNLinSolFree(F2C_IDA_linsol);
   return;
 }
 
diff --git a/src/ida/fcmix/fida.h b/src/ida/fcmix/fida.h
index f2281ad..8bb066d 100644
--- a/src/ida/fcmix/fida.h
+++ b/src/ida/fcmix/fida.h
@@ -1,695 +1,937 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4795 $
- * $Date: 2016-07-01 15:10:25 -0700 (Fri, 01 Jul 2016) $
- * ----------------------------------------------------------------- 
+/*---------------------------------------------------------------
  * Programmer(s): Aaron Collier and Radu Serban @ LLNL
  *                Daniel R. Reynolds @ SMU
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ *---------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
+ * LLNS/SMU Copyright End
+ *---------------------------------------------------------------
  * This is the header file for FIDA, the Fortran interface to
  * the IDA package.
- * -----------------------------------------------------------------
- */
+ *--------------------------------------------------------------*/
 
-/*
- * =============================================================================
- *
- *                  FIDA Interface Package
- *
- * The FIDA Interface Package is a package of C functions which support
- * the use of the IDA solver, for the solution of DAE systems, in a
- * mixed Fortran/C setting.  While IDA is written in C, it is assumed
- * here that the user's calling program and user-supplied problem-defining
- * routines are written in Fortran.  This package provides the necessary
- * interface to IDA for both the serial and the parallel NVECTOR
- * implementations.
- *
- * The user-callable functions, with the corresponding IDA functions,
- * are as follows:
- *
- *   FNVINITS* and FNVINITP*  interface to N_VNew_Serial and
- *                            N_VNew_Parallel, respectively
- *   FNVINITOMP               N_VNew_OpenMP
- *   FNVINITPTS               N_VNew_Pthreads
- *
- *   FIDAMALLOC  interfaces to IDACreate and IDAInit
- *
- *   FIDAREINIT  interfaces to IDAReInit
- *
- *   FIDASETIIN, FIDASETRIN, FIDASETVIN interface to IDASet*
- *
- *   FIDATOLREINIT  interfaces to IDASetTolerances
- *
- *   FIDACALCIC  interfaces to IDACalcIC
- *
- *   FIDAEWTSET  interfaces to IDAWFtolerances
- *
- *   FIDADENSE        interfaces to IDADense
- *   FIDADENSESETJAC  interfaces to IDADenseSetJacFn
- *
- *   FIDABAND        interfaces to IDABand
- *   FIDABANDSETJAC  interfaces to IDABandSetJacFn
- *
- *   FIDAKLU         interfaces to IDAKLU
- *   FIDAKLUReinit   interfaces to IDAKLUReinit
- *   FIDASUPERLUMT   interfaces to IDASuperLUMT
- *   FIDASPARSESETJAC    interfaces to IDASlsSetSparseJacFn
- *
- *   FIDASPTFQMR/FIDASPTFQMRREINIT  interface to IDASptfqmr and IDASptfqmrSet*
- *   FIDASPBCG/FIDASPBCGREINIT      interface to IDASpbcg and IDASpbcgSet*
- *   FIDASPGMR/FIDASPGMRREINIT      interface to IDASpgmr and IDASpgmrSet*
- *   FIDASPILSSETJAC                interfaces to IDASpilsSetJacFn
- *   FIDASPILSSETPREC               interfaces to IDASpilsSetPreconditioner
- *
- *   FIDASOLVE  interfaces to IDASolve, IDAGet*, and IDA*Get*
- *
- *   FIDAGETDKY  interfaces to IDAGetDky
- *
- *   FIDAGETERRWEIGHTS  interfaces to IDAGetErrWeights
- *
- *   FIDAGETESTLOCALERR  interfaces to IDAGetEstLocalErrors
- *
- *   FIDAFREE  interfaces to IDAFree
- *
- * The user-supplied functions, each listed with the corresponding interface
- * function which calls it (and its type within IDA), are as follows:
- *   FIDARESFUN is called by the interface function FIDAresfn of type IDAResFn
- *   FIDADJAC   is called by the interface fn. FIDADenseJac of type IDADenseJacFn
- *   FIDABJAC   is called by the interface fn. FIDABandJac of type IDABandJacFn
- *   FIDAPSOL   is called by the interface fn. FIDAPSol of type IDASpilsPrecSolveFn
- *   FIDAPSET   is called by the interface fn. FIDAPSet of type IDASpilsPrecSetupFn
- *   FIDAJTIMES is called by interface fn. FIDAJtimes of type IDASpilsJacTimesVecFn
- *   FIDASPJAC  is called by interface fn. FIDASparseJac of type IDASlsSparseJacFn
- *   FIDAEWT    is called by interface fn. FIDAEwtSet of type IDAEwtFn
- * In contrast to the case of direct use of IDA, the names of all user-supplied
- * routines here are fixed, in order to maximize portability for the resulting
- * mixed-language program.
- *
- * Important note on portability:
- * In this package, the names of the interface functions, and the names of
- * the Fortran user routines called by them, appear as dummy names
- * which are mapped to actual values by a series of definitions in the
- * header file fida.h.
- *
- * =============================================================================
- *
- *                  Usage of the FIDA Interface Package
- *
- * The usage of FIDA requires calls to a few different interface
- * functions, depending on the method options selected, and one or more
- * user-supplied routines which define the problem to be solved.  These
- * function calls and user routines are summarized separately below.
- *
- * Some details are omitted, and the user is referred to the user documents
- * on IDA for more complete documentation.  Information on the
- * arguments of any given user-callable interface routine, or of a given
- * user-supplied function called by an interface function, can be found in
- * the documentation on the corresponding function in the IDA package.
- *
- * The number labels on the instructions below end with s for instructions
- * that apply to the serial version of IDA only, and end with p for
- * those that apply to the parallel version only.
- *
- * -----------------------------------------------------------------------------
- *
- * (1) User-supplied residual routine: FIDARESFUN
- * The user must in all cases supply the following Fortran routine
- *       SUBROUTINE FIDARESFUN(T, Y, YP, R, IPAR, RPAR, IER)
- *       DIMENSION Y(*), YP(*), R(*), IPAR(*), RPAR(*)
- * It must set the R array to F(t,y,y'), the residual of the DAE 
- * system, as a function of T = t, the array Y = y, and the array YP = y'.
- * Here Y, YP and R are distributed vectors. 
- * IPAR and RPAR are arrays of integer and real user data, respectively,
- * as passed to FIDAMALLOC.
- *
- * (2s) Optional user-supplied dense Jacobian approximation routine: FIDADJAC
- * As an option when using the DENSE linear solver, the user may supply a
- * routine that computes a dense approximation of the system Jacobian 
- * J = df/dy. If supplied, it must have the following form:
- *       SUBROUTINE FIDADJAC(NEQ, T, Y, YP, R, DJAC, CJ, EWT, H,
- *      1                    IPAR, RPAR, WK1, WK2, WK3, IER)
- *       DIMENSION Y(*), YP(*), R(*), EWT(*), DJAC(NEQ,*),
- *      1          IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*)
- * This routine must compute the Jacobian and store it columnwise in DJAC.
- * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC.
- *
- * (3s) Optional user-supplied band Jacobian approximation routine: FIDABJAC
- * As an option when using the BAND linear solver, the user may supply a
- * routine that computes a band approximation of the system Jacobian 
- * J = df/dy. If supplied, it must have the following form:
- *       SUBROUTINE FIDABJAC(NEQ, MU, ML, MDIM, T, Y, YP, R, CJ,
- *      1                    BJAC, EWT, H, IPAR, RPAR, WK1, WK2, WK3, IER)
- *       DIMENSION Y(*), YP(*), R(*), EWT(*), BJAC(MDIM,*),
- *      1          IPAR(*), RPAR(*), WK1(*), WK2(*), WK3(*)
- * This routine must load the MDIM by N array BJAC with the Jacobian matrix at the
- * current (t,y,y') in band form.  Store in BJAC(k,j) the Jacobian element J(i,j)
- * with k = i - j + MU + 1 (k = 1 ... ML+MU+1) and j = 1 ... N.
- * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC.
- *
- * (4) Optional user-supplied Jacobian-vector product routine: FIDAJTIMES
- * As an option when using the SPGMR/SPBCG/SPTFQMR linear solver, the user may
- * supply a routine that computes the product of the system Jacobian J = df/dy
- * and a given vector v.  If supplied, it must have the following form:
- *       SUBROUTINE FIDAJTIMES(T, Y, YP, R, V, FJV, CJ, EWT, H, 
- *      1                      IPAR, RPAR, WK1, WK2, IER)
- *       DIMENSION V(*), FJV(*), Y(*), YP(*), R(*), EWT(*),
- *      1          IPAR(*), RPAR(*), WK1(*), WK2(*)
- * This routine must compute the product vector Jv, where the vector v is stored
- * in V, and store the product in FJV.  On return, set IER = 0 if FIDAJTIMES was
- * successful, and nonzero otherwise.
- * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC.
- *
- * (5s) User-supplied sparse Jacobian approximation routine: FIDASPJAC
- *
- * Required when using the IDAKLU or IDASuperLUMT linear solvers, the 
- * user must supply a routine that computes a compressed-sparse-column [or 
- * compressed-sparse-row] approximation of the system Jacobian 
- * J = dF/dy' + c_j*dF/dy.  If supplied, it must have the following form:
- *
- *       SUBROUTINE FIDASPJAC(T, CJ, Y, YP, R, N, NNZ, JDATA, JRVALS, 
- *      &                    JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
- *
- * It must load the N by N compressed sparse column [row] matrix 
- * with storage for NNZ nonzeros, stored in the arrays JDATA (nonzero
- * values), JRVALS (row [column] indices for each nonzero), JCOLPTRS (indices 
- * for start of each column [row]), with the Jacobian matrix at the current
- * (t,y) in CSC [CSR] form (see sundials_sparse.h for more information).
- *
- * The arguments are:
- *         T    -- current time [realtype, input]
- *         CJ   -- Scalar in the system Jacobian proportional 
- *                 to inverse step size [realtype, input]
- *         Y    -- array containing state variables [realtype, input]
- *         YP   -- array containing state derivatives [realtype, input]
- *         R    -- array containing system residual F(T, Y, YP) [realtype, input]
- *         N    -- number of matrix rows/columns in Jacobian [int, input]
- *         NNZ  -- allocated length of nonzero storage [int, input]
- *        JDATA -- nonzero values in Jacobian
- *                 [realtype of length NNZ, output]
- *       JRVALS -- row [column] indices for each nonzero in Jacobian
- *                  [int of length NNZ, output]
- *       JCPTRS -- pointers to each Jacobian column [row] in preceding arrays
- *                 [int of length N+1, output]
- *         H    -- current step size [realtype, input]
- *         IPAR -- array containing integer user data that was passed to
- *                 FIDAMALLOC [long int, input]
- *         RPAR -- array containing real user data that was passed to
- *                 FIDAMALLOC [realtype, input]
- *         WK*  -- array containing temporary workspace of same size as Y 
- *                 [realtype, input]
- *         IER  -- return flag [int, output]:
- *                    0 if successful, 
- *                   >0 if a recoverable error occurred,
- *                   <0 if an unrecoverable error ocurred.
- *
- * (6) Optional user-supplied error weight vector routine: FIDAEWT
- * As an option to providing the relative and absolute tolerances, the user
- * may supply a routine that computes the weights used in the WRMS norms.
- * If supplied, it must have the following form:
- *       SUBROUTINE FIDAEWT(Y, EWT, IPAR, RPAR, IER)
- *       DIMENSION Y(*), EWT(*)
- * It must store the error weights in EWT, given the current solution vector Y.
- * On return, set IER = 0 if successful, and nonzero otherwise.
- * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC.
- *
- * -----------------------------------------------------------------------------
- *
- * (7) Initialization:  FNVINITS/FNVINITP/FNVINITOMP/FNVINITPTS, 
- *                      FIDAMALLOC, FIDAREINIT,
- *                      FIDATOLREINIT, and FIDACALCIC
- *
- * (7.1s) To initialize the serial machine environment, the user must make
- * the following call:
- *        CALL FNVINITS(KEY, NEQ, IER)
- * The arguments are:
- * KEY = 2 for IDA
- * NEQ = size of vectors
- * IER = return completion flag. Values are 0 = success, -1 = failure.
- *
- * (7.1p) To initialize the distributed memory parallel machine environment, 
- * the user must make one of the following calls:
- *        CALL FNVINITP(KEY, NLOCAL, NGLOBAL, IER)
- *                     -or-
- *        CALL FNVINITP(COMM, KEY, NLOCAL, NGLOBAL, IER)
- * The arguments are:
- * COMM = MPI communicator (e.g., MPI_COMM_WORLD)
- * KEY = 2 for IDA
- * NLOCAL  = local size of vectors on this processor
- * NGLOBAL = the system size, and the global size of vectors (the sum 
- *           of all values of NLOCAL)
- * IER     = return completion flag. Values are 0 = success, -1 = failure.
- * NOTE: The COMM argument passed to the FNVINITP routine is only supported if
- * the MPI implementation used to build SUNDIALS includes the MPI_Comm_f2c
- * function from the MPI-2 specification.  To check if the function is supported
- * look for the line "#define SUNDIALS_MPI_COMM_F2C 1" in the sundials_config.h
- * header file.
- *
- (7.1omp) To initialize the openMP threaded vector kernel, 
-          the user must make the following call:
+/*=============================================================================
+                   FIDA Interface Package
+ 
+  The FIDA Interface Package is a package of C functions which support
+  the use of the IDA solver, for the solution of DAE systems, in a
+  mixed Fortran/C setting.  While IDA is written in C, it is assumed
+  here that the user's calling program and user-supplied problem-defining
+  routines are written in Fortran.  This package provides the necessary
+  interface to IDA for any acceptable NVECTOR implementation.
+ 
+  A summary of the user-callable functions, with the corresponding 
+  IDA functions, are as follows:
+ 
+    Fortran                      IDA
+    ---------------------        --------------------------------
+    FNVINITS                     N_VNew_Serial
+    FNVINITP                     N_VNew_Parallel
+    FNVINITOMP                   N_VNew_OpenMP
+    FNVINITPTS                   N_VNew_Pthreads
+ 
+    FSUNBANDMATINIT              SUNBandMatrix
+    FSUNDENSEMATINIT             SUNDenseMatrix
+    FSUNSPARSEMATINIT            SUNSparseMatrix
 
-          CALL FNVINITOMP (KEY, NEQ, NUM_THREADS, IER)
+    FSUNBANDLINSOLINIT           SUNBandLinearSolver
+    FSUNDENSELINSOLINIT          SUNDenseLinearSolver
+    FSUNKLUINIT                  SUNKLU
+    FSUNKLUREINIT                SUNKLUReinit
+    FSUNLAPACKBANDINIT           SUNLapackBand
+    FSUNLAPACKDENSEINIT          SUNLapackDense
+    FSUNPCGINIT                  SUNPCG
+    FSUNSPBCGSINIT               SUNSPBCGS
+    FSUNSPFGMRINIT               SUNSPFGMR
+    FSUNSPGMRINIT                SUNSPGMR
+    FSUNSPTFQMRINIT              SUNSPTFQMR
+    FSUNSUPERLUMTINIT            SUNSuperLUMT
 
-        The arguments are:
-	  KEY = 2 for IDA
-          NEQ = size of vectors
-          NUM_THREADS = number of threads
-          IER = return completion flag. Values are 0 = success, -1 = failure.
+    FIDAMALLOC                   IDACreate, IDASetUserData and IDAInit
+    FIDAREINIT                   IDAReInit
+ 
+    FIDASETIIN                   IDASet* (integer arguments)
+    FIDASETRIN                   IDASet* (real arguments)
+    FIDASETVIN                   IDASet* (vector arguments)
+ 
+    FIDATOLREINIT                IDASetTolerances
+ 
+    FIDACALCIC                   IDACalcIC
+ 
+    FIDAEWTSET                   IDAWFtolerances
+ 
+    FIDADLSINIT                  IDADlsSetLinearSolver
+    FIDADENSESETJAC              IDADlsSetJacFn
+    FIDABANDSETJAC               IDADlsSetJacFn
+    FIDASPARSESETJAC             IDADlsSetJacFn
+ 
+    FIDASPILSINIT                IDASpilsSetLinearSolver
+    FIDASPILSSETEPSLIN           IDASpilsSetEpsLin
+    FIDASPILSSETINCREMENTFACTOR  IDASpilsSetIncrementFactor
+    FIDASPILSSETJAC              IDASpilsSetJacTimes
+    FIDASPILSSETPREC             IDASpilsSetPreconditioner
+ 
+    FIDASOLVE                    IDASolve, IDAGet*, and IDA*Get*
+ 
+    FIDAGETDKY                   IDAGetDky
+ 
+    FIDAGETERRWEIGHTS            IDAGetErrWeights
+ 
+    FIDAGETESTLOCALERR           IDAGetEstLocalErrors
+ 
+    FIDAFREE                     IDAFree
+    ---------------------        --------------------------------
+ 
+  The user-supplied functions, each listed with the corresponding interface
+  function which calls it (and its type within IDA), are as follows:
 
- (7.1pts) To initialize the Pthreads threaded vector kernel, 
-          the user must make the following call:
+    Fortran:           Interface Fcn:           IDA Type:
+    -------------      ------------------       -----------------------
+    FIDARESFUN         FIDAresfn                IDAResFn
+    FIDADJAC           FIDADenseJac             IDADlsJacFn
+    FIDABJAC           FIDABandJac              IDADlsJacFn
+    FIDASPJAC          FIDASparseJac            IDADlsJacFn
+    FIDAPSET           FIDAPSet                 IDASpilsPrecSetupFn
+    FIDAPSOL           FIDAPSol                 IDASpilsPrecSolveFn
+    FIDAJTSETUP        FIDAJTSetup              IDASpilsJacTimesSetupFn
+    FIDAJTIMES         FIDAJtimes               IDASpilsJacTimesVecFn
+    FIDAEWT            FIDAEwtSet               IDAEwtFn
+    -------------      ------------------       -----------------------
 
-          CALL FNVINITOMP (KEY, NEQ, NUM_THREADS, IER)
+  In contrast to the case of direct use of IDA, the names of all user-supplied
+  routines here are fixed, in order to maximize portability for the resulting
+  mixed-language program.
+ 
+  Important note on portability:
+  In this package, the names of the interface functions, and the names of
+  the Fortran user routines called by them, appear as dummy names
+  which are mapped to actual values by a series of definitions, in this
+  and other header files.
+ 
+  =============================================================================
+ 
+                   Usage of the FIDA Interface Package
+ 
+  The usage of FIDA requires calls to a few different interface
+  functions, depending on the method options selected, and one or more
+  user-supplied routines which define the problem to be solved.  These
+  function calls and user routines are summarized separately below.
+ 
+  Some details are omitted, and the user is referred to the user documents
+  on IDA for more complete documentation.  Information on the
+  arguments of any given user-callable interface routine, or of a given
+  user-supplied function called by an interface function, can be found in
+  the documentation on the corresponding function in the IDA package.
+ 
+  The number labels on the instructions below end with s for instructions
+  that are specific to use with the serial/OpenMP/PThreads NVector package, 
+  and end with p are specific to use with the N_VParallel package.
+ 
+ -----------------------------------------------------------------------------
 
-        The arguments are:
-	  KEY = 2 for IDA
-          NEQ = size of vectors
-          NUM_THREADS = number of threads
-          IER = return completion flag. Values are 0 = success, -1 = failure.
- *
- * (7.2) To set various problem and solution parameters and allocate
- * internal memory, make the following call:
- *       CALL FIDAMALLOC(T0, Y0, YP0, IATOL, RTOL, ATOL, 
- *      1                IOUT, ROUT, IPAR, RPAR, IER)
- * The arguments are:
- * T0    = initial value of t
- * Y0    = array of initial conditions, y(t0)
- * YP0   = value of y'(t0)
- * IATOL = type for absolute tolerance ATOL: 1 = scalar, 2 = array.
- *         If IATOL = 3, then the user must supply a routine FIDAEWT to compute
- *         the error weight vector.
- * RTOL  = relative tolerance (scalar)
- * ATOL  = absolute tolerance (scalar or array)
- * IOUT  = array of length at least 21 for integer optional outputs
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * ROUT  = array of length at least 6 for real optional outputs
- * IPAR  = array with user integer data
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * RPAR  = array with user real data
- * IER   = return completion flag.  Values are 0 = SUCCESS, and -1 = failure.
- *         See printed message for details in case of failure.
- *
- * The user data arrays IPAR and RPAR are passed unmodified to all subsequent
- * calls to user-provided routines. Modifications to either array inside a
- * user-provided routine will be propagated. Using these two arrays, the user
- * can dispense with Common blocks to pass data betwen user-provided routines.
- * 
- * The optional outputs are:
- *           LENRW   = IOUT( 1) -> IDAGetWorkSpace
- *           LENIW   = IOUT( 2) -> IDAGetWorkSpace
- *           NST     = IOUT( 3) -> IDAGetNumSteps
- *           NRE     = IOUT( 4) -> IDAGetNumResEvals
- *           NETF    = IOUT( 5) -> IDAGetNumErrTestFails
- *           NCFN    = IOUT( 6) -> IDAGetNumNonlinSolvConvFails
- *           NNI     = IOUT( 7) -> IDAGetNumNonlinSolvIters
- *           NSETUPS = IOUT( 8) -> IDAGetNumLinSolvSetups
- *           KLAST   = IOUT( 9) -> IDAGetLastOrder
- *           KCUR    = IOUT(10) -> IDAGetCurrentOrder
- *           NBCKTRK = IOUT(11) -> IDAGetNumBacktrackOps
- *           NGE     = IOUT(12) -> IDAGetNumGEvals
- *
- *           HINUSED = ROUT( 1) -> IDAGetActualInitStep
- *           HLAST   = ROUT( 2) -> IDAGetLastStep
- *           HCUR    = ROUT( 3) -> IDAGetCurrentStep
- *           TCUR    = ROUT( 4) -> IDAGetCurrentTime
- *           TOLSFAC = ROUT( 5) -> IDAGetTolScaleFactor
- *           UNITRND = ROUT( 6) -> UNIT_ROUNDOFF
- *
- *
- * If the user program includes the FIDAEWT routine for the evaluation of the 
- * error weights, the following call must be made
- *       CALL FIDAEWTSET(FLAG, IER)
- * with FLAG = 1 to specify that FIDAEWT is provided.
- * The return flag IER is 0 if successful, and nonzero otherwise.
- *
- * (7.3) To set various integer optional inputs, make the folowing call:
- *       CALL FIDASETIIN(KEY, VALUE, IER)
- * to set the optional input specified by the character key KEY to the 
- * integer value VAL.
- * KEY is one of the following: MAX_ORD, MAX_NSTEPS, MAX_ERRFAIL, MAX_NITERS, 
- * MAX_CONVFAIL, SUPPRESS_ALG, MAX_NSTEPS_IC, MAX_NITERS_IC, MAX_NJE_IC, LS_OFF_IC.
- *
- * To set various real optional inputs, make the folowing call:
- *       CALL FIDASETRIN(KEY, VALUE, IER)
- * to set the optional input specified by the character key KEY to the
- * real value VAL.
- * KEY is one of the following: INIT_STEP, MAX_STEP, MIIN_STEP, STOP_TIME,
- * NLCONV_COEF.
- *
- * To set the vector of variable IDs or the vector of constraints, make
- * the following call:
- *       CALL FIDASETVIN(KEY, ARRAY, IER)
- * where ARRAY is an array of reals and KEY is 'ID_VEC' or 'CONSTR_VEC'.
- *
- * FIDASETIIN, FIDASETRIN, and FIDASETVIN return IER=0 if successful and 
- * IER<0 if an error occured.
- *
- * (7.4) To re-initialize the FIDA solver for the solution of a new problem
- * of the same size as one already solved, make the following call:
- *       CALL FIDAREINIT(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR, IER)
- * The arguments have the same names and meanings as those of FIDAMALLOC.
- * FIDAREINIT performs the same initializations as FIDAMALLOC, but does no memory 
- * allocation for IDA data structures, using instead the existing internal memory
- * created by the previous FIDAMALLOC call.  The call to specify the linear system
- * solution method may or may not be needed.  See below.
- *
- * (7.5) To modify the tolerance parameters, make the following call:
- *       CALL FIDATOLREINIT(IATOL, RTOL, ATOL, IER)
- * The arguments have the same names and meanings as those of FIDAMALLOC.
- * FIDATOLREINIT simple calls IDASetTolerances with the given arguments.
- *
- * (7.6) To compute consistent initial conditions for an index-one DAE system,
- * make the following call:
- *       CALL FIDACALCIC(ICOPT, TOUT, IER)
- * The arguments are:
- * ICOPT = specifies the option: 1 = IDA_YP_YDP_INIT, 2 = IDA_Y_INIT.
- *         (See user guide for additional details.)
- * TOUT  = the first value of t at which a solution will be requested
- *         (from FIDASOLVE).
- * IER   = return completion flag.
- * 
- * -----------------------------------------------------------------------------
- *
- * (8) Specification of linear system solution method.
- * FIDA presently includes four choices for the treatment of these systems,
- * and the user of FIDA must call a routine with a specific name to make the
- * desired choice.
- * 
- * (8.1s) DENSE treatment of the linear system.
- * The user must make the call
- *       CALL FIDADENSE(NEQ, IER)
- * The arguments are:
- * NEQ = size of vectors
- * IER = error return flag: 0 = success , negative value = an error occured
- * 
- * If the user program includes the FIDADJAC routine for the evaluation of the 
- * dense approximation to the Jacobian, the following call must be made
- *       CALL FIDADENSESETJAC(FLAG, IER)
- * with FLAG = 1 to specify that FIDADJAC is provided.  (FLAG = 0 specifies
- * using the internal finite differences approximation to the Jacobian.)
- * The return flag IER is 0 if successful, and nonzero otherwise.
- * 
- * Optional outputs specific to the DENSE case are:
- *        LENRWLS = IOUT(13) -> IDADenseGetWorkSpace
- *        LENIWLS = IOUT(14) -> IDADenseGetWorkSpace
- *        LSTF    = IOUT(15) -> IDADenseGetLastFlag
- *        NRELS   = IOUT(16) -> IDADenseGetNumResEvals
- *        NJE     = IOUT(17) -> IDADenseGetNumJacEvals
- *
- * (8.2s) BAND treatment of the linear system
- * The user must make the call
- *       CALL FIDABAND(NEQ, MU, ML, IER)
- * The arguments are:
- * NEQ = size of vectors
- * MU  = upper bandwidth
- * ML  = lower bandwidth
- * IER = error return flag: 0 = success , negative value = an error occured
- * 
- * If the user program includes the FIDABJAC routine for the evaluation of the 
- * band approximation to the Jacobian, the following call must be made
- *       CALL FIDABANDSETJAC (FLAG, IER)
- * with FLAG = 1 to specify that FIDABJAC is provided.  (FLAG = 0 specifies
- * using the internal finite differences approximation to the Jacobian.)
- * The return flag IER is 0 if successful, and nonzero otherwise.
- *
- * Optional outputs specific to the BAND case are:
- *        LENRWLS = IOUT(13) -> IDABandGetWorkSpace
- *        LENIWLS = IOUT(14) -> IDABandGetWorkSpace
- *        LSTF    = IOUT(15) -> IDABandGetLastFlag
- *        NRELS   = IOUT(16) -> IDABandGetNumResEvals
- *        NJE     = IOUT(17) -> IDABandGetNumJacEvals
- *
- *  (8.3s) SPARSE treatment of the linear system using the KLU solver.
- *
- *     The user must make the call
- *
- *       CALL FIDAKLU(NEQ, NNZ, SPARSETYPE, ORDERING, IER)
- *
- *     The arguments are:
- *        NEQ = the problem size [int; input]
- *        NNZ = the maximum number of nonzeros [int; input]
- *        SPARSETYPE = choice between CSC and CSR format
- *           (0 = CSC, 1 = CSR) [int; input]
- *        ORDERING = the matrix ordering desired, possible values
- *           come from the KLU package (0 = AMD, 1 = COLAMD) [int; input]
- *        IER = error return flag [int, output]: 
- *	         0 = success, 
- *		 negative = error.
- * 
- *     When using the KLU solver the user must provide the FIDASPJAC routine for the 
- *     evalution of the sparse approximation to the Jacobian. To indicate that this
- *     routine has been provided, after the call to FIDAKLU, the following call must 
- *     be made    
- *
- *       CALL FIDASPARSESETJAC(IER) 
- *
- *     The int return flag IER=0 if successful, and nonzero otherwise.
- *
- *  
- *     The IDA KLU solver will reuse much of the factorization information from one
- *     nonlinear iteration to the next.  If at any time the user wants to force a full
- *     refactorization or if the number of nonzeros in the Jacobian matrix changes, the
- *     user should make the call
- *
- *       CALL FIDAKLUREINIT(NEQ, NNZ, REINIT_TYPE)
- *
- *     The arguments are:
- *        NEQ = the problem size [int; input]
- *        NNZ = the maximum number of nonzeros [int; input]
- *	REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be destroyed and 
- *          a new one will be allocated with NNZ nonzeros.  For a value of 2, 
- *	  only symbolic and numeric factorizations will be completed. 
- * 
- *     When using FIDAKLU, the user is required to supply the FIDASPJAC 
- *     routine for the evaluation of the sparse approximation to the 
- *     Jacobian, as discussed above with the other user-supplied routines.
- * 
- *     Optional outputs specific to the KLU case are:
- *        LSTF    = IOUT(16) from IDASlsGetLastFlag
- *        NJES    = IOUT(18) from IDASlsGetNumJacEvals
- *     See the IDA manual for descriptions.
- * 
- * (8.4s) SPARSE treatment of the linear system using the SuperLUMT solver.
- *
- *     The user must make the call
- *
- *       CALL FIDASUPERLUMT(NTHREADS, NEQ, NNZ, ORDERING, IER)
- *
- *     The arguments are:
- *        NTHREADS = desired number of threads to use [int; input]
- *        NEQ = the problem size [int; input]
- *        NNZ = the maximum number of nonzeros [int; input]
- *	ORDERING = the matrix ordering desired, possible values
- *	   come from the SuperLU_MT package [int; input]
- *           0 = Natural
- *           1 = Minimum degree on A^T A
- *           2 = Minimum degree on A^T + A
- *           3 = COLAMD
- *	IER = error return flag [int, output]: 
- *	         0 = success, 
- *		 negative = error.
- *	 
- *     At this time, there is no reinitialization capability for the SUNDIALS 
- *     interfaces to the SuperLUMT solver.
- *
- *     When using FIDASUPERLUMT, the user is required to supply the FIDASPJAC 
- *     routine for the evaluation of the CSC approximation to the Jacobian (note: the 
- *     current SuperLU_MT interface in SUNDIALS does not support CSR matrices). To 
- *     indicate that this routine has been provided, after the call to FIDASUPERLUMT,
- *     the following call must be made    
- *
- *       CALL FIDASPARSESETJAC(IER) 
- *
- *     The int return flag IER=0 if successful, and nonzero otherwise.
- * 
- *     Optional outputs specific to the SUPERLUMT case are:
- *        LSTF    = IOUT(14) from IDASlsGetLastFlag
- *        NJES    = IOUT(16) from IDASlsGetNumJacEvals
- *     See the IDA manual for descriptions.
- * 
- * (8.5) SPGMR treatment of the linear systems.
- * For the Scaled Preconditioned GMRES solution of the linear systems,
- * the user must make the following call:
- *       CALL FIDASPGMR(MAXL, IGSTYPE, MAXRS, EPLIFAC, DQINCFAC, IER)
- * The arguments are:
- * MAXL     = maximum Krylov subspace dimension; 0 indicates default.
- * IGSTYPE  = specifies the type of Gram-Schmidt orthogonalization to be used:
- *            1 = MODIFIED_GS, 2 = CLASSICAL_GS
- * EPLIFAC  = factor in the linear iteration convergence test constant
- * DQINCFAC = factor in the increments to y used in the difference quotient
- *            approximations to the matrix-vector products Jv
- * IER      = error return flag: 0 = success; negative value = an error occured
- *
- * Optional outputs specific to the SPGMR case are:
- *        LENRWLS = IOUT(13) -> IDASpgmrGetWorkSpace
- *        LENIWLS = IOUT(14) -> IDASpgmrGetWorkSpace
- *        LSTF    = IOUT(15) -> IDASpgmrGetLastFlag
- *        NRELS   = IOUT(16) -> IDASpgmrGetResEvals
- *        NJE     = IOUT(17) -> IDASpgmrGetJtimesEvals
- *        NPE     = IOUT(18) -> IDASpgmrGetPrecEvals
- *        NPS     = IOUT(19) -> IDASpgmrGetPrecSolves
- *        NLI     = IOUT(20) -> IDASpgmrGetLinIters
- *        NLCF    = IOUT(21) -> IDASpgmrGetConvFails
- *
- * If a sequence of problems of the same size is being solved using the
- * SPGMR linear solver, then following the call to FIDAREINIT, a call to the
- * FIDASPGMRREINIT routine is needed if any of IGSTYPE, MAXRS, EPLIFAC, or
- * DQINCFAC is being changed.  In that case, call FIDASPGMRREINIT as follows:
- *       CALL FIDASPGMRREINIT (IGSTYPE, MAXRS, EPLIFAC, DQINCFAC, IER)              
- * The arguments have the same meanings as for FIDASPGMR.  If MAXL is being
- * changed, then call FIDASPGMR instead.
- *
- * (8.6) SPBCG treatment of the linear systems.
- * For the Scaled Preconditioned Bi-CGSTAB solution of the linear systems,
- * the user must make the following call:
- *       CALL FIDASPBCG(MAXL, EPLIFAC, DQINCFAC, IER)              
- * The arguments are:
- * MAXL     = maximum Krylov subspace dimension; 0 indicates default.
- * EPLIFAC  = factor in the linear iteration convergence test constant
- * DQINCFAC = factor in the increments to y used in the difference quotient
- *            approximations to matrix-vector products Jv
- * IER      = error return flag: 0 = success; negative value = an error occured
- *
- * Optional outputs specific to the SPBCG case are:
- *        LENRWLS = IOUT(13) -> IDASpbcgGetWorkSpace
- *        LENIWLS = IOUT(14) -> IDASpbcgGetWorkSpace
- *        LSTF    = IOUT(15) -> IDASpbcgGetLastFlag
- *        NRELS   = IOUT(16) -> IDASpbcgGetResEvals
- *        NJE     = IOUT(17) -> IDASpbcgGetJtimesEvals
- *        NPE     = IOUT(18) -> IDASpbcgGetPrecEvals
- *        NPS     = IOUT(19) -> IDASpbcgGetPrecSolves
- *        NLI     = IOUT(20) -> IDASpbcgGetLinIters
- *        NLCF    = IOUT(21) -> IDASpbcgGetConvFails
- *
- *      If a sequence of problems of the same size is being solved using the
- * SPBCG linear solver, then following the call to FIDAREINIT, a call to the
- * FIDASPBCGREINIT routine is needed if MAXL, EPLIFAC, or DQINCFAC is
- * being changed.  In that case, call FIDASPBCGREINIT as follows:
- *       CALL FIDASPBCGREINIT(MAXL, EPLIFAC, DQINCFAC, IER)
- * The arguments have the same meanings as for FIDASPBCG.
- *
- * (8.7) SPTFQMR treatment of the linear systems.
- * For the Scaled Preconditioned TFQMR solution of the linear systems,
- * the user must make the following call:
- *       CALL FIDASPTFQMR(MAXL, EPLIFAC, DQINCFAC, IER)              
- * The arguments are:
- * MAXL     = maximum Krylov subspace dimension; 0 indicates default.
- * EPLIFAC  = factor in the linear iteration convergence test constant
- * DQINCFAC = factor in the increments to y used in the difference quotient
- *            approximations to matrix-vector products Jv
- * IER      = error return flag: 0 = success; negative value = an error occured
- *
- * Optional outputs specific to the SPTFQMR case are:
- *        LENRWLS = IOUT(13) -> IDASptfqmrGetWorkSpace
- *        LENIWLS = IOUT(14) -> IDASptfqmrGetWorkSpace
- *        LSTF    = IOUT(15) -> IDASptfqmrGetLastFlag
- *        NRELS   = IOUT(16) -> IDASptfqmrGetResEvals
- *        NJE     = IOUT(17) -> IDASptfqmrGetJtimesEvals
- *        NPE     = IOUT(18) -> IDASptfqmrGetPrecEvals
- *        NPS     = IOUT(19) -> IDASptfqmrGetPrecSolves
- *        NLI     = IOUT(20) -> IDASptfqmrGetLinIters
- *        NLCF    = IOUT(21) -> IDASptfqmrGetConvFails
- *
- *      If a sequence of problems of the same size is being solved using the
- * SPTFQMR linear solver, then following the call to FIDAREINIT, a call to the
- * FIDASPTFQMRREINIT routine is needed if MAXL, EPLIFAC, or DQINCFAC is
- * being changed.  In that case, call FIDASPTFQMRREINIT as follows:
- *       CALL FIDASPTFQMRREINIT (MAXL, EPLIFAC, DQINCFAC, IER)
- * The arguments have the same meanings as for FIDASPTFQMR.
- *
- * (8.8) Using user-provided functions for the iterative linear solvers
- * 
- * If the user program includes the FIDAJTIMES routine for the evaluation of the 
- * Jacobian vector product, the following call must be made
- *       CALL FIDASPILSSETJAC (FLAG, IER)
- * with FLAG = 1 to specify that FIDAJTIMES is provided.  (FLAG = 0 specifies
- * using and internal finite difference approximation to this product.)
- * The return flag IER is 0 if successful, and nonzero otherwise.
- *
- * Usage of the user-supplied routines FIDAPSOL and FIDAPSET for solution of the 
- * preconditioner linear system requires the following call:
- *       CALL FIDASPILSSETPREC(FLAG, IER)
- * with FLAG = 1. The return flag IER is 0 if successful, nonzero otherwise.
- * The user-supplied routine FIDAPSOL must have the form:
- *       SUBROUTINE FIDAPSOL(T, Y, YP, R, RV, ZV, CJ, DELTA, EWT, 
- *      1                    IPAR, RPAR, WRK, IER)
- *       DIMENSION Y(*), YP(*), R(*), RV(*), ZV(*), 
- *      1          IPAR(*), RPAR(*), EWT(*), WRK(*)
- * This routine must solve the preconditioner linear system Pz = r, where r = RV
- * is input, and store the solution z in ZV.
- *
- * The user-supplied routine FIDAPSET must be of the form:
- *       SUBROUTINE FIDAPSET(T, Y, YP, R, CJ, EWT, H, IPAR, RPAR, 
- *      1                    WK1, WK2, WK3, IER)
- *       DIMENSION Y(*), YP(*), R(*), EWT(*), IPAR(*), RPAR(*), 
- *      1          WK1(*), WK2(*), WK3(*)
- * This routine must perform any evaluation of Jacobian-related data and
- * preprocessing needed for the solution of the preconditioner linear systems
- * by FIDAPSOL.  On return, set IER = 0 if FIDAPSET was successful, set IER
- * positive if a recoverable error occurred, and set IER negative if a
- * non-recoverable error occurred.
- * IPAR and RPAR are user (integer and real) arrays passed to FIDAMALLOC.
- *
- * -----------------------------------------------------------------------------
- *
- * (9) The solver: FIDASOLVE
- * To solve the DAE system, make the following call:
- *       CALL FIDASOLVE(TOUT, TRET, Y, YP, ITASK, IER)
- * The arguments are:
- * TOUT  = next value of t at which a solution is desired (input)
- * TRET  = value of t reached by the solver on output
- * Y     = array containing the computed solution on output
- * YP    = array containing current value of y'
- * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate)
- *         2 = one-step mode (return after each internal step taken)
- *         3 = normal tstop mode (like 1, but integration never proceeds past 
- *             TSTOP, which must be specified through a call to FIDASETRIN
- *             using the key 'STOP_TIME'
- *         4 = one step tstop (like 2, but integration never goes past TSTOP)
- * IER   = completion flag: 0 = success, 1 = tstop return, 2 = root return, 
- *         values -1 ... -10 are various failure modes (see IDA manual).
- * The current values of the optional outputs are available in IOUT and ROUT.
- *
- * -----------------------------------------------------------------------------
- *
- * (10) Getting current solution derivative: FIDAGETDKY
- * To obtain interpolated values of y and y' for any value of t in the last
- * internal step taken by IDA, make the following call:
- *       CALL FIDAGETDKY(T, K, DKY, IER)
- * The arguments are:
- * T   = value of t at which solution is desired, in [TCUR - HU,TCUR].
- * K   = order of derivative requested.
- * DKY = array containing computed K-th derivative of the solution y.
- * IER = return flag: = 0 for success, < 0 for illegal argument.
- *
- * -----------------------------------------------------------------------------
- *
- * (11) Memory freeing: FIDAFREE
- * To the free the internal memory created by the calls to FIDAMALLOC and
- * FNVINITS or FNVINITP, depending on the version (serial/parallel), make
- * the following call:
- *       CALL FIDAFREE
- *
- * =============================================================================
- */
+                               Data Types
+
+ Throughout this documentation, we will refer to data types according to 
+ their usage in SUNDIALS.  The equivalent types to these may vary, 
+ depending on your computer architecture and on how SUNDIALS was compiled.  
+ A Fortran user should take care that all arguments passed through this 
+ Fortran/C interface are declared of the appropriate type.
+ 
+ Integers: SUNDIALS uses 'int', 'long int' and 'sunindextype' types.  At 
+ compilation, SUNDIALS allows the configuration of the 'index' type, that 
+ accepts values of 32-bit signed and 64-bit signed.  This choice dictates 
+ the size of a SUNDIALS 'sunindextype' variable.
+   int      -- equivalent to an INTEGER or INTEGER*4 in Fortran
+   long int -- equivalent to an INTEGER*8 in Fortran (Linux/UNIX/OSX), or 
+               equivalent to an INTEGER in Windows
+   sunindextype -- this will depend on the SUNDIALS configuration:
+               32-bit -- equivalent to an INTEGER or INTEGER*4 in Fortran
+               64-bit -- equivalent to an INTEGER*8 in Fortran
+	      
+ Real numbers:  At compilation, SUNDIALS allows the configuration option 
+ '--with-precision', that accepts values of 'single', 'double' or 
+ 'extended' (the default is 'double').  This choice dictates the size of a 
+ SUNDIALS 'realtype' variable.  The corresponding Fortran types for these 
+ 'realtype' sizes are:
+   single   -- equivalent to a REAL or REAL*4 in Fortran
+   double   -- equivalent to a DOUBLE PRECISION or REAL*8 in Fortran
+   extended -- equivalent to a REAL*16 in Fortran
+
+  -----------------------------------------------------------------------------
+ 
+  (1) User-supplied residual routine: FIDARESFUN
+
+      The user must in all cases supply the following Fortran routine
+
+        SUBROUTINE FIDARESFUN(T, Y, YP, R, IPAR, RPAR, IER)
+
+      It must set the R array to F(t,y,y'), the residual of the DAE system.
+
+      The arguments are:
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, output]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                  >0 if a recoverable error occurred,
+                  <0 if an unrecoverable error ocurred.
+ 
+  (2s) Optional user-supplied dense Jacobian approximation routine: FIDADJAC
+
+      As an option when using the Dense or LapackDense linear solvers, the 
+      user may supply a routine that computes a dense approximation of the 
+      system Jacobian J = dF/dy' + c_j*dF/dy. If supplied, it must have the 
+      following form:
+
+        SUBROUTINE FIDADJAC(NEQ, T, Y, YP, R, DJAC, CJ, EWT, H,
+       1                    IPAR, RPAR, WK1, WK2, WK3, IER)
+
+      This routine must compute the Jacobian and store it columnwise in DJAC.
+
+      The arguments are:
+        NEQ  -- number of rows in the matrix [long int, input]
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        DJAC -- 2D array containing the jacobian entries [realtype of size
+                (NEQ,NEQ), output]
+        CJ   -- scalar in the system Jacobian proportional to inverse step
+                size [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        H    -- current step size [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        WK*  -- array containing temporary workspace of same size as Y 
+                [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                  >0 if a recoverable error occurred,
+                  <0 if an unrecoverable error ocurred.
+ 
+  (2s) Optional user-supplied band Jacobian approximation routine: FIDABJAC
+
+      As an option when using the Band or LapackBand linear solvers, the 
+      user may supply a routine that computes a band approximation of the 
+      system Jacobian J = dF/dy' + c_j*dF/dy. If supplied, it must have the 
+      following form:
+
+        SUBROUTINE FIDABJAC(NEQ, MU, ML, MDIM, T, Y, YP, R, CJ, BJAC, 
+       1                    EWT, H, IPAR, RPAR, WK1, WK2, WK3, IER)
+
+      This routine must load the MDIM by N array BJAC with the Jacobian 
+      matrix at the current (t,y,y') in band form.  Store in BJAC(k,j) 
+      the Jacobian element J(i,j) with k = i - j + MU + 1 
+      (k = 1 ... ML+MU+1) and j = 1 ... N.
+ 
+      The arguments are:
+        NEQ  -- number of rows in the matrix [long int, input]
+        MU   -- upper half-bandwidth of the matrix [long int, input]
+        ML   -- lower half-bandwidth of the matrix [long int, input]
+        MDIM -- leading dimension of BJAC array [long int, input]
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        DJAC -- 2D array containing the jacobian entries [realtype of size
+                (NEQ,NEQ), output]
+        CJ   -- scalar in the system Jacobian proportional to inverse step
+                size [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        H    -- current step size [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        WK*  -- array containing temporary workspace of same size as Y 
+                [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                  >0 if a recoverable error occurred,
+                  <0 if an unrecoverable error ocurred.
+ 
+  (2s) User-supplied sparse Jacobian approximation routine: FIDASPJAC
+ 
+      When using the KLU or SuperLUMT linear solvers, the user *must* supply 
+      a routine that computes a compressed-sparse-column [or 
+      compressed-sparse-row] approximation of the system Jacobian 
+      J = dF/dy' + c_j*dF/dy.  If supplied, it must have the following form:
+ 
+        SUBROUTINE FIDASPJAC(T, CJ, Y, YP, R, N, NNZ, JDATA, JRVALS, 
+       1                     JCPTRS, H, IPAR, RPAR, WK1, WK2, WK3, IER)
+ 
+      It must load the N by N compressed sparse column [row] matrix with 
+      storage for NNZ nonzeros, stored in the arrays JDATA (nonzero values), 
+      JRVALS (row [column] indices for each nonzero), JCOLPTRS (indices for 
+      start of each column [row]), with the Jacobian matrix in CSC [CSR] 
+      form (see sunmatrix_sparse.h for more information).
+ 
+      The arguments are:
+          T    -- current time [realtype, input]
+          CJ   -- scalar in the system Jacobian proportional 
+                  to inverse step size [realtype, input]
+          Y    -- array containing state variables [realtype, input]
+          YP   -- array containing state derivatives [realtype, input]
+          R    -- array containing system residual F(T, Y, YP) [realtype, input]
+          N    -- number of matrix rows/columns in Jacobian [int, input]
+          NNZ  -- allocated length of nonzero storage [int, input]
+          JDATA -- nonzero values in Jacobian
+                  [realtype of length NNZ, output]
+          JRVALS -- row [column] indices for each nonzero in Jacobian
+                   [int of length NNZ, output]
+          JCPTRS -- pointers to each Jacobian column [row] in preceding arrays
+                  [int of length N+1, output]
+          H    -- current step size [realtype, input]
+          IPAR -- array containing integer user data that was passed to
+                  FIDAMALLOC [long int, input]
+          RPAR -- array containing real user data that was passed to
+                  FIDAMALLOC [realtype, input]
+          WK*  -- array containing temporary workspace of same size as Y 
+                  [realtype, input]
+          IER  -- return flag [int, output]:
+                     0 if successful, 
+                    >0 if a recoverable error occurred,
+                    <0 if an unrecoverable error ocurred.
+
+      NOTE: this may ONLY be used if SUNDIALS has been configured with 
+      sunindextype set to 64-bit integers.
+ 
+  (2) Optional user-supplied Jacobian-vector product setup routine: 
+      FIDAJTSETUP
+
+      As an option when using the IDASpils iterative linear solver 
+      interface, the user may supply a routine that computes the product of 
+      the system Jacobian J = dF/dy' + c_j*dF/dy and a given vector v, as 
+      well as a routine to set up any user data structures in preparation 
+      for the matrix-vector product.  If a 'setup' routine is supplied, 
+      it must have the following form:
+
+        SUBROUTINE FIDAJTSETUP(T, Y, YP, R, CJ, EWT, H, IPAR, RPAR, IER)
+
+      It must perform any relevant preparations for subsequent calls to the
+      user-provided FIDAJTIMES routine (see below).  
+
+      The arguments are:
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        CJ   -- scalar in the system Jacobian proportional to inverse step
+                size [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        H    -- current step size [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                   nonzero if an error.
+ 
+  (2) Optional user-supplied Jacobian-vector product routine: FIDAJTIMES
+
+      As an option when using the IDASpils linear solver interface, the 
+      user may supply a routine that computes the product of the system 
+      Jacobian J = dF/dy' + c_j*dF/dy and a given vector v.  If supplied, 
+      it must have the following form:
+
+         SUBROUTINE FIDAJTIMES(T, Y, YP, R, V, FJV, CJ, EWT, H, 
+        1                      IPAR, RPAR, WK1, WK2, IER)
+
+      This routine must compute the product vector Jv, where the vector v 
+      is stored in V, and store the product in FJV.
+
+      The arguments are:
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        V    -- array containing vector to multiply [realtype, input]
+        FJV  -- array containing product vector [realtype, output]
+        CJ   -- scalar in the system Jacobian proportional to inverse step
+                size [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        H    -- current step size [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                   nonzero if an error.
+
+  (3) Optional user-supplied preconditioner setup/solve routines: FIDAPSET 
+      and FIDAPSOL 
+
+      As an option when using the IDASPILS linear solver interface, the 
+      user may supply routines to setup and apply the preconditioner.  
+      If supplied, these must have the following form:
+
+        SUBROUTINE FIDAPSET(T, Y, YP, R, CJ, EWT, H, IPAR, RPAR, IER)
+
+      This routine must perform any evaluation of Jacobian-related data and
+      preprocessing needed for the solution of the preconditioner linear 
+      systems by FIDAPSOL.  
+ 
+      The arguments are:
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        CJ   -- scalar in the system Jacobian proportional to inverse step
+                size [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        H    -- current step size [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                   nonzero if an error.
+
+      The user-supplied routine FIDAPSOL must have the form:
+
+         SUBROUTINE FIDAPSOL(T, Y, YP, R, RV, ZV, CJ, DELTA, EWT, 
+        1                    IPAR, RPAR, IER)
+
+      This routine must solve the preconditioner linear system Pz = r, 
+      where r = RV is input, and store the solution z in ZV.
+ 
+      The arguments are:
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        RV   -- right-hand side array [realtype, input]
+        ZV   -- solution array [realtype, output]
+        CJ   -- scalar in the system Jacobian proportional to inverse step
+                size [realtype, input]
+        DELTA -- desired residual tolerance [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                   nonzero if an error.
+
+  (4) Optional user-supplied error weight vector routine: FIDAEWT
+
+      As an option to providing the relative and absolute tolerances, the 
+      user may supply a routine that computes the weights used in the WRMS 
+      norms.  If supplied, it must have the following form:
+
+        SUBROUTINE FIDAEWT(Y, EWT, IPAR, RPAR, IER)
+
+      It must store the error weights in EWT, given the current solution 
+      vector Y.
+
+      The arguments are:
+        Y    -- array containing state variables [realtype, input]
+        EWT  -- array containing the error weight vector [realtype, output]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                   nonzero if an error.
+
+  -----------------------------------------------------------------------------
+ 
+  (5) Initialization:  FNVINITS / FNVINITP / FNVINITOMP / FNVINITPTS, 
+                       FSUNBANDMATINIT / FSUNDENSEMATINIT / 
+                          FSUNSPARSEMATINIT,
+                       FSUNBANDLINSOLINIT / FSUNDENSELINSOLINIT / 
+                          FSUNKLUINIT / FSUNKLUREINIT / FSUNKLUSETORDERING / 
+                          FSUNLAPACKBANDINIT / FSUNLAPACKDENSEINIT / 
+                          FSUNPCGINIT / FSUNSPBCGSINIT / FSUNSPFGMRINIT / 
+                          FSUNSPGMRINIT / FSUNSPTFQMRINIT / FSUNSUPERLUMTINIT /
+                          FSUNSUPERLUMTSETORDERING,
+                       FIDAMALLOC, 
+                       FIDADLSINIT / FIDASPILSINIT
+                       FIDAREINIT,
+                       FIDATOLREINIT, 
+                       FIDACALCIC,
+ 
+      NOTE: the initialization order is important!  It *must* proceed as 
+      shown: vector, matrix (if used), linear solver (if used), IDA, 
+      IDADls/IDASpils, reinit.
+ 
+  (5.1s) To initialize the a vector specification for storing the solution 
+      data, the user must make one of the following calls:
+
+        (serial)   
+           CALL FNVINITS(2, NEQ, IER)
+        (MPI parallel)
+           CALL FNVINITP(COMM, 2, NLOCAL, NGLOBAL, IER)
+        (OpenMP threaded)
+           CALL FNVINITOMP(2, NEQ, NUM_THREADS, IER)
+        (PThreads threaded)
+           CALL FNVINITPTS(2, NEQ, NUM_THREADS, IER)
+
+      In each of these, one argument is an int containing the IDA solver 
+      ID (2). 
+
+      The other arguments are:
+         NEQ = size of vectors [long int, input]
+         COMM = the MPI communicator [int, input]
+         NLOCAL = local size of vectors on this processor 
+            [long int, input]
+         NGLOBAL = the system size, and the global size of vectors (the sum 
+            of all values of NLOCAL) [long int, input]
+         NUM_THREADS = number of threads
+         IER = return completion flag [int, output]:
+                  0 = success, 
+                 -1 = failure.
+
+  (5.2) To initialize a band/dense/sparse matrix structure for 
+      storing the system Jacobian and for use within a direct linear solver,
+      the user must make one of the following calls:
+ 
+           CALL FSUNBANDMATINIT(2, N, MU, ML, SMU, IER)
+           CALL FSUNDENSEMATINIT(2, M, N, IER)
+           CALL FSUNSPARSEMATINIT(2, M, N, NNZ, SPARSETYPE, IER)
+
+      In each of these, one argument is an int containing the IDA solver 
+      ID (2). 
+
+      The other arguments are:
+
+         M = the number of rows of the matrix [long int, input]
+         N = the number of columns of the matrix [long int, input]
+         MU = the number of upper bands (diagonal not included) in a banded 
+            matrix [long int, input]
+         ML = the number of lower bands (diagonal not included) in a banded 
+            matrix [long int, input]
+         SMU = the number of upper bands to store (diagonal not included) 
+            for factorization of a banded matrix [long int, input]
+         NNZ = the storage size (upper bound on the number of nonzeros) for 
+            a sparse matrix [long int, input]
+         SPARSETYPE = integer denoting use of CSC (0) vs CSR (1) storage 
+            for a sparse matrix [int, input]
+         IER = return completion flag [int, output]:
+                  0 = success, 
+                 -1 = failure.
+
+  (5.3) To initialize a linear solver structure for solving linear systems 
+      arising from solution to the DAE, the user must make one of the 
+      following calls:
+
+           CALL FSUNBANDLINSOLINIT(2, IER)
+           CALL FSUNDENSELINSOLINIT(2, IER)
+           CALL FSUNKLUINIT(2, IER)
+           CALL FSUNLAPACKBANDINIT(2, IER)
+           CALL FSUNLAPACKDENSEINIT(2, IER)
+           CALL FSUNPCGINIT(2, PRETYPE, MAXL, IER)
+           CALL FSUNSPBCGSINIT(2, PRETYPE, MAXL, IER)
+           CALL FSUNSPFGMRINIT(2, PRETYPE, MAXL, IER)
+           CALL FSUNSPGMRINIT(2, PRETYPE, MAXL, IER)
+           CALL FSUNSPTFQMRINIT(2, PRETYPE, MAXL, IER)
+           CALL FSUNSUPERLUMTINIT(2, NUM_THREADS, IER)
+
+      Or once these have been initialized, their solver parameters may be
+      modified via calls to the functions
+
+           CALL FSUNKLUSETORDERING(2, ORD_CHOICE, IER)
+           CALL FSUNSUPERLUMTSETORDERING(2, ORD_CHOICE, IER)
+
+           CALL FSUNPCGSETPRECTYPE(2, PRETYPE, IER)
+           CALL FSUNPCGSETMAXL(2, MAXL, IER)
+           CALL FSUNSPBCGSSETPRECTYPE(2, PRETYPE, IER)
+           CALL FSUNSPBCGSSETMAXL(2, MAXL, IER)
+           CALL FSUNSPFGMRSETGSTYPE(2, GSTYPE, IER)
+           CALL FSUNSPFGMRSETPRECTYPE(2, PRETYPE, IER)
+           CALL FSUNSPGMRSETGSTYPE(2, GSTYPE, IER)
+           CALL FSUNSPGMRSETPRECTYPE(2, PRETYPE, IER)
+           CALL FSUNSPTFQMRSETPRECTYPE(2, PRETYPE, IER)
+           CALL FSUNSPTFQMRSETMAXL(2, MAXL, IER)
+
+      In all of the above, one argument is an int containing the IDA solver 
+      ID (2). 
+
+      The other arguments are:
+
+         NNZ = the storage size (upper bound on the number of nonzeros) for 
+            a sparse matrix [long int, input]
+         ORD_CHOICE = integer denoting ordering choice (see 
+            SUNKLUSetOrdering and SUNSuperLUMTSetOrdering documentation 
+            for details) [int, input]
+         PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+            2=right, 3=both) [int, input]
+         MAXL = maximum Krylov subspace dimension [int, input]
+         GSTYPE = choice of Gram-Schmidt orthogonalization algorithm 
+            (0=modified, 1=classical) [int, input]
+         IER = return completion flag [int, output]:
+                   0 = success, 
+                  -1 = failure.
+
+ 
+  (5.4) To set various problem and solution parameters and allocate
+      internal memory, make the following call:
+
+         CALL FIDAMALLOC(T0, Y0, YP0, IATOL, RTOL, ATOL, 
+        1                IOUT, ROUT, IPAR, RPAR, IER)
+
+      The arguments are:
+         T0 = initial value of t [realtype, input]
+         Y0 = array of initial conditions for y(t0) [realtype, input]
+         YP0 = array of initial conditions for y'(t0) [realtype, input]
+         IATOL = type for absolute tolerance ATOL [int, input]: 
+                   1 = scalar, 
+                   2 = array,
+                   3 = user-supplied function; the user must supply a routine
+                       FIDAEWT to compute the error weight vector.
+         RTOL = scalar relative tolerance [realtype, input]
+         ATOL = scalar or array absolute tolerance [realtype, input]
+         IOUT = array of length at least 21 for integer optional outputs
+                [long int, output]
+         ROUT = array of length at least 6 for real optional outputs
+                [realtype, output]
+         IPAR = array of user integer data [long int, input/output]
+         RPAR = array with user real data [realtype, input/output]
+         IER  = return completion flag [int, output]:
+                   0 = SUCCESS,
+                  -1 = failure (see printed message for failure details).
+ 
+      The user data arrays IPAR and RPAR are passed unmodified to all 
+      subsequent calls to user-provided routines. Modifications to either 
+      array inside a user-provided routine will be propagated. Using these 
+      two arrays, the user can dispense with Common blocks to pass data 
+      betwen user-provided routines.
+  
+      The optional outputs are:
+            LENRW   = IOUT( 1) -> IDAGetWorkSpace
+            LENIW   = IOUT( 2) -> IDAGetWorkSpace
+            NST     = IOUT( 3) -> IDAGetNumSteps
+            NRE     = IOUT( 4) -> IDAGetNumResEvals
+            NETF    = IOUT( 5) -> IDAGetNumErrTestFails
+            NCFN    = IOUT( 6) -> IDAGetNumNonlinSolvConvFails
+            NNI     = IOUT( 7) -> IDAGetNumNonlinSolvIters
+            NSETUPS = IOUT( 8) -> IDAGetNumLinSolvSetups
+            KLAST   = IOUT( 9) -> IDAGetLastOrder
+            KCUR    = IOUT(10) -> IDAGetCurrentOrder
+            NBCKTRK = IOUT(11) -> IDAGetNumBacktrackOps
+            NGE     = IOUT(12) -> IDAGetNumGEvals
+ 
+            HINUSED = ROUT( 1) -> IDAGetActualInitStep
+            HLAST   = ROUT( 2) -> IDAGetLastStep
+            HCUR    = ROUT( 3) -> IDAGetCurrentStep
+            TCUR    = ROUT( 4) -> IDAGetCurrentTime
+            TOLSFAC = ROUT( 5) -> IDAGetTolScaleFactor
+            UNITRND = ROUT( 6) -> UNIT_ROUNDOFF
+      See the IDA manual for details. 
+ 
+  (5.5) If a direct linear solver was created in step (5.3) then it must be 
+      attached to IDA.  If the user called any one of FSUNBANDLINSOLINIT, 
+      FSUNDENSELINSOLINIT, FSUNKLUINIT, FSUNLAPACKBANDINIT, 
+      FSUNLAPACKDENSEINIT, or FSUNSUPERLUMTINIT, then this must be 
+      attached to the IDADLS interface using the command:
+
+        CALL FIDADLSINIT(IER)
+
+      The arguments are:
+            IER  = return completion flag [int, output]:
+                   0 = SUCCESS,
+                  -1 = failure (see printed message for failure details).
+
+  (5.5) If an iterative linear solver was created in step (5.3) then it must 
+      be attached to IDA.  If the user called any one of FSUNPCGINIT, 
+      FSUNSPBCGSINIT, FSUNSPFGMRINIT, FSUNSPGMRINIT, or FSUNSPTFQMRINIT, 
+      then this must be attached to the IDASPILS interface using the command:
+
+        CALL FIDASPILSINIT(IER)
+
+      The arguments are:
+            IER  = return completion flag [int, output]:
+                   0 = SUCCESS,
+                  -1 = failure (see printed message for failure details).
+
+ 
+  (5.6) If the user program includes the FIDAEWT routine for the evaluation 
+      of the error weights, the following call must be made
+
+        CALL FIDAEWTSET(FLAG, IER)
+
+      with FLAG = 1 to specify that FIDAEWT is provided and should be used; 
+      FLAG = 0 resets to the default EWT formulation. 
+      The return flag IER is 0 if successful, and nonzero otherwise.
+
+  (5.7) If the user program includes the FIDABJAC routine for the 
+      evaluation of the band approximation to the Jacobian, then following 
+      the call to FIDADLSINIT, the following call must be made 
+
+        CALL FIDABANDSETJAC(FLAG, IER)
+ 
+      with the int FLAG=1 to specify that FIDABJAC is provided and should be 
+      used; FLAG=0 specifies a reset to the internal finite difference 
+      Jacobian approximation.  The int return flag IER=0 if successful, 
+      nonzero otherwise.
+ 
+      If the user program includes the FIDADJAC routine for the evaluation 
+      of the dense approximation to the Jacobian, then after the call to 
+      FIDADLSINIT, the following call must be made 
+
+        CALL FIDADENSESETJAC(FLAG, IER)
+
+      with the int FLAG=1 to specify that FIDADJAC is provided and should be 
+      used; FLAG=0 specifies a reset to the internal finite difference 
+      Jacobian approximation.  The int return flag IER=0 if successful, and 
+      nonzero otherwise.
+ 
+      When using a sparse matrix and linear solver the user must provide the
+      FIDASPJAC routine for the evaluation of the sparse approximation to 
+      the Jacobian.  To indicate that this routine has been provided, after 
+      the call to FIDADLSINIT, the following call must be made 
+
+        CALL FIDASPARSESETJAC(IER)
+
+      The int return flag IER=0 if successful, and nonzero otherwise.
+
+ (5.8) If the user program includes the FIDAJTSETUP and FIDAJTIMES 
+      routines for setup of a Jacobian-times-vector product (for use with 
+      the IDASpils interface), then after creating the IDASpils interface, 
+      the following call must be made:
+
+        CALL FIDASPILSSETJAC(FLAG, IER)
+
+      with the int FLAG=1 to specify that FIDAJTSETUP and FIDAJTIMES are 
+      provided and should be used; FLAG=0 specifies a reset to the internal 
+      finite difference approximation to this product).  The int return 
+      flag IER=0 if successful, and nonzero otherwise.
+ 
+  (5.9) If the user program includes the FIDAPSET and FIDAPSOL routines 
+      for supplying a preconditioner to an iterative linear solver, then 
+      after creating the IDASpils interface, the following call must be made
+
+        CALL FIDASPILSSETPREC(FLAG, IER)
+
+      with the int FLAG=1.  If FLAG=0 then preconditioning with these 
+      routines will be disabled. The return flag IER=0 if successful, 
+      nonzero otherwise.
+
+  (5.10) If the user wishes to use one of IDAode's built-in preconditioning 
+      module, FIDABBD, then that should be initialized after creating the 
+      IDASpils interface using the call
+
+        CALL FIDABBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER)
+
+      Detailed explanation of the inputs to these functions, as well as any 
+      requirements of user-supplied functions on which these preconditioning 
+      modules rely, may be found in the header file fidabbd.h.
+
+  (5.11) To set various integer optional inputs, make the folowing call:
+
+        CALL FIDASETIIN(KEY, VALUE, IER)
+
+      to set the integer input VALUE to the optional input specified by the 
+      quoted character string KEY.  VALUE must be a Fortran integer of size 
+      commensurate with a C "long int".  KEY must be one of the following: 
+      MAX_ORD, MAX_NSTEPS, MAX_ERRFAIL, MAX_NITERS, MAX_CONVFAIL, 
+      SUPPRESS_ALG, MAX_NSTEPS_IC, MAX_NITERS_IC, MAX_NJE_IC, LS_OFF_IC. 
+      The int return flag IER is 0 if successful, and nonzero otherwise. 
+
+  (5.12) To set various real optional inputs, make the folowing call:
+
+        CALL FIDASETRIN(KEY, VALUE, IER)
+
+      to set the realtype value VALUE to the optional input specified by the 
+      quoted character string KEY.  VALUE must be a Fortran real-valued 
+      number of size commensurate with the SUNDIALS "realtype".  KEY must 
+      one of the following: INIT_STEP, MAX_STEP, MIIN_STEP, STOP_TIME,
+      NLCONV_COEF. The int return flag IER is 0 if successful, and nonzero
+      otherwise. 
+ 
+  (5.13) To set the vector of variable IDs or the vector of constraints, 
+      make the following call:
+
+        CALL FIDASETVIN(KEY, ARRAY, IER)
+
+      where ARRAY is an array of realtype and the quoted character string 
+      KEY is one of: ID_VEC or CONSTR_VEC.  The int return flag IER is 0 
+      if successful, and nonzero otherwise. 
+ 
+  (5.14) To re-initialize the FIDA solver for the solution of a new problem
+      of the same size as one already solved, make the following call:
+
+        CALL FIDAREINIT(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR, IER)
+
+      The arguments have the same names and meanings as those of FIDAMALLOC.
+      FIDAREINIT performs the same initializations as FIDAMALLOC, but does 
+      no memory allocation for IDA data structures, using instead the 
+      existing internal memory created by the previous FIDAMALLOC call.  
+      The subsequent calls to attach the linear system solver is only needed
+      if the matrix or linear solver objects have been re-created.
+ 
+  (5.15) To modify the tolerance parameters, make the following call:
+
+        CALL FIDATOLREINIT(IATOL, RTOL, ATOL, IER)
+
+      The arguments have the same names and meanings as those of FIDAMALLOC. 
+      FIDATOLREINIT simply calls IDASetTolerances with the given arguments.
+ 
+  (5.16) To compute consistent initial conditions for an index-one DAE system,
+      make the following call:
+
+        CALL FIDACALCIC(ICOPT, TOUT, IER)
+
+      The arguments are:
+         ICOPT = specifies the option [int, input]:
+                 1 = IDA_YP_YDP_INIT
+                 2 = IDA_Y_INIT
+                 (See user guide for additional details)
+         TOUT  = the first value of t at which a solution will 
+                 be requested from FIDASOLVE [realtype, input].
+         IER   = return completion flag [int, output].
+
+  (5.17) The SUNKLU solver will reuse much of the factorization information 
+      from one solve to the next.  If at any time the user wants to force a 
+      full refactorization or if the number of nonzeros in the Jacobian 
+      matrix changes, the user should make the call
+
+         CALL FSUNKLUREINIT(2, NNZ, REINIT_TYPE, IER)
+
+      The arguments are:
+         NNZ = the maximum number of nonzeros [int; input]
+         REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be 
+           destroyed and a new one will be allocated with NNZ nonzeros.  
+           For a value of 2, only symbolic and numeric factorizations will 
+           be completed. 
+ 
+  -----------------------------------------------------------------------------
+ 
+  (6) Optional outputs from DLS and SPILS linear solvers (stored in the 
+      IOUT array that was passed to FIDAMALLOC)
+
+      Optional outputs specific to the IDADLS interface:
+         LENRWLS = IOUT(13) -> IDADlsGetWorkSpace
+         LENIWLS = IOUT(14) -> IDADlsGetWorkSpace
+         LSTF    = IOUT(15) -> IDADlsGetLastFlag
+         NRELS   = IOUT(16) -> IDADlsGetNumResEvals
+         NJE     = IOUT(17) -> IDADlsGetNumJacEvals
+ 
+      Optional outputs specific to the SPGMR case are:
+         LENRWLS = IOUT(13) -> IDASpilsGetWorkSpace
+         LENIWLS = IOUT(14) -> IDASpilsGetWorkSpace
+         LSTF    = IOUT(15) -> IDASpilsGetLastFlag
+         NRELS   = IOUT(16) -> IDASpilsGetResEvals
+         NJE     = IOUT(17) -> IDASpilsGetJtimesEvals
+         NPE     = IOUT(18) -> IDASpilsGetPrecEvals
+         NPS     = IOUT(19) -> IDASpilsGetPrecSolves
+         NLI     = IOUT(20) -> IDASpilsGetLinIters
+         NLCF    = IOUT(21) -> IDASpilsGetConvFails
+ 
+      See the IDA manual for more detailed descriptions of any of the 
+      above.
+
+  -----------------------------------------------------------------------------
+ 
+  (7) The solver: FIDASOLVE
+
+      To solve the DAE system, make the following call:
+
+         CALL FIDASOLVE(TOUT, TRET, Y, YP, ITASK, IER)
+
+      The arguments are:
+        TOUT = next value of t at which a solution is desired [realtype, input]
+        TRET = value of t reached by the solver [realtype, output]
+        Y = array containing state variables on output [realtype, output]
+        YP = array containing state derivatives on output [realtype, output]
+        ITASK = task indicator [int, input]:
+                   1 = normal mode (overshoot TOUT and interpolate)
+                   2 = one-step mode (return after each internal step taken)
+                   3 = normal tstop mode (like 1, but integration never 
+                       proceeds past TSTOP, which must be specified through a 
+                       call to FIDASETRIN using the key 'STOP_TIME')
+                   4 = one step tstop (like 2, but integration never goes 
+                       past TSTOP)
+        IER = completion flag [int, output]: 
+                   0 = success, 
+                   1 = tstop return, 
+                   2 = root return, 
+                   negative values are failure modes (see IDA manual).
+      The current values of the optional outputs are immediately available in
+      the IOUT and ROUT arrays.
+
+  -----------------------------------------------------------------------------
+ 
+  (8) Getting current solution derivative: FIDAGETDKY
+
+      To obtain interpolated values of y and y' for any value of t in the 
+      last internal step taken by IDA, make the following call:
+
+         CALL FIDAGETDKY(T, K, DKY, IER)
+
+      The arguments are:
+        T = time at which solution derivative is desired, within the interval
+            [TCUR-HU,TCUR], [realtype, input].
+        K = derivative order (0 .le. K .le. QU) [int, input]
+        DKY = array containing computed K-th derivative of y [realtype, output]
+        IER = return flag [int, output]: 0=success, <0 = illegal argument.
+ 
+  -----------------------------------------------------------------------------
+ 
+  (9) Get the current error weight vector: FIDAGETERRWEIGHTS
+
+      To obtain the current error weight vector, make the following call:
+
+        CALL FIDAGETERRWEIGHTS(EWT, IER)
+
+      The arguments are:
+        EWT = array containing the error weight vector [realtype, output]
+        IER = return flag [int, output]: 0=success, nonzero if an error.
+ 
+  -----------------------------------------------------------------------------
+
+  (10) Get an estimate of the local error: FIDAGETESTLOCALERR
+
+      To obtain the current error estimate vector, make the following call:
+
+        CALL FIDAGETESTLOCALERR(ELE, IER)
+
+      The arguments are:
+        ELE = array with the estimated local error vector [realtype, output]
+        IER = return flag [int, output]: 0=success, nonzero if an error.
+ 
+  -----------------------------------------------------------------------------
+ 
+  (11) Memory freeing: FIDAFREE
+
+      To the free the internal memory created by the calls to FIDAMALLOC,
+      FIDADLSINIT/FIDASPILSINIT, the generic linear solver and matrix modules, 
+      and FNVINIT*, make the following call:
+
+        CALL FIDAFREE
+ 
+ =============================================================================*/
 
 #ifndef _FIDA_H
 #define _FIDA_H
 
-#include <ida/ida.h>                   /* definition of type IDAResFn */
-#include <sundials/sundials_direct.h>  /* definition of type DlsMat  */
-#include <sundials/sundials_sparse.h>  /* definition of type SlsMat  */
-#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
-#include <sundials/sundials_types.h>   /* definition of type realtype */
+#include <ida/ida.h>                         /* definition of type IDAResFn */
+#include <sundials/sundials_linearsolver.h>  /* definition of type SUNLinearSolver */
+#include <sundials/sundials_matrix.h>        /* definition of type SUNMatrix */
+#include <sundials/sundials_nvector.h>       /* definition of type N_Vector */
+#include <sundials/sundials_types.h>         /* definition of type realtype */
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -706,34 +948,25 @@ extern "C" {
 #define FIDA_SOLVE          SUNDIALS_F77_FUNC(fidasolve, FIDASOLVE)
 #define FIDA_FREE           SUNDIALS_F77_FUNC(fidafree, FIDAFREE)
 #define FIDA_CALCIC         SUNDIALS_F77_FUNC(fidacalcic, FIDACALCIC)
-#define FIDA_BAND           SUNDIALS_F77_FUNC(fidaband, FIDABAND)
+#define FIDA_DLSINIT        SUNDIALS_F77_FUNC(fidadlsinit, FIDADLSINIT)
+#define FIDA_SPILSINIT      SUNDIALS_F77_FUNC(fidaspilsinit,FIDASPILSINIT)
+#define FIDA_SPILSSETEPSLIN SUNDIALS_F77_FUNC(fidaspilssetepslin, FIDASPILSSETEPSLIN)
+#define FIDA_SPILSSETINCREMENTFACTOR SUNDIALS_F77_FUNC(fidaspilssetincrementfactor, FIDASPILSSETINCREMENTFACTOR)
 #define FIDA_BANDSETJAC     SUNDIALS_F77_FUNC(fidabandsetjac, FIDABANDSETJAC)
-#define FIDA_DENSE          SUNDIALS_F77_FUNC(fidadense, FIDADENSE)
+#define FIDA_BJAC           SUNDIALS_F77_FUNC(fidabjac, FIDABJAC)
 #define FIDA_DENSESETJAC    SUNDIALS_F77_FUNC(fidadensesetjac, FIDADENSESETJAC)
-#define FIDA_LAPACKBAND        SUNDIALS_F77_FUNC(fidalapackband, FIDALAPACKBAND)
-#define FIDA_LAPACKBANDSETJAC  SUNDIALS_F77_FUNC(fidalapackbandsetjac, FIDALAPACKBANDSETJAC)
-#define FIDA_LAPACKDENSE       SUNDIALS_F77_FUNC(fidalapackdense, FIDALAPACKDENSE)
-#define FIDA_LAPACKDENSESETJAC SUNDIALS_F77_FUNC(fidalapackdensesetjac, FIDALAPACKDENSESETJAC)
-#define FIDA_KLU            SUNDIALS_F77_FUNC(fidaklu, FIDAKLU)
-#define FIDA_KLUREINIT      SUNDIALS_F77_FUNC(fidaklureinit, FIDAKLUREINIT)
-#define FIDA_SUPERLUMT      SUNDIALS_F77_FUNC(fidasuperlumt, FIDASUPERLUMT)
+#define FIDA_DJAC           SUNDIALS_F77_FUNC(fidadjac, FIDADJAC)
 #define FIDA_SPARSESETJAC   SUNDIALS_F77_FUNC(fidasparsesetjac, FIDASPARSESETJAC)
-#define FIDA_SPTFQMR        SUNDIALS_F77_FUNC(fidasptfqmr, FIDASPTFQMR)
-#define FIDA_SPBCG          SUNDIALS_F77_FUNC(fidaspbcg, FIDASPBCG)
-#define FIDA_SPGMR          SUNDIALS_F77_FUNC(fidaspgmr, FIDASPGMR)
-#define FIDA_SPTFQMRREINIT  SUNDIALS_F77_FUNC(fidasptfqmrreinit, FIDASPTFQMRREINIT)
-#define FIDA_SPBCGREINIT    SUNDIALS_F77_FUNC(fidaspbcgreinit, FIDASPBCGREINIT)
-#define FIDA_SPGMRREINIT    SUNDIALS_F77_FUNC(fidaspgmrreinit, FIDASPGMRREINIT)
+#define FIDA_SPJAC          SUNDIALS_F77_FUNC(fidaspjac, FIDASPJAC)
 #define FIDA_SPILSSETJAC    SUNDIALS_F77_FUNC(fidaspilssetjac, FIDASPILSSETJAC)
+#define FIDA_JTSETUP        SUNDIALS_F77_FUNC(fidajtsetup, FIDAJTSETUP)
+#define FIDA_JTIMES         SUNDIALS_F77_FUNC(fidajtimes, FIDAJTIMES)
 #define FIDA_SPILSSETPREC   SUNDIALS_F77_FUNC(fidaspilssetprec, FIDASPILSSETPREC)
-#define FIDA_RESFUN         SUNDIALS_F77_FUNC(fidaresfun, FIDARESFUN)
-#define FIDA_DJAC           SUNDIALS_F77_FUNC(fidadjac, FIDADJAC)
-#define FIDA_BJAC           SUNDIALS_F77_FUNC(fidabjac, FIDABJAC)
 #define FIDA_PSET           SUNDIALS_F77_FUNC(fidapset, FIDAPSET)
 #define FIDA_PSOL           SUNDIALS_F77_FUNC(fidapsol, FIDAPSOL)
-#define FIDA_JTIMES         SUNDIALS_F77_FUNC(fidajtimes, FIDAJTIMES)
-#define FIDA_EWT            SUNDIALS_F77_FUNC(fidaewt, FIDAEWT)
+#define FIDA_RESFUN         SUNDIALS_F77_FUNC(fidaresfun, FIDARESFUN)
 #define FIDA_EWTSET         SUNDIALS_F77_FUNC(fidaewtset, FIDAEWTSET)
+#define FIDA_EWT            SUNDIALS_F77_FUNC(fidaewt, FIDAEWT)
 #define FIDA_GETDKY         SUNDIALS_F77_FUNC(fidagetdky, FIDAGETDKY)
 #define FIDA_GETERRWEIGHTS  SUNDIALS_F77_FUNC(fidageterrweights, FIDAGETERRWEIGHTS)
 #define FIDA_GETESTLOCALERR SUNDIALS_F77_FUNC(fidagetestlocalerr, FIDAGETESTLOCALERR)
@@ -749,32 +982,24 @@ extern "C" {
 #define FIDA_SOLVE          fidasolve_
 #define FIDA_FREE           fidafree_
 #define FIDA_CALCIC         fidacalcic_
-#define FIDA_BAND           fidaband_
+#define FIDA_DLSINIT        fidadlsinit_
+#define FIDA_SPILSINIT      fidaspilsinit_
+#define FIDA_SPILSSETEPSLIN fidaspilssetepslin_
+#define FIDA_SPILSSETINCREMENTFACTOR fidaspilssetincrementfactor_
 #define FIDA_BANDSETJAC     fidabandsetjac_
-#define FIDA_DENSE          fidadense_
+#define FIDA_BJAC           fidabjac_
 #define FIDA_DENSESETJAC    fidadensesetjac_
-#define FIDA_LAPACKBAND        fidalapackband_
-#define FIDA_LAPACKBANDSETJAC  fidalapackbandsetjac_
-#define FIDA_LAPACKDENSE       fidalapackdense_
-#define FIDA_LAPACKDENSESETJAC fidalapackdensesetjac_
-#define FIDA_KLU            fidaklu_
-#define FIDA_KLUREINIT      fidaklureinit_
-#define FIDA_SUPERLUMT      fidasuperlumt_
+#define FIDA_DJAC           fidadjac_
 #define FIDA_SPARSESETJAC   fidasparsesetjac_
-#define FIDA_SPTFQMR        fidasptfqmr_
-#define FIDA_SPBCG          fidaspbcg_
-#define FIDA_SPGMR          fidaspgmr_
-#define FIDA_SPTFQMRREINIT  fidasptfqmrreinit_
-#define FIDA_SPBCGREINIT    fidaspbcgreinit_
-#define FIDA_SPGMRREINIT    fidaspgmrreinit_
+#define FIDA_SPJAC          fidaspjac_
 #define FIDA_SPILSSETJAC    fidaspilssetjac_
+#define FIDA_JTSETUP        fidajtsetup_
+#define FIDA_JTIMES         fidajtimes_
 #define FIDA_SPILSSETPREC   fidaspilssetprec_
-#define FIDA_RESFUN         fidaresfun_
-#define FIDA_DJAC           fidadjac_
-#define FIDA_BJAC           fidabjac_
 #define FIDA_PSET           fidapset_
 #define FIDA_PSOL           fidapsol_
-#define FIDA_JTIMES         fidajtimes_
+#define FIDA_RESFUN         fidaresfun_
+#define FIDA_EWTSET         fidaewtset_
 #define FIDA_EWT            fidaewt_
 #define FIDA_GETDKY         fidagetdky_
 #define FIDA_GETERRWEIGHTS  fidageterrweights_
@@ -794,49 +1019,32 @@ typedef struct {
 void FIDA_MALLOC(realtype *t0, realtype *yy0, realtype *yp0,
                  int *iatol, realtype *rtol, realtype *atol,
                  long int *iout, realtype *rout,
-                 long int *ipar, realtype *rpar,
-                 int *ier);
+                 long int *ipar, realtype *rpar, int *ier);
 void FIDA_REINIT(realtype *t0, realtype *yy0, realtype *yp0,
                  int *iatol, realtype *rtol, realtype *atol,
                  int *ier);
 
 void FIDA_SETIIN(char key_name[], long int *ival, int *ier);
-
 void FIDA_SETRIN(char key_name[], realtype *rval, int *ier);
-
 void FIDA_SETVIN(char key_name[], realtype *vval, int *ier);
 
 void FIDA_TOLREINIT(int *iatol, realtype *rtol, realtype *atol, int *ier);
 void FIDA_CALCIC(int *icopt, realtype *tout1, int *ier);
 
-void FIDA_DENSE(long int *neq, int *ier);
+void FIDA_DLSINIT(int *ier);
 void FIDA_DENSESETJAC(int *flag, int *ier);
-void FIDA_BAND(long int *neq, long int *mupper, long int *mlower, int *ier);
 void FIDA_BANDSETJAC(int *flag, int *ier);
-
-void FIDA_LAPACKDENSE(int *neq, int *ier);
-void FIDA_LAPACKDENSESETJAC(int *flag, int *ier);
-void FIDA_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier);
-void FIDA_LAPACKBANDSETJAC(int *flag, int *ier);
-
-void FIDA_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier);
-void FIDA_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier);
-void FIDA_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier);
 void FIDA_SPARSESETJAC(int *ier);
 
-void FIDA_SPTFQMR(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier);
-void FIDA_SPBCG(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier);
-void FIDA_SPGMR(int *maxl, int *gstype, int *maxrs, realtype *eplifac,
-                realtype *dqincfac, int *ier);
-void FIDA_SPTFQMRREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier);
-void FIDA_SPBCGREINIT(int *maxl, realtype *eplifac, realtype *dqincfac, int *ier);
-void FIDA_SPGMRREINIT(int *gstype, int *maxrs, realtype *eplifac,
-                      realtype *dqincfac, int *ier);
+void FIDA_SPILSINIT(int *ier);
+void FIDA_SPILSSETEPSLIN(realtype *eplifac, int *ier);
+void FIDA_SPILSSETINCREMENTFACTOR(realtype *dqincfac, int *ier);
 void FIDA_SPILSSETJAC(int *flag, int *ier);
 void FIDA_SPILSSETPREC(int *flag, int *ier);
 
 void FIDA_SOLVE(realtype *tout, realtype *tret, realtype *yret,
                 realtype *ypret, int *itask, int *ier);
+
 void FIDA_FREE(void);
 void FIDA_EWTSET(int *flag, int *ier);
 void FIDA_GETDKY(realtype *t, int *k, realtype *dky, int *ier);
@@ -847,66 +1055,51 @@ void FIDA_GETESTLOCALERR(realtype *ele, int *ier);
 
 int FIDAresfn(realtype t, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data);
 
-int FIDADenseJac(long int N, realtype t, realtype c_j, 
-                 N_Vector yy, N_Vector yp, N_Vector rr,
-                 DlsMat Jac, void *user_data,
+int FIDADenseJac(realtype t, realtype c_j, N_Vector yy, N_Vector yp,
+                 N_Vector rr, SUNMatrix Jac, void *user_data,
                  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
 
-int FIDABandJac(long int N, long int mupper, long int mlower,
-                realtype t, realtype c_j, 
-                N_Vector yy, N_Vector yp, N_Vector rr,
-                DlsMat Jac, void *user_data,
+int FIDABandJac(realtype t, realtype c_j, N_Vector yy, N_Vector yp,
+                N_Vector rr, SUNMatrix Jac, void *user_data,
                 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
 
-int FIDALapackDenseJac(long int N, realtype t, realtype c_j, 
-                       N_Vector yy, N_Vector yp, N_Vector rr,
-                       DlsMat Jac, void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-
-int FIDALapackBandJac(long int N, long int mupper, long int mlower,
-                      realtype t, realtype c_j, 
-                      N_Vector yy, N_Vector yp, N_Vector rr,
-                      DlsMat J, void *user_data,
-                      N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
-
-int FIDASparseJac(realtype t, realtype cj, N_Vector y, N_Vector yp,
-		  N_Vector fval, SlsMat J, void *user_data, 
+int FIDASparseJac(realtype t, realtype c_j, N_Vector y, N_Vector yp,
+		  N_Vector rr, SUNMatrix Jac, void *user_data, 
 		  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
 
+int FIDAJTSetup(realtype t, N_Vector y, N_Vector yp, N_Vector r,
+                realtype c_j, void *user_data);
+
 int FIDAJtimes(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
                N_Vector v, N_Vector Jv,
                realtype c_j, void *user_data,
                N_Vector vtemp1, N_Vector vtemp2);
 
 int FIDAPSet(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
-             realtype c_j, void *user_data,
-             N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3);
+             realtype c_j, void *user_data);
 
 int FIDAPSol(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
              N_Vector rvec, N_Vector zvec,
-             realtype c_j, realtype delta, void *user_data,
-             N_Vector vtemp1);
+             realtype c_j, realtype delta, void *user_data);
 
 int FIDAEwtSet(N_Vector yy, N_Vector ewt, void *user_data);
 
 /* Declarations for global variables shared amongst various routines */
-
-extern N_Vector F2C_IDA_vec;    /* defined in FNVECTOR module */
-
-extern N_Vector F2C_IDA_ypvec;  /* defined in fida.c */
-extern N_Vector F2C_IDA_ewtvec; /* defined in fida.c */
-extern void *IDA_idamem;        /* defined in fida.c */
-extern long int *IDA_iout;      /* defined in fida.c */
-extern realtype *IDA_rout;      /* defined in fida.c */  
-extern int IDA_ls;              /* defined in fida.c */
-extern int IDA_nrtfn;           /* defined in fida.c */
+extern N_Vector F2C_IDA_vec;            /* defined in FNVECTOR module */
+extern N_Vector F2C_IDA_ypvec;          /* defined in fida.c */
+extern N_Vector F2C_IDA_ewtvec;         /* defined in fida.c */
+extern SUNMatrix F2C_IDA_matrix;        /* defined in FSUNMATRIX module */
+extern SUNLinearSolver F2C_IDA_linsol;  /* defined in FSUNLINSOL module */
+extern void *IDA_idamem;                /* defined in fida.c */
+extern long int *IDA_iout;              /* defined in fida.c */
+extern realtype *IDA_rout;              /* defined in fida.c */  
+extern int IDA_ls;                      /* defined in fida.c */
+extern int IDA_nrtfn;                   /* defined in fida.c */
 
 /* Linear solver IDs */
-
-enum { IDA_LS_DENSE = 1, IDA_LS_BAND = 2, 
-       IDA_LS_LAPACKDENSE = 3, IDA_LS_LAPACKBAND = 4, 
-       IDA_LS_KLU = 5, IDA_LS_SUPERLUMT = 6, 
-       IDA_LS_SPGMR = 7, IDA_LS_SPBCG = 8, IDA_LS_SPTFQMR = 9 };
+enum { IDA_LS_ITERATIVE = 0,
+       IDA_LS_DIRECT = 1,
+       IDA_LS_CUSTOM = 2 };
 
 #ifdef __cplusplus
 }
diff --git a/src/ida/fcmix/fidaband.c b/src/ida/fcmix/fidaband.c
index ac2ab3f..1154d9a 100644
--- a/src/ida/fcmix/fidaband.c
+++ b/src/ida/fcmix/fidaband.c
@@ -1,24 +1,24 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*-----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Aaron Collier @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for IDA/IDABAND, for the case of
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Fortran/C interface routines for IDA/IDADLS, for the case of
  * a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -26,7 +26,8 @@
 #include "fida.h"     /* function names, prototypes, global vars.*/
 #include "ida_impl.h" /* definition of IDAMem type               */
 
-#include <ida/ida_band.h>
+#include <ida/ida_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
 
 /*************************************************/
 
@@ -34,12 +35,12 @@
 extern "C" {
 #endif
 
-  extern void FIDA_BJAC(long int*, long int*, long int*, long int*,
-                        realtype*, realtype*, realtype*, realtype*,
-                        realtype*, realtype*, realtype*, realtype*,
-                        long int*, realtype*,
-                        realtype*, realtype*, realtype*, int*);
-
+  extern void FIDA_BJAC(long int* N, long int* MU, long int* ML,
+                        long int* EBAND, realtype* T, realtype* Y,
+                        realtype* YP, realtype* R, realtype* CJ,
+                        realtype* J, realtype* EWT, realtype* H,
+                        long int* IPAR, realtype* RPAR, realtype* V1, 
+                        realtype* V2, realtype* V3, int* IER);
 #ifdef __cplusplus
 }
 #endif
@@ -48,14 +49,9 @@ extern "C" {
 
 void FIDA_BANDSETJAC(int *flag, int *ier)
 {
-  *ier = 0;
-
   if (*flag == 0) {
-
-    *ier = IDADlsSetBandJacFn(IDA_idamem, NULL);
-
+    *ier = IDADlsSetJacFn(IDA_idamem, NULL);
   } else {
-
     if (F2C_IDA_ewtvec == NULL) {
       F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec);
       if (F2C_IDA_ewtvec == NULL) {
@@ -63,25 +59,21 @@ void FIDA_BANDSETJAC(int *flag, int *ier)
         return;
       }
     }
-
-    *ier = IDADlsSetBandJacFn(IDA_idamem, FIDABandJac);
-
+    *ier = IDADlsSetJacFn(IDA_idamem, FIDABandJac);
   }
-
   return;
 }
 
 /*************************************************/
 
-int FIDABandJac(long int N, long int mupper, long int mlower,
-		realtype t, realtype c_j, 
-		N_Vector yy, N_Vector yp, N_Vector rr,
-		DlsMat J, void *user_data,
-		N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+int FIDABandJac(realtype t, realtype c_j, N_Vector yy,  
+		N_Vector yp, N_Vector rr, SUNMatrix J,
+		void *user_data, N_Vector vtemp1,
+                N_Vector vtemp2, N_Vector vtemp3)
 {
   realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data;
   realtype h;
-  long int eband;
+  long int N, mupper, mlower, smu, eband;
   int ier;
   FIDAUserData IDA_userdata;
 
@@ -107,14 +99,18 @@ int FIDABandJac(long int N, long int mupper, long int mlower,
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
 
-  eband = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
+  N       = SUNBandMatrix_Columns(J);
+  mupper  = SUNBandMatrix_UpperBandwidth(J);
+  mlower  = SUNBandMatrix_LowerBandwidth(J);
+  smu     = SUNBandMatrix_StoredUpperBandwidth(J);
+  eband   = smu + mlower + 1;
+  jacdata = SUNBandMatrix_Column(J,0) - mupper;
 
   IDA_userdata = (FIDAUserData) user_data;
 
   /* Call user-supplied routine */
-  FIDA_BJAC(&N, &mupper, &mlower, &eband, &t, yy_data, yp_data, rr_data,
-	    &c_j, jacdata, ewtdata, &h, 
+  FIDA_BJAC(&N, &mupper, &mlower, &eband, &t, yy_data, yp_data,
+            rr_data, &c_j, jacdata, ewtdata, &h, 
             IDA_userdata->ipar, IDA_userdata->rpar,
             v1data, v2data, v3data, &ier);
 
diff --git a/src/ida/fcmix/fidabbd.c b/src/ida/fcmix/fidabbd.c
index 44e425c..2c16995 100644
--- a/src/ida/fcmix/fidabbd.c
+++ b/src/ida/fcmix/fidabbd.c
@@ -1,26 +1,26 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*-----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Aaron Collier @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
  * This module contains the routines necessary to interface with the
  * IDABBDPRE module and user-supplied Fortran routines.
  * The routines here call the generically named routines and provide
  * a standard interface to the C code of the IDABBDPRE package.
- * -----------------------------------------------------------------
- */
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -29,9 +29,6 @@
 #include "fidabbd.h"         /* prototypes of interfaces to IDABBD           */
 
 #include <ida/ida_bbdpre.h>  /* prototypes of IDABBDPRE functions and macros */
-#include <ida/ida_spgmr.h>   /* prototypes of IDASPGMR interface routines    */
-#include <ida/ida_spbcgs.h>  /* prototypes of IDASPBCG interface routines    */
-#include <ida/ida_sptfqmr.h> /* prototypes of IDASPTFQMR interface routines  */
 
 /*************************************************/
 
@@ -45,14 +42,14 @@
 extern "C" {
 #endif
 
-  extern void FIDA_GLOCFN(long int*, 
-                          realtype*, realtype*, realtype*, realtype*, 
-                          long int*, realtype*,
-                          int*);
-  extern void FIDA_COMMFN(long int*, 
-                          realtype*, realtype*, realtype*, 
-                          long int*, realtype*,
-                          int*);
+  extern void FIDA_GLOCFN(long int* NLOC, realtype* Y,
+                          realtype* YLOC, realtype* YPLOC,
+                          realtype* GLOC, long int* IPAR,
+                          realtype* RPAR, int* IER);
+  extern void FIDA_COMMFN(long int* NLOC, realtype* T,
+                          realtype* Y, realtype* YP, 
+                          long int* IPAR, realtype* RPAR,
+                          int* IER);
 
 #ifdef __cplusplus
 }
@@ -60,31 +57,32 @@ extern "C" {
 
 /*************************************************/
 
-void FIDA_BBDINIT(long int *Nloc, long int *mudq, long int *mldq,
-		  long int *mu, long int *ml, realtype *dqrely, int *ier)
+void FIDA_BBDINIT(long int *Nloc, long int *mudq,
+                  long int *mldq, long int *mu,
+                  long int *ml, realtype *dqrely,
+                  int *ier)
 {
-  *ier = IDABBDPrecInit(IDA_idamem, *Nloc, *mudq, *mldq, *mu, *ml,
-                        *dqrely, (IDABBDLocalFn) FIDAgloc, (IDABBDCommFn) FIDAcfn);
-
+  *ier = IDABBDPrecInit(IDA_idamem, *Nloc, *mudq, 
+                        *mldq, *mu, *ml, *dqrely,
+                        (IDABBDLocalFn) FIDAgloc,
+                        (IDABBDCommFn) FIDAcfn);
   return;
 }
 
 /*************************************************/
 
-void FIDA_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq,
-		    realtype *dqrely, int *ier)
+void FIDA_BBDREINIT(long int *Nloc, long int *mudq,
+                    long int *mldq, realtype *dqrely,
+                    int *ier)
 {
-  *ier = 0;
-
   *ier = IDABBDPrecReInit(IDA_idamem, *mudq, *mldq, *dqrely);
-
   return;
 }
 
 /*************************************************/
 
-int FIDAgloc(long int Nloc, realtype t, N_Vector yy, N_Vector yp,
-	     N_Vector gval, void *user_data)
+int FIDAgloc(long int Nloc, realtype t, N_Vector yy,
+             N_Vector yp, N_Vector gval, void *user_data)
 {
   realtype *yy_data, *yp_data, *gval_data;
   int ier;
@@ -109,7 +107,6 @@ int FIDAgloc(long int Nloc, realtype t, N_Vector yy, N_Vector yp,
   /* Call user-supplied routine */
   FIDA_GLOCFN(&Nloc, &t, yy_data, yp_data, gval_data, 
               IDA_userdata->ipar, IDA_userdata->rpar, &ier);
-
   return(ier);
 }
 
@@ -140,16 +137,15 @@ int FIDAcfn(long int Nloc, realtype t, N_Vector yy, N_Vector yp,
   /* Call user-supplied routine */
   FIDA_COMMFN(&Nloc, &t, yy_data, yp_data, 
               IDA_userdata->ipar, IDA_userdata->rpar, &ier);
-
   return(ier);
 }
 
 /*************************************************/
 
-void FIDA_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd)
+void FIDA_BBDOPT(long int *lenrwbbd, long int *leniwbbd,
+                 long int *ngebbd)
 {
   IDABBDPrecGetWorkSpace(IDA_idamem, lenrwbbd, leniwbbd);
   IDABBDPrecGetNumGfnEvals(IDA_idamem, ngebbd);
-
   return;
 }
diff --git a/src/ida/fcmix/fidabbd.h b/src/ida/fcmix/fidabbd.h
index e1cd9bd..cb29faa 100644
--- a/src/ida/fcmix/fidabbd.h
+++ b/src/ida/fcmix/fidabbd.h
@@ -1,294 +1,504 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Aaron Collier @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
  * This is the Fortran interface include file for the BBD
  * preconditioner (IDABBDPRE)
- * -----------------------------------------------------------------
- */
+ *-----------------------------------------------------------------*/
 
-/*
- * ==============================================================================
- *
- *                   FIDABBD Interface Package
- *
- * The FIDABBD Interface Package is a package of C functions which,
- * together with the FIDA Interface Package, support the use of the
- * IDA solver (parallel MPI version) with the IDABBDPRE preconditioner module,
- * for the solution of DAE systems in a mixed Fortran/C setting.  The
- * combination of IDA and IDABBDPRE solves DAE systems with the SPGMR
- * (scaled preconditioned GMRES), SPBCG (scaled preconditioned Bi-CGSTAB), or
- * SPTFQMR (scaled preconditioned TFQMR) method for the linear systems that arise,
- * and with a preconditioner that is block-diagonal with banded blocks.  While
- * IDA and IDABBDPRE are written in C, it is assumed here that the user's
- * calling program and user-supplied problem-defining routines are written in
- * Fortran.
- *
- * The user-callable functions in this package, with the corresponding
- * IDA and IDABBDPRE functions, are as follows: 
- *   FIDABBDININT   interfaces to IDABBDPrecInit
- *   FIDABBDREINIT  interfaces to IDABBDPrecReInit
- *   FIDABBDOPT     accesses optional outputs
- *   FIDABBDFREE    interfaces to IDABBDPrecFree
- *
- * In addition to the Fortran residual function FIDARESFUN, the
- * user-supplied functions used by this package, are listed below,
- * each with the corresponding interface function which calls it (and its
- * type within IDABBDPRE or IDA):
- *   FIDAGLOCFN  is called by the interface function FIDAgloc of type IDABBDLocalFn
- *   FIDACOMMFN  is called by the interface function FIDAcfn of type IDABBDCommFn
- *   FIDAJTIMES  (optional) is called by the interface function FIDAJtimes of 
- *               type IDASpilsJacTimesVecFn
- * (The names of all user-supplied routines here are fixed, in order to
- * maximize portability for the resulting mixed-language program.)
- *
- * Important note on portability:
- * In this package, the names of the interface functions, and the names of
- * the Fortran user routines called by them, appear as dummy names
- * which are mapped to actual values by a series of definitions in the
- * header file fidabbd.h.
- *
- * ==============================================================================
- *
- *               Usage of the FIDA/FIDABBD Interface Packages
- *
- * The usage of the combined interface packages FIDA and FIDABBD requires
- * calls to several interface functions, and a few different user-supplied
- * routines which define the problem to be solved and indirectly define
- * the preconditioner.  These function calls and user routines are
- * summarized separately below.
- *
- * Some details are omitted, and the user is referred to the IDA user document 
- * for more complete information.
- *
- * (1) User-supplied residual routine: FIDARESFUN
- * The user must in all cases supply the following Fortran routine
- *       SUBROUTINE FIDARESFUN(T, Y, YP, R, IPAR, RPAR, IER)
- *       DIMENSION Y(*), YP(*), R(*), IPAR(*), RPAR(*)
- * It must set the R array to F(t,y,y'), the residual of the DAE 
- * system, as a function of T = t, the array Y = y, and the array YP = y'.
- * Here Y, YP and R are distributed vectors.
- *
- * (2) User-supplied routines to define preconditoner: FIDAGLOCFN and FIDACOMMFN
- *
- * The routines in the IDABBDPRE module provide a preconditioner matrix
- * for IDA that is block-diagonal with banded blocks.  The blocking
- * corresponds to the distribution of the dependent variable vectors y and y'
- * among the processes.  Each preconditioner block is generated from the
- * Jacobian of the local part (associated with the current process) of a given
- * function G(t,y,y') approximating F(t,y,y').  The blocks are generated by a
- * difference quotient scheme independently by each process, utilizing
- * an assumed banded structure with given half-bandwidths.  A separate
- * pair of half-bandwidths defines the band matrix retained.
- *
- * (2.1) Local approximate function FIDAGLOCFN.
- * The user must supply a subroutine of the form
- *       SUBROUTINE FIDAGLOCFN(NLOC, T, YLOC, YPLOC, GLOC, IPAR, RPAR, IER)
- *       DIMENSION YLOC(*), YPLOC(*), GLOC(*), IPAR(*), RPAR(*)
- * to compute the function G(t,y,y') which approximates the residual
- * function F(t,y,y').  This function is to be computed locally, i.e., without 
- * interprocess communication.  (The case where G is mathematically
- * identical to F is allowed.)  It takes as input the local vector length
- * NLOC, the independent variable value T = t, and the local realtype
- * dependent variable arrays YLOC and YPLOC.  It is to compute the local part
- * of G(t,y,y') and store this in the realtype array GLOC.
- *
- * (2.2) Communication function FIDACOMMF.
- * The user must also supply a subroutine of the form
- *       SUBROUTINE FIDACOMMFN(NLOC, T, YLOC, YPLOC, IPAR, RPAR, IER)
- *       DIMENSION YLOC(*), YPLOC(*), IPAR(*), RPAR(*)
- * which is to perform all interprocess communication necessary to
- * evaluate the approximate residual function G described above.
- * This function takes as input the local vector length NLOC, the
- * independent variable value T = t, and the local real dependent
- * variable arrays YLOC and YPLOC.  It is expected to save communicated
- * data in  work space defined by the user, and made available to FIDAGLOCFN.
- * Each call to the FIDACOMMFN is preceded by a call to FIDARESFUN with
- * the same (t,y,y') arguments.  Thus FIDACOMMFN can omit any
- * communications done by FIDARESFUN if relevant to the evaluation of G.
- *
- * (3) Optional user-supplied Jacobian-vector product routine: FIDAJTIMES
- * As an option when using the SPGMR/SPBCG/SPTFQMR linear solver, the user may
- * supply a routine that computes the product of the system Jacobian J = df/dy
- * and a given vector v.  If supplied, it must have the following form:
- *       SUBROUTINE FIDAJTIMES(T, Y, YP, R, V, FJV, CJ, EWT, H, 
- *      1                      IPAR, RPAR, WK1, WK2, IER)
- *       DIMENSION V(*), FJV(*), Y(*), YP(*), R(*), EWT(*),
- *      1          , IPAR(*), RPAR(*), WK1(*), WK2(*)
- * This routine must compute the product vector Jv, where the vector v is stored
- * in V, and store the product in FJV.  On return, set IER = 0 if FIDAJTIMES was
- * successful, and nonzero otherwise.
- *
- * (4) Initialization:  FNVINITP, FIDAMALLOC, FIDABBDINIT.
- *
- * (4.1) To initialize the parallel machine environment, the user must make 
- * one of the following calls:
- *        CALL FNVINITP (KEY, NLOCAL, NGLOBAL, IER)
- *                     -or-
- *        CALL FNVINITP (COMM, KEY, NLOCAL, NGLOBAL, IER)
- * The arguments are:
- * COMM = MPI communicator (e.g., MPI_COMM_WORLD)
- * KEY = 3 for IDA
- * NLOCAL  = local size of vectors on this processor
- * NGLOBAL = the system size, and the global size of vectors (the sum 
- *           of all values of NLOCAL)
- * IER     = return completion flag. Values are 0 = success, -1 = failure.
- * NOTE: The COMM argument passed to the FNVINITP routine is only supported if
- * the MPI implementation used to build SUNDIALS includes the MPI_Comm_f2c
- * function from the MPI-2 specification.  To check if the function is supported
- * look for the line "#define SUNDIALS_MPI_COMM_F2C 1" in the sundials_config.h
- * header file.
- *
- * (4.2) To set various problem and solution parameters and allocate
- * internal memory, make the following call:
- *       CALL FIDAMALLOC(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR,
- *      1                IOUT, ROUT, IPAR, RPAR, IER)
- * The arguments are:
- * T0    = initial value of t
- * Y0    = array of initial conditions, y(t0)
- * YP0   = value of y'(t0)
- * IATOL = type for absolute tolerance ATOL: 1 = scalar, 2 = array.
- *         If IATOL = 3, then the user must supply a routine FIDAEWT to compute
- *         the error weight vector.
- * RTOL  = relative tolerance (scalar)
- * ATOL  = absolute tolerance (scalar or array)
- * IOUT  = array of length at least 21 for integer optional inputs and outputs
- *          (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * ROUT  = array of length 6 for real optional inputs and outputs
- *
- *         The optional outputs are:
- *
- *           LENRW   = IOUT( 1) -> IDAGetWorkSpace
- *           LENIW   = IOUT( 2) -> IDAGetWorkSpace
- *           NST     = IOUT( 3) -> IDAGetNumSteps
- *           NRE     = IOUT( 4) -> IDAGetNumResEvals
- *           NETF    = IOUT( 5) -> IDAGetNumErrTestFails
- *           NCFN    = IOUT( 6) -> IDAGetNumNonlinSolvConvFails
- *           NNI     = IOUT( 7) -> IDAGetNumNonlinSolvIters
- *           NSETUPS = IOUT( 8) -> IDAGetNumLinSolvSetups
- *           KLAST   = IOUT( 9) -> IDAGetLastOrder
- *           KCUR    = IOUT(10) -> IDAGetCurrentOrder
- *           NBCKTRK = IOUT(11) -> IDAGetNumBacktrackOps
- *           NGE     = IOUT(12) -> IDAGetNumGEvals
- *
- *           HINUSED = ROUT( 1) -> IDAGetActualInitStep
- *           HLAST   = ROUT( 2) -> IDAGetLastStep
- *           HCUR    = ROUT( 3) -> IDAGetCurrentStep
- *           TCUR    = ROUT( 4) -> IDAGetCurrentTime
- *           TOLSFAC = ROUT( 5) -> IDAGetTolScaleFactor
- *           UNITRND = ROUT( 6) -> UNIT_ROUNDOFF
- *
- * IPAR  = array with user integer data
- *         (declare as INTEGER*4 or INTEGER*8 according to C type long int)
- * RPAR  = array with user real data
- * IER   = return completion flag.  Values are 0 = SUCCESS, and -1 = failure.
- *         See printed message for details in case of failure.
- *
- * If the user program includes the FIDAEWT routine for the evaluation of the 
- * error weights, the following call must be made
- *       CALL FIDAEWTSET (FLAG, IER)
- * with FLAG = 1 to specify that FIDAEWT is provided.
- * The return flag IER is 0 if successful, and nonzero otherwise.
- *
- * (4.3) Attach one of the 3 SPILS linear solvers. Make one of the 
- * following calls (see fida.h for more details).
- *       CALL FIDASPGMR(MAXL, IGSTYPE, MAXRS, EPLIFAC, DQINCFAC, IER)
- *       CALL FIDASPBCG(MAXL, EPLIFAC, DQINCFAC, IER)
- *       CALL FIDASPTFQMR(MAXL, EPLIFAC, DQINCFAC, IER)
- *
- * (4.4) To allocate memory and initialize data associated with the IDABBDPRE
- * preconditioner, make the following call:
- *       CALL FIDABBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER)
- * The arguments are:
- * NLOCAL    = local size of vectors
- * MUDQ,MLDQ = upper and lower half-bandwidths to be used in the computation
- *             of the local Jacobian blocks by difference quotients.
- *             These may be smaller than the true half-bandwidths of the
- *             Jacobian of the local block of g, when smaller values may
- *             provide greater efficiency.
- * MU, ML    = upper and lower half-bandwidths of the band matrix that 
- *             is retained as an approximation of the local Jacobian block.
- *             These may be smaller than MUDQ and MLDQ.
- * DQRELY    = relative increment factor in y for difference quotients
- *             (optional). 0.0 indicates the default, sqrt(UNIT_ROUNDOFF).
- * IER       = return completion flag: IER=0: success, IER<0: an error occured
- *
- * (4.5) To specify whether the linear solver should use the supplied FIDAJTIMES or the 
- * internal finite difference approximation, make the call
- *        CALL FIDASPILSSETJAC(FLAG, IER)
- * where FLAG=0 for finite differences approxaimtion or
- *       FLAG=1 to use the supplied routine FIDAJTIMES
- *
- * (5) Re-initialization: FIDAREINIT, FIDABBDREINIT
- * If a sequence of problems of the same size is being solved using the SPGMR or
- * SPBCG linear solver in combination with the IDABBDPRE preconditioner, then the
- * IDA package can be reinitialized for the second and subsequent problems
- * so as to avoid further memory allocation.  First, in place of the call
- * to FIDAMALLOC, make the following call:
- *       CALL FIDAREINIT(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR, IER)
- * The arguments have the same names and meanings as those of FIDAMALLOC.
- * FIDAREINIT performs the same initializations as FIDAMALLOC, but does no
- * memory allocation for IDA data structures, using instead the existing
- * internal memory created by the previous FIDAMALLOC call.  Following the call
- * to FIDAREINIT, a call to FIDABBDINIT may or may not be needed.  If the input
- * arguments are the same, no FIDABBDINIT call is needed.  If there is a change
- * in input arguments other than MU, ML or MAXL, then the user program should call
- * FIDABBDREINIT.  The arguments of the FIDABBDREINIT routine have the
- * same names and meanings as FIDABBDINIT.  Finally, if the value of MU, ML, or
- * MAXL is being changed, then a call to FIDABBDINIT must be made.
- *
- * (6) The solver: FIDASOLVE
- * To solve the DAE system, make the following call:
- *       CALL FIDASOLVE (TOUT, TRET, Y, YP, ITASK, IER)
- * The arguments are:
- * TOUT  = next value of t at which a solution is desired (input)
- * TRET  = value of t reached by the solver on output
- * Y     = array containing the computed solution on output
- * YP    = array containing current value of y'
- * ITASK = task indicator: 1 = normal mode (overshoot TOUT and interpolate)
- *         2 = one-step mode (return after each internal step taken)
- *         3 = normal tstop mode (like 1, but integration never proceeds past 
- *             TSTOP,  which must be specified through a call to FIDASETRIN
- *             using the key 'STOP_TIME'
- *         4 = one step tstop (like 2, but integration never goes past TSTOP)
- * IER   = completion flag: 0 = success, 1 = tstop return, 2 = root return, 
- *         values -1 ... -10 are various failure modes (see IDA manual).
- * The current values of the optional outputs are available in IOUT and ROUT.
- *
- * (7) Optional outputs: FIDABBDOPT
- * Optional outputs specific to the SPGMR/SPBCG/SPTFQMR solver are available 
- * in IOUT(13)...IOUT(21)
- *
- * To obtain the optional outputs associated with the IDABBDPRE module, make
- * the following call:
- *       CALL FIDABBDOPT (LENRWBBD, LENIWBBD, NGEBBD)
- * The arguments returned are:
- * LENRWBBD = length of real preconditioner work space, in realtype words.
- *            This size is local to the current process.
- * LENIWBBD = length of integer preconditioner work space, in integer words.
- *            This size is local to the current process.
- * NGEBBD   = number of G(t,y,y') evaluations (calls to FIDAGLOCFN) so far.
- *
- * (8) Memory freeing: FIDAFREE
- * To the free the internal memory created by the calls to FNVINITP and
- * FIDAMALLOC, make the following call:
- *       CALL FIDAFREE
- *
- * ==============================================================================
- */
+/*==============================================================================
+                    FIDABBD Interface Package
+ 
+  The FIDABBD Interface Package is a package of C functions which, together with 
+  the FIDA Interface Package, support the use of the IDA solver and MPI-parallel 
+  N_Vector module, along with the IDABBDPRE preconditioner module, for the 
+  solution of DAE systems in a mixed Fortran/C setting.  The combination of IDA
+  and IDABBDPRE solves the linear systems arising from the solution of DAE 
+  systems using a Krylov iterative linear solver via the IDASPILS interface, 
+  and with a preconditioner that is block-diagonal with banded blocks.  While
+  IDA and IDABBDPRE are written in C, it is assumed here that the user's
+  calling program and user-supplied problem-defining routines are written in
+  Fortran.
+ 
+  The user-callable functions in this package, with the corresponding
+  IDA and IDABBDPRE functions, are as follows: 
+
+    Fortran              IDA
+    --------------       ---------------------------
+    FIDABBDININT         IDABBDPrecInit
+    FIDABBDREINIT        IDABBDPrecReInit
+    FIDABBDOPT           (accesses optional outputs)
+    FIDABBDFREE          IDABBDPrecFree
+    --------------       ---------------------------
+ 
+  In addition to the Fortran residual function FIDARESFUN, the
+  user-supplied functions used by this package, are listed below,
+  each with the corresponding interface function which calls it (and its
+  type within IDABBDPRE or IDA):
+
+   Fortran           IDA               Type
+   --------------    -----------       -----------------
+   FIDAGLOCFN        FIDAgloc          IDABBDLocalFn
+   FIDACOMMFN        FIDAcfn           IDABBDCommFn
+   FIDAJTSETUP(*)    FIDAJTSetup       IDASpilsJTSetupFn
+   FIDAJTIMES(*)     FIDAJtimes        IDASpilsJacTimesVecFn
+   --------------    -----------       -----------------
+   (*) = optional
+
+  Important notes on portability:
+
+  The names of all user-supplied routines here are fixed, in 
+  order to maximize portability for the resulting mixed-language 
+  program.
+
+  Additionally, the names of the interface functions, and the names of
+  the Fortran user routines called by them, appear as dummy names
+  which are mapped to actual values by a series of definitions in the
+  header file fidabbd.h.
+ 
+  ==============================================================================
+ 
+                Usage of the FIDA/FIDABBD Interface Packages
+ 
+  The usage of the combined interface packages FIDA and FIDABBD requires
+  calls to several interface functions, and a few different user-supplied
+  routines which define the problem to be solved and indirectly define
+  the preconditioner.  These function calls and user routines are
+  summarized separately below.
+ 
+  Some details are omitted, and the user is referred to the IDA user 
+  document for more complete information.
+ 
+  (1) User-supplied residual routine: FIDARESFUN
+
+      The user must in all cases supply the following Fortran routine
+
+        SUBROUTINE FIDARESFUN(T, Y, YP, R, IPAR, RPAR, IER)
+
+      It must set the R array to F(t,y,y'), the residual of the DAE 
+      system, as a function of T, Y and YP.
+
+      The arguments are:
+        T    -- scalar value of the independent variable [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state derivatives [realtype, input]
+        R    -- array containing DAE residuals [realtype, output]
+        IPAR -- array containing integer user data that was passed
+                to FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                  >0 if a recoverable error occurred,
+                  <0 if an unrecoverable error ocurred.
+ 
+  (2) User-supplied routines to define preconditoner: FIDAGLOCFN 
+      and FIDACOMMFN
+ 
+      The routines in the IDABBDPRE module provide a preconditioner matrix
+      for IDA that is block-diagonal with banded blocks.  The blocking
+      corresponds to the distribution of the dependent variable vectors y 
+      and y' among the processes.  Each preconditioner block is generated 
+      from the Jacobian of the local part (associated with the current 
+      process) of a given function G(t,y,y') approximating F(t,y,y').  The 
+      blocks are generated by a difference quotient scheme independently 
+      by each process, utilizing an assumed banded structure with given 
+      half-bandwidths.  A separate pair of half-bandwidths defines the 
+      band matrix retained.
+ 
+  (2.1) Local approximate function FIDAGLOCFN.
+
+      The user must supply a subroutine of the form
+
+        SUBROUTINE FIDAGLOCFN(NLOC, T, YLOC, YPLOC, GLOC, IPAR, RPAR, IER)
+
+      Computes the function G(t,y,y') which approximates the residual
+      function F(t,y,y').  This function is to be computed locally, i.e., 
+      without interprocess communication.  (The case where G is 
+      mathematically identical to F is allowed.)  
+
+
+      The arguments are:
+        NLOC -- local problem size [long int, input]
+        T    -- current time [realtype, input]
+        YLOC -- array containing local state variables 
+                [realtype, input]
+       YPLOC -- array containing local state variable derivatives
+                [realtype, input]
+        GLOC -- array containing local DAE residuals [realtype, output]
+        IPAR -- array containing integer user data that was passed
+                to FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                  >0 if a recoverable error occurred,
+                  <0 if an unrecoverable error ocurred.
+ 
+  (2.2) Communication function FIDACOMMF.
+
+      The user must also supply a subroutine of the form
+
+        SUBROUTINE FIDACOMMFN(NLOC, T, YLOC, YPLOC, IPAR, RPAR, IER)
+
+      Performs all interprocess communication necessary to evaluate the 
+      approximate residual function G described above.  It is expected to
+      save communicated data in  work space defined by the user, and made 
+      available to FIDAGLOCFN.  Each call to the FIDACOMMFN is preceded 
+      by a call to FIDARESFUN with the same (t,y,y') arguments.  Thus 
+      FIDACOMMFN can omit any communications done by FIDARESFUN if 
+      relevant to the evaluation of G.
+
+      The arguments are:
+        NLOC -- local problem size [long int, input]
+        T    -- current time [realtype, input]
+        YLOC -- array containing local state variables 
+                [realtype, input]
+        YPLOC -- array containing local state variable derivatives
+                [realtype, input]
+        IPAR -- array containing integer user data that was passed
+                to FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                  >0 if a recoverable error occurred,
+                  <0 if an unrecoverable error ocurred.
+
+ 
+  (3) Optional user-supplied Jacobian-vector setup and product 
+      functions: FIDAJTSETUP and FIDAJTIMSE
+
+      As an option, the user may supply a routine that computes the 
+      product of the system Jacobian J = dF/dy and a given vector v.  
+      If supplied, a 'setup' routine to prepare any user data 
+      structures must exist, and have the form:
+ 
+        SUBROUTINE FIDAJTSETUP(T, Y, YP, R, CJ, EWT, H, IPAR, RPAR, IER)
+
+      It must perform any relevant preparations for subsequent calls to 
+      the user-provided FIDAJTIMES routine (see below).  
+
+      The arguments are:
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives
+                [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        CJ   -- current value of scalar in Jacobian [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        H    -- current step size [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        IER  -- return flag [int, output]:
+                   0 if successful, 
+                   nonzero if an error.
+ 
+      The accompanying Jacobian matrix-vector product routine must 
+      have the following form:
+
+        SUBROUTINE FIDAJTIMES(T, Y, YP, R, V, FJV, CJ, EWT, H, 
+       1                      IPAR, RPAR, WK1, WK2, IER)
+
+      This routine must compute the product vector J*v, and store 
+      the product in FJV.  
+ 
+      The arguments are:
+        T    -- current time [realtype, input]
+        Y    -- array containing state variables [realtype, input]
+        YP   -- array containing state variable derivatives
+                [realtype, input]
+        R    -- array containing DAE residuals [realtype, input]
+        V    -- vector to multiply [realtype, input]
+        FJV  -- product vector [realtype, output]
+        CJ   -- current value of scalar in Jacobian [realtype, input]
+        EWT  -- array containing error weight vector [realtype, input]
+        H    -- current step size [realtype, input]
+        IPAR -- array containing integer user data that was passed to
+                FIDAMALLOC [long int, input]
+        RPAR -- array containing real user data that was passed to
+                FIDAMALLOC [realtype, input]
+        WK1, WK2 -- arrays containing temporary workspace of same size
+                as Y [realtype, input]
+        IER  -- return flag [int, output]:
+                    0 if successful, 
+                    nonzero if an error.
+ 
+  (4) Initialization:  FNVINITP, generic iterative linear solver initialization, 
+      FIDAMALLOC, FIDASPILSINIT, and FIDABBDINIT.
+ 
+  (4.1) To initialize the parallel machine environment, the user must make 
+      the following call:
+
+         CALL FNVINITP(COMM, 2, NLOCAL, NGLOBAL, IER)
+
+      where the second argument is an int containing the IDA
+      solver ID (2). The other arguments are:
+        COMM = the MPI communicator [int, input]
+        NLOCAL = local vector size on this processor 
+           [long int, input]
+        NGLOBAL = system size, and the global size of vectors 
+           (the sum of all values of NLOCAL) [long int, input]
+        IER = return completion flag [int, ouptut]. 
+                  0 = success, 
+                 -1 = failure.
+
+      NOTE: The COMM argument passed to the FNVINITP routine is only supported 
+      if the MPI implementation used to build SUNDIALS includes the MPI_Comm_f2c
+      function from the MPI-2 specification.  To check if the function is 
+      supported look for the line "#define SUNDIALS_MPI_COMM_F2C 1" in the 
+      sundials_config.h header file.
+ 
+ (4.2) To initialize a generic iterative linear solver structure for 
+      solving linear systems within the Newton solver, the user must make one 
+      of the following calls:
+
+          CALL FSUNPCGINIT(2, PRETYPE, MAXL, IER)
+          CALL FSUNSPBCGSINIT(2, PRETYPE, MAXL, IER)
+          CALL FSUNSPFGMRINIT(2, PRETYPE, MAXL, IER)
+          CALL FSUNSPGMRINIT(2, PRETYPE, MAXL, IER)
+          CALL FSUNSPTFQMRINIT(2, PRETYPE, MAXL, IER)
+
+      In each of these, one argument is an int containing the IDA solver 
+      ID (2). 
+
+      The other arguments are:
+
+        PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+           2=right, 3=both) [int, input]
+        MAXL = maximum Krylov subspace dimension [int, input]
+        IER = return completion flag [int, output]:
+	          0 = success, 
+		 -1 = failure.
+
+  (4.3) To set various problem and solution parameters and allocate
+      internal memory, make the following call:
+
+        CALL FIDAMALLOC(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR,
+       1                IOUT, ROUT, IPAR, RPAR, IER)
+
+      The arguments are:
+        T0    = initial value of t [realtype, input]
+        Y0    = array of initial conditions, y(t0) [realtype, input]
+        YP0   = value of y'(t0) [realtype, input]
+        IATOL = type for absolute tolerance ATOL [int, input]: 
+                  1 = scalar, 
+                  2 = array,
+                  3 = user-supplied function; the user must 
+                      supply a routine FIDAEWT to compute the 
+		      error weight vector.
+        RTOL  = scalar relative tolerance [realtype, input]
+        ATOL  = scalar/array absolute tolerance [realtype, input]
+        IOUT  = array of length at least 21 for integer optional 
+                inputs and outputs [long int, output]
+        ROUT  = array of length 6 for real optional inputs and 
+                outputs [realtype, output]
+	IPAR = array of user integer data [long int, in/out]
+	RPAR = array with user real data [realtype, in/out]
+	IER  = return completion flag [int, output]:
+                  0 = SUCCESS,
+                 -1 = failure (see printed message for details).
+ 
+      The optional outputs are:
+ 
+            LENRW   = IOUT( 1) -> IDAGetWorkSpace
+            LENIW   = IOUT( 2) -> IDAGetWorkSpace
+            NST     = IOUT( 3) -> IDAGetNumSteps
+            NRE     = IOUT( 4) -> IDAGetNumResEvals
+            NETF    = IOUT( 5) -> IDAGetNumErrTestFails
+            NCFN    = IOUT( 6) -> IDAGetNumNonlinSolvConvFails
+            NNI     = IOUT( 7) -> IDAGetNumNonlinSolvIters
+            NSETUPS = IOUT( 8) -> IDAGetNumLinSolvSetups
+            KLAST   = IOUT( 9) -> IDAGetLastOrder
+            KCUR    = IOUT(10) -> IDAGetCurrentOrder
+            NBCKTRK = IOUT(11) -> IDAGetNumBacktrackOps
+            NGE     = IOUT(12) -> IDAGetNumGEvals
+ 
+            HINUSED = ROUT( 1) -> IDAGetActualInitStep
+            HLAST   = ROUT( 2) -> IDAGetLastStep
+            HCUR    = ROUT( 3) -> IDAGetCurrentStep
+            TCUR    = ROUT( 4) -> IDAGetCurrentTime
+            TOLSFAC = ROUT( 5) -> IDAGetTolScaleFactor
+            UNITRND = ROUT( 6) -> UNIT_ROUNDOFF
+
+      The user data arrays IPAR and RPAR are passed unmodified to 
+      all subsequent calls to user-provided routines. Changes to
+      either array inside a user-provided routine will be 
+      propagated. Using these two arrays, the user can dispense 
+      with COMMON blocks to pass data betwen user-provided 
+      routines. 
+
+      If the user program includes the FIDAEWT routine for the 
+      evaluation of the error weights, the following call must be made
+
+         CALL FIDAEWTSET (FLAG, IER)
+
+      with FLAG = 1 to specify that FIDAEWT is provided.
+      The return flag IER is 0 if successful, and nonzero otherwise.
+ 
+  (4.4) Create the IDASPILS interface to attach the generic 
+     iterative linear solver to IDA, by making the following call:
+    
+       CALL FIDASPILSINIT(IER)
+
+     The arguments are:
+	IER = error return flag [int, output]: 
+	       0 = success; 
+	      <0 = an error occured
+ 
+  (4.5) To allocate memory and initialize data associated with the 
+      IDABBDPRE preconditioner, make the following call:
+
+        CALL FIDABBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, DQRELY, IER)
+
+      The arguments are:
+        NLOCAL = local vector size on this process 
+             [long int, input]
+        MUDQ = upper half-bandwidth to be used in the computation
+             of the local Jacobian blocks by difference 
+             quotients.  These may be smaller than the true 
+             half-bandwidths of the Jacobian of the local block 
+             of g, when smaller values may provide greater 
+             efficiency [long int, input]
+        MLDQ = lower half-bandwidth to be used in the computation
+             of the local Jacobian blocks by difference 
+             quotients [long int, input]
+        MU = upper half-bandwidth of the band matrix that is
+             retained as an approximation of the local Jacobian
+             block (may be smaller than MUDQ) [long int, input]
+        ML = lower half-bandwidth of the band matrix that is
+             retained as an approximation of the local Jacobian
+             block (may be smaller than MLDQ) [long int, input]
+        DQRELY = relative increment factor in y for difference 
+             quotients [realtype, input]
+                    0.0 = default (sqrt(unit roundoff))
+        IER = return completion flag [int, output]:
+                    0 = success
+                   <0 = an error occurred
+ 
+  (4.6) To specify whether the Krylov linear solver should use the 
+      supplied FIDAJTSETUP and FIDAJTIMES routines, or the internal 
+      finite difference approximation, make the call
+
+         CALL FIDASPILSSETJAC(FLAG, IER)
+
+      with the int FLAG=1 to specify that FIDAJTSETUP and FIDAJTIMES 
+      are provided (FLAG=0 specifies to use and internal finite 
+      difference approximation to this product).  The int return 
+      flag IER=0 if successful, and nonzero otherwise.
+ 
+  (5) Re-initialization: FIDAREINIT, FIDABBDREINIT
+
+      If a sequence of problems of the same size is being solved using 
+      the Krylov linear solver in combination with the IDABBDPRE 
+      preconditioner, then the IDA package can be reinitialized for 
+      the second and subsequent problems so as to avoid further memory 
+      allocation.  First, in place of the call to FIDAMALLOC, make the 
+      following call:
+
+        CALL FIDAREINIT(T0, Y0, YP0, IATOL, RTOL, ATOL, ID, CONSTR, IER)
+
+      The arguments have the same names and meanings as those of 
+      FIDAMALLOC.  FIDAREINIT performs the same initializations as 
+      FIDAMALLOC, but does no memory allocation for IDA data structures, 
+      using instead the existing internal memory created by the previous 
+      FIDAMALLOC call.  
+
+      Following the call to FIDAREINIT, if there is no change in any of 
+      the linear solver arguments, but the user wishes to modify the 
+      values of MUDQ, MLDQ or DQRELY from the previous call to 
+      FIDABBDINIT, then a user may call:
+
+       CALL FIDABBDREINIT(MUDQ, MLDQ, DQRELY, IER)
+
+      The arguments have the same names and meanings as those of 
+      FIDABBDINIT.
+
+      However, if there is a change in any of the linear solver 
+      arguments or other preconditioner arguments, then a call to
+      FSUNPCGINIT, FSUNSPBCGSINIT, FSUNSPFGMRINIT, FSUNSPGMRINIT, 
+      or FSUNSPTFQMRINIT is required; in this case the linear 
+      solver memory is reallocated.  Following this call, the 
+      IDASPILS interface must also be reconstructed using another
+      call to FIDASPILSINIT (interface memory is freed and 
+      reallocated), as well as a subsequent call to FIDABBDINIT.
+ 
+  (6) The solver: FIDASOLVE
+
+      To solve the DAE system, make the following call:
+
+        CALL FIDASOLVE(TOUT, TRET, Y, YP, ITASK, IER)
+
+      The arguments are:
+       TOUT = next value of t at which a solution is desired 
+           [realtype, input]
+       TRET = value of t reached by the solver [realtype, output]
+       Y = state variable array [realtype, output]
+       YP = state variable derivative array [realtype, output]
+       ITASK = task indicator [int, input]:
+                 1 = normal mode (overshoot TOUT and interpolate)
+                 2 = one-step mode (return after each internal 
+                     step taken)
+                 3 = normal tstop mode (like 1, but integration 
+                     never proceeds past TSTOP, which must be 
+                     specified through a call to FIDASETRIN using
+                     the key 'STOP_TIME')
+                 4 = one step tstop (like 2, but integration 
+                     never goes past TSTOP)
+       IER = completion flag [int, output]: 
+                  0 = success, 
+                  1 = tstop return, 
+                  2 = root return, 
+                  values -1 ... -10 are failure modes (see 
+                    IDA manual).
+     The current values of the optional outputs are immediately 
+     available in the IOUT and ROUT arrays.
+ 
+  (7) Optional outputs: FIDABBDOPT
+
+      Optional outputs specific to the IDASpils linear solver are 
+      available in IOUT(13)...IOUT(21)
+ 
+      To obtain the optional outputs associated with the IDABBDPRE 
+      module, make the following call:
+
+        CALL FIDABBDOPT (LENRWBBD, LENIWBBD, NGEBBD)
+
+      The arguments returned are:
+        LENRWBBD = length of real preconditioner work space, in 
+             realtype words (this size is local to the current 
+             process if run in parallel) [long int, output]
+        LENIWBBD = length of integer preconditioner work space, in 
+             integer words (this size is local to the current 
+             process if run in parallel) [long int, output]
+        NGEBBD   = number of G(t,y,y') evaluations (calls to 
+             FIDAGLOCFN) so far [long int, output]
+ 
+  (8) Memory freeing: FIDAFREE
+
+      To the free the internal memory created by the calls to 
+      FNVINITP, FIDAMALLOC, FIDASPILSINIT and FIDABBDINIT, make 
+      the following call:
+
+        CALL FIDAFREE
+ 
+==============================================================================*/
 
 #ifndef _FIDABBD_H
 #define _FIDABBD_H
@@ -326,12 +536,15 @@ void FIDA_BBDINIT(long int *Nloc, long int *mudq, long int *mldq,
 void FIDA_BBDREINIT(long int *Nloc, long int *mudq, long int *mldq,
 		    realtype *dqrely, int *ier);
 
-void FIDA_BBDOPT(long int *lenrwbbd, long int *leniwbbd, long int *ngebbd);
+void FIDA_BBDOPT(long int *lenrwbbd, long int *leniwbbd,
+                 long int *ngebbd);
 
 /* Prototypes: Functions Called by the IDABBD Module */
 
-int FIDAgloc(long int Nloc, realtype t, N_Vector yy, N_Vector yp, N_Vector gval, void *user_data);
-int FIDAcfn(long int Nloc, realtype t, N_Vector yy, N_Vector yp, void *user_data);
+int FIDAgloc(long int Nloc, realtype t, N_Vector yy, N_Vector yp,
+             N_Vector gval, void *user_data);
+int FIDAcfn(long int Nloc, realtype t, N_Vector yy, N_Vector yp,
+            void *user_data);
 
 #ifdef __cplusplus
 }
diff --git a/src/ida/fcmix/fidadense.c b/src/ida/fcmix/fidadense.c
index 897e1ed..5961489 100644
--- a/src/ida/fcmix/fidadense.c
+++ b/src/ida/fcmix/fidadense.c
@@ -1,24 +1,24 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Aaron Collier @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for IDA/IDADENSE, for the case
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Fortran/C interface routines for IDA/IDADLS, for the case
  * of a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -26,7 +26,8 @@
 #include "fida.h"     /* actual function names, prototypes and global vars.*/
 #include "ida_impl.h" /* definition of IDAMem type                         */
 
-#include <ida/ida_dense.h>
+#include <ida/ida_direct.h>
+#include <sunmatrix/sunmatrix_dense.h>
 
 /*************************************************/
 
@@ -34,13 +35,12 @@
 extern "C" {
 #endif
 
-  extern void FIDA_DJAC(long int*, 
-                        realtype*, realtype*, realtype*, realtype*,
-                        realtype*, 
-                        realtype*, realtype*, realtype*,
-                        long int*, realtype*,
-                        realtype*, realtype*, realtype*, 
-                        int*);
+  extern void FIDA_DJAC(long int* N, realtype* T, realtype* Y,
+                        realtype* YP, realtype* R, realtype* J, 
+                        realtype* CJ, realtype* EWT, realtype* H,
+                        long int* IPAR, realtype* RPAR,
+                        realtype* V1, realtype* V2, realtype* V3, 
+                        int* IER);
 
 #ifdef __cplusplus
 }
@@ -50,14 +50,9 @@ extern "C" {
 
 void FIDA_DENSESETJAC(int *flag, int *ier)
 {
-  *ier = 0;
-
   if (*flag == 0) {
-
-    *ier = IDADlsSetDenseJacFn(IDA_idamem, NULL);
-
+    *ier = IDADlsSetJacFn(IDA_idamem, NULL);
   } else {
-
     if (F2C_IDA_ewtvec == NULL) {
       F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec);
       if (F2C_IDA_ewtvec == NULL) {
@@ -65,22 +60,20 @@ void FIDA_DENSESETJAC(int *flag, int *ier)
         return;
       }
     }
-
-    *ier = IDADlsSetDenseJacFn(IDA_idamem, FIDADenseJac);
+    *ier = IDADlsSetJacFn(IDA_idamem, FIDADenseJac);
   }
-
   return;
 }
 
 /*************************************************/
 
-int FIDADenseJac(long int N, realtype t, realtype c_j, 
-		 N_Vector yy, N_Vector yp, N_Vector rr,
-                 DlsMat Jac, void *user_data,
+int FIDADenseJac(realtype t, realtype c_j, N_Vector yy, N_Vector yp,
+                 N_Vector rr, SUNMatrix J, void *user_data,
 		 N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
 {
   realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data;
   realtype h;
+  long int N;
   int ier;
   FIDAUserData IDA_userdata;
 
@@ -106,13 +99,14 @@ int FIDADenseJac(long int N, realtype t, realtype c_j,
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
 
-  jacdata = DENSE_COL(Jac,0);
+  N       = SUNDenseMatrix_Columns(J);
+  jacdata = SUNDenseMatrix_Column(J,0);
 
   IDA_userdata = (FIDAUserData) user_data;
 
   /* Call user-supplied routine*/
-  FIDA_DJAC(&N, &t, yy_data, yp_data, rr_data, jacdata,
-	    &c_j, ewtdata, &h, 
+  FIDA_DJAC(&N, &t, yy_data, yp_data, rr_data,
+            jacdata, &c_j, ewtdata, &h, 
             IDA_userdata->ipar, IDA_userdata->rpar,
             v1data, v2data, v3data, &ier);
 
diff --git a/src/ida/fcmix/fidaewt.c b/src/ida/fcmix/fidaewt.c
index f7a229a..cb0c43a 100644
--- a/src/ida/fcmix/fidaewt.c
+++ b/src/ida/fcmix/fidaewt.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Aaron Collier @ LLNL
  * -----------------------------------------------------------------
diff --git a/src/ida/fcmix/fidajtimes.c b/src/ida/fcmix/fidajtimes.c
index 360beae..2b2a4a0 100644
--- a/src/ida/fcmix/fidajtimes.c
+++ b/src/ida/fcmix/fidajtimes.c
@@ -1,26 +1,27 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*-----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Aaron Collier and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * The C function FIDAJtimes is to interface between the
- * IDASPILS modules and the user-supplied Jacobian-vector
- * product routine FIDAJTIMES. Note the use of the generic name
- * FIDA_JTIMES below.
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * The C functions FIDAJTSetup and FIDAJtimes are to interface 
+ * between the IDASPILS modules and the user-supplied 
+ * Jacobian-vector product routines FIDAJTSETUP and FIDAJTIMES. 
+ * Note the use of the generic names FIDA_JTSETUP and FIDA_JTIMES 
+ * below.
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -36,12 +37,16 @@
 extern "C" {
 #endif
 
-  extern void FIDA_JTIMES(realtype*, realtype*, realtype*,     /* T, Y, YP   */
-                          realtype*, realtype*, realtype*,     /* R, V, FJV  */
-                          realtype*, realtype*, realtype*,     /* CJ, EWT, H */
-                          long int*, realtype*,                /* IPAR, RPAR */
-                          realtype*, realtype*,                /* WK1, WK2   */
-                          int*);                               /* IER        */
+  extern void FIDA_JTSETUP(realtype *T, realtype *Y, realtype *YP,
+                           realtype *R, realtype *CJ, realtype *EWT, 
+                           realtype *H, long int *IPAR,
+                           realtype *RPAR, int *IER);
+
+  extern void FIDA_JTIMES(realtype *T, realtype *Y, realtype *YP,
+                          realtype *R, realtype *V, realtype *FJV,
+                          realtype *CJ, realtype *EWT, realtype *H,
+                          long int *IPAR, realtype *RPAR,
+                          realtype *WK1, realtype *WK2, int *IER);
 
 #ifdef __cplusplus
 }
@@ -49,16 +54,13 @@ extern "C" {
 
 /*************************************************/
 
+/* Fortran interface to C routine IDASpilsSetJacTimes; see 
+   fida.h for further information */
 void FIDA_SPILSSETJAC(int *flag, int *ier)
 {
-  *ier = 0;
-
   if (*flag == 0) {
-
-    *ier = IDASpilsSetJacTimesVecFn(IDA_idamem, NULL);
-
+    *ier = IDASpilsSetJacTimes(IDA_idamem, NULL, NULL);
   } else {
-
     if (F2C_IDA_ewtvec == NULL) {
       F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec);
       if (F2C_IDA_ewtvec == NULL) {
@@ -66,20 +68,52 @@ void FIDA_SPILSSETJAC(int *flag, int *ier)
         return;
       }
     }
-
-    *ier = IDASpilsSetJacTimesVecFn(IDA_idamem, FIDAJtimes);
-
+    *ier = IDASpilsSetJacTimes(IDA_idamem, FIDAJTSetup, FIDAJtimes);
   }
-
   return;
 }
 
 /*************************************************/
 
+/* C interface to user-supplied Fortran routine FIDAJTSETUP; see
+   fida.h for further information */
+int FIDAJTSetup(realtype t, N_Vector y, N_Vector yp, 
+                N_Vector r, realtype cj, void *user_data)
+{
+  realtype *ydata, *ypdata, *rdata, *ewtdata;
+  realtype h;
+  FIDAUserData IDA_userdata;
+  int ier = 0;
+  
+  /* Initialize all pointers to NULL */
+  ydata = ypdata = rdata = ewtdata = NULL;
+
+  /* NOTE: The user-supplied routine should set ier to an
+     appropriate value, but we preset the value to zero
+     (meaning SUCCESS) so the user need only reset the
+     value if an error occurred */
+  ier = 0;
+  
+  IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec);
+  IDAGetLastStep(IDA_idamem, &h);
+  ydata   = N_VGetArrayPointer(y);
+  ypdata  = N_VGetArrayPointer(yp);
+  rdata   = N_VGetArrayPointer(r);
+  ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec);
+
+  IDA_userdata = (FIDAUserData) user_data;
+ 
+  /* Call user-supplied routine */
+  FIDA_JTSETUP(&t, ydata, ypdata, rdata, &cj, ewtdata, &h,
+               IDA_userdata->ipar, IDA_userdata->rpar, &ier);
+  return(ier);
+}
+
+/* C interface to user-supplied Fortran routine FIDAJTIMES; see
+   fida.h for further information */
 int FIDAJtimes(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
-	       N_Vector v, N_Vector Jv,
-	       realtype c_j, void *user_data,
-	       N_Vector vtemp1, N_Vector vtemp2)
+	       N_Vector v, N_Vector Jv, realtype c_j,
+               void *user_data, N_Vector vtemp1, N_Vector vtemp2)
 {
   realtype *yy_data, *yp_data, *rr_data, *vdata, *Jvdata, *ewtdata;
   realtype *v1data, *v2data;
diff --git a/src/ida/fcmix/fidaklu.c b/src/ida/fcmix/fidaklu.c
deleted file mode 100644
index 4191bd6..0000000
--- a/src/ida/fcmix/fidaklu.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4654 $
- * $Date: 2016-02-17 20:12:58 -0800 (Wed, 17 Feb 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the Fortran interface to
- * the IDAKLU solver. See fida.h for usage.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "fida.h"
-#include "ida_impl.h"
-#include <ida/ida_klu.h>
- 
-/*
- * ----------------------------------------------------------------
- * Function : FIDA_KLU
- * ----------------------------------------------------------------
- */
-
-void FIDA_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier)
-{
-  *ier = IDAKLU(IDA_idamem, *neq, *nnz, *sparsetype);
-  IDAKLUSetOrdering(IDA_idamem, *ordering);
-  IDA_ls = IDA_LS_KLU;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FIDA_KLUReinit
- * ----------------------------------------------------------------
- */
-
-void FIDA_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier)
-{
-  *ier = IDAKLUReInit(IDA_idamem, *neq, *nnz, *reinit_type);
-}
-
diff --git a/src/ida/fcmix/fidalapack.c b/src/ida/fcmix/fidalapack.c
deleted file mode 100644
index 2faf2ea..0000000
--- a/src/ida/fcmix/fidalapack.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for IDA/IDALAPACK.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fida.h"     /* actual function names, prototypes and global vars.*/
-#include "ida_impl.h" /* definition of IDAMem type                         */
-
-#include <ida/ida_lapack.h>
-
-/*************************************************/
-
-void FIDA_LAPACKDENSE(int *neq, int *ier)
-{
-
-  *ier = 0;
-
-  *ier = IDALapackDense(IDA_idamem, *neq);
-
-  IDA_ls = IDA_LS_LAPACKDENSE;
-
-  return;
-}
-
-/*************************************************/
-
-void FIDA_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier)
-{
-
-  *ier = 0;
-
-  *ier = IDALapackBand(IDA_idamem, *neq, *mupper, *mlower);
-
-  IDA_ls = IDA_LS_LAPACKBAND;
-
-  return;
-}
-
-/*************************************************/
diff --git a/src/ida/fcmix/fidalapband.c b/src/ida/fcmix/fidalapband.c
deleted file mode 100644
index 4b6ecba..0000000
--- a/src/ida/fcmix/fidalapband.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for IDA/IDALAPACK, for the case of
- * a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fida.h"     /* function names, prototypes, global vars.*/
-#include "ida_impl.h" /* definition of IDAMem type               */
-
-#include <ida/ida_lapack.h>
-
-/*************************************************/
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-  extern void FIDA_BJAC(long int*, long int*, long int*, long int*,
-                        realtype*, realtype*, realtype*, realtype*,
-                        realtype*, realtype*, realtype*, realtype*,
-                        long int*, realtype*,
-                        realtype*, realtype*, realtype*, int*);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*************************************************/
-
-void FIDA_BANDSETJAC(int *flag, int *ier)
-{
-  *ier = 0;
-
-  if (*flag == 0) {
-    *ier = IDADlsSetBandJacFn(IDA_idamem, NULL);
-  } else {
-    if (F2C_IDA_ewtvec == NULL) {
-      F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec);
-      if (F2C_IDA_ewtvec == NULL) {
-        *ier = -1;
-        return;
-      }
-    }
-    *ier = IDADlsSetBandJacFn(IDA_idamem, FIDABandJac);
-  }
-
-  return;
-}
-
-/*************************************************/
-
-int FIDALapackBandJac(long int N, long int mupper, long int mlower,
-                      realtype t, realtype c_j, 
-                      N_Vector yy, N_Vector yp, N_Vector rr,
-                      DlsMat J, void *user_data,
-                      N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data;
-  realtype h;
-  long int eband;
-  int ier;
-  FIDAUserData IDA_userdata;
-
-  /* Initialize all pointers to NULL */
-  yy_data = yp_data = rr_data = jacdata = ewtdata = NULL;
-  v1data = v2data = v3data = NULL;
-
-  /* NOTE: The user-supplied routine should set ier to an
-     appropriate value, but we preset the value to zero
-     (meaning SUCCESS) so the user need only reset the
-     value if an error occurred */
-  ier = 0;
-
-  IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec);
-  IDAGetLastStep(IDA_idamem, &h);
-
-  /* Get pointers to vector data */
-  yy_data = N_VGetArrayPointer(yy);
-  yp_data = N_VGetArrayPointer(yp);
-  rr_data = N_VGetArrayPointer(rr);
-  ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec);
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-
-  eband = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
-
-  IDA_userdata = (FIDAUserData) user_data;
-
-  /* Call user-supplied routine */
-  FIDA_BJAC(&N, &mupper, &mlower, &eband, &t, yy_data, yp_data, rr_data,
-            &c_j, jacdata, ewtdata, &h, 
-            IDA_userdata->ipar, IDA_userdata->rpar,
-            v1data, v2data, v3data, &ier);
-
-  return(ier);
-}
diff --git a/src/ida/fcmix/fidalapdense.c b/src/ida/fcmix/fidalapdense.c
deleted file mode 100644
index 7cdbc5c..0000000
--- a/src/ida/fcmix/fidalapdense.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for IDA/IDALAPACK, for the case
- * of a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fida.h"     /* actual function names, prototypes and global vars.*/
-#include "ida_impl.h" /* definition of IDAMem type                         */
-
-#include <ida/ida_lapack.h>
-
-/*************************************************/
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-  extern void FIDA_DJAC(long int*, 
-                        realtype*, realtype*, realtype*, realtype*,
-                        realtype*, 
-                        realtype*, realtype*, realtype*,
-                        long int*, realtype*,
-                        realtype*, realtype*, realtype*, 
-                        int*);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*************************************************/
-
-void FIDA_LAPACKDENSESETJAC(int *flag, int *ier)
-{
-  *ier = 0;
-
-  if (*flag == 0) {
-    *ier = IDADlsSetDenseJacFn(IDA_idamem, NULL);
-  } else {
-    if (F2C_IDA_ewtvec == NULL) {
-      F2C_IDA_ewtvec = N_VClone(F2C_IDA_vec);
-      if (F2C_IDA_ewtvec == NULL) {
-        *ier = -1;
-        return;
-      }
-    }
-    *ier = IDADlsSetDenseJacFn(IDA_idamem, FIDADenseJac);
-  }
-
-  return;
-}
-
-/*************************************************/
-
-int FIDALapackDenseJac(long int N, realtype t, realtype c_j, 
-                       N_Vector yy, N_Vector yp, N_Vector rr,
-                       DlsMat Jac, void *user_data,
-                       N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
-{
-  realtype *yy_data, *yp_data, *rr_data, *jacdata, *ewtdata, *v1data, *v2data, *v3data;
-  realtype h;
-  int ier;
-  FIDAUserData IDA_userdata;
-
-  /* Initialize all pointers to NULL */
-  yy_data = yp_data = rr_data = jacdata = ewtdata = NULL;
-  v1data = v2data = v3data = NULL;
-
-  /* NOTE: The user-supplied routine should set ier to an
-     appropriate value, but we preset the value to zero
-     (meaning SUCCESS) so the user need only reset the
-     value if an error occurred */
-  ier = 0;
-
-  IDAGetErrWeights(IDA_idamem, F2C_IDA_ewtvec);
-  IDAGetLastStep(IDA_idamem, &h);
-
-  /* Get pointers to vector data */
-  yy_data = N_VGetArrayPointer(yy);
-  yp_data = N_VGetArrayPointer(yp);
-  rr_data = N_VGetArrayPointer(rr);
-  ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec);
-  v1data  = N_VGetArrayPointer(vtemp1);
-  v2data  = N_VGetArrayPointer(vtemp2);
-  v3data  = N_VGetArrayPointer(vtemp3);
-
-  jacdata = DENSE_COL(Jac,0);
-
-  IDA_userdata = (FIDAUserData) user_data;
-
-  /* Call user-supplied routine*/
-  FIDA_DJAC(&N, &t, yy_data, yp_data, rr_data, jacdata,
-            &c_j, ewtdata, &h, 
-            IDA_userdata->ipar, IDA_userdata->rpar,
-            v1data, v2data, v3data, &ier);
-
-  return(ier);
-}
diff --git a/src/ida/fcmix/fidapreco.c b/src/ida/fcmix/fidapreco.c
index 14b8b21..ec1f6d3 100644
--- a/src/ida/fcmix/fidapreco.c
+++ b/src/ida/fcmix/fidapreco.c
@@ -1,14 +1,10 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
+/* -----------------------------------------------------------------
  * Programmer(s): Aaron Collier and Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -18,8 +14,7 @@
  * The C function FIDAPSet is to interface between the IDASPILS
  * modules and the user-supplied preconditioner setup routine FIDAPSET.
  * Note the use of the generic name FIDA_PSET below.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,17 +30,15 @@
 extern "C" {
 #endif
 
-  extern void FIDA_PSET(realtype*, realtype*, realtype*, realtype*,
-                        realtype*, realtype*, realtype*, 
-                        long int*, realtype*,
-                        realtype*, realtype*, realtype*, 
-                        int*);
+  extern void FIDA_PSET(realtype* t,  realtype* yy,   realtype* yp,
+                        realtype* rr, realtype* c_j,  realtype* ewt,
+                        realtype* h,  long int* ipar, realtype* rpar,
+                        int* ier);
   
-  extern void FIDA_PSOL(realtype*, realtype*, realtype*, realtype*,
-                        realtype*, realtype*, realtype*, realtype*,
-                        realtype*, 
-                        long int*, realtype*,
-                        realtype*, int*);
+  extern void FIDA_PSOL(realtype* t,    realtype* yy,    realtype* yp,
+                        realtype* rr,   realtype* r,     realtype* z,
+                        realtype* c_j,  realtype* delta, realtype* ewt,
+                        long int* ipar, realtype* rpar,  int* ier);
 
 #ifdef __cplusplus
 }
@@ -81,17 +74,15 @@ void FIDA_SPILSSETPREC(int *flag, int *ier)
 /*************************************************/
 
 int FIDAPSet(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
-	     realtype c_j, void *user_data,
-	     N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
+	     realtype c_j, void *user_data)
 {
-  realtype *yy_data, *yp_data, *rr_data, *ewtdata, *v1data, *v2data, *v3data;
+  realtype *yy_data, *yp_data, *rr_data, *ewtdata;
   realtype h;
   int ier;
   FIDAUserData IDA_userdata;
 
   /* Initialize all pointers to NULL */
   yy_data = yp_data = rr_data = ewtdata = NULL;
-  v1data = v2data = v3data = NULL;
 
   /* NOTE: The user-supplied routine should set ier to an
      appropriate value, but we preset the value to zero
@@ -107,16 +98,12 @@ int FIDAPSet(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
   yp_data = N_VGetArrayPointer(yp);
   rr_data = N_VGetArrayPointer(rr);
   ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec);
-  v1data = N_VGetArrayPointer(vtemp1);
-  v2data = N_VGetArrayPointer(vtemp2);
-  v3data = N_VGetArrayPointer(vtemp3);
 
   IDA_userdata = (FIDAUserData) user_data;
 
   /* Call user-supplied routine */
   FIDA_PSET(&t, yy_data, yp_data, rr_data, &c_j, ewtdata, &h,
-            IDA_userdata->ipar, IDA_userdata->rpar,
-	    v1data, v2data, v3data, &ier);
+            IDA_userdata->ipar, IDA_userdata->rpar, &ier);
 
   return(ier);
 }
@@ -125,15 +112,14 @@ int FIDAPSet(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
 
 int FIDAPSol(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
 	     N_Vector rvec, N_Vector zvec,
-	     realtype c_j, realtype delta, void *user_data,
-	     N_Vector vtemp1)
+	     realtype c_j, realtype delta, void *user_data)
 {
-  realtype *yy_data, *yp_data, *rr_data, *ewtdata, *rdata, *zdata, *v1data;
+  realtype *yy_data, *yp_data, *rr_data, *ewtdata, *rdata, *zdata;
   int ier;
   FIDAUserData IDA_userdata;
 
   /* Initialize all pointers to NULL */
-  yy_data = yp_data = rr_data = ewtdata = zdata = v1data = NULL;
+  yy_data = yp_data = rr_data = ewtdata = zdata = NULL;
 
   /* NOTE: The user-supplied routine should set ier to an
      appropriate value, but we preset the value to zero
@@ -150,15 +136,13 @@ int FIDAPSol(realtype t, N_Vector yy, N_Vector yp, N_Vector rr,
   ewtdata = N_VGetArrayPointer(F2C_IDA_ewtvec);
   rdata   = N_VGetArrayPointer(rvec);
   zdata   = N_VGetArrayPointer(zvec);
-  v1data  = N_VGetArrayPointer(vtemp1);
 
   IDA_userdata = (FIDAUserData) user_data;
 
   /* Call user-supplied routine */
   FIDA_PSOL(&t, yy_data, yp_data, rr_data, rdata, zdata,
 	    &c_j, &delta, ewtdata, 
-            IDA_userdata->ipar, IDA_userdata->rpar,
-            v1data, &ier);
+            IDA_userdata->ipar, IDA_userdata->rpar, &ier);
 
   return(ier);
 }
diff --git a/src/ida/fcmix/fidaroot.c b/src/ida/fcmix/fidaroot.c
index 9d19b8c..00bd30d 100644
--- a/src/ida/fcmix/fidaroot.c
+++ b/src/ida/fcmix/fidaroot.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Aaron Collier and Alan C. Hindmarsh @ LLNL
  * -----------------------------------------------------------------
diff --git a/src/ida/fcmix/fidaroot.h b/src/ida/fcmix/fidaroot.h
index 73b71b2..3c7a167 100644
--- a/src/ida/fcmix/fidaroot.h
+++ b/src/ida/fcmix/fidaroot.h
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Aaron Collier and Alan C. Hindmarsh @ LLNL
  * -----------------------------------------------------------------
@@ -57,7 +54,7 @@
  *   Y  = dependent variable vector y  [input]
  *   YP = dependent variable derivative vector y'  [input]
  *   G  = function values g(t,y,y')  [output]
- *   IPAR, RPAR = user (integer and real) data [input/output]
+ *   IPAR, RPAR = user (long int and realtype) data [input/output]
  *   IER = return flag (set on 0 if successful, non-zero if an error occurred)
  *
  * 2. After calling FIDAMALLOC but prior to calling FIDASOLVE, the user must
diff --git a/src/ida/fcmix/fidasparse.c b/src/ida/fcmix/fidasparse.c
index 5253d47..a97d1af 100644
--- a/src/ida/fcmix/fidasparse.c
+++ b/src/ida/fcmix/fidasparse.c
@@ -1,28 +1,30 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4815 $
- * $Date: 2016-07-20 16:51:55 -0700 (Wed, 20 Jul 2016) $
- * -----------------------------------------------------------------
+/*-----------------------------------------------------------------
  * Programmer(s): Carol Woodward @ LLNL
  *                Daniel R. Reynolds @ SMU
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "fida.h"
 #include "ida_impl.h"
-#include <ida/ida_sparse.h>
+#include <ida/ida_direct.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+
+/*=============================================================*/
 
 /* Prototype of the Fortran routine */
  
@@ -31,10 +33,10 @@ extern "C" {
 #endif
  
 extern void FIDA_SPJAC(realtype *T, realtype *CJ, realtype *Y, 
-		       realtype *YP, realtype *R, int *N, int *NNZ, 
-		       realtype *JDATA, int *JRVALS, 
-		       int *JCPTRS, realtype *H, 
-		       long int *IPAR, realtype *RPAR, 
+		       realtype *YP, realtype *R, long int *N,
+                       long int *NNZ, realtype *JDATA,
+                       long int *JRVALS, long int *JCPTRS,
+                       realtype *H, long int *IPAR, realtype *RPAR, 
 		       realtype *V1, realtype *V2, 
 		       realtype *V3, int *ier);
  
@@ -48,7 +50,14 @@ extern void FIDA_SPJAC(realtype *T, realtype *CJ, realtype *Y,
    fida.h for further information */
 void FIDA_SPARSESETJAC(int *ier)
 {
-  *ier = IDASlsSetSparseJacFn(IDA_idamem, FIDASparseJac);
+#if defined(SUNDIALS_INT32_T)
+  IDAProcessError((IDAMem) IDA_idamem, IDA_ILL_INPUT, "IDA",
+                  "FIDASPARSESETJAC", 
+                  "Sparse Fortran users must configure SUNDIALS with 64-bit integers.");
+  *ier = 1;
+#else  
+  *ier = IDADlsSetJacFn(IDA_idamem, FIDASparseJac);
+#endif
 }
 
 /*=============================================================*/
@@ -56,25 +65,31 @@ void FIDA_SPARSESETJAC(int *ier)
 /* C interface to user-supplied Fortran routine FIDASPJAC; see 
    fida.h for additional information  */
 int FIDASparseJac(realtype t, realtype cj, N_Vector y, N_Vector yp,
-		  N_Vector fval, SlsMat J, void *user_data, 
+		  N_Vector fval, SUNMatrix J, void *user_data, 
 		  N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3)
 {
   int ier;
-  realtype *ydata, *ypdata, *rdata, *v1data, *v2data, *v3data;
+  realtype *ydata, *ypdata, *rdata, *v1data, *v2data, *v3data, *Jdata;
   realtype h;
+  long int NP, NNZ, *indexvals, *indexptrs; 
   FIDAUserData IDA_userdata;
 
   IDAGetLastStep(IDA_idamem, &h);
   ydata   = N_VGetArrayPointer(y);
   ypdata  = N_VGetArrayPointer(yp);
-  rdata  = N_VGetArrayPointer(fval);
+  rdata   = N_VGetArrayPointer(fval);
   v1data  = N_VGetArrayPointer(vtemp1);
   v2data  = N_VGetArrayPointer(vtemp2);
   v3data  = N_VGetArrayPointer(vtemp3);
   IDA_userdata = (FIDAUserData) user_data;
+  NP = SUNSparseMatrix_NP(J);
+  NNZ = SUNSparseMatrix_NNZ(J);
+  Jdata = SUNSparseMatrix_Data(J);
+  indexvals = SUNSparseMatrix_IndexValues(J);
+  indexptrs = SUNSparseMatrix_IndexPointers(J);
 
-  FIDA_SPJAC(&t, &cj, ydata, ypdata, rdata, &(J->NP), &(J->NNZ),
-	    J->data, J->indexvals, J->indexptrs, &h, 
+  FIDA_SPJAC(&t, &cj, ydata, ypdata, rdata, &NP, &NNZ,
+	    Jdata, indexvals, indexptrs, &h, 
 	    IDA_userdata->ipar, IDA_userdata->rpar, v1data, 
 	    v2data, v3data, &ier); 
   return(ier);
diff --git a/src/ida/fcmix/fidasuperlumt.c b/src/ida/fcmix/fidasuperlumt.c
deleted file mode 100644
index c3c9d71..0000000
--- a/src/ida/fcmix/fidasuperlumt.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4402 $
- * $Date: 2015-02-28 19:35:39 -0800 (Sat, 28 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the Fortran interface to
- * the IDASuperLUMT solver. See fida.h for usage.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "fida.h"
-#include "ida_impl.h"
-#include <ida/ida_superlumt.h>
- 
-/*
- * ----------------------------------------------------------------
- * Function : FIDA_SUPERLUMT
- * ----------------------------------------------------------------
- */
-
-void FIDA_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier)
-{
-  *ier = IDASuperLUMT(IDA_idamem, *nthreads, *neq, *nnz);
-  IDASuperLUMTSetOrdering(IDA_idamem, *ordering);
-  IDA_ls = IDA_LS_SUPERLUMT;
-}
-
-
diff --git a/src/ida/ida.c b/src/ida/ida.c
index 4dd8217..f21cdef 100644
--- a/src/ida/ida.c
+++ b/src/ida/ida.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4845 $
- * $Date: 2016-08-03 15:45:09 -0700 (Wed, 03 Aug 2016) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Alan Hindmarsh, Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -95,15 +92,6 @@
 
 /* 
  * =================================================================
- * MACRO DEFINITIONS
- * =================================================================
- */
-
-/* Macro: loop */
-#define loop for(;;)
-
-/* 
- * =================================================================
  * IDAS PRIVATE CONSTANTS
  * =================================================================
  */
@@ -317,7 +305,7 @@ void *IDACreate(void)
   IDA_mem->ida_res         = NULL;
   IDA_mem->ida_user_data   = NULL;
   IDA_mem->ida_itol        = IDA_NN;
-  IDA_mem->ida_user_efun   = FALSE;
+  IDA_mem->ida_user_efun   = SUNFALSE;
   IDA_mem->ida_efun        = NULL;
   IDA_mem->ida_edata       = NULL;
   IDA_mem->ida_ehfun       = IDAErrHandler;
@@ -331,11 +319,11 @@ void *IDACreate(void)
   IDA_mem->ida_maxnef      = MXNEF;
   IDA_mem->ida_maxncf      = MXNCF;
   IDA_mem->ida_maxcor      = MAXIT;
-  IDA_mem->ida_suppressalg = FALSE;
+  IDA_mem->ida_suppressalg = SUNFALSE;
   IDA_mem->ida_id          = NULL;
   IDA_mem->ida_constraints = NULL;
-  IDA_mem->ida_constraintsSet = FALSE;
-  IDA_mem->ida_tstopset    = FALSE;
+  IDA_mem->ida_constraintsSet = SUNFALSE;
+  IDA_mem->ida_tstopset    = SUNFALSE;
 
   /* set the saved value maxord_alloc */
   IDA_mem->ida_maxord_alloc = MAXORD_DEFAULT;
@@ -346,7 +334,7 @@ void *IDACreate(void)
   IDA_mem->ida_maxnj   = MAXNJ;
   IDA_mem->ida_maxnit  = MAXNI;
   IDA_mem->ida_maxbacks  = MAXBACKS;
-  IDA_mem->ida_lsoff   = FALSE;
+  IDA_mem->ida_lsoff   = SUNFALSE;
   IDA_mem->ida_steptol = SUNRpowerR(IDA_mem->ida_uround, TWOTHIRDS);
 
   /* Initialize lrw and liw */
@@ -354,10 +342,10 @@ void *IDACreate(void)
   IDA_mem->ida_liw = 38;
 
   /* No mallocs have been done yet */
-  IDA_mem->ida_VatolMallocDone = FALSE;
-  IDA_mem->ida_constraintsMallocDone = FALSE;
-  IDA_mem->ida_idMallocDone = FALSE;
-  IDA_mem->ida_MallocDone = FALSE;
+  IDA_mem->ida_VatolMallocDone = SUNFALSE;
+  IDA_mem->ida_constraintsMallocDone = SUNFALSE;
+  IDA_mem->ida_idMallocDone = SUNFALSE;
+  IDA_mem->ida_MallocDone = SUNFALSE;
 
   /* Return pointer to IDA memory block */
   return((void *)IDA_mem);
@@ -365,11 +353,6 @@ void *IDACreate(void)
 
 /*-----------------------------------------------------------------*/
 
-#define lrw   (IDA_mem->ida_lrw)
-#define liw   (IDA_mem->ida_liw)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDAInit
  *
@@ -384,7 +367,7 @@ int IDAInit(void *ida_mem, IDAResFn res,
 {
   IDAMem IDA_mem;
   booleantype nvectorOK, allocOK;
-  long int lrw1, liw1;
+  sunindextype lrw1, liw1;
 
   /* Check ida_mem */
 
@@ -490,22 +473,17 @@ int IDAInit(void *ida_mem, IDAResFn res,
 
   /* Initial setup not done yet */
 
-  IDA_mem->ida_SetupDone = FALSE;
+  IDA_mem->ida_SetupDone = SUNFALSE;
 
   /* Problem memory has been successfully allocated */
 
-  IDA_mem->ida_MallocDone = TRUE;
+  IDA_mem->ida_MallocDone = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
 
 /*-----------------------------------------------------------------*/
 
-#define lrw1 (IDA_mem->ida_lrw1)
-#define liw1 (IDA_mem->ida_liw1)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDAReInit
  *
@@ -535,7 +513,7 @@ int IDAReInit(void *ida_mem,
 
   /* Check if problem was malloc'ed */
   
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDAReInit", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -580,7 +558,7 @@ int IDAReInit(void *ida_mem,
 
   /* Initial setup not done yet */
 
-  IDA_mem->ida_SetupDone = FALSE;
+  IDA_mem->ida_SetupDone = SUNFALSE;
       
   /* Problem has been successfully re-initialized */
 
@@ -615,7 +593,7 @@ int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASStolerances", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -639,7 +617,7 @@ int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol)
 
   IDA_mem->ida_itol = IDA_SS;
 
-  IDA_mem->ida_user_efun = FALSE;
+  IDA_mem->ida_user_efun = SUNFALSE;
   IDA_mem->ida_efun = IDAEwtSet;
   IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup; */
 
@@ -657,7 +635,7 @@ int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASVtolerances", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -678,9 +656,9 @@ int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
   
   if ( !(IDA_mem->ida_VatolMallocDone) ) {
     IDA_mem->ida_Vatol = N_VClone(IDA_mem->ida_ewt);
-    lrw += lrw1;
-    liw += liw1;
-    IDA_mem->ida_VatolMallocDone = TRUE;
+    IDA_mem->ida_lrw += IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw += IDA_mem->ida_liw1;
+    IDA_mem->ida_VatolMallocDone = SUNTRUE;
   }
 
   IDA_mem->ida_rtol = reltol;
@@ -688,7 +666,7 @@ int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
 
   IDA_mem->ida_itol = IDA_SV;
 
-  IDA_mem->ida_user_efun = FALSE;
+  IDA_mem->ida_user_efun = SUNFALSE;
   IDA_mem->ida_efun = IDAEwtSet;
   IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup; */
 
@@ -706,14 +684,14 @@ int IDAWFtolerances(void *ida_mem, IDAEwtFn efun)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDAWFtolerances", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
 
   IDA_mem->ida_itol = IDA_WF;
 
-  IDA_mem->ida_user_efun = TRUE;
+  IDA_mem->ida_user_efun = SUNTRUE;
   IDA_mem->ida_efun = efun;
   IDA_mem->ida_edata = NULL; /* will be set to user_data in InitialSetup */ 
 
@@ -722,16 +700,6 @@ int IDAWFtolerances(void *ida_mem, IDAEwtFn efun)
 
 /*-----------------------------------------------------------------*/
 
-#define gfun    (IDA_mem->ida_gfun)
-#define glo     (IDA_mem->ida_glo)
-#define ghi     (IDA_mem->ida_ghi)
-#define grout   (IDA_mem->ida_grout)
-#define iroots  (IDA_mem->ida_iroots)
-#define rootdir (IDA_mem->ida_rootdir)
-#define gactive (IDA_mem->ida_gactive)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDARootInit
  *
@@ -761,15 +729,15 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
      currently held memory resources */
   if ((nrt != IDA_mem->ida_nrtfn) && (IDA_mem->ida_nrtfn > 0)) {
 
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); iroots = NULL;
-    free(gactive); gactive = NULL;
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
+    free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
+    free(IDA_mem->ida_gactive); IDA_mem->ida_gactive = NULL;
 
-    lrw -= 3 * (IDA_mem->ida_nrtfn);
-    liw -= 3 * (IDA_mem->ida_nrtfn);
+    IDA_mem->ida_lrw -= 3 * (IDA_mem->ida_nrtfn);
+    IDA_mem->ida_liw -= 3 * (IDA_mem->ida_nrtfn);
 
   }
 
@@ -777,7 +745,7 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
      zero and ida_gfun to NULL before returning */
   if (nrt == 0) {
     IDA_mem->ida_nrtfn = nrt;
-    gfun = NULL;
+    IDA_mem->ida_gfun = NULL;
     return(IDA_SUCCESS);
   }
 
@@ -787,23 +755,23 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
   /* If g != NULL then return as currently reserved memory resources
      will suffice */
   if (nrt == IDA_mem->ida_nrtfn) {
-    if (g != gfun) {
+    if (g != IDA_mem->ida_gfun) {
       if (g == NULL) {
-	free(glo); glo = NULL;
-	free(ghi); ghi = NULL;
-	free(grout); grout = NULL;
-	free(iroots); iroots = NULL;
-        free(rootdir); iroots = NULL;
-        free(gactive); gactive = NULL;
+	free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+	free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+	free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+	free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
+        free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
+        free(IDA_mem->ida_gactive); IDA_mem->ida_gactive = NULL;
 
-        lrw -= 3*nrt;
-        liw -= 3*nrt;
+        IDA_mem->ida_lrw -= 3*nrt;
+        IDA_mem->ida_liw -= 3*nrt;
 
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL);
         return(IDA_ILL_INPUT);
       }
       else {
-        gfun = g;
+        IDA_mem->ida_gfun = g;
         return(IDA_SUCCESS);
       }
     }
@@ -816,178 +784,78 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARootInit", MSG_ROOT_FUNC_NULL);
     return(IDA_ILL_INPUT);
   }
-  else gfun = g;
+  else IDA_mem->ida_gfun = g;
 
   /* Allocate necessary memory and return */
-  glo = NULL;
-  glo = (realtype *) malloc(nrt*sizeof(realtype));
-  if (glo == NULL) {
+  IDA_mem->ida_glo = NULL;
+  IDA_mem->ida_glo = (realtype *) malloc(nrt*sizeof(realtype));
+  if (IDA_mem->ida_glo == NULL) {
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  ghi = NULL;
-  ghi = (realtype *) malloc(nrt*sizeof(realtype));
-  if (ghi == NULL) {
-    free(glo); glo = NULL;
+  IDA_mem->ida_ghi = NULL;
+  IDA_mem->ida_ghi = (realtype *) malloc(nrt*sizeof(realtype));
+  if (IDA_mem->ida_ghi == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  grout = NULL;
-  grout = (realtype *) malloc(nrt*sizeof(realtype));
-  if (grout == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
+  IDA_mem->ida_grout = NULL;
+  IDA_mem->ida_grout = (realtype *) malloc(nrt*sizeof(realtype));
+  if (IDA_mem->ida_grout == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  iroots = NULL;
-  iroots = (int *) malloc(nrt*sizeof(int));
-  if (iroots == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
+  IDA_mem->ida_iroots = NULL;
+  IDA_mem->ida_iroots = (int *) malloc(nrt*sizeof(int));
+  if (IDA_mem->ida_iroots == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  rootdir = NULL;
-  rootdir = (int *) malloc(nrt*sizeof(int));
-  if (rootdir == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
+  IDA_mem->ida_rootdir = NULL;
+  IDA_mem->ida_rootdir = (int *) malloc(nrt*sizeof(int));
+  if (IDA_mem->ida_rootdir == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  gactive = NULL;
-  gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
-  if (gactive == NULL) {
-    free(glo); glo = NULL; 
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
+  IDA_mem->ida_gactive = NULL;
+  IDA_mem->ida_gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
+  if (IDA_mem->ida_gactive == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL; 
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
+    free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
   /* Set default values for rootdir (both directions) */
-  for(i=0; i<nrt; i++) rootdir[i] = 0;
+  for(i=0; i<nrt; i++) IDA_mem->ida_rootdir[i] = 0;
 
   /* Set default values for gactive (all active) */
-  for(i=0; i<nrt; i++) gactive[i] = TRUE;
+  for(i=0; i<nrt; i++) IDA_mem->ida_gactive[i] = SUNTRUE;
 
-  lrw += 3*nrt;
-  liw += 3*nrt;
+  IDA_mem->ida_lrw += 3*nrt;
+  IDA_mem->ida_liw += 3*nrt;
 
   return(IDA_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * readability constants
- * -----------------------------------------------------------------
- */
-
-#define res (IDA_mem->ida_res)
-#define y0  (IDA_mem->ida_y0)
-#define yp0 (IDA_mem->ida_yp0)
-
-#define itol  (IDA_mem->ida_itol)
-#define rtol  (IDA_mem->ida_rtol)
-#define Satol (IDA_mem->ida_Satol)
-#define Vatol (IDA_mem->ida_Vatol)
-#define efun  (IDA_mem->ida_efun)
-#define edata (IDA_mem->ida_edata)
-
-#define user_data   (IDA_mem->ida_user_data)
-#define maxord      (IDA_mem->ida_maxord)
-#define mxstep      (IDA_mem->ida_mxstep)
-#define hin         (IDA_mem->ida_hin)
-#define hmax_inv    (IDA_mem->ida_hmax_inv)
-#define tstop       (IDA_mem->ida_tstop)
-#define tstopset    (IDA_mem->ida_tstopset)
-#define epcon       (IDA_mem->ida_epcon)
-#define maxnef      (IDA_mem->ida_maxnef)
-#define maxncf      (IDA_mem->ida_maxncf)
-#define maxcor      (IDA_mem->ida_maxcor)
-#define suppressalg (IDA_mem->ida_suppressalg)
-#define id          (IDA_mem->ida_id)
-#define constraints (IDA_mem->ida_constraints)
-
-#define epiccon (IDA_mem->ida_epiccon)
-#define maxnh   (IDA_mem->ida_maxnh)
-#define maxnj   (IDA_mem->ida_maxnj)
-#define maxnit  (IDA_mem->ida_maxnit)
-#define lsoff   (IDA_mem->ida_lsoff)
-#define steptol (IDA_mem->ida_steptol)
-
-#define uround         (IDA_mem->ida_uround)  
-#define phi            (IDA_mem->ida_phi) 
-#define ewt            (IDA_mem->ida_ewt)  
-#define yy             (IDA_mem->ida_yy)
-#define yp             (IDA_mem->ida_yp)
-#define delta          (IDA_mem->ida_delta)
-#define mm             (IDA_mem->ida_mm)
-#define ee             (IDA_mem->ida_ee)
-#define savres         (IDA_mem->ida_savres)
-#define tempv1         (IDA_mem->ida_tempv1)
-#define tempv2         (IDA_mem->ida_tempv2) 
-#define kk             (IDA_mem->ida_kk)
-#define hh             (IDA_mem->ida_hh)
-#define h0u            (IDA_mem->ida_h0u)
-#define tn             (IDA_mem->ida_tn)
-#define tretlast       (IDA_mem->ida_tretlast)
-#define cj             (IDA_mem->ida_cj)
-#define cjold          (IDA_mem->ida_cjold)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define cjlast         (IDA_mem->ida_cjlast)
-#define nbacktr        (IDA_mem->ida_nbacktr)
-#define nst            (IDA_mem->ida_nst)
-#define nre            (IDA_mem->ida_nre)
-#define ncfn           (IDA_mem->ida_ncfn)
-#define netf           (IDA_mem->ida_netf)
-#define nni            (IDA_mem->ida_nni)
-#define nsetups        (IDA_mem->ida_nsetups)
-
-#define ns             (IDA_mem->ida_ns)
-#define linit          (IDA_mem->ida_linit)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve) 
-#define lperf          (IDA_mem->ida_lperf)
-#define lfree          (IDA_mem->ida_lfree) 
-#define lmem           (IDA_mem->ida_lmem) 
-#define knew           (IDA_mem->ida_knew)
-#define kused          (IDA_mem->ida_kused)          
-#define hused          (IDA_mem->ida_hused)         
-#define tolsf          (IDA_mem->ida_tolsf)      
-#define phase          (IDA_mem->ida_phase)
-#define epsNewt        (IDA_mem->ida_epsNewt)
-#define toldel         (IDA_mem->ida_toldel)
-#define ss             (IDA_mem->ida_ss)
-#define rr             (IDA_mem->ida_rr)
-#define psi            (IDA_mem->ida_psi)
-#define alpha          (IDA_mem->ida_alpha)
-#define beta           (IDA_mem->ida_beta)
-#define sigma          (IDA_mem->ida_sigma)
-#define gamma          (IDA_mem->ida_gamma)
-#define setupNonNull   (IDA_mem->ida_setupNonNull) 
-#define constraintsSet (IDA_mem->ida_constraintsSet)
-#define nrtfn          (IDA_mem->ida_nrtfn)
-#define tlo            (IDA_mem->ida_tlo)
-#define thi            (IDA_mem->ida_thi)
-#define toutc          (IDA_mem->ida_toutc)
-#define trout          (IDA_mem->ida_trout)
-#define ttol           (IDA_mem->ida_ttol)
-#define taskc          (IDA_mem->ida_taskc)
-#define irfnd          (IDA_mem->ida_irfnd)
-#define nge            (IDA_mem->ida_nge)
-
 /* 
  * -----------------------------------------------------------------
  * Main solver function
@@ -1051,7 +919,7 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
 
   /* Check if problem was malloc'ed */
   
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDASolve", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -1062,13 +930,13 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_YRET_NULL);
     return(IDA_ILL_INPUT);
   }
-  yy = yret;  
+  IDA_mem->ida_yy = yret;  
 
   if (ypret == NULL) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_YPRET_NULL);
     return(IDA_ILL_INPUT);
   }
-  yp = ypret;
+  IDA_mem->ida_yp = ypret;
   
   if (tret == NULL) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TRET_NULL);
@@ -1080,127 +948,132 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
     return(IDA_ILL_INPUT);
   }
   
-  if (itask == IDA_NORMAL) toutc = tout;
-  taskc = itask;
+  if (itask == IDA_NORMAL) IDA_mem->ida_toutc = tout;
+  IDA_mem->ida_taskc = itask;
 
-  if (nst == 0) {       /* This is the first call */
+  if (IDA_mem->ida_nst == 0) {       /* This is the first call */
 
     /* Check inputs to IDA for correctness and consistency */
 
-    if (IDA_mem->ida_SetupDone == FALSE) {
+    if (IDA_mem->ida_SetupDone == SUNFALSE) {
       ier = IDAInitialSetup(IDA_mem);
       if (ier != IDA_SUCCESS) return(IDA_ILL_INPUT);
-      IDA_mem->ida_SetupDone = TRUE;
+      IDA_mem->ida_SetupDone = SUNTRUE;
     }
 
     /* On first call, check for tout - tn too small, set initial hh,
        check for approach to tstop, and scale phi[1] by hh.
        Also check for zeros of root function g at and near t0.    */
 
-    tdist = SUNRabs(tout - tn);
+    tdist = SUNRabs(tout - IDA_mem->ida_tn);
     if (tdist == ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_CLOSE);
       return(IDA_ILL_INPUT);
     }
-    troundoff = TWO*uround*(SUNRabs(tn) + SUNRabs(tout));
+    troundoff = TWO * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(tout));
     if (tdist < troundoff) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_CLOSE);
       return(IDA_ILL_INPUT);
     }
 
-    hh = hin;
-    if ( (hh != ZERO) && ((tout-tn)*hh < ZERO) ) {
+    IDA_mem->ida_hh = IDA_mem->ida_hin;
+    if ( (IDA_mem->ida_hh != ZERO) && ((tout-IDA_mem->ida_tn)*IDA_mem->ida_hh < ZERO) ) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_HINIT);
       return(IDA_ILL_INPUT);
     }
 
-    if (hh == ZERO) {
-      hh = PT001*tdist;
-      ypnorm = IDAWrmsNorm(IDA_mem, phi[1], ewt, suppressalg);
-      if (ypnorm > HALF/hh) hh = HALF/ypnorm;
-      if (tout < tn) hh = -hh;
+    if (IDA_mem->ida_hh == ZERO) {
+      IDA_mem->ida_hh = PT001*tdist;
+      ypnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_phi[1],
+                           IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+      if (ypnorm > HALF/IDA_mem->ida_hh)
+        IDA_mem->ida_hh = HALF/ypnorm;
+      if (tout < IDA_mem->ida_tn)
+        IDA_mem->ida_hh = -IDA_mem->ida_hh;
     }
 
-    rh = SUNRabs(hh)*hmax_inv;
-    if (rh > ONE) hh /= rh;
+    rh = SUNRabs(IDA_mem->ida_hh)*IDA_mem->ida_hmax_inv;
+    if (rh > ONE) IDA_mem->ida_hh /= rh;
 
-    if (tstopset) {
-      if ( (tstop - tn)*hh <= ZERO) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+    if (IDA_mem->ida_tstopset) {
+      if ( (IDA_mem->ida_tstop - IDA_mem->ida_tn)*IDA_mem->ida_hh <= ZERO) {
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
         return(IDA_ILL_INPUT);
       }
-      if ( (tn + hh - tstop)*hh > ZERO) 
-        hh = (tstop - tn)*(ONE-FOUR*uround);
+      if ( (IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+        IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE-FOUR*IDA_mem->ida_uround);
     }
 
-    h0u = hh;
-    kk = 0; kused = 0;  /* set in case of an error return before a step */
+    IDA_mem->ida_h0u = IDA_mem->ida_hh;
+    IDA_mem->ida_kk = 0;
+    IDA_mem->ida_kused = 0;  /* set in case of an error return before a step */
 
     /* Check for exact zeros of the root functions at or near t0. */
-    if (nrtfn > 0) {
+    if (IDA_mem->ida_nrtfn > 0) {
       ier = IDARcheck1(IDA_mem);
       if (ier == IDA_RTFUNC_FAIL) {
-        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck1", MSG_RTFUNC_FAILED, tn);
+        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck1", MSG_RTFUNC_FAILED, IDA_mem->ida_tn);
         return(IDA_RTFUNC_FAIL);
       }
     }
 
-    N_VScale(hh, phi[1], phi[1]);  /* set phi[1] = hh*y' */
+    N_VScale(IDA_mem->ida_hh, IDA_mem->ida_phi[1], IDA_mem->ida_phi[1]);  /* set phi[1] = hh*y' */
 
     /* Set the convergence test constants epsNewt and toldel */
-    epsNewt = epcon;
-    toldel = PT0001 * epsNewt;
+    IDA_mem->ida_epsNewt = IDA_mem->ida_epcon;
+    IDA_mem->ida_toldel = PT0001 * IDA_mem->ida_epsNewt;
 
   } /* end of first-call block. */
 
   /* Call lperf function and set nstloc for later performance testing. */
 
-  if (lperf != NULL) lperf(IDA_mem, 0);
+  if (IDA_mem->ida_lperf != NULL)
+    IDA_mem->ida_lperf(IDA_mem, 0);
   nstloc = 0;
 
   /* If not the first call, perform all stopping tests. */
 
-  if (nst > 0) {
+  if (IDA_mem->ida_nst > 0) {
 
     /* First, check for a root in the last step taken, other than the
        last root found, if any.  If itask = IDA_ONE_STEP and y(tn) was not
        returned because of an intervening root, return y(tn) now.     */
 
-    if (nrtfn > 0) {
+    if (IDA_mem->ida_nrtfn > 0) {
 
-      irfndp = irfnd;
+      irfndp = IDA_mem->ida_irfnd;
       
       ier = IDARcheck2(IDA_mem);
 
       if (ier == CLOSERT) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARcheck2", MSG_CLOSE_ROOTS, tlo);
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDARcheck2", MSG_CLOSE_ROOTS, IDA_mem->ida_tlo);
         return(IDA_ILL_INPUT);
       } else if (ier == IDA_RTFUNC_FAIL) {
-        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck2", MSG_RTFUNC_FAILED, tlo);
+        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck2", MSG_RTFUNC_FAILED, IDA_mem->ida_tlo);
         return(IDA_RTFUNC_FAIL);
       } else if (ier == RTFOUND) {
-        tretlast = *tret = tlo;
+        IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tlo;
         return(IDA_ROOT_RETURN);
       }
 
       /* If tn is distinct from tretlast (within roundoff),
          check remaining interval for roots */
-      troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-      if ( SUNRabs(tn - tretlast) > troundoff ) {
+      troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+      if ( SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tretlast) > troundoff ) {
         ier = IDARcheck3(IDA_mem);
         if (ier == IDA_SUCCESS) {     /* no root found */
-          irfnd = 0;
+          IDA_mem->ida_irfnd = 0;
           if ((irfndp == 1) && (itask == IDA_ONE_STEP)) {
-            tretlast = *tret = tn;
-            ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+            IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tn;
+            ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
             return(IDA_SUCCESS);
           }
         } else if (ier == RTFOUND) {  /* a new root was found */
-          irfnd = 1;
-          tretlast = *tret = tlo;
+          IDA_mem->ida_irfnd = 1;
+          IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tlo;
           return(IDA_ROOT_RETURN);
         } else if (ier == IDA_RTFUNC_FAIL) {  /* g failed */
-          IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck3", MSG_RTFUNC_FAILED, tlo);
+          IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck3", MSG_RTFUNC_FAILED, IDA_mem->ida_tlo);
           return(IDA_RTFUNC_FAIL);
         }
       }
@@ -1216,37 +1089,39 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
 
   /* Looping point for internal steps. */
 
-  loop {
+  for(;;) {
    
     /* Check for too many steps taken. */
     
-    if ( (mxstep>0) && (nstloc >= mxstep) ) {
-      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_MAX_STEPS, tn);
+    if ( (IDA_mem->ida_mxstep>0) && (nstloc >= IDA_mem->ida_mxstep) ) {
+      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_MAX_STEPS, IDA_mem->ida_tn);
       istate = IDA_TOO_MUCH_WORK;
-      *tret = tretlast = tn;
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
       break; /* Here yy=yret and yp=ypret already have the current solution. */
     }
 
     /* Call lperf to generate warnings of poor performance. */
 
-    if (lperf != NULL) lperf(IDA_mem, 1);
+    if (IDA_mem->ida_lperf != NULL)
+      IDA_mem->ida_lperf(IDA_mem, 1);
 
     /* Reset and check ewt (if not first call). */
 
-    if (nst > 0) {
+    if (IDA_mem->ida_nst > 0) {
 
-      ier = efun(phi[0], ewt, edata);
+      ier = IDA_mem->ida_efun(IDA_mem->ida_phi[0], IDA_mem->ida_ewt,
+                              IDA_mem->ida_edata);
 
       if (ier != 0) {
 
-        if (itol == IDA_WF) 
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_FAIL, tn);
+        if (IDA_mem->ida_itol == IDA_WF) 
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_FAIL, IDA_mem->ida_tn);
         else
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_BAD, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_EWT_NOW_BAD, IDA_mem->ida_tn);
 	
         istate = IDA_ILL_INPUT;
-        ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
-        *tret = tretlast = tn;
+        ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
+        *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
         break;
 
       }
@@ -1255,14 +1130,15 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
     
     /* Check for too much accuracy requested. */
     
-    nrm = IDAWrmsNorm(IDA_mem, phi[0], ewt, suppressalg);
-    tolsf = uround * nrm;
-    if (tolsf > ONE) {
-      tolsf *= TEN;
-      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_MUCH_ACC, tn);
+    nrm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_phi[0], IDA_mem->ida_ewt,
+                      IDA_mem->ida_suppressalg);
+    IDA_mem->ida_tolsf = IDA_mem->ida_uround * nrm;
+    if (IDA_mem->ida_tolsf > ONE) {
+      IDA_mem->ida_tolsf *= TEN;
+      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_TOO_MUCH_ACC, IDA_mem->ida_tn);
       istate = IDA_TOO_MUCH_ACC;
-      *tret = tretlast = tn;
-      if (nst > 0) ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
+      if (IDA_mem->ida_nst > 0) ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
       break;
     }
 
@@ -1274,8 +1150,8 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
 
     if (sflag != IDA_SUCCESS) {
       istate = IDAHandleFailure(IDA_mem, sflag);
-      *tret = tretlast = tn;
-      ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
+      ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
       break;
     }
     
@@ -1285,17 +1161,17 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
 
     /* First check for root in the last step taken. */
 
-    if (nrtfn > 0) {
+    if (IDA_mem->ida_nrtfn > 0) {
 
       ier = IDARcheck3(IDA_mem);
 
       if (ier == RTFOUND) {  /* A new root was found */
-        irfnd = 1;
+        IDA_mem->ida_irfnd = 1;
         istate = IDA_ROOT_RETURN;
-        tretlast = *tret = tlo;
+        IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tlo;
         break;
       } else if (ier == IDA_RTFUNC_FAIL) { /* g failed */
-        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck3", MSG_RTFUNC_FAILED, tlo);
+        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDA", "IDARcheck3", MSG_RTFUNC_FAILED, IDA_mem->ida_tlo);
         istate = IDA_RTFUNC_FAIL;
         break;
       }
@@ -1305,11 +1181,11 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
        * as this may indicate a user error in the implementation
        * of the root function. */
 
-      if (nst==1) {
-        inactive_roots = FALSE;
-        for (ir=0; ir<nrtfn; ir++) { 
-          if (!gactive[ir]) {
-            inactive_roots = TRUE;
+      if (IDA_mem->ida_nst==1) {
+        inactive_roots = SUNFALSE;
+        for (ir=0; ir<IDA_mem->ida_nrtfn; ir++) { 
+          if (!IDA_mem->ida_gactive[ir]) {
+            inactive_roots = SUNTRUE;
             break;
           }
         }
@@ -1372,18 +1248,20 @@ int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
     return(IDA_BAD_DKY);
   }
   
-  if ((k < 0) || (k > kused)) {
+  if ((k < 0) || (k > IDA_mem->ida_kused)) {
     IDAProcessError(IDA_mem, IDA_BAD_K, "IDA", "IDAGetDky", MSG_BAD_K);
     return(IDA_BAD_K);
   }
 
   /* Check t for legality.  Here tn - hused is t_{n-1}. */
 
-  tfuzz = HUNDRED * uround * (SUNRabs(tn) + SUNRabs(hh));
-  if (hh < ZERO) tfuzz = - tfuzz;
-  tp = tn - hused - tfuzz;
-  if ((t - tp)*hh < ZERO) {
-    IDAProcessError(IDA_mem, IDA_BAD_T, "IDA", "IDAGetDky", MSG_BAD_T, t, tn-hused, tn);
+  tfuzz = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+  if (IDA_mem->ida_hh < ZERO)
+    tfuzz = - tfuzz;
+  tp = IDA_mem->ida_tn - IDA_mem->ida_hused - tfuzz;
+  if ((t - tp)*IDA_mem->ida_hh < ZERO) {
+    IDAProcessError(IDA_mem, IDA_BAD_T, "IDA", "IDAGetDky", MSG_BAD_T, t,
+                    IDA_mem->ida_tn-IDA_mem->ida_hused, IDA_mem->ida_tn);
     return(IDA_BAD_T);
   }
 
@@ -1393,7 +1271,7 @@ int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
     cjk_1[i] = 0;
   }
 
-  delt = t-tn;
+  delt = t-IDA_mem->ida_tn;
 
   for(i=0; i<=k; i++) {
 
@@ -1420,29 +1298,29 @@ int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
         c_i^(i) can be always updated since c_i^(i) = -----  --------  ... -----
                                                       psi_j  psi_{j-1}     psi_1
       */
-      cjk[i] = cjk[i-1]*i/psi[i-1];
-      psij_1 = psi[i-1];
+      cjk[i] = cjk[i-1]*i / IDA_mem->ida_psi[i-1];
+      psij_1 = IDA_mem->ida_psi[i-1];
     }
 
     /* update c_j^(i) */
 
     /*j does not need to go till kused */
-    for(j=i+1; j<=kused-k+i; j++) {
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) {
 
-      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / psi[j-1];      
-      psij_1 = psi[j-1];
+      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / IDA_mem->ida_psi[j-1];      
+      psij_1 = IDA_mem->ida_psi[j-1];
     }
 
     /* save existing c_j^(i)'s */
-    for(j=i+1; j<=kused-k+i; j++) cjk_1[j] = cjk[j];
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) cjk_1[j] = cjk[j];
   }
 
   /* Compute sum (c_j(t) * phi(t)) */
 
   N_VConst(ZERO, dky);
-  for(j=k; j<=kused; j++)
+  for(j=k; j<=IDA_mem->ida_kused; j++)
   {
-    N_VLinearSum(ONE, dky, cjk[j], phi[j], dky);
+    N_VLinearSum(ONE, dky, cjk[j], IDA_mem->ida_phi[j], dky);
   }
 
   return(IDA_SUCCESS);
@@ -1473,15 +1351,16 @@ void IDAFree(void **ida_mem)
   
   IDAFreeVectors(IDA_mem);
 
-  if (lfree != NULL) lfree(IDA_mem);
+  if (IDA_mem->ida_lfree != NULL)
+    IDA_mem->ida_lfree(IDA_mem);
 
-  if (nrtfn > 0) {
-    free(glo); glo = NULL; 
-    free(ghi);  ghi = NULL;
-    free(grout);  grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
-    free(gactive); gactive = NULL;
+  if (IDA_mem->ida_nrtfn > 0) {
+    free(IDA_mem->ida_glo);     IDA_mem->ida_glo = NULL; 
+    free(IDA_mem->ida_ghi);     IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout);   IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots);  IDA_mem->ida_iroots = NULL;
+    free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
+    free(IDA_mem->ida_gactive); IDA_mem->ida_gactive = NULL;
   }
 
   free(*ida_mem);
@@ -1498,7 +1377,7 @@ void IDAFree(void **ida_mem)
  * IDACheckNvector
  *
  * This routine checks if all required vector operations are present.
- * If any of them is missing it returns FALSE.
+ * If any of them is missing it returns SUNFALSE.
  */
 
 static booleantype IDACheckNvector(N_Vector tmpl)
@@ -1514,9 +1393,9 @@ static booleantype IDACheckNvector(N_Vector tmpl)
      (tmpl->ops->nvaddconst     == NULL) ||
      (tmpl->ops->nvwrmsnorm     == NULL) ||
      (tmpl->ops->nvmin          == NULL))
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 /* 
@@ -1531,8 +1410,8 @@ static booleantype IDACheckNvector(N_Vector tmpl)
  * This routine allocates the IDA vectors ewt, tempv1, tempv2, and
  * phi[0], ..., phi[maxord].
  * If all memory allocations are successful, IDAAllocVectors returns 
- * TRUE. Otherwise all allocated memory is freed and IDAAllocVectors 
- * returns FALSE.
+ * SUNTRUE. Otherwise all allocated memory is freed and IDAAllocVectors 
+ * returns SUNFALSE.
  * This routine also sets the optional outputs lrw and liw, which are
  * (respectively) the lengths of the real and integer work spaces
  * allocated here.
@@ -1544,66 +1423,66 @@ static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
 
   /* Allocate ewt, ee, delta, tempv1, tempv2 */
   
-  ewt = N_VClone(tmpl);
-  if (ewt == NULL) return(FALSE);
+  IDA_mem->ida_ewt = N_VClone(tmpl);
+  if (IDA_mem->ida_ewt == NULL) return(SUNFALSE);
 
-  ee = N_VClone(tmpl);
-  if (ee == NULL) {
-    N_VDestroy(ewt);
-    return(FALSE);
+  IDA_mem->ida_ee = N_VClone(tmpl);
+  if (IDA_mem->ida_ee == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    return(SUNFALSE);
   }
 
-  delta = N_VClone(tmpl);
-  if (delta == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(ee);
-    return(FALSE);
+  IDA_mem->ida_delta = N_VClone(tmpl);
+  if (IDA_mem->ida_delta == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    N_VDestroy(IDA_mem->ida_ee);
+    return(SUNFALSE);
   }
 
-  tempv1 = N_VClone(tmpl);
-  if (tempv1 == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(ee);
-    N_VDestroy(delta);
-    return(FALSE);
+  IDA_mem->ida_tempv1 = N_VClone(tmpl);
+  if (IDA_mem->ida_tempv1 == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    N_VDestroy(IDA_mem->ida_ee);
+    N_VDestroy(IDA_mem->ida_delta);
+    return(SUNFALSE);
   }
 
-  tempv2= N_VClone(tmpl);
-  if (tempv2 == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(ee);
-    N_VDestroy(delta);
-    N_VDestroy(tempv1);
-    return(FALSE);
+  IDA_mem->ida_tempv2= N_VClone(tmpl);
+  if (IDA_mem->ida_tempv2 == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    N_VDestroy(IDA_mem->ida_ee);
+    N_VDestroy(IDA_mem->ida_delta);
+    N_VDestroy(IDA_mem->ida_tempv1);
+    return(SUNFALSE);
   }
 
-  savres = tempv1;
+  IDA_mem->ida_savres = IDA_mem->ida_tempv1;
 
   /* Allocate phi[0] ... phi[maxord].  Make sure phi[2] and phi[3] are
   allocated (for use as temporary vectors), regardless of maxord.       */
 
-  maxcol = SUNMAX(maxord,3);
+  maxcol = SUNMAX(IDA_mem->ida_maxord,3);
   for (j=0; j <= maxcol; j++) {
-    phi[j] = N_VClone(tmpl);
-    if (phi[j] == NULL) {
-      N_VDestroy(ewt);
-      N_VDestroy(ee);
-      N_VDestroy(delta);
-      N_VDestroy(tempv1);
-      N_VDestroy(tempv2);
-      for (i=0; i < j; i++) N_VDestroy(phi[i]);
-      return(FALSE);
+    IDA_mem->ida_phi[j] = N_VClone(tmpl);
+    if (IDA_mem->ida_phi[j] == NULL) {
+      N_VDestroy(IDA_mem->ida_ewt);
+      N_VDestroy(IDA_mem->ida_ee);
+      N_VDestroy(IDA_mem->ida_delta);
+      N_VDestroy(IDA_mem->ida_tempv1);
+      N_VDestroy(IDA_mem->ida_tempv2);
+      for (i=0; i < j; i++) N_VDestroy(IDA_mem->ida_phi[i]);
+      return(SUNFALSE);
     }
   }
 
   /* Update solver workspace lengths  */
-  lrw += (maxcol + 6)*lrw1;
-  liw += (maxcol + 6)*liw1;
+  IDA_mem->ida_lrw += (maxcol + 6)*IDA_mem->ida_lrw1;
+  IDA_mem->ida_liw += (maxcol + 6)*IDA_mem->ida_liw1;
 
   /* Store the value of maxord used here */
-  IDA_mem->ida_maxord_alloc = maxord;
+  IDA_mem->ida_maxord_alloc = IDA_mem->ida_maxord;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -1616,33 +1495,33 @@ static void IDAFreeVectors(IDAMem IDA_mem)
 {
   int j, maxcol;
   
-  N_VDestroy(ewt);
-  N_VDestroy(ee);
-  N_VDestroy(delta);
-  N_VDestroy(tempv1);
-  N_VDestroy(tempv2);
+  N_VDestroy(IDA_mem->ida_ewt);
+  N_VDestroy(IDA_mem->ida_ee);
+  N_VDestroy(IDA_mem->ida_delta);
+  N_VDestroy(IDA_mem->ida_tempv1);
+  N_VDestroy(IDA_mem->ida_tempv2);
   maxcol = SUNMAX(IDA_mem->ida_maxord_alloc,3);
-  for(j=0; j <= maxcol; j++) N_VDestroy(phi[j]);
+  for(j=0; j <= maxcol; j++) N_VDestroy(IDA_mem->ida_phi[j]);
 
-  lrw -= (maxcol + 6)*lrw1;
-  liw -= (maxcol + 6)*liw1;
+  IDA_mem->ida_lrw -= (maxcol + 6)*IDA_mem->ida_lrw1;
+  IDA_mem->ida_liw -= (maxcol + 6)*IDA_mem->ida_liw1;
 
   if (IDA_mem->ida_VatolMallocDone) {
-    N_VDestroy(Vatol);
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(IDA_mem->ida_Vatol);
+    IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw -= IDA_mem->ida_liw1;
   }
 
   if (IDA_mem->ida_constraintsMallocDone) {
-    N_VDestroy(constraints);
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(IDA_mem->ida_constraints);
+    IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw -= IDA_mem->ida_liw1;
   }
 
   if (IDA_mem->ida_idMallocDone) {
-    N_VDestroy(id);
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(IDA_mem->ida_id);
+    IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw -= IDA_mem->ida_liw1;
   }
 
 }
@@ -1671,32 +1550,33 @@ int IDAInitialSetup(IDAMem IDA_mem)
   int ier;
 
   /* Test for more vector operations, depending on options */
-  if (suppressalg)
-    if (phi[0]->ops->nvwrmsnormmask == NULL) {
+  if (IDA_mem->ida_suppressalg)
+    if (IDA_mem->ida_phi[0]->ops->nvwrmsnormmask == NULL) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_BAD_NVECTOR);
       return(IDA_ILL_INPUT);
   }
 
   /* Test id vector for legality */
-  if (suppressalg && (id==NULL)){ 
+  if (IDA_mem->ida_suppressalg && (IDA_mem->ida_id==NULL)){ 
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_MISSING_ID);
     return(IDA_ILL_INPUT); 
   }
 
   /* Did the user specify tolerances? */
-  if (itol == IDA_NN) {
+  if (IDA_mem->ida_itol == IDA_NN) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_NO_TOLS);
     return(IDA_ILL_INPUT);
   }
 
   /* Set data for efun */
-  if (IDA_mem->ida_user_efun) edata = user_data;
-  else                        edata = IDA_mem;
+  if (IDA_mem->ida_user_efun) IDA_mem->ida_edata = IDA_mem->ida_user_data;
+  else                        IDA_mem->ida_edata = IDA_mem;
 
   /* Initial error weight vector */
-  ier = efun(phi[0], ewt, edata);
+  ier = IDA_mem->ida_efun(IDA_mem->ida_phi[0], IDA_mem->ida_ewt,
+                          IDA_mem->ida_edata);
   if (ier != 0) {
-    if (itol == IDA_WF) 
+    if (IDA_mem->ida_itol == IDA_WF) 
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_FAIL_EWT);
     else
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_BAD_EWT);
@@ -1704,8 +1584,8 @@ int IDAInitialSetup(IDAMem IDA_mem)
   }
 
   /* Check to see if y0 satisfies constraints. */
-  if (constraintsSet) {
-    conOK = N_VConstrMask(constraints, phi[0], tempv2);
+  if (IDA_mem->ida_constraintsSet) {
+    conOK = N_VConstrMask(IDA_mem->ida_constraints, IDA_mem->ida_phi[0], IDA_mem->ida_tempv2);
     if (!conOK) { 
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_Y0_FAIL_CONSTR);
       return(IDA_ILL_INPUT); 
@@ -1713,13 +1593,13 @@ int IDAInitialSetup(IDAMem IDA_mem)
   }
 
   /* Check that lsolve exists and call linit function if it exists. */
-  if (lsolve == NULL) {
+  if (IDA_mem->ida_lsolve == NULL) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_LSOLVE_NULL);
     return(IDA_ILL_INPUT);
   }
 
-  if (linit != NULL) {
-    ier = linit(IDA_mem);
+  if (IDA_mem->ida_linit != NULL) {
+    ier = IDA_mem->ida_linit(IDA_mem);
     if (ier != 0) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDAInitialSetup", MSG_LINIT_FAIL);
       return(IDA_LINIT_FAIL);
@@ -1755,7 +1635,7 @@ int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
   IDA_mem = (IDAMem) data;
 
-  switch(itol) {
+  switch(IDA_mem->ida_itol) {
   case IDA_SS: 
     flag = IDAEwtSetSS(IDA_mem, ycur, weight); 
     break;
@@ -1778,11 +1658,11 @@ int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
 static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv1);
-  N_VScale(rtol, tempv1, tempv1);
-  N_VAddConst(tempv1, Satol, tempv1);
-  if (N_VMin(tempv1) <= ZERO) return(-1);
-  N_VInv(tempv1, weight);
+  N_VAbs(ycur, IDA_mem->ida_tempv1);
+  N_VScale(IDA_mem->ida_rtol, IDA_mem->ida_tempv1, IDA_mem->ida_tempv1);
+  N_VAddConst(IDA_mem->ida_tempv1, IDA_mem->ida_Satol, IDA_mem->ida_tempv1);
+  if (N_VMin(IDA_mem->ida_tempv1) <= ZERO) return(-1);
+  N_VInv(IDA_mem->ida_tempv1, weight);
   return(0);
 }
 
@@ -1798,10 +1678,11 @@ static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight)
 
 static int IDAEwtSetSV(IDAMem IDA_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv1);
-  N_VLinearSum(rtol, tempv1, ONE, Vatol, tempv1);
-  if (N_VMin(tempv1) <= ZERO) return(-1);
-  N_VInv(tempv1, weight);
+  N_VAbs(ycur, IDA_mem->ida_tempv1);
+  N_VLinearSum(IDA_mem->ida_rtol, IDA_mem->ida_tempv1, ONE,
+               IDA_mem->ida_Vatol, IDA_mem->ida_tempv1);
+  if (N_VMin(IDA_mem->ida_tempv1) <= ZERO) return(-1);
+  N_VInv(IDA_mem->ida_tempv1, weight);
   return(0);
 }
 
@@ -1838,84 +1719,84 @@ static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret,
     
   case IDA_NORMAL:
 
-    if (tstopset) {
+    if (IDA_mem->ida_tstopset) {
       /* Test for tn past tstop, tn = tretlast, tn past tout, tn near tstop. */
-      if ( (tn - tstop)*hh > ZERO) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+      if ( (IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) {
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
         return(IDA_ILL_INPUT);
       }
     }
 
     /* Test for tout = tretlast, and for tn past tout. */
-    if (tout == tretlast) {
-      *tret = tretlast = tout;
+    if (tout == IDA_mem->ida_tretlast) {
+      *tret = IDA_mem->ida_tretlast = tout;
       return(IDA_SUCCESS);
     }
-    if ((tn - tout)*hh >= ZERO) {
+    if ((IDA_mem->ida_tn - tout)*IDA_mem->ida_hh >= ZERO) {
       ier = IDAGetSolution(IDA_mem, tout, yret, ypret);
       if (ier != IDA_SUCCESS) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TOUT, tout);
         return(IDA_ILL_INPUT);
       }
-      *tret = tretlast = tout;
+      *tret = IDA_mem->ida_tretlast = tout;
       return(IDA_SUCCESS);
     }
 
-    if (tstopset) {
-      troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-      if (SUNRabs(tn - tstop) <= troundoff) {
-        ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+    if (IDA_mem->ida_tstopset) {
+      troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+      if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+        ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
         if (ier != IDA_SUCCESS) {
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
           return(IDA_ILL_INPUT);
         }
-        *tret = tretlast = tstop;
-        tstopset = FALSE;
+        *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+        IDA_mem->ida_tstopset = SUNFALSE;
         return(IDA_TSTOP_RETURN);
       }
-      if ((tn + hh - tstop)*hh > ZERO) 
-        hh = (tstop - tn)*(ONE-FOUR*uround);
+      if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+        IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
     }
 
     return(CONTINUE_STEPS);
     
   case IDA_ONE_STEP:
 
-    if (tstopset) {
+    if (IDA_mem->ida_tstopset) {
       /* Test for tn past tstop, tn past tretlast, and tn near tstop. */
-      if ((tn - tstop)*hh > ZERO) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+      if ((IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) {
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
         return(IDA_ILL_INPUT);
       }
     }
 
     /* Test for tn past tretlast. */
-    if ((tn - tretlast)*hh > ZERO) {
-      ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
-      *tret = tretlast = tn;
+    if ((IDA_mem->ida_tn - IDA_mem->ida_tretlast)*IDA_mem->ida_hh > ZERO) {
+      ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
       return(IDA_SUCCESS);
     }
 
-    if (tstopset) {
-      troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-      if (SUNRabs(tn - tstop) <= troundoff) {
-        ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+    if (IDA_mem->ida_tstopset) {
+      troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+      if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+        ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
         if (ier != IDA_SUCCESS) {
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
           return(IDA_ILL_INPUT);
         }
-        *tret = tretlast = tstop;
-        tstopset = FALSE;
+        *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+        IDA_mem->ida_tstopset = SUNFALSE;
         return(IDA_TSTOP_RETURN);
       }
-      if ((tn + hh - tstop)*hh > ZERO) 
-        hh = (tstop - tn)*(ONE-FOUR*uround);
+      if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+        IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
     }
 
     return(CONTINUE_STEPS);
         
   }
-  return(IDA_ILL_INPUT);
+  return(IDA_ILL_INPUT);  /* This return should never happen. */
 }
 
 /*
@@ -1928,6 +1809,7 @@ static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret,
  *  CONTINUE_STEPS     if no stop conditions were found
  *  IDA_SUCCESS        for a normal return to the user
  *  IDA_TSTOP_RETURN   for a tstop-reached return to the user
+ *  IDA_ILL_INPUT      for an illegal-input return to the user
  *
  * In the two cases with tstop, this routine may reset the stepsize hh
  * to cause the next step to reach tstop exactly.
@@ -1950,47 +1832,47 @@ static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret,
     case IDA_NORMAL:  
 
       /* Test for tn past tout. */
-      if ((tn - tout)*hh >= ZERO) {
+      if ((IDA_mem->ida_tn - tout)*IDA_mem->ida_hh >= ZERO) {
         /* ier = */ IDAGetSolution(IDA_mem, tout, yret, ypret);
-        *tret = tretlast = tout;
+        *tret = IDA_mem->ida_tretlast = tout;
         return(IDA_SUCCESS);
       }
 
-      if (tstopset) {
+      if (IDA_mem->ida_tstopset) {
         /* Test for tn at tstop and for tn near tstop */
-        troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-        if (SUNRabs(tn - tstop) <= troundoff) {
-          /* ier = */ IDAGetSolution(IDA_mem, tstop, yret, ypret);
-          *tret = tretlast = tstop;
-          tstopset = FALSE;
+        troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+        if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+          /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
+          *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+          IDA_mem->ida_tstopset = SUNFALSE;
           return(IDA_TSTOP_RETURN);
         }
-        if ((tn + hh - tstop)*hh > ZERO) 
-          hh = (tstop - tn)*(ONE-FOUR*uround);
+        if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+          IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
       }
 
       return(CONTINUE_STEPS);
 
     case IDA_ONE_STEP:
 
-      if (tstopset) {
+      if (IDA_mem->ida_tstopset) {
         /* Test for tn at tstop and for tn near tstop */
-        troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-        if (SUNRabs(tn - tstop) <= troundoff) {
-          /* ier = */ IDAGetSolution(IDA_mem, tstop, yret, ypret);
-          *tret = tretlast = tstop;
-          tstopset = FALSE;
+        troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+        if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+          /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
+          *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+          IDA_mem->ida_tstopset = SUNFALSE;
           return(IDA_TSTOP_RETURN);
         }
-        if ((tn + hh - tstop)*hh > ZERO) 
-          hh = (tstop - tn)*(ONE-FOUR*uround);
+        if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+          IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
       }
 
-      *tret = tretlast = tn;
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
       return(IDA_SUCCESS);
 
   }
-  return IDA_ILL_INPUT;
+  return IDA_ILL_INPUT;  /* This return should never happen. */
 }
 
 /* 
@@ -2013,36 +1895,36 @@ static int IDAHandleFailure(IDAMem IDA_mem, int sflag)
   switch (sflag) {
 
     case IDA_ERR_FAIL:
-      IDAProcessError(IDA_mem, IDA_ERR_FAIL, "IDA", "IDASolve", MSG_ERR_FAILS, tn, hh);
+      IDAProcessError(IDA_mem, IDA_ERR_FAIL, "IDA", "IDASolve", MSG_ERR_FAILS, IDA_mem->ida_tn, IDA_mem->ida_hh);
       return(IDA_ERR_FAIL);
 
     case IDA_CONV_FAIL:
-      IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDASolve", MSG_CONV_FAILS, tn, hh);
+      IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDA", "IDASolve", MSG_CONV_FAILS, IDA_mem->ida_tn, IDA_mem->ida_hh);
       return(IDA_CONV_FAIL);
 
     case IDA_LSETUP_FAIL:  
-      IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDA", "IDASolve", MSG_SETUP_FAILED, tn);
+      IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDA", "IDASolve", MSG_SETUP_FAILED, IDA_mem->ida_tn);
       return(IDA_LSETUP_FAIL);
 
     case IDA_LSOLVE_FAIL: 
-      IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDA", "IDASolve", MSG_SOLVE_FAILED, tn);
+      IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDA", "IDASolve", MSG_SOLVE_FAILED, IDA_mem->ida_tn);
       return(IDA_LSOLVE_FAIL);
 
     case IDA_REP_RES_ERR:
-      IDAProcessError(IDA_mem, IDA_REP_RES_ERR, "IDA", "IDASolve", MSG_REP_RES_ERR, tn);
+      IDAProcessError(IDA_mem, IDA_REP_RES_ERR, "IDA", "IDASolve", MSG_REP_RES_ERR, IDA_mem->ida_tn);
       return(IDA_REP_RES_ERR);
 
     case IDA_RES_FAIL: 
-      IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDA", "IDASolve", MSG_RES_NONRECOV, tn);
+      IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDA", "IDASolve", MSG_RES_NONRECOV, IDA_mem->ida_tn);
       return(IDA_RES_FAIL);
 
     case IDA_CONSTR_FAIL: 
-      IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDA", "IDASolve", MSG_FAILED_CONSTR, tn);
+      IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDA", "IDASolve", MSG_FAILED_CONSTR, IDA_mem->ida_tn);
       return(IDA_CONSTR_FAIL);
 
   }
 
-  return (IDA_UNRECOGNISED_ERROR);
+  return (IDA_UNRECOGNISED_ERROR);   /* This return should never happen */
 }
 
 /* 
@@ -2096,9 +1978,9 @@ static int IDAHandleFailure(IDAMem IDA_mem, int sflag)
  *       order for the problem, maxord, plus 1.
  *
  *       Return values are:
- *       IDA_SUCCESS   IDA_RES_FAIL        LSETUP_ERROR_NONRECVR       
+ *       IDA_SUCCESS   IDA_RES_FAIL      LSETUP_ERROR_NONRECVR       
  *                     IDA_LSOLVE_FAIL   IDA_ERR_FAIL            
- *                     IDA_CONSTR_FAIL               IDA_CONV_FAIL          
+ *                     IDA_CONSTR_FAIL   IDA_CONV_FAIL          
  *                     IDA_REP_RES_ERR            
  */
 
@@ -2109,17 +1991,17 @@ static int IDAStep(IDAMem IDA_mem)
   int ncf, nef;
   int nflag, kflag;
 
-  saved_t = tn;
+  saved_t = IDA_mem->ida_tn;
   ncf = nef = 0;
 
-  if (nst == ZERO){
-    kk = 1;
-    kused = 0;
-    hused = ZERO;
-    psi[0] = hh;
-    cj = ONE/hh;
-    phase = 0;
-    ns = 0;
+  if (IDA_mem->ida_nst == ZERO){
+    IDA_mem->ida_kk = 1;
+    IDA_mem->ida_kused = 0;
+    IDA_mem->ida_hused = ZERO;
+    IDA_mem->ida_psi[0] = IDA_mem->ida_hh;
+    IDA_mem->ida_cj = ONE/IDA_mem->ida_hh;
+    IDA_mem->ida_phase = 0;
+    IDA_mem->ida_ns = 0;
   }
 
   /* To prevent 'unintialized variable' warnings */
@@ -2128,7 +2010,7 @@ static int IDAStep(IDAMem IDA_mem)
 
   /* Looping point for attempts to take a step */
 
-  loop {  
+  for(;;) {  
 
     /*-----------------------
       Set method coefficients
@@ -2142,9 +2024,10 @@ static int IDAStep(IDAMem IDA_mem)
       If tn is past tstop (by roundoff), reset it to tstop.
       -----------------------------------------------------*/
     
-    tn = tn + hh;
-    if (tstopset) {
-      if ((tn - tstop)*hh > ZERO) tn = tstop;
+    IDA_mem->ida_tn = IDA_mem->ida_tn + IDA_mem->ida_hh;
+    if (IDA_mem->ida_tstopset) {
+      if ((IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO)
+        IDA_mem->ida_tn = IDA_mem->ida_tstop;
     }
 
     /*-----------------------
@@ -2164,13 +2047,14 @@ static int IDAStep(IDAMem IDA_mem)
       /* restore and decide what to do */
       IDARestore(IDA_mem, saved_t);
       kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1, 
-                             &ncfn, &ncf, &netf, &nef);
+                             &(IDA_mem->ida_ncfn), &ncf,
+                             &(IDA_mem->ida_netf), &nef);
 
       /* exit on nonrecoverable failure */ 
       if (kflag != PREDICT_AGAIN) return(kflag);
 
       /* recoverable error; predict again */
-      if(nst==0) IDAReset(IDA_mem);
+      if(IDA_mem->ida_nst==0) IDAReset(IDA_mem);
       continue;
 
     }
@@ -2196,7 +2080,7 @@ static int IDAStep(IDAMem IDA_mem)
            returns either PREDICT_AGAIN or IDA_SUCCESS
    */
 
-  N_VScale(ck, ee, ee);
+  N_VScale(ck, IDA_mem->ida_ee, IDA_mem->ida_ee);
 
   return(IDA_SUCCESS);
 }
@@ -2219,45 +2103,47 @@ static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck)
 
   /* Set coefficients for the current stepsize h */
 
-  if (hh != hused || kk != kused) ns = 0;
-  ns = SUNMIN(ns+1,kused+2);
-  if (kk+1 >= ns){
-    beta[0] = ONE;
-    alpha[0] = ONE;
-    temp1 = hh;
-    gamma[0] = ZERO;
-    sigma[0] = ONE;
-    for(i=1;i<=kk;i++){
-      temp2 = psi[i-1];
-      psi[i-1] = temp1;
-      beta[i] = beta[i-1] * psi[i-1] / temp2;
-      temp1 = temp2 + hh;
-      alpha[i] = hh / temp1;
-      sigma[i] = i * sigma[i-1] * alpha[i]; 
-      gamma[i] = gamma[i-1] + alpha[i-1] / hh;
+  if (IDA_mem->ida_hh != IDA_mem->ida_hused || IDA_mem->ida_kk != IDA_mem->ida_kused)
+    IDA_mem->ida_ns = 0;
+  IDA_mem->ida_ns = SUNMIN(IDA_mem->ida_ns+1, IDA_mem->ida_kused+2);
+  if (IDA_mem->ida_kk + 1 >= IDA_mem->ida_ns) {
+    IDA_mem->ida_beta[0] = ONE;
+    IDA_mem->ida_alpha[0] = ONE;
+    temp1 = IDA_mem->ida_hh;
+    IDA_mem->ida_gamma[0] = ZERO;
+    IDA_mem->ida_sigma[0] = ONE;
+    for(i=1; i<=IDA_mem->ida_kk; i++){
+      temp2 = IDA_mem->ida_psi[i-1];
+      IDA_mem->ida_psi[i-1] = temp1;
+      IDA_mem->ida_beta[i] = IDA_mem->ida_beta[i-1] * IDA_mem->ida_psi[i-1] / temp2;
+      temp1 = temp2 + IDA_mem->ida_hh;
+      IDA_mem->ida_alpha[i] = IDA_mem->ida_hh / temp1;
+      IDA_mem->ida_sigma[i] = i * IDA_mem->ida_sigma[i-1] * IDA_mem->ida_alpha[i]; 
+      IDA_mem->ida_gamma[i] = IDA_mem->ida_gamma[i-1] + IDA_mem->ida_alpha[i-1] / IDA_mem->ida_hh;
    }
-    psi[kk] = temp1;
+    IDA_mem->ida_psi[IDA_mem->ida_kk] = temp1;
   }
   /* compute alphas, alpha0 */
   alphas = ZERO;
   alpha0 = ZERO;
-  for(i=0;i<kk;i++){
+  for(i=0; i<IDA_mem->ida_kk ;i++){
     alphas = alphas - ONE/(i+1);
-    alpha0 = alpha0 - alpha[i];
+    alpha0 = alpha0 - IDA_mem->ida_alpha[i];
   }
 
   /* compute leading coefficient cj  */
-  cjlast = cj;
-  cj = -alphas/hh;
+  IDA_mem->ida_cjlast = IDA_mem->ida_cj;
+  IDA_mem->ida_cj = -alphas/IDA_mem->ida_hh;
   
   /* compute variable stepsize error coefficient ck */
 
-  *ck = SUNRabs(alpha[kk] + alphas - alpha0);
-  *ck = SUNMAX(*ck, alpha[kk]);
+  *ck = SUNRabs(IDA_mem->ida_alpha[IDA_mem->ida_kk] + alphas - alpha0);
+  *ck = SUNMAX(*ck, IDA_mem->ida_alpha[IDA_mem->ida_kk]);
 
  /* change phi to phi-star  */
 
-  for(i=ns;i<=kk;i++) N_VScale(beta[i], phi[i], phi[i]);
+  for(i=IDA_mem->ida_ns; i<=IDA_mem->ida_kk; i++)
+    N_VScale(IDA_mem->ida_beta[i], IDA_mem->ida_phi[i], IDA_mem->ida_phi[i]);
 
 }
 
@@ -2293,49 +2179,52 @@ static int IDANls(IDAMem IDA_mem)
   realtype temp1, temp2, vnorm;
   N_Vector tempv3;
 
-  callSetup = FALSE;
+  callSetup = SUNFALSE;
 
   /* Initialize if the first time called */
 
-  if (nst == 0){
-    cjold = cj;
-    ss = TWENTY;
-    if (setupNonNull) callSetup = TRUE;
+  if (IDA_mem->ida_nst == 0){
+    IDA_mem->ida_cjold = IDA_mem->ida_cj;
+    IDA_mem->ida_ss = TWENTY;
+    if (IDA_mem->ida_lsetup) callSetup = SUNTRUE;
   }
 
-  mm = tempv2;
-  tempv3 = ee;
+  IDA_mem->ida_mm = IDA_mem->ida_tempv2;
+  tempv3 = IDA_mem->ida_ee;
 
   /* Decide if lsetup is to be called */
 
-  if (setupNonNull){
-    cjratio = cj / cjold;
+  if (IDA_mem->ida_lsetup) {
+    IDA_mem->ida_cjratio = IDA_mem->ida_cj / IDA_mem->ida_cjold;
     temp1 = (ONE - XRATE) / (ONE + XRATE);
     temp2 = ONE/temp1;
-    {if (cjratio < temp1 || cjratio > temp2) callSetup = TRUE;}
-    {if (cj != cjlast) ss=HUNDRED;}
+    {if (IDA_mem->ida_cjratio < temp1 || IDA_mem->ida_cjratio > temp2) callSetup = SUNTRUE;}
+    {if (IDA_mem->ida_cj != IDA_mem->ida_cjlast) IDA_mem->ida_ss=HUNDRED;}
   }
 
   /* Begin the main loop. This loop is traversed at most twice. 
      The second pass only occurs when the first pass had a recoverable
      failure with old Jacobian data */
-  loop{
+  for(;;){
 
     /* Compute predicted values for yy and yp, and compute residual there. */
     IDAPredict(IDA_mem);
 
-    retval = res(tn, yy, yp, delta, user_data);
-    nre++;
+    retval = IDA_mem->ida_res(IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                              IDA_mem->ida_delta, IDA_mem->ida_user_data);
+    IDA_mem->ida_nre++;
     if (retval < 0) return(IDA_RES_FAIL);
     if (retval > 0) return(IDA_RES_RECVR);
 
     /* If indicated, call linear solver setup function and reset parameters. */
     if (callSetup){
-      nsetups++;
-      retval = lsetup(IDA_mem, yy, yp, delta, tempv1, tempv2, tempv3);
-      cjold = cj;
-      cjratio = ONE;
-      ss = TWENTY;
+      IDA_mem->ida_nsetups++;
+      retval = IDA_mem->ida_lsetup(IDA_mem, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                                   IDA_mem->ida_delta, IDA_mem->ida_tempv1,
+                                   IDA_mem->ida_tempv2, tempv3);
+      IDA_mem->ida_cjold = IDA_mem->ida_cj;
+      IDA_mem->ida_cjratio = ONE;
+      IDA_mem->ida_ss = TWENTY;
       if (retval < 0) return(IDA_LSETUP_FAIL);
       if (retval > 0) return(IDA_LSETUP_RECVR);
     }
@@ -2346,10 +2235,10 @@ static int IDANls(IDAMem IDA_mem)
 
     /* Retry the current step on recoverable failure with old Jacobian data. */
 
-    tryAgain = (retval>0)&&(setupNonNull) &&(!callSetup);
+    tryAgain = (retval>0) && (IDA_mem->ida_lsetup) && (!callSetup);
 
     if (tryAgain){
-      callSetup = TRUE;
+      callSetup = SUNTRUE;
       continue;
     }
     else break;
@@ -2360,31 +2249,39 @@ static int IDANls(IDAMem IDA_mem)
 
   /* If otherwise successful, check and enforce inequality constraints. */
 
-  if (constraintsSet){  /* Check constraints and get mask vector mm, 
-                          set where constraints failed */
-    constraintsPassed = N_VConstrMask(constraints,yy,mm);
+  if (IDA_mem->ida_constraintsSet){  /* Check constraints and get mask vector mm, 
+                                        set where constraints failed */
+    constraintsPassed = N_VConstrMask(IDA_mem->ida_constraints,
+                                      IDA_mem->ida_yy, IDA_mem->ida_mm);
     if (constraintsPassed) return(IDA_SUCCESS);
     else {
-      N_VCompare(ONEPT5, constraints, tempv1);  
+      N_VCompare(ONEPT5, IDA_mem->ida_constraints, IDA_mem->ida_tempv1);  
       /* a , where a[i] =1. when |c[i]| = 2 ,  c the vector of constraints */
-      N_VProd(tempv1, constraints, tempv1);       /* a * c */
-      N_VDiv(tempv1, ewt, tempv1);                /* a * c * wt */
-      N_VLinearSum(ONE, yy, -PT1, tempv1, tempv1);/* y - 0.1 * a * c * wt */
-      N_VProd(tempv1, mm, tempv1);               /*  v = mm*(y-.1*a*c*wt) */
-      vnorm = IDAWrmsNorm(IDA_mem, tempv1, ewt, FALSE); /*  ||v|| */
+      N_VProd(IDA_mem->ida_tempv1, IDA_mem->ida_constraints,
+              IDA_mem->ida_tempv1);                            /* a * c */
+      N_VDiv(IDA_mem->ida_tempv1, IDA_mem->ida_ewt,
+             IDA_mem->ida_tempv1);                             /* a * c * wt */
+      N_VLinearSum(ONE, IDA_mem->ida_yy, -PT1,
+                   IDA_mem->ida_tempv1, IDA_mem->ida_tempv1);  /* y - 0.1 * a * c * wt */
+      N_VProd(IDA_mem->ida_tempv1, IDA_mem->ida_mm,
+              IDA_mem->ida_tempv1);                            /*  v = mm*(y-.1*a*c*wt) */
+      vnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_tempv1,
+                          IDA_mem->ida_ewt, SUNFALSE);            /*  ||v|| */
       
       /* If vector v of constraint corrections is small
          in norm, correct and accept this step */      
-      if (vnorm <= epsNewt){  
-        N_VLinearSum(ONE, ee, -ONE, tempv1, ee);  /* ee <- ee - v */
+      if (vnorm <= IDA_mem->ida_epsNewt){  
+        N_VLinearSum(ONE, IDA_mem->ida_ee, -ONE,
+                     IDA_mem->ida_tempv1, IDA_mem->ida_ee);    /* ee <- ee - v */
         return(IDA_SUCCESS);
       }
       else {
         /* Constraints not met -- reduce h by computing rr = h'/h */
-        N_VLinearSum(ONE, phi[0], -ONE, yy, tempv1);
-        N_VProd(mm, tempv1, tempv1);
-        rr = PT9*N_VMinQuotient(phi[0], tempv1);
-        rr = SUNMAX(rr,PT1);
+        N_VLinearSum(ONE, IDA_mem->ida_phi[0], -ONE, IDA_mem->ida_yy,
+                     IDA_mem->ida_tempv1);
+        N_VProd(IDA_mem->ida_mm, IDA_mem->ida_tempv1, IDA_mem->ida_tempv1);
+        IDA_mem->ida_rr = PT9*N_VMinQuotient(IDA_mem->ida_phi[0], IDA_mem->ida_tempv1);
+        IDA_mem->ida_rr = SUNMAX(IDA_mem->ida_rr,PT1);
         return(IDA_CONSTR_RECVR);
       }
     }
@@ -2403,12 +2300,14 @@ static void IDAPredict(IDAMem IDA_mem)
 {
   int j;
 
-  N_VScale(ONE, phi[0], yy);
-  N_VConst(ZERO, yp);
+  N_VScale(ONE, IDA_mem->ida_phi[0], IDA_mem->ida_yy);
+  N_VConst(ZERO, IDA_mem->ida_yp);
   
-  for(j=1; j<=kk; j++) {
-    N_VLinearSum(ONE,      phi[j], ONE, yy, yy);
-    N_VLinearSum(gamma[j], phi[j], ONE, yp, yp);
+  for(j=1; j<=IDA_mem->ida_kk; j++) {
+    N_VLinearSum(ONE,      IDA_mem->ida_phi[j], ONE,
+                 IDA_mem->ida_yy, IDA_mem->ida_yy);
+    N_VLinearSum(IDA_mem->ida_gamma[j], IDA_mem->ida_phi[j], ONE,
+                 IDA_mem->ida_yp, IDA_mem->ida_yp);
   }
 }
 
@@ -2438,51 +2337,54 @@ static int IDANewtonIter(IDAMem IDA_mem)
 
   /* Initialize counter mnewt and cumulative correction vector ee. */
   mnewt = 0;
-  N_VConst(ZERO, ee);
+  N_VConst(ZERO, IDA_mem->ida_ee);
 
   /* Initialize oldnrm to avoid compiler warning message */
   oldnrm = ZERO;
 
   /* Looping point for Newton iteration.  Break out on any error. */
-  loop {
+  for(;;) {
 
-    nni++;
+    IDA_mem->ida_nni++;
 
     /* Save a copy of the residual vector in savres. */
-    N_VScale(ONE, delta, savres);
+    N_VScale(ONE, IDA_mem->ida_delta, IDA_mem->ida_savres);
 
     /* Call the lsolve function to get correction vector delta. */
-    retval = lsolve(IDA_mem, delta, ewt, yy, yp, savres); 
+    retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delta,
+                                 IDA_mem->ida_ewt, IDA_mem->ida_yy,
+                                 IDA_mem->ida_yp, IDA_mem->ida_savres); 
     if (retval < 0) return(IDA_LSOLVE_FAIL);
     if (retval > 0) return(IDA_LSOLVE_RECVR);
 
     /* Apply delta to yy, yp, and ee, and get norm(delta). */
-    N_VLinearSum(ONE, yy, -ONE, delta, yy);
-    N_VLinearSum(ONE, ee, -ONE, delta, ee);
-    N_VLinearSum(ONE, yp, -cj,  delta, yp);
-    delnrm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE);
+    N_VLinearSum(ONE, IDA_mem->ida_yy, -ONE, IDA_mem->ida_delta, IDA_mem->ida_yy);
+    N_VLinearSum(ONE, IDA_mem->ida_ee, -ONE, IDA_mem->ida_delta, IDA_mem->ida_ee);
+    N_VLinearSum(ONE, IDA_mem->ida_yp, -IDA_mem->ida_cj,  IDA_mem->ida_delta, IDA_mem->ida_yp);
+    delnrm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, SUNFALSE);
 
     /* Test for convergence, first directly, then with rate estimate. */
 
     if (mnewt == 0){ 
        oldnrm = delnrm;
-       if (delnrm <= toldel) return(IDA_SUCCESS);
+       if (delnrm <= IDA_mem->ida_toldel) return(IDA_SUCCESS);
     }
     else {
       rate = SUNRpowerR( delnrm/oldnrm, ONE/mnewt );
       if (rate > RATEMAX) return(IDA_NCONV_RECVR); 
-      ss = rate/(ONE - rate);
+      IDA_mem->ida_ss = rate/(ONE - rate);
     }
 
-    if (ss*delnrm <= epsNewt) return(IDA_SUCCESS);
+    if (IDA_mem->ida_ss*delnrm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
 
     /* Not yet converged.  Increment mnewt and test for max allowed. */
     mnewt++;
-    if (mnewt >= maxcor) {retval = IDA_NCONV_RECVR; break;}
+    if (mnewt >= IDA_mem->ida_maxcor) {retval = IDA_NCONV_RECVR; break;}
 
     /* Call res for new residual and check error flag from res. */
-    retval = res(tn, yy, yp, delta, user_data);
-    nre++;
+    retval = IDA_mem->ida_res(IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                              IDA_mem->ida_delta, IDA_mem->ida_user_data);
+    IDA_mem->ida_nre++;
     if (retval < 0) return(IDA_RES_FAIL);
     if (retval > 0) return(IDA_RES_RECVR);
 
@@ -2519,35 +2421,40 @@ static int IDATestError(IDAMem IDA_mem, realtype ck,
   realtype terr_k, terr_km1, terr_km2;      /* local truncation error norms */
 
   /* Compute error for order k. */
-  enorm_k = IDAWrmsNorm(IDA_mem, ee, ewt, suppressalg);
-  *err_k = sigma[kk] * enorm_k;
-  terr_k = (kk+1) * (*err_k);
+  enorm_k = IDAWrmsNorm(IDA_mem, IDA_mem->ida_ee, IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+  *err_k = IDA_mem->ida_sigma[IDA_mem->ida_kk] * enorm_k;
+  terr_k = (IDA_mem->ida_kk + 1) * (*err_k);
 
-  knew = kk;
+  IDA_mem->ida_knew = IDA_mem->ida_kk;
 
-  if ( kk > 1 ) {
+  if ( IDA_mem->ida_kk > 1 ) {
 
     /* Compute error at order k-1 */
-    N_VLinearSum(ONE, phi[kk], ONE, ee, delta);
-    enorm_km1 = IDAWrmsNorm(IDA_mem, delta, ewt, suppressalg);
-    *err_km1 = sigma[kk-1] * enorm_km1;
-    terr_km1 = kk * (*err_km1);
+    N_VLinearSum(ONE, IDA_mem->ida_phi[IDA_mem->ida_kk], ONE, IDA_mem->ida_ee, IDA_mem->ida_delta);
+    enorm_km1 = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta,
+                            IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+    *err_km1 = IDA_mem->ida_sigma[IDA_mem->ida_kk - 1] * enorm_km1;
+    terr_km1 = IDA_mem->ida_kk * (*err_km1);
 
-    if ( kk > 2 ) {
+    if ( IDA_mem->ida_kk > 2 ) {
 
       /* Compute error at order k-2 */
-      N_VLinearSum(ONE, phi[kk-1], ONE, delta, delta);
-      enorm_km2 = IDAWrmsNorm(IDA_mem, delta, ewt, suppressalg);
-      err_km2 = sigma[kk-2] * enorm_km2;
-      terr_km2 = (kk-1) * err_km2;
+      N_VLinearSum(ONE, IDA_mem->ida_phi[IDA_mem->ida_kk - 1], ONE,
+                   IDA_mem->ida_delta, IDA_mem->ida_delta);
+      enorm_km2 = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta,
+                              IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+      err_km2 = IDA_mem->ida_sigma[IDA_mem->ida_kk - 2] * enorm_km2;
+      terr_km2 = (IDA_mem->ida_kk - 1) * err_km2;
 
       /* Decrease order if errors are reduced */
-      if (SUNMAX(terr_km1, terr_km2) <= terr_k)  knew = kk - 1;
+      if (SUNMAX(terr_km1, terr_km2) <= terr_k)
+        IDA_mem->ida_knew = IDA_mem->ida_kk - 1;
 
     } else {
 
       /* Decrease order to 1 if errors are reduced by at least 1/2 */
-      if (terr_km1 <= (HALF * terr_k) )  knew = kk - 1; 
+      if (terr_km1 <= (HALF * terr_k) )
+        IDA_mem->ida_knew = IDA_mem->ida_kk - 1; 
 
     }
 
@@ -2569,13 +2476,13 @@ static void IDARestore(IDAMem IDA_mem, realtype saved_t)
 {
   int j;
 
-  tn = saved_t;
+  IDA_mem->ida_tn = saved_t;
   
-  for (j = 1; j <= kk; j++) 
-    psi[j-1] = psi[j] - hh;
+  for (j = 1; j <= IDA_mem->ida_kk; j++) 
+    IDA_mem->ida_psi[j-1] = IDA_mem->ida_psi[j] - IDA_mem->ida_hh;
 
-  for (j = ns; j <= kk; j++) 
-    N_VScale(ONE/beta[j], phi[j], phi[j]);
+  for (j = IDA_mem->ida_ns; j <= IDA_mem->ida_kk; j++) 
+    N_VScale(ONE/IDA_mem->ida_beta[j], IDA_mem->ida_phi[j], IDA_mem->ida_phi[j]);
 
 }
 
@@ -2627,7 +2534,7 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
 {
   realtype err_knew;
 
-  phase = 1;
+  IDA_mem->ida_phase = 1;
     
   if (nflag != ERROR_TEST_FAIL) {
 
@@ -2646,11 +2553,11 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
       
       /* Reduce step size for a new prediction
          Note that if nflag=IDA_CONSTR_RECVR then rr was already set in IDANls */
-      if (nflag != IDA_CONSTR_RECVR) rr = QUARTER;
-      hh *= rr;
+      if (nflag != IDA_CONSTR_RECVR) IDA_mem->ida_rr = QUARTER;
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
 
       /* Test if there were too many convergence failures */
-      if (*ncfPtr < maxncf)               return(PREDICT_AGAIN);
+      if (*ncfPtr < IDA_mem->ida_maxncf)  return(PREDICT_AGAIN);
       else if (nflag == IDA_RES_RECVR)    return(IDA_REP_RES_ERR);
       else if (nflag == IDA_CONSTR_RECVR) return(IDA_CONSTR_FAIL);
       else                                return(IDA_CONV_FAIL);
@@ -2670,12 +2577,12 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
       /* On first error test failure, keep current order or lower order by one. 
          Compute new stepsize based on differences of the solution. */
 
-      err_knew = (kk==knew)? err_k : err_km1;
+      err_knew = (IDA_mem->ida_kk == IDA_mem->ida_knew) ? err_k : err_km1;
 
-      kk = knew;      
-      rr = PT9 * SUNRpowerR( TWO * err_knew + PT0001,(-ONE/(kk+1)) );
-      rr = SUNMAX(QUARTER, SUNMIN(PT9,rr));
-      hh *=rr;
+      IDA_mem->ida_kk = IDA_mem->ida_knew;      
+      IDA_mem->ida_rr = PT9 * SUNRpowerR( TWO * err_knew + PT0001, -ONE/(IDA_mem->ida_kk + 1) );
+      IDA_mem->ida_rr = SUNMAX(QUARTER, SUNMIN(PT9,IDA_mem->ida_rr));
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
       return(PREDICT_AGAIN);
       
     } else if (*nefPtr == 2) {
@@ -2683,18 +2590,18 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
       /* On second error test failure, use current order or decrease order by one. 
          Reduce stepsize by factor of 1/4. */
 
-      kk = knew;
-      rr = QUARTER;
-      hh *= rr;
+      IDA_mem->ida_kk = IDA_mem->ida_knew;
+      IDA_mem->ida_rr = QUARTER;
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
       return(PREDICT_AGAIN);
       
-    } else if (*nefPtr < maxnef) {
+    } else if (*nefPtr < IDA_mem->ida_maxnef) {
       
       /* On third and subsequent error test failures, set order to 1.
          Reduce stepsize by factor of 1/4. */
-      kk = 1;
-      rr = QUARTER;
-      hh *= rr;
+      IDA_mem->ida_kk = 1;
+      IDA_mem->ida_rr = QUARTER;
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
       return(PREDICT_AGAIN);
 
     } else {
@@ -2717,9 +2624,9 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
 
 static void IDAReset(IDAMem IDA_mem)
 {
-  psi[0] = hh;
+  IDA_mem->ida_psi[0] = IDA_mem->ida_hh;
 
-  N_VScale(rr, phi[1], phi[1]);
+  N_VScale(IDA_mem->ida_rr, IDA_mem->ida_phi[1], IDA_mem->ida_phi[1]);
 }
 
 /* 
@@ -2743,12 +2650,13 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
   realtype err_knew, err_kp1;
   realtype enorm, tmp, hnew;
 
-  nst++;
-  kdiff = kk - kused;
-  kused = kk;
-  hused = hh;
+  IDA_mem->ida_nst++;
+  kdiff = IDA_mem->ida_kk - IDA_mem->ida_kused;
+  IDA_mem->ida_kused = IDA_mem->ida_kk;
+  IDA_mem->ida_hused = IDA_mem->ida_hh;
 
-  if ( (knew == kk-1) || (kk == maxord) ) phase = 1;
+  if ( (IDA_mem->ida_knew == IDA_mem->ida_kk - 1) ||
+       (IDA_mem->ida_kk == IDA_mem->ida_maxord) ) IDA_mem->ida_phase = 1;
 
   /* For the first few steps, until either a step fails, or the order is 
      reduced, or the order reaches its maximum, we raise the order and double 
@@ -2758,13 +2666,14 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
      Note that, after the first step, the order is not increased, as not all 
      of the neccessary information is available yet. */
   
-  if (phase == 0) {
-
-    if(nst > 1) {
-      kk++;
-      hnew = TWO * hh;
-      if( (tmp = SUNRabs(hnew)*hmax_inv) > ONE ) hnew /= tmp;
-      hh = hnew;
+  if (IDA_mem->ida_phase == 0) {
+
+    if(IDA_mem->ida_nst > 1) {
+      IDA_mem->ida_kk++;
+      hnew = TWO * IDA_mem->ida_hh;
+      if( (tmp = SUNRabs(hnew)*IDA_mem->ida_hmax_inv) > ONE )
+        hnew /= tmp;
+      IDA_mem->ida_hh = hnew;
     }
 
   } else {
@@ -2773,28 +2682,31 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
     
     /* Set action = LOWER/MAINTAIN/RAISE to specify order decision */
     
-    if (knew == kk-1)                   {action = LOWER;    goto takeaction;}
-    if (kk == maxord)                   {action = MAINTAIN; goto takeaction;}
-    if ( (kk+1 >= ns ) || (kdiff == 1)) {action = MAINTAIN; goto takeaction;}
+    if (IDA_mem->ida_knew == IDA_mem->ida_kk - 1)  {action = LOWER;    goto takeaction;}
+    if (IDA_mem->ida_kk == IDA_mem->ida_maxord)    {action = MAINTAIN; goto takeaction;}
+    if ( (IDA_mem->ida_kk + 1 >= IDA_mem->ida_ns ) ||
+         (kdiff == 1))                             {action = MAINTAIN; goto takeaction;}
     
     /* Estimate the error at order k+1, unless already decided to
        reduce order, or already using maximum order, or stepsize has not
        been constant, or order was just raised. */
     
-    N_VLinearSum (ONE, ee, -ONE, phi[kk+1], tempv1);
-    enorm = IDAWrmsNorm(IDA_mem, tempv1, ewt, suppressalg);
-    err_kp1= enorm/(kk+2);
+    N_VLinearSum(ONE, IDA_mem->ida_ee, -ONE,
+                 IDA_mem->ida_phi[IDA_mem->ida_kk + 1], IDA_mem->ida_tempv1);
+    enorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_tempv1, IDA_mem->ida_ewt,
+                        IDA_mem->ida_suppressalg);
+    err_kp1= enorm/(IDA_mem->ida_kk + 2);
 
     /* Choose among orders k-1, k, k+1 using local truncation error norms. */
 
-    terr_k   = (kk+1) * err_k;
-    terr_kp1 = (kk+2) * err_kp1;
+    terr_k   = (IDA_mem->ida_kk + 1) * err_k;
+    terr_kp1 = (IDA_mem->ida_kk + 2) * err_kp1;
 
-    if (kk == 1) {
+    if (IDA_mem->ida_kk == 1) {
       if (terr_kp1 >= HALF * terr_k)         {action = MAINTAIN; goto takeaction;}
       else                                   {action = RAISE;    goto takeaction;}
     } else {
-      terr_km1 = kk * err_km1;
+      terr_km1 = IDA_mem->ida_kk * err_km1;
       if (terr_km1 <= SUNMIN(terr_k, terr_kp1)) {action = LOWER;    goto takeaction;}
       else if (terr_kp1 >= terr_k)           {action = MAINTAIN; goto takeaction;}
       else                                   {action = RAISE;    goto takeaction;}
@@ -2803,38 +2715,40 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
   takeaction:
     
     /* Set the estimated error norm and, on change of order, reset kk. */
-    if      (action == RAISE) { kk++; err_knew = err_kp1; }
-    else if (action == LOWER) { kk--; err_knew = err_km1; }
-    else                      {       err_knew = err_k;   }  
+    if      (action == RAISE) { IDA_mem->ida_kk++; err_knew = err_kp1; }
+    else if (action == LOWER) { IDA_mem->ida_kk--; err_knew = err_km1; }
+    else                      {                    err_knew = err_k;   }  
 
     /* Compute rr = tentative ratio hnew/hh from error norm estimate.
        Reduce hh if rr <= 1, double hh if rr >= 2, else leave hh as is.
        If hh is reduced, hnew/hh is restricted to be between .5 and .9. */
     
-    hnew = hh;
-    rr = SUNRpowerR( (TWO * err_knew + PT0001) , (-ONE/(kk+1) ) );
+    hnew = IDA_mem->ida_hh;
+    IDA_mem->ida_rr = SUNRpowerR( TWO * err_knew + PT0001, -ONE/(IDA_mem->ida_kk + 1) );
     
-    if (rr >= TWO) {
-      hnew = TWO * hh;
-      if( (tmp = SUNRabs(hnew)*hmax_inv) > ONE ) hnew /= tmp;
-    } else if (rr <= ONE ) { 
-      rr = SUNMAX(HALF, SUNMIN(PT9,rr));
-      hnew = hh * rr;
+    if (IDA_mem->ida_rr >= TWO) {
+      hnew = TWO * IDA_mem->ida_hh;
+      if( (tmp = SUNRabs(hnew)*IDA_mem->ida_hmax_inv) > ONE )
+        hnew /= tmp;
+    } else if (IDA_mem->ida_rr <= ONE ) { 
+      IDA_mem->ida_rr = SUNMAX(HALF, SUNMIN(PT9,IDA_mem->ida_rr));
+      hnew = IDA_mem->ida_hh * IDA_mem->ida_rr;
     }
     
-    hh = hnew;
+    IDA_mem->ida_hh = hnew;
     
   } /* end of phase if block */
   
   /* Save ee for possible order increase on next step */
-  if (kused < maxord) {
-    N_VScale(ONE, ee, phi[kused+1]);
+  if (IDA_mem->ida_kused < IDA_mem->ida_maxord) {
+    N_VScale(ONE, IDA_mem->ida_ee, IDA_mem->ida_phi[IDA_mem->ida_kused + 1]);
   }
 
   /* Update phi arrays */
-  N_VLinearSum(ONE, ee, ONE, phi[kused], phi[kused]);
-  for (j= kused-1; j>=0; j--)
-    N_VLinearSum(ONE, phi[j], ONE, phi[j+1], phi[j]);
+  N_VLinearSum(ONE, IDA_mem->ida_ee, ONE, IDA_mem->ida_phi[IDA_mem->ida_kused],
+               IDA_mem->ida_phi[IDA_mem->ida_kused]);
+  for (j= IDA_mem->ida_kused-1; j>=0; j--)
+    N_VLinearSum(ONE, IDA_mem->ida_phi[j], ONE, IDA_mem->ida_phi[j+1], IDA_mem->ida_phi[j]);
 
 }
 
@@ -2875,32 +2789,34 @@ int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret)
 
   /* Check t for legality.  Here tn - hused is t_{n-1}. */
  
-  tfuzz = HUNDRED * uround * (SUNRabs(tn) + SUNRabs(hh));
-  if (hh < ZERO) tfuzz = - tfuzz;
-  tp = tn - hused - tfuzz;
-  if ((t - tp)*hh < ZERO) {
-    IDAProcessError(IDA_mem, IDA_BAD_T, "IDA", "IDAGetSolution", MSG_BAD_T, t, tn-hused, tn);
+  tfuzz = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+  if (IDA_mem->ida_hh < ZERO)
+    tfuzz = - tfuzz;
+  tp = IDA_mem->ida_tn - IDA_mem->ida_hused - tfuzz;
+  if ((t - tp)*IDA_mem->ida_hh < ZERO) {
+    IDAProcessError(IDA_mem, IDA_BAD_T, "IDA", "IDAGetSolution", MSG_BAD_T, t,
+                    IDA_mem->ida_tn-IDA_mem->ida_hused, IDA_mem->ida_tn);
     return(IDA_BAD_T);
   }
 
   /* Initialize yret = phi[0], ypret = 0, and kord = (kused or 1). */
 
-  N_VScale (ONE, phi[0], yret);
-  N_VConst (ZERO, ypret);
-  kord = kused; 
-  if (kused == 0) kord = 1;
+  N_VScale(ONE, IDA_mem->ida_phi[0], yret);
+  N_VConst(ZERO, ypret);
+  kord = IDA_mem->ida_kused; 
+  if (IDA_mem->ida_kused == 0) kord = 1;
 
   /* Accumulate multiples of columns phi[j] into yret and ypret. */
 
-  delt = t - tn;
+  delt = t - IDA_mem->ida_tn;
   c = ONE; d = ZERO;
-  gam = delt/psi[0];
+  gam = delt / IDA_mem->ida_psi[0];
   for (j=1; j <= kord; j++) {
-    d = d*gam + c/psi[j-1];
+    d = d*gam + c / IDA_mem->ida_psi[j-1];
     c = c*gam;
-    gam = (delt + psi[j-1])/psi[j];
-    N_VLinearSum(ONE,  yret, c, phi[j],  yret);
-    N_VLinearSum(ONE, ypret, d, phi[j], ypret);
+    gam = (delt + IDA_mem->ida_psi[j-1]) / IDA_mem->ida_psi[j];
+    N_VLinearSum(ONE,  yret, c, IDA_mem->ida_phi[j],  yret);
+    N_VLinearSum(ONE, ypret, d, IDA_mem->ida_phi[j], ypret);
   }
   return(IDA_SUCCESS);
 }
@@ -2915,12 +2831,12 @@ int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret)
  * IDAWrmsNorm
  *
  *  Returns the WRMS norm of vector x with weights w.
- *  If mask = TRUE, the weight vector w is masked by id, i.e.,
+ *  If mask = SUNTRUE, the weight vector w is masked by id, i.e.,
  *      nrm = N_VWrmsNormMask(x,w,id);
  *  Otherwise,
  *      nrm = N_VWrmsNorm(x,w);
  * 
- * mask = FALSE       when the call is made from the nonlinear solver.
+ * mask = SUNFALSE       when the call is made from the nonlinear solver.
  * mask = suppressalg otherwise.
  */
 
@@ -2929,7 +2845,7 @@ realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w,
 {
   realtype nrm;
 
-  if (mask) nrm = N_VWrmsNormMask(x, w, id);
+  if (mask) nrm = N_VWrmsNormMask(x, w, IDA_mem->ida_id);
   else      nrm = N_VWrmsNorm(x, w);
 
   return(nrm);
@@ -2959,39 +2875,42 @@ static int IDARcheck1(IDAMem IDA_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  tlo = tn;
-  ttol = (SUNRabs(tn) + SUNRabs(hh))*uround*HUNDRED;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+    IDA_mem->ida_iroots[i] = 0;
+  IDA_mem->ida_tlo = IDA_mem->ida_tn;
+  IDA_mem->ida_ttol = (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)) * IDA_mem->ida_uround * HUNDRED;
 
   /* Evaluate g at initial t and check for zero values. */
-  retval = gfun (tlo, phi[0], phi[1], glo, user_data);
-  nge = 1;
+  retval = IDA_mem->ida_gfun(IDA_mem->ida_tlo, IDA_mem->ida_phi[0], IDA_mem->ida_phi[1],
+                             IDA_mem->ida_glo, IDA_mem->ida_user_data);
+  IDA_mem->ida_nge = 1;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      gactive[i] = FALSE;
+  zroot = SUNFALSE;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (SUNRabs(IDA_mem->ida_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      IDA_mem->ida_gactive[i] = SUNFALSE;
     }
   }
   if (!zroot) return(IDA_SUCCESS);
 
   /* Some g_i is zero at t0; look at g at t0+(small increment). */
-  hratio = SUNMAX(ttol/SUNRabs(hh), PT1);
-  smallh = hratio*hh;
-  tplus = tlo + smallh;
-  N_VLinearSum(ONE, phi[0], smallh, phi[1], yy);
-  retval = gfun (tplus, yy, phi[1], ghi, user_data);  
-  nge++;
+  hratio = SUNMAX(IDA_mem->ida_ttol/SUNRabs(IDA_mem->ida_hh), PT1);
+  smallh = hratio * IDA_mem->ida_hh;
+  tplus = IDA_mem->ida_tlo + smallh;
+  N_VLinearSum(ONE, IDA_mem->ida_phi[0], smallh, IDA_mem->ida_phi[1], IDA_mem->ida_yy);
+  retval = IDA_mem->ida_gfun(tplus, IDA_mem->ida_yy, IDA_mem->ida_phi[1],
+                             IDA_mem->ida_ghi, IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
   /* We check now only the components of g which were exactly 0.0 at t0
    * to see if we can 'activate' them. */
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i] && SUNRabs(ghi[i]) != ZERO) {
-      gactive[i] = TRUE;
-      glo[i] = ghi[i];
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (!IDA_mem->ida_gactive[i] && SUNRabs(IDA_mem->ida_ghi[i]) != ZERO) {
+      IDA_mem->ida_gactive[i] = SUNTRUE;
+      IDA_mem->ida_glo[i] = IDA_mem->ida_ghi[i];
     }
   }
   return(IDA_SUCCESS);
@@ -3024,49 +2943,54 @@ static int IDARcheck2(IDAMem IDA_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  if (irfnd == 0) return(IDA_SUCCESS);
+  if (IDA_mem->ida_irfnd == 0) return(IDA_SUCCESS);
 
-  (void) IDAGetSolution(IDA_mem, tlo, yy, yp);
-  retval = gfun (tlo, yy, yp, glo, user_data);  
-  nge++;
+  (void) IDAGetSolution(IDA_mem, IDA_mem->ida_tlo, IDA_mem->ida_yy, IDA_mem->ida_yp);
+  retval = IDA_mem->ida_gfun(IDA_mem->ida_tlo, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                             IDA_mem->ida_glo, IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+    IDA_mem->ida_iroots[i] = 0;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (!IDA_mem->ida_gactive[i]) continue;
+    if (SUNRabs(IDA_mem->ida_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      IDA_mem->ida_iroots[i] = 1;
     }
   }
   if (!zroot) return(IDA_SUCCESS);
 
   /* One or more g_i has a zero at tlo.  Check g at tlo+smallh. */
-  ttol = (SUNRabs(tn) + SUNRabs(hh))*uround*HUNDRED;
-  smallh = (hh > ZERO) ? ttol : -ttol;
-  tplus = tlo + smallh;
-  if ( (tplus - tn)*hh >= ZERO) {
-    hratio = smallh/hh;
-    N_VLinearSum(ONE, yy, hratio, phi[1], yy);
+  IDA_mem->ida_ttol = (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)) * IDA_mem->ida_uround * HUNDRED;
+  smallh = (IDA_mem->ida_hh > ZERO) ? IDA_mem->ida_ttol : -IDA_mem->ida_ttol;
+  tplus = IDA_mem->ida_tlo + smallh;
+  if ( (tplus - IDA_mem->ida_tn)*IDA_mem->ida_hh >= ZERO) {
+    hratio = smallh/IDA_mem->ida_hh;
+    N_VLinearSum(ONE, IDA_mem->ida_yy, hratio,
+                 IDA_mem->ida_phi[1], IDA_mem->ida_yy);
   } else {
-    (void) IDAGetSolution(IDA_mem, tplus, yy, yp);
+    (void) IDAGetSolution(IDA_mem, tplus, IDA_mem->ida_yy, IDA_mem->ida_yp);
   }
-  retval = gfun (tplus, yy, yp, ghi, user_data);  
-  nge++;
+  retval = IDA_mem->ida_gfun(tplus, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                             IDA_mem->ida_ghi, IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
   /* Check for close roots (error return), for a new zero at tlo+smallh,
   and for a g_i that changed from zero to nonzero. */
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if (iroots[i] == 1) return(CLOSERT);
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (!IDA_mem->ida_gactive[i]) continue;
+    if (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) {
+      if (IDA_mem->ida_iroots[i] == 1) return(CLOSERT);
+      zroot = SUNTRUE;
+      IDA_mem->ida_iroots[i] = 1;
     } else {
-      if (iroots[i] == 1) glo[i] = ghi[i];
+      if (IDA_mem->ida_iroots[i] == 1)
+        IDA_mem->ida_glo[i] = IDA_mem->ida_ghi[i];
     }
   }
   if (zroot) return(RTFOUND);
@@ -3091,34 +3015,37 @@ static int IDARcheck3(IDAMem IDA_mem)
   int i, ier, retval;
 
   /* Set thi = tn or tout, whichever comes first. */
-  if (taskc == IDA_ONE_STEP) thi = tn;
-  if (taskc == IDA_NORMAL) {
-    thi = ( (toutc - tn)*hh >= ZERO) ? tn : toutc;
+  if (IDA_mem->ida_taskc == IDA_ONE_STEP) IDA_mem->ida_thi = IDA_mem->ida_tn;
+  if (IDA_mem->ida_taskc == IDA_NORMAL) {
+    IDA_mem->ida_thi = ( (IDA_mem->ida_toutc - IDA_mem->ida_tn)*IDA_mem->ida_hh >= ZERO)
+      ? IDA_mem->ida_tn : IDA_mem->ida_toutc;
   }
 
   /* Get y and y' at thi. */
-  (void) IDAGetSolution(IDA_mem, thi, yy, yp);
+  (void) IDAGetSolution(IDA_mem, IDA_mem->ida_thi, IDA_mem->ida_yy, IDA_mem->ida_yp);
 
 
   /* Set ghi = g(thi) and call IDARootfind to search (tlo,thi) for roots. */
-  retval = gfun (thi, yy, yp, ghi, user_data);  
-  nge++;
+  retval = IDA_mem->ida_gfun(IDA_mem->ida_thi, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                             IDA_mem->ida_ghi, IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
-  ttol = (SUNRabs(tn) + SUNRabs(hh))*uround*HUNDRED;
+  IDA_mem->ida_ttol = (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)) * IDA_mem->ida_uround * HUNDRED;
   ier = IDARootfind(IDA_mem);
   if (ier == IDA_RTFUNC_FAIL) return(IDA_RTFUNC_FAIL);
-  for(i=0; i<nrtfn; i++) {
-    if(!gactive[i] && grout[i] != ZERO) gactive[i] = TRUE;
+  for(i=0; i<IDA_mem->ida_nrtfn; i++) {
+    if(!IDA_mem->ida_gactive[i] && IDA_mem->ida_grout[i] != ZERO)
+      IDA_mem->ida_gactive[i] = SUNTRUE;
   }
-  tlo = trout;
-  for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+  IDA_mem->ida_tlo = IDA_mem->ida_trout;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) IDA_mem->ida_glo[i] = IDA_mem->ida_grout[i];
 
   /* If no root found, return IDA_SUCCESS. */  
   if (ier == IDA_SUCCESS) return(IDA_SUCCESS);
 
   /* If a root was found, interpolate to get y(trout) and return.  */
-  (void) IDAGetSolution(IDA_mem, trout, yy, yp);
+  (void) IDAGetSolution(IDA_mem, IDA_mem->ida_trout, IDA_mem->ida_yy, IDA_mem->ida_yp);
   return(RTFOUND);
 }
 
@@ -3152,10 +3079,10 @@ static int IDARcheck3(IDAMem IDA_mem)
  *
  * gactive  = array specifying whether a component of g should
  *            or should not be monitored. gactive[i] is initially
- *            set to TRUE for all i=0,...,nrtfn-1, but it may be
- *            reset to FALSE if at the first step g[i] is 0.0
+ *            set to SUNTRUE for all i=0,...,nrtfn-1, but it may be
+ *            reset to SUNFALSE if at the first step g[i] is 0.0
  *            both at the I.C. and at a small perturbation of them.
- *            gactive[i] is then set back on TRUE only after the 
+ *            gactive[i] is then set back on SUNTRUE only after the 
  *            corresponding g function moves away from 0.0.
  *
  * nge      = cumulative counter for gfun calls.
@@ -3210,19 +3137,20 @@ static int IDARootfind(IDAMem IDA_mem)
 
   /* First check for change in sign in ghi or for a zero in ghi. */
   maxfrac = ZERO;
-  zroot = FALSE;
-  sgnchg = FALSE;
-  for (i = 0;  i < nrtfn; i++) {
-    if(!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if(rootdir[i]*glo[i] <= ZERO) {
-        zroot = TRUE;
+  zroot = SUNFALSE;
+  sgnchg = SUNFALSE;
+  for (i = 0;  i < IDA_mem->ida_nrtfn; i++) {
+    if(!IDA_mem->ida_gactive[i]) continue;
+    if (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) {
+      if(IDA_mem->ida_rootdir[i] * IDA_mem->ida_glo[i] <= ZERO) {
+        zroot = SUNTRUE;
       }
     } else {
-      if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-        gfrac = SUNRabs(ghi[i]/(ghi[i] - glo[i]));
+      if ( (IDA_mem->ida_glo[i] * IDA_mem->ida_ghi[i] < ZERO) &&
+           (IDA_mem->ida_rootdir[i] * IDA_mem->ida_glo[i] <= ZERO) ) {
+        gfrac = SUNRabs(IDA_mem->ida_ghi[i] / (IDA_mem->ida_ghi[i] - IDA_mem->ida_glo[i]));
         if (gfrac > maxfrac) {
-          sgnchg = TRUE;
+          sgnchg = SUNTRUE;
           maxfrac = gfrac;
           imax = i;
         }
@@ -3233,14 +3161,16 @@ static int IDARootfind(IDAMem IDA_mem)
   /* If no sign change was found, reset trout and grout.  Then return
      IDA_SUCCESS if no zero was found, or set iroots and return RTFOUND.  */ 
   if (!sgnchg) {
-    trout = thi;
-    for (i = 0; i < nrtfn; i++) grout[i] = ghi[i];
+    IDA_mem->ida_trout = IDA_mem->ida_thi;
+    for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+      IDA_mem->ida_grout[i] = IDA_mem->ida_ghi[i];
     if (!zroot) return(IDA_SUCCESS);
-    for (i = 0; i < nrtfn; i++) {
-      iroots[i] = 0;
-      if(!gactive[i]) continue;
-      if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-        iroots[i] = glo[i] > 0 ? -1:1;
+    for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+      IDA_mem->ida_iroots[i] = 0;
+      if(!IDA_mem->ida_gactive[i]) continue;
+      if ( (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) &&
+           (IDA_mem->ida_rootdir[i] * IDA_mem->ida_glo[i] <= ZERO) )
+        IDA_mem->ida_iroots[i] = IDA_mem->ida_glo[i] > 0 ? -1:1;
     }
     return(RTFOUND);
   }
@@ -3251,10 +3181,10 @@ static int IDARootfind(IDAMem IDA_mem)
   /* A sign change was found.  Loop to locate nearest root. */
 
   side = 0;  sideprev = -1;
-  loop {                                    /* Looping point */
+  for(;;) {                                    /* Looping point */
 
     /* If interval size is already less than tolerance ttol, break. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) <= IDA_mem->ida_ttol) break;
 
     /* Set weight alph.
        On the first two passes, set alph = 1.  Thereafter, reset alph
@@ -3275,38 +3205,42 @@ static int IDARootfind(IDAMem IDA_mem)
     /* Set next root approximation tmid and get g(tmid).
        If tmid is too close to tlo or thi, adjust it inward,
        by a fractional distance that is between 0.1 and 0.5.  */
-    tmid = thi - (thi - tlo)*ghi[imax]/(ghi[imax] - alph*glo[imax]);
-    if (SUNRabs(tmid - tlo) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    tmid = IDA_mem->ida_thi - (IDA_mem->ida_thi - IDA_mem->ida_tlo)*IDA_mem->ida_ghi[imax] /
+      (IDA_mem->ida_ghi[imax] - alph*IDA_mem->ida_glo[imax]);
+    if (SUNRabs(tmid - IDA_mem->ida_tlo) < HALF*IDA_mem->ida_ttol) {
+      fracint = SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo)/IDA_mem->ida_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = tlo + fracsub*(thi - tlo);
+      tmid = IDA_mem->ida_tlo + fracsub*(IDA_mem->ida_thi - IDA_mem->ida_tlo);
     }
-    if (SUNRabs(thi - tmid) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    if (SUNRabs(IDA_mem->ida_thi - tmid) < HALF*IDA_mem->ida_ttol) {
+      fracint = SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo)/IDA_mem->ida_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = thi - fracsub*(thi - tlo);
+      tmid = IDA_mem->ida_thi - fracsub*(IDA_mem->ida_thi - IDA_mem->ida_tlo);
     }
 
-    (void) IDAGetSolution(IDA_mem, tmid, yy, yp);
-    retval = gfun (tmid, yy, yp, grout, user_data);  
-    nge++;
+    (void) IDAGetSolution(IDA_mem, tmid, IDA_mem->ida_yy, IDA_mem->ida_yp);
+    retval = IDA_mem->ida_gfun(tmid, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                               IDA_mem->ida_grout, IDA_mem->ida_user_data);  
+    IDA_mem->ida_nge++;
     if (retval != 0) return(IDA_RTFUNC_FAIL);
 
     /* Check to see in which subinterval g changes sign, and reset imax.
        Set side = 1 if sign change is on low side, or 2 if on high side.  */  
     maxfrac = ZERO;
-    zroot = FALSE;
-    sgnchg = FALSE;
+    zroot = SUNFALSE;
+    sgnchg = SUNFALSE;
     sideprev = side;
-    for (i = 0;  i < nrtfn; i++) {
-      if(!gactive[i]) continue;
-      if (SUNRabs(grout[i]) == ZERO) {
-        if(rootdir[i]*glo[i] <= ZERO) zroot = TRUE;
+    for (i = 0;  i < IDA_mem->ida_nrtfn; i++) {
+      if(!IDA_mem->ida_gactive[i]) continue;
+      if (SUNRabs(IDA_mem->ida_grout[i]) == ZERO) {
+        if(IDA_mem->ida_rootdir[i] * IDA_mem->ida_glo[i] <= ZERO)
+          zroot = SUNTRUE;
       } else {
-        if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-          gfrac = SUNRabs(grout[i]/(grout[i] - glo[i]));
+        if ( (IDA_mem->ida_glo[i] * IDA_mem->ida_grout[i] < ZERO) &&
+             (IDA_mem->ida_rootdir[i] * IDA_mem->ida_glo[i] <= ZERO) ) {
+          gfrac = SUNRabs(IDA_mem->ida_grout[i] / (IDA_mem->ida_grout[i] - IDA_mem->ida_glo[i]));
           if (gfrac > maxfrac) {
-            sgnchg = TRUE;
+            sgnchg = SUNTRUE;
             maxfrac = gfrac;
             imax = i;
           }
@@ -3315,41 +3249,46 @@ static int IDARootfind(IDAMem IDA_mem)
     }
     if (sgnchg) {
       /* Sign change found in (tlo,tmid); replace thi with tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      IDA_mem->ida_thi = tmid;
+      for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+        IDA_mem->ida_ghi[i] = IDA_mem->ida_grout[i];
       side = 1;
       /* Stop at root thi if converged; otherwise loop. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) <= IDA_mem->ida_ttol) break;
       continue;  /* Return to looping point. */
     }
 
     if (zroot) {
       /* No sign change in (tlo,tmid), but g = 0 at tmid; return root tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      IDA_mem->ida_thi = tmid;
+      for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+        IDA_mem->ida_ghi[i] = IDA_mem->ida_grout[i];
       break;
     }
 
     /* No sign change in (tlo,tmid), and no zero at tmid.
        Sign change must be in (tmid,thi).  Replace tlo with tmid. */
-    tlo = tmid;
-    for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+    IDA_mem->ida_tlo = tmid;
+    for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+      IDA_mem->ida_glo[i] = IDA_mem->ida_grout[i];
     side = 2;
     /* Stop at root thi if converged; otherwise loop back. */
-    if (SUNRabs(thi - tlo) <= ttol) break;
+    if (SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) <= IDA_mem->ida_ttol) break;
 
   } /* End of root-search loop */
 
   /* Reset trout and grout, set iroots, and return RTFOUND. */
-  trout = thi;
-  for (i = 0; i < nrtfn; i++) {
-    grout[i] = ghi[i];
-    iroots[i] = 0;
-    if(!gactive[i]) continue;
-    if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-      iroots[i] = glo[i] > 0 ? -1:1;
-    if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) 
-      iroots[i] = glo[i] > 0 ? -1:1;
+  IDA_mem->ida_trout = IDA_mem->ida_thi;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    IDA_mem->ida_grout[i] = IDA_mem->ida_ghi[i];
+    IDA_mem->ida_iroots[i] = 0;
+    if(!IDA_mem->ida_gactive[i]) continue;
+    if ( (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) &&
+         (IDA_mem->ida_rootdir[i] * IDA_mem->ida_glo[i] <= ZERO) )
+      IDA_mem->ida_iroots[i] = IDA_mem->ida_glo[i] > 0 ? -1:1;
+    if ( (IDA_mem->ida_glo[i] * IDA_mem->ida_ghi[i] < ZERO) &&
+         (IDA_mem->ida_rootdir[i] * IDA_mem->ida_glo[i] <= ZERO) ) 
+      IDA_mem->ida_iroots[i] = IDA_mem->ida_glo[i] > 0 ? -1:1;
   }
   return(RTFOUND);
 }
@@ -3367,9 +3306,6 @@ static int IDARootfind(IDAMem IDA_mem)
  *   pointed to by ida_ehfun.
  */
 
-#define ehfun   (IDA_mem->ida_ehfun)
-#define eh_data (IDA_mem->ida_eh_data)
-
 void IDAProcessError(IDAMem IDA_mem, 
                     int error_code, const char *module, const char *fname, 
                     const char *msgfmt, ...)
@@ -3393,7 +3329,7 @@ void IDAProcessError(IDAMem IDA_mem,
 #endif
 
   } else {                 /* We can call ehfun */
-    ehfun(error_code, module, fname, msg, eh_data);
+    IDA_mem->ida_ehfun(error_code, module, fname, msg, IDA_mem->ida_eh_data);
   }
 
   /* Finalize argument processing */
@@ -3405,8 +3341,6 @@ void IDAProcessError(IDAMem IDA_mem,
 /* IDAErrHandler is the default error handling function.
    It sends the error message to the stream pointed to by ida_errfp */
 
-#define errfp (IDA_mem->ida_errfp)
-
 void IDAErrHandler(int error_code, const char *module,
                    const char *function, char *msg, void *data)
 {
@@ -3423,9 +3357,9 @@ void IDAErrHandler(int error_code, const char *module,
     sprintf(err_type,"ERROR");
 
 #ifndef NO_FPRINTF_OUTPUT
-  if (errfp!=NULL) {
-    fprintf(errfp,"\n[%s %s]  %s\n",module,err_type,function);
-    fprintf(errfp,"  %s\n\n",msg);
+  if (IDA_mem->ida_errfp!=NULL) {
+    fprintf(IDA_mem->ida_errfp,"\n[%s %s]  %s\n",module,err_type,function);
+    fprintf(IDA_mem->ida_errfp,"  %s\n\n",msg);
   }
 #endif
 
diff --git a/src/ida/ida_band.c b/src/ida/ida_band.c
deleted file mode 100644
index 11992fa..0000000
--- a/src/ida/ida_band.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4951 $
- * $Date: 2016-09-22 10:21:00 -0700 (Thu, 22 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDA banded linear
- * solver module, IDABAND. This module uses standard banded
- * matrix techniques to solve the linear systems generated by the
- * (nonlinear) Newton iteration process. The user may either
- * supply a banded Jacobian routine or use the routine supplied
- * with this module (IDABandDQJac).
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <ida/ida_band.h>
-#include "ida_direct_impl.h"
-#include "ida_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* IDABAND linit, lsetup, lsolve, and lfree routines */
- 
-static int IDABandInit(IDAMem IDA_mem);
-
-static int IDABandSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                        N_Vector rrp, N_Vector tmp1,
-                        N_Vector tmp2, N_Vector tmp3);
-
-static int IDABandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDABandFree(IDAMem IDA_mem);
-
-/* Readability Replacements */
-
-#define res         (IDA_mem->ida_res)
-#define tn          (IDA_mem->ida_tn)
-#define hh          (IDA_mem->ida_hh)
-#define cj          (IDA_mem->ida_cj)
-#define cjratio     (IDA_mem->ida_cjratio)
-#define ewt         (IDA_mem->ida_ewt)
-#define constraints (IDA_mem->ida_constraints)
-#define linit       (IDA_mem->ida_linit)
-#define lsetup      (IDA_mem->ida_lsetup)
-#define lsolve      (IDA_mem->ida_lsolve)
-#define lperf       (IDA_mem->ida_lperf)
-#define lfree       (IDA_mem->ida_lfree)
-#define lmem        (IDA_mem->ida_lmem)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define mtype       (idadls_mem->d_type)
-#define neq         (idadls_mem->d_n)
-#define ml          (idadls_mem->d_ml)
-#define mu          (idadls_mem->d_mu)
-#define jacDQ       (idadls_mem->d_jacDQ)
-#define bjac        (idadls_mem->d_bjac)
-#define JJ          (idadls_mem->d_J)
-#define smu         (idadls_mem->d_smu)
-#define lpivots     (idadls_mem->d_lpivots)
-#define nje         (idadls_mem->d_nje)
-#define nreDQ       (idadls_mem->d_nreDQ)
-#define jacdata     (idadls_mem->d_J_data)
-#define last_flag   (idadls_mem->d_last_flag)
-                  
-/*
- * -----------------------------------------------------------------
- * IDABand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDABAND linear solver module.
- * IDABand first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDABandInit, IDABandSetup,
- * IDABandSolve, NULL, and IDABandFree, respectively.
- * It allocates memory for a structure of type IDADlsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jacdata field in
- * the IDADlsMemRec structure to be the input parameter jdata, and sets
- * the d_bjac field to be:
- *   (1) the input parameter bjac, if bjac != NULL, or
- *   (2) IDABandDQJac, if bjac == NULL.
- * Finally, it allocates memory for JJ and lpivots.
- * IDABand returns IDADLS_SUCCESS = 0, IDADLS_LMEM_FAIL = -1,
- * or IDADLS_ILL_INPUT = -2.
- *
- * NOTE: The band linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDABand will first 
- *       test for a compatible N_Vector internal representation by
- *       checking that the N_VGetArrayPointer function exists
- * -----------------------------------------------------------------
- */
-
-int IDABand(void *ida_mem, long int Neq, long int mupper, long int mlower)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDABAND", "IDABand", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDABAND", "IDABand", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Test mlower and mupper for legality. */
-  if ((mlower < 0) || (mupper < 0) || (mlower >= Neq) || (mupper >= Neq)) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDABAND", "IDABand", MSGD_BAD_SIZES);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem. */
-  linit  = IDABandInit;
-  lsetup = IDABandSetup;
-  lsolve = IDABandSolve;
-  lperf  = NULL;
-  lfree  = IDABandFree;
-
-  /* Get memory for IDADlsMemRec. */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDABAND", "IDABand", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ   = TRUE;
-  bjac    = NULL;
-  jacdata = NULL;
-
-  last_flag = IDADLS_SUCCESS;
-
-  idaDlsInitializeCounters(idadls_mem);
-
-  setupNonNull = TRUE;
-
-  /* Store problem size */
-  neq = Neq;
-
-  idadls_mem->d_ml = mlower;
-  idadls_mem->d_mu = mupper;
-    
-  /* Set extended upper half-bandwidth for JJ (required for pivoting). */
-  smu = SUNMIN(Neq-1, mupper + mlower);
-
-  /* Allocate memory for JJ and pivot array. */
-  JJ = NULL;
-  JJ = NewBandMat(Neq, mupper, mlower, smu);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDABAND", "IDABand", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  lpivots = NULL;
-  lpivots = NewLintArray(Neq);
-  if (lpivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDABAND", "IDABand", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }  
-  
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDABAND interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDABAND
-  linear solver module.  It returns 0.
-*/
-
-static int IDABandInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  idaDlsInitializeCounters(idadls_mem);
-
-/*
-    nje   = 0;
-    nreDQ = 0;
-*/
-
-  if (jacDQ) {
-    bjac = idaDlsBandDQJac;
-    jacdata = IDA_mem;
-  } else {
-    jacdata = IDA_mem->ida_user_data;
-  }
-
-  last_flag = 0;
-  return(0);
-}
-
-
-/*
-  This routine does the setup operations for the IDABAND linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the band LU factorization routine.
-  The return value is either
-     IDADLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDABandSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                        N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-                        N_Vector tmp3)
-{
-  int retval;
-  long int retfac;
-  IDADlsMem idadls_mem;
-  
-  idadls_mem = (IDADlsMem) lmem;
-
-  /* Increment nje counter. */
-  nje++;
-
-  /* Zero out JJ; call Jacobian routine jac; return if it failed. */
-  SetToZero(JJ);
-  retval = bjac(neq, mu, ml, tn,  cj, yyp, ypp, rrp,
-                JJ, jacdata, tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDABAND", "IDABandSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  /* Do LU factorization of JJ; return success or fail flag. */
-  retfac = BandGBTRF(JJ, lpivots);
-  
-  if (retfac != 0) {
-    last_flag = retfac;
-    return(+1);
-  }
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-/*
-  This routine handles the solve operation for the IDABAND linear
-  solver module.  It calls the band backsolve routine, scales the
-  solution vector according to cjratio, then returns IDADLS_SUCCESS = 0.
-*/
-
-static int IDABandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  bd = N_VGetArrayPointer(b);
-  BandGBTRS(JJ, lpivots, bd);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-  
-  last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine frees memory specific to the IDABAND linear solver.
-*/
-
-static int IDABandFree(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(lpivots);
-  free(lmem); lmem = NULL;
-
-  return(0);
-
-}
-
diff --git a/src/ida/ida_bbdpre.c b/src/ida/ida_bbdpre.c
index dcf3d00..440122a 100644
--- a/src/ida/ida_bbdpre.c
+++ b/src/ida/ida_bbdpre.c
@@ -1,24 +1,26 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4920 $
- * $Date: 2016-09-19 14:34:35 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *        Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This file contains implementations of routines for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with IDA and an IDASPILS
- * linear solver.
+ * matrix with banded blocks, for use with IDA, the IDASPILS 
+ * linear solver interface.
  *
  * NOTE: With only one processor in use, a banded matrix results
  * rather than a block-diagonal matrix with banded blocks.
@@ -32,86 +34,64 @@
 #include "ida_impl.h"
 #include "ida_spils_impl.h"
 #include "ida_bbdpre_impl.h"
-
-#include <ida/ida_spgmr.h>
-#include <ida/ida_spbcgs.h>
-#include <ida/ida_sptfqmr.h>
-
 #include <sundials/sundials_math.h>
+#include <nvector/nvector_serial.h>
+
 
 #define ZERO RCONST(0.0)
 #define ONE  RCONST(1.0)
 #define TWO  RCONST(2.0)
 
-/* Prototypes of IDABBDPrecSetup and IDABBDPrecSolve */
-
-static int IDABBDPrecSetup(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           realtype c_j, void *prec_data,
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
- 
-static int IDABBDPrecSolve(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           N_Vector rvec, N_Vector zvec,
-                           realtype c_j, realtype delta, void *prec_data,
-                           N_Vector tmp);
+/* Prototypes of functions IDABBDPrecSetup and IDABBDPrecSolve */
+static int IDABBDPrecSetup(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, realtype c_j, void *prec_data);
+static int IDABBDPrecSolve(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, N_Vector rvec, N_Vector zvec,
+                           realtype c_j, realtype delta, void *prec_data);
 
 /* Prototype for IDABBDPrecFree */
-
 static int IDABBDPrecFree(IDAMem ida_mem);
 
 /* Prototype for difference quotient Jacobian calculation routine */
-
 static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
                      N_Vector yy, N_Vector yp, N_Vector gref, 
                      N_Vector ytemp, N_Vector yptemp, N_Vector gtemp);
 
-/* 
- * ================================================================
- * User-Callable Functions: initialization, reinit and free
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define uround   (IDA_mem->ida_uround)
-#define vec_tmpl (IDA_mem->ida_tempv1)
-
-/*
- * -----------------------------------------------------------------
- * User-Callable Functions : malloc, reinit and free
- * -----------------------------------------------------------------
- */
-
-int IDABBDPrecInit(void *ida_mem, long int Nlocal, 
-                   long int mudq, long int mldq, 
-                   long int mukeep, long int mlkeep, 
+/*---------------------------------------------------------------
+  User-Callable Functions: initialization, reinit and free
+  ---------------------------------------------------------------*/
+int IDABBDPrecInit(void *ida_mem, sunindextype Nlocal, 
+                   sunindextype mudq, sunindextype mldq, 
+                   sunindextype mukeep, sunindextype mlkeep, 
                    realtype dq_rel_yy, 
                    IDABBDLocalFn Gres, IDABBDCommFn Gcomm)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
-  N_Vector tempv4;
-  long int muk, mlk, storage_mu;
+  sunindextype muk, mlk, storage_mu, lrw1, liw1;
+  long int lrw, liw;
   int flag;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  /* Test if the NVECTOR package is compatible with BLOCK BAND preconditioner */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_BAD_NVECTOR);
+  /* Test compatibility of NVECTOR package with the BBD preconditioner */
+  if(IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_BAD_NVECTOR);
     return(IDASPILS_ILL_INPUT);
   }
 
@@ -119,7 +99,8 @@ int IDABBDPrecInit(void *ida_mem, long int Nlocal,
   pdata = NULL;
   pdata = (IBBDPrecData) malloc(sizeof *pdata);
   if (pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL);
   }
 
@@ -139,92 +120,201 @@ int IDABBDPrecInit(void *ida_mem, long int Nlocal,
 
   /* Allocate memory for preconditioner matrix. */
   pdata->PP = NULL;
-  pdata->PP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+  pdata->PP = SUNBandMatrix(Nlocal, muk, mlk, storage_mu);
   if (pdata->PP == NULL) { 
     free(pdata); pdata = NULL;
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL); 
   }
 
-  /* Allocate memory for lpivots. */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(Nlocal);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->PP);
+  /* Allocate memory for temporary N_Vectors */
+  pdata->zlocal = NULL;
+  pdata->zlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->zlocal == NULL) {
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", 
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->rlocal = NULL;
+  pdata->rlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->rlocal == NULL) {
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", 
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv1 = NULL;
+  pdata->tempv1 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv1 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv2 = NULL;
+  pdata->tempv2 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv2 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->tempv1);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv3 = NULL;
+  pdata->tempv3 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv3 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv4 = NULL;
+  pdata->tempv4 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv4 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    SUNMatDestroy(pdata->PP);
     free(pdata); pdata = NULL;
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL);
   }
 
-  /* Allocate tempv4 for use by IBBDDQJac */
-  tempv4 = NULL;
-  tempv4 = N_VClone(vec_tmpl); 
-  if (tempv4 == NULL){
-    DestroyMat(pdata->PP);
-    DestroyArray(pdata->lpivots);
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(pdata->rlocal, pdata->PP);
+  if (pdata->LS == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    N_VDestroy(pdata->tempv4);
+    SUNMatDestroy(pdata->PP);
     free(pdata); pdata = NULL;
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL);
   }
-  pdata->tempv4 = tempv4;
-  
+
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    N_VDestroy(pdata->tempv4);
+    SUNMatDestroy(pdata->PP);
+    SUNLinSolFree(pdata->LS);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDABBDPRE",
+                    "IDABBDPrecInit", MSGBBD_SUNLS_FAIL);
+    return(IDASPILS_SUNLS_FAIL);
+  }
+ 
   /* Set rel_yy based on input value dq_rel_yy (0 implies default). */
-  pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : SUNRsqrt(uround); 
+  pdata->rel_yy = (dq_rel_yy > ZERO) ?
+    dq_rel_yy : SUNRsqrt(IDA_mem->ida_uround); 
 
   /* Store Nlocal to be used in IDABBDPrecSetup */
   pdata->n_local = Nlocal;
   
   /* Set work space sizes and initialize nge. */
-  pdata->rpwsize = Nlocal*(mlk + storage_mu + 1);
-  pdata->ipwsize = Nlocal;
+  pdata->rpwsize = 0;
+  pdata->ipwsize = 0;
+  if (IDA_mem->ida_tempv1->ops->nvspace) {
+    N_VSpace(IDA_mem->ida_tempv1, &lrw1, &liw1);
+    pdata->rpwsize += 4*lrw1;
+    pdata->ipwsize += 4*liw1;
+  }
+  if (pdata->rlocal->ops->nvspace) {
+    N_VSpace(pdata->rlocal, &lrw1, &liw1);
+    pdata->rpwsize += 2*lrw1;
+    pdata->ipwsize += 2*liw1;
+  }
+  if (pdata->PP->ops->space) {
+    flag = SUNMatSpace(pdata->PP, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
   pdata->nge = 0;
 
-  /* make sure s_pdata is free from any previous allocations */
-  if (idaspils_mem->s_pfree != NULL) {
-    idaspils_mem->s_pfree(IDA_mem);
-  }
+  /* make sure pdata is free from any previous allocations */
+  if (idaspils_mem->pfree) 
+    idaspils_mem->pfree(IDA_mem);
 
   /* Point to the new pdata field in the SPILS memory */
-  idaspils_mem->s_pdata = pdata;
+  idaspils_mem->pdata = pdata;
 
   /* Attach the pfree function */
-  idaspils_mem->s_pfree = IDABBDPrecFree;
+  idaspils_mem->pfree = IDABBDPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = IDASpilsSetPreconditioner(ida_mem, IDABBDPrecSetup, IDABBDPrecSolve);
+  flag = IDASpilsSetPreconditioner(ida_mem,
+                                   IDABBDPrecSetup,
+                                   IDABBDPrecSolve);
 
   return(flag);
 }
 
-int IDABBDPrecReInit(void *ida_mem,
-		     long int mudq, long int mldq, 
-		     realtype dq_rel_yy)
+
+/*-------------------------------------------------------------*/
+int IDABBDPrecReInit(void *ida_mem, sunindextype mudq,
+                     sunindextype mldq, realtype dq_rel_yy)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
-  long int Nlocal;
-
+  sunindextype Nlocal;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecReInit", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecReInit", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
   /* Test if the preconditioner data is non-NULL */
-  if (idaspils_mem->s_pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_PMEM_NULL);
+  if (idaspils_mem->pdata == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecReInit", MSGBBD_PMEM_NULL);
     return(IDASPILS_PMEM_NULL);
   } 
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
 
   /* Load half-bandwidths. */
   Nlocal = pdata->n_local;
@@ -232,7 +322,8 @@ int IDABBDPrecReInit(void *ida_mem,
   pdata->mldq = SUNMIN(Nlocal-1, SUNMAX(0, mldq));
 
   /* Set rel_yy based on input value dq_rel_yy (0 implies default). */
-  pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : SUNRsqrt(uround); 
+  pdata->rel_yy = (dq_rel_yy > ZERO) ?
+    dq_rel_yy : SUNRsqrt(IDA_mem->ida_uround); 
 
   /* Re-initialize nge */
   pdata->nge = 0;
@@ -240,29 +331,36 @@ int IDABBDPrecReInit(void *ida_mem,
   return(IDASPILS_SUCCESS);
 }
 
-int IDABBDPrecGetWorkSpace(void *ida_mem, long int *lenrwBBDP, long int *leniwBBDP)
+
+/*-------------------------------------------------------------*/
+int IDABBDPrecGetWorkSpace(void *ida_mem,
+                           long int *lenrwBBDP,
+                           long int *leniwBBDP)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  if (idaspils_mem->s_pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
+  if (idaspils_mem->pdata == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
     return(IDASPILS_PMEM_NULL);
   } 
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
 
   *lenrwBBDP = pdata->rpwsize;
   *leniwBBDP = pdata->ipwsize;
@@ -270,29 +368,35 @@ int IDABBDPrecGetWorkSpace(void *ida_mem, long int *lenrwBBDP, long int *leniwBB
   return(IDASPILS_SUCCESS);
 }
 
-int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP)
+
+/*-------------------------------------------------------------*/
+int IDABBDPrecGetNumGfnEvals(void *ida_mem,
+                             long int *ngevalsBBDP)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  if (idaspils_mem->s_pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
+  if (idaspils_mem->pdata == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE",
+                    "IDABBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
     return(IDASPILS_PMEM_NULL);
   } 
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
 
   *ngevalsBBDP = pdata->nge;
 
@@ -300,140 +404,116 @@ int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP)
 }
 
 
-/* Readability Replacements */
-
-#define Nlocal  (pdata->n_local)
-#define mudq    (pdata->mudq)
-#define mldq    (pdata->mldq)
-#define mukeep  (pdata->mukeep)
-#define mlkeep  (pdata->mlkeep)
-#define glocal  (pdata->glocal)
-#define gcomm   (pdata->gcomm)
-#define lpivots (pdata->lpivots)
-#define PP      (pdata->PP)
-#define tempv4  (pdata->tempv4)
-#define nge     (pdata->nge)
-#define rel_yy  (pdata->rel_yy)
+/*---------------------------------------------------------------
+  IDABBDPrecSetup:
 
-/*
- * -----------------------------------------------------------------
- * Function : IDABBDPrecSetup                                     
- * -----------------------------------------------------------------
- * IDABBDPrecSetup generates a band-block-diagonal preconditioner
- * matrix, where the local block (on this processor) is a band
- * matrix. Each local block is computed by a difference quotient
- * scheme via calls to the user-supplied routines glocal, gcomm.
- * After generating the block in the band matrix PP, this routine
- * does an LU factorization in place in PP.
- *
- * The IDABBDPrecSetup parameters used here are as follows:
- *
- * tt is the current value of the independent variable t.
- *
- * yy is the current value of the dependent variable vector,
- *    namely the predicted value of y(t).
- *
- * yp is the current value of the derivative vector y',
- *    namely the predicted value of y'(t).
- *
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *
- * bbd_data is the pointer to BBD memory set by IDABBDInit
- *
- * tmp1, tmp2, tmp3 are pointers to vectors of type
- *                  N_Vector, used for temporary storage or
- *                  work space.
- *
- * The arguments Neq, rr, res, uround, and nrePtr are not used.
- *
- * Return value:
- * The value returned by this IDABBDPrecSetup function is a int
- * flag indicating whether it was successful. This value is
- *    0    if successful,
- *  > 0    for a recoverable error (step will be retried), or
- *  < 0    for a nonrecoverable error (step fails).
- * -----------------------------------------------------------------
- */
-
-static int IDABBDPrecSetup(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           realtype c_j, void *bbd_data,
-                           N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+  IDABBDPrecSetup generates a band-block-diagonal preconditioner
+  matrix, where the local block (on this processor) is a band
+  matrix. Each local block is computed by a difference quotient
+  scheme via calls to the user-supplied routines glocal, gcomm.
+  After generating the block in the band matrix PP, this routine
+  does an LU factorization in place in PP.
+ 
+  The IDABBDPrecSetup parameters used here are as follows:
+ 
+  tt is the current value of the independent variable t.
+ 
+  yy is the current value of the dependent variable vector,
+     namely the predicted value of y(t).
+ 
+  yp is the current value of the derivative vector y',
+     namely the predicted value of y'(t).
+ 
+  c_j is the scalar in the system Jacobian, proportional to 1/hh.
+ 
+  bbd_data is the pointer to BBD memory set by IDABBDInit
+ 
+  The argument rr is not used.
+ 
+  Return value:
+  The value returned by this IDABBDPrecSetup function is a int
+  flag indicating whether it was successful. This value is
+     0    if successful,
+   > 0    for a recoverable error (step will be retried), or
+   < 0    for a nonrecoverable error (step fails).
+ ----------------------------------------------------------------*/
+static int IDABBDPrecSetup(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, realtype c_j, void *bbd_data)
 {
-  int retval;
-  long int ier;
+  sunindextype ier;
   IBBDPrecData pdata;
   IDAMem IDA_mem;
+  int retval;
 
   pdata =(IBBDPrecData) bbd_data;
 
   IDA_mem = (IDAMem) pdata->ida_mem;
 
   /* Call IBBDDQJac for a new Jacobian calculation and store in PP. */
-  SetToZero(PP);
-  retval = IBBDDQJac(pdata, tt, c_j, yy, yp,
-                     tempv1, tempv2, tempv3, tempv4);
+  retval = SUNMatZero(pdata->PP);
+  retval = IBBDDQJac(pdata, tt, c_j, yy, yp, pdata->tempv1,
+                     pdata->tempv2, pdata->tempv3, pdata->tempv4);
   if (retval < 0) {
-    IDAProcessError(IDA_mem, -1, "IDABBDPRE", "IDABBDPrecSetup", MSGBBD_FUNC_FAILED);
+    IDAProcessError(IDA_mem, -1, "IDABBDPRE", "IDABBDPrecSetup",
+                    MSGBBD_FUNC_FAILED);
     return(-1);
   }
   if (retval > 0) {
-    return(+1);
+    return(1);
   } 
  
-  /* Do LU factorization of preconditioner block in place (in PP). */
-  ier = BandGBTRF(PP, lpivots);
-
-  /* Return 0 if the LU was complete, or +1 otherwise. */
-  if (ier > 0) return(+1);
-  return(0);
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->PP);
+  return(ier);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function: IDABBDPrecSolve
- * -----------------------------------------------------------------
- * The function IDABBDPrecSolve computes a solution to the linear
- * system P z = r, where P is the left preconditioner defined by
- * the routine IDABBDPrecSetup.
- *
- * The IDABBDPrecSolve parameters used here are as follows:
- *
- * rvec is the input right-hand side vector r.
- *
- * zvec is the computed solution vector z.
- *
- * bbd_data is the pointer to BBD data set by IDABBDInit.
- *
- * The arguments tt, yy, yp, rr, c_j, delta, and tmp are NOT used.
- *
- * IDABBDPrecSolve always returns 0, indicating success.
- * -----------------------------------------------------------------
- */
 
-static int IDABBDPrecSolve(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           N_Vector rvec, N_Vector zvec,
-                           realtype c_j, realtype delta, void *bbd_data,
-                           N_Vector tmp)
+/*---------------------------------------------------------------
+  IDABBDPrecSolve
+
+  The function IDABBDPrecSolve computes a solution to the linear
+  system P z = r, where P is the left preconditioner defined by
+  the routine IDABBDPrecSetup.
+ 
+  The IDABBDPrecSolve parameters used here are as follows:
+ 
+  rvec is the input right-hand side vector r.
+ 
+  zvec is the computed solution vector z.
+ 
+  bbd_data is the pointer to BBD data set by IDABBDInit.
+ 
+  The arguments tt, yy, yp, rr, c_j and delta are NOT used.
+ 
+  IDABBDPrecSolve returns the value returned from the linear 
+  solver object.
+  ---------------------------------------------------------------*/
+static int IDABBDPrecSolve(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, N_Vector rvec, N_Vector zvec,
+                           realtype c_j, realtype delta, void *bbd_data)
 {
   IBBDPrecData pdata;
-  realtype *zd;
-
+  int retval;
+  
   pdata = (IBBDPrecData) bbd_data;
 
-  /* Copy rvec to zvec, do the backsolve, and return. */
-  N_VScale(ONE, rvec, zvec);
-
-  zd = N_VGetArrayPointer(zvec);
+  /* Attach local data arrays for rvec and zvec to rlocal and zlocal */
+  N_VSetArrayPointer(N_VGetArrayPointer(rvec), pdata->rlocal);
+  N_VSetArrayPointer(N_VGetArrayPointer(zvec), pdata->zlocal);
+  
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->PP, pdata->zlocal, 
+                          pdata->rlocal, ZERO);
 
-  BandGBTRS(PP, lpivots, zd);
+  /* Detach local data arrays from rlocal and zlocal */
+  N_VSetArrayPointer(NULL, pdata->rlocal);
+  N_VSetArrayPointer(NULL, pdata->zlocal);
 
-  return(0);
+  return(retval);
 }
 
 
-
+/*-------------------------------------------------------------*/
 static int IDABBDPrecFree(IDAMem IDA_mem)
 {
   IDASpilsMem idaspils_mem;
@@ -442,12 +522,17 @@ static int IDABBDPrecFree(IDAMem IDA_mem)
   if (IDA_mem->ida_lmem == NULL) return(0);
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
   
-  if (idaspils_mem->s_pdata == NULL) return(0);
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
-
-  DestroyMat(PP);
-  DestroyArray(lpivots);
-  N_VDestroy(tempv4);
+  if (idaspils_mem->pdata == NULL) return(0);
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
+
+  SUNLinSolFree(pdata->LS);
+  N_VDestroy(pdata->rlocal);
+  N_VDestroy(pdata->zlocal);
+  N_VDestroy(pdata->tempv1);
+  N_VDestroy(pdata->tempv2);
+  N_VDestroy(pdata->tempv3);
+  N_VDestroy(pdata->tempv4);
+  SUNMatDestroy(pdata->PP);
 
   free(pdata);
   pdata = NULL;
@@ -456,40 +541,32 @@ static int IDABBDPrecFree(IDAMem IDA_mem)
 }
 
 
-#define ewt         (IDA_mem->ida_ewt)
-#define user_data   (IDA_mem->ida_user_data)
-#define hh          (IDA_mem->ida_hh)
-#define constraints (IDA_mem->ida_constraints)
-
-/*
- * -----------------------------------------------------------------
- * IBBDDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation
- * to the local block of the Jacobian of G(t,y,y'). It assumes that
- * a band matrix of type BandMat is stored column-wise, and that
- * elements within each column are contiguous.
- *
- * All matrix elements are generated as difference quotients, by way
- * of calls to the user routine glocal. By virtue of the band
- * structure, the number of these calls is bandwidth + 1, where
- * bandwidth = mldq + mudq + 1. But the band matrix kept has
- * bandwidth = mlkeep + mukeep + 1. This routine also assumes that
- * the local elements of a vector are stored contiguously.
- *
- * Return values are: 0 (success), > 0 (recoverable error),
- * or < 0 (nonrecoverable error).
- * -----------------------------------------------------------------
- */
+/*---------------------------------------------------------------
+  IBBDDQJac
 
+  This routine generates a banded difference quotient approximation
+  to the local block of the Jacobian of G(t,y,y'). It assumes that
+  a band matrix of type SUNMatrix is stored column-wise, and that
+  elements within each column are contiguous.
+ 
+  All matrix elements are generated as difference quotients, by way
+  of calls to the user routine glocal. By virtue of the band
+  structure, the number of these calls is bandwidth + 1, where
+  bandwidth = mldq + mudq + 1. But the band matrix kept has
+  bandwidth = mlkeep + mukeep + 1. This routine also assumes that
+  the local elements of a vector are stored contiguously.
+ 
+  Return values are: 0 (success), > 0 (recoverable error),
+  or < 0 (nonrecoverable error).
+  ----------------------------------------------------------------*/
 static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
                      N_Vector yy, N_Vector yp, N_Vector gref, 
                      N_Vector ytemp, N_Vector yptemp, N_Vector gtemp)
 {
   IDAMem IDA_mem;
   realtype inc, inc_inv;
-  int  retval;
-  long int group, i, j, width, ngroups, i1, i2;
+  int retval;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *ydata, *ypdata, *ytempdata, *yptempdata, *grefdata, *gtempdata;
   realtype *cnsdata = NULL, *ewtdata;
   realtype *col_j, conj, yj, ypj, ewtj;
@@ -497,44 +574,39 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
   IDA_mem = (IDAMem) pdata->ida_mem;
 
   /* Initialize ytemp and yptemp. */
-
   N_VScale(ONE, yy, ytemp);
   N_VScale(ONE, yp, yptemp);
 
   /* Obtain pointers as required to the data array of vectors. */
-
   ydata     = N_VGetArrayPointer(yy);
   ypdata    = N_VGetArrayPointer(yp);
   gtempdata = N_VGetArrayPointer(gtemp);
-  ewtdata   = N_VGetArrayPointer(ewt);
-  if (constraints != NULL) 
-    cnsdata = N_VGetArrayPointer(constraints);
+  ewtdata   = N_VGetArrayPointer(IDA_mem->ida_ewt);
+  if (IDA_mem->ida_constraints != NULL) 
+    cnsdata = N_VGetArrayPointer(IDA_mem->ida_constraints);
   ytempdata = N_VGetArrayPointer(ytemp);
   yptempdata= N_VGetArrayPointer(yptemp);
   grefdata = N_VGetArrayPointer(gref);
 
   /* Call gcomm and glocal to get base value of G(t,y,y'). */
-
-  if (gcomm != NULL) {
-    retval = gcomm(Nlocal, tt, yy, yp, user_data);
+  if (pdata->gcomm != NULL) {
+    retval = pdata->gcomm(pdata->n_local, tt, yy, yp, IDA_mem->ida_user_data);
     if (retval != 0) return(retval);
   }
 
-  retval = glocal(Nlocal, tt, yy, yp, gref, user_data); 
-  nge++;
+  retval = pdata->glocal(pdata->n_local, tt, yy, yp, gref, IDA_mem->ida_user_data); 
+  pdata->nge++;
   if (retval != 0) return(retval);
 
-
   /* Set bandwidth and number of column groups for band differencing. */
-
-  width = mldq + mudq + 1;
-  ngroups = SUNMIN(width, Nlocal);
+  width = pdata->mldq + pdata->mudq + 1;
+  ngroups = SUNMIN(width, pdata->n_local);
 
   /* Loop over groups. */
   for(group = 1; group <= ngroups; group++) {
     
     /* Loop over the components in this group. */
-    for(j = group-1; j < Nlocal; j += width) {
+    for(j = group-1; j < pdata->n_local; j += width) {
       yj = ydata[j];
       ypj = ypdata[j];
       ewtj = ewtdata[j];
@@ -542,12 +614,13 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
       /* Set increment inc to yj based on rel_yy*abs(yj), with
          adjustments using ypj and ewtj if this is small, and a further
          adjustment to give it the same sign as hh*ypj. */
-      inc = rel_yy*SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(hh*ypj), ONE/ewtj));
-      if (hh*ypj < ZERO) inc = -inc;
+      inc = pdata->rel_yy *
+        SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(IDA_mem->ida_hh*ypj), ONE/ewtj));
+      if (IDA_mem->ida_hh*ypj < ZERO)  inc = -inc;
       inc = (yj + inc) - yj;
       
       /* Adjust sign(inc) again if yj has an inequality constraint. */
-      if (constraints != NULL) {
+      if (IDA_mem->ida_constraints != NULL) {
         conj = cnsdata[j];
         if (SUNRabs(conj) == ONE)      {if ((yj+inc)*conj <  ZERO) inc = -inc;}
         else if (SUNRabs(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
@@ -560,22 +633,23 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
     }
 
     /* Evaluate G with incremented y and yp arguments. */
-
-    retval = glocal(Nlocal, tt, ytemp, yptemp, gtemp, user_data); 
-    nge++;
+    retval = pdata->glocal(pdata->n_local, tt, ytemp, yptemp,
+                           gtemp, IDA_mem->ida_user_data); 
+    pdata->nge++;
     if (retval != 0) return(retval);
 
     /* Loop over components of the group again; restore ytemp and yptemp. */
-    for(j = group-1; j < Nlocal; j += width) {
+    for(j = group-1; j < pdata->n_local; j += width) {
       yj  = ytempdata[j]  = ydata[j];
       ypj = yptempdata[j] = ypdata[j];
       ewtj = ewtdata[j];
 
       /* Set increment inc as before .*/
-      inc = rel_yy*SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(hh*ypj), ONE/ewtj));
-      if (hh*ypj < ZERO) inc = -inc;
+      inc = pdata->rel_yy *
+        SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(IDA_mem->ida_hh*ypj), ONE/ewtj));
+      if (IDA_mem->ida_hh*ypj < ZERO)  inc = -inc;
       inc = (yj + inc) - yj;
-      if (constraints != NULL) {
+      if (IDA_mem->ida_constraints != NULL) {
         conj = cnsdata[j];
         if (SUNRabs(conj) == ONE)      {if ((yj+inc)*conj <  ZERO) inc = -inc;}
         else if (SUNRabs(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
@@ -583,11 +657,12 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
 
       /* Form difference quotients and load into PP. */
       inc_inv = ONE/inc;
-      col_j = BAND_COL(PP,j);
-      i1 = SUNMAX(0, j-mukeep);
-      i2 = SUNMIN(j+mlkeep, Nlocal-1);
-      for(i = i1; i <= i2; i++) BAND_COL_ELEM(col_j,i,j) =
-                                  inc_inv * (gtempdata[i] - grefdata[i]);
+      col_j = SUNBandMatrix_Column(pdata->PP,j);
+      i1 = SUNMAX(0, j - pdata->mukeep);
+      i2 = SUNMIN(j + pdata->mlkeep, pdata->n_local-1);
+      for(i=i1; i <= i2; i++)
+        SM_COLUMN_ELEMENT_B(col_j,i,j) =
+          inc_inv * (gtempdata[i] - grefdata[i]);
     }
   }
   
diff --git a/src/ida/ida_bbdpre_impl.h b/src/ida/ida_bbdpre_impl.h
index a9ef672..e354a52 100644
--- a/src/ida/ida_bbdpre_impl.h
+++ b/src/ida/ida_bbdpre_impl.h
@@ -1,32 +1,33 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*-----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
  * This is the header file (private version) for the IDABBDPRE
  * module, for a band-block-diagonal preconditioner, i.e. a
  * block-diagonal matrix with banded blocks, for use with IDA
  * and an IDASPILS linear solver.
- * -----------------------------------------------------------------
- */
+ *-----------------------------------------------------------------*/
 
 #ifndef _IDABBDPRE_IMPL_H
 #define _IDABBDPRE_IMPL_H
 
 #include <ida/ida_bbdpre.h>
-#include <sundials/sundials_band.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -42,33 +43,29 @@ typedef struct IBBDPrecDataRec {
 
   /* passed by user to IDABBDPrecAlloc and used by
      IDABBDPrecSetup/IDABBDPrecSolve functions */
-
-  long int mudq, mldq, mukeep, mlkeep;
+  sunindextype mudq, mldq, mukeep, mlkeep;
   realtype rel_yy;
   IDABBDLocalFn glocal;
   IDABBDCommFn gcomm;
 
-  /* allocated for use by IDABBDPrecSetup */
-
+  /* set by IDABBDPrecSetup and used by IDABBDPrecSetup and 
+     IDABBDPrecSolve functions */
+  sunindextype n_local;
+  SUNMatrix PP;
+  SUNLinearSolver LS;
+  N_Vector zlocal;
+  N_Vector rlocal;
+  N_Vector tempv1;
+  N_Vector tempv2;
+  N_Vector tempv3;
   N_Vector tempv4;
 
-  /* set by IDABBDPrecon and used by IDABBDPrecSolve */
-
-  DlsMat PP;
-  long int *lpivots;
-
-  /* set by IDABBDPrecAlloc and used by IDABBDPrecSetup */
-
-  long int n_local;
-
   /* available for optional output */
-
   long int rpwsize;
   long int ipwsize;
   long int nge;
 
   /* pointer to ida_mem */
-
   void *ida_mem;
 
 } *IBBDPrecData;
@@ -83,6 +80,8 @@ typedef struct IBBDPrecDataRec {
 #define MSGBBD_LMEM_NULL   "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBBD_MEM_FAIL    "A memory request failed."
 #define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGBBD_SUNMAT_FAIL "An error arose from a SUNBandMatrix routine."
+#define MSGBBD_SUNLS_FAIL  "An error arose from a SUNBandLinearSolver routine."
 #define MSGBBD_PMEM_NULL   "BBD peconditioner memory is NULL. IDABBDPrecInit must be called."
 #define MSGBBD_FUNC_FAILED "The Glocal or Gcomm routine failed in an unrecoverable manner."
 
diff --git a/src/ida/ida_dense.c b/src/ida/ida_dense.c
deleted file mode 100644
index f98b168..0000000
--- a/src/ida/ida_dense.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4951 $
- * $Date: 2016-09-22 10:21:00 -0700 (Thu, 22 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDADENSE linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <ida/ida_dense.h>
-#include "ida_direct_impl.h"
-#include "ida_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* IDADENSE linit, lsetup, lsolve, and lfree routines */
- 
-static int IDADenseInit(IDAMem IDA_mem);
-
-static int IDADenseSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                         N_Vector rrp, N_Vector tmp1,
-                         N_Vector tmp2, N_Vector tmp3);
-
-static int IDADenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                         N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDADenseFree(IDAMem IDA_mem);
-
-/* Readability Replacements */
-
-#define res          (IDA_mem->ida_res)
-#define tn           (IDA_mem->ida_tn)
-#define hh           (IDA_mem->ida_hh)
-#define cj           (IDA_mem->ida_cj)
-#define cjratio      (IDA_mem->ida_cjratio)
-#define ewt          (IDA_mem->ida_ewt)
-#define constraints  (IDA_mem->ida_constraints)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define mtype        (idadls_mem->d_type)
-#define neq          (idadls_mem->d_n)
-#define jacDQ        (idadls_mem->d_jacDQ)
-#define djac         (idadls_mem->d_djac)
-#define JJ           (idadls_mem->d_J)
-#define lpivots      (idadls_mem->d_lpivots)
-#define nje          (idadls_mem->d_nje)
-#define nreDQ        (idadls_mem->d_nreDQ)
-#define jacdata      (idadls_mem->d_J_data)
-#define last_flag    (idadls_mem->d_last_flag)
-                  
-/*
- * -----------------------------------------------------------------
- * IDADense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDADENSE linear solver module.  
- * IDADense first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDADenseInit, IDADenseSetup,
- * IDADenseSolve, NULL, and IDADenseFree, respectively.
- * It allocates memory for a structure of type IDADlsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jdata field
- * in the IDADlsMemRec structure to be the input parameter jdata,
- * and sets the d_jac field to be:
- *   (1) the input parameter djac, if djac != NULL, or                
- *   (2) IDADenseDQJac, if djac == NULL.                             
- * Finally, it allocates memory for JJ and lpivots.
- * The return value is IDADLS_SUCCESS = 0, IDADLS_LMEM_FAIL = -1,
- * or IDADLS_ILL_INPUT = -2.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDADense will first 
- *       test for a compatible N_Vector internal
- *       representation by checking that the functions N_VGetArrayPointer
- *       and N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-int IDADense(void *ida_mem, long int Neq)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADENSE", "IDADense", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL ||
-     vec_tmpl->ops->nvsetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDADENSE", "IDADense", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(IDA_mem);
-
-  /* Set five main function fields in IDA_mem. */
-  linit  = IDADenseInit;
-  lsetup = IDADenseSetup;
-  lsolve = IDADenseSolve;
-  lperf  = NULL;
-  lfree  = IDADenseFree;
-
-  /* Get memory for IDADlsMemRec. */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADENSE", "IDADense", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ   = TRUE;
-  djac    = NULL;
-  jacdata = NULL;
-
-  last_flag = IDADLS_SUCCESS;
-
-  idaDlsInitializeCounters(idadls_mem);
-
-  setupNonNull = TRUE;
-
-  /* Store problem size */
-  neq = Neq;
-
-  /* Allocate memory for JJ and pivot array. */
-  JJ = NULL;
-  JJ = NewDenseMat(Neq, Neq);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADENSE", "IDADense", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  lpivots = NULL;
-  lpivots = NewLintArray(Neq);
-  if (lpivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADENSE", "IDADense", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDADENSE interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDADENSE
-  linear solver module.  It returns 0.
-*/
-
-static int IDADenseInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-  
-  idadls_mem = (IDADlsMem) lmem;
-
-  idaDlsInitializeCounters(idadls_mem);
-  /*
-   nje   = 0;
-   nreDQ = 0;
-  */
-
-  if (jacDQ) {
-    djac = idaDlsDenseDQJac;
-    jacdata = IDA_mem;
-  } else {
-    jacdata = IDA_mem->ida_user_data;
-  }
-  
-  last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the IDADENSE linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the dense LU factorization routine.
-  The return value is either
-     IDADLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDADenseSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                         N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-                         N_Vector tmp3)
-{
-  int retval;
-  long int retfac;
-  IDADlsMem idadls_mem;
-  
-  idadls_mem = (IDADlsMem) lmem;
-
-  /* Increment nje counter. */
-  nje++;
-
-  /* Zero out JJ; call Jacobian routine jac; return if it failed. */
-  SetToZero(JJ);
-  retval = djac(neq, tn, cj, yyp, ypp, rrp, JJ, jacdata, 
-                tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDADENSE", "IDADenseSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  /* Do LU factorization of JJ; return success or fail flag. */
-  retfac = DenseGETRF(JJ, lpivots);
-
-  if (retfac != 0) {
-    last_flag = retfac;
-    return(+1);
-  }
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the IDADENSE linear
-  solver module.  It calls the dense backsolve routine, scales the
-  solution vector according to cjratio, then returns IDADLS_SUCCESS = 0.
-*/
-
-static int IDADenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                         N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd;
-  
-  idadls_mem = (IDADlsMem) lmem;
-  
-  bd = N_VGetArrayPointer(b);
-
-  DenseGETRS(JJ, lpivots, bd);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-
-  last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine frees memory specific to the IDADENSE linear solver.
-*/
-
-static int IDADenseFree(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(lpivots);
-  free(lmem); lmem = NULL;
-
-  return(0);
-}
diff --git a/src/ida/ida_direct.c b/src/ida/ida_direct.c
index 9f7d403..ef0b912 100644
--- a/src/ida/ida_direct.c
+++ b/src/ida/ida_direct.c
@@ -1,29 +1,24 @@
-/*
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for an IDADLS linear solver.
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
+ * This is the implementation file for an IDADLS linear solver 
+ * interface
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,215 +26,258 @@
 #include "ida_impl.h"
 #include "ida_direct_impl.h"
 #include <sundials/sundials_math.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
+/*=================================================================
+  FUNCTION SPECIFIC CONSTANTS
+  =================================================================*/
 
 #define ZERO         RCONST(0.0)
 #define ONE          RCONST(1.0)
 #define TWO          RCONST(2.0)
 
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define res            (IDA_mem->ida_res)
-#define user_data      (IDA_mem->ida_user_data)
-#define uround         (IDA_mem->ida_uround)
-#define nst            (IDA_mem->ida_nst)
-#define tn             (IDA_mem->ida_tn)
-#define hh             (IDA_mem->ida_hh)
-#define cj             (IDA_mem->ida_cj)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define ewt            (IDA_mem->ida_ewt)
-#define constraints    (IDA_mem->ida_constraints)
-
-#define linit          (IDA_mem->ida_linit)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve)
-#define lfree          (IDA_mem->ida_lfree)
-#define lperf          (IDA_mem->ida_lperf)
-#define lmem           (IDA_mem->ida_lmem)
-#define tempv          (IDA_mem->ida_tempv1)
-#define setupNonNull   (IDA_mem->ida_setupNonNull)
-
-#define mtype          (idadls_mem->d_type)
-#define n              (idadls_mem->d_n)
-#define ml             (idadls_mem->d_ml)
-#define mu             (idadls_mem->d_mu)
-#define smu            (idadls_mem->d_smu)
-#define jacDQ          (idadls_mem->d_jacDQ)
-#define djac           (idadls_mem->d_djac)
-#define bjac           (idadls_mem->d_bjac)
-#define M              (idadls_mem->d_J)
-#define pivots         (idadls_mem->d_pivots)
-#define nje            (idadls_mem->d_nje)
-#define nreDQ          (idadls_mem->d_nreDQ)
-#define last_flag      (idadls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * IDADlsSetDenseJacFn specifies the dense Jacobian function.
- */
-int IDADlsSetDenseJacFn(void *ida_mem, IDADlsDenseJacFn jac)
+/*===============================================================
+  IDADLS Exported functions -- Required
+  ===============================================================*/
+
+/*---------------------------------------------------------------
+  IDADlsSetLinearSolver specifies the direct linear solver.
+  ---------------------------------------------------------------*/
+int IDADlsSetLinearSolver(void *ida_mem, SUNLinearSolver LS,
+                          SUNMatrix A)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsSetDenseJacFn", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", 
+                    "IDADlsSetLinearSolver", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
+  if ( (LS == NULL)  || (A == NULL) ) {
+    IDAProcessError(NULL, IDADLS_ILL_INPUT, "IDADLS", 
+                    "IDADlsSetLinearSolver",
+                    "Both LS and A must be non-NULL");
+    return(IDADLS_ILL_INPUT);
+  }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsSetDenseJacFn", MSGD_LMEM_NULL);
-    return(IDADLS_LMEM_NULL);
+  /* Test if solver and vector are compatible with DLS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
+    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDADLS", 
+                    "IDADlsSetLinearSolver", 
+                    "Non-direct LS supplied to IDADls interface");
+    return(IDADLS_ILL_INPUT);
+  }
+  if (IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL ||
+      IDA_mem->ida_tempv1->ops->nvsetarraypointer == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDADLS", 
+                    "IDADlsSetLinearSolver", MSGD_BAD_NVECTOR);
+    return(IDADLS_ILL_INPUT);
   }
-  idadls_mem = (IDADlsMem) lmem;
 
-  if (jac != NULL) {
-    jacDQ = FALSE;
-    djac = jac;
-  } else {
-    jacDQ = TRUE;
+  /* free any existing system solver attached to IDA */
+  if (IDA_mem->ida_lfree)  IDA_mem->ida_lfree(IDA_mem);
+
+  /* Set four main system linear solver function fields in IDA_mem */
+  IDA_mem->ida_linit  = idaDlsInitialize;
+  IDA_mem->ida_lsetup = idaDlsSetup;
+  IDA_mem->ida_lsolve = idaDlsSolve;
+  IDA_mem->ida_lperf  = NULL;
+  IDA_mem->ida_lfree  = idaDlsFree;
+  
+  /* Get memory for IDADlsMemRec */
+  idadls_mem = NULL;
+  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
+  if (idadls_mem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADLS",
+                    "IDADlsSetLinearSolver", MSGD_MEM_FAIL);
+    return(IDADLS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer */
+  idadls_mem->LS = LS;
+  
+  /* set SUNMatrix pointer */
+  idadls_mem->J = A;
+
+  /* Initialize Jacobian-related data */
+  idadls_mem->jacDQ     = SUNTRUE;
+  idadls_mem->jac       = idaDlsDQJac;
+  idadls_mem->J_data    = IDA_mem;
+  idadls_mem->last_flag = IDADLS_SUCCESS;
+
+  /* Initialize counters */
+  idaDlsInitializeCounters(idadls_mem);
+
+  /* Allocate memory for x */
+  idadls_mem->x = N_VClone(IDA_mem->ida_tempv1);
+  if (idadls_mem->x == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDADLS", 
+                    "IDADlsSetLinearSolver", MSGD_MEM_FAIL);
+    free(idadls_mem); idadls_mem = NULL;
+    return(IDADLS_MEM_FAIL);
   }
+  
+  /* Attach linear solver memory to integrator memory */
+  IDA_mem->ida_lmem = idadls_mem;
 
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsSetBandJacFn specifies the band Jacobian function.
- */
-int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac)
+
+/*===============================================================
+  IDADLS Exported functions -- Optional input/output
+  ===============================================================*/
+
+/*---------------------------------------------------------------
+  IDADlsSetJacFn specifies the Jacobian function.
+  ---------------------------------------------------------------*/
+int IDADlsSetJacFn(void *ida_mem, IDADlsJacFn jac)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsSetBandJacFn", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS",
+                    "IDADlsSetJacFn", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsSetBandJacFn", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS",
+                    "IDADlsSetJacFn", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
   if (jac != NULL) {
-    jacDQ = FALSE;
-    bjac = jac;
+    idadls_mem->jacDQ  = SUNFALSE;
+    idadls_mem->jac    = jac;
+    idadls_mem->J_data = IDA_mem->ida_user_data;
   } else {
-    jacDQ = TRUE;
+    idadls_mem->jacDQ  = SUNTRUE;
+    idadls_mem->jac    = idaDlsDQJac;
+    idadls_mem->J_data = IDA_mem;
   }
 
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetWorkSpace returns the length of workspace allocated for the
- * IDALAPACK linear solver.
- */
-int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS)
+/*---------------------------------------------------------------
+  IDADlsGetWorkSpace returns the length of workspace allocated 
+  for the IDADLS linear solver interface
+  ---------------------------------------------------------------*/
+int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS,
+                       long int *leniwLS)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetWorkSpace", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS",
+                    "IDADlsGetWorkSpace", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetWorkSpace", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS",
+                    "IDADlsGetWorkSpace", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* initialize outputs with requirements from IDADlsMem structure */
+  *lenrwLS = 0;
+  *leniwLS = 3;
+
+  /* add vector sizes */
+  if (idadls_mem->x->ops->nvspace) {
+    N_VSpace(idadls_mem->x, &lrw1, &liw1);
+    *lenrwLS += lrw1;
+    *leniwLS += liw1;
+  }
 
-  if (mtype == SUNDIALS_DENSE) {
-    *lenrwLS = n*n;
-    *leniwLS = n;
-  } else if (mtype == SUNDIALS_BAND) {
-    *lenrwLS = n*(smu + ml + 1);
-    *leniwLS = n;
+  /* add LS sizes */
+  if (idadls_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(idadls_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
-    
+
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetNumJacEvals returns the number of Jacobian evaluations.
+  ---------------------------------------------------------------*/
 int IDADlsGetNumJacEvals(void *ida_mem, long int *njevals)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetNumJacEvals", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS",
+                    "IDADlsGetNumJacEvals", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetNumJacEvals", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS",
+                    "IDADlsGetNumJacEvals", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  *njevals = nje;
+  *njevals = idadls_mem->nje;
 
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetNumResEvals returns the number of calls to the DAE function
- * needed for the DQ Jacobian approximation.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetNumResEvals returns the number of calls to the DAE 
+  function needed for the DQ Jacobian approximation.
+  ---------------------------------------------------------------*/
 int IDADlsGetNumResEvals(void *ida_mem, long int *nrevalsLS)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetNumFctEvals", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS",
+                    "IDADlsGetNumResEvals", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetNumFctEvals", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS",
+                    "IDADlsGetNumResEvals", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  *nrevalsLS = nreDQ;
+  *nrevalsLS = idadls_mem->nreDQ;
 
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetReturnFlagName returns the name associated with a IDALAPACK
- * return value.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetReturnFlagName returns the name associated with a 
+  IDADLS return value.
+  ---------------------------------------------------------------*/
 char *IDADlsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -268,6 +306,9 @@ char *IDADlsGetReturnFlagName(long int flag)
   case IDADLS_JACFUNC_RECVR:
     sprintf(name,"IDADLS_JACFUNC_RECVR");
     break;
+  case IDADLS_SUNMAT_FAIL:
+    sprintf(name,"IDADLS_SUNMAT_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -275,91 +316,132 @@ char *IDADlsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * IDADlsGetLastFlag returns the last flag set in a IDALAPACK function.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetLastFlag returns the last flag set in a IDADLS function.
+  ---------------------------------------------------------------*/
 int IDADlsGetLastFlag(void *ida_mem, long int *flag)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", "IDADlsGetLastFlag", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS",
+                    "IDADlsGetLastFlag", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", "IDADlsGetLastFlag", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS",
+                    "IDADlsGetLastFlag", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  *flag = last_flag;
+  *flag = idadls_mem->last_flag;
 
   return(IDADLS_SUCCESS);
 }
 
-/* 
- * =================================================================
- * DQ JACOBIAN APPROXIMATIONS
- * =================================================================
- */
 
-/*
- * -----------------------------------------------------------------
- * idaDlsDenseDQJac 
- * -----------------------------------------------------------------
- * This routine generates a dense difference quotient approximation to
- * the Jacobian F_y + c_j*F_y'. It assumes that a dense matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. The address of the jth column of J is obtained via
- * the macro LAPACK_DENSE_COL and this pointer is associated with an N_Vector
- * using the N_VGetArrayPointer/N_VSetArrayPointer functions. 
- * Finally, the actual computation of the jth column of the Jacobian is 
- * done with a call to N_VLinearSum.
- * -----------------------------------------------------------------
- */ 
-int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
-                     N_Vector yy, N_Vector yp, N_Vector rr, 
-                     DlsMat Jac, void *data,
-                     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+/*===============================================================
+  IDADLS Private functions
+  ===============================================================*/
+
+/*---------------------------------------------------------------
+  idaDlsDQJac:
+
+  This routine is a wrapper for the Dense and Band 
+  implementations of the difference quotient Jacobian 
+  approximation routines.
+---------------------------------------------------------------*/
+int idaDlsDQJac(realtype t, realtype c_j, N_Vector y,  
+                N_Vector yp, N_Vector r, SUNMatrix Jac, 
+                void *ida_mem, N_Vector tmp1, N_Vector tmp2,
+                N_Vector tmp3)
+{
+  int retval;
+  IDAMem IDA_mem;
+  IDA_mem = (IDAMem) ida_mem;
+
+  /* verify that Jac is non-NULL */
+  if (Jac == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", 
+		    "idaDlsDQJac", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
+  }
+
+  if (SUNMatGetID(Jac) == SUNMATRIX_DENSE) {
+    retval = idaDlsDenseDQJac(t, c_j, y, yp, r, Jac, IDA_mem, tmp1);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_BAND) {
+    retval = idaDlsBandDQJac(t, c_j, y, yp, r, Jac, IDA_mem, tmp1, tmp2, tmp3);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_SPARSE) {
+    IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDADLS", 
+		    "idaDlsDQJac", 
+                    "idaDlsDQJac not implemented for SUNMATRIX_SPARSE");
+    retval = IDA_ILL_INPUT;
+  } else {
+    IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDADLS", 
+		    "idaDlsDQJac", 
+                    "unrecognized matrix type for idaDlsDQJac");
+    retval = IDA_ILL_INPUT;
+  }
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+  idaDlsDenseDQJac 
+
+  This routine generates a dense difference quotient approximation
+  to the Jacobian F_y + c_j*F_y'. It assumes a dense SUNmatrix 
+  input (stored column-wise, and that elements within each column
+  are contiguous). The address of the jth column of J is obtained 
+  via the function SUNDenseMatrix_Column() and this pointer is 
+  associated with an N_Vector using the 
+  N_VGetArrayPointer/N_VSetArrayPointer functions.  Finally, the 
+  actual computation of the jth column of the Jacobian is 
+  done with a call to N_VLinearSum.
+---------------------------------------------------------------*/
+int idaDlsDenseDQJac(realtype tt, realtype c_j, N_Vector yy, 
+                     N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                     IDAMem IDA_mem, N_Vector tmp1)
 {
   realtype inc, inc_inv, yj, ypj, srur, conj;
-  realtype *tmp2_data, *y_data, *yp_data, *ewt_data, *cns_data = NULL;
+  realtype *y_data, *yp_data, *ewt_data, *cns_data = NULL;
   N_Vector rtemp, jthCol;
-  long int j;
+  sunindextype j, N;
   int retval = 0;
-
-  IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* data points to IDA_mem */
-  IDA_mem = (IDAMem) data;
-  idadls_mem = (IDADlsMem) lmem;
+  /* access DlsMem interface structure */
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  /* Save pointer to the array in tmp2 */
-  tmp2_data = N_VGetArrayPointer(tmp2);
+  /* access matrix dimension */
+  N = SUNDenseMatrix_Rows(Jac);
 
   /* Rename work vectors for readibility */
-  rtemp  = tmp1;
-  jthCol = tmp2;
+  rtemp = tmp1;
 
+  /* Create an empty vector for matrix column calculations */
+  jthCol = N_VCloneEmpty(tmp1);
+  
   /* Obtain pointers to the data for ewt, yy, yp. */
-  ewt_data = N_VGetArrayPointer(ewt);
+  ewt_data = N_VGetArrayPointer(IDA_mem->ida_ewt);
   y_data   = N_VGetArrayPointer(yy);
   yp_data  = N_VGetArrayPointer(yp);
-  if(constraints!=NULL) cns_data = N_VGetArrayPointer(constraints);
+  if(IDA_mem->ida_constraints!=NULL)
+    cns_data = N_VGetArrayPointer(IDA_mem->ida_constraints);
 
-  srur = SUNRsqrt(uround);
+  srur = SUNRsqrt(IDA_mem->ida_uround);
 
   for (j=0; j < N; j++) {
 
     /* Generate the jth col of J(tt,yy,yp) as delta(F)/delta(y_j). */
 
     /* Set data address of jthCol, and save y_j and yp_j values. */
-    N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol);
+    N_VSetArrayPointer(SUNDenseMatrix_Column(Jac,j), jthCol);
     yj = y_data[j];
     ypj = yp_data[j];
 
@@ -367,13 +449,14 @@ int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
     adjustments using yp_j and ewt_j if this is small, and a further
     adjustment to give it the same sign as hh*yp_j. */
 
-    inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(hh*ypj) ) , ONE/ewt_data[j] );
+    inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(IDA_mem->ida_hh*ypj) ),
+                  ONE/ewt_data[j] );
 
-    if (hh*ypj < ZERO) inc = -inc;
+    if (IDA_mem->ida_hh*ypj < ZERO) inc = -inc;
     inc = (yj + inc) - yj;
 
     /* Adjust sign(inc) again if y_j has an inequality constraint. */
-    if (constraints != NULL) {
+    if (IDA_mem->ida_constraints != NULL) {
       conj = cns_data[j];
       if (SUNRabs(conj) == ONE)      {if((yj+inc)*conj <  ZERO) inc = -inc;}
       else if (SUNRabs(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
@@ -383,91 +466,87 @@ int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
     y_data[j] += inc;
     yp_data[j] += c_j*inc;
 
-    retval = res(tt, yy, yp, rtemp, user_data);
-    nreDQ++;
+    retval = IDA_mem->ida_res(tt, yy, yp, rtemp, IDA_mem->ida_user_data);
+    idadls_mem->nreDQ++;
     if (retval != 0) break;
 
     /* Construct difference quotient in jthCol */
     inc_inv = ONE/inc;
     N_VLinearSum(inc_inv, rtemp, -inc_inv, rr, jthCol);
 
-    DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);
+    /* DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);  /\* UNNECESSARY *\/ */
 
     /*  reset y_j, yp_j */     
     y_data[j] = yj;
     yp_data[j] = ypj;
   }
 
-  /* Restore original array pointer in tmp2 */
-  N_VSetArrayPointer(tmp2_data, tmp2);
+  /* Destroy jthCol vector */
+  N_VSetArrayPointer(NULL, jthCol);  /* SHOULDN'T BE NEEDED */
+  N_VDestroy(jthCol);
 
   return(retval);
 
 }
 
-/*
- * -----------------------------------------------------------------
- * idaDlsBandDQJac 
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation JJ
- * to the DAE system Jacobian J.  It assumes that a band matrix of type
- * BandMat is stored column-wise, and that elements within each column
- * are contiguous.  The address of the jth column of JJ is obtained via
- * the macros BAND_COL and BAND_COL_ELEM. The columns of the Jacobian are 
- * constructed using mupper + mlower + 1 calls to the res routine, and
- * appropriate differencing.
- * The return value is either IDABAND_SUCCESS = 0, or the nonzero value returned
- * by the res routine, if any.
- */
-
-int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
-                    realtype tt, realtype c_j, 
-                    N_Vector yy, N_Vector yp, N_Vector rr,
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+
+/*---------------------------------------------------------------
+  idaDlsBandDQJac 
+
+  This routine generates a banded difference quotient approximation 
+  JJ to the DAE system Jacobian J.  It assumes a band SUNMatrix 
+  input (stored column-wise, and that elements within each column
+  are contiguous).  This makes it possible to get the address 
+  of a column of JJ via the function SUNBandMatrix_Column(). The 
+  columns of the Jacobian are constructed using mupper + mlower + 1 
+  calls to the res routine, and appropriate differencing.
+  The return value is either IDABAND_SUCCESS = 0, or the nonzero 
+  value returned by the res routine, if any.
+  ---------------------------------------------------------------*/
+int idaDlsBandDQJac(realtype tt, realtype c_j, N_Vector yy,
+                    N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                    IDAMem IDA_mem, N_Vector tmp1, N_Vector tmp2,
+                    N_Vector tmp3)
 {
   realtype inc, inc_inv, yj, ypj, srur, conj, ewtj;
   realtype *y_data, *yp_data, *ewt_data, *cns_data = NULL;
   realtype *ytemp_data, *yptemp_data, *rtemp_data, *r_data, *col_j;
   N_Vector rtemp, ytemp, yptemp;
-  long int i, j, i1, i2, width, ngroups, group;
+  sunindextype i, j, i1, i2, width, ngroups, group;
+  sunindextype N, mupper, mlower;
   int retval = 0;
-
-  IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* data points to IDA_mem */
-  IDA_mem = (IDAMem) data;
-  idadls_mem = (IDADlsMem) lmem;
-
-  rtemp = tmp1; /* Rename work vector for use as the perturbed residual. */
-
-  ytemp = tmp2; /* Rename work vector for use as a temporary for yy. */
+  /* access DlsMem interface structure */
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
+  /* access matrix dimensions */
+  N = SUNBandMatrix_Columns(Jac);
+  mupper = SUNBandMatrix_UpperBandwidth(Jac);
+  mlower = SUNBandMatrix_LowerBandwidth(Jac);
 
-  yptemp= tmp3; /* Rename work vector for use as a temporary for yp. */
+  /* Rename work vectors for use as temporary values of r, y and yp */
+  rtemp = tmp1;
+  ytemp = tmp2;
+  yptemp= tmp3;
 
   /* Obtain pointers to the data for all eight vectors used.  */
-
-  ewt_data = N_VGetArrayPointer(ewt);
-  r_data   = N_VGetArrayPointer(rr);
-  y_data   = N_VGetArrayPointer(yy);
-  yp_data  = N_VGetArrayPointer(yp);
-
+  ewt_data    = N_VGetArrayPointer(IDA_mem->ida_ewt);
+  r_data      = N_VGetArrayPointer(rr);
+  y_data      = N_VGetArrayPointer(yy);
+  yp_data     = N_VGetArrayPointer(yp);
   rtemp_data  = N_VGetArrayPointer(rtemp);
   ytemp_data  = N_VGetArrayPointer(ytemp);
   yptemp_data = N_VGetArrayPointer(yptemp);
-
-  if (constraints != NULL) cns_data = N_VGetArrayPointer(constraints);
+  if (IDA_mem->ida_constraints != NULL)
+    cns_data = N_VGetArrayPointer(IDA_mem->ida_constraints);
 
   /* Initialize ytemp and yptemp. */
-
   N_VScale(ONE, yy, ytemp);
   N_VScale(ONE, yp, yptemp);
 
   /* Compute miscellaneous values for the Jacobian computation. */
-
-  srur = SUNRsqrt(uround);
+  srur = SUNRsqrt(IDA_mem->ida_uround);
   width = mlower + mupper + 1;
   ngroups = SUNMIN(width, N);
 
@@ -475,7 +554,6 @@ int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
   for (group=1; group <= ngroups; group++) {
 
     /* Increment all yy[j] and yp[j] for j in this group. */
-
     for (j=group-1; j<N; j+=width) {
         yj = y_data[j];
         ypj = yp_data[j];
@@ -484,73 +562,235 @@ int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
         /* Set increment inc to yj based on sqrt(uround)*abs(yj), with
         adjustments using ypj and ewtj if this is small, and a further
         adjustment to give it the same sign as hh*ypj. */
-
-        inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(hh*ypj) ) , ONE/ewtj );
-
-        if (hh*ypj < ZERO) inc = -inc;
+        inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(IDA_mem->ida_hh*ypj) ),
+                      ONE/ewtj );
+        if (IDA_mem->ida_hh*ypj < ZERO)  inc = -inc;
         inc = (yj + inc) - yj;
 
         /* Adjust sign(inc) again if yj has an inequality constraint. */
-
-        if (constraints != NULL) {
+        if (IDA_mem->ida_constraints != NULL) {
           conj = cns_data[j];
           if (SUNRabs(conj) == ONE)      {if((yj+inc)*conj <  ZERO) inc = -inc;}
           else if (SUNRabs(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
         }
 
         /* Increment yj and ypj. */
-
         ytemp_data[j] += inc;
-        yptemp_data[j] += cj*inc;
+        yptemp_data[j] += IDA_mem->ida_cj*inc;
     }
 
     /* Call res routine with incremented arguments. */
-
-    retval = res(tt, ytemp, yptemp, rtemp, user_data);
-    nreDQ++;
+    retval = IDA_mem->ida_res(tt, ytemp, yptemp, rtemp, IDA_mem->ida_user_data);
+    idadls_mem->nreDQ++;
     if (retval != 0) break;
 
     /* Loop over the indices j in this group again. */
-
     for (j=group-1; j<N; j+=width) {
 
       /* Reset ytemp and yptemp components that were perturbed. */
-
       yj = ytemp_data[j]  = y_data[j];
       ypj = yptemp_data[j] = yp_data[j];
-      col_j = BAND_COL(Jac, j);
+      col_j = SUNBandMatrix_Column(Jac, j);
       ewtj = ewt_data[j];
       
       /* Set increment inc exactly as above. */
-
-      inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(hh*ypj) ) , ONE/ewtj );
-      if (hh*ypj < ZERO) inc = -inc;
+      inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(IDA_mem->ida_hh*ypj) ),
+                    ONE/ewtj );
+      if (IDA_mem->ida_hh*ypj < ZERO)  inc = -inc;
       inc = (yj + inc) - yj;
-      if (constraints != NULL) {
+      if (IDA_mem->ida_constraints != NULL) {
         conj = cns_data[j];
         if (SUNRabs(conj) == ONE)      {if((yj+inc)*conj <  ZERO) inc = -inc;}
         else if (SUNRabs(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
       }
       
-      /* Load the difference quotient Jacobian elements for column j. */
-
+      /* Load the difference quotient Jacobian elements for column j */
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-mupper);
       i2 = SUNMIN(j+mlower,N-1);
-      
       for (i=i1; i<=i2; i++) 
-            BAND_COL_ELEM(col_j,i,j) = inc_inv*(rtemp_data[i]-r_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (rtemp_data[i]-r_data[i]);
     }
-    
   }
   
   return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ idaDlsInitialize performs remaining initializations specific
+ to the direct linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int idaDlsInitialize(IDAMem IDA_mem)
+{
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", 
+                    "idaDlsInitialize", MSGD_IDAMEM_NULL);
+    return(IDADLS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", 
+                    "idaDlsInitialize", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
+  }
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
   
+  idaDlsInitializeCounters(idadls_mem);
+
+  /* Set Jacobian function and data, depending on jacDQ (in case 
+     it has changed based on user input) */
+  if (idadls_mem->jacDQ) {
+    idadls_mem->jac    = idaDlsDQJac;
+    idadls_mem->J_data = IDA_mem;
+  } else {
+    idadls_mem->J_data = IDA_mem->ida_user_data;
+  }
+
+  /* Call LS initialize routine */
+  idadls_mem->last_flag = SUNLinSolInitialize(idadls_mem->LS);
+  return(idadls_mem->last_flag);
 }
 
+
+/*---------------------------------------------------------------
+  idaDlsSetup does the setup operations for the IDADLS linear 
+  solver interface.  It calls the Jacobian evaluation routine, 
+  updates counters, and calls the LS 'setup' routine to prepare
+  for subsequent calls to the LS 'solve' routine.
+
+  The return value is either
+     IDADLS_SUCCESS = 0  if successful,
+      1  if the jac or LS 'setup' routine failed recoverably, or
+     -1  if the jac or LS 'setup' routines failed unrecoverably.
+---------------------------------------------------------------*/
+int idaDlsSetup(IDAMem IDA_mem, N_Vector y, N_Vector yp, N_Vector r, 
+                N_Vector vt1, N_Vector vt2, N_Vector vt3)
+{
+  int retval;
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", 
+                    "idaDlsSetup", MSGD_IDAMEM_NULL);
+    return(IDADLS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", 
+                    "idaDlsSetup", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
+  }
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* Increment nje counter. */
+  idadls_mem->nje++;
+
+  /* Zero out J; call Jacobian routine jac; return if it failed. */
+  retval = SUNMatZero(idadls_mem->J);
+  if (retval != 0) {
+    IDAProcessError(IDA_mem, IDADLS_SUNMAT_FAIL, "IDADLS",
+                    "idaDlsSetup", MSGD_MATZERO_FAILED);
+    idadls_mem->last_flag = IDADLS_SUNMAT_FAIL;
+    return(-1);
+  }
+  
+  retval = idadls_mem->jac(IDA_mem->ida_tn, IDA_mem->ida_cj, y,
+                           yp, r, idadls_mem->J,
+                           idadls_mem->J_data, vt1, vt2, vt3);
+  if (retval < 0) {
+    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDADLS",
+                    "idaDlsSetup", MSGD_JACFUNC_FAILED);
+    idadls_mem->last_flag = IDADLS_JACFUNC_UNRECVR;
+    return(-1);
+  }
+  if (retval > 0) {
+    idadls_mem->last_flag = IDADLS_JACFUNC_RECVR;
+    return(1);
+  }
+
+  /* Call generic linear solver 'setup' with this system matrix, and
+     return success/failure flag */
+  idadls_mem->last_flag = SUNLinSolSetup(idadls_mem->LS, idadls_mem->J);
+  return(idadls_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ idaDlsSolve interfaces between IDA and the generic 
+ SUNLinearSolver object LS, by calling the LS 'solve' routine 
+ and scaling the result if cjratio does not equal one.
+---------------------------------------------------------------*/
+int idaDlsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                N_Vector ycur, N_Vector ypcur, N_Vector rescur)
+{
+  int retval;
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDADLS", 
+		    "idaDlsSolve", MSGD_IDAMEM_NULL);
+    return(IDADLS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDADLS", 
+		    "idaDlsSolve", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
+  }
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* call the generic linear system solver, and copy x to b */
+  retval = SUNLinSolSolve(idadls_mem->LS, idadls_mem->J, idadls_mem->x, b, ZERO);
+  N_VScale(ONE, idadls_mem->x, b);
+  
+  /* scale the correction to account for change in cj */
+  if (IDA_mem->ida_cjratio != ONE) 
+    N_VScale(TWO/(ONE + IDA_mem->ida_cjratio), b, b);
+  
+  /* store solver return value and return */
+  idadls_mem->last_flag = retval;
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ idaDlsFree frees memory associates with the IDADls system
+ solver interface.
+---------------------------------------------------------------*/
+int idaDlsFree(IDAMem IDA_mem)
+{
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL)  return (IDADLS_SUCCESS);
+  if (IDA_mem->ida_lmem == NULL)  return(IDADLS_SUCCESS);
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* Free x vector */
+  if (idadls_mem->x) {
+    N_VDestroy(idadls_mem->x);
+    idadls_mem->x = NULL;
+  }
+
+  /* Nullify SUNMatrix pointer */
+  idadls_mem->J = NULL;
+
+  /* free IDADls interface structure */
+  free(IDA_mem->ida_lmem);
+  
+  return(IDADLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+  idaDlsInitializeCounters resets counters for the DLS interface
+  ---------------------------------------------------------------*/
 int idaDlsInitializeCounters(IDADlsMem idadls_mem)
 {
-  idadls_mem->d_nje   = 0;
-  idadls_mem->d_nreDQ = 0;
+  idadls_mem->nje   = 0;
+  idadls_mem->nreDQ = 0;
   return(0);
 }
diff --git a/src/ida/ida_direct_impl.h b/src/ida/ida_direct_impl.h
index 8361d19..44f804e 100644
--- a/src/ida/ida_direct_impl.h
+++ b/src/ida/ida_direct_impl.h
@@ -1,102 +1,98 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Implementation header file for the IDADLS linear solvers.
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Implementation header file for the IDADLS linear solver 
+ * interface
+ *-----------------------------------------------------------------*/
 
 #ifndef _IDADLS_IMPL_H
 #define _IDADLS_IMPL_H
 
 #include <ida/ida_direct.h>
+#include "ida_impl.h"
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * =================================================================
- * I D A D I R E C T    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDADlsMemRec, IDADlsMem                             
- * -----------------------------------------------------------------
- * IDADlsMem is pointer to a IDADlsMemRec structure.
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types : IDADlsMemRec, IDADlsMem                             
 
+  IDADlsMem is pointer to a IDADlsMemRec structure.
+  -----------------------------------------------------------------*/
 typedef struct IDADlsMemRec {
 
-  int d_type;               /* Type of Jacobians (DENSE or BAND)             */
-
-  long int d_n;             /* problem dimension                             */
-
-  long int d_ml;            /* b_ml = lower bandwidth of savedJ              */
-  long int d_mu;            /* b_mu = upper bandwidth of savedJ              */ 
-  long int d_smu;           /* upper bandwith of M = MIN(N-1,b_mu+b_ml)      */
+  booleantype jacDQ;    /* SUNTRUE if using internal DQ Jacobian approx.  */
+  IDADlsJacFn jac;      /* Jacobian routine to be called                  */
+  void *J_data;         /* J_data is passed to jac                        */
 
-  booleantype d_jacDQ;      /* TRUE if using internal DQ Jacobian approx.    */
-  IDADlsDenseJacFn d_djac;  /* dense Jacobian routine to be called           */
-  IDADlsBandJacFn d_bjac;   /* band Jacobian routine to be called            */
-  void *d_J_data;           /* J_data is passed to djac or bjac              */
+  SUNLinearSolver LS;   /* generic direct linear solver object            */
 
-  DlsMat d_J;               /* J = dF/dy + cj*dF/dy'                         */
+  SUNMatrix J;          /* J = dF/dy + cj*dF/dy'                          */
 
-  int *d_pivots;            /* pivots = int pivot array for PM = LU          */
-  long int *d_lpivots;      /* lpivots = long int pivot array for PM = LU    */
+  N_Vector x;           /* solution vector used by SUNLinearSolver        */
   
-  long int d_nje;           /* nje = no. of calls to jac                     */
+  long int nje;         /* nje = no. of calls to jac                      */
 
-  long int d_nreDQ;         /* no. of calls to res due to DQ Jacobian approx.*/
+  long int nreDQ;       /* no. of calls to res due to DQ Jacobian approx. */
 
-  long int d_last_flag;     /* last error return flag                        */
+  long int last_flag;   /* last error return flag                         */
   
 } *IDADlsMem;
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-  
-int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
-                     N_Vector yy, N_Vector yp, N_Vector rr, 
-                     DlsMat Jac, void *data,
-                     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-  
-int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
-                    realtype tt, realtype c_j, 
-                    N_Vector yy, N_Vector yp, N_Vector rr,
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
 
-/* Auxilliary functions */
+/*---------------------------------------------------------------
+  Prototypes of internal functions
+  ---------------------------------------------------------------*/
+ 
+/* difference-quotient Jacobian approximation routines */
+int idaDlsDQJac(realtype tt, realtype c_j, N_Vector yy, 
+                N_Vector yp, N_Vector rr, SUNMatrix Jac, 
+                void *data, N_Vector tmp1, N_Vector tmp2, 
+                N_Vector tmp3);
+int idaDlsDenseDQJac(realtype tt, realtype c_j, N_Vector yy,
+                     N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                     IDAMem IDA_mem, N_Vector tmp1);
+int idaDlsBandDQJac(realtype tt, realtype c_j,  N_Vector yy,
+                    N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                    IDAMem IDA_mem, N_Vector tmp1,
+                    N_Vector tmp2, N_Vector tmp3);
 
+/* generic linit/lsetup/lsolve/lfree interface routines for IDA to call */
+int idaDlsInitialize(IDAMem IDA_mem);
+
+int idaDlsSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
+                N_Vector resp, N_Vector vtemp1,
+                N_Vector vtemp2, N_Vector vtemp3); 
+
+int idaDlsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                N_Vector ycur, N_Vector ypcur, N_Vector rescur);
+
+int idaDlsFree(IDAMem IDA_mem);
+
+  
+/* Auxilliary functions */
 int idaDlsInitializeCounters(IDADlsMem idadls_mem);
 
 
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
+/*=================================================================
+  Error Messages
+  =================================================================*/
 
 #define MSGD_IDAMEM_NULL "Integrator memory is NULL."
 #define MSGD_BAD_NVECTOR "A required vector operation is not implemented."
@@ -104,6 +100,7 @@ int idaDlsInitializeCounters(IDADlsMem idadls_mem);
 #define MSGD_MEM_FAIL "A memory request failed."
 #define MSGD_LMEM_NULL "Linear solver memory is NULL."
 #define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
+#define MSGD_MATZERO_FAILED "The SUNMatZero routine failed in an unrecoverable manner."
 
 #ifdef __cplusplus
 }
diff --git a/src/ida/ida_ic.c b/src/ida/ida_ic.c
index 2da1bca..95180e5 100644
--- a/src/ida/ida_ic.c
+++ b/src/ida/ida_ic.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4536 $
- * $Date: 2015-09-16 14:14:12 -0700 (Wed, 16 Sep 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -26,9 +26,6 @@
 #include "ida_impl.h"
 #include <sundials/sundials_math.h>
 
-/* Macro: loop */
-#define loop for(;;)
-
 /*
  * =================================================================
  * IDA Constants 
@@ -78,55 +75,6 @@ static int IDAICFailFlag(IDAMem IDA_mem, int retval);
 
 /*
  * =================================================================
- * Readibility Constants
- * =================================================================
- */
-
-#define t0             (IDA_mem->ida_t0)
-#define yy0            (IDA_mem->ida_yy0)
-#define yp0            (IDA_mem->ida_yp0)
-
-#define user_data      (IDA_mem->ida_user_data)
-#define res            (IDA_mem->ida_res)
-#define efun           (IDA_mem->ida_efun)
-#define edata          (IDA_mem->ida_edata)
-#define uround         (IDA_mem->ida_uround)  
-#define phi            (IDA_mem->ida_phi) 
-#define ewt            (IDA_mem->ida_ewt)  
-#define delta          (IDA_mem->ida_delta)
-#define ee             (IDA_mem->ida_ee)
-#define savres         (IDA_mem->ida_savres)
-#define tempv2         (IDA_mem->ida_tempv2) 
-#define hh             (IDA_mem->ida_hh)
-#define tn             (IDA_mem->ida_tn)
-#define cj             (IDA_mem->ida_cj)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define nbacktr        (IDA_mem->ida_nbacktr)
-#define maxbacks       (IDA_mem->ida_maxbacks)
-#define nre            (IDA_mem->ida_nre)
-#define ncfn           (IDA_mem->ida_ncfn)
-#define nni            (IDA_mem->ida_nni)
-#define nsetups        (IDA_mem->ida_nsetups)
-#define ns             (IDA_mem->ida_ns)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve) 
-#define hused          (IDA_mem->ida_hused)         
-#define epsNewt        (IDA_mem->ida_epsNewt)
-#define id             (IDA_mem->ida_id)
-#define setupNonNull   (IDA_mem->ida_setupNonNull) 
-#define suppressalg    (IDA_mem->ida_suppressalg)
-#define constraints    (IDA_mem->ida_constraints)
-#define constraintsSet (IDA_mem->ida_constraintsSet)
-
-#define epiccon  (IDA_mem->ida_epiccon)
-#define maxnh    (IDA_mem->ida_maxnh)
-#define maxnj    (IDA_mem->ida_maxnj)
-#define maxnit   (IDA_mem->ida_maxnit)
-#define lsoff    (IDA_mem->ida_lsoff)
-#define steptol  (IDA_mem->ida_steptol)
-
-/*
- * =================================================================
  * EXPORTED FUNCTIONS IMPLEMENTATION
  * =================================================================
  */
@@ -176,7 +124,7 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   /* Check if problem was malloc'ed */
   
-  if(IDA_mem->ida_MallocDone == FALSE) {
+  if(IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDA", "IDACalcIC", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -185,7 +133,7 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   ier = IDAInitialSetup(IDA_mem);
   if(ier != IDA_SUCCESS) return(IDA_ILL_INPUT);
-  IDA_mem->ida_SetupDone = TRUE;
+  IDA_mem->ida_SetupDone = SUNTRUE;
 
   /* Check legality of input arguments, and set IDA memory copies. */
 
@@ -195,13 +143,13 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
   }
   IDA_mem->ida_icopt = icopt;
 
-  if(icopt == IDA_YA_YDP_INIT && (id == NULL)) {
+  if(icopt == IDA_YA_YDP_INIT && (IDA_mem->ida_id == NULL)) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_MISSING_ID);
     return(IDA_ILL_INPUT);
   }
 
-  tdist = SUNRabs(tout1 - tn);
-  troundoff = TWO*uround*(SUNRabs(tn) + SUNRabs(tout1));
+  tdist = SUNRabs(tout1 - IDA_mem->ida_tn);
+  troundoff = TWO * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(tout1));
   if(tdist < troundoff) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_TOO_CLOSE);
     return(IDA_ILL_INPUT);
@@ -209,18 +157,18 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   /* Allocate space and initialize temporary vectors */
 
-  yy0 = N_VClone(ee);
-  yp0 = N_VClone(ee);
-  t0  = tn;
-  N_VScale(ONE, phi[0], yy0);
-  N_VScale(ONE, phi[1], yp0);
+  IDA_mem->ida_yy0 = N_VClone(IDA_mem->ida_ee);
+  IDA_mem->ida_yp0 = N_VClone(IDA_mem->ida_ee);
+  IDA_mem->ida_t0  = IDA_mem->ida_tn;
+  N_VScale(ONE, IDA_mem->ida_phi[0], IDA_mem->ida_yy0);
+  N_VScale(ONE, IDA_mem->ida_phi[1], IDA_mem->ida_yp0);
 
   /* For use in the IDA_YA_YP_INIT case, set sysindex and tscale. */
 
   IDA_mem->ida_sysindex = 1;
   IDA_mem->ida_tscale   = tdist;
   if(icopt == IDA_YA_YDP_INIT) {
-    minid = N_VMin(id);
+    minid = N_VMin(IDA_mem->ida_id);
     if(minid < ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDACalcIC", MSG_IC_BAD_ID);
       return(IDA_ILL_INPUT);
@@ -230,28 +178,29 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   /* Set the test constant in the Newton convergence test */
 
-  IDA_mem->ida_epsNewt = epiccon;
+  IDA_mem->ida_epsNewt = IDA_mem->ida_epiccon;
 
   /* Initializations: 
      cjratio = 1 (for use in direct linear solvers); 
      set nbacktr = 0; */
 
-  cjratio = ONE;
-  nbacktr = 0;
+  IDA_mem->ida_cjratio = ONE;
+  IDA_mem->ida_nbacktr = 0;
 
   /* Set hic, hh, cj, and mxnh. */
 
   hic = PT001*tdist;
-  ypnorm = IDAWrmsNorm(IDA_mem, yp0, ewt, suppressalg);
+  ypnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_yp0,
+                       IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
   if(ypnorm > HALF/hic) hic = HALF/ypnorm;
-  if(tout1 < tn) hic = -hic;
-  hh = hic;
+  if(tout1 < IDA_mem->ida_tn) hic = -hic;
+  IDA_mem->ida_hh = hic;
   if(icopt == IDA_YA_YDP_INIT) {
-    cj = ONE/hic;
-    mxnh = maxnh;
+    IDA_mem->ida_cj = ONE/hic;
+    mxnh = IDA_mem->ida_maxnh;
   }
   else {
-    cj = ZERO;
+    IDA_mem->ida_cj = ZERO;
     mxnh = 1;
   }
 
@@ -267,39 +216,40 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
       /* Cut h and loop on recoverable IDA_YA_YDP_INIT failure; else break. */
       if(retval == IDA_SUCCESS) break;
-      ncfn++;
+      IDA_mem->ida_ncfn++;
       if(retval < 0) break;
       if(nh == mxnh) break;
       /* If looping to try again, reset yy0 and yp0 if not converging. */
       if(retval != IC_SLOW_CONVRG) {
-        N_VScale(ONE, phi[0], yy0);
-        N_VScale(ONE, phi[1], yp0);
+        N_VScale(ONE, IDA_mem->ida_phi[0], IDA_mem->ida_yy0);
+        N_VScale(ONE, IDA_mem->ida_phi[1], IDA_mem->ida_yp0);
       }
       hic *= PT1;
-      cj = ONE/hic;
-      hh = hic;
+      IDA_mem->ida_cj = ONE/hic;
+      IDA_mem->ida_hh = hic;
     }   /* End of nh loop */
 
     /* Break on failure; else reset ewt, save yy0, yp0 in phi, and loop. */
     if(retval != IDA_SUCCESS) break;
-    ewtsetOK = efun(yy0, ewt, edata);
+    ewtsetOK = IDA_mem->ida_efun(IDA_mem->ida_yy0, IDA_mem->ida_ewt,
+                                 IDA_mem->ida_edata);
     if(ewtsetOK != 0) { 
       retval = IDA_BAD_EWT; 
       break; 
     }
-    N_VScale(ONE, yy0, phi[0]);
-    N_VScale(ONE, yp0, phi[1]);
+    N_VScale(ONE, IDA_mem->ida_yy0, IDA_mem->ida_phi[0]);
+    N_VScale(ONE, IDA_mem->ida_yp0, IDA_mem->ida_phi[1]);
 
   }   /* End of nwt loop */
 
   /* Free temporary space */
 
-  N_VDestroy(yy0);
-  N_VDestroy(yp0);
+  N_VDestroy(IDA_mem->ida_yy0);
+  N_VDestroy(IDA_mem->ida_yp0);
 
   /* Load the optional outputs. */
 
-  if(icopt == IDA_YA_YDP_INIT)   hused = hic;
+  if(icopt == IDA_YA_YDP_INIT)   IDA_mem->ida_hused = hic;
 
   /* On any failure, print message and return proper flag. */
 
@@ -320,14 +270,6 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
  * =================================================================
  */
 
-#define icopt    (IDA_mem->ida_icopt)
-#define sysindex (IDA_mem->ida_sysindex)
-#define tscale   (IDA_mem->ida_tscale)
-#define ynew     (IDA_mem->ida_ynew)
-#define ypnew    (IDA_mem->ida_ypnew)
-#define delnew   (IDA_mem->ida_delnew)
-#define dtemp    (IDA_mem->ida_dtemp)
-
 /*
  * -----------------------------------------------------------------
  * IDAnlsIC
@@ -358,25 +300,29 @@ static int IDAnlsIC (IDAMem IDA_mem)
   int retval, nj;
   N_Vector tv1, tv2, tv3;
 
-  tv1 = ee;
-  tv2 = tempv2;
-  tv3 = phi[2];
+  tv1 = IDA_mem->ida_ee;
+  tv2 = IDA_mem->ida_tempv2;
+  tv3 = IDA_mem->ida_phi[2];
 
-  retval = res(t0, yy0, yp0, delta, user_data);
-  nre++;
+  retval = IDA_mem->ida_res(IDA_mem->ida_t0, IDA_mem->ida_yy0,
+                            IDA_mem->ida_yp0, IDA_mem->ida_delta,
+                            IDA_mem->ida_user_data);
+  IDA_mem->ida_nre++;
   if(retval < 0) return(IDA_RES_FAIL);
   if(retval > 0) return(IDA_FIRST_RES_FAIL);
 
-  N_VScale(ONE, delta, savres);
+  N_VScale(ONE, IDA_mem->ida_delta, IDA_mem->ida_savres);
 
   /* Loop over nj = number of linear solve Jacobian setups. */
 
-  for(nj = 1; nj <= maxnj; nj++) {
+  for(nj = 1; nj <= IDA_mem->ida_maxnj; nj++) {
 
     /* If there is a setup routine, call it. */
-    if(setupNonNull) {
-      nsetups++;
-      retval = lsetup(IDA_mem, yy0, yp0, delta, tv1, tv2, tv3);
+    if(IDA_mem->ida_lsetup) {
+      IDA_mem->ida_nsetups++;
+      retval = IDA_mem->ida_lsetup(IDA_mem, IDA_mem->ida_yy0,
+                                   IDA_mem->ida_yp0, IDA_mem->ida_delta,
+                                   tv1, tv2, tv3);
       if(retval < 0) return(IDA_LSETUP_FAIL);
       if(retval > 0) return(IC_FAIL_RECOV);
     }
@@ -386,8 +332,8 @@ static int IDAnlsIC (IDAMem IDA_mem)
     if(retval == IDA_SUCCESS) return(IDA_SUCCESS);
 
     /* If converging slowly and lsetup is nontrivial, retry. */
-    if(retval == IC_SLOW_CONVRG && setupNonNull) {
-      N_VScale(ONE, savres, delta);
+    if(retval == IC_SLOW_CONVRG && IDA_mem->ida_lsetup) {
+      N_VScale(ONE, IDA_mem->ida_savres, IDA_mem->ida_delta);
       continue;
     } else {
       return(retval);
@@ -431,17 +377,21 @@ static int IDANewtonIC(IDAMem IDA_mem)
   realtype delnorm, fnorm, fnorm0, oldfnrm, rate;
 
   /* Set pointer for vector delnew */
-  delnew = phi[2];
+  IDA_mem->ida_delnew = IDA_mem->ida_phi[2];
 
   /* Call the linear solve function to get the Newton step, delta. */
-  retval = lsolve(IDA_mem, delta, ewt, yy0, yp0, savres);
+  retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delta,
+                               IDA_mem->ida_ewt, IDA_mem->ida_yy0,
+                               IDA_mem->ida_yp0, IDA_mem->ida_savres);
   if(retval < 0) return(IDA_LSOLVE_FAIL);
   if(retval > 0) return(IC_FAIL_RECOV);
 
   /* Compute the norm of the step; return now if this is small. */
-  fnorm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE);
-  if(sysindex == 0) fnorm *= tscale*SUNRabs(cj);
-  if(fnorm <= epsNewt) return(IDA_SUCCESS);
+  fnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, SUNFALSE);
+  if(IDA_mem->ida_sysindex == 0)
+    fnorm *= IDA_mem->ida_tscale * SUNRabs(IDA_mem->ida_cj);
+  if(fnorm <= IDA_mem->ida_epsNewt)
+    return(IDA_SUCCESS);
   fnorm0 = fnorm;
 
   /* Initialize rate to avoid compiler warning message */
@@ -449,9 +399,9 @@ static int IDANewtonIC(IDAMem IDA_mem)
 
   /* Newton iteration loop */
 
-  for(mnewt = 0; mnewt < maxnit; mnewt++) {
+  for(mnewt = 0; mnewt < IDA_mem->ida_maxnit; mnewt++) {
 
-    nni++;
+    IDA_mem->ida_nni++;
     delnorm = fnorm;
     oldfnrm = fnorm;
 
@@ -461,10 +411,10 @@ static int IDANewtonIC(IDAMem IDA_mem)
 
     /* Set the observed convergence rate and test for convergence. */
     rate = fnorm/oldfnrm;
-    if(fnorm <= epsNewt) return(IDA_SUCCESS);
+    if(fnorm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
 
     /* If not converged, copy new step vector, and loop. */
-    N_VScale(ONE, delnew, delta);
+    N_VScale(ONE, IDA_mem->ida_delnew, IDA_mem->ida_delta);
 
   }   /* End of Newton iteration loop */
 
@@ -512,64 +462,66 @@ static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm)
 
   /* Initialize work space pointers, f1norm, ratio.
      (Use of mc in constraint check does not conflict with ypnew.) */
-  mc = ee;
-  dtemp = phi[3];
-  ynew = tempv2;
-  ypnew = ee;
+  mc = IDA_mem->ida_ee;
+  IDA_mem->ida_dtemp = IDA_mem->ida_phi[3];
+  IDA_mem->ida_ynew = IDA_mem->ida_tempv2;
+  IDA_mem->ida_ypnew = IDA_mem->ida_ee;
   f1norm = (*fnorm)*(*fnorm)*HALF;
   ratio = ONE;
 
   /* If there are constraints, check and reduce step if necessary. */
-  if(constraintsSet) {
+  if(IDA_mem->ida_constraintsSet) {
 
     /* Update y and check constraints. */
     IDANewy(IDA_mem);
-    conOK = N_VConstrMask(constraints, ynew, mc);
+    conOK = N_VConstrMask(IDA_mem->ida_constraints, IDA_mem->ida_ynew, mc);
 
     if(!conOK) {
       /* Not satisfied.  Compute scaled step to satisfy constraints. */
-      N_VProd(mc, delta, dtemp);
-      ratio = PT99*N_VMinQuotient(yy0, dtemp);
+      N_VProd(mc, IDA_mem->ida_delta, IDA_mem->ida_dtemp);
+      ratio = PT99*N_VMinQuotient(IDA_mem->ida_yy0, IDA_mem->ida_dtemp);
       (*delnorm) *= ratio;
-      if((*delnorm) <= steptol) return(IC_CONSTR_FAILED);
-      N_VScale(ratio, delta, delta);
+      if((*delnorm) <= IDA_mem->ida_steptol) return(IC_CONSTR_FAILED);
+      N_VScale(ratio, IDA_mem->ida_delta, IDA_mem->ida_delta);
     }
 
   } /* End of constraints check */
 
   slpi = -TWO*f1norm*ratio;
-  minlam = steptol/(*delnorm);
+  minlam = IDA_mem->ida_steptol / (*delnorm);
   lambda = ONE;
   nbacks = 0;
 
   /* In IDA_Y_INIT case, set ypnew = yp0 (fixed) for linesearch. */
-  if(icopt == IDA_Y_INIT) N_VScale(ONE, yp0, ypnew);
+  if(IDA_mem->ida_icopt == IDA_Y_INIT)
+    N_VScale(ONE, IDA_mem->ida_yp0, IDA_mem->ida_ypnew);
 
   /* Loop on linesearch variable lambda. */
 
-  loop {
+  for(;;) {
 
-    if (nbacks == maxbacks) return(IC_LINESRCH_FAILED);
+    if (nbacks == IDA_mem->ida_maxbacks) return(IC_LINESRCH_FAILED);
     /* Get new (y,y') = (ynew,ypnew) and norm of new function value. */
     IDANewyyp(IDA_mem, lambda);
     retval = IDAfnorm(IDA_mem, &fnormp);
     if(retval != IDA_SUCCESS) return(retval);
 
     /* If lsoff option is on, break out. */
-    if(lsoff) break;
+    if(IDA_mem->ida_lsoff) break;
 
     /* Do alpha-condition test. */
     f1normp = fnormp*fnormp*HALF;
     if(f1normp <= f1norm + ALPHALS*slpi*lambda) break;
     if(lambda < minlam) return(IC_LINESRCH_FAILED);
     lambda /= TWO;
-    nbacktr++; nbacks++;
+    IDA_mem->ida_nbacktr++; nbacks++;
 
   }  /* End of breakout linesearch loop */
 
   /* Update yy0, yp0, and fnorm, then return. */
-  N_VScale(ONE, ynew,  yy0);
-  if(icopt == IDA_YA_YDP_INIT) N_VScale(ONE, ypnew, yp0);
+  N_VScale(ONE, IDA_mem->ida_ynew,  IDA_mem->ida_yy0);
+  if(IDA_mem->ida_icopt == IDA_YA_YDP_INIT)
+    N_VScale(ONE, IDA_mem->ida_ypnew, IDA_mem->ida_yp0);
   *fnorm = fnormp;
   return(IDA_SUCCESS);
 
@@ -599,21 +551,26 @@ static int IDAfnorm(IDAMem IDA_mem, realtype *fnorm)
   int retval;
 
   /* Get residual vector F, return if failed, and save F in savres. */
-  retval = res(t0, ynew, ypnew, delnew, user_data);
-  nre++;
+  retval = IDA_mem->ida_res(IDA_mem->ida_t0, IDA_mem->ida_ynew,
+                            IDA_mem->ida_ypnew, IDA_mem->ida_delnew,
+                            IDA_mem->ida_user_data);
+  IDA_mem->ida_nre++;
   if(retval < 0) return(IDA_RES_FAIL);
   if(retval > 0) return(IC_FAIL_RECOV);
 
-  N_VScale(ONE, delnew, savres);
+  N_VScale(ONE, IDA_mem->ida_delnew, IDA_mem->ida_savres);
 
   /* Call the linear solve function to get J-inverse F; return if failed. */
-  retval = lsolve(IDA_mem, delnew, ewt, ynew, ypnew, savres);
+  retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delnew,
+                               IDA_mem->ida_ewt, IDA_mem->ida_ynew,
+                               IDA_mem->ida_ypnew, IDA_mem->ida_savres);
   if(retval < 0) return(IDA_LSOLVE_FAIL);
   if(retval > 0) return(IC_FAIL_RECOV);
 
   /* Compute the WRMS-norm; rescale if index = 0. */
-  *fnorm = IDAWrmsNorm(IDA_mem, delnew, ewt, FALSE);
-  if(sysindex == 0) (*fnorm) *= tscale*SUNRabs(cj);
+  *fnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delnew, IDA_mem->ida_ewt, SUNFALSE);
+  if(IDA_mem->ida_sysindex == 0)
+    (*fnorm) *= IDA_mem->ida_tscale * SUNRabs(IDA_mem->ida_cj);
 
   return(IDA_SUCCESS);
 
@@ -636,16 +593,20 @@ static int IDANewyyp(IDAMem IDA_mem, realtype lambda)
   
   /* IDA_YA_YDP_INIT case: ynew  = yy0 - lambda*delta    where id_i = 0
                            ypnew = yp0 - cj*lambda*delta where id_i = 1. */
-  if(icopt == IDA_YA_YDP_INIT) {
-    N_VProd(id, delta, dtemp);
-    N_VLinearSum(ONE, yp0, -cj*lambda, dtemp, ypnew);
-    N_VLinearSum(ONE, delta, -ONE, dtemp, dtemp);
-    N_VLinearSum(ONE, yy0, -lambda, dtemp, ynew);
+  if(IDA_mem->ida_icopt == IDA_YA_YDP_INIT) {
+    N_VProd(IDA_mem->ida_id, IDA_mem->ida_delta, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_yp0, -IDA_mem->ida_cj*lambda,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_ypnew);
+    N_VLinearSum(ONE, IDA_mem->ida_delta, -ONE,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_yy0, -lambda,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_ynew);
     return(IDA_SUCCESS);
   }
 
   /* IDA_Y_INIT case: ynew = yy0 - lambda*delta. (ypnew = yp0 preset.) */
-  N_VLinearSum(ONE, yy0, -lambda, delta, ynew);
+  N_VLinearSum(ONE, IDA_mem->ida_yy0, -lambda,
+               IDA_mem->ida_delta, IDA_mem->ida_ynew);
   return(IDA_SUCCESS);
 
 }
@@ -666,15 +627,18 @@ static int IDANewy(IDAMem IDA_mem)
 {
   
   /* IDA_YA_YDP_INIT case: ynew = yy0 - delta    where id_i = 0. */
-  if(icopt == IDA_YA_YDP_INIT) {
-    N_VProd(id, delta, dtemp);
-    N_VLinearSum(ONE, delta, -ONE, dtemp, dtemp);
-    N_VLinearSum(ONE, yy0, -ONE, dtemp, ynew);
+  if(IDA_mem->ida_icopt == IDA_YA_YDP_INIT) {
+    N_VProd(IDA_mem->ida_id, IDA_mem->ida_delta, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_delta, -ONE,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_yy0, -ONE,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_ynew);
     return(IDA_SUCCESS);
   }
 
   /* IDA_Y_INIT case: ynew = yy0 - delta. */
-  N_VLinearSum(ONE, yy0, -ONE, delta, ynew);
+  N_VLinearSum(ONE, IDA_mem->ida_yy0, -ONE,
+               IDA_mem->ida_delta, IDA_mem->ida_ynew);
   return(IDA_SUCCESS);
 
 }
diff --git a/src/ida/ida_impl.h b/src/ida/ida_impl.h
index 1ea32af..23c49c4 100644
--- a/src/ida/ida_impl.h
+++ b/src/ida/ida_impl.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4920 $
- * $Date: 2016-09-19 14:34:35 -0700 (Mon, 19 Sep 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Allan G. Taylor, Alan C. Hindmarsh, Radu Serban,
  *                and Aaron Collier @ LLNL
@@ -67,15 +67,14 @@ typedef struct IDAMemRec {
   realtype       ida_rtol;           /* relative tolerance                    */
   realtype       ida_Satol;          /* scalar absolute tolerance             */  
   N_Vector       ida_Vatol;          /* vector absolute tolerance             */  
-  booleantype    ida_user_efun;      /* TRUE if user provides efun            */
+  booleantype    ida_user_efun;      /* SUNTRUE if user provides efun         */
   IDAEwtFn       ida_efun;           /* function to set ewt                   */
   void          *ida_edata;          /* user pointer passed to efun           */
   
 
-  booleantype    ida_setupNonNull;   /* Does setup do something?              */
   booleantype    ida_constraintsSet; /* constraints vector present: 
                                         do constraints calc                   */
-  booleantype    ida_suppressalg;    /* true means suppress algebraic vars
+  booleantype    ida_suppressalg;    /* SUNTRUE means suppress algebraic vars
                                         in local error tests                  */
 
   /* Divided differences array and associated minor arrays */
@@ -177,8 +176,8 @@ typedef struct IDAMemRec {
 
   /* Space requirements for IDA */
 
-  long int ida_lrw1;     /* no. of realtype words in 1 N_Vector               */
-  long int ida_liw1;     /* no. of integer words in 1 N_Vector                */
+  sunindextype ida_lrw1; /* no. of realtype words in 1 N_Vector               */
+  sunindextype ida_liw1; /* no. of integer words in 1 N_Vector                */
   long int ida_lrw;      /* number of realtype words in IDA work vectors      */
   long int ida_liw;      /* no. of integer words in IDA work vectors          */
 
@@ -192,15 +191,15 @@ typedef struct IDAMemRec {
 
   /* Flags to verify correct calling sequence */
 
-  booleantype ida_SetupDone;  /* set to FALSE by IDAMalloc and IDAReInit
-                                 set to TRUE by IDACalcIC or IDASolve         */
+  booleantype ida_SetupDone;  /* set to SUNFALSE by IDAMalloc and IDAReInit
+                                 set to SUNTRUE by IDACalcIC or IDASolve      */
 
   booleantype ida_VatolMallocDone;
   booleantype ida_constraintsMallocDone;
   booleantype ida_idMallocDone;
 
-  booleantype ida_MallocDone; /* set to FALSE by IDACreate
-                                 set to TRUE by IDAMAlloc
+  booleantype ida_MallocDone; /* set to SUNFALSE by IDACreate
+                                 set to SUNTRUE by IDAMAlloc
                                  tested by IDAReInit and IDASolve             */
 
   /* Linear Solver Data */
@@ -274,8 +273,8 @@ typedef struct IDAMemRec {
 /*
  * -----------------------------------------------------------------
  * int (*ida_lsetup)(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,   
- *                  N_Vector resp,                                 
- *            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);  
+ *                   N_Vector resp, N_Vector tempv1, 
+ *                   N_Vector tempv2, N_Vector tempv3);  
  * -----------------------------------------------------------------
  * The job of ida_lsetup is to prepare the linear solver for       
  * subsequent calls to ida_lsolve. Its parameters are as follows:  
@@ -283,7 +282,6 @@ typedef struct IDAMemRec {
  * idamem - problem memory pointer of type IDAMem. See the big     
  *          typedef earlier in this file.                          
  *                                                                 
- *                                                                 
  * yyp   - the predicted y vector for the current IDA internal     
  *         step.                                                   
  *                                                                 
@@ -304,7 +302,7 @@ typedef struct IDAMemRec {
 /*
  * -----------------------------------------------------------------
  * int (*ida_lsolve)(IDAMem IDA_mem, N_Vector b, N_Vector weight,  
- *               N_Vector ycur, N_Vector ypcur, N_Vector rescur);  
+ *                   N_Vector ycur, N_Vector ypcur, N_Vector rescur);  
  * -----------------------------------------------------------------
  * ida_lsolve must solve the linear equation P x = b, where        
  * P is some approximation to the system Jacobian                  
diff --git a/src/ida/ida_io.c b/src/ida/ida_io.c
index ade32f5..fd6e6e5 100644
--- a/src/ida/ida_io.c
+++ b/src/ida/ida_io.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4529 $
- * $Date: 2015-09-02 15:41:00 -0700 (Wed, 02 Sep 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Alan Hindmarsh, Radu Serban and
  *                Aaron Collier @ LLNL
@@ -39,15 +39,6 @@
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define lrw  (IDA_mem->ida_lrw)
-#define liw  (IDA_mem->ida_liw)
-#define lrw1 (IDA_mem->ida_lrw1)
-#define liw1 (IDA_mem->ida_liw1)
-
 int IDASetErrHandlerFn(void *ida_mem, IDAErrHandlerFn ehfun, void *eh_data)
 {
   IDAMem IDA_mem;
@@ -230,7 +221,7 @@ int IDASetStopTime(void *ida_mem, realtype tstop)
   }
 
   IDA_mem->ida_tstop = tstop;
-  IDA_mem->ida_tstopset = TRUE;
+  IDA_mem->ida_tstopset = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
@@ -346,18 +337,18 @@ int IDASetId(void *ida_mem, N_Vector id)
   if (id == NULL) {
     if (IDA_mem->ida_idMallocDone) {
       N_VDestroy(IDA_mem->ida_id);
-      lrw -= lrw1;
-      liw -= liw1;
+      IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+      IDA_mem->ida_liw -= IDA_mem->ida_liw1;
     }
-    IDA_mem->ida_idMallocDone = FALSE;    
+    IDA_mem->ida_idMallocDone = SUNFALSE;    
     return(IDA_SUCCESS);
   }
 
   if ( !(IDA_mem->ida_idMallocDone) ) {
     IDA_mem->ida_id = N_VClone(id);
-    lrw += lrw1;
-    liw += liw1;
-    IDA_mem->ida_idMallocDone = TRUE;
+    IDA_mem->ida_lrw += IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw += IDA_mem->ida_liw1;
+    IDA_mem->ida_idMallocDone = SUNTRUE;
   }
 
   /* Load the id vector */
@@ -384,11 +375,11 @@ int IDASetConstraints(void *ida_mem, N_Vector constraints)
   if (constraints == NULL) {
     if (IDA_mem->ida_constraintsMallocDone) {
       N_VDestroy(IDA_mem->ida_constraints);
-      lrw -= lrw1;
-      liw -= liw1;
+      IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+      IDA_mem->ida_liw -= IDA_mem->ida_liw1;
     }
-    IDA_mem->ida_constraintsMallocDone = FALSE;
-    IDA_mem->ida_constraintsSet = FALSE;
+    IDA_mem->ida_constraintsMallocDone = SUNFALSE;
+    IDA_mem->ida_constraintsSet = SUNFALSE;
     return(IDA_SUCCESS);
   }
 
@@ -413,16 +404,16 @@ int IDASetConstraints(void *ida_mem, N_Vector constraints)
 
   if ( !(IDA_mem->ida_constraintsMallocDone) ) {
     IDA_mem->ida_constraints = N_VClone(constraints);
-    lrw += lrw1;
-    liw += liw1;
-    IDA_mem->ida_constraintsMallocDone = TRUE;
+    IDA_mem->ida_lrw += IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw += IDA_mem->ida_liw1;
+    IDA_mem->ida_constraintsMallocDone = SUNTRUE;
   }
 
   /* Load the constraints vector */
 
   N_VScale(ONE, constraints, IDA_mem->ida_constraints);
 
-  IDA_mem->ida_constraintsSet = TRUE;
+  IDA_mem->ida_constraintsSet = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
@@ -643,35 +634,6 @@ int IDASetStepToleranceIC(void *ida_mem, realtype steptol)
 
 /* 
  * =================================================================
- * Readability constants
- * =================================================================
- */
-
-#define ewt         (IDA_mem->ida_ewt)
-#define kk          (IDA_mem->ida_kk)
-#define hh          (IDA_mem->ida_hh)
-#define h0u         (IDA_mem->ida_h0u)
-#define tn          (IDA_mem->ida_tn)
-#define nbacktr     (IDA_mem->ida_nbacktr)
-#define nst         (IDA_mem->ida_nst)
-#define nre         (IDA_mem->ida_nre)
-#define ncfn        (IDA_mem->ida_ncfn)
-#define netf        (IDA_mem->ida_netf)
-#define nni         (IDA_mem->ida_nni)
-#define nsetups     (IDA_mem->ida_nsetups)
-#define lrw         (IDA_mem->ida_lrw)
-#define liw         (IDA_mem->ida_liw)
-#define kused       (IDA_mem->ida_kused)          
-#define hused       (IDA_mem->ida_hused)         
-#define tolsf       (IDA_mem->ida_tolsf) 
-#define efun        (IDA_mem->ida_efun)
-#define edata       (IDA_mem->ida_edata)
-#define nge         (IDA_mem->ida_nge)
-#define iroots      (IDA_mem->ida_iroots)
-#define ee          (IDA_mem->ida_ee)
-
-/* 
- * =================================================================
  * IDA optional input functions
  * =================================================================
  */
@@ -687,7 +649,7 @@ int IDAGetNumSteps(void *ida_mem, long int *nsteps)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nsteps = nst;
+  *nsteps = IDA_mem->ida_nst;
 
   return(IDA_SUCCESS);
 }
@@ -705,7 +667,7 @@ int IDAGetNumResEvals(void *ida_mem, long int *nrevals)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nrevals = nre;
+  *nrevals = IDA_mem->ida_nre;
 
   return(IDA_SUCCESS);
 }
@@ -723,7 +685,7 @@ int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nlinsetups = nsetups;
+  *nlinsetups = IDA_mem->ida_nsetups;
 
   return(IDA_SUCCESS);
 }
@@ -741,7 +703,7 @@ int IDAGetNumErrTestFails(void *ida_mem, long int *netfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *netfails = netf;
+  *netfails = IDA_mem->ida_netf;
 
   return(IDA_SUCCESS);
 }
@@ -759,7 +721,7 @@ int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktracks)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nbacktracks = nbacktr;
+  *nbacktracks = IDA_mem->ida_nbacktr;
 
   return(IDA_SUCCESS);
 }
@@ -801,7 +763,7 @@ int IDAGetLastOrder(void *ida_mem, int *klast)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *klast = kused;
+  *klast = IDA_mem->ida_kused;
 
   return(IDA_SUCCESS);
 }
@@ -819,7 +781,7 @@ int IDAGetCurrentOrder(void *ida_mem, int *kcur)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *kcur = kk;
+  *kcur = IDA_mem->ida_kk;
 
   return(IDA_SUCCESS);
 }
@@ -837,7 +799,7 @@ int IDAGetActualInitStep(void *ida_mem, realtype *hinused)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *hinused = h0u;
+  *hinused = IDA_mem->ida_h0u;
 
   return(IDA_SUCCESS);
 }
@@ -855,7 +817,7 @@ int IDAGetLastStep(void *ida_mem, realtype *hlast)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *hlast = hused;
+  *hlast = IDA_mem->ida_hused;
 
   return(IDA_SUCCESS);
 }
@@ -873,7 +835,7 @@ int IDAGetCurrentStep(void *ida_mem, realtype *hcur)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *hcur = hh;
+  *hcur = IDA_mem->ida_hh;
 
   return(IDA_SUCCESS);
 }
@@ -891,7 +853,7 @@ int IDAGetCurrentTime(void *ida_mem, realtype *tcur)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *tcur = tn;
+  *tcur = IDA_mem->ida_tn;
 
   return(IDA_SUCCESS);
 }
@@ -909,7 +871,7 @@ int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *tolsfact = tolsf;
+  *tolsfact = IDA_mem->ida_tolsf;
 
   return(IDA_SUCCESS);
 }
@@ -927,7 +889,7 @@ int IDAGetErrWeights(void *ida_mem, N_Vector eweight)
 
   IDA_mem = (IDAMem) ida_mem; 
 
-  N_VScale(ONE, ewt, eweight);
+  N_VScale(ONE, IDA_mem->ida_ewt, eweight);
 
   return(IDA_SUCCESS);
 }
@@ -944,7 +906,7 @@ int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  N_VScale(ONE, ee, ele);
+  N_VScale(ONE, IDA_mem->ida_ee, ele);
 
   return(IDA_SUCCESS);
 }
@@ -962,8 +924,8 @@ int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *leniw = liw;
-  *lenrw = lrw;
+  *leniw = IDA_mem->ida_liw;
+  *lenrw = IDA_mem->ida_lrw;
 
   return(IDA_SUCCESS);
 }
@@ -984,16 +946,16 @@ int IDAGetIntegratorStats(void *ida_mem, long int *nsteps, long int *nrevals,
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nsteps     = nst;
-  *nrevals    = nre;
-  *nlinsetups = nsetups;
-  *netfails   = netf;
-  *klast      = kused;
-  *kcur       = kk;
-  *hinused    = h0u;
-  *hlast      = hused;
-  *hcur       = hh;  
-  *tcur       = tn;
+  *nsteps     = IDA_mem->ida_nst;
+  *nrevals    = IDA_mem->ida_nre;
+  *nlinsetups = IDA_mem->ida_nsetups;
+  *netfails   = IDA_mem->ida_netf;
+  *klast      = IDA_mem->ida_kused;
+  *kcur       = IDA_mem->ida_kk;
+  *hinused    = IDA_mem->ida_h0u;
+  *hlast      = IDA_mem->ida_hused;
+  *hcur       = IDA_mem->ida_hh;  
+  *tcur       = IDA_mem->ida_tn;
 
   return(IDA_SUCCESS);
 }
@@ -1011,7 +973,7 @@ int IDAGetNumGEvals(void *ida_mem, long int *ngevals)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *ngevals = nge;
+  *ngevals = IDA_mem->ida_nge;
 
   return(IDA_SUCCESS);
 }
@@ -1032,7 +994,7 @@ int IDAGetRootInfo(void *ida_mem, int *rootsfound)
 
   nrt = IDA_mem->ida_nrtfn;
 
-  for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+  for (i=0; i<nrt; i++) rootsfound[i] = IDA_mem->ida_iroots[i];
 
   return(IDA_SUCCESS);
 }
@@ -1050,7 +1012,7 @@ int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nniters = nni;
+  *nniters = IDA_mem->ida_nni;
 
   return(IDA_SUCCESS);
 }
@@ -1068,7 +1030,7 @@ int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nncfails = ncfn;
+  *nncfails = IDA_mem->ida_ncfn;
 
   return(IDA_SUCCESS);
 }
@@ -1086,8 +1048,8 @@ int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters, long int *nncfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nniters  = nni;
-  *nncfails = ncfn;
+  *nniters  = IDA_mem->ida_nni;
+  *nncfails = IDA_mem->ida_ncfn;
 
   return(IDA_SUCCESS);
 }
diff --git a/src/ida/ida_klu.c b/src/ida/ida_klu.c
deleted file mode 100644
index 78d9f1b..0000000
--- a/src/ida/ida_klu.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4874 $
- * $Date: 2016-08-31 10:22:40 -0700 (Wed, 31 Aug 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDAKLU linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "ida/ida_klu.h"
-#include "ida_impl.h"
-#include "ida_sparse_impl.h"
-#include "sundials/sundials_klu_impl.h"
-#include "sundials/sundials_math.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-#define TWOTHIRDS    RCONST(0.6666666666666667)
-
-/* IDAKLU linit, lsetup, lsolve, and lfree routines */
- 
-static int IDAKLUInit(IDAMem IDA_mem);
-
-static int IDAKLUSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-		       N_Vector rrp, N_Vector tmp1,
-		       N_Vector tmp2, N_Vector tmp3);
-
-static int IDAKLUSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-			     N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDAKLUFree(IDAMem IDA_mem);
-
-/*
- * -----------------------------------------------------------------
- * IDAKLU
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDA / KLU linear solver module.  
- * IDAKLU first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDAKLUInit, IDAKLUSetup,
- * IDAKLUSolve, NULL, and IDAKLUFree, respectively.
- * It allocates memory for a structure of type IDAkluMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE.
- * Finally, it allocates memory for KLU.
- * The return value is IDASLS_SUCCESS = 0, IDASLS_LMEM_FAIL = -1,
- * or IDASLS_ILL_INPUT = -2.
- *
- * NOTE: The KLU linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDAKLU will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int IDAKLU(void *ida_mem, int n, int nnz, int sparsetype)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-  int flag;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDAKLU", 
-                    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASLS", "IDAKLU", 
-                    MSGSP_BAD_NVECTOR);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  if (IDA_mem->ida_lfree != NULL) flag = IDA_mem->ida_lfree(IDA_mem);
-
-  /* Set five main function fields in IDA_mem. */
-  IDA_mem->ida_linit  = IDAKLUInit;
-  IDA_mem->ida_lsetup = IDAKLUSetup;
-  IDA_mem->ida_lsolve = IDAKLUSolve;
-  IDA_mem->ida_lperf  = NULL;
-  IDA_mem->ida_lfree  = IDAKLUFree;
-
-  /* Get memory for IDASlsMemRec. */
-  idasls_mem = (IDASlsMem) malloc(sizeof(struct IDASlsMemRec));
-  if (idasls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDAKLU", 
-                    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* Get memory for KLUData. */
-  klu_data = (KLUData)malloc(sizeof(struct KLUDataRec));
-  if (klu_data == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDAKLU", 
-                    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  IDA_mem->ida_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  idasls_mem->s_jaceval = NULL;
-  idasls_mem->s_jacdata = NULL;
-  idasls_mem->sparsetype = sparsetype;
-
-  /* Allocate memory for the sparse Jacobian */
-  idasls_mem->s_JacMat = SparseNewMat(n, n, nnz, sparsetype);
-  if (idasls_mem->s_JacMat == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDAKLU", 
-                    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* KInitialize KLU structures */
-  switch (sparsetype) {
-    case CSC_MAT:
-      klu_data->sun_klu_solve = &klu_solve;
-      break;
-    case CSR_MAT:
-      klu_data->sun_klu_solve = &klu_tsolve;
-      break;
-    default:
-      SparseDestroyMat(idasls_mem->s_JacMat);
-      free(klu_data);
-      free(idasls_mem);
-      return(IDASLS_ILL_INPUT);
-  }
-  klu_data->s_Symbolic = NULL;
-  klu_data->s_Numeric = NULL;
-
-  /* Set default parameters for KLU */
-  flag = klu_defaults(&klu_data->s_Common);
-  if (flag == 0) {
-    IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "IDAKLU", 
-                    MSGSP_PACKAGE_FAIL);
-    return(IDASLS_PACKAGE_FAIL);
-  }
-
-  /* Set ordering to COLAMD as the idas default use.
-     Users can set a different value with IDAKLUSetOrdering,
-     and the user-set value is loaded before any call to klu_analyze in
-     IDAKLUSetup.  */
-  klu_data->s_ordering = 1;
-  klu_data->s_Common.ordering = klu_data->s_ordering;
-
-  /* Attach linear solver memory to the integrator memory */
-  idasls_mem->s_solver_data = (void *) klu_data;
-  IDA_mem->ida_lmem = idasls_mem;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDAKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to IDAKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is IDASLS_SUCCESS = 0, IDASLS_MEM_NULL = -1, 
- * IDASLS_LMEM_NULL = -2, IDASLS_ILL_INPUT = -3, or IDASLS_MEM_FAIL = -4.
- * -----------------------------------------------------------------
- */
-
-int IDAKLUReInit(void *ida_mem_v, int n, int nnz, int reinit_type)
-{
-  IDAMem ida_mem;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem_v == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDAKLUReInit", 
-                    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  ida_mem = (IDAMem) ida_mem_v;
-
-  /* Return immediately if ark_lmem is NULL. */
-  if (ida_mem->ida_lmem == NULL) {
-    IDAProcessError(NULL, IDASLS_LMEM_NULL, "IDASLS", "IDAKLUReInit", 
-                    MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-
-  idasls_mem = (IDASlsMem) (ida_mem->ida_lmem);
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  /* Return if reinit_type is not valid */
-  if ((reinit_type != 1) && (reinit_type != 2)) {
-    IDAProcessError(NULL, IDASLS_ILL_INPUT, "IDASLS", "IDAKLUReInit", 
-                    MSGSP_ILL_INPUT);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  if (reinit_type == 1) {
-
-    /* Destroy previous Jacobian information */
-    if (idasls_mem->s_JacMat) {
-      SparseDestroyMat(idasls_mem->s_JacMat);
-    }
-
-    /* Allocate memory for the sparse Jacobian */
-    idasls_mem->s_JacMat = SparseNewMat(n, n, nnz, idasls_mem->sparsetype);
-    if (idasls_mem->s_JacMat == NULL) {
-      IDAProcessError(ida_mem, IDASLS_MEM_FAIL, "IDASLS", "IDAKLU", 
-                      MSGSP_MEM_FAIL);
-      return(IDASLS_MEM_FAIL);
-    }
-  }
-
-  /* Free the prior factorazation and reset for first factorization */
-  if( klu_data->s_Symbolic != NULL)
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  if( klu_data->s_Numeric != NULL)
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  idasls_mem->s_first_factorize = 1;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDAKLU interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDAKLU
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int IDAKLUInit(IDAMem IDA_mem)
-{
-  IDASlsMem idasls_mem;
-
-  idasls_mem = (IDASlsMem)IDA_mem->ida_lmem;
-
-  idasls_mem->s_jacdata = IDA_mem->ida_user_data;
-
-  idasls_mem->s_nje = 0;
-  /* This forces a factorize every call to IDA */
-  idasls_mem->s_first_factorize = 1;
-
-  idasls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the IDAKLU linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     IDASLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDAKLUSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-		       N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-		       N_Vector tmp3)
-{
-  int retval;
-  realtype tn, cj;
-  IDASlsMem idasls_mem;
-  IDASlsSparseJacFn jaceval;
-  KLUData klu_data;
-  SlsMat JacMat;
-  void *jacdata;
-  
-  realtype uround_twothirds;
-
-  uround_twothirds = SUNRpowerR(IDA_mem->ida_uround,TWOTHIRDS);
-
-  idasls_mem = (IDASlsMem) (IDA_mem->ida_lmem);
-  tn = IDA_mem->ida_tn; 
-  cj = IDA_mem->ida_cj;
-
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  jaceval = idasls_mem->s_jaceval;
-  jacdata = idasls_mem->s_jacdata;
-  JacMat = idasls_mem->s_JacMat;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_JAC_NOSET, "IDASLS", "IDAKLUSetup", 
-		    MSGSP_JAC_NOSET);
-    free(idasls_mem); idasls_mem = NULL;
-    return(IDASLS_JAC_NOSET);
-  }
-
-  /* Increment nje counter and call Jacobian eval routine. */
-  idasls_mem->s_nje++;
-  retval = jaceval(tn, cj, yyp, ypp, rrp, JacMat, jacdata, 
-		   tmp1, tmp2, tmp3);
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDASLS_JACFUNC_UNRECVR, "IDASLS", 
-		    "IDAKLUSetup", MSGSP_JACFUNC_FAILED);
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_UNRECVR;
-    return(IDASLS_JACFUNC_UNRECVR);
-  }
-  if (retval > 0) {
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  if (idasls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get the symbolic factorization
-       ------------------------------------------------------------*/ 
-    /* Update the ordering option with any user-updated values from 
-       calls to IDAKLUSetOrdering */
-    klu_data->s_Common.ordering = klu_data->s_ordering;
-
-     if (klu_data->s_Symbolic != NULL) {
-       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    }
-     klu_data->s_Symbolic = klu_analyze(JacMat->NP, JacMat->indexptrs, 
-				       JacMat->indexvals, &(klu_data->s_Common));
-     if (klu_data->s_Symbolic == NULL) {
-      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "IDAKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(IDASLS_PACKAGE_FAIL);
-     }
-
-     /* ------------------------------------------------------------
-	Compute the LU factorization of  the Jacobian.
-       ------------------------------------------------------------*/
-     if( klu_data->s_Numeric != NULL) {
-       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-     }
-     klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
-				      klu_data->s_Symbolic, &(klu_data->s_Common));
-
-     if (klu_data->s_Numeric == NULL) {
-       IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "IDAKLUSetup", 
-		       MSGSP_PACKAGE_FAIL);
-       return(IDASLS_PACKAGE_FAIL);
-     }
-
-     idasls_mem->s_first_factorize = 0;
-  }
-  else {
-
-    retval = klu_refactor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
-			  klu_data->s_Symbolic, klu_data->s_Numeric,
-			  &(klu_data->s_Common));
-    if (retval == 0) {
-      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(IDASLS_PACKAGE_FAIL);
-    }
-    
-    /*-----------------------------------------------------------
-      Check if a cheap estimate of the reciprocal of the condition 
-      number is getting too small.  If so, delete
-      the prior numeric factorization and recompute it.
-      -----------------------------------------------------------*/
-    
-    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
-		       &(klu_data->s_Common));
-    if (retval == 0) {
-      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(IDASLS_PACKAGE_FAIL);
-    }
-
-    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
-      
-      /* Condition number may be getting large.  
-	 Compute more accurate estimate */
-      retval = klu_condest(JacMat->indexptrs, JacMat->data, 
-			   klu_data->s_Symbolic, klu_data->s_Numeric,
-			   &(klu_data->s_Common));
-      if (retval == 0) {
-	IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
-			MSGSP_PACKAGE_FAIL);
-	return(IDASLS_PACKAGE_FAIL);
-      }
-      
-      if ( (klu_data->s_Common.condest) > 
-	   (1.0/uround_twothirds) ) {
-
-	/* More accurate estimate also says condition number is 
-	   large, so recompute the numeric factorization */
-
-	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-	
-	klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-					 JacMat->data, klu_data->s_Symbolic, 
-					 &(klu_data->s_Common));
-
-	if (klu_data->s_Numeric == NULL) {
-	  IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", 
-			  "IDAKLUSetup", MSGSP_PACKAGE_FAIL);
-	  return(IDASLS_PACKAGE_FAIL);
-	}
-      }
-    }
-  }
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the IDAKLU linear
-  solver module.  It calls the KLU solve routine, scales the
-  solution vector according to cjratio, then returns IDASLS_SUCCESS = 0.
-*/
-
-static int IDAKLUSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-		       N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  int flag;
-  realtype cjratio;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-  SlsMat JacMat;
-  realtype *bd;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-  JacMat = idasls_mem->s_JacMat;
-  cjratio = IDA_mem->ida_cjratio;
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-  bd = N_VGetArrayPointer(b);
-
-  /* Call KLU to solve the linear system */
-  flag = klu_data->sun_klu_solve(klu_data->s_Symbolic, klu_data->s_Numeric, JacMat->NP, 1, bd, 
-                                 &(klu_data->s_Common));
-  if (flag == 0) {
-    IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "IDAKLUSolve", 
-		    MSGSP_PACKAGE_FAIL);
-    return(IDASLS_PACKAGE_FAIL);
-  }
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-  return(IDASLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the IDAKLU linear solver.
-*/
-
-static int IDAKLUFree(IDAMem IDA_mem)
-{
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  if( klu_data->s_Numeric != NULL)
-  {
-     klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  }
-  if( klu_data->s_Symbolic != NULL)
-  {
-     klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  }
-
-  if (idasls_mem->s_JacMat) {
-    SparseDestroyMat(idasls_mem->s_JacMat);
-    idasls_mem->s_JacMat = NULL;
-  }
-
-  free(klu_data); 
-  free(IDA_mem->ida_lmem); 
-
-  return(IDASLS_SUCCESS);
-}
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDAKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in IDA is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int IDAKLUSetOrdering(void *ida_mem_v, int ordering_choice)
-{
-  IDAMem ida_mem;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-
- /* Return immediately if ida_mem is NULL */
-  if (ida_mem_v == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDAKLUSetOrdering",
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  ida_mem = (IDAMem) ida_mem_v;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) ) {
-    IDAProcessError(NULL, IDASLS_ILL_INPUT, "IDASLS", "IDAKLUSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  idasls_mem = (IDASlsMem) ida_mem->ida_lmem;
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  klu_data->s_ordering = ordering_choice;
-
-  return(IDASLS_SUCCESS);
-}
diff --git a/src/ida/ida_lapack.c b/src/ida/ida_lapack.c
deleted file mode 100644
index bbe524f..0000000
--- a/src/ida/ida_lapack.c
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4951 $
- * $Date: 2016-09-22 10:21:00 -0700 (Thu, 22 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for a IDA dense linear solver
- * using BLAS and LAPACK functions.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <ida/ida_lapack.h>
-#include "ida_direct_impl.h"
-#include "ida_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/* IDALAPACK DENSE linit, lsetup, lsolve, and lfree routines */ 
-static int idaLapackDenseInit(IDAMem IDA_mem);
-static int idaLapackDenseSetup(IDAMem IDA_mem,
-                               N_Vector yP, N_Vector ypP, N_Vector fctP, 
-                               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int idaLapackDenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                               N_Vector yC, N_Vector ypC, N_Vector fctC);
-static int idaLapackDenseFree(IDAMem IDA_mem);
-
-/* IDALAPACK BAND linit, lsetup, lsolve, and lfree routines */ 
-static int idaLapackBandInit(IDAMem IDA_mem);
-static int idaLapackBandSetup(IDAMem IDA_mem,
-                              N_Vector yP, N_Vector ypP, N_Vector fctP, 
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int idaLapackBandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector ypC, N_Vector fctC);
-static int idaLapackBandFree(IDAMem IDA_mem);
-
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define res            (IDA_mem->ida_res)
-#define nst            (IDA_mem->ida_nst)
-#define tn             (IDA_mem->ida_tn)
-#define hh             (IDA_mem->ida_hh)
-#define cj             (IDA_mem->ida_cj)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define ewt            (IDA_mem->ida_ewt)
-#define constraints    (IDA_mem->ida_constraints)
-
-#define linit          (IDA_mem->ida_linit)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve)
-#define lfree          (IDA_mem->ida_lfree)
-#define lperf          (IDA_mem->ida_lperf)
-#define lmem           (IDA_mem->ida_lmem)
-#define tempv          (IDA_mem->ida_tempv1)
-#define setupNonNull   (IDA_mem->ida_setupNonNull)
-
-#define mtype          (idadls_mem->d_type)
-#define n              (idadls_mem->d_n)
-#define ml             (idadls_mem->d_ml)
-#define mu             (idadls_mem->d_mu)
-#define smu            (idadls_mem->d_smu)
-#define jacDQ          (idadls_mem->d_jacDQ)
-#define djac           (idadls_mem->d_djac)
-#define bjac           (idadls_mem->d_bjac)
-#define JJ             (idadls_mem->d_J)
-#define pivots         (idadls_mem->d_pivots)
-#define nje            (idadls_mem->d_nje)
-#define nreDQ          (idadls_mem->d_nreDQ)
-#define J_data         (idadls_mem->d_J_data)
-#define last_flag      (idadls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * -----------------------------------------------------------------
- * IDALapackDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the linear solver module.  IDALapackDense first
- * calls the existing lfree routine if this is not NULL.  Then it sets
- * the ida_linit, ida_lsetup, ida_lsolve, ida_lfree fields in (*ida_mem)
- * to be idaLapackDenseInit, idaLapackDenseSetup, idaLapackDenseSolve, 
- * and idaLapackDenseFree, respectively.  It allocates memory for a 
- * structure of type IDADlsMemRec and sets the ida_lmem field in 
- * (*ida_mem) to the address of this structure.  It sets setupNonNull 
- * in (*ida_mem) to TRUE, and the d_jac field to the default 
- * idaLapackDenseDQJac. Finally, it allocates memory for M, pivots.
- *
- * The return value is SUCCESS = 0, or LMEM_FAIL = -1.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDALapackDense will first 
- *       test for a compatible N_Vector internal representation 
- *       by checking that N_VGetArrayPointer and N_VSetArrayPointer 
- *       exist.
- * -----------------------------------------------------------------
- */
-int IDALapackDense(void *ida_mem, int N)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDALAPACK", "IDALapackDense", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the LAPACK solver */
-  if (tempv->ops->nvgetarraypointer == NULL ||
-      tempv->ops->nvsetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDALAPACK", "IDALapackDense", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(IDA_mem);
-
-  /* Set four main function fields in IDA_mem */
-  linit  = idaLapackDenseInit;
-  lsetup = idaLapackDenseSetup;
-  lsolve = idaLapackDenseSolve;
-  lperf  = NULL;
-  lfree  = idaLapackDenseFree;
-
-  /* Get memory for IDADlsMemRec */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackDense", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  djac   = NULL;
-  J_data = NULL;
-
-  last_flag = IDADLS_SUCCESS;
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = (long int) N;
-
-  /* Allocate memory for JJ and pivot array */
-  JJ = NULL;
-  pivots = NULL;
-
-  JJ = NewDenseMat(n, n);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackDense", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackDense", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDALapackBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module. It first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * ida_linit, ida_lsetup, ida_lsolve, and ida_lfree fields in (*ida_mem)
- * to be idaLapackBandInit, idaLapackBandSetup, idaLapackBandSolve, 
- * and idaLapackBandFree, respectively.  It allocates memory for a 
- * structure of type IDALapackBandMemRec and sets the ida_lmem field in 
- * (*ida_mem) to the address of this structure.  It sets setupNonNull 
- * in (*ida_mem) to be TRUE, mu to be mupper, ml to be mlower, and 
- * the jacE and jacI field to NULL.
- * Finally, it allocates memory for M and pivots.
- * The IDALapackBand return value is IDADLS_SUCCESS = 0, 
- * IDADLS_MEM_FAIL = -1, or IDADLS_ILL_INPUT = -2.
- *
- * NOTE: The IDALAPACK linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDALapackBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */                  
-int IDALapackBand(void *ida_mem, int N, int mupper, int mlower)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDALAPACK", "IDALapackBand", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (tempv->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDALAPACK", "IDALapackBand", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(IDA_mem);
-
-  /* Set four main function fields in IDA_mem */  
-  linit  = idaLapackBandInit;
-  lsetup = idaLapackBandSetup;
-  lsolve = idaLapackBandSolve;
-  lperf  = NULL;
-  lfree  = idaLapackBandFree;
-  
-  /* Get memory for IDADlsMemRec */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackBand", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  bjac   = NULL;
-  J_data = NULL;
-
-  last_flag = IDADLS_SUCCESS;
-
-  idaDlsInitializeCounters(idadls_mem);
-
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = (long int) N;
-
-  /* Load half-bandwiths in idadls_mem */
-  ml = (long int) mlower;
-  mu = (long int) mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= n) || (mu >= n)) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDALAPACK", "IDALapackBand", MSGD_BAD_SIZES);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = mu + ml;
-
-  /* Allocate memory for JJ and pivot arrays */
-  JJ = NULL;
-  pivots = NULL;
-
-  JJ = NewBandMat(n, mu, ml, smu);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackBand", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }  
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDALAPACK", "IDALapackBand", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS
- * =================================================================
- */
-
-/*
- * idaLapackDenseInit does remaining initializations specific to the dense
- * linear solver.
- */
-static int idaLapackDenseInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  idaDlsInitializeCounters(idadls_mem);
-  
-  /*
-     nje   = 0;
-     nreDQ = 0;
-  */
-
-  if (jacDQ) {
-    djac = idaDlsDenseDQJac;
-    J_data = IDA_mem;
-  } else {
-    J_data = IDA_mem->ida_user_data;
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackDenseSetup does the setup operations for the dense linear solver. 
- * It calls the Jacobian function to obtain the Newton matrix M = F_y + c_j*F_y', 
- * updates counters, and calls the dense LU factorization routine.
- */
-static int idaLapackDenseSetup(IDAMem IDA_mem,
-                               N_Vector yP, N_Vector ypP, N_Vector fctP,
-                               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  IDADlsMem idadls_mem;
-  int ier, retval;
-  int intn;
-
-  idadls_mem = (IDADlsMem) lmem;
-  intn = (int) n;
-
-  /* Call Jacobian function */
-  nje++;
-  SetToZero(JJ);
-  retval = djac(n, tn, cj, yP, ypP, fctP, JJ, J_data, tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDALAPACK", "idaLapackDenseSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  } else if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(1);
-  }
-  
-  /* Do LU factorization of M */
-  dgetrf_f77(&intn, &intn, JJ->data, &intn, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-/*
- * idaLapackDenseSolve handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.
- */
-static int idaLapackDenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                               N_Vector yC, N_Vector ypC, N_Vector fctC)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn;
-
-  idadls_mem = (IDADlsMem) lmem;
-  intn = (int) n;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgetrs_f77("N", &intn, &one, JJ->data, &intn, pivots, bd, &intn, &ier, 1); 
-  if (ier > 0) return(1);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) {
-    fact = TWO/(ONE + cjratio);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackDenseFree frees memory specific to the dense linear solver.
- */
-static int idaLapackDenseFree(IDAMem IDA_mem)
-{
-  IDADlsMem  idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(pivots);
-  free(idadls_mem); 
-  idadls_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS
- * =================================================================
- */
-
-/*
- * idaLapackBandInit does remaining initializations specific to the band
- * linear solver.
- */
-static int idaLapackBandInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  nje   = 0;
-  nreDQ = 0;
-
-  if (jacDQ) {
-    bjac = idaDlsBandDQJac;
-    J_data = IDA_mem;
-  } else {
-    J_data = IDA_mem->ida_user_data;
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackBandSetup does the setup operations for the band linear solver.
- * It calls the Jacobian function to obtain the Newton matrix M = F_y + c_j*F_y', 
- * updates counters, and calls the band LU factorization routine.
- */
-static int idaLapackBandSetup(IDAMem IDA_mem,
-                              N_Vector yP, N_Vector ypP, N_Vector fctP, 
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  IDADlsMem idadls_mem;
-  int ier, retval;
-  int intn, iml, imu, ldmat;
-
-  idadls_mem = (IDADlsMem) lmem;
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = JJ->ldim;
-
-  /* Call Jacobian function */
-  nje++;
-  SetToZero(JJ);
-  retval = bjac(n, mu, ml, tn, cj, yP, ypP, fctP, JJ, J_data, tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDALAPACK", "idaLapackBandSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  } else if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(+1);
-  }
-  
-  /* Do LU factorization of M */
-  dgbtrf_f77(&intn, &intn, &iml, &imu, JJ->data, &ldmat, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-
-}
-
-/*
- * idaLapackBandSolve handles the solve operation for the band linear solver
- * by calling the band backsolve routine.
- */
-static int idaLapackBandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector ypC, N_Vector fctC)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn, iml, imu, ldmat;
-
-  idadls_mem = (IDADlsMem) lmem;
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = JJ->ldim;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgbtrs_f77("N", &intn, &iml, &imu, &one, JJ->data, &ldmat, pivots, bd, &intn, &ier, 1);
-  if (ier > 0) return(1);
-
-  /* For BDF, scale the correction to account for change in cj */
-  if (cjratio != ONE) {
-    fact = TWO/(ONE + cjratio);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackBandFree frees memory specific to the band linear solver.
- */
-static int idaLapackBandFree(IDAMem IDA_mem)
-{
-  IDADlsMem  idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(pivots);
-  free(idadls_mem); 
-  idadls_mem = NULL;
-
-  return(0);
-}
-
diff --git a/src/ida/ida_sparse.c b/src/ida/ida_sparse.c
deleted file mode 100644
index c683f78..0000000
--- a/src/ida/ida_sparse.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for an IDASLS linear solver.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "ida_impl.h"
-#include "ida_sparse_impl.h"
-#include <sundials/sundials_math.h>
-
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * IDASlsSetSparseJacFn specifies the sparse Jacobian function.
- */
-int IDASlsSetSparseJacFn(void *ida_mem, IDASlsSparseJacFn jac)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDASlsSetSparseJacFn", 
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_LMEM_NULL, "IDASLS", 
-		    "IDASlsSetSparseJacFn", MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  idasls_mem->s_jaceval = jac;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * IDASlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
-int IDASlsGetNumJacEvals(void *ida_mem, long int *njevals)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDASlsGetNumJacEvals", MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_LMEM_NULL, "IDASLS", 
-		    "IDASlsGetNumJacEvals", MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  *njevals = idasls_mem->s_nje;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * IDASlsGetReturnFlagName returns the name associated with a IDASLS
- * return value.
- */
-char *IDASlsGetReturnFlagName(long int flag)
-{
-  char *name;
-
-  name = (char *)malloc(30*sizeof(char));
-
-  switch(flag) {
-  case IDASLS_SUCCESS:
-    sprintf(name,"IDASLS_SUCCESS");
-    break;   
-  case IDASLS_MEM_NULL:
-    sprintf(name,"IDASLS_MEM_NULL");
-    break;
-  case IDASLS_LMEM_NULL:
-    sprintf(name,"IDASLS_LMEM_NULL");
-    break;
-  case IDASLS_ILL_INPUT:
-    sprintf(name,"IDASLS_ILL_INPUT");
-    break;
-  case IDASLS_MEM_FAIL:
-    sprintf(name,"IDASLS_MEM_FAIL");
-    break;
-  case IDASLS_JAC_NOSET:
-    sprintf(name,"IDASLS_JAC_NOSET");
-    break;
-  case IDASLS_JACFUNC_UNRECVR:
-    sprintf(name,"IDASLS_JACFUNC_UNRECVR");
-    break;
-  case IDASLS_JACFUNC_RECVR:
-    sprintf(name,"IDASLS_JACFUNC_RECVR");
-    break;
-  default:
-    sprintf(name,"NONE");
-  }
-
-  return(name);
-}
-
-/*
- * IDASlsGetLastFlag returns the last flag set in a IDASLS function.
- */
-int IDASlsGetLastFlag(void *ida_mem, long int *flag)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDASlsGetLastFlag", 
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_LMEM_NULL, "IDASLS", 
-		    "IDASlsGetLastFlag", MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  *flag = idasls_mem->s_last_flag;
-
-  return(IDASLS_SUCCESS);
-}
-
diff --git a/src/ida/ida_sparse_impl.h b/src/ida/ida_sparse_impl.h
deleted file mode 100644
index 65d34b0..0000000
--- a/src/ida/ida_sparse_impl.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Implementation header file for the IDASLS linear solvers.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASPARSE_IMPL_H
-#define _IDASPARSE_IMPL_H
-
-#include "ida/ida_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * I D A S S P A R S E    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASlsMemRec, IDASlsMem                             
- * -----------------------------------------------------------------
- * IDASlsMem is pointer to a IDASlsMemRec structure.
- * -----------------------------------------------------------------
- */
-
-typedef struct IDASlsMemRec {
-
-  IDASlsSparseJacFn s_jaceval; /* user Jacobian evaluation routine 
-                                  to be called */
-  void *s_jacdata;           /* J_data is passed to djac or bjac */
-
-  long int s_nje;           /* nje = no. of calls to jac */
-
-  long int s_last_flag;     /* last error return flag */
-
-  int s_first_factorize;    /* flag telling whether the first 
-                               factorization needs to happen */
-  SlsMat s_JacMat;          /* J = dF/dy + cj*dF/dy' */
-  
-  int sparsetype;           /* matrix type: compressed sparse column or row */
-
-  void *s_solver_data;      /* structure for solver-specific data */
-  
-
-} *IDASlsMem;
-
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-  
-
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASlsMemRecB, IDASlsMemB       
- * -----------------------------------------------------------------
- * An IDASLS linear solver's specification function attaches such
- * a structure to the lmemB filed of IDABMem
- * -----------------------------------------------------------------
- */
-
-typedef struct IDASlsMemRecB {
-
-  IDASlsSparseJacFnB s_djacB;
-  IDASlsSparseJacFnBS s_djacBS;
-
-} *IDASlsMemB;
-
-
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
-
-#define MSGSP_IDAMEM_NULL "Integrator memory is NULL."
-#define MSGSP_BAD_NVECTOR "A required vector operation is not implemented."
-#define MSGSP_MEM_FAIL "A memory request failed."
-#define MSGSP_LMEM_NULL "Linear solver memory is NULL."
-#define MSGSP_ILL_INPUT "Invalid input detected."
-#define MSGSP_JAC_NOSET "Jacobian evaluation function has not been set."
-#define MSGSP_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
-#define MSGSP_PACKAGE_FAIL "A call to an external package failed."
-
-#define MSGSP_CAMEM_NULL "idaadj_mem = NULL illegal."
-#define MSGSP_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
-#define MSGSP_BAD_T "Bad t for interpolation."
-#define MSGSP_BAD_WHICH "Illegal value for which."
-#define MSGSP_NO_ADJ "Illegal attempt to call before calling IDAAdjInit."
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/ida/ida_spbcgs.c b/src/ida/ida_spbcgs.c
deleted file mode 100644
index a795f89..0000000
--- a/src/ida/ida_spbcgs.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4829 $
- * $Date: 2016-07-27 16:01:15 -0700 (Wed, 27 Jul 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDA scaled preconditioned
- * Bi-CGSTAB linear solver module, IDASPBCG.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <ida/ida_spbcgs.h>
-#include "ida_spils_impl.h"
-#include "ida_impl.h"
-
-#include <sundials/sundials_spbcgs.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-#define PT9  RCONST(0.9)
-#define PT05 RCONST(0.05)
-
-/* IDASPBCG linit, lsetup, lsolve, lperf, and lfree routines */
-
-static int IDASpbcgInit(IDAMem IDA_mem);
-
-static int IDASpbcgSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int IDASpbcgSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now);
-
-static int IDASpbcgPerf(IDAMem IDA_mem, int perftask);
-
-static int IDASpbcgFree(IDAMem IDA_mem);
-
-
-/* Readability Replacements */
-
-#define nst          (IDA_mem->ida_nst)
-#define tn           (IDA_mem->ida_tn)
-#define cj           (IDA_mem->ida_cj)
-#define epsNewt      (IDA_mem->ida_epsNewt)
-#define res          (IDA_mem->ida_res)
-#define user_data    (IDA_mem->ida_user_data)
-#define ewt          (IDA_mem->ida_ewt)
-#define errfp        (IDA_mem->ida_errfp)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define nni          (IDA_mem->ida_nni)
-#define ncfn         (IDA_mem->ida_ncfn)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define sqrtN     (idaspils_mem->s_sqrtN)
-#define epslin    (idaspils_mem->s_epslin)
-#define ytemp     (idaspils_mem->s_ytemp)
-#define yptemp    (idaspils_mem->s_yptemp)
-#define xx        (idaspils_mem->s_xx)
-#define ycur      (idaspils_mem->s_ycur)
-#define ypcur     (idaspils_mem->s_ypcur)
-#define rcur      (idaspils_mem->s_rcur)
-#define npe       (idaspils_mem->s_npe)
-#define nli       (idaspils_mem->s_nli)
-#define nps       (idaspils_mem->s_nps)
-#define ncfl      (idaspils_mem->s_ncfl)
-#define nst0      (idaspils_mem->s_nst0)
-#define nni0      (idaspils_mem->s_nni0)
-#define nli0      (idaspils_mem->s_nli0)
-#define ncfn0     (idaspils_mem->s_ncfn0)
-#define ncfl0     (idaspils_mem->s_ncfl0)
-#define nwarn     (idaspils_mem->s_nwarn)
-#define njtimes   (idaspils_mem->s_njtimes)
-#define nres      (idaspils_mem->s_nres)
-#define spils_mem (idaspils_mem->s_spils_mem)
-
-#define jtimesDQ  (idaspils_mem->s_jtimesDQ)
-#define jtimes    (idaspils_mem->s_jtimes)
-#define jdata     (idaspils_mem->s_jdata)
-
-#define last_flag (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcg
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDASPBCG linear solver module.
- *
- * IDASpbcg first calls the existing lfree routine if this is not NULL.
- * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASpbcgInit, IDASpbcgSetup,
- * IDASpbcgSolve, IDASpbcgPerf, and IDASpbcgFree, respectively.
- * It allocates memory for a structure of type IDASpilsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem). It then sets various fields
- * in the IDASpilsMemRec structure. Finally, IDASpbcg allocates memory
- * for ytemp, yptemp, and xx, and calls SpbcgMalloc to allocate memory
- * for the Spbcg solver.
- *
- * The return value of IDASpbcg is:
- *   IDASPILS_SUCCESS   =  0 if successful
- *   IDASPILS_MEM_FAIL  = -1 if IDA_mem is NULL or a memory
- *                           allocation failed
- *   IDASPILS_ILL_INPUT = -2 if a required vector operation is not
- *                           implemented.
- * -----------------------------------------------------------------
- */
-
-int IDASpbcg(void *ida_mem, int maxl)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-  int maxl1;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPBCG", "IDASpbcg", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPBCG", "IDASpbcg", MSGS_BAD_NVECTOR);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem */
-  linit  = IDASpbcgInit;
-  lsetup = IDASpbcgSetup;
-  lsolve = IDASpbcgSolve;
-  lperf  = IDASpbcgPerf;
-  lfree  = IDASpbcgFree;
-
-  /* Get memory for IDASpilsMemRec */
-  idaspils_mem = NULL;
-  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
-  if (idaspils_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  idaspils_mem->s_type = SPILS_SPBCG;
-
-  /* Set SPBCG parameters that were passed in call sequence */
-  maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
-  idaspils_mem->s_maxl = maxl1;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  jdata    = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  idaspils_mem->s_pset   = NULL;
-  idaspils_mem->s_psolve = NULL;
-  idaspils_mem->s_pfree  = NULL;
-  idaspils_mem->s_pdata  = IDA_mem->ida_user_data;
-
-  /* Set default values for the rest of the Spbcg parameters */
-  idaspils_mem->s_eplifac   = PT05;
-  idaspils_mem->s_dqincfac  = ONE;
-
-  idaspils_mem->s_last_flag = IDASPILS_SUCCESS;
-
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to FALSE */
-  setupNonNull = FALSE;
-
-  /* Allocate memory for ytemp, yptemp, and xx */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  yptemp = N_VClone(vec_tmpl);
-  if (yptemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  xx = N_VClone(vec_tmpl);
-  if (xx == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SpbcgMalloc to allocate workspace for Spbcg */
-  spbcg_mem = NULL;
-  spbcg_mem = SpbcgMalloc(maxl1, vec_tmpl);
-  if (spbcg_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    N_VDestroy(xx);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Attach SPBCG memory to spils memory structure */
-  spils_mem = (void *)spbcg_mem;
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idaspils_mem;
-
-  return(IDASPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASPBCG interface routines
- * -----------------------------------------------------------------
- */
-
-/* Additional readability Replacements */
-
-#define maxl     (idaspils_mem->s_maxl)
-#define eplifac  (idaspils_mem->s_eplifac)
-#define psolve   (idaspils_mem->s_psolve)
-#define pset     (idaspils_mem->s_pset)
-#define pdata    (idaspils_mem->s_pdata)
-
-static int IDASpbcgInit(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to TRUE iff there is preconditioning with setup */
-  setupNonNull = (psolve != NULL) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = IDASpilsDQJtimes;
-    jdata = IDA_mem;
-  } else {
-    jdata = user_data;
-  }
-
-  /*  Set maxl in the SPBCG memory in case it was changed by the user */
-  spbcg_mem->l_max  = maxl;
-
-  last_flag = IDASPILS_SUCCESS;
-
-  return(0);
-}
-
-static int IDASpbcgSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  int retval;
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Call user setup routine pset and update counter npe */
-  retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata,
-                tmp1, tmp2, tmp3);
-  npe++;
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, SPBCG_PSET_FAIL_UNREC, "IDASPBCG", "IDASpbcgSetup", MSGS_PSET_FAILED);
-    last_flag = SPBCG_PSET_FAIL_UNREC;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = SPBCG_PSET_FAIL_REC;
-    return(+1);
-  }
-
-  last_flag = SPBCG_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcgSolve
- * -----------------------------------------------------------------
- * Note: The x-scaling and b-scaling arrays are both equal to weight.
- *
- * We set the initial guess, x = 0, then call SpbcgSolve.
- * We copy the solution x into b, and update the counters nli, nps,
- * and ncfl. If SpbcgSolve returned nli_inc = 0 (hence x = 0), we
- * take the SPBCG vtemp vector (= P_inverse F) as the correction
- * vector instead. Finally, we set the return value according to the
- * success of SpbcgSolve.
- * -----------------------------------------------------------------
- */
-
-static int IDASpbcgSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now)
-{
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-  int pretype, nli_inc, nps_inc, retval;
-  realtype res_norm;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  spbcg_mem = (SpbcgMem)spils_mem;
-
-  /* Set SpbcgSolve convergence test constant epslin, in terms of the
-     Newton convergence test constant epsNewt and safety factors. The factor
-     sqrt(Neq) assures that the Bi-CGSTAB convergence test is applied to the
-     WRMS norm of the residual vector, rather than the weighted L2 norm. */
-  epslin = sqrtN*eplifac*epsNewt;
-
-  /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */
-  ycur = yy_now;
-  ypcur = yp_now;
-  rcur = rr_now;
-
-  /* Set SpbcgSolve inputs pretype and initial guess xx = 0 */  
-  pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT;
-  N_VConst(ZERO, xx);
-  
-  /* Call SpbcgSolve and copy xx to bb */
-  retval = SpbcgSolve(spbcg_mem, IDA_mem, xx, bb, pretype, epslin,
-                      IDA_mem, weight, weight, IDASpilsAtimes,
-                      IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  if (nli_inc == 0) N_VScale(ONE, SPBCG_VTEMP(spbcg_mem), bb);
-  else N_VScale(ONE, xx, bb);
-  
-  /* Increment counters nli, nps, and return if successful */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPBCG_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpbcgSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPBCG_SUCCESS:
-    return(0);
-    break;
-  case SPBCG_RES_REDUCED:
-    return(1);
-    break;
-  case SPBCG_CONV_FAIL:
-    return(1);
-    break;
-  case SPBCG_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_MEM_NULL:
-    return(-1);
-    break;
-  case SPBCG_ATIMES_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPBCG_ATIMES_FAIL_UNREC, "IDaSPBCG", "IDASpbcgSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPBCG_PSOLVE_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPBCG_PSOLVE_FAIL_UNREC, "IDASPBCG", "IDASpbcgSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcgPerf
- * -----------------------------------------------------------------
- * This routine handles performance monitoring specific to the
- * IDASPBCG linear solver. When perftask = 0, it saves values of
- * various counters. When perftask = 1, it examines difference
- * quotients in these counters, and depending on their values, it
- * prints up to three warning messages. Messages are printed up to
- * a maximum of 10 times.
- * -----------------------------------------------------------------
- */
-
-static int IDASpbcgPerf(IDAMem IDA_mem, int perftask)
-{
-  IDASpilsMem idaspils_mem;
-  realtype avdim, rcfn, rcfl;
-  long int nstd, nnid;
-  booleantype lavd, lcfn, lcfl;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (perftask == 0) {
-    nst0 = nst;  nni0 = nni;  nli0 = nli;
-    ncfn0 = ncfn;  ncfl0 = ncfl;  
-    nwarn = 0;
-    return(0);
-  }
-
-  nstd = nst - nst0;  nnid = nni - nni0;
-  if (nstd == 0 || nnid == 0) return(0);
-  avdim = (realtype) ((nli - nli0)/((realtype) nnid));
-  rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd));
-  rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid));
-  lavd = (avdim > ((realtype) maxl));
-  lcfn = (rcfn > PT9);
-  lcfl = (rcfl > PT9);
-  if (!(lavd || lcfn || lcfl)) return(0);
-  nwarn++;
-  if (nwarn > 10) return(1);
-  if (lavd) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_AVD_WARN, tn, avdim);
-  if (lcfn) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_CFN_WARN, tn, rcfn);
-  if (lcfl) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_CFL_WARN, tn, rcfl);
-
-  return(0);
-}
-
-static int IDASpbcgFree(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(yptemp);
-  N_VDestroy(xx);
-
-  spbcg_mem = (SpbcgMem)spils_mem;
-  SpbcgFree(spbcg_mem);
-
-  if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem);
-
-  free(idaspils_mem); idaspils_mem = NULL;
-
-  return(0);
-}
diff --git a/src/ida/ida_spgmr.c b/src/ida/ida_spgmr.c
deleted file mode 100644
index e380ddf..0000000
--- a/src/ida/ida_spgmr.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4829 $
- * $Date: 2016-07-27 16:01:15 -0700 (Wed, 27 Jul 2016) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDA Scaled              
- * Preconditioned GMRES linear solver module, IDASPGMR.            
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <ida/ida_spgmr.h>
-#include "ida_spils_impl.h"
-#include "ida_impl.h"
-
-#include <sundials/sundials_spgmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define PT9          RCONST(0.9)
-#define PT05         RCONST(0.05)
-
-/* IDASPGMR linit, lsetup, lsolve, lperf, and lfree routines */
-
-static int IDASpgmrInit(IDAMem IDA_mem);
-
-static int IDASpgmrSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int IDASpgmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now);
-
-static int IDASpgmrPerf(IDAMem IDA_mem, int perftask);
-
-static int IDASpgmrFree(IDAMem IDA_mem);
-
-
-/* Readability Replacements */
-
-#define nst          (IDA_mem->ida_nst)
-#define tn           (IDA_mem->ida_tn)
-#define cj           (IDA_mem->ida_cj)
-#define epsNewt      (IDA_mem->ida_epsNewt)
-#define res          (IDA_mem->ida_res)
-#define user_data    (IDA_mem->ida_user_data)
-#define ewt          (IDA_mem->ida_ewt)
-#define errfp        (IDA_mem->ida_errfp)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define nni          (IDA_mem->ida_nni)
-#define ncfn         (IDA_mem->ida_ncfn)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define sqrtN     (idaspils_mem->s_sqrtN)
-#define epslin    (idaspils_mem->s_epslin)
-#define ytemp     (idaspils_mem->s_ytemp)
-#define yptemp    (idaspils_mem->s_yptemp)
-#define xx        (idaspils_mem->s_xx)
-#define ycur      (idaspils_mem->s_ycur)
-#define ypcur     (idaspils_mem->s_ypcur)
-#define rcur      (idaspils_mem->s_rcur)
-#define npe       (idaspils_mem->s_npe)
-#define nli       (idaspils_mem->s_nli)
-#define nps       (idaspils_mem->s_nps)
-#define ncfl      (idaspils_mem->s_ncfl)
-#define nst0      (idaspils_mem->s_nst0)
-#define nni0      (idaspils_mem->s_nni0)
-#define nli0      (idaspils_mem->s_nli0)
-#define ncfn0     (idaspils_mem->s_ncfn0)
-#define ncfl0     (idaspils_mem->s_ncfl0)
-#define nwarn     (idaspils_mem->s_nwarn)
-#define njtimes   (idaspils_mem->s_njtimes)
-#define nres      (idaspils_mem->s_nres)
-#define spils_mem (idaspils_mem->s_spils_mem)
-
-#define jtimesDQ  (idaspils_mem->s_jtimesDQ)
-#define jtimes    (idaspils_mem->s_jtimes)
-#define jdata     (idaspils_mem->s_jdata)
-
-#define last_flag (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * IDASpgmr
- * -----------------------------------------------------------------
- *
- * This routine initializes the memory record and sets various function
- * fields specific to the IDASPGMR linear solver module.  
- *
- * IDASpgmr first calls the existing lfree routine if this is not NULL.
- * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASpgmrInit, IDASpgmrSetup,
- * IDASpgmrSolve, IDASpgmrPerf, and IDASpgmrFree, respectively.
- * It allocates memory for a structure of type IDASpilsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem).  It then various fields in the
- * IDASpilsMemRec structure. Finally, IDASpgmr allocates memory for 
- * ytemp, yptemp, and xx, and calls SpgmrMalloc to allocate memory
- * for the Spgmr solver.
- *
- * The return value of IDASpgmr is:
- *   IDASPILS_SUCCESS       = 0  if successful
- *   IDASPILS_MEM_FAIL     = -1 if IDA_mem is NULL or a memory allocation failed
- *   IDASPILS_ILL_INPUT = -2 if the gstype argument is illegal.
- *
- * -----------------------------------------------------------------
- */
-
-int IDASpgmr(void *ida_mem, int maxl)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-  SpgmrMem spgmr_mem;
-  int maxl1;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPGMR", "IDASpgmr", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Check if N_VDotProd is present */
-  if(vec_tmpl->ops->nvdotprod == NULL) {
-    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPGMR", "IDASpgmr", MSGS_BAD_NVECTOR);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem */
-  linit  = IDASpgmrInit;
-  lsetup = IDASpgmrSetup;
-  lsolve = IDASpgmrSolve;
-  lperf  = IDASpgmrPerf;
-  lfree  = IDASpgmrFree;
-
-  /* Get memory for IDASpilsMemRec */
-  idaspils_mem = NULL;
-  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
-  if (idaspils_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  idaspils_mem->s_type = SPILS_SPGMR;
-
-  /* Set SPGMR parameters that were passed in call sequence */
-  maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
-  idaspils_mem->s_maxl     = maxl1;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  jdata    = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  idaspils_mem->s_pset   = NULL;
-  idaspils_mem->s_psolve = NULL;
-  idaspils_mem->s_pfree  = NULL;
-  idaspils_mem->s_pdata  = IDA_mem->ida_user_data;
-
-  /* Set default values for the rest of the Spgmr parameters */
-  idaspils_mem->s_gstype   = MODIFIED_GS;
-  idaspils_mem->s_maxrs    = IDA_SPILS_MAXRS;
-  idaspils_mem->s_eplifac  = PT05;
-  idaspils_mem->s_dqincfac = ONE;
-
-  idaspils_mem->s_last_flag  = IDASPILS_SUCCESS;
-  
-  /* initialize solver performance counters */
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to FALSE */
-  setupNonNull = FALSE;
-
-  /* Allocate memory for ytemp, yptemp, and xx */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  yptemp = N_VClone(vec_tmpl);
-  if (yptemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  xx = N_VClone(vec_tmpl);
-  if (xx == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt( N_VDotProd(ytemp, ytemp) );
-
-  /* Call SpgmrMalloc to allocate workspace for Spgmr */
-  spgmr_mem = NULL;
-  spgmr_mem = SpgmrMalloc(maxl1, vec_tmpl);
-  if (spgmr_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    N_VDestroy(xx);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Attach SPGMR memory to spils memory structure */
-  spils_mem = (void *)spgmr_mem;
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idaspils_mem;
-
-  return(IDASPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASPGMR interface routines
- * -----------------------------------------------------------------
- */
-
-/* Additional readability Replacements */
-
-#define gstype   (idaspils_mem->s_gstype)
-#define maxl     (idaspils_mem->s_maxl)
-#define maxrs    (idaspils_mem->s_maxrs)
-#define eplifac  (idaspils_mem->s_eplifac)
-#define psolve   (idaspils_mem->s_psolve)
-#define pset     (idaspils_mem->s_pset)
-#define pdata    (idaspils_mem->s_pdata)
-
-static int IDASpgmrInit(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Initialize counters */
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to TRUE iff there is preconditioning with setup */
-  setupNonNull = (psolve != NULL) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = IDASpilsDQJtimes;
-    jdata = IDA_mem;
-  } else {
-    jdata = user_data;
-  }
-
-  last_flag = IDASPILS_SUCCESS;
-  return(0);
-}
-
-static int IDASpgmrSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  int retval;
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Call user setup routine pset and update counter npe. */
-  retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata,
-                tmp1, tmp2, tmp3);
-  npe++;
-
-  /* Return flag showing success or failure of pset. */
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, SPGMR_PSET_FAIL_UNREC, "IDASPGMR", "IDASpgmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPGMR_PSET_FAIL_UNREC;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = SPGMR_PSET_FAIL_REC;
-    return(+1);
-  }
-
-  last_flag = SPGMR_SUCCESS;
-  return(0);
-}
-
-
-/*
- * The x-scaling and b-scaling arrays are both equal to weight.
- *  
- * We set the initial guess, x = 0, then call SpgmrSolve.  
- * We copy the solution x into b, and update the counters nli, nps, ncfl.
- * If SpgmrSolve returned nli_inc = 0 (hence x = 0), we take the SPGMR
- * vtemp vector (= P_inverse F) as the correction vector instead.
- *  Finally, we set the return value according to the success of SpgmrSolve.
- */
-
-static int IDASpgmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now)
-{
-  IDASpilsMem idaspils_mem;
-  SpgmrMem spgmr_mem;
-  int pretype, nli_inc, nps_inc, retval;
-  realtype res_norm;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-
-  /* Set SpgmrSolve convergence test constant epslin, in terms of the
-    Newton convergence test constant epsNewt and safety factors.  The factor 
-    sqrt(Neq) assures that the GMRES convergence test is applied to the
-    WRMS norm of the residual vector, rather than the weighted L2 norm. */
-  epslin = sqrtN*eplifac*epsNewt;
-
-  /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */
-  ycur = yy_now;
-  ypcur = yp_now;
-  rcur = rr_now;
-
-  /* Set SpgmrSolve inputs pretype and initial guess xx = 0. */  
-  pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT;
-  N_VConst(ZERO, xx);
-  
-  /* Call SpgmrSolve and copy xx to bb. */
-  retval = SpgmrSolve(spgmr_mem, IDA_mem, xx, bb, pretype, gstype, epslin,
-                      maxrs, IDA_mem, weight, weight, IDASpilsAtimes,
-                      IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  if (nli_inc == 0) N_VScale(ONE, SPGMR_VTEMP(spgmr_mem), bb);
-  else N_VScale(ONE, xx, bb);
-  
-  /* Increment counters nli, nps, and return if successful. */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPGMR_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPGMR_SUCCESS:
-    return(0);
-    break;
-  case SPGMR_RES_REDUCED:
-    return(1);
-    break;
-  case SPGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPGMR_ATIMES_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPGMR_ATIMES_FAIL_UNREC, "IDASPGMR", "IDASpgmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPGMR_PSOLVE_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPGMR_PSOLVE_FAIL_UNREC, "IDASPGMR", "IDASpgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * This routine handles performance monitoring specific to the IDASPGMR
- * linear solver.  When perftask = 0, it saves values of various counters.
- * When perftask = 1, it examines difference quotients in these counters,
- * and depending on their values, it prints up to three warning messages.
- * Messages are printed up to a maximum of 10 times.
- */
-
-static int IDASpgmrPerf(IDAMem IDA_mem, int perftask)
-{
-  IDASpilsMem idaspils_mem;
-  realtype avdim, rcfn, rcfl;
-  long int nstd, nnid;
-  booleantype lavd, lcfn, lcfl;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (perftask == 0) {
-    nst0 = nst;  nni0 = nni;  nli0 = nli;
-    ncfn0 = ncfn;  ncfl0 = ncfl;  
-    nwarn = 0;
-    return(0);
-  }
-
-  nstd = nst - nst0;  nnid = nni - nni0;
-  if (nstd == 0 || nnid == 0) return(0);
-  avdim = (realtype) ((nli - nli0)/((realtype) nnid));
-  rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd));
-  rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid));
-  lavd = (avdim > ((realtype) maxl ));
-  lcfn = (rcfn > PT9);
-  lcfl = (rcfl > PT9);
-  if (!(lavd || lcfn || lcfl)) return(0);
-  nwarn++;
-  if (nwarn > 10) return(1);
-  if (lavd) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_AVD_WARN, tn, avdim);
-  if (lcfn) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_CFN_WARN, tn, rcfn);
-  if (lcfl) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_CFL_WARN, tn, rcfl);
-
-  return(0);
-}
-
-static int IDASpgmrFree(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SpgmrMem spgmr_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-  
-  N_VDestroy(ytemp);
-  N_VDestroy(yptemp);
-  N_VDestroy(xx);
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-  SpgmrFree(spgmr_mem);
-
-  if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem);
-
-  free(idaspils_mem); idaspils_mem = NULL;
-
-  return(0);
-}
diff --git a/src/ida/ida_spils.c b/src/ida/ida_spils.c
index b784f46..c8e1179 100644
--- a/src/ida/ida_spils.c
+++ b/src/ida/ida_spils.c
@@ -1,490 +1,607 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the common implementation file for the IDA Scaled              
- * Preconditioned Linear Solver modules.
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * This is the implementation file for the IDASPILS linear solver
+ * interface
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "ida_impl.h"
 #include "ida_spils_impl.h"
+#include <sundials/sundials_math.h>
 
 /* Private constants */
-
 #define ZERO   RCONST(0.0)
 #define PT25   RCONST(0.25)
 #define PT05   RCONST(0.05)
+#define PT9    RCONST(0.9)
 #define ONE    RCONST(1.0)
 
 /* Algorithmic constants */
-
 #define MAX_ITERS  3  /* max. number of attempts to recover in DQ J*v */
 
-/* Readability Replacements */
-
-#define lrw1      (IDA_mem->ida_lrw1)
-#define liw1      (IDA_mem->ida_liw1)
-#define tn        (IDA_mem->ida_tn)
-#define cj        (IDA_mem->ida_cj)
-#define res       (IDA_mem->ida_res)
-#define user_data (IDA_mem->ida_user_data)
-#define ewt       (IDA_mem->ida_ewt)
-#define lmem      (IDA_mem->ida_lmem)
-
-#define ils_type  (idaspils_mem->s_type)
-#define sqrtN     (idaspils_mem->s_sqrtN)
-#define epslin    (idaspils_mem->s_epslin)
-#define ytemp     (idaspils_mem->s_ytemp)
-#define yptemp    (idaspils_mem->s_yptemp)
-#define xx        (idaspils_mem->s_xx)
-#define ycur      (idaspils_mem->s_ycur)
-#define ypcur     (idaspils_mem->s_ypcur)
-#define rcur      (idaspils_mem->s_rcur)
-#define npe       (idaspils_mem->s_npe)
-#define nli       (idaspils_mem->s_nli)
-#define nps       (idaspils_mem->s_nps)
-#define ncfl      (idaspils_mem->s_ncfl)
-#define njtimes   (idaspils_mem->s_njtimes)
-#define nres      (idaspils_mem->s_nres)
-
-#define jtimesDQ  (idaspils_mem->s_jtimesDQ)
-#define jtimes    (idaspils_mem->s_jtimes)
-#define jdata     (idaspils_mem->s_jdata)
-
-#define last_flag (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * OPTIONAL INPUT and OUTPUT
- * -----------------------------------------------------------------
- */
-
-int IDASpilsSetGSType(void *ida_mem, int gstype)
+
+/*===============================================================
+  IDASPILS Exported functions -- Required
+===============================================================*/
+
+/*---------------------------------------------------------------
+  IDASpilsSetLinearSolver specifies the iterative linear solver
+  ---------------------------------------------------------------*/
+int IDASpilsSetLinearSolver(void *ida_mem, SUNLinearSolver LS)
 {
+  int retval;
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetGSType", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "IDASpilsSetLinearSolver", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
-  IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetGSType", MSGS_LMEM_NULL);
-    return(IDASPILS_LMEM_NULL);
+  if (LS == NULL) {
+    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPILS", 
+		    "IDASpilsSetLinearSolver", 
+                    "LS must be non-NULL");
+    return(IDASPILS_ILL_INPUT);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  IDA_mem = (IDAMem) ida_mem;
 
-  if (ils_type != SPILS_SPGMR) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetGSType", MSGS_BAD_LSTYPE);
+  /* Test if solver and vector are compatible with SPILS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_ITERATIVE) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", 
+                    "Non-iterative LS supplied to IDASpils interface");
     return(IDASPILS_ILL_INPUT);
   }
-
-  /* Check for legal gstype */
-  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetGSType", MSGS_BAD_GSTYPE);
+  if ( (IDA_mem->ida_tempv1->ops->nvdotprod == NULL) ||
+       (IDA_mem->ida_tempv1->ops->nvconst == NULL) ||
+       (IDA_mem->ida_tempv1->ops->nvscale == NULL) ||
+       (IDA_mem->ida_tempv1->ops->nvlinearsum == NULL) ) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_BAD_NVECTOR);
     return(IDASPILS_ILL_INPUT);
   }
 
-  idaspils_mem->s_gstype = gstype;
-
-  return(IDASPILS_SUCCESS);
-}
-
-int IDASpilsSetMaxRestarts(void *ida_mem, int maxrs)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
+  /* free any existing system solver attached to IDA */
+  if (IDA_mem->ida_lfree)  IDA_mem->ida_lfree(IDA_mem);
+
+  /* Set four main system linear solver function fields in IDA_mem */
+  IDA_mem->ida_linit  = idaSpilsInitialize;
+  IDA_mem->ida_lsetup = idaSpilsSetup;
+  IDA_mem->ida_lsolve = idaSpilsSolve;
+  IDA_mem->ida_lperf  = idaSpilsPerf;
+  IDA_mem->ida_lfree  = idaSpilsFree;
+  
+  /* Get memory for IDASpilsMemRec */
+  idaspils_mem = NULL;
+  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
+  if (idaspils_mem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
   }
-  IDA_mem = (IDAMem) ida_mem;
 
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_LMEM_NULL);
-    return(IDASPILS_LMEM_NULL);
+  /* set SUNLinearSolver pointer */
+  idaspils_mem->LS = LS;
+  
+  /* Set defaults for Jacobian-related fields */
+  idaspils_mem->jtimesDQ = SUNTRUE;
+  idaspils_mem->jtsetup  = NULL;
+  idaspils_mem->jtimes   = IDASpilsDQJtimes;
+  idaspils_mem->jdata    = IDA_mem;
+
+  /* Set defaults for preconditioner-related fields */
+  idaspils_mem->pset   = NULL;
+  idaspils_mem->psolve = NULL;
+  idaspils_mem->pfree  = NULL;
+  idaspils_mem->pdata  = IDA_mem->ida_user_data;
+
+  /* Set default values for the rest of the Spils parameters */
+  idaspils_mem->eplifac  = PT05;
+  idaspils_mem->dqincfac = ONE;
+
+  /* Initialize counters */
+  idaSpilsInitializeCounters(idaspils_mem);
+
+  /* Set default values for the rest of the SPILS parameters */
+  idaspils_mem->last_flag = IDASPILS_SUCCESS;
+
+  /* Attach default IDASpils interface routines to iterative LS */
+  retval = SUNLinSolSetATimes(LS, IDA_mem, IDASpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetATimes");
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_SUNLS_FAIL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (ils_type != SPILS_SPGMR) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_BAD_LSTYPE);
-    return(IDASPILS_ILL_INPUT);
+  retval = SUNLinSolSetPreconditioner(LS, IDA_mem, NULL, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_SUNLS_FAIL);
   }
 
-  /* Check for legal maxrs */
-  if (maxrs < 0) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxRestarts", MSGS_NEG_MAXRS);
-    return(IDASPILS_ILL_INPUT);
+  /* Allocate memory for ytemp, yptemp and x */
+  idaspils_mem->ytemp = N_VClone(IDA_mem->ida_tempv1);
+  if (idaspils_mem->ytemp == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_MEM_FAIL);
   }
 
-  idaspils_mem->s_maxrs = maxrs;
-
-  return(IDASPILS_SUCCESS);
-}
-
-int IDASpilsSetMaxl(void *ida_mem, int maxl)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetMaxl", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
+  idaspils_mem->yptemp = N_VClone(IDA_mem->ida_tempv1);
+  if (idaspils_mem->yptemp == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    N_VDestroy(idaspils_mem->ytemp);
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_MEM_FAIL);
   }
-  IDA_mem = (IDAMem) ida_mem;
 
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetMaxl", MSGS_LMEM_NULL);
-    return(IDASPILS_LMEM_NULL);
+  idaspils_mem->x = N_VClone(IDA_mem->ida_tempv1);
+  if (idaspils_mem->x == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    N_VDestroy(idaspils_mem->ytemp);
+    N_VDestroy(idaspils_mem->yptemp);
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_MEM_FAIL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
 
-  if (ils_type == SPILS_SPGMR) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetMaxl", MSGS_BAD_LSTYPE);
-    return(IDASPILS_ILL_INPUT);
-  }
+  /* Compute sqrtN from a dot product */
+  N_VConst(ONE, idaspils_mem->ytemp);
+  idaspils_mem->sqrtN = SUNRsqrt( N_VDotProd(idaspils_mem->ytemp, 
+                                             idaspils_mem->ytemp) );
 
-  idaspils_mem->s_maxl = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
+  /* Attach linear solver memory to integrator memory */
+  IDA_mem->ida_lmem = idaspils_mem;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*===============================================================
+  IDASPILS Exported functions -- Optional input/output
+  ===============================================================*/
+
+
+/*---------------------------------------------------------------*/
 int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetEpsLin", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsSetEpsLin", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetEpsLin", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsSetEpsLin", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  /* Check for legal maxrs */
+  /* Check for legal eplifac */
   if (eplifac < ZERO) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetEpsLin", MSGS_NEG_EPLIFAC);
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS",
+                    "IDASpilsSetEpsLin", MSGS_NEG_EPLIFAC);
     return(IDASPILS_ILL_INPUT);
   }
 
   if (eplifac == ZERO)
-    idaspils_mem->s_eplifac = PT05;
+    idaspils_mem->eplifac = PT05;
   else
-    idaspils_mem->s_eplifac = eplifac;
+    idaspils_mem->eplifac = eplifac;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetIncrementFactor", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsSetIncrementFactor", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetIncrementFactor", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsSetIncrementFactor", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
   /* Check for legal maxrs */
   if (dqincfac <= ZERO) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS", "IDASpilsSetIncrementFactor", MSGS_NEG_DQINCFAC);
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPILS",
+                    "IDASpilsSetIncrementFactor", MSGS_NEG_DQINCFAC);
     return(IDASPILS_ILL_INPUT);
   }
 
-  idaspils_mem->s_dqincfac = dqincfac;
+  idaspils_mem->dqincfac = dqincfac;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsSetPreconditioner(void *ida_mem,
-                              IDASpilsPrecSetupFn pset, IDASpilsPrecSolveFn psolve)
+                              IDASpilsPrecSetupFn psetup,
+                              IDASpilsPrecSolveFn psolve)
 {
+  int retval;
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
+  PSetupFn idaspils_psetup;
+  PSolveFn idaspils_psolve;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetPreconditioner", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsSetPreconditioner", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetPreconditioner", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsSetPreconditioner", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  idaspils_mem->s_pset = pset;
-  idaspils_mem->s_psolve = psolve;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  idaspils_mem->pset   = psetup;
+  idaspils_mem->psolve = psolve;
+
+  /* notify iterative linear solver to call IDASpils interface routines */
+  idaspils_psetup = (psetup == NULL) ? NULL : IDASpilsPSetup;
+  idaspils_psolve = (psolve == NULL) ? NULL : IDASpilsPSolve;
+  retval = SUNLinSolSetPreconditioner(idaspils_mem->LS, IDA_mem, 
+                                      idaspils_psetup, idaspils_psolve);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASPILS", 
+                    "IDASpilsSetPreconditioner", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    return(IDASPILS_SUNLS_FAIL);
+  }
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsSetJacTimesVecFn(void *ida_mem, IDASpilsJacTimesVecFn jtv)
+
+/*---------------------------------------------------------------*/
+int IDASpilsSetJacTimes(void *ida_mem,
+                        IDASpilsJacTimesSetupFn jtsetup,
+                        IDASpilsJacTimesVecFn jtimes)
 {
+  int retval;
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsSetJacTimesVecFn", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsSetJacTimes", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsSetJacTimes", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  if (jtv != NULL) {
-    jtimesDQ = FALSE;
-    jtimes = jtv;
+  /* store function pointers for user-supplied routines in IDASpils 
+     interface (NULL jtimes implies use of DQ default) */
+  if (jtimes != NULL) {
+    idaspils_mem->jtimesDQ = SUNFALSE;
+    idaspils_mem->jtimes   = jtimes;
   } else {
-    jtimesDQ = TRUE;
+    idaspils_mem->jtimesDQ = SUNTRUE;
+  }
+  idaspils_mem->jtsetup = jtsetup;
+
+  /* notify iterative linear solver to call IDASpils interface routine */
+  retval = SUNLinSolSetATimes(idaspils_mem->LS, IDA_mem, IDASpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASPILS", 
+                    "IDASpilsSetJacTimes", 
+                    "Error in calling SUNLinSolSetATimes");
+    return(IDASPILS_SUNLS_FAIL);
   }
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS)
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS,
+                         long int *leniwLS)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
-  int maxl;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetWorkSpace", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetWorkSpace", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetWorkSpace", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetWorkSpace", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  switch(ils_type) {
-  case SPILS_SPGMR:
-    maxl = idaspils_mem->s_maxl;
-    *lenrwLS = lrw1*(maxl + 6) + maxl*(maxl + 4) + 1;
-    *leniwLS = liw1*(maxl + 6);
-    break;
-  case SPILS_SPBCG:
-    *lenrwLS = lrw1 * 10;
-    *leniwLS = liw1 * 10;
-    break;
-  case SPILS_SPTFQMR:
-    *lenrwLS = lrw1*13;
-    *leniwLS = liw1*13;
-    break;
+  /* start with fixed sizes */
+  *lenrwLS = 4;
+  *leniwLS = 14;
+
+  /* add N_Vector sizes */
+  if (IDA_mem->ida_tempv1->ops->nvspace) {
+    N_VSpace(IDA_mem->ida_tempv1, &lrw1, &liw1);
+    *lenrwLS += 3*lrw1;
+    *leniwLS += 3*liw1;
+  }
+
+  /* add LS sizes */
+  if (idaspils_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(idaspils_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumPrecEvals", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumPrecEvals", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumPrecEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *npevals = npe;
+  *npevals = idaspils_mem->npe;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumPrecSolves", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumPrecSolves", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumPrecSolves", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *npsolves = nps;
+  *npsolves = idaspils_mem->nps;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumLinIters", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumLinIters", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumLinIters", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumLinIters", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *nliters = nli;
+  *nliters = idaspils_mem->nli;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumConvFails", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumConvFails", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumConvFails", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  *nlcfails = idaspils_mem->ncfl;
+
+  return(IDASPILS_SUCCESS);
+}
 
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumConvFails", MSGS_LMEM_NULL);
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetNumJTSetupEvals(void *ida_mem, long int *njtsetups)
+{
+  IDAMem IDA_mem;
+  IDASpilsMem idaspils_mem;
+
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumJTSetupEvals", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  IDA_mem = (IDAMem) ida_mem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumJTSetupEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *nlcfails = ncfl;
+  *njtsetups = idaspils_mem->njtsetup;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumJtimesEvals", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumJtimesEvals", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *njvevals = njtimes;
+  *njvevals = idaspils_mem->njtimes;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumResEvals(void *ida_mem, long int *nrevalsLS)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetNumResEvals", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumResEvals", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetNumResEvals", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetNumResEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *nrevalsLS = nres;
+  *nrevalsLS = idaspils_mem->nres;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetLastFlag(void *ida_mem, long int *flag)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", "IDASpilsGetLastFlag", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS",
+                    "IDASpilsGetLastFlag", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", "IDASpilsGetLastFlag", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS",
+                    "IDASpilsGetLastFlag", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *flag = last_flag;
+  *flag = idaspils_mem->last_flag;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 char *IDASpilsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -510,6 +627,9 @@ char *IDASpilsGetReturnFlagName(long int flag)
   case IDASPILS_PMEM_NULL:
     sprintf(name,"IDASPILS_PMEM_NULL");
     break;
+  case IDASPILS_SUNLS_FAIL:
+    sprintf(name,"IDASPILS_SUNLS_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -517,78 +637,157 @@ char *IDASpilsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * -----------------------------------------------------------------
- * IDASPILS private functions
- * -----------------------------------------------------------------
- */
 
-#define psolve   (idaspils_mem->s_psolve)
-#define pdata    (idaspils_mem->s_pdata)
-#define dqincfac (idaspils_mem->s_dqincfac)
+/*===============================================================
+  IDASPILS Private functions
+  ===============================================================*/
 
-/*
- * This routine generates the matrix-vector product z = Jv, where
- * J is the system Jacobian, by calling either the user provided
- * routine or the internal DQ routine.
- */
+/*---------------------------------------------------------------
+  IDASpilsATimes:
 
-int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z)
+  This routine generates the matrix-vector product z = Jv, where
+  J is the system Jacobian, by calling either the user provided
+  routine or the internal DQ routine.  The return value is 
+  the same as the value returned by jtimes -- 
+  0 if successful, nonzero otherwise.
+  ---------------------------------------------------------------*/
+int IDASpilsATimes(void *ida_mem, N_Vector v, N_Vector z)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   int jtflag;
 
+  /* Return immediately if ida_mem or ida_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+                    "IDASpilsATimes", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  jtflag = jtimes(tn, ycur, ypcur, rcur, v, z, cj, jdata, ytemp, yptemp);
-  njtimes++;
-
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+                    "IDASpilsATimes", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  jtflag = idaspils_mem->jtimes(IDA_mem->ida_tn,
+                                idaspils_mem->ycur,
+                                idaspils_mem->ypcur,
+                                idaspils_mem->rcur, v, z,
+                                IDA_mem->ida_cj,
+                                idaspils_mem->jdata,
+                                idaspils_mem->ytemp,
+                                idaspils_mem->yptemp);
+  idaspils_mem->njtimes++;
   return(jtflag);
 }
 
-/*
- * This routine interfaces between the generic Solve routine and
- * the user's psolve routine.  It passes to psolve all required state 
- * information from ida_mem.  Its return value is the same as that
- * returned by psolve.  Note that the generic solver guarantees
- * that IDASilsPSolve will not be called in the case psolve = NULL.
- */
 
-int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z, int lr)
+/*---------------------------------------------------------------
+  IDASpilsPSetup:
+
+  This routine interfaces between the generic iterative linear 
+  solvers and the user's psetup routine.  It passes to psetup all 
+  required state information from ida_mem.  Its return value 
+  is the same as that returned by psetup. Note that the generic
+  iterative linear solvers guarantee that IDASpilsPSetup will only
+  be called in the case that the user's psetup routine is non-NULL.
+  ---------------------------------------------------------------*/
+int IDASpilsPSetup(void *ida_mem)
 {
-  IDAMem IDA_mem;
+  int         retval;
+  IDAMem      IDA_mem;
   IDASpilsMem idaspils_mem;
-  int retval;
 
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "IDASpilsPSetup", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
-  idaspils_mem = (IDASpilsMem) lmem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+		    "IDASpilsPSetup", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  /* Call user pset routine to update preconditioner and possibly 
+     reset jcur (pass !jbad as update suggestion) */
+  retval = idaspils_mem->pset(IDA_mem->ida_tn, 
+                              idaspils_mem->ycur, 
+                              idaspils_mem->ypcur, 
+                              idaspils_mem->rcur, 
+                              IDA_mem->ida_cj, 
+                              idaspils_mem->pdata);
+  idaspils_mem->npe++;
+  return(retval);
+}
 
-  retval = psolve(tn, ycur, ypcur, rcur, r, z, cj, epslin, pdata, ytemp);
 
-  /* This call is counted in nps within the IDASp**Solve routine */
+/*---------------------------------------------------------------
+  IDASpilsPSolve:
+
+  This routine interfaces between the generic SUNLinSolSolve 
+  routine and the user's psolve routine.  It passes to psolve all 
+  required state information from ida_mem.  Its return value is
+  the same as that returned by psolve.  Note that the generic 
+  SUNLinSol solver guarantees that IDASilsPSolve will not be 
+  called in the case in which preconditioning is not done. This 
+  is the only case in which the user's psolve routine is allowed 
+  to be NULL.
+  ---------------------------------------------------------------*/
+int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z,
+                   realtype tol, int lr)
+{
+  IDAMem IDA_mem;
+  IDASpilsMem idaspils_mem;
+  int retval;
 
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "IDASpilsPSolve", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  IDA_mem = (IDAMem) ida_mem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+		    "IDASpilsPSolve", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  retval = idaspils_mem->psolve(IDA_mem->ida_tn,
+                                idaspils_mem->ycur,
+                                idaspils_mem->ypcur,
+                                idaspils_mem->rcur, r, z,
+                                IDA_mem->ida_cj, tol,
+                                idaspils_mem->pdata);
+  idaspils_mem->nps++;
   return(retval);
-
 }
 
-/*
- * This routine generates the matrix-vector product z = Jv, where
- * J is the system Jacobian, by using a difference quotient approximation.
- * The approximation is 
- *      Jv = [F(t,y1,yp1) - F(t,y,yp)]/sigma,  where
- *        y1 = y + sigma*v,  yp1 = yp + cj*sigma*v,
- *        sigma = sqrt(Neq)*dqincfac.
- * The return value from the call to res is saved in order to set the
- * return flag from IDASp**Solve.
- */
-
-int IDASpilsDQJtimes(realtype tt,
-                     N_Vector yy, N_Vector yp, N_Vector rr,
-                     N_Vector v, N_Vector Jv, 
-                     realtype c_j, void *data, 
-                     N_Vector work1, N_Vector work2)
+
+/*---------------------------------------------------------------
+  IDASpilsDQJtimes:
+
+  This routine generates a difference quotient approximation to 
+  the matrix-vector product z = Jv, where J is the system 
+  Jacobian. The approximation is 
+       Jv = [F(t,y1,yp1) - F(t,y,yp)]/sigma,  
+  where
+       y1 = y + sigma*v,  yp1 = yp + cj*sigma*v,
+       sigma = sqrt(Neq)*dqincfac.
+  The return value from the call to res is saved in order to set 
+  the return flag from IDASpilsSolve.
+  ---------------------------------------------------------------*/
+int IDASpilsDQJtimes(realtype tt, N_Vector yy, N_Vector yp,
+                     N_Vector rr, N_Vector v, N_Vector Jv, 
+                     realtype c_j, void *ida_mem, N_Vector work1, 
+                     N_Vector work2)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
@@ -596,21 +795,22 @@ int IDASpilsDQJtimes(realtype tt,
   realtype sig=ZERO, siginv;
   int iter, retval;
 
-  /* data is ida_mem */
-  IDA_mem = (IDAMem) data;
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  switch(ils_type) {
-  case SPILS_SPGMR:
-    sig = sqrtN*dqincfac;
-    break;
-  case SPILS_SPBCG:
-    sig = dqincfac/N_VWrmsNorm(v, ewt);
-    break;
-  case SPILS_SPTFQMR:
-    sig = dqincfac/N_VWrmsNorm(v, ewt);
-    break;
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "IDASpilsDQJtimes", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
   }
+  IDA_mem = (IDAMem) ida_mem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+		    "IDASpilsDQJtimes", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  sig = idaspils_mem->sqrtN * idaspils_mem->dqincfac;  /* GMRES */
+  /*sig = idaspils_mem->dqincfac / N_VWrmsNorm(v, IDA_mem->ida_ewt);*/  /* BiCGStab/TFQMR */ 
 
   /* Rename work1 and work2 for readibility */
   y_tmp  = work1;
@@ -623,8 +823,8 @@ int IDASpilsDQJtimes(realtype tt,
     N_VLinearSum(c_j*sig, v, ONE, yp, yp_tmp);
     
     /* Call res for Jv = F(t, y_tmp, yp_tmp), and return if it failed. */
-    retval = res(tt, y_tmp, yp_tmp, Jv, user_data); 
-    nres++;
+    retval = IDA_mem->ida_res(tt, y_tmp, yp_tmp, Jv, IDA_mem->ida_user_data); 
+    idaspils_mem->nres++;
     if (retval == 0) break;
     if (retval < 0)  return(-1);
 
@@ -638,17 +838,320 @@ int IDASpilsDQJtimes(realtype tt,
   N_VLinearSum(siginv, Jv, -siginv, rr, Jv);
 
   return(0);
+}
+
+
+/*---------------------------------------------------------------
+ idaSpilsInitialize performs remaining initializations specific
+ to the iterative linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int idaSpilsInitialize(IDAMem IDA_mem)
+{
+  IDASpilsMem idaspils_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "idaSpilsInitialize", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+		    "idaSpilsInitialize", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+  
+  idaSpilsInitializeCounters(idaspils_mem);
+
+  /* Set Jacobian-related fields, based on jtimesDQ */
+  if (idaspils_mem->jtimesDQ) {
+    idaspils_mem->jtsetup = NULL;
+    idaspils_mem->jtimes  = IDASpilsDQJtimes;
+    idaspils_mem->jdata   = IDA_mem;
+  } else {
+    idaspils_mem->jdata   = IDA_mem->ida_user_data;
+  }
+
+  /* if psetup is not present, then idaSpilsSetup does not need to be 
+     called, so set the lsetup function to NULL */
+  if (idaspils_mem->pset == NULL)  IDA_mem->ida_lsetup = NULL;
+
+  /* Call LS initialize routine */
+  idaspils_mem->last_flag = SUNLinSolInitialize(idaspils_mem->LS);
+  return(idaspils_mem->last_flag);
+}
+
+
+/*---------------------------------------------------------------
+ idaSpilsSetup calls the LS 'setup' routine.
+---------------------------------------------------------------*/
+int idaSpilsSetup(IDAMem IDA_mem, N_Vector y, N_Vector yp, N_Vector r, 
+                  N_Vector vt1, N_Vector vt2, N_Vector vt3)
+{
+  int  retval;
+  IDASpilsMem idaspils_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "idaSpilsSetup", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+		    "idaSpilsSetup", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  /* Set IDASpils N_Vector pointers to inputs */
+  idaspils_mem->ycur  = y;
+  idaspils_mem->ypcur = yp;
+  idaspils_mem->rcur  = r;
+
+  /* Call LS setup routine -- the LS will call IDASpilsPSetup 
+     if applicable */
+  retval = SUNLinSolSetup(idaspils_mem->LS, NULL);
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+ idaSpilsSolve: interfaces between IDA and the generic 
+ SUNLinearSolver object LS, by setting the appropriate tolerance 
+ and scaling vectors, calling the solver, and accumulating 
+ statistics from the solve for use/reporting by IDA.
+---------------------------------------------------------------*/
+int idaSpilsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                  N_Vector ycur, N_Vector ypcur, N_Vector rescur)
+{
+  IDASpilsMem idaspils_mem;
+  int nli_inc, retval;
+  
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "idaSpilsSolve", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+		    "idaSpilsSolve", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  /* Set convergence test constant epslin, in terms of the
+     Newton convergence test constant epsNewt and safety factors. The factor
+     sqrt(Neq) assures that the convergence test is applied to the WRMS norm 
+     of the residual vector, rather than the weighted L2 norm. */
+  idaspils_mem->epslin = idaspils_mem->sqrtN *
+    idaspils_mem->eplifac * IDA_mem->ida_epsNewt;
+
+  /* Set vectors ycur, ypcur and rcur for use by the Atimes and 
+     Psolve interface routines */
+  idaspils_mem->ycur  = ycur;
+  idaspils_mem->ypcur = ypcur;
+  idaspils_mem->rcur  = rescur;
+
+  /* Set initial guess x = 0 to LS */  
+  N_VConst(ZERO, idaspils_mem->x);
+
+  /* Set scaling vectors for LS to use */
+  retval = SUNLinSolSetScalingVectors(idaspils_mem->LS, weight, weight);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASPILS", "idaSpilsSolve", 
+                    "Error in calling SUNLinSolSetScalingVectors");
+    return(IDASPILS_SUNLS_FAIL);
+  }
+
+  /* If a user-provided jtsetup routine is supplied, call that here */
+  if (idaspils_mem->jtsetup) {
+    retval = idaspils_mem->jtsetup(IDA_mem->ida_tn, ycur, ypcur, rescur,
+                                   IDA_mem->ida_cj, idaspils_mem->jdata);
+    idaspils_mem->njtsetup++;
+    if (retval != 0) {
+      IDAProcessError(IDA_mem, retval, "IDASPILS", 
+                      "idaSpilsSolve", MSGS_JTSETUP_FAILED);
+      return(retval);
+    }
+  }
+  
+  /* Call solver */
+  retval = SUNLinSolSolve(idaspils_mem->LS, NULL, idaspils_mem->x,
+                          b, idaspils_mem->epslin);
+
+  /* Retrieve solver statistics */
+  nli_inc = SUNLinSolNumIters(idaspils_mem->LS);
+  
+  /* Copy x (or preconditioned residual vector if no iterations required) to b */
+  if (nli_inc == 0) N_VScale(ONE, SUNLinSolResid(idaspils_mem->LS), b);
+  else N_VScale(ONE, idaspils_mem->x, b);
+
+  /* Increment counters nli and ncfl */
+  idaspils_mem->nli += nli_inc;
+  if (retval != SUNLS_SUCCESS) idaspils_mem->ncfl++;
+
+  /* Interpret solver return value  */
+  idaspils_mem->last_flag = retval;
+
+  switch(retval) {
+
+  case SUNLS_SUCCESS:
+    return(0);
+    break;
+  case SUNLS_RES_REDUCED:
+  case SUNLS_CONV_FAIL:
+  case SUNLS_PSOLVE_FAIL_REC:
+  case SUNLS_PACKAGE_FAIL_REC:
+  case SUNLS_QRFACT_FAIL:
+  case SUNLS_LUFACT_FAIL:
+    return(1);
+    break;
+  case SUNLS_MEM_NULL:
+  case SUNLS_ILL_INPUT:
+  case SUNLS_MEM_FAIL:
+  case SUNLS_GS_FAIL:
+  case SUNLS_QRSOL_FAIL:
+    return(-1);
+    break;
+  case SUNLS_PACKAGE_FAIL_UNREC:
+    IDAProcessError(IDA_mem, SUNLS_PACKAGE_FAIL_UNREC, "IDASPILS", 
+                    "idaSpilsSolve",
+                    "Failure in SUNLinSol external package");
+    return(-1);
+    break;
+  case SUNLS_PSOLVE_FAIL_UNREC:
+    IDAProcessError(IDA_mem, SUNLS_PSOLVE_FAIL_UNREC, "IDASPILS", 
+                    "idaSpilsSolve", MSGS_PSOLVE_FAILED);
+    return(-1);
+    break;
+  }
+  
+  return(0); 
+}
+
+
+/*---------------------------------------------------------------
+ idaSpilsPerf: accumulates performance statistics information 
+ for IDA
+---------------------------------------------------------------*/
+int idaSpilsPerf(IDAMem IDA_mem, int perftask)
+{
+  IDASpilsMem idaspils_mem;
+  realtype rcfn, rcfl;
+  long int nstd, nnid;
+  booleantype lcfn, lcfl;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPILS", 
+		    "idaSpilsPerf", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASPILS", 
+		    "idaSpilsPerf", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  /* when perftask == 0, store current performance statistics */
+  if (perftask == 0) {
+    idaspils_mem->nst0  = IDA_mem->ida_nst;
+    idaspils_mem->nni0  = IDA_mem->ida_nni;
+    idaspils_mem->ncfn0 = IDA_mem->ida_ncfn;
+    idaspils_mem->ncfl0 = idaspils_mem->ncfl;  
+    idaspils_mem->nwarn = 0;
+    return(0);
+  }
+
+  /* Compute statistics since last call
+
+     Note: the performance monitor that checked whether the average 
+       number of linear iterations was too close to maxl has been 
+       removed, since the 'maxl' value is no longer owned by the 
+       IDASpils interface.
+   */
+  nstd = IDA_mem->ida_nst - idaspils_mem->nst0;
+  nnid = IDA_mem->ida_nni - idaspils_mem->nni0;
+  if (nstd == 0 || nnid == 0) return(0);
+  
+  rcfn = (realtype) ( (IDA_mem->ida_ncfn - idaspils_mem->ncfn0) /
+                      ((realtype) nstd) );
+  rcfl = (realtype) ( (idaspils_mem->ncfl - idaspils_mem->ncfl0) /
+                      ((realtype) nnid) );
+  lcfn = (rcfn > PT9);
+  lcfl = (rcfl > PT9);
+  if (!(lcfn || lcfl)) return(0);
+  idaspils_mem->nwarn++;
+  if (idaspils_mem->nwarn > 10) return(1);
+  if (lcfn) 
+    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPILS", "idaSpilsPerf",
+                    MSGS_CFN_WARN, IDA_mem->ida_tn, rcfn);
+  if (lcfl) 
+    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPILS", "idaSpilsPerf",
+                    MSGS_CFL_WARN, IDA_mem->ida_tn, rcfl);
+  return(0);
+}
+
+
+/*---------------------------------------------------------------
+ idaSpilsFree frees memory associates with the IDASpils system
+ solver interface.
+---------------------------------------------------------------*/
+int idaSpilsFree(IDAMem IDA_mem)
+{
+  IDASpilsMem idaspils_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL)  return (IDASPILS_SUCCESS);
+  if (IDA_mem->ida_lmem == NULL)  return(IDASPILS_SUCCESS);
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
+  /* Free N_Vector memory */
+  if (idaspils_mem->ytemp) {
+    N_VDestroy(idaspils_mem->ytemp);
+    idaspils_mem->ytemp = NULL;
+  }
+  if (idaspils_mem->yptemp) {
+    N_VDestroy(idaspils_mem->yptemp);
+    idaspils_mem->yptemp = NULL;
+  }
+  if (idaspils_mem->x) {
+    N_VDestroy(idaspils_mem->x);
+    idaspils_mem->x = NULL;
+  }
+
+  /* Nullify other N_Vector pointers */
+  idaspils_mem->ycur  = NULL;
+  idaspils_mem->ypcur = NULL;
+  idaspils_mem->rcur  = NULL;
+
+  /* Free preconditioner memory (if applicable) */
+  if (idaspils_mem->pfree)  idaspils_mem->pfree(IDA_mem);
+  
+  /* free IDASpils interface structure */
+  free(IDA_mem->ida_lmem);
+  
+  return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------
+ idaSpilsInitializeCounters resets all counters from an 
+ IDASpilsMem structure.
+---------------------------------------------------------------*/
 int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem)
 {
-  idaspils_mem->s_npe     = 0;
-  idaspils_mem->s_nli     = 0;
-  idaspils_mem->s_nps     = 0;
-  idaspils_mem->s_ncfl    = 0;
-  idaspils_mem->s_njtimes = 0;
-  idaspils_mem->s_nres    = 0;
+  idaspils_mem->npe      = 0;
+  idaspils_mem->nli      = 0;
+  idaspils_mem->nps      = 0;
+  idaspils_mem->ncfl     = 0;
+  idaspils_mem->nres     = 0;
+  idaspils_mem->njtsetup = 0;
+  idaspils_mem->njtimes  = 0;
 
   return(0);
 }
diff --git a/src/ida/ida_spils_impl.h b/src/ida/ida_spils_impl.h
index 4836d98..1a7a254 100644
--- a/src/ida/ida_spils_impl.h
+++ b/src/ida/ida_spils_impl.h
@@ -1,24 +1,24 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4920 $
- * $Date: 2016-09-19 14:34:35 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the common header file (private version) for the Scaled
- * Preconditioned Iterative Linear Solver modules.
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Implementation header file for the Scaled Preconditioned 
+ * Iterative Linear Solver interface.
+ *-----------------------------------------------------------------*/
 
 #ifndef _IDASPILS_IMPL_H
 #define _IDASPILS_IMPL_H
@@ -30,120 +30,106 @@
 extern "C" {
 #endif
 
-/* Types of iterative linear solvers */
-
-#define SPILS_SPGMR   1
-#define SPILS_SPBCG   2
-#define SPILS_SPTFQMR 3
-
-/* Constants */
-
-#define IDA_SPILS_MAXL    5
-#define IDA_SPILS_MAXRS   5
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASpilsMemRec, IDASpilsMem                             
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Types : IDASpilsMemRec, IDASpilsMem                             
+  -----------------------------------------------------------------*/
 
 typedef struct IDASpilsMemRec {
 
-  int s_type;          /* type of scaled preconditioned iterative LS   */
-
-  int  s_gstype;       /* type of Gram-Schmidt orthogonalization       */
-  realtype s_sqrtN;    /* sqrt(N)                                      */
-  int  s_maxl;         /* maxl = maximum dimension of the Krylov space */
-  int  s_maxrs;        /* maxrs = max. number of GMRES restarts        */
-  realtype s_eplifac;  /* eplifac = linear convergence factor          */
-  realtype s_dqincfac; /* dqincfac = optional increment factor in Jv   */
-  realtype s_epslin;   /* SpgrmSolve tolerance parameter               */
-
-  long int s_npe;      /* npe = total number of precond calls          */   
-  long int s_nli;      /* nli = total number of linear iterations      */
-  long int s_nps;      /* nps = total number of psolve calls           */
-  long int s_ncfl;     /* ncfl = total number of convergence failures  */
-  long int s_nres;     /* nres = total number of calls to res          */
-  long int s_njtimes;  /* njtimes = total number of calls to jtimes    */
-
-  long int s_nst0;     /* nst0 = saved nst (for performance monitor)   */   
-  long int s_nni0;     /* nni0 = saved nni (for performance monitor)   */   
-  long int s_nli0;     /* nli0 = saved nli (for performance monitor)   */   
-  long int s_ncfn0;    /* ncfn0 = saved ncfn (for performance monitor) */   
-  long int s_ncfl0;    /* ncfl0 = saved ncfl (for performance monitor) */   
-  long int s_nwarn;    /* nwarn = no. of warnings (for perf. monitor)  */   
-
-  N_Vector s_ytemp;    /* temp vector used by IDAAtimesDQ              */ 
-  N_Vector s_yptemp;   /* temp vector used by IDAAtimesDQ              */ 
-  N_Vector s_xx;       /* temp vector used by the solve function       */
-  N_Vector s_ycur;     /* current y vector in Newton iteration         */
-  N_Vector s_ypcur;    /* current yp vector in Newton iteration        */
-  N_Vector s_rcur;     /* rcur = F(tn, ycur, ypcur)                    */
-
-  void *s_spils_mem;   /* memory used by the generic solver            */
-
-  long int s_last_flag; /* last error return flag                      */
+  realtype sqrtN;     /* sqrt(N)                                      */
+  realtype eplifac;   /* eplifac = linear convergence factor          */
+  realtype dqincfac;  /* dqincfac = optional increment factor in Jv   */
+  realtype epslin;    /* Solver tolerance parameter                   */
+
+  long int npe;       /* npe = total number of precond calls          */   
+  long int nli;       /* nli = total number of linear iterations      */
+  long int nps;       /* nps = total number of psolve calls           */
+  long int ncfl;      /* ncfl = total number of convergence failures  */
+  long int nres;      /* nres = total number of calls to res          */
+  long int njtsetup;  /* njtsetup = total number of calls to jtsetup  */
+  long int njtimes;   /* njtimes = total number of calls to jtimes    */
+
+  long int nst0;      /* nst0 = saved nst (for performance monitor)   */   
+  long int nni0;      /* nni0 = saved nni (for performance monitor)   */   
+  long int ncfn0;     /* ncfn0 = saved ncfn (for performance monitor) */   
+  long int ncfl0;     /* ncfl0 = saved ncfl (for performance monitor) */   
+  long int nwarn;     /* nwarn = no. of warnings (for perf. monitor)  */   
+
+  N_Vector ytemp;     /* temp vector used by IDAAtimesDQ              */ 
+  N_Vector yptemp;    /* temp vector used by IDAAtimesDQ              */ 
+  N_Vector x;         /* temp vector used by the solve function       */
+  N_Vector ycur;      /* current y vector in Newton iteration         */
+  N_Vector ypcur;     /* current yp vector in Newton iteration        */
+  N_Vector rcur;      /* rcur = F(tn, ycur, ypcur)                    */
+
+  SUNLinearSolver LS; /* generic iterative linear solver object       */
+  
+  long int last_flag; /* last error return flag                       */
 
   /* Preconditioner computation
-   * (a) user-provided:
-   *     - pdata == user_data
-   *     - pfree == NULL (the user dealocates memory for f_data)
-   * (b) internal preconditioner module
-   *     - pdata == ida_mem
-   *     - pfree == set by the prec. module and called in IDASpilsFree
-   */
-
-  IDASpilsPrecSetupFn s_pset;
-  IDASpilsPrecSolveFn s_psolve;
-  int (*s_pfree)(IDAMem IDA_mem);
-  void *s_pdata;
+     (a) user-provided:
+         - pdata == user_data
+         - pfree == NULL (the user dealocates memory)
+     (b) internal preconditioner module
+         - pdata == ida_mem
+         - pfree == set by the prec. module and called in idaSpilsFree */
+  IDASpilsPrecSetupFn pset;
+  IDASpilsPrecSolveFn psolve;
+  int (*pfree)(IDAMem IDA_mem);
+  void *pdata;
   
   /* Jacobian times vector compuation
-   * (a) jtimes function provided by the user:
-   *     - jdata == user_data
-   *     - jtimesDQ == FALSE
-   * (b) internal jtimes
-   *     - jdata == ida_mem
-   *     - jtimesDQ == TRUE
-   */
-
-  booleantype s_jtimesDQ;
-  IDASpilsJacTimesVecFn s_jtimes;
-  void *s_jdata;
+     (a) jtimes function provided by the user:
+         - jdata == user_data
+         - jtimesDQ == SUNFALSE
+     (b) internal jtimes
+         - jdata == ida_mem
+         - jtimesDQ == SUNTRUE */
+  booleantype jtimesDQ;
+  IDASpilsJacTimesSetupFn jtsetup;
+  IDASpilsJacTimesVecFn jtimes;
+  void *jdata;
 
 } *IDASpilsMem;
 
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
 
-/* Atimes and PSolve routines called by generic solver */
-
-int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z);
-
-int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z, int lr);
+/* Interface routines called by system SUNLinearSolver */
+int IDASpilsATimes(void *ida_mem, N_Vector v, N_Vector z);
+int IDASpilsPSetup(void *ida_mem);
+int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z,
+                   realtype tol, int lr);
 
 /* Difference quotient approximation for Jac times vector */
-
-int IDASpilsDQJtimes(realtype tt,
-                     N_Vector yy, N_Vector yp, N_Vector rr,
-                     N_Vector v, N_Vector Jv, 
+int IDASpilsDQJtimes(realtype tt, N_Vector yy, N_Vector yp,
+                     N_Vector rr, N_Vector v, N_Vector Jv, 
                      realtype c_j, void *data, 
                      N_Vector work1, N_Vector work2);
 
-/* Auxilliary functions */
+/* Generic linit/lsetup/lsolve/lfree interface routines for IDA to call */
+int idaSpilsInitialize(IDAMem IDA_mem);
 
-int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem);
+int idaSpilsSetup(IDAMem IDA_mem, N_Vector y, N_Vector yp, N_Vector r, 
+                  N_Vector vt1, N_Vector vt2, N_Vector vt3); 
+
+int idaSpilsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                  N_Vector ycur, N_Vector ypcur, N_Vector rescur);
 
+int idaSpilsPerf(IDAMem IDA_mem, int perftask);
 
-/*
- * -----------------------------------------------------------------
- * Error and Warning Messages
- * -----------------------------------------------------------------
- */
+int idaSpilsFree(IDAMem IDA_mem);
+
+  
+/* Auxilliary functions */
+int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem);
+
+  
+/*---------------------------------------------------------------
+  Error and Warning Messages
+  ---------------------------------------------------------------*/
 
 #if defined(SUNDIALS_EXTENDED_PRECISION)
 
@@ -177,18 +163,17 @@ int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem);
 
 #define MSGS_PSET_FAILED "The preconditioner setup routine failed in an unrecoverable manner."
 #define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner."
+#define MSGS_JTSETUP_FAILED "The Jacobian x vector setup routine failed in an unrecoverable manner."
 #define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
 
 /* Warning Messages */
 
 #define MSGS_WARN  "Warning: " MSGS_TIME "poor iterative algorithm performance. "
 
-#define MSGS_AVD_WARN  MSGS_WARN "Average number of linear iterations is " MSGS_FRMT
 #define MSGS_CFN_WARN  MSGS_WARN "Nonlinear convergence failure rate is " MSGS_FRMT
 #define MSGS_CFL_WARN  MSGS_WARN "Linear convergence failure rate is " MSGS_FRMT
 
 
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/ida/ida_sptfqmr.c b/src/ida/ida_sptfqmr.c
deleted file mode 100644
index 284bbbf..0000000
--- a/src/ida/ida_sptfqmr.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4829 $
- * $Date: 2016-07-27 16:01:15 -0700 (Wed, 27 Jul 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDA scaled preconditioned
- * TFQMR linear solver module, IDASPTFQMR.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <ida/ida_sptfqmr.h>
-#include "ida_spils_impl.h"
-#include "ida_impl.h"
-
-#include <sundials/sundials_sptfqmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-#define PT9  RCONST(0.9)
-#define PT05 RCONST(0.05)
-
-/* IDASPTFQMR linit, lsetup, lsolve, lperf, and lfree routines */
-
-static int IDASptfqmrInit(IDAMem IDA_mem);
-
-static int IDASptfqmrSetup(IDAMem IDA_mem, 
-			   N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-			   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int IDASptfqmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-			   N_Vector yy_now, N_Vector yp_now, N_Vector rr_now);
-
-static int IDASptfqmrPerf(IDAMem IDA_mem, int perftask);
-
-static int IDASptfqmrFree(IDAMem IDA_mem);
-
-/* Readability Replacements */
-
-#define nst          (IDA_mem->ida_nst)
-#define tn           (IDA_mem->ida_tn)
-#define cj           (IDA_mem->ida_cj)
-#define epsNewt      (IDA_mem->ida_epsNewt)
-#define res          (IDA_mem->ida_res)
-#define user_data    (IDA_mem->ida_user_data)
-#define ewt          (IDA_mem->ida_ewt)
-#define errfp        (IDA_mem->ida_errfp)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define nni          (IDA_mem->ida_nni)
-#define ncfn         (IDA_mem->ida_ncfn)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define sqrtN       (idaspils_mem->s_sqrtN)
-#define epslin      (idaspils_mem->s_epslin)
-#define ytemp       (idaspils_mem->s_ytemp)
-#define yptemp      (idaspils_mem->s_yptemp)
-#define xx          (idaspils_mem->s_xx)
-#define ycur        (idaspils_mem->s_ycur)
-#define ypcur       (idaspils_mem->s_ypcur)
-#define rcur        (idaspils_mem->s_rcur)
-#define npe         (idaspils_mem->s_npe)
-#define nli         (idaspils_mem->s_nli)
-#define nps         (idaspils_mem->s_nps)
-#define ncfl        (idaspils_mem->s_ncfl)
-#define nst0        (idaspils_mem->s_nst0)
-#define nni0        (idaspils_mem->s_nni0)
-#define nli0        (idaspils_mem->s_nli0)
-#define ncfn0       (idaspils_mem->s_ncfn0)
-#define ncfl0       (idaspils_mem->s_ncfl0)
-#define nwarn       (idaspils_mem->s_nwarn)
-#define njtimes     (idaspils_mem->s_njtimes)
-#define nres        (idaspils_mem->s_nres)
-#define spils_mem   (idaspils_mem->s_spils_mem)
-
-#define jtimesDQ    (idaspils_mem->s_jtimesDQ)
-#define jtimes      (idaspils_mem->s_jtimes)
-#define jdata       (idaspils_mem->s_jdata)
-
-#define last_flag   (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmr
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDASPTFQMR linear solver module.
- *
- * IDASptfqmr first calls the existing lfree routine if this is not NULL.
- * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASptfqmrInit, IDASptfqmrSetup,
- * IDASptfqmrSolve, IDASptfqmrPerf, and IDASptfqmrFree, respectively.
- * It allocates memory for a structure of type IDASpilsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem). It then sets various fields
- * in the IDASpilsMemRec structure. Finally, IDASptfqmr allocates 
- * memory for ytemp, yptemp, and xx, and calls SptfqmrMalloc to 
- * allocate memory for the Sptfqmr solver.
- *
- * The return value of IDASptfqmr is:
- *   IDASPILS_SUCCESS   =  0 if successful
- *   IDASPILS_MEM_FAIL  = -1 if IDA_mem is NULL or a memory
- *                             allocation failed
- *   IDASPILS_ILL_INPUT = -2 if a required vector operation is not
- *                             implemented.
- * -----------------------------------------------------------------
- */
-
-int IDASptfqmr(void *ida_mem, int maxl)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int maxl1;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPTFQMR", "IDASptfqmr", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPTFQMR", "IDASptfqmr", MSGS_BAD_NVECTOR);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem */
-  linit  = IDASptfqmrInit;
-  lsetup = IDASptfqmrSetup;
-  lsolve = IDASptfqmrSolve;
-  lperf  = IDASptfqmrPerf;
-  lfree  = IDASptfqmrFree;
-
-  /* Get memory for IDASpilsMemRec */
-  idaspils_mem = NULL;
-  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
-  if (idaspils_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  idaspils_mem->s_type = SPILS_SPTFQMR;
-
-  /* Set SPTFQMR parameters that were passed in call sequence */
-  maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
-  idaspils_mem->s_maxl = maxl1;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  jdata    = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  idaspils_mem->s_pset   = NULL;
-  idaspils_mem->s_psolve = NULL;
-  idaspils_mem->s_pfree  = NULL;
-  idaspils_mem->s_pdata  = IDA_mem->ida_user_data;
-
-  /* Set default values for the rest of the Sptfqmr parameters */
-  idaspils_mem->s_eplifac   = PT05;
-  idaspils_mem->s_dqincfac  = ONE;
-
-  idaspils_mem->s_last_flag = IDASPILS_SUCCESS;
-
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to FALSE */
-  setupNonNull = FALSE;
-
-  /* Allocate memory for ytemp, yptemp, and xx */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  yptemp = N_VClone(vec_tmpl);
-  if (yptemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  xx = N_VClone(vec_tmpl);
-  if (xx == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */
-  sptfqmr_mem = NULL;
-  sptfqmr_mem = SptfqmrMalloc(maxl1, vec_tmpl);
-  if (sptfqmr_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    N_VDestroy(xx);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Attach SPTFQMR memory to spils memory structure */
-  spils_mem = (void *)sptfqmr_mem;
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idaspils_mem;
-
-  return(IDASPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASPTFQMR interface routines
- * -----------------------------------------------------------------
- */
-
-/* Additional readability Replacements */
-
-#define maxl     (idaspils_mem->s_maxl)
-#define eplifac  (idaspils_mem->s_eplifac)
-#define psolve   (idaspils_mem->s_psolve)
-#define pset     (idaspils_mem->s_pset)
-#define pdata    (idaspils_mem->s_pdata)
-
-static int IDASptfqmrInit(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to TRUE iff there is preconditioning with setup */
-  setupNonNull = (psolve != NULL) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = IDASpilsDQJtimes;
-    jdata = IDA_mem;
-  } else {
-    jdata = user_data;
-  }
-
-  /*  Set maxl in the SPTFQMR memory in case it was changed by the user */
-  sptfqmr_mem->l_max  = maxl;
-
-  last_flag = IDASPILS_SUCCESS;
-
-  return(0);
-}
-
-static int IDASptfqmrSetup(IDAMem IDA_mem, 
-			   N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-			   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  int retval;
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Call user setup routine pset and update counter npe */
-  retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata,
-                tmp1, tmp2, tmp3);
-  npe++;
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, SPTFQMR_PSET_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPTFQMR_PSET_FAIL_UNREC;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = SPTFQMR_PSET_FAIL_REC;
-    return(+1);
-  }
-
-  last_flag = SPTFQMR_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmrSolve
- * -----------------------------------------------------------------
- * Note: The x-scaling and b-scaling arrays are both equal to weight.
- *
- * We set the initial guess, x = 0, then call SptfqmrSolve.
- * We copy the solution x into b, and update the counters nli, nps,
- * and ncfl. If SptfqmrSolve returned nli_inc = 0 (hence x = 0), we
- * take the SPTFQMR vtemp vector (= P_inverse F) as the correction
- * vector instead. Finally, we set the return value according to the
- * success of SptfqmrSolve.
- * -----------------------------------------------------------------
- */
-
-static int IDASptfqmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-			   N_Vector yy_now, N_Vector yp_now, N_Vector rr_now)
-{
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int pretype, nli_inc, nps_inc, retval;
-  realtype res_norm;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  sptfqmr_mem = (SptfqmrMem)spils_mem;
-
-  /* Set SptfqmrSolve convergence test constant epslin, in terms of the
-     Newton convergence test constant epsNewt and safety factors. The factor
-     sqrt(Neq) assures that the TFQMR convergence test is applied to the
-     WRMS norm of the residual vector, rather than the weighted L2 norm. */
-  epslin = sqrtN*eplifac*epsNewt;
-
-  /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */
-  ycur = yy_now;
-  ypcur = yp_now;
-  rcur = rr_now;
-
-  /* Set SptfqmrSolve inputs pretype and initial guess xx = 0 */  
-  pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT;
-  N_VConst(ZERO, xx);
-  
-  /* Call SptfqmrSolve and copy xx to bb */
-  retval = SptfqmrSolve(sptfqmr_mem, IDA_mem, xx, bb, pretype, epslin,
-                      IDA_mem, weight, weight, IDASpilsAtimes,
-                      IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  if (nli_inc == 0) N_VScale(ONE, SPTFQMR_VTEMP(sptfqmr_mem), bb);
-  else N_VScale(ONE, xx, bb);
-  
-  /* Increment counters nli, nps, and return if successful */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPTFQMR_SUCCESS) ncfl++;
-
-    /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPTFQMR_SUCCESS:
-    return(0);
-    break;
-  case SPTFQMR_RES_REDUCED:
-    return(1);
-    break;
-  case SPTFQMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPTFQMR_ATIMES_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmrPerf
- * -----------------------------------------------------------------
- * This routine handles performance monitoring specific to the
- * IDASPTFQMR linear solver. When perftask = 0, it saves values of
- * various counters. When perftask = 1, it examines difference
- * quotients in these counters, and depending on their values, it
- * prints up to three warning messages. Messages are printed up to
- * a maximum of 10 times.
- * -----------------------------------------------------------------
- */
-
-static int IDASptfqmrPerf(IDAMem IDA_mem, int perftask)
-{
-  IDASpilsMem idaspils_mem;
-  realtype avdim, rcfn, rcfl;
-  long int nstd, nnid;
-  booleantype lavd, lcfn, lcfl;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (perftask == 0) {
-    nst0 = nst;  nni0 = nni;  nli0 = nli;
-    ncfn0 = ncfn;  ncfl0 = ncfl;  
-    nwarn = 0;
-    return(0);
-  }
-
-  nstd = nst - nst0;  nnid = nni - nni0;
-  if (nstd == 0 || nnid == 0) return(0);
-  avdim = (realtype) ((nli - nli0)/((realtype) nnid));
-  rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd));
-  rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid));
-  lavd = (avdim > ((realtype) maxl));
-  lcfn = (rcfn > PT9);
-  lcfl = (rcfl > PT9);
-  if (!(lavd || lcfn || lcfl)) return(0);
-  nwarn++;
-  if (nwarn > 10) return(1);
-  if (lavd) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_AVD_WARN, tn, avdim);
-  if (lcfn) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_CFN_WARN, tn, rcfn);
-  if (lcfl) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_CFL_WARN, tn, rcfl);
-
-  return(0);
-}
-
-static int IDASptfqmrFree(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(yptemp);
-  N_VDestroy(xx);
-  
-  sptfqmr_mem = (SptfqmrMem)spils_mem;
-  SptfqmrFree(sptfqmr_mem);
-
-  if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem);
-
-  free(idaspils_mem); idaspils_mem = NULL;
-
-  return(0);
-}
-
diff --git a/src/ida/ida_superlumt.c b/src/ida/ida_superlumt.c
deleted file mode 100644
index eda8449..0000000
--- a/src/ida/ida_superlumt.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4938 $
- * $Date: 2016-09-21 14:33:08 -0700 (Wed, 21 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDASUPERLUMT linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "sundials/sundials_math.h"
-#include "sundials/sundials_superlumt_impl.h"
-
-#include "ida_impl.h"
-#include "ida_sparse_impl.h"
-#include "ida/ida_superlumt.h"
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* IDASUPERLUMT linit, lsetup, lsolve, and lfree routines */
- 
-static int IDASuperLUMTInit(IDAMem IDA_mem);
-
-static int IDASuperLUMTSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-			     N_Vector rrp, N_Vector tmp1,
-			     N_Vector tmp2, N_Vector tmp3);
-
-static int IDASuperLUMTSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-			     N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDASuperLUMTFree(IDAMem IDA_mem);
-
-/*
- * -----------------------------------------------------------------
- * IDASuperLUMT
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDA / SuperLUMT linear solver module.  
- * IDASuperLUMT first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASuperLUMTInit, IDASuperLUMTSetup,
- * IDASuperLUMTSolve, NULL, and IDASuperLUMTFree, respectively.
- * It allocates memory for a structure of type IDAsluMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jdata field
- * in the IDAsluMemRec structure to be the input parameter jdata,
- * and sets the d_jac field to be:
- *   (1) the input parameter djac, if djac != NULL, or                
- *   (2) throws an error, if djac == NULL.                             
- * Finally, it allocates memory for SuperLUMT.
- * The return value is IDASLS_SUCCESS = 0, IDASLS_LMEM_FAIL = -1,
- * or IDASLS_ILL_INPUT = -2.
- *
- * NOTE: The SuperLUMT linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDASuperLUMT will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int IDASuperLUMT(void *ida_mem, int num_threads, int n, int nnz)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-  int *perm_c, *perm_r;
-  int nrhs, panel_size, relax;
-  double *bd;
-  SuperMatrix *B;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDASuperLUMT", 
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASLS", "IDASuperLUMT", 
-		    MSGSP_BAD_NVECTOR);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  if (IDA_mem->ida_lfree != NULL) IDA_mem->ida_lfree(IDA_mem);
-
-  /* Set five main function fields in IDA_mem. */
-  IDA_mem->ida_linit  = IDASuperLUMTInit;
-  IDA_mem->ida_lsetup = IDASuperLUMTSetup;
-  IDA_mem->ida_lsolve = IDASuperLUMTSolve;
-  IDA_mem->ida_lperf  = NULL;
-  IDA_mem->ida_lfree  = IDASuperLUMTFree;
-
-  /* Get memory for IDASlsMemRec. */
-  idasls_mem = NULL;
-  idasls_mem = (IDASlsMem) malloc(sizeof(struct IDASlsMemRec));
-  if (idasls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* Get memory for SLUMT_data. */
-  slumt_data = NULL;
-  slumt_data = (SLUMTData)malloc(sizeof(struct SLUMTDataRec));
-  if (slumt_data == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  IDA_mem->ida_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  idasls_mem->s_jaceval = NULL;
-  idasls_mem->s_jacdata = IDA_mem->ida_user_data;
-
-  /* Allocate memory for the sparse Jacobian */
-  idasls_mem->s_JacMat = NULL;
-  idasls_mem->s_JacMat = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (idasls_mem->s_JacMat == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* Set up memory for the permutations */
-  perm_r = (int *)malloc(n*sizeof(int));
-  if (perm_r == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-  perm_c = (int *)malloc(n*sizeof(int));
-  if (perm_c == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    free(perm_r);
-    return(IDASLS_MEM_FAIL);
-  }
-  slumt_data->perm_r = perm_r;
-  slumt_data->perm_c = perm_c;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  /* Set default parameters for SuperLU */
-  slumt_data->num_threads = num_threads;
-  slumt_data->diag_pivot_thresh = 1.0;
-
-  /* Allocate structures for SuperLU */
-  slumt_data->Gstat = (Gstat_t *)malloc(sizeof(Gstat_t));
-  slumt_data->s_A = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_AC = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_L = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_U = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_A->Store  = NULL;
-  slumt_data->s_AC->Store = NULL;
-  slumt_data->s_L->Store  = NULL;
-  slumt_data->s_U->Store  = NULL;
-  slumt_data->superlumt_options = (superlumt_options_t *)malloc(sizeof(superlumt_options_t));
-
-  dCreate_CompCol_Matrix(slumt_data->s_A, idasls_mem->s_JacMat->M, 
-			 idasls_mem->s_JacMat->N, 
-			 idasls_mem->s_JacMat->NNZ, idasls_mem->s_JacMat->data, 
-			 idasls_mem->s_JacMat->indexvals, 
-			 idasls_mem->s_JacMat->indexptrs, 
-			 SLU_NC, SLU_D, SLU_GE);
-
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  StatAlloc(idasls_mem->s_JacMat->N, num_threads, panel_size, relax, 
-	    slumt_data->Gstat);
-  
-  /* Create RHS matrix */
-  nrhs = 1;
-  bd = NULL;
-  B = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  B->Store = NULL;
-  dCreate_Dense_Matrix(B, n, nrhs, bd, n, 
-		       SLU_DN, SLU_D, SLU_GE);
-  slumt_data->s_B = B;
-
-  /* Set ordering to COLAMD as the ida default use.
-     Users can set a different value with IDASuperLUMTSetOrdering,
-     and the user-set value is loaded before any call to factorize the
-     matrix in IDASuperLUMTSetup.  */
-  slumt_data->s_ordering = 3;
-
-  /* Attach linear solver memory to the integrator memory */
-  idasls_mem->s_solver_data = (void *) slumt_data;
-  IDA_mem->ida_lmem = idasls_mem;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASuperLUMT interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDASuperLUMT
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int IDASuperLUMTInit(IDAMem IDA_mem)
-{
-  int num_threads, n;
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-
-  idasls_mem = (IDASlsMem)IDA_mem->ida_lmem;
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  idasls_mem->s_nje = 0;
-  idasls_mem->s_first_factorize = 1;
-
-  /* ------------------------------------------------------------
-     Allocate storage and initialize statistics variables. 
-     ------------------------------------------------------------*/
-  n = idasls_mem->s_JacMat->N;
-  num_threads = slumt_data->num_threads;
-
-  StatInit(n, num_threads, slumt_data->Gstat);
-
-  idasls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the IDASuperLUMT linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     IDASLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDASuperLUMTSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-			     N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-			     N_Vector tmp3)
-{
-  int retval, info;
-  int nprocs, panel_size, relax, permc_spec, lwork;
-  int *perm_r, *perm_c;
-  realtype tn, cj;
-  double diag_pivot_thresh, drop_tol;
-  fact_t fact;
-  trans_t trans;
-  yes_no_t refact, usepr;
-  IDASlsMem idasls_mem;
-  IDASlsSparseJacFn jaceval;
-  SuperMatrix *A, *AC, *L, *U;
-  Gstat_t *Gstat;
-  superlumt_options_t *superlumt_options;
-  SLUMTData slumt_data;
-  SlsMat JacMat;
-  void *jacdata;
-  void *work;
-  
-  idasls_mem = (IDASlsMem) (IDA_mem->ida_lmem);
-  tn = IDA_mem->ida_tn; 
-  cj = IDA_mem->ida_cj;
-
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  jaceval = idasls_mem->s_jaceval;
-  jacdata = idasls_mem->s_jacdata;
-  JacMat = idasls_mem->s_JacMat;
-
-  superlumt_options = slumt_data->superlumt_options;
-  A = slumt_data->s_A;
-  AC = slumt_data->s_AC;
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  Gstat = slumt_data->Gstat;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  nprocs = slumt_data->num_threads;
-  diag_pivot_thresh = slumt_data->diag_pivot_thresh;
-
-  /* Set option values for SuperLU_MT */
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  fact = EQUILIBRATE;
-  trans = NOTRANS;
-  usepr = NO;
-  drop_tol = 0.0;
-  lwork = 0;
-  work = NULL;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_JAC_NOSET, "IDASLS", "IDASuperLUMTSetup", 
-		    MSGSP_JAC_NOSET);
-    free(idasls_mem); idasls_mem = NULL;
-    return(IDASLS_JAC_NOSET);
-  }
-
-  /* Increment nje counter and call Jacobian eval routine. */
-  idasls_mem->s_nje++;
-  retval = jaceval(tn, cj, yyp, ypp, rrp, JacMat, jacdata, 
-		   tmp1, tmp2, tmp3);
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDASLS_JACFUNC_UNRECVR, "IDASLS", 
-		    "IDASuperLUMTSetup", MSGSP_JACFUNC_FAILED);
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_UNRECVR;
-    return(IDASLS_JACFUNC_UNRECVR);
-  }
-  if (retval > 0) {
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  if (idasls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get column permutation vector perm_c[], according to permc_spec:
-       permc_spec = 3: approximate minimum degree for unsymmetric matrices
-       ------------------------------------------------------------*/ 
-    permc_spec = slumt_data->s_ordering;
-    get_perm_c(permc_spec, A, perm_c);
- 
-    refact= NO;
-    idasls_mem->s_first_factorize = 0;
-  }
-  else {
-    /* ------------------------------------------------------------
-       Re-initialize statistics variables 
-       ------------------------------------------------------------*/
-    StatInit(JacMat->N, nprocs, Gstat);
-    Destroy_CompCol_Permuted(AC);
-    refact= YES;
-  }
-
-  /* ------------------------------------------------------------
-     Initialize the option structure superlumt_options using the
-     user-input parameters;  Subsequent calls will re-initialize
-     options.
-     Apply perm_c to the columns of original A to form AC.
-     ------------------------------------------------------------*/
-  pdgstrf_init(nprocs, fact, trans, refact, panel_size, relax,
-	       diag_pivot_thresh, usepr, drop_tol, perm_c, perm_r,
-	       work, lwork, A, AC, superlumt_options, Gstat);
-  /* ------------------------------------------------------------
-     Compute the LU factorization of A.
-     The following routine will create nprocs threads.
-     ------------------------------------------------------------*/
-  pdgstrf(superlumt_options, AC, perm_r, L, U, Gstat, &info);
-    
-  if (info != 0) {
-    idasls_mem->s_last_flag = info;
-    return(+1);
-  }
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the IDASuperLUMT linear
-  solver module.  It calls the SuperLUMT solve routine, scales the
-  solution vector according to cjratio, then returns IDASLU_SUCCESS = 0.
-*/
-
-static int IDASuperLUMTSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-			     N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  int info, trans;
-  int *perm_r, *perm_c;
-  double cjratio;
-  IDASlsMem idasls_mem;
-  SuperMatrix *L, *U, *B;
-  Gstat_t *Gstat;
-  DNformat *Bstore;
-  SLUMTData slumt_data;
-  realtype *bd;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-  cjratio = IDA_mem->ida_cjratio;
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  Gstat = slumt_data->Gstat;
-  B = slumt_data->s_B;
-   
-  bd = N_VGetArrayPointer(b);
-  Bstore = (DNformat *) (B->Store);
-  Bstore->nzval = bd;
-
-  /* Call SuperLUMT to solve the linear system using L and U */
-  trans = NOTRANS;
-  dgstrs(trans, L, U, perm_r, perm_c, B, Gstat, &info);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-
-  Bstore->nzval = NULL;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-  return(IDASLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the IDASuperLUMT linear solver.
-*/
-
-static int IDASuperLUMTFree(IDAMem IDA_mem)
-{
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  pxgstrf_finalize(slumt_data->superlumt_options, slumt_data->s_AC);
-
-  free(slumt_data->perm_r);
-  free(slumt_data->perm_c);
-  free(slumt_data->superlumt_options);
-  Destroy_SuperNode_SCP( (slumt_data->s_L) );
-  Destroy_CompCol_NCP( (slumt_data->s_U) );
-  StatFree( (slumt_data->Gstat) );
-  free(slumt_data->Gstat);
-  
-  Destroy_SuperMatrix_Store(slumt_data->s_B);
-  SUPERLU_FREE(slumt_data->s_A->Store);
-  if (idasls_mem->s_JacMat) {
-    SparseDestroyMat(idasls_mem->s_JacMat);
-    idasls_mem->s_JacMat = NULL;
-  }
-
-  free(slumt_data->s_B);
-  free(slumt_data->s_A);
-  free(slumt_data->s_AC);
-  free(slumt_data->s_L);
-  free(slumt_data->s_U);
-
-  free(slumt_data); 
-  slumt_data = NULL;
- 
-  free(IDA_mem->ida_lmem); 
-  IDA_mem->ida_lmem = NULL;
-
-  return(IDASLS_SUCCESS);
-}
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDASuperLUMTSetOrdering sets the ordering used by SuperLUMT for reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int IDASuperLUMTSetOrdering(void *ida_mem_v, int ordering_choice)
-{
-  IDAMem ida_mem;
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-
- /* Return immediately if ida_mem is NULL */
-  if (ida_mem_v == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDASuperLUMTSetOrdering",
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  ida_mem = (IDAMem) ida_mem_v;
-  idasls_mem = (IDASlsMem) ida_mem->ida_lmem;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) && (ordering_choice != 3) ) {
-    IDAProcessError(NULL, IDASLS_ILL_INPUT, "IDASLS", "IDASuperLUMTSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  slumt_data->s_ordering = ordering_choice;
-
-  return(IDASLS_SUCCESS);
-}
-
-
-
-
diff --git a/src/idas/CMakeLists.txt b/src/idas/CMakeLists.txt
index 400a228..905b7f6 100644
--- a/src/idas/CMakeLists.txt
+++ b/src/idas/CMakeLists.txt
@@ -1,18 +1,20 @@
 # ---------------------------------------------------------------
-# $Revision: 4759 $
-# $Date: 2016-05-18 16:25:17 -0700 (Wed, 18 May 2016) $
+# Programmer:  Daniel R. Reynolds @ SMU
+#              Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
-# ---------------------------------------------------------------
-# LLNS Copyright Start
-# Copyright (c) 2014, Lawrence Livermore National Security
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
 # This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
-# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
-# Produced at the Lawrence Livermore National Laboratory.
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
-# LLNS Copyright End
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the IDAS library
 
@@ -26,86 +28,56 @@ SET(idas_SOURCES
   idas_ic.c
   idaa_io.c
   idas_direct.c
-  idas_band.c
-  idas_dense.c
-  idas_sparse.c
   idas_spils.c
-  idas_spbcgs.c
-  idas_spgmr.c
-  idas_sptfqmr.c
   idas_bbdpre.c
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND idas_SOURCES idas_klu.c)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND idas_SOURCES idas_superlumt.c)
-ENDIF()
-
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the IDAS library
 SET(shared_SOURCES
-  sundials_nvector.c
-  sundials_math.c
-  sundials_direct.c
-  sundials_band.c
-  sundials_dense.c
-  sundials_iterative.c
-  sundials_sparse.c
-  sundials_spbcgs.c
-  sundials_spgmr.c
-  sundials_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_band.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_dense.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_direct.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_version.c
+  ${sundials_SOURCE_DIR}/src/nvec_ser/nvector_serial.c
+  )
+
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the IDAS library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/sunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/sunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/sunmatrix_sparse.c
   )
 
-# Add prefix with complete path to the common SUNDIALS sources
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the IDAS library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/sunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/sunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/sunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/sunlinsol_pcg.c
+  )
 
 # Add variable idas_HEADERS with the exported IDAS header files
 SET(idas_HEADERS
-  idas_band.h
+  idas.h
   idas_bbdpre.h
-  idas_dense.h
   idas_direct.h
-  idas.h
-  idas_sparse.h
-  idas_spbcgs.h
-  idas_spgmr.h
   idas_spils.h
-  idas_sptfqmr.h
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND idas_HEADERS idas_klu.h)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND idas_HEADERS idas_superlumt.h)
-ENDIF()
-
 # Add prefix with complete path to the IDAS header files
 ADD_PREFIX(${sundials_SOURCE_DIR}/include/idas/ idas_HEADERS)
 
-# If Blas/Lapack support was enabled, set-up additional file lists
-IF(LAPACK_FOUND)
-  SET(idas_BL_SOURCES idas_lapack.c)
-  SET(idas_BL_HEADERS idas_lapack.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/idas/ idas_BL_HEADERS)
-ELSE(LAPACK_FOUND)
-  SET(idas_BL_SOURCES "")
-  SET(idas_BL_HEADERS "")
-ENDIF(LAPACK_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  SET(idas_SLU_SOURCES idas_superlumt.c)
-  SET(idas_SLU_HEADERS idas_superlumt.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/idas/ idas_SLU_HEADERS)
-ELSE(SUPERLUMT_FOUND)
-  SET(idas_SLU_SOURCES "")
-  SET(idas_SLU_HEADERS "")
-ENDIF(SUPERLUMT_FOUND)
-
 # Add source directories to include directories for access to
 # implementation only header files.
 INCLUDE_DIRECTORIES(.)
@@ -119,7 +91,7 @@ IF(BUILD_STATIC_LIBS)
 
   # Add the build target for the static IDAS library
   ADD_LIBRARY(sundials_idas_static STATIC 
-    ${idas_SOURCES} ${idas_BL_SOURCES} ${idas_SLU_SOURCES}  ${shared_SOURCES})
+    ${idas_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_idas_static
@@ -135,7 +107,11 @@ IF(BUILD_SHARED_LIBS)
 
   # Add the build target for the IDAS library
   ADD_LIBRARY(sundials_idas_shared SHARED 
-    ${idas_SOURCES}  ${idas_BL_SOURCES} ${idas_SLU_SOURCES} ${shared_SOURCES})
+    ${idas_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_idas_shared m)
+  ENDIF()
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_idas_shared
@@ -151,7 +127,7 @@ IF(BUILD_SHARED_LIBS)
 ENDIF(BUILD_SHARED_LIBS)
 
 # Install the IDAS header files
-INSTALL(FILES ${idas_HEADERS} ${idas_BL_HEADERS} ${idas_SLU_HEADERS} DESTINATION include/idas)
+INSTALL(FILES ${idas_HEADERS} DESTINATION include/idas)
 
 # Install the IDAS implementation header file
 INSTALL(FILES idas_impl.h DESTINATION include/idas)
diff --git a/src/idas/README b/src/idas/README
index cc7c3e7..a8f99e3 100644
--- a/src/idas/README
+++ b/src/idas/README
@@ -1,5 +1,5 @@
                                IDAS
-                    Release 1.3.0, September 2016
+                    Release 2.1.0, November 2017
                            Radu Serban 
               Center for Applied Scientific Computing, LLNL
 
@@ -72,6 +72,8 @@ C. References
 D. Releases
 -----------
 
+v. 2.1.0   - Nov. 2017
+v. 2.0.0   - Sep. 2017
 v. 1.3.0   - Sep. 2016
 v. 1.2.2   - Aug. 2015
 v. 1.2.1   - Mar. 2015
diff --git a/src/idas/idaa.c b/src/idas/idaa.c
index 3ee80d1..06bf086 100644
--- a/src/idas/idaa.c
+++ b/src/idas/idaa.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4847 $
- * $Date: 2016-08-03 15:50:53 -0700 (Wed, 03 Aug 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -30,12 +30,6 @@
 #include <sundials/sundials_math.h>
 
 /*=================================================================*/
-/*                  Macros                                         */
-/*=================================================================*/
-
-#define loop for(;;)
-
-/*=================================================================*/
 /*                 IDAA Private Constants                          */
 /*=================================================================*/
 
@@ -94,135 +88,6 @@ static int IDAAGettnSolutionYpS(IDAMem IDA_mem, N_Vector *ypS);
 
 extern int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret);
 
-/*=================================================================*/
-/*             Readibility Constants                               */
-/*=================================================================*/
-
-/* IDAADJ memory block */
-#define tinitial     (IDAADJ_mem->ia_tinitial)
-#define tfinal       (IDAADJ_mem->ia_tfinal)
-#define nckpnts      (IDAADJ_mem->ia_nckpnts)
-#define nbckpbs      (IDAADJ_mem->ia_nbckpbs)
-#define nsteps       (IDAADJ_mem->ia_nsteps)
-#define ckpntData    (IDAADJ_mem->ia_ckpntData)
-#define newData      (IDAADJ_mem->ia_newData)
-#define np           (IDAADJ_mem->ia_np)
-#define dt           (IDAADJ_mem->ia_dt)
-#define yyTmp        (IDAADJ_mem->ia_yyTmp)
-#define ypTmp        (IDAADJ_mem->ia_ypTmp)
-#define yySTmp       (IDAADJ_mem->ia_yySTmp)
-#define ypSTmp       (IDAADJ_mem->ia_ypSTmp)
-#define res_B        (IDAADJ_mem->ia_resB)
-#define djac_B       (IDAADJ_mem->ia_djacB)
-#define bjac_B       (IDAADJ_mem->ia_bjacB)
-#define pset_B       (IDAADJ_mem->ia_psetB)
-#define psolve_B     (IDAADJ_mem->ia_psolveB)
-#define jtimes_B     (IDAADJ_mem->ia_jtimesB)
-#define jdata_B      (IDAADJ_mem->ia_jdataB)
-#define pdata_B      (IDAADJ_mem->ia_pdataB)
-#define rhsQ_B       (IDAADJ_mem->ia_rhsQB)
-
-#define Y            (IDAADJ_mem->ia_Y)
-#define YS           (IDAADJ_mem->ia_YS)
-#define T            (IDAADJ_mem->ia_T)
-#define mallocDone   (IDAADJ_mem->ia_mallocDone)
-
-#define interpSensi  (IDAADJ_mem->ia_interpSensi)
-#define storeSensi   (IDAADJ_mem->ia_storeSensi)
-#define noInterp     (IDAADJ_mem->ia_noInterp)
-
-/* Forward IDAS memory block */
-#define uround     (IDA_mem->ida_uround)
-#define res        (IDA_mem->ida_res)
-#define itol       (IDA_mem->ida_itol)
-#define reltol     (IDA_mem->ida_reltol)
-#define abstol     (IDA_mem->ida_abstol)
-#define user_data  (IDA_mem->ida_user_data)
-
-#define forceSetup (IDA_mem->ida_forceSetup)
-#define h0u        (IDA_mem->ida_h0u)
-
-#define phi        (IDA_mem->ida_phi)
-#define psi        (IDA_mem->ida_psi)
-#define alpha      (IDA_mem->ida_alpha)
-#define beta       (IDA_mem->ida_beta)
-#define sigma      (IDA_mem->ida_sigma)
-#define gamma      (IDA_mem->ida_gamma)
-#define tn         (IDA_mem->ida_tn)
-#define kk         (IDA_mem->ida_kk)
-#define nst        (IDA_mem->ida_nst)
-#define tretlast   (IDA_mem->ida_tretlast)
-#define kk         (IDA_mem->ida_kk)
-#define kused      (IDA_mem->ida_kused)
-#define knew       (IDA_mem->ida_knew)
-#define maxord     (IDA_mem->ida_maxord)
-#define phase      (IDA_mem->ida_phase)
-#define ns         (IDA_mem->ida_ns)
-#define hh         (IDA_mem->ida_hh)
-#define hused      (IDA_mem->ida_hused)
-#define rr         (IDA_mem->ida_rr)
-#define cj         (IDA_mem->ida_cj)
-#define cjlast     (IDA_mem->ida_cjlast)
-#define cjold      (IDA_mem->ida_cjold)
-#define cjratio    (IDA_mem->ida_cjratio) 
-#define ss         (IDA_mem->ida_ss)
-#define ssS        (IDA_mem->ida_ssS)
-
-#define tempv      (IDA_mem->ida_tempv1)
-
-#define sensi      (IDA_mem->ida_sensi)
-#define Ns         (IDA_mem->ida_Ns)
-#define phiS       (IDA_mem->ida_phiS)
-
-#define quadr      (IDA_mem->ida_quadr)
-#define errconQ    (IDA_mem->ida_errconQ)
-#define phiQ       (IDA_mem->ida_phiQ)
-#define rhsQ       (IDA_mem->ida_rhsQ)
-
-#define quadr_sensi (IDA_mem->ida_quadr_sensi)
-#define errconQS   (IDA_mem->ida_errconQS)
-#define phiQS      (IDA_mem->ida_phiQS)
-
-#define tempvQ     (IDA_mem->ida_eeQ)
-
-/* Checkpoint memory block */
-
-#define t0_        (ck_mem->ck_t0)
-#define t1_        (ck_mem->ck_t1)
-#define phi_       (ck_mem->ck_phi)
-#define phiQ_      (ck_mem->ck_phiQ)
-#define psi_       (ck_mem->ck_psi)
-#define alpha_     (ck_mem->ck_alpha)
-#define beta_      (ck_mem->ck_beta)
-#define sigma_     (ck_mem->ck_sigma)
-#define gamma_     (ck_mem->ck_gamma)
-#define nst_       (ck_mem->ck_nst)
-#define tretlast_  (ck_mem->ck_tretlast)
-#define kk_        (ck_mem->ck_kk)
-#define kused_     (ck_mem->ck_kused)
-#define knew_      (ck_mem->ck_knew)
-#define phase_     (ck_mem->ck_phase)
-#define ns_        (ck_mem->ck_ns)
-#define hh_        (ck_mem->ck_hh)
-#define hused_     (ck_mem->ck_hused)
-#define rr_        (ck_mem->ck_rr)
-#define cj_        (ck_mem->ck_cj)
-#define cjlast_    (ck_mem->ck_cjlast)
-#define cjold_     (ck_mem->ck_cjold)
-#define cjratio_   (ck_mem->ck_cjratio)
-#define ss_        (ck_mem->ck_ss)
-#define ssS_       (ck_mem->ck_ssS)
-#define next_      (ck_mem->ck_next)
-#define phi_alloc_ (ck_mem->ck_phi_alloc)
-
-#define sensi_     (ck_mem->ck_sensi)
-#define Ns_        (ck_mem->ck_Ns)
-#define phiS_      (ck_mem->ck_phiS)
-
-#define quadr_     (ck_mem->ck_quadr)
-#define phiQS_     (ck_mem->ck_phiQS)
-
-#define quadr_sensi_ (ck_mem->ck_quadr_sensi)
 
 /*=================================================================*/
 /*                  Exported Functions                             */
@@ -280,7 +145,7 @@ int IDAAdjInit(void *ida_mem, long int steps, int interp)
   IDAADJ_mem->ia_nsteps = steps;
 
   /* Allocate space for the array of Data Point structures. */
-  if (IDAAdataMalloc(IDA_mem) == FALSE) {
+  if (IDAAdataMalloc(IDA_mem) == SUNFALSE) {
     free(IDAADJ_mem); IDAADJ_mem = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAA", "IDAAdjInit", MSGAM_MEM_FAIL);
     return(IDA_MEM_FAIL);
@@ -306,19 +171,19 @@ int IDAAdjInit(void *ida_mem, long int steps, int interp)
   }
 
  /* The interpolation module has not been initialized yet */
-  IDAADJ_mem->ia_mallocDone = FALSE;
+  IDAADJ_mem->ia_mallocDone = SUNFALSE;
 
   /* By default we will store but not interpolate sensitivities
-   *  - storeSensi will be set in IDASolveF to FALSE if FSA is not enabled
+   *  - storeSensi will be set in IDASolveF to SUNFALSE if FSA is not enabled
    *    or if the user forced this through IDAAdjSetNoSensi 
-   *  - interpSensi will be set in IDASolveB to TRUE if storeSensi is TRUE 
+   *  - interpSensi will be set in IDASolveB to SUNTRUE if storeSensi is SUNTRUE 
    *    and if at least one backward problem requires sensitivities 
-   *  - noInterp will be set in IDACalcICB to TRUE before the call to
-   *    IDACalcIC and FALSE after.*/
+   *  - noInterp will be set in IDACalcICB to SUNTRUE before the call to
+   *    IDACalcIC and SUNFALSE after.*/
 
-  IDAADJ_mem->ia_storeSensi  = TRUE;
-  IDAADJ_mem->ia_interpSensi = FALSE;
-  IDAADJ_mem->ia_noInterp    = FALSE;
+  IDAADJ_mem->ia_storeSensi  = SUNTRUE;
+  IDAADJ_mem->ia_interpSensi = SUNFALSE;
+  IDAADJ_mem->ia_noInterp    = SUNFALSE;
 
   /* Initialize backward problems. */
   IDAADJ_mem->IDAB_mem = NULL;
@@ -326,13 +191,13 @@ int IDAAdjInit(void *ida_mem, long int steps, int interp)
   IDAADJ_mem->ia_nbckpbs = 0;
 
   /* Flags for tracking the first calls to IDASolveF and IDASolveF. */
-  IDAADJ_mem->ia_firstIDAFcall = TRUE;
-  IDAADJ_mem->ia_tstopIDAFcall = FALSE;
-  IDAADJ_mem->ia_firstIDABcall = TRUE;
+  IDAADJ_mem->ia_firstIDAFcall = SUNTRUE;
+  IDAADJ_mem->ia_tstopIDAFcall = SUNFALSE;
+  IDAADJ_mem->ia_firstIDABcall = SUNTRUE;
 
   /* Adjoint module initialized and allocated. */
-  IDA_mem->ida_adj = TRUE;
-  IDA_mem->ida_adjMallocDone = TRUE;
+  IDA_mem->ida_adj = SUNTRUE;
+  IDA_mem->ida_adjMallocDone = SUNTRUE;
 
   return(IDA_SUCCESS);
 } 
@@ -357,7 +222,7 @@ int IDAAdjReInit(void *ida_mem)
   IDA_mem = (IDAMem)ida_mem;
 
   /* Was ASA previously initialized? */
-  if(IDA_mem->ida_adjMallocDone == FALSE) {
+  if(IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAAdjReInit",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
@@ -373,9 +238,9 @@ int IDAAdjReInit(void *ida_mem)
   IDAADJ_mem->ia_ckpntData = NULL;
 
   /* Flags for tracking the first calls to IDASolveF and IDASolveF. */
-  IDAADJ_mem->ia_firstIDAFcall = TRUE;
-  IDAADJ_mem->ia_tstopIDAFcall = FALSE;
-  IDAADJ_mem->ia_firstIDABcall = TRUE;
+  IDAADJ_mem->ia_firstIDAFcall = SUNTRUE;
+  IDAADJ_mem->ia_tstopIDAFcall = SUNFALSE;
+  IDAADJ_mem->ia_firstIDABcall = SUNTRUE;
 
   return(IDA_SUCCESS);
 } 
@@ -489,7 +354,7 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized ? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASolveF",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
@@ -524,14 +389,14 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
 
   /* If tstop is enabled, store some info */
   if (IDA_mem->ida_tstopset) {
-    IDAADJ_mem->ia_tstopIDAFcall = TRUE;
+    IDAADJ_mem->ia_tstopIDAFcall = SUNTRUE;
     IDAADJ_mem->ia_tstopIDAF = IDA_mem->ida_tstop;
   }
   
   /* We will call IDASolve in IDA_ONE_STEP mode, regardless
      of what itask is, so flag if we need to return */
-/*   if (itask == IDA_ONE_STEP) iret = TRUE;
- *   else                       iret = FALSE;
+/*   if (itask == IDA_ONE_STEP) iret = SUNTRUE;
+ *   else                       iret = SUNFALSE;
  */
 
   /* On the first step:
@@ -543,16 +408,16 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
    */
   if ( IDAADJ_mem->ia_firstIDAFcall ) {
     
-    tinitial = tn;
+    IDAADJ_mem->ia_tinitial = IDA_mem->ida_tn;
     IDAADJ_mem->ck_mem = IDAAckpntInit(IDA_mem);
     if (IDAADJ_mem->ck_mem == NULL) {
       IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAA", "IDASolveF", MSG_MEM_FAIL);
       return(IDA_MEM_FAIL);
     }
 
-    if (!mallocDone) {
+    if (!IDAADJ_mem->ia_mallocDone) {
       /* Do we need to store sensitivities? */
-      if (!sensi) storeSensi = FALSE;
+      if (!IDA_mem->ida_sensi) IDAADJ_mem->ia_storeSensi = SUNFALSE;
 
       /* Allocate space for interpolation data */
       allocOK = IDAADJ_mem->ia_malloc(IDA_mem);
@@ -562,34 +427,35 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
       }
 
       /* Rename phi and, if needed, phiS for use in interpolation */
-      for (i=0;i<MXORDP1;i++) Y[i] = phi[i];
-      if (storeSensi) {
-        for (i=0;i<MXORDP1;i++) YS[i] = phiS[i];
+      for (i=0;i<MXORDP1;i++) IDAADJ_mem->ia_Y[i] = IDA_mem->ida_phi[i];
+      if (IDAADJ_mem->ia_storeSensi) {
+        for (i=0;i<MXORDP1;i++)
+          IDAADJ_mem->ia_YS[i] = IDA_mem->ida_phiS[i];
       }
 
-      mallocDone = TRUE;
+      IDAADJ_mem->ia_mallocDone = SUNTRUE;
     }
 
     dt_mem[0]->t = IDAADJ_mem->ck_mem->ck_t0;
     IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[0]);
 
-    IDAADJ_mem->ia_firstIDAFcall = FALSE;
+    IDAADJ_mem->ia_firstIDAFcall = SUNFALSE;
 
-  } else if ( (tn-tout)*hh >= ZERO ) {
+  } else if ( (IDA_mem->ida_tn-tout)*IDA_mem->ida_hh >= ZERO ) {
 
     /* If tout was passed, return interpolated solution. 
        No changes to ck_mem or dt_mem are needed. */
     *tret = tout;
     flag = IDAGetSolution(IDA_mem, tout, yret, ypret);
-    *ncheckPtr = nckpnts;
-    newData = TRUE;
-    ckpntData = IDAADJ_mem->ck_mem;
-    np = nst % nsteps + 1;
+    *ncheckPtr = IDAADJ_mem->ia_nckpnts;
+    IDAADJ_mem->ia_newData = SUNTRUE;
+    IDAADJ_mem->ia_ckpntData = IDAADJ_mem->ck_mem;
+    IDAADJ_mem->ia_np = IDA_mem->ida_nst % IDAADJ_mem->ia_nsteps + 1;
 
     return(flag);
   }
   /* Integrate to tout while loading check points */
-  loop {
+  for(;;) {
 
     /* Perform one step of the integration */
 
@@ -599,7 +465,7 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
 
     /* Test if a new check point is needed */
 
-    if ( nst % nsteps == 0 ) {
+    if ( IDA_mem->ida_nst % IDAADJ_mem->ia_nsteps == 0 ) {
 
       IDAADJ_mem->ck_mem->ck_t1 = *tret;
 
@@ -612,9 +478,9 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
 
       tmp->ck_next = IDAADJ_mem->ck_mem;
       IDAADJ_mem->ck_mem = tmp;
-      nckpnts++;
+      IDAADJ_mem->ia_nckpnts++;
       
-      forceSetup = TRUE;
+      IDA_mem->ida_forceSetup = SUNTRUE;
       
       /* Reset i=0 and load dt_mem[0] */
       dt_mem[0]->t = IDAADJ_mem->ck_mem->ck_t0;
@@ -623,8 +489,8 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
     } else {
       
       /* Load next point in dt_mem */
-      dt_mem[nst%nsteps]->t = *tret;
-      IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[nst%nsteps]);
+      dt_mem[IDA_mem->ida_nst%IDAADJ_mem->ia_nsteps]->t = *tret;
+      IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[IDA_mem->ida_nst % IDAADJ_mem->ia_nsteps]);
     }
 
     /* Set t1 field of the current ckeck point structure
@@ -633,13 +499,13 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
     IDAADJ_mem->ck_mem->ck_t1 = *tret;
 
     /* tfinal is now set to *t */
-    tfinal = *tret;
+    IDAADJ_mem->ia_tfinal = *tret;
 
     /* In IDA_ONE_STEP mode break from loop */
     if (itask == IDA_ONE_STEP) break;
 
     /* Return if tout reached */
-    if ( (*tret - tout)*hh >= ZERO ) {
+    if ( (*tret - tout)*IDA_mem->ida_hh >= ZERO ) {
       *tret = tout;
       IDAGetSolution(IDA_mem, tout, yret, ypret);
       /* Reset tretlast in IDA_mem so that IDAGetQuad and IDAGetSens 
@@ -650,12 +516,12 @@ int IDASolveF(void *ida_mem, realtype tout, realtype *tret,
   }
 
   /* Get ncheck from IDAADJ_mem */ 
-  *ncheckPtr = nckpnts;
+  *ncheckPtr = IDAADJ_mem->ia_nckpnts;
 
   /* Data is available for the last interval */
-  newData = TRUE;
-  ckpntData = IDAADJ_mem->ck_mem;
-  np = nst % nsteps + 1;
+  IDAADJ_mem->ia_newData = SUNTRUE;
+  IDAADJ_mem->ia_ckpntData = IDAADJ_mem->ck_mem;
+  IDAADJ_mem->ia_np = IDA_mem->ida_nst % IDAADJ_mem->ia_nsteps + 1;
 
   return(flag);
 }
@@ -684,7 +550,7 @@ int IDACreateB(void *ida_mem, int *which)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized ? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDACreateB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
@@ -731,8 +597,8 @@ int IDACreateB(void *ida_mem, int *which)
   new_IDAB_mem->ida_yy       = NULL;
   new_IDAB_mem->ida_yp       = NULL;
 
-  new_IDAB_mem->ida_res_withSensi = FALSE;
-  new_IDAB_mem->ida_rhsQ_withSensi = FALSE;
+  new_IDAB_mem->ida_res_withSensi = SUNFALSE;
+  new_IDAB_mem->ida_rhsQ_withSensi = SUNFALSE;
   
   /* Attach the new object to the beginning of the linked list IDAADJ_mem->IDAB_mem. */
   new_IDAB_mem->ida_next = IDAADJ_mem->IDAB_mem;
@@ -766,20 +632,20 @@ int IDAInitB(void *ida_mem, int which, IDAResFnB resB,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized ? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAInitB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the initial time for this backward problem against the adjoint data. */
-  if ( (tB0 < tinitial) || (tB0 > tfinal) ) {
+  if ( (tB0 < IDAADJ_mem->ia_tinitial) || (tB0 > IDAADJ_mem->ia_tfinal) ) {
     IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDAInitB", MSGAM_BAD_TB0);
     return(IDA_BAD_TB0);
   }
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAInitB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -801,7 +667,7 @@ int IDAInitB(void *ida_mem, int which, IDAResFnB resB,
 
   /* Copy residual function in IDAB_mem. */
   IDAB_mem->ida_res = resB;
-  IDAB_mem->ida_res_withSensi = FALSE;
+  IDAB_mem->ida_res_withSensi = SUNFALSE;
 
   /* Initialized the initial time field. */
   IDAB_mem->ida_t0 = tB0;
@@ -832,26 +698,26 @@ int IDAInitBS(void *ida_mem, int which, IDAResFnBS resS,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized ? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAInitBS",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the initial time for this backward problem against the adjoint data. */
-  if ( (tB0 < tinitial) || (tB0 > tfinal) ) {
+  if ( (tB0 < IDAADJ_mem->ia_tinitial) || (tB0 > IDAADJ_mem->ia_tfinal) ) {
     IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDAInitBS", MSGAM_BAD_TB0);
     return(IDA_BAD_TB0);
   }
 
   /* Were sensitivities active during the forward integration? */
-  if (!storeSensi) {
+  if (!IDAADJ_mem->ia_storeSensi) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAInitBS", MSGAM_BAD_SENSI);
     return(IDA_ILL_INPUT);
   }
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAInitBS", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -873,7 +739,7 @@ int IDAInitBS(void *ida_mem, int which, IDAResFnBS resS,
   if (flag != IDA_SUCCESS) return(flag);
 
   /* Copy residual function pointer in IDAB_mem. */
-  IDAB_mem->ida_res_withSensi = TRUE;
+  IDAB_mem->ida_res_withSensi = SUNTRUE;
   IDAB_mem->ida_resS = resS;
 
   /* Allocate space and initialize the yy and yp vectors. */
@@ -904,20 +770,20 @@ int IDAReInitB(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized ? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAReInitB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the initial time for this backward problem against the adjoint data. */
-  if ( (tB0 < tinitial) || (tB0 > tfinal) ) {
+  if ( (tB0 < IDAADJ_mem->ia_tinitial) || (tB0 > IDAADJ_mem->ia_tfinal) ) {
     IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDAReInitB", MSGAM_BAD_TB0);
     return(IDA_BAD_TB0);
   }
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAReInitB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -955,14 +821,14 @@ int IDASStolerancesB(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASStolerancesB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASStolerancesB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -998,14 +864,14 @@ int IDASVtolerancesB(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASVtolerancesB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASVtolerancesB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1041,14 +907,14 @@ int IDAQuadSStolerancesB(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAQuadSStolerancesB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadSStolerancesB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1082,14 +948,14 @@ int IDAQuadSVtolerancesB(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAQuadSVtolerancesB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadSVtolerancesB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1123,14 +989,14 @@ int IDAQuadInitB(void *ida_mem, int which, IDAQuadRhsFnB rhsQB, N_Vector yQB0)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAQuadInitB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadInitB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1147,7 +1013,7 @@ int IDAQuadInitB(void *ida_mem, int which, IDAQuadRhsFnB rhsQB, N_Vector yQB0)
   flag = IDAQuadInit(ida_memB, IDAArhsQ, yQB0);
   if (IDA_SUCCESS != flag) return flag;
 
-  IDAB_mem->ida_rhsQ_withSensi = FALSE;
+  IDAB_mem->ida_rhsQ_withSensi = SUNFALSE;
   IDAB_mem->ida_rhsQ = rhsQB;
 
   return(flag);
@@ -1170,14 +1036,14 @@ int IDAQuadInitBS(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized ? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAQuadInitBS",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadInitBS", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1199,7 +1065,7 @@ int IDAQuadInitBS(void *ida_mem, int which,
   if (flag != IDA_SUCCESS) return(flag);
 
   /* Copy RHS function pointer in IDAB_mem and enable quad sensitivities. */
-  IDAB_mem->ida_rhsQ_withSensi = TRUE;
+  IDAB_mem->ida_rhsQ_withSensi = SUNTRUE;
   IDAB_mem->ida_rhsQS = rhsQS;
 
   return(IDA_SUCCESS);
@@ -1220,14 +1086,14 @@ int IDAQuadReInitB(void *ida_mem, int which, N_Vector yQB0)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAQuadInitB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAQuadInitB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1274,14 +1140,14 @@ int IDACalcICB(void *ida_mem, int which, realtype tout1,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDACalcICB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDACalcICB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1301,17 +1167,17 @@ int IDACalcICB(void *ida_mem, int which, realtype tout1,
 
   /* Save (y, y') in yyTmp and ypTmp for use in the res wrapper.*/
   /* yyTmp and ypTmp workspaces are safe to use if IDAADataStore is not called.*/
-  N_VScale(ONE, yy0, yyTmp);
-  N_VScale(ONE, yp0, ypTmp);
+  N_VScale(ONE, yy0, IDAADJ_mem->ia_yyTmp);
+  N_VScale(ONE, yp0, IDAADJ_mem->ia_ypTmp);
   
-  /* Set noInterp flag to true, so IDAARes will use user provided values for
+  /* Set noInterp flag to SUNTRUE, so IDAARes will use user provided values for
      y and y' and will not call the interpolation routine(s). */
-  noInterp = TRUE;
+  IDAADJ_mem->ia_noInterp = SUNTRUE;
   
   flag = IDACalcIC(ida_memB, IDA_YA_YDP_INIT, tout1);
 
   /* Set interpolation on in IDAARes. */
-  noInterp = FALSE;
+  IDAADJ_mem->ia_noInterp = SUNFALSE;
 
   return(flag);
 }
@@ -1345,20 +1211,20 @@ int IDACalcICBS(void *ida_mem, int which, realtype tout1,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDACalcICBS",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Were sensitivities active during the forward integration? */
-  if (!storeSensi) {
+  if (!IDAADJ_mem->ia_storeSensi) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDACalcICBS", MSGAM_BAD_SENSI);
     return(IDA_ILL_INPUT);
   }
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDACalcICBS", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1386,22 +1252,22 @@ int IDACalcICBS(void *ida_mem, int which, realtype tout1,
      for residual will use these values instead of calling interpolation routine.*/
 
   /* The four workspaces variables are safe to use if IDAADataStore is not called.*/
-  N_VScale(ONE, yy0, yyTmp);
-  N_VScale(ONE, yp0, ypTmp);
+  N_VScale(ONE, yy0, IDAADJ_mem->ia_yyTmp);
+  N_VScale(ONE, yp0, IDAADJ_mem->ia_ypTmp);
 
-  for (is=0; is<Ns; is++) {
-    N_VScale(ONE, yyS0[is], yySTmp[is]);
-    N_VScale(ONE, ypS0[is], ypSTmp[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VScale(ONE, yyS0[is], IDAADJ_mem->ia_yySTmp[is]);
+    N_VScale(ONE, ypS0[is], IDAADJ_mem->ia_ypSTmp[is]);
   }
   
-  /* Set noInterp flag to true, so IDAARes will use user provided values for
+  /* Set noInterp flag to SUNTRUE, so IDAARes will use user provided values for
      y and y' and will not call the interpolation routine(s). */
-  noInterp = TRUE;
+  IDAADJ_mem->ia_noInterp = SUNTRUE;
   
   flag = IDACalcIC(ida_memB, IDA_YA_YDP_INIT, tout1);
 
   /* Set interpolation on in IDAARes. */
-  noInterp = FALSE;
+  IDAADJ_mem->ia_noInterp = SUNFALSE;
 
   return(flag);
 }
@@ -1445,13 +1311,13 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized ? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASolveB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
-  if ( nbckpbs == 0 ) {
+  if ( IDAADJ_mem->ia_nbckpbs == 0 ) {
     IDAProcessError(IDA_mem, IDA_NO_BCK, "IDAA", "IDASolveB", MSGAM_NO_BCK);
     return(IDA_NO_BCK);
   }
@@ -1462,7 +1328,7 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
     IDAProcessError(IDA_mem, IDA_NO_FWD, "IDAA", "IDASolveB", MSGAM_NO_FWD);
     return(IDA_NO_FWD);
   }
-  sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+  sign = (IDAADJ_mem->ia_tfinal - IDAADJ_mem->ia_tinitial > ZERO) ? 1 : -1;
 
   /* If this is the first call, loop over all backward problems and
    *   - check that tB0 is valid
@@ -1478,7 +1344,7 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
 
       tBn = tmp_IDAB_mem->IDA_mem->ida_tn;
 
-      if ( (sign*(tBn-tinitial) < ZERO) || (sign*(tfinal-tBn) < ZERO) ) {
+      if ( (sign*(tBn-IDAADJ_mem->ia_tinitial) < ZERO) || (sign*(IDAADJ_mem->ia_tfinal-tBn) < ZERO) ) {
         IDAProcessError(IDA_mem, IDA_BAD_TB0, "IDAA", "IDASolveB", 
                         MSGAM_BAD_TB0, tmp_IDAB_mem->ida_index);
         return(IDA_BAD_TB0);
@@ -1491,18 +1357,19 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
       }
 
       if ( tmp_IDAB_mem->ida_res_withSensi || 
-           tmp_IDAB_mem->ida_rhsQ_withSensi ) interpSensi = TRUE;
+           tmp_IDAB_mem->ida_rhsQ_withSensi )
+        IDAADJ_mem->ia_interpSensi = SUNTRUE;
 
       /* Advance in list. */
       tmp_IDAB_mem = tmp_IDAB_mem->ida_next;      
     }
 
-    if ( interpSensi && !storeSensi) {
+    if ( IDAADJ_mem->ia_interpSensi && !IDAADJ_mem->ia_storeSensi) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveB", MSGAM_BAD_SENSI);
       return(IDA_ILL_INPUT);
     }
 
-    IDAADJ_mem->ia_firstIDABcall = FALSE;
+    IDAADJ_mem->ia_firstIDABcall = SUNFALSE;
   }
 
   /* Check for valid itask */
@@ -1512,10 +1379,11 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
   }
 
   /* Check if tBout is legal */
-  if ( (sign*(tBout-tinitial) < ZERO) || (sign*(tfinal-tBout) < ZERO) ) {
-    tfuzz = HUNDRED*uround*(SUNRabs(tinitial) + SUNRabs(tfinal));
-    if ( (sign*(tBout-tinitial) < ZERO) && (SUNRabs(tBout-tinitial) < tfuzz) ) {
-      tBout = tinitial;
+  if ( (sign*(tBout-IDAADJ_mem->ia_tinitial) < ZERO) || (sign*(IDAADJ_mem->ia_tfinal-tBout) < ZERO) ) {
+    tfuzz = HUNDRED * IDA_mem->ida_uround *
+      (SUNRabs(IDAADJ_mem->ia_tinitial) + SUNRabs(IDAADJ_mem->ia_tfinal));
+    if ( (sign*(tBout-IDAADJ_mem->ia_tinitial) < ZERO) && (SUNRabs(tBout-IDAADJ_mem->ia_tinitial) < tfuzz) ) {
+      tBout = IDAADJ_mem->ia_tinitial;
     } else {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASolveB", MSGAM_BAD_TBOUT);
       return(IDA_ILL_INPUT);
@@ -1528,20 +1396,20 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
 
   ck_mem = IDAADJ_mem->ck_mem;
 
-  gotCkpnt = FALSE;
+  gotCkpnt = SUNFALSE;
 
-  loop {
+  for(;;) {
     tmp_IDAB_mem = IDAB_mem;
     while(tmp_IDAB_mem != NULL) {
       tBn = tmp_IDAB_mem->IDA_mem->ida_tn;
 
-      if ( sign*(tBn-t0_) > ZERO ) {
-        gotCkpnt = TRUE;
+      if ( sign*(tBn-ck_mem->ck_t0) > ZERO ) {
+        gotCkpnt = SUNTRUE;
         break;
       }
 
-      if ( (itaskB == IDA_NORMAL) && (tBn == t0_) && (sign*(tBout-t0_) >= ZERO) ) {
-        gotCkpnt = TRUE;
+      if ( (itaskB == IDA_NORMAL) && (tBn == ck_mem->ck_t0) && (sign*(tBout-ck_mem->ck_t0) >= ZERO) ) {
+        gotCkpnt = SUNTRUE;
         break;
       }
 
@@ -1556,11 +1424,11 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
   }
 
   /* Loop while propagating backward problems */
-  loop {
+  for(;;) {
 
     /* Store interpolation data if not available.
        This is the 2nd forward integration pass */
-    if (ck_mem != ckpntData) {
+    if (ck_mem != IDAADJ_mem->ia_ckpntData) {
 
       flag = IDAAdataStore(IDA_mem, ck_mem);
       if (flag != IDA_SUCCESS) break;
@@ -1573,13 +1441,13 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
     while (tmp_IDAB_mem != NULL) {
 
       /* Decide if current backward problem is "active" in this check point */
-      isActive = TRUE;
+      isActive = SUNTRUE;
 
       tBn = tmp_IDAB_mem->IDA_mem->ida_tn;
 
-      if ( (tBn == t0_) && (sign*(tBout-t0_) < ZERO ) ) isActive = FALSE;
-      if ( (tBn == t0_) && (itaskB == IDA_ONE_STEP) ) isActive = FALSE;
-      if ( sign*(tBn - t0_) < ZERO ) isActive = FALSE;
+      if ( (tBn == ck_mem->ck_t0) && (sign*(tBout-ck_mem->ck_t0) < ZERO ) ) isActive = SUNFALSE;
+      if ( (tBn == ck_mem->ck_t0) && (itaskB == IDA_ONE_STEP) ) isActive = SUNFALSE;
+      if ( sign*(tBn - ck_mem->ck_t0) < ZERO ) isActive = SUNFALSE;
 
       if ( isActive ) {
         /* Store the address of current backward problem memory 
@@ -1587,7 +1455,7 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
         IDAADJ_mem->ia_bckpbCrt = tmp_IDAB_mem;
 
         /* Integrate current backward problem */
-        IDASetStopTime(tmp_IDAB_mem->IDA_mem, t0_);
+        IDASetStopTime(tmp_IDAB_mem->IDA_mem, ck_mem->ck_t0);
         flag = IDASolve(tmp_IDAB_mem->IDA_mem, tBout, &tBret, 
                         tmp_IDAB_mem->ida_yy, tmp_IDAB_mem->ida_yp, 
                         itaskB);
@@ -1619,12 +1487,12 @@ int IDASolveB(void *ida_mem, realtype tBout, int itaskB)
     if (itaskB == IDA_ONE_STEP) break;
 
     /* If all backward problems have succesfully reached tBout, return now */
-    reachedTBout = TRUE;
+    reachedTBout = SUNTRUE;
 
     tmp_IDAB_mem = IDAB_mem;
     while(tmp_IDAB_mem != NULL) {
       if ( sign*(tmp_IDAB_mem->ida_tout - tBout) > ZERO ) {
-        reachedTBout = FALSE;
+        reachedTBout = SUNFALSE;
         break;
       }
       tmp_IDAB_mem = tmp_IDAB_mem->ida_next;
@@ -1663,14 +1531,14 @@ SUNDIALS_EXPORT int IDAGetB(void* ida_mem, int which, realtype *tret,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1717,14 +1585,14 @@ int IDAGetQuadB(void *ida_mem, int which, realtype *tret, N_Vector qB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetQuadB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetQuadB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -1772,23 +1640,23 @@ static CkpntMem IDAAckpntInit(IDAMem IDA_mem)
   ck_mem = (CkpntMem) malloc(sizeof(struct CkpntMemRec));
   if (NULL==ck_mem) return(NULL);
 
-  t0_    = tn;
-  nst_   = 0;
-  kk_    = 1;
-  hh_    = ZERO;
+  ck_mem->ck_t0    = IDA_mem->ida_tn;
+  ck_mem->ck_nst   = 0;
+  ck_mem->ck_kk    = 1;
+  ck_mem->ck_hh    = ZERO;
 
   /* Test if we need to carry quadratures */
-  quadr_ = quadr && errconQ;
+  ck_mem->ck_quadr = IDA_mem->ida_quadr && IDA_mem->ida_errconQ;
 
   /* Test if we need to carry sensitivities */
-  sensi_ = sensi;
-  if(sensi_) Ns_    = Ns;
+  ck_mem->ck_sensi = IDA_mem->ida_sensi;
+  if(ck_mem->ck_sensi) ck_mem->ck_Ns = IDA_mem->ida_Ns;
 
   /* Test if we need to carry quadrature sensitivities */
-  quadr_sensi_ = quadr_sensi && errconQS;
+  ck_mem->ck_quadr_sensi = IDA_mem->ida_quadr_sensi && IDA_mem->ida_errconQS;
 
   /* Alloc 3: current order, i.e. 1,  +   2. */
-  phi_alloc_ = 3;
+  ck_mem->ck_phi_alloc = 3;
   
   if (!IDAAckpntAllocVectors(IDA_mem, ck_mem)) {
     free(ck_mem); ck_mem = NULL;
@@ -1798,7 +1666,7 @@ static CkpntMem IDAAckpntInit(IDAMem IDA_mem)
   IDAAckpntCopyVectors(IDA_mem, ck_mem);
 
   /* Next in list */
-  next_  = NULL;
+  ck_mem->ck_next  = NULL;
 
   return(ck_mem);
 }
@@ -1819,43 +1687,44 @@ static CkpntMem IDAAckpntNew(IDAMem IDA_mem)
   ck_mem = (CkpntMem) malloc(sizeof(struct CkpntMemRec));
   if (ck_mem == NULL) return(NULL);
 
-  nst_       = nst;
-  tretlast_  = tretlast;
-  kk_        = kk;
-  kused_     = kused;
-  knew_      = knew;
-  phase_     = phase;
-  ns_        = ns;
-  hh_        = hh;
-  hused_     = hused;
-  rr_        = rr;
-  cj_        = cj;
-  cjlast_    = cjlast;
-  cjold_     = cjold;
-  cjratio_   = cjratio;
-  ss_        = ss;
-  ssS_       = ssS;
-  t0_        = tn;
+  ck_mem->ck_nst       = IDA_mem->ida_nst;
+  ck_mem->ck_tretlast  = IDA_mem->ida_tretlast;
+  ck_mem->ck_kk        = IDA_mem->ida_kk;
+  ck_mem->ck_kused     = IDA_mem->ida_kused;
+  ck_mem->ck_knew      = IDA_mem->ida_knew;
+  ck_mem->ck_phase     = IDA_mem->ida_phase;
+  ck_mem->ck_ns        = IDA_mem->ida_ns;
+  ck_mem->ck_hh        = IDA_mem->ida_hh;
+  ck_mem->ck_hused     = IDA_mem->ida_hused;
+  ck_mem->ck_rr        = IDA_mem->ida_rr;
+  ck_mem->ck_cj        = IDA_mem->ida_cj;
+  ck_mem->ck_cjlast    = IDA_mem->ida_cjlast;
+  ck_mem->ck_cjold     = IDA_mem->ida_cjold;
+  ck_mem->ck_cjratio   = IDA_mem->ida_cjratio;
+  ck_mem->ck_ss        = IDA_mem->ida_ss;
+  ck_mem->ck_ssS       = IDA_mem->ida_ssS;
+  ck_mem->ck_t0        = IDA_mem->ida_tn;
 
   for (j=0; j<MXORDP1; j++) {
-    psi_[j]   = psi[j];
-    alpha_[j] = alpha[j];
-    beta_[j]  = beta[j];
-    sigma_[j] = sigma[j];
-    gamma_[j] = gamma[j];
+    ck_mem->ck_psi[j]   = IDA_mem->ida_psi[j];
+    ck_mem->ck_alpha[j] = IDA_mem->ida_alpha[j];
+    ck_mem->ck_beta[j]  = IDA_mem->ida_beta[j];
+    ck_mem->ck_sigma[j] = IDA_mem->ida_sigma[j];
+    ck_mem->ck_gamma[j] = IDA_mem->ida_gamma[j];
   }
 
   /* Test if we need to carry quadratures */
-  quadr_ = quadr && errconQ;
+  ck_mem->ck_quadr = IDA_mem->ida_quadr && IDA_mem->ida_errconQ;
 
   /* Test if we need to carry sensitivities */
-  sensi_ = sensi;
-  if(sensi_) Ns_    = Ns;
+  ck_mem->ck_sensi = IDA_mem->ida_sensi;
+  if(ck_mem->ck_sensi) ck_mem->ck_Ns = IDA_mem->ida_Ns;
 
   /* Test if we need to carry quadrature sensitivities */
-  quadr_sensi_ = quadr_sensi && errconQS;
+  ck_mem->ck_quadr_sensi = IDA_mem->ida_quadr_sensi && IDA_mem->ida_errconQS;
 
-  phi_alloc_ =  kk+2 < MXORDP1 ? kk+2 : MXORDP1;
+  ck_mem->ck_phi_alloc = (IDA_mem->ida_kk+2 < MXORDP1) ?
+    IDA_mem->ida_kk+2 : MXORDP1;
 
   if (!IDAAckpntAllocVectors(IDA_mem, ck_mem)) {
     free(ck_mem); ck_mem = NULL;
@@ -1920,67 +1789,75 @@ static booleantype IDAAckpntAllocVectors(IDAMem IDA_mem, CkpntMem ck_mem)
 {
   int j, jj;
 
-  for (j=0; j<phi_alloc_; j++) {
-    phi_[j] = N_VClone(tempv);
-    if(phi_[j] == NULL) {    
-      for(jj=0; jj<j; jj++) N_VDestroy(phi_[jj]);
-      return(FALSE);
+  for (j=0; j<ck_mem->ck_phi_alloc; j++) {
+    ck_mem->ck_phi[j] = N_VClone(IDA_mem->ida_tempv1);
+    if(ck_mem->ck_phi[j] == NULL) {    
+      for(jj=0; jj<j; jj++) N_VDestroy(ck_mem->ck_phi[jj]);
+      return(SUNFALSE);
     }
   }
 
   /* Do we need to carry quadratures? */
-  if(quadr_) {
-    for (j=0; j<phi_alloc_; j++) {
-      phiQ_[j] = N_VClone(tempvQ);
-      if(phiQ_[j] == NULL)  {        
-        for (jj=0; jj<j; jj++) N_VDestroy(phiQ_[jj]);
+  if(ck_mem->ck_quadr) {
+    for (j=0; j<ck_mem->ck_phi_alloc; j++) {
+      ck_mem->ck_phiQ[j] = N_VClone(IDA_mem->ida_eeQ);
+      if(ck_mem->ck_phiQ[j] == NULL)  {        
+        for (jj=0; jj<j; jj++) N_VDestroy(ck_mem->ck_phiQ[jj]);
 
-        for(jj=0; jj<phi_alloc_; jj++) N_VDestroy(phi_[jj]);
+        for(jj=0; jj<ck_mem->ck_phi_alloc; jj++)
+          N_VDestroy(ck_mem->ck_phi[jj]);
 
-        return(FALSE);
+        return(SUNFALSE);
       }
     }
   }
 
   /* Do we need to carry sensitivities? */
-  if(sensi_) {
+  if(ck_mem->ck_sensi) {
 
-    for (j=0; j<phi_alloc_; j++) {
-      phiS_[j] = N_VCloneVectorArray(Ns, tempv);
-      if (phiS_[j] == NULL) {
-        for (jj=0; jj<j; jj++) N_VDestroyVectorArray(phiS_[jj], Ns);
+    for (j=0; j<ck_mem->ck_phi_alloc; j++) {
+      ck_mem->ck_phiS[j] = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
+      if (ck_mem->ck_phiS[j] == NULL) {
+        for (jj=0; jj<j; jj++)
+          N_VDestroyVectorArray(ck_mem->ck_phiS[jj], IDA_mem->ida_Ns);
 
-        if (quadr_)
-          for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phiQ_[jj]);
+        if (ck_mem->ck_quadr)
+          for (jj=0; jj<ck_mem->ck_phi_alloc; jj++)
+            N_VDestroy(ck_mem->ck_phiQ[jj]);
 
-        for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phi_[jj]);
+        for (jj=0; jj<ck_mem->ck_phi_alloc; jj++)
+          N_VDestroy(ck_mem->ck_phi[jj]);
 
-        return(FALSE);
+        return(SUNFALSE);
       }
     }
   }
 
   /* Do we need to carry quadrature sensitivities? */
-  if (quadr_sensi_) {
+  if (ck_mem->ck_quadr_sensi) {
 
-    for (j=0; j<phi_alloc_; j++) {
-      phiQS_[j] = N_VCloneVectorArray(Ns, tempvQ);
-      if (phiQS_[j] == NULL) {
+    for (j=0; j<ck_mem->ck_phi_alloc; j++) {
+      ck_mem->ck_phiQS[j] = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_eeQ);
+      if (ck_mem->ck_phiQS[j] == NULL) {
 
-        for (jj=0; jj<j; jj++) N_VDestroyVectorArray(phiQS_[jj], Ns);
+        for (jj=0; jj<j; jj++)
+          N_VDestroyVectorArray(ck_mem->ck_phiQS[jj], IDA_mem->ida_Ns);
 
-        for (jj=0; jj<phi_alloc_; jj++) N_VDestroyVectorArray(phiS_[jj], Ns);
+        for (jj=0; jj<ck_mem->ck_phi_alloc; jj++)
+          N_VDestroyVectorArray(ck_mem->ck_phiS[jj], IDA_mem->ida_Ns);
 
-        if (quadr_) 
-          for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phiQ_[jj]);
+        if (ck_mem->ck_quadr) 
+          for (jj=0; jj<ck_mem->ck_phi_alloc; jj++)
+            N_VDestroy(ck_mem->ck_phiQ[jj]);
 
-        for (jj=0; jj<phi_alloc_; jj++) N_VDestroy(phi_[jj]);
+        for (jj=0; jj<ck_mem->ck_phi_alloc; jj++)
+          N_VDestroy(ck_mem->ck_phi[jj]);
 
-        return(FALSE);
+        return(SUNFALSE);
       }
     }
   }
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /* 
@@ -1995,22 +1872,24 @@ static void IDAAckpntCopyVectors(IDAMem IDA_mem, CkpntMem ck_mem)
 
   /* Save phi* arrays from IDA_mem */
 
-  for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phi[j], phi_[j]);
+  for (j=0; j<ck_mem->ck_phi_alloc; j++)
+    N_VScale(ONE, IDA_mem->ida_phi[j], ck_mem->ck_phi[j]);
 
-  if (quadr_) {
-    for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phiQ[j], phiQ_[j]);
+  if (ck_mem->ck_quadr) {
+    for (j=0; j<ck_mem->ck_phi_alloc; j++)
+      N_VScale(ONE, IDA_mem->ida_phiQ[j], ck_mem->ck_phiQ[j]);
   }
 
-  if (sensi_) {
-    for (is=0; is<Ns; is++)
-      for (j=0; j<phi_alloc_; j++) 
-        N_VScale(ONE, phiS[j][is], phiS_[j][is]);
+  if (ck_mem->ck_sensi) {
+    for (is=0; is<IDA_mem->ida_Ns; is++)
+      for (j=0; j<ck_mem->ck_phi_alloc; j++) 
+        N_VScale(ONE, IDA_mem->ida_phiS[j][is], ck_mem->ck_phiS[j][is]);
   }
 
-  if(quadr_sensi_) {
-    for (is=0; is<Ns; is++)
-      for (j=0; j<phi_alloc_; j++) 
-        N_VScale(ONE, phiQS[j][is], phiQS_[j][is]);
+  if(ck_mem->ck_quadr_sensi) {
+    for (is=0; is<IDA_mem->ida_Ns; is++)
+      for (j=0; j<ck_mem->ck_phi_alloc; j++) 
+        N_VScale(ONE, IDA_mem->ida_phiQS[j][is], ck_mem->ck_phiQS[j][is]);
 
   }
 }
@@ -2033,10 +1912,10 @@ static booleantype IDAAdataMalloc(IDAMem IDA_mem)
   IDAADJ_mem = IDA_mem->ida_adj_mem;
   IDAADJ_mem->dt_mem = NULL;
 
-  dt_mem = (DtpntMem *)malloc((nsteps+1)*sizeof(struct DtpntMemRec *));
-  if (dt_mem==NULL) return(FALSE);
+  dt_mem = (DtpntMem *)malloc((IDAADJ_mem->ia_nsteps+1)*sizeof(struct DtpntMemRec *));
+  if (dt_mem==NULL) return(SUNFALSE);
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=IDAADJ_mem->ia_nsteps; i++) {
     
     dt_mem[i] = (DtpntMem)malloc(sizeof(struct DtpntMemRec));
     
@@ -2047,13 +1926,13 @@ static booleantype IDAAdataMalloc(IDAMem IDA_mem)
         free(dt_mem[j]);
 
       free(dt_mem);
-      return(FALSE);
+      return(SUNFALSE);
     }
     dt_mem[i]->content = NULL;
   }
   /* Attach the allocated dt_mem to IDAADJ_mem. */
   IDAADJ_mem->dt_mem = dt_mem;
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -2074,7 +1953,7 @@ static void IDAAdataFree(IDAMem IDA_mem)
   /* Destroy data points by calling the interpolation's 'free' routine. */
   IDAADJ_mem->ia_free(IDA_mem);
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=IDAADJ_mem->ia_nsteps; i++) {
      free(IDAADJ_mem->dt_mem[i]);
      IDAADJ_mem->dt_mem[i] = NULL;
   }
@@ -2114,7 +1993,7 @@ static int IDAAdataStore(IDAMem IDA_mem, CkpntMem ck_mem)
     return(IDA_REIFWD_FAIL);
 
   /* Set first structure in dt_mem[0] */
-  dt_mem[0]->t = t0_;
+  dt_mem[0]->t = ck_mem->ck_t0;
   IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[0]);
 
   /* Decide whether TSTOP must be activated */
@@ -2122,25 +2001,26 @@ static int IDAAdataStore(IDAMem IDA_mem, CkpntMem ck_mem)
     IDASetStopTime(IDA_mem, IDAADJ_mem->ia_tstopIDAF);
   }
 
-  sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+  sign = (IDAADJ_mem->ia_tfinal - IDAADJ_mem->ia_tinitial > ZERO) ? 1 : -1;
 
   /* Run IDASolve in IDA_ONE_STEP mode to set following structures in dt_mem[i]. */
   i = 1;
   do {
 
-    flag = IDASolve(IDA_mem, t1_, &t, yyTmp, ypTmp, IDA_ONE_STEP);
+    flag = IDASolve(IDA_mem, ck_mem->ck_t1, &t, IDAADJ_mem->ia_yyTmp,
+                    IDAADJ_mem->ia_ypTmp, IDA_ONE_STEP);
     if (flag < 0) return(IDA_FWD_FAIL);
 
     dt_mem[i]->t = t;
     IDAADJ_mem->ia_storePnt(IDA_mem, dt_mem[i]);
 
     i++;
-  } while ( sign*(t1_ - t) > ZERO );
+  } while ( sign*(ck_mem->ck_t1 - t) > ZERO );
 
   /* New data is now available. */
-  ckpntData = ck_mem;
-  newData = TRUE;
-  np  = i;
+  IDAADJ_mem->ia_ckpntData = ck_mem;
+  IDAADJ_mem->ia_newData = SUNTRUE;
+  IDAADJ_mem->ia_np  = i;
 
   return(IDA_SUCCESS);
 }
@@ -2156,83 +2036,87 @@ static int IDAAckpntGet(IDAMem IDA_mem, CkpntMem ck_mem)
 {
   int flag, j, is;
 
-  if (next_ == NULL) {
+  if (ck_mem->ck_next == NULL) {
 
     /* In this case, we just call the reinitialization routine,
      * but make sure we use the same initial stepsize as on 
      * the first run. */
 
-    IDASetInitStep(IDA_mem, h0u);
+    IDASetInitStep(IDA_mem, IDA_mem->ida_h0u);
 
-    flag = IDAReInit(IDA_mem, t0_, phi_[0], phi_[1]);
+    flag = IDAReInit(IDA_mem, ck_mem->ck_t0, ck_mem->ck_phi[0], ck_mem->ck_phi[1]);
     if (flag != IDA_SUCCESS) return(flag);
 
-    if (quadr_) {
-      flag = IDAQuadReInit(IDA_mem, phiQ_[0]);
+    if (ck_mem->ck_quadr) {
+      flag = IDAQuadReInit(IDA_mem, ck_mem->ck_phiQ[0]);
       if (flag != IDA_SUCCESS) return(flag);
     }
 
-    if (sensi_) {
-      flag = IDASensReInit(IDA_mem, IDA_mem->ida_ism, phiS_[0], phiS_[1]);
+    if (ck_mem->ck_sensi) {
+      flag = IDASensReInit(IDA_mem, IDA_mem->ida_ism, ck_mem->ck_phiS[0], ck_mem->ck_phiS[1]);
       if (flag != IDA_SUCCESS) return(flag);
     }
 
-    if (quadr_sensi_) {
-      flag = IDAQuadSensReInit(IDA_mem, phiQS_[0]);
+    if (ck_mem->ck_quadr_sensi) {
+      flag = IDAQuadSensReInit(IDA_mem, ck_mem->ck_phiQS[0]);
       if (flag != IDA_SUCCESS) return(flag);
     }
 
   } else {
 
     /* Copy parameters from check point data structure */
-    nst       = nst_;
-    tretlast  = tretlast_;
-    kk        = kk_;
-    kused     = kused_;
-    knew      = knew_;
-    phase     = phase_;
-    ns        = ns_;
-    hh        = hh_;
-    hused     = hused_;
-    rr        = rr_;
-    cj        = cj_;
-    cjlast    = cjlast_;
-    cjold     = cjold_;
-    cjratio   = cjratio_;
-    tn        = t0_;
-    ss        = ss_;
-    ssS       = ssS_;
+    IDA_mem->ida_nst       = ck_mem->ck_nst;
+    IDA_mem->ida_tretlast  = ck_mem->ck_tretlast;
+    IDA_mem->ida_kk        = ck_mem->ck_kk;
+    IDA_mem->ida_kused     = ck_mem->ck_kused;
+    IDA_mem->ida_knew      = ck_mem->ck_knew;
+    IDA_mem->ida_phase     = ck_mem->ck_phase;
+    IDA_mem->ida_ns        = ck_mem->ck_ns;
+    IDA_mem->ida_hh        = ck_mem->ck_hh;
+    IDA_mem->ida_hused     = ck_mem->ck_hused;
+    IDA_mem->ida_rr        = ck_mem->ck_rr;
+    IDA_mem->ida_cj        = ck_mem->ck_cj;
+    IDA_mem->ida_cjlast    = ck_mem->ck_cjlast;
+    IDA_mem->ida_cjold     = ck_mem->ck_cjold;
+    IDA_mem->ida_cjratio   = ck_mem->ck_cjratio;
+    IDA_mem->ida_tn        = ck_mem->ck_t0;
+    IDA_mem->ida_ss        = ck_mem->ck_ss;
+    IDA_mem->ida_ssS       = ck_mem->ck_ssS;
 
     
     /* Copy the arrays from check point data structure */
-    for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phi_[j], phi[j]);
+    for (j=0; j<ck_mem->ck_phi_alloc; j++)
+      N_VScale(ONE, ck_mem->ck_phi[j], IDA_mem->ida_phi[j]);
 
-    if(quadr_) {
-      for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phiQ_[j], phiQ[j]);
+    if(ck_mem->ck_quadr) {
+      for (j=0; j<ck_mem->ck_phi_alloc; j++)
+        N_VScale(ONE, ck_mem->ck_phiQ[j], IDA_mem->ida_phiQ[j]);
     }
 
-    if (sensi_) {
-      for (is=0; is<Ns; is++) {
-        for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phiS_[j][is], phiS[j][is]);
+    if (ck_mem->ck_sensi) {
+      for (is=0; is<IDA_mem->ida_Ns; is++) {
+        for (j=0; j<ck_mem->ck_phi_alloc; j++)
+          N_VScale(ONE, ck_mem->ck_phiS[j][is], IDA_mem->ida_phiS[j][is]);
       }
     }
 
-    if (quadr_sensi_) {
-      for (is=0; is<Ns; is++) {
-        for (j=0; j<phi_alloc_; j++) N_VScale(ONE, phiQS_[j][is], phiQS[j][is]);
+    if (ck_mem->ck_quadr_sensi) {
+      for (is=0; is<IDA_mem->ida_Ns; is++) {
+        for (j=0; j<ck_mem->ck_phi_alloc; j++)
+          N_VScale(ONE, ck_mem->ck_phiQS[j][is], IDA_mem->ida_phiQS[j][is]);
       }
     }
 
     for (j=0; j<MXORDP1; j++) {
-      psi[j]   = psi_[j];
-      alpha[j] = alpha_[j];
-      beta[j]  = beta_[j];
-      sigma[j] = sigma_[j];
-      gamma[j] = gamma_[j];
+      IDA_mem->ida_psi[j]   = ck_mem->ck_psi[j];
+      IDA_mem->ida_alpha[j] = ck_mem->ck_alpha[j];
+      IDA_mem->ida_beta[j]  = ck_mem->ck_beta[j];
+      IDA_mem->ida_sigma[j] = ck_mem->ck_sigma[j];
+      IDA_mem->ida_gamma[j] = ck_mem->ck_gamma[j];
     }
 
     /* Force a call to setup */
-    forceSetup = TRUE;
+    IDA_mem->ida_forceSetup = SUNTRUE;
   }
 
   return(IDA_SUCCESS);
@@ -2262,36 +2146,36 @@ static booleantype IDAAhermiteMalloc(IDAMem IDA_mem)
   long int i, ii=0;
   booleantype allocOK;
 
-  allocOK = TRUE;
+  allocOK = SUNTRUE;
 
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Allocate space for the vectors yyTmp and ypTmp. */
-  yyTmp = N_VClone(tempv);
-  if (yyTmp == NULL) {
-    return(FALSE);
+  IDAADJ_mem->ia_yyTmp = N_VClone(IDA_mem->ida_tempv1);
+  if (IDAADJ_mem->ia_yyTmp == NULL) {
+    return(SUNFALSE);
   }
-  ypTmp = N_VClone(tempv);
-  if (ypTmp == NULL) {
-    return(FALSE);
+  IDAADJ_mem->ia_ypTmp = N_VClone(IDA_mem->ida_tempv1);
+  if (IDAADJ_mem->ia_ypTmp == NULL) {
+    return(SUNFALSE);
   }
 
   /* Allocate space for sensitivities temporary vectors. */
-  if (storeSensi) {
+  if (IDAADJ_mem->ia_storeSensi) {
     
-    yySTmp = N_VCloneVectorArray(Ns, tempv);
-    if (yySTmp == NULL) {
-      N_VDestroy(yyTmp);
-      N_VDestroy(ypTmp);
-      return(FALSE);
+    IDAADJ_mem->ia_yySTmp = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
+    if (IDAADJ_mem->ia_yySTmp == NULL) {
+      N_VDestroy(IDAADJ_mem->ia_yyTmp);
+      N_VDestroy(IDAADJ_mem->ia_ypTmp);
+      return(SUNFALSE);
     }
 
-    ypSTmp = N_VCloneVectorArray(Ns, tempv);
-    if (ypSTmp == NULL) {
-      N_VDestroy(yyTmp);
-      N_VDestroy(ypTmp);
-      N_VDestroyVectorArray(yySTmp, Ns);
-      return(FALSE);
+    IDAADJ_mem->ia_ypSTmp = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
+    if (IDAADJ_mem->ia_ypSTmp == NULL) {
+      N_VDestroy(IDAADJ_mem->ia_yyTmp);
+      N_VDestroy(IDAADJ_mem->ia_ypTmp);
+      N_VDestroyVectorArray(IDAADJ_mem->ia_yySTmp, IDA_mem->ida_Ns);
+      return(SUNFALSE);
 
     }
   }
@@ -2300,53 +2184,53 @@ static booleantype IDAAhermiteMalloc(IDAMem IDA_mem)
 
   dt_mem = IDAADJ_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=IDAADJ_mem->ia_nsteps; i++) {
 
     content = NULL;
     content = (HermiteDataMem) malloc(sizeof(struct HermiteDataMemRec));
     if (content == NULL) {
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    content->y = N_VClone(tempv);
+    content->y = N_VClone(IDA_mem->ida_tempv1);
     if (content->y == NULL) {
       free(content); content = NULL;
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    content->yd = N_VClone(tempv);
+    content->yd = N_VClone(IDA_mem->ida_tempv1);
     if (content->yd == NULL) {
       N_VDestroy(content->y);
       free(content); content = NULL;
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    if (storeSensi) {
+    if (IDAADJ_mem->ia_storeSensi) {
       
-      content->yS = N_VCloneVectorArray(Ns, tempv);
+      content->yS = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
       if (content->yS == NULL) {
         N_VDestroy(content->y);
         N_VDestroy(content->yd);
         free(content); content = NULL;
         ii = i;
-        allocOK = FALSE;
+        allocOK = SUNFALSE;
         break;
       }
 
-      content->ySd = N_VCloneVectorArray(Ns, tempv);
+      content->ySd = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
       if (content->ySd == NULL) {
         N_VDestroy(content->y);
         N_VDestroy(content->yd);
-        N_VDestroyVectorArray(content->yS, Ns);
+        N_VDestroyVectorArray(content->yS, IDA_mem->ida_Ns);
         free(content); content = NULL;
         ii = i;
-        allocOK = FALSE;
+        allocOK = SUNFALSE;
         break;
       }
     }
@@ -2359,12 +2243,12 @@ static booleantype IDAAhermiteMalloc(IDAMem IDA_mem)
 
   if (!allocOK) {
 
-    N_VDestroy(yyTmp);
-    N_VDestroy(ypTmp);  
+    N_VDestroy(IDAADJ_mem->ia_yyTmp);
+    N_VDestroy(IDAADJ_mem->ia_ypTmp);  
 
-    if (storeSensi) {     
-      N_VDestroyVectorArray(yySTmp, Ns);
-      N_VDestroyVectorArray(ypSTmp, Ns);
+    if (IDAADJ_mem->ia_storeSensi) {     
+      N_VDestroyVectorArray(IDAADJ_mem->ia_yySTmp, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDAADJ_mem->ia_ypSTmp, IDA_mem->ida_Ns);
     }
 
     for (i=0; i<ii; i++) {
@@ -2372,9 +2256,9 @@ static booleantype IDAAhermiteMalloc(IDAMem IDA_mem)
       N_VDestroy(content->y);
       N_VDestroy(content->yd);
 
-      if (storeSensi) {
-        N_VDestroyVectorArray(content->yS, Ns);
-        N_VDestroyVectorArray(content->ySd, Ns);        
+      if (IDAADJ_mem->ia_storeSensi) {
+        N_VDestroyVectorArray(content->yS, IDA_mem->ida_Ns);
+        N_VDestroyVectorArray(content->ySd, IDA_mem->ida_Ns);        
       }
 
       free(dt_mem[i]->content); dt_mem[i]->content = NULL;
@@ -2400,17 +2284,17 @@ static void IDAAhermiteFree(IDAMem IDA_mem)
 
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
-  N_VDestroy(yyTmp);
-  N_VDestroy(ypTmp);
+  N_VDestroy(IDAADJ_mem->ia_yyTmp);
+  N_VDestroy(IDAADJ_mem->ia_ypTmp);
 
-  if (storeSensi) {    
-    N_VDestroyVectorArray(yySTmp, Ns);
-    N_VDestroyVectorArray(ypSTmp, Ns);
+  if (IDAADJ_mem->ia_storeSensi) {    
+    N_VDestroyVectorArray(IDAADJ_mem->ia_yySTmp, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDAADJ_mem->ia_ypSTmp, IDA_mem->ida_Ns);
   }
 
   dt_mem = IDAADJ_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=IDAADJ_mem->ia_nsteps; i++) {
 
     content = (HermiteDataMem) (dt_mem[i]->content);
     /* content might be NULL, if IDAAdjInit was called but IDASolveF was not. */
@@ -2419,9 +2303,9 @@ static void IDAAhermiteFree(IDAMem IDA_mem)
       N_VDestroy(content->y);
       N_VDestroy(content->yd);
 
-      if (storeSensi) {
-        N_VDestroyVectorArray(content->yS, Ns);
-        N_VDestroyVectorArray(content->ySd, Ns);      
+      if (IDAADJ_mem->ia_storeSensi) {
+        N_VDestroyVectorArray(content->yS, IDA_mem->ida_Ns);
+        N_VDestroyVectorArray(content->ySd, IDA_mem->ida_Ns);      
       }
       free(dt_mem[i]->content); 
       dt_mem[i]->content = NULL;
@@ -2448,17 +2332,17 @@ static int IDAAhermiteStorePnt(IDAMem IDA_mem, DtpntMem d)
   content = (HermiteDataMem) d->content;
 
   /* Load solution(s) */
-  N_VScale(ONE, phi[0], content->y);
+  N_VScale(ONE, IDA_mem->ida_phi[0], content->y);
   
-  if (storeSensi) {
-    for (is=0; is<Ns; is++) 
-      N_VScale(ONE, phiS[0][is], content->yS[is]);
+  if (IDAADJ_mem->ia_storeSensi) {
+    for (is=0; is<IDA_mem->ida_Ns; is++) 
+      N_VScale(ONE, IDA_mem->ida_phiS[0][is], content->yS[is]);
   }
 
   /* Load derivative(s). */
   IDAAGettnSolutionYp(IDA_mem, content->yd);
 
-  if (storeSensi) {
+  if (IDAADJ_mem->ia_storeSensi) {
     IDAAGettnSolutionYpS(IDA_mem, content->ySd);
   }
 
@@ -2499,7 +2383,7 @@ static int IDAAhermiteGetY(IDAMem IDA_mem, realtype t,
   dt_mem = IDAADJ_mem->dt_mem;
  
   /* Local value of Ns */
-  NS = (interpSensi && (yyS != NULL)) ? Ns : 0;
+  NS = (IDAADJ_mem->ia_interpSensi && (yyS != NULL)) ? IDA_mem->ida_Ns : 0;
 
   /* Get the index in dt_mem */
   flag = IDAAfindIndex(IDA_mem, t, &indx, &newpoint);
@@ -2528,7 +2412,7 @@ static int IDAAhermiteGetY(IDAMem IDA_mem, realtype t,
   content0 = (HermiteDataMem) (dt_mem[indx-1]->content);
   y0  = content0->y;
   yd0 = content0->yd;
-  if (interpSensi) {
+  if (IDAADJ_mem->ia_interpSensi) {
     yS0  = content0->yS;
     ySd0 = content0->ySd;
   }
@@ -2541,20 +2425,20 @@ static int IDAAhermiteGetY(IDAMem IDA_mem, realtype t,
     y1  = content1->y;
     yd1 = content1->yd;
 
-    N_VLinearSum(ONE, y1, -ONE, y0, Y[0]);
-    N_VLinearSum(ONE, yd1,  ONE, yd0, Y[1]);
-    N_VLinearSum(delta, Y[1], -TWO, Y[0], Y[1]);
-    N_VLinearSum(ONE, Y[0], -delta, yd0, Y[0]);
+    N_VLinearSum(ONE, y1, -ONE, y0, IDAADJ_mem->ia_Y[0]);
+    N_VLinearSum(ONE, yd1,  ONE, yd0, IDAADJ_mem->ia_Y[1]);
+    N_VLinearSum(delta, IDAADJ_mem->ia_Y[1], -TWO, IDAADJ_mem->ia_Y[0], IDAADJ_mem->ia_Y[1]);
+    N_VLinearSum(ONE, IDAADJ_mem->ia_Y[0], -delta, yd0, IDAADJ_mem->ia_Y[0]);
 
 
     yS1  = content1->yS;
     ySd1 = content1->ySd;
       
     for (is=0; is<NS; is++) {
-      N_VLinearSum(ONE, yS1[is], -ONE, yS0[is], YS[0][is]);
-      N_VLinearSum(ONE, ySd1[is],  ONE, ySd0[is], YS[1][is]);
-      N_VLinearSum(delta, YS[1][is], -TWO, YS[0][is], YS[1][is]);
-      N_VLinearSum(ONE, YS[0][is], -delta, ySd0[is], YS[0][is]);
+      N_VLinearSum(ONE, yS1[is], -ONE, yS0[is], IDAADJ_mem->ia_YS[0][is]);
+      N_VLinearSum(ONE, ySd1[is],  ONE, ySd0[is], IDAADJ_mem->ia_YS[1][is]);
+      N_VLinearSum(delta, IDAADJ_mem->ia_YS[1][is], -TWO, IDAADJ_mem->ia_YS[0][is], IDAADJ_mem->ia_YS[1][is]);
+      N_VLinearSum(ONE, IDAADJ_mem->ia_YS[0][is], -delta, ySd0[is], IDAADJ_mem->ia_YS[0][is]);
     }
 
   }
@@ -2570,14 +2454,14 @@ static int IDAAhermiteGetY(IDAMem IDA_mem, realtype t,
   factor3 = factor2*(t-t1)/delta;
 
   N_VLinearSum(ONE, y0, factor1, yd0, yy);
-  N_VLinearSum(ONE, yy, factor2, Y[0], yy);
-  N_VLinearSum(ONE, yy, factor3, Y[1], yy);
+  N_VLinearSum(ONE, yy, factor2, IDAADJ_mem->ia_Y[0], yy);
+  N_VLinearSum(ONE, yy, factor3, IDAADJ_mem->ia_Y[1], yy);
 
   /* Sensi Interpolation. */
   for (is=0; is<NS; is++) {
     N_VLinearSum(ONE, yS0[is], factor1, ySd0[is], yyS[is]);
-    N_VLinearSum(ONE, yyS[is], factor2, YS[0][is], yyS[is]);
-    N_VLinearSum(ONE, yyS[is], factor3, YS[1][is], yyS[is]);
+    N_VLinearSum(ONE, yyS[is], factor2, IDAADJ_mem->ia_YS[0][is], yyS[is]);
+    N_VLinearSum(ONE, yyS[is], factor3, IDAADJ_mem->ia_YS[1][is], yyS[is]);
   }
 
   /*For y'. */
@@ -2585,13 +2469,13 @@ static int IDAAhermiteGetY(IDAMem IDA_mem, realtype t,
   factor2 = factor1*((3*t-2*t1-t0)/delta); /* factor2 = (t-t0)(3*t-2*t1-t0)/(t1-t0)^3 */
   factor1 *= 2;
 
-  N_VLinearSum(ONE, yd0, factor1, Y[0], yp);
-  N_VLinearSum(ONE, yp,  factor2, Y[1], yp);
+  N_VLinearSum(ONE, yd0, factor1, IDAADJ_mem->ia_Y[0], yp);
+  N_VLinearSum(ONE, yp,  factor2, IDAADJ_mem->ia_Y[1], yp);
                                             
   /* Sensi interpolation for 1st derivative. */
   for (is=0; is<NS; is++) {
-    N_VLinearSum(ONE, ySd0[is], factor1, YS[0][is], ypS[is]);
-    N_VLinearSum(ONE, ypS[is],  factor2, YS[1][is], ypS[is]);    
+    N_VLinearSum(ONE, ySd0[is], factor1, IDAADJ_mem->ia_YS[0][is], ypS[is]);
+    N_VLinearSum(ONE, ypS[is],  factor2, IDAADJ_mem->ia_YS[1][is], ypS[is]);    
   }
 
   return(IDA_SUCCESS);
@@ -2623,35 +2507,35 @@ static booleantype IDAApolynomialMalloc(IDAMem IDA_mem)
   long int i, ii=0;
   booleantype allocOK;
 
-  allocOK = TRUE;
+  allocOK = SUNTRUE;
 
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Allocate space for the vectors yyTmp and ypTmp */
-  yyTmp = N_VClone(tempv);
-  if (yyTmp == NULL) {
-    return(FALSE);
+  IDAADJ_mem->ia_yyTmp = N_VClone(IDA_mem->ida_tempv1);
+  if (IDAADJ_mem->ia_yyTmp == NULL) {
+    return(SUNFALSE);
   }
-  ypTmp = N_VClone(tempv);
-  if (ypTmp == NULL) {
-    return(FALSE);
+  IDAADJ_mem->ia_ypTmp = N_VClone(IDA_mem->ida_tempv1);
+  if (IDAADJ_mem->ia_ypTmp == NULL) {
+    return(SUNFALSE);
   }
 
-  if (storeSensi) {
+  if (IDAADJ_mem->ia_storeSensi) {
     
-    yySTmp = N_VCloneVectorArray(Ns, tempv);
-    if (yySTmp == NULL) {
-      N_VDestroy(yyTmp);
-      N_VDestroy(ypTmp);
-      return(FALSE);
+    IDAADJ_mem->ia_yySTmp = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
+    if (IDAADJ_mem->ia_yySTmp == NULL) {
+      N_VDestroy(IDAADJ_mem->ia_yyTmp);
+      N_VDestroy(IDAADJ_mem->ia_ypTmp);
+      return(SUNFALSE);
     }
 
-    ypSTmp = N_VCloneVectorArray(Ns, tempv);
-    if (ypSTmp == NULL) {
-      N_VDestroy(yyTmp);
-      N_VDestroy(ypTmp);
-      N_VDestroyVectorArray(yySTmp, Ns);
-      return(FALSE);
+    IDAADJ_mem->ia_ypSTmp = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
+    if (IDAADJ_mem->ia_ypSTmp == NULL) {
+      N_VDestroy(IDAADJ_mem->ia_yyTmp);
+      N_VDestroy(IDAADJ_mem->ia_ypTmp);
+      N_VDestroyVectorArray(IDAADJ_mem->ia_yySTmp, IDA_mem->ida_Ns);
+      return(SUNFALSE);
 
     }
   }
@@ -2659,61 +2543,61 @@ static booleantype IDAApolynomialMalloc(IDAMem IDA_mem)
   /* Allocate space for the content field of the dt structures */
   dt_mem = IDAADJ_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=IDAADJ_mem->ia_nsteps; i++) {
 
     content = NULL;
     content = (PolynomialDataMem) malloc(sizeof(struct PolynomialDataMemRec));
     if (content == NULL) {
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
-    content->y = N_VClone(tempv);
+    content->y = N_VClone(IDA_mem->ida_tempv1);
     if (content->y == NULL) {
       free(content); content = NULL;
       ii = i;
-      allocOK = FALSE;
+      allocOK = SUNFALSE;
       break;
     }
 
     /* Allocate space for yp also. Needed for the most left point interpolation. */
     if (i == 0) {
-      content->yd = N_VClone(tempv);
+      content->yd = N_VClone(IDA_mem->ida_tempv1);
       
       /* Memory allocation failure ? */
       if (content->yd == NULL) {
         N_VDestroy(content->y);
         free(content); content = NULL;
         ii = i;
-        allocOK = FALSE;
+        allocOK = SUNFALSE;
       }
     } else {
       /* Not the first data point. */
       content->yd = NULL;
     }
 
-    if (storeSensi) {
+    if (IDAADJ_mem->ia_storeSensi) {
       
-      content->yS = N_VCloneVectorArray(Ns, tempv);
+      content->yS = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
       if (content->yS == NULL) {
         N_VDestroy(content->y);
         if (content->yd) N_VDestroy(content->yd);
         free(content); content = NULL;
         ii = i;
-        allocOK = FALSE;
+        allocOK = SUNFALSE;
         break;
       }
       
       if (i==0) {
-        content->ySd = N_VCloneVectorArray(Ns, tempv);
+        content->ySd = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
         if (content->ySd == NULL) {
           N_VDestroy(content->y);
           if (content->yd) N_VDestroy(content->yd);
-          N_VDestroyVectorArray(content->yS, Ns);
+          N_VDestroyVectorArray(content->yS, IDA_mem->ida_Ns);
           free(content); content = NULL;
           ii = i;
-          allocOK = FALSE;
+          allocOK = SUNFALSE;
         }
       } else {
         content->ySd = NULL;
@@ -2726,12 +2610,12 @@ static booleantype IDAApolynomialMalloc(IDAMem IDA_mem)
   /* If an error occurred, deallocate and return */
   if (!allocOK) {
 
-    N_VDestroy(yyTmp);
-    N_VDestroy(ypTmp);
-    if (storeSensi) {
+    N_VDestroy(IDAADJ_mem->ia_yyTmp);
+    N_VDestroy(IDAADJ_mem->ia_ypTmp);
+    if (IDAADJ_mem->ia_storeSensi) {
 
-        N_VDestroyVectorArray(yySTmp, Ns);
-        N_VDestroyVectorArray(ypSTmp, Ns);      
+        N_VDestroyVectorArray(IDAADJ_mem->ia_yySTmp, IDA_mem->ida_Ns);
+        N_VDestroyVectorArray(IDAADJ_mem->ia_ypSTmp, IDA_mem->ida_Ns);      
     }
 
     for (i=0; i<ii; i++) {
@@ -2740,12 +2624,12 @@ static booleantype IDAApolynomialMalloc(IDAMem IDA_mem)
 
       if (content->yd) N_VDestroy(content->yd);
 
-      if (storeSensi) {
+      if (IDAADJ_mem->ia_storeSensi) {
         
-          N_VDestroyVectorArray(content->yS, Ns);
+          N_VDestroyVectorArray(content->yS, IDA_mem->ida_Ns);
         
           if (content->ySd)
-            N_VDestroyVectorArray(content->ySd, Ns);
+            N_VDestroyVectorArray(content->ySd, IDA_mem->ida_Ns);
       }
       free(dt_mem[i]->content); dt_mem[i]->content = NULL;
     }
@@ -2769,17 +2653,17 @@ static void IDAApolynomialFree(IDAMem IDA_mem)
 
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
-  N_VDestroy(yyTmp);
-  N_VDestroy(ypTmp);
+  N_VDestroy(IDAADJ_mem->ia_yyTmp);
+  N_VDestroy(IDAADJ_mem->ia_ypTmp);
 
-  if (storeSensi) {
-    N_VDestroyVectorArray(yySTmp, Ns);
-    N_VDestroyVectorArray(ypSTmp, Ns);
+  if (IDAADJ_mem->ia_storeSensi) {
+    N_VDestroyVectorArray(IDAADJ_mem->ia_yySTmp, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDAADJ_mem->ia_ypSTmp, IDA_mem->ida_Ns);
   }
 
   dt_mem = IDAADJ_mem->dt_mem;
 
-  for (i=0; i<=nsteps; i++) {
+  for (i=0; i<=IDAADJ_mem->ia_nsteps; i++) {
 
     content = (PolynomialDataMem) (dt_mem[i]->content);
 
@@ -2789,12 +2673,12 @@ static void IDAApolynomialFree(IDAMem IDA_mem)
 
       if (content->yd) N_VDestroy(content->yd);
 
-      if (storeSensi) {
+      if (IDAADJ_mem->ia_storeSensi) {
         
-        N_VDestroyVectorArray(content->yS, Ns);
+        N_VDestroyVectorArray(content->yS, IDA_mem->ida_Ns);
         
         if (content->ySd)
-          N_VDestroyVectorArray(content->ySd, Ns);
+          N_VDestroyVectorArray(content->ySd, IDA_mem->ida_Ns);
       }
       free(dt_mem[i]->content); dt_mem[i]->content = NULL;
     }
@@ -2821,24 +2705,24 @@ static int IDAApolynomialStorePnt(IDAMem IDA_mem, DtpntMem d)
   IDAADJ_mem = IDA_mem->ida_adj_mem;
   content = (PolynomialDataMem) d->content;
 
-  N_VScale(ONE, phi[0], content->y);
+  N_VScale(ONE, IDA_mem->ida_phi[0], content->y);
 
   /* copy also the derivative for the first data point (in this case
      content->yp is non-null). */
   if (content->yd)
     IDAAGettnSolutionYp(IDA_mem, content->yd);
 
-  if (storeSensi) {
+  if (IDAADJ_mem->ia_storeSensi) {
     
-    for (is=0; is<Ns; is++) 
-      N_VScale(ONE, phiS[0][is], content->yS[is]);
+    for (is=0; is<IDA_mem->ida_Ns; is++) 
+      N_VScale(ONE, IDA_mem->ida_phiS[0][is], content->yS[is]);
     
     /* store the derivative if it is the first data point. */
     if(content->ySd)
       IDAAGettnSolutionYpS(IDA_mem, content->ySd);
   }
 
-  content->order = kused;
+  content->order = IDA_mem->ida_kused;
 
   return(0);
 }
@@ -2869,7 +2753,7 @@ static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
   dt_mem = IDAADJ_mem->dt_mem;
  
   /* Local value of Ns */
-  NS = (interpSensi && (yyS != NULL)) ? Ns : 0;
+  NS = (IDAADJ_mem->ia_interpSensi && (yyS != NULL)) ? IDA_mem->ida_Ns : 0;
 
   /* Get the index in dt_mem */
   flag = IDAAfindIndex(IDA_mem, t, &indx, &newpoint);
@@ -2896,7 +2780,7 @@ static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
   delt = SUNRabs(dt_mem[indx]->t - dt_mem[indx-1]->t);
 
   /* Find the direction of the forward integration */
-  dir = (tfinal - tinitial > ZERO) ? 1 : -1;
+  dir = (IDAADJ_mem->ia_tfinal - IDAADJ_mem->ia_tinitial > ZERO) ? 1 : -1;
 
   /* Establish the base point depending on the integration direction.
      Modify the base if there are not enough points for the current order */
@@ -2910,7 +2794,7 @@ static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
     base = indx-1;
     content = (PolynomialDataMem) (dt_mem[base]->content);
     order = content->order;
-    if (np-indx > order) base -= indx+order-np;
+    if (IDAADJ_mem->ia_np-indx > order) base -= indx+order-IDAADJ_mem->ia_np;
   }
 
   /* Recompute Y (divided differences for Newton polynomial) if needed */
@@ -2920,22 +2804,22 @@ static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
     /* Store 0-th order DD */
     if (dir == 1) {
       for(j=0;j<=order;j++) {
-        T[j] = dt_mem[base-j]->t;
+        IDAADJ_mem->ia_T[j] = dt_mem[base-j]->t;
         content = (PolynomialDataMem) (dt_mem[base-j]->content);
-        N_VScale(ONE, content->y, Y[j]);
+        N_VScale(ONE, content->y, IDAADJ_mem->ia_Y[j]);
         
         for (is=0; is<NS; is++) 
-          N_VScale(ONE, content->yS[is], YS[j][is]);
+          N_VScale(ONE, content->yS[is], IDAADJ_mem->ia_YS[j][is]);
        
       }
     } else {
       for(j=0;j<=order;j++) {
-        T[j] = dt_mem[base-1+j]->t;
+        IDAADJ_mem->ia_T[j] = dt_mem[base-1+j]->t;
         content = (PolynomialDataMem) (dt_mem[base-1+j]->content);
-        N_VScale(ONE, content->y, Y[j]);
+        N_VScale(ONE, content->y, IDAADJ_mem->ia_Y[j]);
         
         for (is=0; is<NS; is++) 
-          N_VScale(ONE, content->yS[is], YS[j][is]);
+          N_VScale(ONE, content->yS[is], IDAADJ_mem->ia_YS[j][is]);
         
       }
     }
@@ -2943,28 +2827,28 @@ static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
     /* Compute higher-order DD */
     for(i=1;i<=order;i++) {
       for(j=order;j>=i;j--) {
-        factor = delt/(T[j]-T[j-i]);
-        N_VLinearSum(factor, Y[j], -factor, Y[j-1], Y[j]);
+        factor = delt/(IDAADJ_mem->ia_T[j]-IDAADJ_mem->ia_T[j-i]);
+        N_VLinearSum(factor, IDAADJ_mem->ia_Y[j], -factor, IDAADJ_mem->ia_Y[j-1], IDAADJ_mem->ia_Y[j]);
         
         for (is=0; is<NS; is++) 
-          N_VLinearSum(factor, YS[j][is], -factor, YS[j-1][is], YS[j][is]);
+          N_VLinearSum(factor, IDAADJ_mem->ia_YS[j][is], -factor, IDAADJ_mem->ia_YS[j-1][is], IDAADJ_mem->ia_YS[j][is]);
         
       }
     }
   }
 
   /* Perform the actual interpolation for yy using nested multiplications */
-  N_VScale(ONE, Y[order], yy);
+  N_VScale(ONE, IDAADJ_mem->ia_Y[order], yy);
   
   for (is=0; is<NS; is++) 
-    N_VScale(ONE, YS[order][is], yyS[is]);
+    N_VScale(ONE, IDAADJ_mem->ia_YS[order][is], yyS[is]);
   
   for (i=order-1; i>=0; i--) {
-    factor = (t-T[i])/delt;
-    N_VLinearSum(factor, yy, ONE, Y[i], yy);
+    factor = (t-IDAADJ_mem->ia_T[i])/delt;
+    N_VLinearSum(factor, yy, ONE, IDAADJ_mem->ia_Y[i], yy);
     
     for (is=0; is<NS; is++) 
-      N_VLinearSum(factor, yyS[is], ONE, YS[i][is], yyS[is]);
+      N_VLinearSum(factor, yyS[is], ONE, IDAADJ_mem->ia_YS[i][is], yyS[is]);
     
   }
   
@@ -2990,15 +2874,15 @@ static int IDAApolynomialGetY(IDAMem IDA_mem, realtype t,
     N_VConst(ZERO, ypS[is]);
 
   for(i=1; i<=order; i++) {
-    factor = (t-T[i-1])/delt;
+    factor = (t-IDAADJ_mem->ia_T[i-1])/delt;
 
     Psiprime = Psi/delt +  factor * Psiprime;
     Psi = Psi * factor;
 
-    N_VLinearSum(ONE, yp, Psiprime, Y[i], yp);
+    N_VLinearSum(ONE, yp, Psiprime, IDAADJ_mem->ia_Y[i], yp);
     
     for (is=0; is<NS; is++)
-      N_VLinearSum(ONE, ypS[is], Psiprime, YS[i][is], ypS[is]);
+      N_VLinearSum(ONE, ypS[is], Psiprime, IDAADJ_mem->ia_YS[i][is], ypS[is]);
   }
 
   return(IDA_SUCCESS);
@@ -3022,10 +2906,10 @@ static int IDAAGettnSolutionYp(IDAMem IDA_mem, N_Vector yp)
   int j, kord;
   realtype C, D, gam;
 
-  if (nst==0) {
+  if (IDA_mem->ida_nst==0) {
 
     /* If no integration was done, return the yp supplied by user.*/
-      N_VScale(ONE, phi[1], yp);
+      N_VScale(ONE, IDA_mem->ida_phi[1], yp);
 
     return(0);
   }
@@ -3033,16 +2917,16 @@ static int IDAAGettnSolutionYp(IDAMem IDA_mem, N_Vector yp)
   /* Compute yp as in IDAGetSolution for this particular case when t=tn. */
   N_VConst(ZERO, yp);
   
-  kord = kused;
-  if(kused==0) kord=1;
+  kord = IDA_mem->ida_kused;
+  if(IDA_mem->ida_kused==0) kord=1;
   
   C = ONE; D = ZERO;
   gam = ZERO;
   for (j=1; j <= kord; j++) {
-    D = D*gam + C/psi[j-1];
+    D = D*gam + C/IDA_mem->ida_psi[j-1];
     C = C*gam;
-    gam = psi[j-1]/psi[j];
-    N_VLinearSum(ONE, yp, D, phi[j], yp);
+    gam = IDA_mem->ida_psi[j-1] / IDA_mem->ida_psi[j];
+    N_VLinearSum(ONE, yp, D, IDA_mem->ida_phi[j], yp);
   }   
 
   return(0);
@@ -3061,30 +2945,30 @@ static int IDAAGettnSolutionYpS(IDAMem IDA_mem, N_Vector *ypS)
   int j, kord, is;
   realtype C, D, gam;
 
-  if (nst==0) {
+  if (IDA_mem->ida_nst==0) {
 
     /* If no integration was done, return the ypS supplied by user.*/
-    for (is=0; is<Ns; is++) 
-      N_VScale(ONE, phiS[1][is], ypS[is]);
+    for (is=0; is<IDA_mem->ida_Ns; is++) 
+      N_VScale(ONE, IDA_mem->ida_phiS[1][is], ypS[is]);
 
     return(0);
   }
 
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<IDA_mem->ida_Ns; is++) 
     N_VConst(ZERO, ypS[is]);
   
-  kord = kused;
-  if(kused==0) kord=1;
+  kord = IDA_mem->ida_kused;
+  if(IDA_mem->ida_kused==0) kord=1;
   
   C = ONE; D = ZERO;
   gam = ZERO;
   for (j=1; j <= kord; j++) {
-    D = D*gam + C/psi[j-1];
+    D = D*gam + C/IDA_mem->ida_psi[j-1];
     C = C*gam;
-    gam = psi[j-1]/psi[j];
+    gam = IDA_mem->ida_psi[j-1] / IDA_mem->ida_psi[j];
   
-    for (is=0; is<Ns; is++)
-      N_VLinearSum(ONE, ypS[is], D, phiS[j][is], ypS[is]);
+    for (is=0; is<IDA_mem->ida_Ns; is++)
+      N_VLinearSum(ONE, ypS[is], D, IDA_mem->ida_phiS[j][is], ypS[is]);
   }   
 
   return(0);
@@ -3097,7 +2981,7 @@ static int IDAAGettnSolutionYpS(IDAMem IDA_mem, N_Vector *ypS)
  *
  * Finds the index in the array of data point strctures such that
  *     dt_mem[indx-1].t <= t < dt_mem[indx].t
- * If indx is changed from the previous invocation, then newpoint = TRUE
+ * If indx is changed from the previous invocation, then newpoint = SUNTRUE
  *
  * If t is beyond the leftmost limit, but close enough, indx=0.
  *
@@ -3119,16 +3003,16 @@ static int IDAAfindIndex(IDAMem ida_mem, realtype t,
   IDAADJ_mem = IDA_mem->ida_adj_mem;
   dt_mem = IDAADJ_mem->dt_mem;
 
-  *newpoint = FALSE;
+  *newpoint = SUNFALSE;
 
   /* Find the direction of integration */
-  sign = (tfinal - tinitial > ZERO) ? 1 : -1;
+  sign = (IDAADJ_mem->ia_tfinal - IDAADJ_mem->ia_tinitial > ZERO) ? 1 : -1;
 
   /* If this is the first time we use new data */
-  if (newData) {
-    ilast     = np-1;
-    *newpoint = TRUE;
-    newData   = FALSE;
+  if (IDAADJ_mem->ia_newData) {
+    ilast     = IDAADJ_mem->ia_np-1;
+    *newpoint = SUNTRUE;
+    IDAADJ_mem->ia_newData   = SUNFALSE;
   }
 
   /* Search for indx starting from ilast */
@@ -3138,10 +3022,10 @@ static int IDAAfindIndex(IDAMem ida_mem, realtype t,
   if ( to_left ) {
     /* look for a new indx to the left */
 
-    *newpoint = TRUE;
+    *newpoint = SUNTRUE;
     
     *indx = ilast;
-    loop {
+    for(;;) {
       if ( *indx == 0 ) break;
       if ( sign*(t - dt_mem[*indx-1]->t) <= ZERO ) (*indx)--;
       else                                         break;
@@ -3154,7 +3038,7 @@ static int IDAAfindIndex(IDAMem ida_mem, realtype t,
 
     if ( *indx == 0 ) {
       /* t is beyond leftmost limit. Is it too far? */  
-      if ( SUNRabs(t - dt_mem[0]->t) > FUZZ_FACTOR * uround ) {
+      if ( SUNRabs(t - dt_mem[0]->t) > FUZZ_FACTOR * IDA_mem->ida_uround ) {
         return(IDA_GETY_BADT);
       }
     }
@@ -3162,10 +3046,10 @@ static int IDAAfindIndex(IDAMem ida_mem, realtype t,
   } else if ( to_right ) {
     /* look for a new indx to the right */
 
-    *newpoint = TRUE;
+    *newpoint = SUNTRUE;
 
     *indx = ilast;
-    loop {
+    for(;;) {
       if ( sign*(t - dt_mem[*indx]->t) > ZERO) (*indx)++;
       else                                     break;
     }
@@ -3235,11 +3119,11 @@ static int IDAAres(realtype tt,
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
 
   /* Get forward solution from interpolation. */
-  if( noInterp == FALSE) {
-    if (interpSensi)
-      flag = IDAADJ_mem->ia_getY(ida_mem, tt, yyTmp, ypTmp, yySTmp, ypSTmp);
+  if( IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    if (IDAADJ_mem->ia_interpSensi)
+      flag = IDAADJ_mem->ia_getY(ida_mem, tt, IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, IDAADJ_mem->ia_yySTmp, IDAADJ_mem->ia_ypSTmp);
     else
-      flag = IDAADJ_mem->ia_getY(ida_mem, tt, yyTmp, ypTmp, NULL, NULL);
+      flag = IDAADJ_mem->ia_getY(ida_mem, tt, IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, NULL, NULL);
   
     if (flag != IDA_SUCCESS) {
       IDAProcessError(IDA_mem, -1, "IDAA", "IDAAres", MSGAM_BAD_TINTERP, tt);
@@ -3249,12 +3133,12 @@ static int IDAAres(realtype tt,
 
   /* Call the user supplied residual. */
   if(IDAB_mem->ida_res_withSensi) {
-    retval = IDAB_mem->ida_resS(tt, yyTmp, ypTmp, 
-                                yySTmp, ypSTmp,
+    retval = IDAB_mem->ida_resS(tt, IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, 
+                                IDAADJ_mem->ia_yySTmp, IDAADJ_mem->ia_ypSTmp,
                                 yyB, ypB, 
                                 rrB, IDAB_mem->ida_user_data);
   }else {
-    retval = IDAB_mem->ida_res(tt, yyTmp, ypTmp, yyB, ypB, rrB, IDAB_mem->ida_user_data);
+    retval = IDAB_mem->ida_res(tt, IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, yyB, ypB, rrB, IDAB_mem->ida_user_data);
   }
   return(retval);
 }
@@ -3287,11 +3171,11 @@ static int IDAArhsQ(realtype tt,
   retval = IDA_SUCCESS;
 
   /* Get forward solution from interpolation. */
-  if (noInterp == FALSE) {
-    if (interpSensi) {
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, yySTmp, ypSTmp);
+  if (IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    if (IDAADJ_mem->ia_interpSensi) {
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, IDAADJ_mem->ia_yySTmp, IDAADJ_mem->ia_ypSTmp);
     } else {
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, NULL, NULL);
     }
     
     if (flag != IDA_SUCCESS) {
@@ -3302,12 +3186,12 @@ static int IDAArhsQ(realtype tt,
 
   /* Call user's adjoint quadrature RHS routine */
   if (IDAB_mem->ida_rhsQ_withSensi) {
-    retval = IDAB_mem->ida_rhsQS(tt, yyTmp, ypTmp, yySTmp, ypSTmp, 
+    retval = IDAB_mem->ida_rhsQS(tt, IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, IDAADJ_mem->ia_yySTmp, IDAADJ_mem->ia_ypSTmp, 
                                  yyB, ypB, 
                                  resvalQB, IDAB_mem->ida_user_data);
   } else {
     retval = IDAB_mem->ida_rhsQ(tt,
-                                yyTmp, ypTmp,
+                                IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp,
                                 yyB, ypB,
                                 resvalQB, IDAB_mem->ida_user_data);
   }
diff --git a/src/idas/idaa_io.c b/src/idas/idaa_io.c
index dae7618..5f123c2 100644
--- a/src/idas/idaa_io.c
+++ b/src/idas/idaa_io.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4538 $
- * $Date: 2015-09-16 15:18:28 -0700 (Wed, 16 Sep 2015) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
@@ -43,13 +43,6 @@
 
 /* 
  * -----------------------------------------------------------------
- * Readibility Constants
- * -----------------------------------------------------------------
- */
-#define nbckpbs        (IDAADJ_mem->ia_nbckpbs)
-
-/* 
- * -----------------------------------------------------------------
  * Optional input functions for ASA
  * -----------------------------------------------------------------
  */
@@ -75,13 +68,13 @@ SUNDIALS_EXPORT int IDAAdjSetNoSensi(void *ida_mem)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAAdjSetNoSensi",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
-  IDAADJ_mem->ia_storeSensi = FALSE;
+  IDAADJ_mem->ia_storeSensi = SUNFALSE;
   
   return(IDA_SUCCESS);
 }
@@ -100,14 +93,14 @@ int IDASetUserDataB(void *ida_mem, int which, void *user_dataB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetUserDataB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetUserDataB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -141,14 +134,14 @@ int IDASetMaxOrdB(void *ida_mem, int which, int maxordB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetMaxOrdB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetMaxOrdB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -180,14 +173,14 @@ int IDASetMaxNumStepsB(void *ida_mem, int which, long int mxstepsB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetMaxNumStepsB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetMaxNumStepsB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -219,14 +212,14 @@ int IDASetInitStepB(void *ida_mem, int which, realtype hinB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetInitStepB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetInitStepB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -258,14 +251,14 @@ int IDASetMaxStepB(void *ida_mem, int which, realtype hmaxB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetMaxStepB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetMaxStepB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -297,14 +290,14 @@ int IDASetSuppressAlgB(void *ida_mem, int which,  booleantype suppressalgB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetSuppressAlgB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetSuppressAlgB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -336,14 +329,14 @@ int IDASetIdB(void *ida_mem, int which,  N_Vector idB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetIdB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetIdB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -375,14 +368,14 @@ int IDASetConstraintsB(void *ida_mem, int which,  N_Vector constraintsB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetConstraintsB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetConstraintsB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -419,14 +412,14 @@ int IDASetQuadErrConB(void *ida_mem, int which, int errconQB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDASetQuadErrConB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDASetQuadErrConB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
@@ -474,14 +467,14 @@ SUNDIALS_EXPORT void *IDAGetAdjIDABmem(void *ida_mem, int which)
   IDA_mem = (IDAMem) ida_mem; 
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, 0, "IDAA", "IDAGetAdjIDABmem",  MSGAM_NO_ADJ);
     return(NULL);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, 0, "IDAA", "IDAGetAdjIDABmem", MSGAM_BAD_WHICH);
     return(NULL);
   }
@@ -522,7 +515,7 @@ int IDAGetAdjCheckPointsInfo(void *ida_mem, IDAadjCheckPointRec *ckpnt)
   IDA_mem = (IDAMem) ida_mem; 
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjCheckPointsInfo",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
@@ -577,7 +570,7 @@ int IDAGetAdjDataPointHermite(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem; 
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjDataPointHermite",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
@@ -626,7 +619,7 @@ int IDAGetAdjDataPointPolynomial(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem; 
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjDataPointPolynomial", MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
@@ -667,7 +660,7 @@ SUNDIALS_EXPORT int IDAGetAdjCurrentCheckPoint(void *ida_mem, void **addr)
   IDA_mem = (IDAMem) ida_mem; 
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetAdjCurrentCheckPoint",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
@@ -704,14 +697,14 @@ int IDAGetConsistentICB(void *ida_mem, int which, N_Vector yyB0_mod, N_Vector yp
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_ADJ, "IDAA", "IDAGetConsistentICB",  MSGAM_NO_ADJ);
     return(IDA_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
-  if ( which >= nbckpbs ) {
+  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAA", "IDAGetConsistentICB", MSGAM_BAD_WHICH);
     return(IDA_ILL_INPUT);
   }
diff --git a/src/idas/idas.c b/src/idas/idas.c
index 04465c7..8feca60 100644
--- a/src/idas/idas.c
+++ b/src/idas/idas.c
@@ -1,7 +1,4 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4845 $
- * $Date: 2016-08-03 15:45:09 -0700 (Wed, 03 Aug 2016) $
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -157,15 +154,6 @@
 
 /* 
  * =================================================================
- * MACRO DEFINITIONS
- * =================================================================
- */
-
-/* Macro: loop */
-#define loop for(;;)
-
-/* 
- * =================================================================
  * IDAS PRIVATE CONSTANTS
  * =================================================================
  */
@@ -460,7 +448,7 @@ void *IDACreate(void)
   IDA_mem->ida_res         = NULL;
   IDA_mem->ida_user_data   = NULL;
   IDA_mem->ida_itol        = IDA_NN;
-  IDA_mem->ida_user_efun   = FALSE;
+  IDA_mem->ida_user_efun   = SUNFALSE;
   IDA_mem->ida_efun        = NULL;
   IDA_mem->ida_edata       = NULL;
   IDA_mem->ida_ehfun       = IDAErrHandler;
@@ -474,11 +462,11 @@ void *IDACreate(void)
   IDA_mem->ida_maxnef      = MXNEF;
   IDA_mem->ida_maxncf      = MXNCF;
   IDA_mem->ida_maxcor      = MAXIT;
-  IDA_mem->ida_suppressalg = FALSE;
+  IDA_mem->ida_suppressalg = SUNFALSE;
   IDA_mem->ida_id          = NULL;
   IDA_mem->ida_constraints = NULL;
-  IDA_mem->ida_constraintsSet = FALSE;
-  IDA_mem->ida_tstopset    = FALSE;
+  IDA_mem->ida_constraintsSet = SUNFALSE;
+  IDA_mem->ida_tstopset    = SUNFALSE;
 
   /* set the saved value maxord_alloc */
   IDA_mem->ida_maxord_alloc = MAXORD_DEFAULT;
@@ -489,39 +477,39 @@ void *IDACreate(void)
   IDA_mem->ida_maxnj   = MAXNJ;
   IDA_mem->ida_maxnit  = MAXNI;
   IDA_mem->ida_maxbacks  = MAXBACKS;
-  IDA_mem->ida_lsoff   = FALSE;
+  IDA_mem->ida_lsoff   = SUNFALSE;
   IDA_mem->ida_steptol = SUNRpowerR(IDA_mem->ida_uround, TWOTHIRDS);
 
   /* Set default values for quad. optional inputs */
-  IDA_mem->ida_quadr      = FALSE;
+  IDA_mem->ida_quadr      = SUNFALSE;
   IDA_mem->ida_rhsQ       = NULL;
-  IDA_mem->ida_errconQ    = FALSE;
+  IDA_mem->ida_errconQ    = SUNFALSE;
   IDA_mem->ida_itolQ      = IDA_NN;
 
   /* Set default values for sensi. optional inputs */
-  IDA_mem->ida_sensi        = FALSE;
+  IDA_mem->ida_sensi        = SUNFALSE;
   IDA_mem->ida_user_dataS   = (void *)IDA_mem;
   IDA_mem->ida_resS         = IDASensResDQ;
-  IDA_mem->ida_resSDQ       = TRUE;
+  IDA_mem->ida_resSDQ       = SUNTRUE;
   IDA_mem->ida_DQtype       = IDA_CENTERED;
   IDA_mem->ida_DQrhomax     = ZERO;
   IDA_mem->ida_p            = NULL;
   IDA_mem->ida_pbar         = NULL;
   IDA_mem->ida_plist        = NULL;
-  IDA_mem->ida_errconS      = FALSE;
+  IDA_mem->ida_errconS      = SUNFALSE;
   IDA_mem->ida_maxcorS      = MAXIT;
   IDA_mem->ida_itolS        = IDA_EE;
 
   /* Defaults for sensi. quadr. optional inputs. */
-  IDA_mem->ida_quadr_sensi  = FALSE;
+  IDA_mem->ida_quadr_sensi  = SUNFALSE;
   IDA_mem->ida_user_dataQS  = (void *)IDA_mem;
   IDA_mem->ida_rhsQS        = IDAQuadSensRhsInternalDQ;
-  IDA_mem->ida_rhsQSDQ      = TRUE;
-  IDA_mem->ida_errconQS     = FALSE;
+  IDA_mem->ida_rhsQSDQ      = SUNTRUE;
+  IDA_mem->ida_errconQS     = SUNFALSE;
   IDA_mem->ida_itolQS       = IDA_EE;
 
   /* Set defaults for ASA. */
-  IDA_mem->ida_adj     = FALSE;
+  IDA_mem->ida_adj     = SUNFALSE;
   IDA_mem->ida_adj_mem = NULL;
 
   /* Initialize lrw and liw */
@@ -530,23 +518,23 @@ void *IDACreate(void)
 
   /* No mallocs have been done yet */
 
-  IDA_mem->ida_VatolMallocDone       = FALSE;
-  IDA_mem->ida_constraintsMallocDone = FALSE;
-  IDA_mem->ida_idMallocDone          = FALSE;
-  IDA_mem->ida_MallocDone            = FALSE;
+  IDA_mem->ida_VatolMallocDone       = SUNFALSE;
+  IDA_mem->ida_constraintsMallocDone = SUNFALSE;
+  IDA_mem->ida_idMallocDone          = SUNFALSE;
+  IDA_mem->ida_MallocDone            = SUNFALSE;
 
-  IDA_mem->ida_VatolQMallocDone      = FALSE;
-  IDA_mem->ida_quadMallocDone        = FALSE;
+  IDA_mem->ida_VatolQMallocDone      = SUNFALSE;
+  IDA_mem->ida_quadMallocDone        = SUNFALSE;
 
-  IDA_mem->ida_VatolSMallocDone      = FALSE;
-  IDA_mem->ida_SatolSMallocDone      = FALSE;
-  IDA_mem->ida_sensMallocDone        = FALSE;
+  IDA_mem->ida_VatolSMallocDone      = SUNFALSE;
+  IDA_mem->ida_SatolSMallocDone      = SUNFALSE;
+  IDA_mem->ida_sensMallocDone        = SUNFALSE;
 
-  IDA_mem->ida_VatolQSMallocDone      = FALSE;
-  IDA_mem->ida_SatolQSMallocDone      = FALSE;
-  IDA_mem->ida_quadSensMallocDone     = FALSE;
+  IDA_mem->ida_VatolQSMallocDone      = SUNFALSE;
+  IDA_mem->ida_SatolQSMallocDone      = SUNFALSE;
+  IDA_mem->ida_quadSensMallocDone     = SUNFALSE;
 
-  IDA_mem->ida_adjMallocDone          = FALSE;
+  IDA_mem->ida_adjMallocDone          = SUNFALSE;
 
   /* Return pointer to IDA memory block */
   return((void *)IDA_mem);
@@ -554,11 +542,6 @@ void *IDACreate(void)
 
 /*-----------------------------------------------------------------*/
 
-#define lrw   (IDA_mem->ida_lrw)
-#define liw   (IDA_mem->ida_liw)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDAInit
  *
@@ -573,7 +556,7 @@ int IDAInit(void *ida_mem, IDAResFn res,
 {
   IDAMem IDA_mem;
   booleantype nvectorOK, allocOK;
-  long int lrw1, liw1;
+  sunindextype lrw1, liw1;
 
   /* Check ida_mem */
 
@@ -643,9 +626,9 @@ int IDAInit(void *ida_mem, IDAResFn res,
   IDA_mem->ida_lfree  = NULL;
   IDA_mem->ida_lmem   = NULL;
 
-  /* Set forceSetup to FALSE */
+  /* Set forceSetup to SUNFALSE */
 
-  IDA_mem->ida_forceSetup = FALSE;
+  IDA_mem->ida_forceSetup = SUNFALSE;
 
   /* Initialize the phi array */
 
@@ -686,22 +669,17 @@ int IDAInit(void *ida_mem, IDAResFn res,
 
   /* Initial setup not done yet */
 
-  IDA_mem->ida_SetupDone = FALSE;
+  IDA_mem->ida_SetupDone = SUNFALSE;
 
   /* Problem memory has been successfully allocated */
 
-  IDA_mem->ida_MallocDone = TRUE;
+  IDA_mem->ida_MallocDone = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
 
 /*-----------------------------------------------------------------*/
 
-#define lrw1 (IDA_mem->ida_lrw1)
-#define liw1 (IDA_mem->ida_liw1)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDAReInit
  *
@@ -731,7 +709,7 @@ int IDAReInit(void *ida_mem,
 
   /* Check if problem was malloc'ed */
   
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDAReInit", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -752,9 +730,9 @@ int IDAReInit(void *ida_mem,
 
   IDA_mem->ida_tn  = t0;
 
-  /* Set forceSetup to FALSE */
+  /* Set forceSetup to SUNFALSE */
 
-  IDA_mem->ida_forceSetup = FALSE;
+  IDA_mem->ida_forceSetup = SUNFALSE;
 
   /* Initialize the phi array */
 
@@ -780,7 +758,7 @@ int IDAReInit(void *ida_mem,
 
   /* Initial setup not done yet */
 
-  IDA_mem->ida_SetupDone = FALSE;
+  IDA_mem->ida_SetupDone = SUNFALSE;
       
   /* Problem has been successfully re-initialized */
 
@@ -815,7 +793,7 @@ int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDASStolerances", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -837,7 +815,7 @@ int IDASStolerances(void *ida_mem, realtype reltol, realtype abstol)
 
   IDA_mem->ida_itol = IDA_SS;
 
-  IDA_mem->ida_user_efun = FALSE;
+  IDA_mem->ida_user_efun = SUNFALSE;
   IDA_mem->ida_efun = IDAEwtSet;
   IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup */ 
 
@@ -855,7 +833,7 @@ int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDASVtolerances", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -876,9 +854,9 @@ int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
   
   if ( !(IDA_mem->ida_VatolMallocDone) ) {
     IDA_mem->ida_Vatol = N_VClone(IDA_mem->ida_ewt);
-    lrw += lrw1;
-    liw += liw1;
-    IDA_mem->ida_VatolMallocDone = TRUE;
+    IDA_mem->ida_lrw += IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw += IDA_mem->ida_liw1;
+    IDA_mem->ida_VatolMallocDone = SUNTRUE;
   }
 
   IDA_mem->ida_rtol = reltol;
@@ -886,7 +864,7 @@ int IDASVtolerances(void *ida_mem, realtype reltol, N_Vector abstol)
 
   IDA_mem->ida_itol = IDA_SV;
 
-  IDA_mem->ida_user_efun = FALSE;
+  IDA_mem->ida_user_efun = SUNFALSE;
   IDA_mem->ida_efun = IDAEwtSet;
   IDA_mem->ida_edata = NULL; /* will be set to ida_mem in InitialSetup */ 
 
@@ -904,14 +882,14 @@ int IDAWFtolerances(void *ida_mem, IDAEwtFn efun)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDAWFtolerances", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
 
   IDA_mem->ida_itol = IDA_WF;
 
-  IDA_mem->ida_user_efun = TRUE;
+  IDA_mem->ida_user_efun = SUNTRUE;
   IDA_mem->ida_efun = efun;
   IDA_mem->ida_edata = NULL; /* will be set to user_data in InitialSetup */
 
@@ -935,7 +913,7 @@ int IDAQuadInit(void *ida_mem, IDAQuadRhsFn rhsQ, N_Vector yQ0)
 {
   IDAMem IDA_mem;
   booleantype allocOK;
-  long int lrw1Q, liw1Q;
+  sunindextype lrw1Q, liw1Q;
   int i;
 
   /* Check ida_mem */
@@ -971,8 +949,8 @@ int IDAQuadInit(void *ida_mem, IDAQuadRhsFn rhsQ, N_Vector yQ0)
   IDA_mem->ida_netfQ = 0;
 
   /* Quadrature integration turned ON */
-  IDA_mem->ida_quadr = TRUE;
-  IDA_mem->ida_quadMallocDone = TRUE;
+  IDA_mem->ida_quadr = SUNTRUE;
+  IDA_mem->ida_quadMallocDone = SUNTRUE;
 
   /* Quadrature initialization was successfull */
   return(IDA_SUCCESS);
@@ -980,11 +958,6 @@ int IDAQuadInit(void *ida_mem, IDAQuadRhsFn rhsQ, N_Vector yQ0)
 
 /*-----------------------------------------------------------------*/
 
-#define lrw1Q (IDA_mem->ida_lrw1Q)
-#define liw1Q (IDA_mem->ida_liw1Q)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDAQuadReInit
  *
@@ -1011,7 +984,7 @@ int IDAQuadReInit(void *ida_mem, N_Vector yQ0)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Ckeck if quadrature was initialized */
-  if (IDA_mem->ida_quadMallocDone == FALSE) {
+  if (IDA_mem->ida_quadMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAQuadReInit", MSG_NO_QUAD);
     return(IDA_NO_QUAD);
   }
@@ -1027,7 +1000,7 @@ int IDAQuadReInit(void *ida_mem, N_Vector yQ0)
   IDA_mem->ida_netfQ = 0;
 
   /* Quadrature integration turned ON */
-  IDA_mem->ida_quadr = TRUE;
+  IDA_mem->ida_quadr = SUNTRUE;
 
   /* Quadrature re-initialization was successfull */
   return(IDA_SUCCESS);
@@ -1061,7 +1034,7 @@ int IDAQuadSStolerances(void *ida_mem, realtype reltolQ, realtype abstolQ)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Ckeck if quadrature was initialized */
-  if (IDA_mem->ida_quadMallocDone == FALSE) {
+  if (IDA_mem->ida_quadMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAQuadSStolerances", MSG_NO_QUAD);
     return(IDA_NO_QUAD);
   }
@@ -1099,7 +1072,7 @@ int IDAQuadSVtolerances(void *ida_mem, realtype reltolQ, N_Vector abstolQ)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Ckeck if quadrature was initialized */
-  if (IDA_mem->ida_quadMallocDone == FALSE) {
+  if (IDA_mem->ida_quadMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAQuadSVtolerances", MSG_NO_QUAD);
     return(IDA_NO_QUAD);
   }
@@ -1125,11 +1098,11 @@ int IDAQuadSVtolerances(void *ida_mem, realtype reltolQ, N_Vector abstolQ)
   IDA_mem->ida_rtolQ = reltolQ;
 
   /* clone the absolute tolerances vector (if necessary) */
-  if (FALSE == IDA_mem->ida_VatolQMallocDone) {
+  if (SUNFALSE == IDA_mem->ida_VatolQMallocDone) {
     IDA_mem->ida_VatolQ = N_VClone(abstolQ);
-    lrw += lrw1Q;
-    liw += liw1Q;
-    IDA_mem->ida_VatolQMallocDone = TRUE;
+    IDA_mem->ida_lrw += IDA_mem->ida_lrw1Q;
+    IDA_mem->ida_liw += IDA_mem->ida_liw1Q;
+    IDA_mem->ida_VatolQMallocDone = SUNTRUE;
   }
 
   N_VScale(ONE, abstolQ, IDA_mem->ida_VatolQ);
@@ -1193,11 +1166,11 @@ int IDASensInit(void *ida_mem, int Ns, int ism,
   if (fS != NULL) {
     IDA_mem->ida_resS    = fS;
     IDA_mem->ida_user_dataS  = IDA_mem->ida_user_data;
-    IDA_mem->ida_resSDQ  = FALSE;
+    IDA_mem->ida_resSDQ  = SUNFALSE;
   } else {
     IDA_mem->ida_resS       = IDASensResDQ;
     IDA_mem->ida_user_dataS = ida_mem;
-    IDA_mem->ida_resSDQ     = TRUE;
+    IDA_mem->ida_resSDQ     = SUNTRUE;
   }
 
   /* Allocate the vectors (using yS0[0] as a template) */
@@ -1233,8 +1206,8 @@ int IDASensInit(void *ida_mem, int Ns, int ism,
   }
 
   /* Sensitivities will be computed */
-  IDA_mem->ida_sensi = TRUE;
-  IDA_mem->ida_sensMallocDone = TRUE;
+  IDA_mem->ida_sensi = SUNTRUE;
+  IDA_mem->ida_sensMallocDone = SUNTRUE;
 
   /* Sensitivity initialization was successfull */
   return(IDA_SUCCESS);
@@ -1242,10 +1215,6 @@ int IDASensInit(void *ida_mem, int Ns, int ism,
 
 /*-----------------------------------------------------------------*/
 
-#define Ns (IDA_mem->ida_Ns)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDASensReInit
  *
@@ -1274,7 +1243,7 @@ int IDASensReInit(void *ida_mem, int ism, N_Vector *yS0, N_Vector *ypS0)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Was sensitivity initialized? */
-  if (IDA_mem->ida_sensMallocDone == FALSE) {
+  if (IDA_mem->ida_sensMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensReInit", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   } 
@@ -1301,7 +1270,7 @@ int IDASensReInit(void *ida_mem, int ism, N_Vector *yS0, N_Vector *ypS0)
     -----------------------------------------------*/
 
   /* Initialize the phiS array */
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     N_VScale(ONE, yS0[is],  IDA_mem->ida_phiS[0][is]);  
     N_VScale(ONE, ypS0[is], IDA_mem->ida_phiS[1][is]);  
   }
@@ -1315,13 +1284,13 @@ int IDASensReInit(void *ida_mem, int ism, N_Vector *yS0, N_Vector *ypS0)
   IDA_mem->ida_nsetupsS = 0;
 
   /* Set default values for plist and pbar */
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     IDA_mem->ida_plist[is] = is;
     IDA_mem->ida_pbar[is] = ONE;
   }
 
   /* Sensitivities will be computed */
-  IDA_mem->ida_sensi = TRUE;
+  IDA_mem->ida_sensi = SUNTRUE;
 
   /* Sensitivity re-initialization was successfull */
   return(IDA_SUCCESS);
@@ -1360,7 +1329,7 @@ int IDASensSStolerances(void *ida_mem, realtype reltolS, realtype *abstolS)
 
   /* Was sensitivity initialized? */
 
-  if (IDA_mem->ida_sensMallocDone == FALSE) {
+  if (IDA_mem->ida_sensMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensSStolerances", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   } 
@@ -1377,7 +1346,7 @@ int IDASensSStolerances(void *ida_mem, realtype reltolS, realtype *abstolS)
     return(IDA_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<IDA_mem->ida_Ns; is++)
     if (abstolS[is] < ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSStolerances", MSG_BAD_ATOLS);
       return(IDA_ILL_INPUT);
@@ -1391,12 +1360,12 @@ int IDASensSStolerances(void *ida_mem, realtype reltolS, realtype *abstolS)
 
   if ( !(IDA_mem->ida_SatolSMallocDone) ) {
     IDA_mem->ida_SatolS = NULL;
-    IDA_mem->ida_SatolS = (realtype *)malloc(Ns*sizeof(realtype));
-    lrw += Ns;
-    IDA_mem->ida_SatolSMallocDone = TRUE;
+    IDA_mem->ida_SatolS = (realtype *)malloc(IDA_mem->ida_Ns*sizeof(realtype));
+    IDA_mem->ida_lrw += IDA_mem->ida_Ns;
+    IDA_mem->ida_SatolSMallocDone = SUNTRUE;
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<IDA_mem->ida_Ns; is++)
     IDA_mem->ida_SatolS[is] = abstolS[is];
 
   return(IDA_SUCCESS);
@@ -1417,7 +1386,7 @@ int IDASensSVtolerances(void *ida_mem,  realtype reltolS, N_Vector *abstolS)
 
   /* Was sensitivity initialized? */
 
-  if (IDA_mem->ida_sensMallocDone == FALSE) {
+  if (IDA_mem->ida_sensMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensSVtolerances", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   } 
@@ -1434,7 +1403,7 @@ int IDASensSVtolerances(void *ida_mem,  realtype reltolS, N_Vector *abstolS)
     return(IDA_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     if (N_VMin(abstolS[is])<ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASensSStolerances", MSG_BAD_ATOLS);
       return(IDA_ILL_INPUT);      
@@ -1444,14 +1413,14 @@ int IDASensSVtolerances(void *ida_mem,  realtype reltolS, N_Vector *abstolS)
   IDA_mem->ida_itolS = IDA_SV;
   IDA_mem->ida_rtolS = reltolS ;
 
-  if ( FALSE == IDA_mem->ida_VatolSMallocDone ) {
-    IDA_mem->ida_VatolS = N_VCloneVectorArray(Ns, IDA_mem->ida_tempv1);
-    lrw += Ns*lrw1;
-    liw += Ns*liw1;
-    IDA_mem->ida_VatolSMallocDone = TRUE;
+  if ( SUNFALSE == IDA_mem->ida_VatolSMallocDone ) {
+    IDA_mem->ida_VatolS = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_tempv1);
+    IDA_mem->ida_lrw += IDA_mem->ida_Ns*IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw += IDA_mem->ida_Ns*IDA_mem->ida_liw1;
+    IDA_mem->ida_VatolSMallocDone = SUNTRUE;
   }
   
-  for (is=0; is<Ns; is++)    
+  for (is=0; is<IDA_mem->ida_Ns; is++)    
     N_VScale(ONE, abstolS[is], IDA_mem->ida_VatolS[is]);
     
   return(IDA_SUCCESS);
@@ -1469,7 +1438,7 @@ int IDASensEEtolerances(void *ida_mem)
 
   /* Was sensitivity initialized? */
 
-  if (IDA_mem->ida_sensMallocDone == FALSE) {
+  if (IDA_mem->ida_sensMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASensEEtolerances", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   } 
@@ -1513,19 +1482,19 @@ int IDAQuadSensInit(void *ida_mem, IDAQuadSensRhsFn rhsQS, N_Vector *yQS0)
 
   /* Error checking complete. */
   if (rhsQS == NULL) {
-    IDA_mem->ida_rhsQSDQ = TRUE;
+    IDA_mem->ida_rhsQSDQ = SUNTRUE;
     IDA_mem->ida_rhsQS = IDAQuadSensRhsInternalDQ;
 
     IDA_mem->ida_user_dataQS = ida_mem;
   } else {
-    IDA_mem->ida_rhsQSDQ = FALSE;
+    IDA_mem->ida_rhsQSDQ = SUNFALSE;
     IDA_mem->ida_rhsQS = rhsQS;
 
     IDA_mem->ida_user_dataQS = IDA_mem->ida_user_data;
   }
 
   /* Initialize phiQS[0] in the history array */
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<IDA_mem->ida_Ns; is++) 
     N_VScale(ONE, yQS0[is], IDA_mem->ida_phiQS[0][is]);
 
   /* Initialize all sensitivities related counters. */
@@ -1534,8 +1503,8 @@ int IDAQuadSensInit(void *ida_mem, IDAQuadSensRhsFn rhsQS, N_Vector *yQS0)
   IDA_mem->ida_netfQS = 0;
 
   /* Everything allright, set the flags and return with success. */
-  IDA_mem->ida_quadr_sensi = TRUE;
-  IDA_mem->ida_quadSensMallocDone = TRUE;
+  IDA_mem->ida_quadr_sensi = SUNTRUE;
+  IDA_mem->ida_quadSensMallocDone = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
@@ -1572,7 +1541,7 @@ int IDAQuadSensReInit(void *ida_mem, N_Vector *yQS0)
   /* Error checking complete at this point. */
 
   /* Initialize phiQS[0] in the history array */
-  for (is=0; is<Ns; is++) 
+  for (is=0; is<IDA_mem->ida_Ns; is++) 
     N_VScale(ONE, yQS0[is], IDA_mem->ida_phiQS[0][is]);
 
   /* Initialize all sensitivities related counters. */
@@ -1581,7 +1550,7 @@ int IDAQuadSensReInit(void *ida_mem, N_Vector *yQS0)
   IDA_mem->ida_netfQS = 0;
 
   /* Everything allright, set the flags and return with success. */
-  IDA_mem->ida_quadr_sensi = TRUE;
+  IDA_mem->ida_quadr_sensi = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
@@ -1640,7 +1609,7 @@ int IDAQuadSensSStolerances(void *ida_mem, realtype reltolQS, realtype *abstolQS
     return(IDA_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<IDA_mem->ida_Ns; is++)
     if (abstolQS[is] < ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSStolerances", MSG_BAD_ABSTOLQS);
       return(IDA_ILL_INPUT);
@@ -1651,12 +1620,12 @@ int IDAQuadSensSStolerances(void *ida_mem, realtype reltolQS, realtype *abstolQS
   IDA_mem->ida_rtolQS = reltolQS;
 
   if ( !(IDA_mem->ida_SatolQSMallocDone) ) {
-    IDA_mem->ida_SatolQS = (realtype *)malloc(Ns*sizeof(realtype));
-    lrw += Ns;
-    IDA_mem->ida_SatolQSMallocDone = TRUE;
+    IDA_mem->ida_SatolQS = (realtype *)malloc(IDA_mem->ida_Ns*sizeof(realtype));
+    IDA_mem->ida_lrw += IDA_mem->ida_Ns;
+    IDA_mem->ida_SatolQSMallocDone = SUNTRUE;
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<IDA_mem->ida_Ns; is++)
     IDA_mem->ida_SatolQS[is] = abstolQS[is];
 
   return(IDA_SUCCESS);
@@ -1697,7 +1666,7 @@ int IDAQuadSensSVtolerances(void *ida_mem, realtype reltolQS, N_Vector *abstolQS
     return(IDA_ILL_INPUT);
   }
 
-  for (is=0; is<Ns; is++)
+  for (is=0; is<IDA_mem->ida_Ns; is++)
     if (N_VMin(abstolQS[is]) < ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAQuadSensSVtolerances", MSG_BAD_ABSTOLQS);
       return(IDA_ILL_INPUT);
@@ -1708,13 +1677,13 @@ int IDAQuadSensSVtolerances(void *ida_mem, realtype reltolQS, N_Vector *abstolQS
   IDA_mem->ida_rtolQS = reltolQS;
 
   if ( !(IDA_mem->ida_VatolQSMallocDone) ) {
-    IDA_mem->ida_VatolQS = N_VCloneVectorArray(Ns, abstolQS[0]);
-    lrw += Ns*lrw1Q;
-    liw += Ns*liw1Q;
-    IDA_mem->ida_VatolQSMallocDone = TRUE;
+    IDA_mem->ida_VatolQS = N_VCloneVectorArray(IDA_mem->ida_Ns, abstolQS[0]);
+    IDA_mem->ida_lrw += IDA_mem->ida_Ns*IDA_mem->ida_lrw1Q;
+    IDA_mem->ida_liw += IDA_mem->ida_Ns*IDA_mem->ida_liw1Q;
+    IDA_mem->ida_VatolQSMallocDone = SUNTRUE;
   }
   
-  for (is=0; is<Ns; is++)    
+  for (is=0; is<IDA_mem->ida_Ns; is++)    
     N_VScale(ONE, abstolQS[is], IDA_mem->ida_VatolQS[is]);
 
   return(IDA_SUCCESS);
@@ -1765,25 +1734,12 @@ int IDASensToggleOff(void *ida_mem)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Disable sensitivities */
-  IDA_mem->ida_sensi = FALSE;
-  IDA_mem->ida_quadr_sensi = FALSE;
+  IDA_mem->ida_sensi = SUNFALSE;
+  IDA_mem->ida_quadr_sensi = SUNFALSE;
 
   return(IDA_SUCCESS);
 }
 
-/*-----------------------------------------------------------------*/
-
-
-#define gfun   (IDA_mem->ida_gfun)
-#define glo    (IDA_mem->ida_glo)
-#define ghi    (IDA_mem->ida_ghi)
-#define grout  (IDA_mem->ida_grout)
-#define iroots (IDA_mem->ida_iroots)
-#define rootdir (IDA_mem->ida_rootdir)
-#define gactive (IDA_mem->ida_gactive)
-
-/*-----------------------------------------------------------------*/
-
 /*
  * IDARootInit
  *
@@ -1813,15 +1769,15 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
      currently held memory resources */
   if ((nrt != IDA_mem->ida_nrtfn) && (IDA_mem->ida_nrtfn > 0)) {
 
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); iroots = NULL;
-    free(gactive); gactive = NULL;
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
+    free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
+    free(IDA_mem->ida_gactive); IDA_mem->ida_gactive = NULL;
 
-    lrw -= 3 * (IDA_mem->ida_nrtfn);
-    liw -= 3 * (IDA_mem->ida_nrtfn);
+    IDA_mem->ida_lrw -= 3 * (IDA_mem->ida_nrtfn);
+    IDA_mem->ida_liw -= 3 * (IDA_mem->ida_nrtfn);
 
   }
 
@@ -1829,7 +1785,7 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
      zero and ida_gfun to NULL before returning */
   if (nrt == 0) {
     IDA_mem->ida_nrtfn = nrt;
-    gfun = NULL;
+    IDA_mem->ida_gfun = NULL;
     return(IDA_SUCCESS);
   }
 
@@ -1839,23 +1795,23 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
   /* If g != NULL then return as currently reserved memory resources
      will suffice */
   if (nrt == IDA_mem->ida_nrtfn) {
-    if (g != gfun) {
+    if (g != IDA_mem->ida_gfun) {
       if (g == NULL) {
-	free(glo); glo = NULL;
-	free(ghi); ghi = NULL;
-	free(grout); grout = NULL;
-	free(iroots); iroots = NULL;
-        free(rootdir); iroots = NULL;
-        free(gactive); gactive = NULL;
+	free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+	free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+	free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+	free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
+        free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
+        free(IDA_mem->ida_gactive); IDA_mem->ida_gactive = NULL;
 
-        lrw -= 3*nrt;
-        liw -= 3*nrt;
+        IDA_mem->ida_lrw -= 3*nrt;
+        IDA_mem->ida_liw -= 3*nrt;
 
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDARootInit", MSG_ROOT_FUNC_NULL);
         return(IDA_ILL_INPUT);
       }
       else {
-        gfun = g;
+        IDA_mem->ida_gfun = g;
         return(IDA_SUCCESS);
       }
     }
@@ -1868,263 +1824,78 @@ int IDARootInit(void *ida_mem, int nrtfn, IDARootFn g)
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDARootInit", MSG_ROOT_FUNC_NULL);
     return(IDA_ILL_INPUT);
   }
-  else gfun = g;
+  else IDA_mem->ida_gfun = g;
 
   /* Allocate necessary memory and return */
-  glo = NULL;
-  glo = (realtype *) malloc(nrt*sizeof(realtype));
-  if (glo == NULL) {
+  IDA_mem->ida_glo = NULL;
+  IDA_mem->ida_glo = (realtype *) malloc(nrt*sizeof(realtype));
+  if (IDA_mem->ida_glo == NULL) {
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  ghi = NULL;
-  ghi = (realtype *) malloc(nrt*sizeof(realtype));
-  if (ghi == NULL) {
-    free(glo); glo = NULL;
+  IDA_mem->ida_ghi = NULL;
+  IDA_mem->ida_ghi = (realtype *) malloc(nrt*sizeof(realtype));
+  if (IDA_mem->ida_ghi == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  grout = NULL;
-  grout = (realtype *) malloc(nrt*sizeof(realtype));
-  if (grout == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
+  IDA_mem->ida_grout = NULL;
+  IDA_mem->ida_grout = (realtype *) malloc(nrt*sizeof(realtype));
+  if (IDA_mem->ida_grout == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  iroots = NULL;
-  iroots = (int *) malloc(nrt*sizeof(int));
-  if (iroots == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
+  IDA_mem->ida_iroots = NULL;
+  IDA_mem->ida_iroots = (int *) malloc(nrt*sizeof(int));
+  if (IDA_mem->ida_iroots == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  rootdir = NULL;
-  rootdir = (int *) malloc(nrt*sizeof(int));
-  if (rootdir == NULL) {
-    free(glo); glo = NULL;
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
+  IDA_mem->ida_rootdir = NULL;
+  IDA_mem->ida_rootdir = (int *) malloc(nrt*sizeof(int));
+  if (IDA_mem->ida_rootdir == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL;
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDAS", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
-  gactive = NULL;
-  gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
-  if (gactive == NULL) {
-    free(glo); glo = NULL; 
-    free(ghi); ghi = NULL;
-    free(grout); grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
+  IDA_mem->ida_gactive = NULL;
+  IDA_mem->ida_gactive = (booleantype *) malloc(nrt*sizeof(booleantype));
+  if (IDA_mem->ida_gactive == NULL) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL; 
+    free(IDA_mem->ida_ghi); IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout); IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
+    free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
     IDAProcessError(IDA_mem, IDA_MEM_FAIL, "IDA", "IDARootInit", MSG_MEM_FAIL);
     return(IDA_MEM_FAIL);
   }
 
   /* Set default values for rootdir (both directions) */
-  for(i=0; i<nrt; i++) rootdir[i] = 0;
+  for(i=0; i<nrt; i++) IDA_mem->ida_rootdir[i] = 0;
 
   /* Set default values for gactive (all active) */
-  for(i=0; i<nrt; i++) gactive[i] = TRUE;
+  for(i=0; i<nrt; i++) IDA_mem->ida_gactive[i] = SUNTRUE;
 
-  lrw += 3*nrt;
-  liw += 3*nrt;
+  IDA_mem->ida_lrw += 3*nrt;
+  IDA_mem->ida_liw += 3*nrt;
 
   return(IDA_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Readability constants
- * -----------------------------------------------------------------
- */
-
-/* State variables */
-
-#define res            (IDA_mem->ida_res)
-#define user_data      (IDA_mem->ida_user_data)
-#define y0             (IDA_mem->ida_y0)
-#define yp0            (IDA_mem->ida_yp0)
-
-#define itol           (IDA_mem->ida_itol)
-#define rtol           (IDA_mem->ida_rtol)
-#define Satol          (IDA_mem->ida_Satol)
-#define Vatol          (IDA_mem->ida_Vatol)
-#define efun           (IDA_mem->ida_efun)
-#define edata          (IDA_mem->ida_edata)
-
-#define maxord         (IDA_mem->ida_maxord)
-#define mxstep         (IDA_mem->ida_mxstep)
-#define hin            (IDA_mem->ida_hin)
-#define hmax_inv       (IDA_mem->ida_hmax_inv)
-#define tstop          (IDA_mem->ida_tstop)
-#define tstopset       (IDA_mem->ida_tstopset)
-#define epcon          (IDA_mem->ida_epcon)
-#define maxnef         (IDA_mem->ida_maxnef)
-#define maxncf         (IDA_mem->ida_maxncf)
-#define maxcor         (IDA_mem->ida_maxcor)
-#define suppressalg    (IDA_mem->ida_suppressalg)
-#define id             (IDA_mem->ida_id)
-#define constraints    (IDA_mem->ida_constraints)
-
-#define epiccon        (IDA_mem->ida_epiccon)
-#define maxnh          (IDA_mem->ida_maxnh)
-#define maxnj          (IDA_mem->ida_maxnj)
-#define maxnit         (IDA_mem->ida_maxnit)
-#define lsoff          (IDA_mem->ida_lsoff)
-#define steptol        (IDA_mem->ida_steptol)
-
-#define uround         (IDA_mem->ida_uround)  
-#define phi            (IDA_mem->ida_phi) 
-#define ewt            (IDA_mem->ida_ewt)  
-#define yy             (IDA_mem->ida_yy)
-#define yp             (IDA_mem->ida_yp)
-#define delta          (IDA_mem->ida_delta)
-#define mm             (IDA_mem->ida_mm)
-#define ee             (IDA_mem->ida_ee)
-#define savres         (IDA_mem->ida_savres)
-#define tempv1         (IDA_mem->ida_tempv1)
-#define tempv2         (IDA_mem->ida_tempv2) 
-#define kk             (IDA_mem->ida_kk)
-#define hh             (IDA_mem->ida_hh)
-#define h0u            (IDA_mem->ida_h0u)
-#define tn             (IDA_mem->ida_tn)
-#define tretlast       (IDA_mem->ida_tretlast)
-#define cj             (IDA_mem->ida_cj)
-#define cjold          (IDA_mem->ida_cjold)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define cjlast         (IDA_mem->ida_cjlast)
-#define nbacktr        (IDA_mem->ida_nbacktr)
-#define nst            (IDA_mem->ida_nst)
-#define nre            (IDA_mem->ida_nre)
-#define ncfn           (IDA_mem->ida_ncfn)
-#define netf           (IDA_mem->ida_netf)
-#define nni            (IDA_mem->ida_nni)
-#define nsetups        (IDA_mem->ida_nsetups)
-#define ns             (IDA_mem->ida_ns)
-#define linit          (IDA_mem->ida_linit)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve) 
-#define lperf          (IDA_mem->ida_lperf)
-#define lfree          (IDA_mem->ida_lfree) 
-#define lmem           (IDA_mem->ida_lmem) 
-#define setupNonNull   (IDA_mem->ida_setupNonNull) 
-#define forceSetup     (IDA_mem->ida_forceSetup)
-#define knew           (IDA_mem->ida_knew)
-#define kused          (IDA_mem->ida_kused)          
-#define hused          (IDA_mem->ida_hused)         
-#define tolsf          (IDA_mem->ida_tolsf)      
-#define phase          (IDA_mem->ida_phase)
-#define epsNewt        (IDA_mem->ida_epsNewt)
-#define toldel         (IDA_mem->ida_toldel)
-#define ss             (IDA_mem->ida_ss)
-#define rr             (IDA_mem->ida_rr)
-#define psi            (IDA_mem->ida_psi)
-#define alpha          (IDA_mem->ida_alpha)
-#define beta           (IDA_mem->ida_beta)
-#define sigma          (IDA_mem->ida_sigma)
-#define gamma          (IDA_mem->ida_gamma)
-#define constraintsSet (IDA_mem->ida_constraintsSet)
-#define nrtfn          (IDA_mem->ida_nrtfn)
-#define tlo            (IDA_mem->ida_tlo)
-#define thi            (IDA_mem->ida_thi)
-#define toutc          (IDA_mem->ida_toutc)
-#define trout          (IDA_mem->ida_trout)
-#define ttol           (IDA_mem->ida_ttol)
-#define taskc          (IDA_mem->ida_taskc)
-#define irfnd          (IDA_mem->ida_irfnd)
-#define nge            (IDA_mem->ida_nge)
-
-/* Quadrature variables */
-
-#define quadr          (IDA_mem->ida_quadr)
-#define rhsQ           (IDA_mem->ida_rhsQ)
-#define errconQ        (IDA_mem->ida_errconQ)
-#define itolQ          (IDA_mem->ida_itolQ)
-#define rtolQ          (IDA_mem->ida_rtolQ)
-#define SatolQ         (IDA_mem->ida_SatolQ)
-#define VatolQ         (IDA_mem->ida_VatolQ)
-
-#define phiQ           (IDA_mem->ida_phiQ)
-#define yyQ            (IDA_mem->ida_yyQ)
-#define ypQ            (IDA_mem->ida_ypQ)
-#define ewtQ           (IDA_mem->ida_ewtQ)
-#define eeQ            (IDA_mem->ida_eeQ)
-#define nrQe           (IDA_mem->ida_nrQe)
-#define netfQ          (IDA_mem->ida_netfQ)
-#define ncfnQ          (IDA_mem->ida_ncfnQ)
-#define lrw1Q          (IDA_mem->ida_lrw1Q)
-#define liw1Q          (IDA_mem->ida_liw1Q)
-
-#define quadMallocDone (IDA_mem->ida_quadMallocDone)
-
-/* Sensitivity variables */
-#define sensi          (IDA_mem->ida_sensi)
-#define ism            (IDA_mem->ida_ism)
-
-#define resS           (IDA_mem->ida_resS)
-#define user_dataS     (IDA_mem->ida_user_dataS)
-#define resSDQ         (IDA_mem->ida_resSDQ)
-
-#define errconS        (IDA_mem->ida_errconS)
-#define itolS          (IDA_mem->ida_itolS)
-#define rtolS          (IDA_mem->ida_rtolS)
-#define SatolS         (IDA_mem->ida_SatolS)
-#define VatolS         (IDA_mem->ida_VatolS)
-#define sensMallocDone (IDA_mem->ida_sensMallocDone)
-
-/* Sensitivities for quadratures */
-#define quadr_sensi         (IDA_mem->ida_quadr_sensi)
-#define yyQS                (IDA_mem->ida_yyQS)
-#define phiQS               (IDA_mem->ida_phiQS)
-#define tempvQS             (IDA_mem->ida_tempvQS)
-#define errconQS            (IDA_mem->ida_errconQS)
-#define ewtQS               (IDA_mem->ida_ewtQS)
-#define itolQS              (IDA_mem->ida_itolQS)
-#define rtolQS              (IDA_mem->ida_rtolQS)
-#define SatolQS             (IDA_mem->ida_SatolQS)
-#define VatolQS             (IDA_mem->ida_VatolQS)
-#define eeQS                (IDA_mem->ida_eeQS)
-#define nrQeS               (IDA_mem->ida_nrQeS)
-#define nrQSe               (IDA_mem->ida_nrQSe)
-#define netfQS              (IDA_mem->ida_netfQS)
-#define quadSensMallocDone  (IDA_mem->ida_quadSensMallocDone)
-#define user_dataQS         (IDA_mem->ida_user_dataQS)
-#define rhsQS               (IDA_mem->ida_rhsQS)
-#define rhsQSDQ             (IDA_mem->ida_rhsQSDQ)
-#define savrhsQ             (IDA_mem->ida_savrhsQ)
-
-#define DQtype         (IDA_mem->ida_DQtype)
-#define DQrhomax       (IDA_mem->ida_DQrhomax)
-#define pbar           (IDA_mem->ida_pbar)
-#define p              (IDA_mem->ida_p)
-#define plist          (IDA_mem->ida_plist)
-
-#define maxcorS        (IDA_mem->ida_maxcorS)
-#define Ns             (IDA_mem->ida_Ns)
-#define phiS           (IDA_mem->ida_phiS)
-#define ewtS           (IDA_mem->ida_ewtS)
-#define yyS            (IDA_mem->ida_yyS)
-#define ypS            (IDA_mem->ida_ypS)
-#define deltaS         (IDA_mem->ida_deltaS)
-#define eeS            (IDA_mem->ida_eeS)
-#define tmpS1          (IDA_mem->ida_tmpS1)
-#define tmpS2          (IDA_mem->ida_tmpS2)
-#define tmpS3          (IDA_mem->ida_tmpS3)
-#define ssS            (IDA_mem->ida_ssS)
-#define nrSe           (IDA_mem->ida_nrSe)
-#define nreS           (IDA_mem->ida_nreS)
-#define nniS           (IDA_mem->ida_nniS)
-#define ncfnS          (IDA_mem->ida_ncfnS)
-#define netfS          (IDA_mem->ida_netfS)
-#define nsetupsS       (IDA_mem->ida_nsetupsS)
 
 
 /* 
@@ -2188,7 +1959,7 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Check if problem was malloc'ed */
-  if (IDA_mem->ida_MallocDone == FALSE) {
+  if (IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDASolve", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -2198,13 +1969,13 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_YRET_NULL);
     return(IDA_ILL_INPUT);
   }
-  yy = yret;  
+  IDA_mem->ida_yy = yret;  
 
   if (ypret == NULL) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_YPRET_NULL);
     return(IDA_ILL_INPUT);
   }
-  yp = ypret;
+  IDA_mem->ida_yp = ypret;
   
   if (tret == NULL) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_TRET_NULL);
@@ -2216,165 +1987,172 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
     return(IDA_ILL_INPUT);
   }
 
-  if (itask == IDA_NORMAL) toutc = tout;
-  taskc = itask;
+  if (itask == IDA_NORMAL)  IDA_mem->ida_toutc = tout;
+  IDA_mem->ida_taskc = itask;
 
   /* Sensitivity-specific tests (if using internal DQ functions) */
-  if (sensi && resSDQ) {
+  if (IDA_mem->ida_sensi && IDA_mem->ida_resSDQ) {
     /* Make sure we have the right 'user data' */
-    user_dataS = ida_mem;
+    IDA_mem->ida_user_dataS = ida_mem;
     /* Test if we have the problem parameters */
-    if(p == NULL) {
+    if(IDA_mem->ida_p == NULL) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_NULL_P);
       return(IDA_ILL_INPUT);
     }
   }
 
-  if (quadr_sensi && rhsQSDQ) {
-    user_dataQS = ida_mem;
+  if (IDA_mem->ida_quadr_sensi && IDA_mem->ida_rhsQSDQ) {
+    IDA_mem->ida_user_dataQS = ida_mem;
     /* Test if we have the problem parameters */
-    if(p == NULL) {
+    if(IDA_mem->ida_p == NULL) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_NULL_P);
       return(IDA_ILL_INPUT);
     }
   }
 
-  if (nst == 0) {       /* This is the first call */
+  if (IDA_mem->ida_nst == 0) {       /* This is the first call */
 
     /* Check inputs to IDA for correctness and consistency */
-    if (IDA_mem->ida_SetupDone == FALSE) {
+    if (IDA_mem->ida_SetupDone == SUNFALSE) {
       ier = IDAInitialSetup(IDA_mem);
       if (ier != IDA_SUCCESS) return(ier);
-      IDA_mem->ida_SetupDone = TRUE;
+      IDA_mem->ida_SetupDone = SUNTRUE;
     }
 
     /* On first call, check for tout - tn too small, set initial hh,
        check for approach to tstop, and scale phi[1], phiQ[1], and phiS[1] by hh.
        Also check for zeros of root function g at and near t0.    */
 
-    tdist = SUNRabs(tout - tn);
+    tdist = SUNRabs(tout - IDA_mem->ida_tn);
     if (tdist == ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_TOO_CLOSE);
       return(IDA_ILL_INPUT);
     }
-    troundoff = TWO*uround*(SUNRabs(tn) + SUNRabs(tout));
+    troundoff = TWO * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(tout));
     if (tdist < troundoff) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_TOO_CLOSE);
       return(IDA_ILL_INPUT);
     }
 
-    hh = hin;
-    if ( (hh != ZERO) && ((tout-tn)*hh < ZERO) ) {
+    IDA_mem->ida_hh = IDA_mem->ida_hin;
+    if ( (IDA_mem->ida_hh != ZERO) && ((tout-IDA_mem->ida_tn)*IDA_mem->ida_hh < ZERO) ) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_BAD_HINIT);
       return(IDA_ILL_INPUT);
     }
 
-    if (hh == ZERO) {
-      hh = PT001*tdist;
-      ypnorm = IDAWrmsNorm(IDA_mem, phi[1], ewt, suppressalg);
-      if (errconQ)
-        ypnorm = IDAQuadWrmsNormUpdate(IDA_mem, ypnorm, phiQ[1], ewtQ);
-      if (errconS)
-        ypnorm = IDASensWrmsNormUpdate(IDA_mem, ypnorm, phiS[1], ewtS, suppressalg);
-      if (errconQS)
-        ypnorm = IDAQuadSensWrmsNormUpdate(IDA_mem, ypnorm, phiQS[1], ewtQS);
-
-      if (ypnorm > HALF/hh) hh = HALF/ypnorm;
-      if (tout < tn) hh = -hh;
+    if (IDA_mem->ida_hh == ZERO) {
+      IDA_mem->ida_hh = PT001*tdist;
+      ypnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_phi[1],
+                           IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+      if (IDA_mem->ida_errconQ)
+        ypnorm = IDAQuadWrmsNormUpdate(IDA_mem, ypnorm,
+                                       IDA_mem->ida_phiQ[1], IDA_mem->ida_ewtQ);
+      if (IDA_mem->ida_errconS)
+        ypnorm = IDASensWrmsNormUpdate(IDA_mem, ypnorm, IDA_mem->ida_phiS[1],
+                                       IDA_mem->ida_ewtS, IDA_mem->ida_suppressalg);
+      if (IDA_mem->ida_errconQS)
+        ypnorm = IDAQuadSensWrmsNormUpdate(IDA_mem, ypnorm, IDA_mem->ida_phiQS[1],
+                                           IDA_mem->ida_ewtQS);
+
+      if (ypnorm > HALF/IDA_mem->ida_hh) IDA_mem->ida_hh = HALF/ypnorm;
+      if (tout < IDA_mem->ida_tn) IDA_mem->ida_hh = -IDA_mem->ida_hh;
     }
 
-    rh = SUNRabs(hh)*hmax_inv;
-    if (rh > ONE) hh /= rh;
+    rh = SUNRabs(IDA_mem->ida_hh) * IDA_mem->ida_hmax_inv;
+    if (rh > ONE) IDA_mem->ida_hh /= rh;
 
-    if (tstopset) {
-      if ( (tstop - tn)*hh <= ZERO) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+    if (IDA_mem->ida_tstopset) {
+      if ( (IDA_mem->ida_tstop - IDA_mem->ida_tn)*IDA_mem->ida_hh <= ZERO) {
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve",
+                        MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
         return(IDA_ILL_INPUT);
       }
-      if ( (tn + hh - tstop)*hh > ZERO) 
-        hh = (tstop - tn)*(ONE-FOUR*uround);
+      if ( (IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+        IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
     }
 
-    h0u = hh;
-    kk = 0; kused = 0;  /* set in case of an error return before a step */
+    IDA_mem->ida_h0u = IDA_mem->ida_hh;
+    IDA_mem->ida_kk = 0;
+    IDA_mem->ida_kused = 0;  /* set in case of an error return before a step */
 
     /* Check for exact zeros of the root functions at or near t0. */
-    if (nrtfn > 0) {
+    if (IDA_mem->ida_nrtfn > 0) {
       ier = IDARcheck1(IDA_mem);
       if (ier == IDA_RTFUNC_FAIL) {
-        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck1", MSG_RTFUNC_FAILED, tn);
+        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck1", MSG_RTFUNC_FAILED, IDA_mem->ida_tn);
         return(IDA_RTFUNC_FAIL);
       }
     }
 
-    N_VScale(hh, phi[1], phi[1]);                /* set phi[1] = hh*y' */
+    N_VScale(IDA_mem->ida_hh, IDA_mem->ida_phi[1], IDA_mem->ida_phi[1]);                /* set phi[1] = hh*y' */
 
-    if (quadr)
-      N_VScale(hh, phiQ[1], phiQ[1]);            /* set phiQ[1] = hh*yQ' */
+    if (IDA_mem->ida_quadr)
+      N_VScale(IDA_mem->ida_hh, IDA_mem->ida_phiQ[1], IDA_mem->ida_phiQ[1]);            /* set phiQ[1] = hh*yQ' */
 
-    if (sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(hh, phiS[1][is], phiS[1][is]);  /* set phiS[1][i] = hh*yS_i' */
+    if (IDA_mem->ida_sensi)
+      for (is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(IDA_mem->ida_hh, IDA_mem->ida_phiS[1][is], IDA_mem->ida_phiS[1][is]);  /* set phiS[1][i] = hh*yS_i' */
 
-    if (quadr_sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(hh, phiQS[1][is], phiQS[1][is]);  /* set phiQS[1][i] = hh*yQS_i' */
+    if (IDA_mem->ida_quadr_sensi)
+      for (is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(IDA_mem->ida_hh, IDA_mem->ida_phiQS[1][is], IDA_mem->ida_phiQS[1][is]);  /* set phiQS[1][i] = hh*yQS_i' */
       
 
     /* Set the convergence test constants epsNewt and toldel */
-    epsNewt = epcon;
-    toldel = PT0001 * epsNewt;
+    IDA_mem->ida_epsNewt = IDA_mem->ida_epcon;
+    IDA_mem->ida_toldel = PT0001 * IDA_mem->ida_epsNewt;
 
   } /* end of first-call block. */
 
   /* Call lperf function and set nstloc for later performance testing. */
 
-  if (lperf != NULL) lperf(IDA_mem, 0);
+  if (IDA_mem->ida_lperf != NULL)
+    IDA_mem->ida_lperf(IDA_mem, 0);
   nstloc = 0;
 
   /* If not the first call, perform all stopping tests. */
 
-  if (nst > 0) {
+  if (IDA_mem->ida_nst > 0) {
 
     /* First, check for a root in the last step taken, other than the
        last root found, if any.  If itask = IDA_ONE_STEP and y(tn) was not
        returned because of an intervening root, return y(tn) now.     */
 
-    if (nrtfn > 0) {
+    if (IDA_mem->ida_nrtfn > 0) {
 
-      irfndp = irfnd;
+      irfndp = IDA_mem->ida_irfnd;
       
       ier = IDARcheck2(IDA_mem);
 
       if (ier == CLOSERT) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDARcheck2", MSG_CLOSE_ROOTS, tlo);
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDARcheck2", MSG_CLOSE_ROOTS, IDA_mem->ida_tlo);
         return(IDA_ILL_INPUT);
       } else if (ier == IDA_RTFUNC_FAIL) {
-        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck2", MSG_RTFUNC_FAILED, tlo);
+        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck2", MSG_RTFUNC_FAILED, IDA_mem->ida_tlo);
         return(IDA_RTFUNC_FAIL);
       } else if (ier == RTFOUND) {
-        tretlast = *tret = tlo;
+        IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tlo;
         return(IDA_ROOT_RETURN);
       }
 
       /* If tn is distinct from tretlast (within roundoff),
          check remaining interval for roots */
-      troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-      if ( SUNRabs(tn - tretlast) > troundoff ) {
+      troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+      if ( SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tretlast) > troundoff ) {
         ier = IDARcheck3(IDA_mem);
         if (ier == IDA_SUCCESS) {     /* no root found */
-          irfnd = 0;
+          IDA_mem->ida_irfnd = 0;
           if ((irfndp == 1) && (itask == IDA_ONE_STEP)) {
-            tretlast = *tret = tn;
-            ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+            IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tn;
+            ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
             return(IDA_SUCCESS);
           }
         } else if (ier == RTFOUND) {  /* a new root was found */
-          irfnd = 1;
-          tretlast = *tret = tlo;
+          IDA_mem->ida_irfnd = 1;
+          IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tlo;
           return(IDA_ROOT_RETURN);
         } else if (ier == IDA_RTFUNC_FAIL) {  /* g failed */
-          IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck3", MSG_RTFUNC_FAILED, tlo);
+          IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck3", MSG_RTFUNC_FAILED, IDA_mem->ida_tlo);
           return(IDA_RTFUNC_FAIL);
         }
       }
@@ -2390,64 +2168,68 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
 
   /* Looping point for internal steps. */
 
-  loop {
+  for(;;) {
    
     /* Check for too many steps taken. */
 
-    if ( (mxstep>0) && (nstloc >= mxstep) ) {
-      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_MAX_STEPS, tn);
+    if ( (IDA_mem->ida_mxstep>0) && (nstloc >= IDA_mem->ida_mxstep) ) {
+      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_MAX_STEPS, IDA_mem->ida_tn);
       istate = IDA_TOO_MUCH_WORK;
-      *tret = tretlast = tn;
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
       break; /* Here yy=yret and yp=ypret already have the current solution. */
     }
 
     /* Call lperf to generate warnings of poor performance. */
 
-    if (lperf != NULL) lperf(IDA_mem, 1);
+    if (IDA_mem->ida_lperf != NULL)
+      IDA_mem->ida_lperf(IDA_mem, 1);
 
     /* Reset and check ewt, ewtQ, ewtS and ewtQS (if not first call). */
 
-    if (nst > 0) {
+    if (IDA_mem->ida_nst > 0) {
 
-      ier = efun(phi[0], ewt, edata);
+      ier = IDA_mem->ida_efun(IDA_mem->ida_phi[0],
+                              IDA_mem->ida_ewt, IDA_mem->ida_edata);
       if (ier != 0) {
-        if (itol == IDA_WF) IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWT_NOW_FAIL, tn);
-        else                IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWT_NOW_BAD, tn);
+        if (IDA_mem->ida_itol == IDA_WF)
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWT_NOW_FAIL, IDA_mem->ida_tn);
+        else
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWT_NOW_BAD, IDA_mem->ida_tn);
         istate = IDA_ILL_INPUT;
-        ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
-        *tret = tretlast = tn;
+        ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
+        *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
         break;
       }
 
-      if (quadr && errconQ) {
-        ier = IDAQuadEwtSet(IDA_mem, phiQ[0], ewtQ);
+      if (IDA_mem->ida_quadr && IDA_mem->ida_errconQ) {
+        ier = IDAQuadEwtSet(IDA_mem, IDA_mem->ida_phiQ[0], IDA_mem->ida_ewtQ);
         if (ier != 0) {
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTQ_NOW_BAD, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTQ_NOW_BAD, IDA_mem->ida_tn);
           istate = IDA_ILL_INPUT;
-          ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
-          *tret = tretlast = tn;
+          ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
+          *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
           break;
         }
       }
 
-      if (sensi) {
-        ier = IDASensEwtSet(IDA_mem, phiS[0], ewtS);
+      if (IDA_mem->ida_sensi) {
+        ier = IDASensEwtSet(IDA_mem, IDA_mem->ida_phiS[0], IDA_mem->ida_ewtS);
         if (ier != 0) {
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTS_NOW_BAD, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTS_NOW_BAD, IDA_mem->ida_tn);
           istate = IDA_ILL_INPUT;
-          ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
-          *tret = tretlast = tn;
+          ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
+          *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
           break;
         }
       }
 
-      if (quadr_sensi && errconQS) {
-        ier = IDAQuadSensEwtSet(IDA_mem, phiQS[0], ewtQS);
+      if (IDA_mem->ida_quadr_sensi && IDA_mem->ida_errconQS) {
+        ier = IDAQuadSensEwtSet(IDA_mem, IDA_mem->ida_phiQS[0], IDA_mem->ida_ewtQS);
         if (ier != 0) {
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTQS_NOW_BAD, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_EWTQS_NOW_BAD, IDA_mem->ida_tn);
           istate = IDA_ILL_INPUT;
-          ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
-          tretlast = *tret = tn;
+          ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
+          IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tn;
           break;
         }
       }
@@ -2456,21 +2238,25 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
     
     /* Check for too much accuracy requested. */
     
-    nrm = IDAWrmsNorm(IDA_mem, phi[0], ewt, suppressalg);
-    if (errconQ)
-      nrm = IDAQuadWrmsNormUpdate(IDA_mem, nrm, phiQ[0], ewtQ);
-    if (errconS)
-      nrm = IDASensWrmsNormUpdate(IDA_mem, nrm, phiS[0], ewtS, suppressalg);
-    if (errconQS)
-      nrm = IDAQuadSensWrmsNormUpdate(IDA_mem, nrm, phiQS[0], ewtQS);
-
-    tolsf = uround * nrm;
-    if (tolsf > ONE) {
-      tolsf *= TEN;
-      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_TOO_MUCH_ACC, tn);
+    nrm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_phi[0],
+                      IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+    if (IDA_mem->ida_errconQ)
+      nrm = IDAQuadWrmsNormUpdate(IDA_mem, nrm, IDA_mem->ida_phiQ[0],
+                                  IDA_mem->ida_ewtQ);
+    if (IDA_mem->ida_errconS)
+      nrm = IDASensWrmsNormUpdate(IDA_mem, nrm, IDA_mem->ida_phiS[0],
+                                  IDA_mem->ida_ewtS, IDA_mem->ida_suppressalg);
+    if (IDA_mem->ida_errconQS)
+      nrm = IDAQuadSensWrmsNormUpdate(IDA_mem, nrm, IDA_mem->ida_phiQS[0],
+                                      IDA_mem->ida_ewtQS);
+
+    IDA_mem->ida_tolsf = IDA_mem->ida_uround * nrm;
+    if (IDA_mem->ida_tolsf > ONE) {
+      IDA_mem->ida_tolsf *= TEN;
+      IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_TOO_MUCH_ACC, IDA_mem->ida_tn);
       istate = IDA_TOO_MUCH_ACC;
-      *tret = tretlast = tn;
-      if (nst > 0) ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
+      if (IDA_mem->ida_nst > 0) ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
       break;
     }
 
@@ -2482,34 +2268,35 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
 
     if (sflag != IDA_SUCCESS) {
       istate = IDAHandleFailure(IDA_mem, sflag);
-      *tret = tretlast = tn;
-      ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
+      ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
       break;
     }
     
     nstloc++;
 
-    /* If tstop is set and was reached, reset tn = tstop */
-    if (tstopset) {
-      troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-      if (SUNRabs(tn - tstop) <= troundoff) tn = tstop;
+    /* If tstop is set and was reached, reset IDA_mem->ida_tn = tstop */
+    if (IDA_mem->ida_tstopset) {
+      troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+      if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff)
+        IDA_mem->ida_tn = IDA_mem->ida_tstop;
     }
 
     /* After successful step, check for stop conditions; continue or break. */
 
     /* First check for root in the last step taken. */
 
-    if (nrtfn > 0) {
+    if (IDA_mem->ida_nrtfn > 0) {
 
       ier = IDARcheck3(IDA_mem);
 
       if (ier == RTFOUND) {  /* A new root was found */
-        irfnd = 1;
+        IDA_mem->ida_irfnd = 1;
         istate = IDA_ROOT_RETURN;
-        tretlast = *tret = tlo;
+        IDA_mem->ida_tretlast = *tret = IDA_mem->ida_tlo;
         break;
       } else if (ier == IDA_RTFUNC_FAIL) { /* g failed */
-        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck3", MSG_RTFUNC_FAILED, tlo);
+        IDAProcessError(IDA_mem, IDA_RTFUNC_FAIL, "IDAS", "IDARcheck3", MSG_RTFUNC_FAILED, IDA_mem->ida_tlo);
         istate = IDA_RTFUNC_FAIL;
         break;
       }
@@ -2519,11 +2306,11 @@ int IDASolve(void *ida_mem, realtype tout, realtype *tret,
        * as this may indicate a user error in the implementation
        * of the root function. */
 
-      if (nst==1) {
-        inactive_roots = FALSE;
-        for (ir=0; ir<nrtfn; ir++) { 
-          if (!gactive[ir]) {
-            inactive_roots = TRUE;
+      if (IDA_mem->ida_nst==1) {
+        inactive_roots = SUNFALSE;
+        for (ir=0; ir<IDA_mem->ida_nrtfn; ir++) { 
+          if (!IDA_mem->ida_gactive[ir]) {
+            inactive_roots = SUNTRUE;
             break;
           }
         }
@@ -2588,18 +2375,19 @@ int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
     return(IDA_BAD_DKY);
   }
   
-  if ((k < 0) || (k > kused)) {
+  if ((k < 0) || (k > IDA_mem->ida_kused)) {
     IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetDky", MSG_BAD_K);
     return(IDA_BAD_K);
   }
 
   /* Check t for legality.  Here tn - hused is t_{n-1}. */
 
-  tfuzz = HUNDRED * uround * (SUNRabs(tn) + SUNRabs(hh));
-  if (hh < ZERO) tfuzz = - tfuzz;
-  tp = tn - hused - tfuzz;
-  if ((t - tp)*hh < ZERO) {
-    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetDky", MSG_BAD_T, t, tn-hused, tn);
+  tfuzz = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+  if (IDA_mem->ida_hh < ZERO) tfuzz = - tfuzz;
+  tp = IDA_mem->ida_tn - IDA_mem->ida_hused - tfuzz;
+  if ((t - tp)*IDA_mem->ida_hh < ZERO) {
+    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetDky", MSG_BAD_T,
+                    t, IDA_mem->ida_tn-IDA_mem->ida_hused, IDA_mem->ida_tn);
     return(IDA_BAD_T);
   }
 
@@ -2609,7 +2397,7 @@ int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
     cjk_1[i] = 0;
   }
 
-  delt = t-tn;
+  delt = t-IDA_mem->ida_tn;
 
   for(i=0; i<=k; i++) {
 
@@ -2636,29 +2424,29 @@ int IDAGetDky(void *ida_mem, realtype t, int k, N_Vector dky)
         c_i^(i) can be always updated since c_i^(i) = -----  --------  ... -----
                                                       psi_j  psi_{j-1}     psi_1
       */
-      cjk[i] = cjk[i-1]*i/psi[i-1];
-      psij_1 = psi[i-1];
+      cjk[i] = cjk[i-1]*i / IDA_mem->ida_psi[i-1];
+      psij_1 = IDA_mem->ida_psi[i-1];
     }
 
     /* update c_j^(i) */
 
     /*j does not need to go till kused */
-    for(j=i+1; j<=kused-k+i; j++) {
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) {
 
-      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / psi[j-1];      
-      psij_1 = psi[j-1];
+      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / IDA_mem->ida_psi[j-1];      
+      psij_1 = IDA_mem->ida_psi[j-1];
     }
 
     /* save existing c_j^(i)'s */
-    for(j=i+1; j<=kused-k+i; j++) cjk_1[j] = cjk[j];
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) cjk_1[j] = cjk[j];
   }
 
   /* Compute sum (c_j(t) * phi(t)) */
 
   N_VConst(ZERO, dky);
-  for(j=k; j<=kused; j++)
+  for(j=k; j<=IDA_mem->ida_kused; j++)
   {
-    N_VLinearSum(ONE, dky, cjk[j], phi[j], dky);
+    N_VLinearSum(ONE, dky, cjk[j], IDA_mem->ida_phi[j], dky);
   }
 
   return(IDA_SUCCESS);
@@ -2683,9 +2471,9 @@ int IDAGetQuad(void *ida_mem, realtype *ptret, N_Vector yQout)
   }
   IDA_mem = (IDAMem)ida_mem;
 
-  *ptret = tretlast;
+  *ptret = IDA_mem->ida_tretlast;
 
-  return IDAGetQuadDky(ida_mem, tretlast, 0, yQout);
+  return IDAGetQuadDky(ida_mem, IDA_mem->ida_tretlast, 0, yQout);
 }
 
 /*
@@ -2711,7 +2499,7 @@ int IDAGetQuadDky(void *ida_mem, realtype t, int k, N_Vector dkyQ)
   IDA_mem = (IDAMem) ida_mem; 
 
   /* Ckeck if quadrature was initialized */
-  if (quadr != TRUE) {
+  if (IDA_mem->ida_quadr != SUNTRUE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadDky", MSG_NO_QUAD);
     return(IDA_NO_QUAD);
   }
@@ -2721,17 +2509,18 @@ int IDAGetQuadDky(void *ida_mem, realtype t, int k, N_Vector dkyQ)
     return(IDA_BAD_DKY);
   }
   
-  if ((k < 0) || (k > kk)) {
+  if ((k < 0) || (k > IDA_mem->ida_kk)) {
     IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetQuadDky", MSG_BAD_K);
     return(IDA_BAD_K);
   }
 
   /* Check t for legality.  Here tn - hused is t_{n-1}. */
  
-  tfuzz = HUNDRED * uround * (tn + hh);
-  tp = tn - hused - tfuzz;
-  if ( (t - tp)*hh < ZERO) {
-    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetQuadDky", MSG_BAD_T, t, tn-hused, tn);
+  tfuzz = HUNDRED * IDA_mem->ida_uround * (IDA_mem->ida_tn + IDA_mem->ida_hh);
+  tp = IDA_mem->ida_tn - IDA_mem->ida_hused - tfuzz;
+  if ( (t - tp)*IDA_mem->ida_hh < ZERO) {
+    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetQuadDky", MSG_BAD_T,
+                    t, IDA_mem->ida_tn-IDA_mem->ida_hused, IDA_mem->ida_tn);
     return(IDA_BAD_T);
   }
 
@@ -2740,7 +2529,7 @@ int IDAGetQuadDky(void *ida_mem, realtype t, int k, N_Vector dkyQ)
     cjk  [i] = 0;
     cjk_1[i] = 0;
   }
-  delt = t-tn;
+  delt = t-IDA_mem->ida_tn;
 
   for(i=0; i<=k; i++) {
 
@@ -2748,26 +2537,26 @@ int IDAGetQuadDky(void *ida_mem, realtype t, int k, N_Vector dkyQ)
       cjk[i] = 1;
       psij_1 = 0;
     }else {
-      cjk[i] = cjk[i-1]*i/psi[i-1];
-      psij_1 = psi[i-1];
+      cjk[i] = cjk[i-1]*i / IDA_mem->ida_psi[i-1];
+      psij_1 = IDA_mem->ida_psi[i-1];
     }
 
     /* update c_j^(i) */
-    for(j=i+1; j<=kused-k+i; j++) {
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) {
 
-      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / psi[j-1];      
-      psij_1 = psi[j-1];
+      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / IDA_mem->ida_psi[j-1];
+      psij_1 = IDA_mem->ida_psi[j-1];
     }
 
     /* save existing c_j^(i)'s */
-    for(j=i+1; j<=kused-k+i; j++) cjk_1[j] = cjk[j];
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) cjk_1[j] = cjk[j];
   }
 
   /* Compute sum (c_j(t) * phi(t)) */
   N_VConst(ZERO, dkyQ);
-  for(j=k; j<=kused; j++)
+  for(j=k; j<=IDA_mem->ida_kused; j++)
   {
-    N_VLinearSum(ONE, dkyQ, cjk[j], phiQ[j], dkyQ);
+    N_VLinearSum(ONE, dkyQ, cjk[j], IDA_mem->ida_phiQ[j], dkyQ);
   }
 
   return(IDA_SUCCESS);
@@ -2802,14 +2591,14 @@ int IDAGetSens(void *ida_mem, realtype *ptret, N_Vector *yySout)
   }
 
   /* Is the sensibility enabled? */
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSens", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *ptret = tretlast;
+  *ptret = IDA_mem->ida_tretlast;
   
-  for(is=0; is<Ns; is++)
+  for(is=0; is<IDA_mem->ida_Ns; is++)
     if( IDA_SUCCESS != (ierr = IDAGetSensDky1(ida_mem, *ptret, 0, is, yySout[is])) ) break;
 
   return(ierr);
@@ -2836,7 +2625,7 @@ int IDAGetSensDky(void *ida_mem, realtype t, int k, N_Vector *dkySout)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensDky", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
@@ -2846,12 +2635,12 @@ int IDAGetSensDky(void *ida_mem, realtype t, int k, N_Vector *dkySout)
     return(IDA_BAD_DKY);
   }
   
-  if ((k < 0) || (k > kk)) {
+  if ((k < 0) || (k > IDA_mem->ida_kk)) {
     IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetSensDky", MSG_BAD_K);
     return(IDA_BAD_K);
   } 
 
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     ier = IDAGetSensDky1(ida_mem, t, k, is, dkySout[is]);
     if (ier!=IDA_SUCCESS) break;
   }
@@ -2878,7 +2667,7 @@ int IDAGetSens1(void *ida_mem, realtype *ptret, int is, N_Vector yySret)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  *ptret = tretlast;
+  *ptret = IDA_mem->ida_tretlast;
 
   return IDAGetSensDky1(ida_mem, *ptret, 0, is, yySret);
 }
@@ -2911,7 +2700,7 @@ int IDAGetSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyS)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensDky1", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
@@ -2922,23 +2711,24 @@ int IDAGetSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyS)
   }
 
   /* Is the requested sensitivity index valid? */
-  if(is<0 || is >= Ns) {
+  if(is<0 || is >= IDA_mem->ida_Ns) {
     IDAProcessError(IDA_mem, IDA_BAD_IS, "IDAS", "IDAGetSensDky1", MSG_BAD_IS);
   }
   
   /* Is the requested order valid? */
-  if ((k < 0) || (k > kused)) {
+  if ((k < 0) || (k > IDA_mem->ida_kused)) {
     IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetSensDky1", MSG_BAD_K);
     return(IDA_BAD_K);
   } 
 
   /* Check t for legality.  Here tn - hused is t_{n-1}. */
  
-  tfuzz = HUNDRED * uround * (SUNRabs(tn) + SUNRabs(hh));
-  if (hh < ZERO) tfuzz = - tfuzz;
-  tp = tn - hused - tfuzz;
-  if ((t - tp)*hh < ZERO) {
-    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetSensDky1", MSG_BAD_T, t, tn-hused, tn);
+  tfuzz = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+  if (IDA_mem->ida_hh < ZERO) tfuzz = - tfuzz;
+  tp = IDA_mem->ida_tn - IDA_mem->ida_hused - tfuzz;
+  if ((t - tp)*IDA_mem->ida_hh < ZERO) {
+    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetSensDky1", MSG_BAD_T,
+                    t, IDA_mem->ida_tn-IDA_mem->ida_hused, IDA_mem->ida_tn);
     return(IDA_BAD_T);
   }
 
@@ -2948,7 +2738,7 @@ int IDAGetSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyS)
     cjk_1[i] = 0;
   }
 
-  delt = t - tn;
+  delt = t - IDA_mem->ida_tn;
 
   for(i=0; i<=k; i++) {
     
@@ -2956,25 +2746,25 @@ int IDAGetSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyS)
       cjk[i] = 1;
       psij_1 = 0;
     }else {     
-      cjk[i] = cjk[i-1]*i/psi[i-1];
-      psij_1 = psi[i-1];
+      cjk[i] = cjk[i-1]*i / IDA_mem->ida_psi[i-1];
+      psij_1 = IDA_mem->ida_psi[i-1];
     }
 
     /* Update cjk based on the reccurence */ 
-    for(j=i+1; j<=kused-k+i; j++) {
-      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / psi[j-1];      
-      psij_1 = psi[j-1];
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) {
+      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / IDA_mem->ida_psi[j-1];      
+      psij_1 = IDA_mem->ida_psi[j-1];
     }
 
     /* Update cjk_1 for the next step */
-    for(j=i+1; j<=kused-k+i; j++) cjk_1[j] = cjk[j];
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) cjk_1[j] = cjk[j];
   }  
 
   /* Compute sum (c_j(t) * phi(t)) */
   N_VConst(ZERO, dkyS);
-  for(j=k; j<=kused; j++)
+  for(j=k; j<=IDA_mem->ida_kused; j++)
   {
-    N_VLinearSum(ONE, dkyS, cjk[j], phiS[j][is], dkyS);
+    N_VLinearSum(ONE, dkyS, cjk[j], IDA_mem->ida_phiS[j][is], dkyS);
   }
 
   return(IDA_SUCCESS);
@@ -3008,14 +2798,14 @@ int IDAGetQuadSens(void *ida_mem, realtype *ptret, N_Vector *yyQSout)
   }
 
   /* Is the sensibility enabled? */
-  if (quadr_sensi==FALSE) {
+  if (IDA_mem->ida_quadr_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSens", MSG_NO_QUADSENSI);
     return(IDA_NO_SENS);
   }
 
-  *ptret = tretlast;
+  *ptret = IDA_mem->ida_tretlast;
   
-  for(is=0; is<Ns; is++)
+  for(is=0; is<IDA_mem->ida_Ns; is++)
     if( IDA_SUCCESS != (ierr = IDAGetQuadSensDky1(ida_mem, *ptret, 0, is, yyQSout[is])) ) break;
 
   return(ierr);
@@ -3042,12 +2832,12 @@ int IDAGetQuadSensDky(void *ida_mem, realtype t, int k, N_Vector *dkyQSout)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSensDky", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  if (quadr_sensi==FALSE) {
+  if (IDA_mem->ida_quadr_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensDky", MSG_NO_QUADSENSI);
     return(IDA_NO_QUADSENS);
   }
@@ -3057,12 +2847,12 @@ int IDAGetQuadSensDky(void *ida_mem, realtype t, int k, N_Vector *dkyQSout)
     return(IDA_BAD_DKY);
   }
   
-  if ((k < 0) || (k > kk)) {
+  if ((k < 0) || (k > IDA_mem->ida_kk)) {
     IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetQuadSensDky", MSG_BAD_K);
     return(IDA_BAD_K);
   } 
 
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     ier = IDAGetQuadSensDky1(ida_mem, t, k, is, dkyQSout[is]);
     if (ier!=IDA_SUCCESS) break;
   }
@@ -3089,12 +2879,12 @@ int IDAGetQuadSens1(void *ida_mem, realtype *ptret, int is, N_Vector yyQSret)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSens1", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  if (quadr_sensi==FALSE) {
+  if (IDA_mem->ida_quadr_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSens1", MSG_NO_QUADSENSI);
     return(IDA_NO_QUADSENS);
   }
@@ -3104,7 +2894,7 @@ int IDAGetQuadSens1(void *ida_mem, realtype *ptret, int is, N_Vector yyQSret)
     return(IDA_BAD_DKY);
   }
 
-  *ptret = tretlast;
+  *ptret = IDA_mem->ida_tretlast;
 
   return IDAGetQuadSensDky1(ida_mem, *ptret, 0, is, yyQSret);
 }
@@ -3137,12 +2927,12 @@ int IDAGetQuadSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyQS)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetQuadSensDky1", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  if (quadr_sensi==FALSE) {
+  if (IDA_mem->ida_quadr_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensDky1", MSG_NO_QUADSENSI);
     return(IDA_NO_QUADSENS);
   }
@@ -3154,23 +2944,24 @@ int IDAGetQuadSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyQS)
   }
 
   /* Is the requested sensitivity index valid*/
-  if(is<0 || is >= Ns) {
+  if(is<0 || is >= IDA_mem->ida_Ns) {
     IDAProcessError(IDA_mem, IDA_BAD_IS, "IDAS", "IDAGetQuadSensDky1", MSG_BAD_IS);
   }
   
   /* Is the requested order valid? */
-  if ((k < 0) || (k > kused)) {
+  if ((k < 0) || (k > IDA_mem->ida_kused)) {
     IDAProcessError(IDA_mem, IDA_BAD_K, "IDAS", "IDAGetQuadSensDky1", MSG_BAD_K);
     return(IDA_BAD_K);
   } 
 
   /* Check t for legality.  Here tn - hused is t_{n-1}. */
  
-  tfuzz = HUNDRED * uround * (SUNRabs(tn) + SUNRabs(hh));
-  if (hh < ZERO) tfuzz = - tfuzz;
-  tp = tn - hused - tfuzz;
-  if ((t - tp)*hh < ZERO) {
-    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetQuadSensDky1", MSG_BAD_T, t, tn-hused, tn);
+  tfuzz = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+  if (IDA_mem->ida_hh < ZERO) tfuzz = - tfuzz;
+  tp = IDA_mem->ida_tn - IDA_mem->ida_hused - tfuzz;
+  if ((t - tp)*IDA_mem->ida_hh < ZERO) {
+    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetQuadSensDky1", MSG_BAD_T,
+                    t, IDA_mem->ida_tn-IDA_mem->ida_hused, IDA_mem->ida_tn);
     return(IDA_BAD_T);
   }
 
@@ -3180,7 +2971,7 @@ int IDAGetQuadSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyQS)
     cjk_1[i] = 0;
   }
 
-  delt = t - tn;
+  delt = t - IDA_mem->ida_tn;
 
   for(i=0; i<=k; i++) {
     
@@ -3188,25 +2979,25 @@ int IDAGetQuadSensDky1(void *ida_mem, realtype t, int k, int is, N_Vector dkyQS)
       cjk[i] = 1;
       psij_1 = 0;
     }else {     
-      cjk[i] = cjk[i-1]*i/psi[i-1];
-      psij_1 = psi[i-1];
+      cjk[i] = cjk[i-1]*i / IDA_mem->ida_psi[i-1];
+      psij_1 = IDA_mem->ida_psi[i-1];
     }
 
     /* Update cjk based on the reccurence */ 
-    for(j=i+1; j<=kused-k+i; j++) {
-      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / psi[j-1];      
-      psij_1 = psi[j-1];
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) {
+      cjk[j] = ( i* cjk_1[j-1] + cjk[j-1] * (delt + psij_1) ) / IDA_mem->ida_psi[j-1];      
+      psij_1 = IDA_mem->ida_psi[j-1];
     }
 
     /* Update cjk_1 for the next step */
-    for(j=i+1; j<=kused-k+i; j++) cjk_1[j] = cjk[j];
+    for(j=i+1; j<=IDA_mem->ida_kused-k+i; j++) cjk_1[j] = cjk[j];
   }  
 
   /* Compute sum (c_j(t) * phi(t)) */
   N_VConst(ZERO, dkyQS);
-  for(j=k; j<=kused; j++)
+  for(j=k; j<=IDA_mem->ida_kused; j++)
   {
-    N_VLinearSum(ONE, dkyQS, cjk[j], phiQS[j][is], dkyQS);
+    N_VLinearSum(ONE, dkyQS, cjk[j], IDA_mem->ida_phiQS[j][is], dkyQS);
   }
 
   return(IDA_SUCCESS);
@@ -3245,15 +3036,16 @@ void IDAFree(void **ida_mem)
 
   IDAAdjFree(IDA_mem);
 
-  if (lfree != NULL) lfree(IDA_mem);
+  if (IDA_mem->ida_lfree != NULL)
+    IDA_mem->ida_lfree(IDA_mem);
 
-  if (nrtfn > 0) {
-    free(glo); glo = NULL; 
-    free(ghi);  ghi = NULL;
-    free(grout);  grout = NULL;
-    free(iroots); iroots = NULL;
-    free(rootdir); rootdir = NULL;
-    free(gactive); gactive = NULL;
+  if (IDA_mem->ida_nrtfn > 0) {
+    free(IDA_mem->ida_glo); IDA_mem->ida_glo = NULL; 
+    free(IDA_mem->ida_ghi);  IDA_mem->ida_ghi = NULL;
+    free(IDA_mem->ida_grout);  IDA_mem->ida_grout = NULL;
+    free(IDA_mem->ida_iroots); IDA_mem->ida_iroots = NULL;
+    free(IDA_mem->ida_rootdir); IDA_mem->ida_rootdir = NULL;
+    free(IDA_mem->ida_gactive); IDA_mem->ida_gactive = NULL;
   }
 
   free(*ida_mem);
@@ -3275,10 +3067,10 @@ void IDAQuadFree(void *ida_mem)
   if (ida_mem == NULL) return;
   IDA_mem = (IDAMem) ida_mem;
 
-  if(quadMallocDone) {
+  if(IDA_mem->ida_quadMallocDone) {
     IDAQuadFreeVectors(IDA_mem);
-    quadMallocDone = FALSE;
-    quadr = FALSE;
+    IDA_mem->ida_quadMallocDone = SUNFALSE;
+    IDA_mem->ida_quadr = SUNFALSE;
   }
 }
 
@@ -3297,10 +3089,10 @@ void IDASensFree(void *ida_mem)
   if (ida_mem == NULL) return;
   IDA_mem = (IDAMem) ida_mem;
 
-  if(sensMallocDone) {
+  if(IDA_mem->ida_sensMallocDone) {
     IDASensFreeVectors(IDA_mem);
-    sensMallocDone = FALSE;
-    sensi = FALSE;
+    IDA_mem->ida_sensMallocDone = SUNFALSE;
+    IDA_mem->ida_sensi = SUNFALSE;
   }
 }
 
@@ -3318,10 +3110,10 @@ void IDAQuadSensFree(void* ida_mem)
   if (ida_mem==NULL) return;
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadSensMallocDone) {
+  if (IDA_mem->ida_quadSensMallocDone) {
     IDAQuadSensFreeVectors(IDA_mem);
-    quadSensMallocDone=FALSE;
-    quadr_sensi = FALSE;
+    IDA_mem->ida_quadSensMallocDone=SUNFALSE;
+    IDA_mem->ida_quadr_sensi = SUNFALSE;
   }
 }
 
@@ -3335,7 +3127,7 @@ void IDAQuadSensFree(void* ida_mem)
  * IDACheckNvector
  *
  * This routine checks if all required vector operations are present.
- * If any of them is missing it returns FALSE.
+ * If any of them is missing it returns SUNFALSE.
  */
 
 static booleantype IDACheckNvector(N_Vector tmpl)
@@ -3351,9 +3143,9 @@ static booleantype IDACheckNvector(N_Vector tmpl)
      (tmpl->ops->nvaddconst     == NULL) ||
      (tmpl->ops->nvwrmsnorm     == NULL) ||
      (tmpl->ops->nvmin          == NULL))
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 /* 
@@ -3368,8 +3160,8 @@ static booleantype IDACheckNvector(N_Vector tmpl)
  * This routine allocates the IDA vectors ewt, tempv1, tempv2, and
  * phi[0], ..., phi[maxord].
  * If all memory allocations are successful, IDAAllocVectors returns 
- * TRUE. Otherwise all allocated memory is freed and IDAAllocVectors 
- * returns FALSE.
+ * SUNTRUE. Otherwise all allocated memory is freed and IDAAllocVectors 
+ * returns SUNFALSE.
  * This routine also sets the optional outputs lrw and liw, which are
  * (respectively) the lengths of the real and integer work spaces
  * allocated here.
@@ -3381,66 +3173,67 @@ static booleantype IDAAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
 
   /* Allocate ewt, ee, delta, tempv1, tempv2 */
   
-  ewt = N_VClone(tmpl);
-  if (ewt == NULL) return(FALSE);
+  IDA_mem->ida_ewt = N_VClone(tmpl);
+  if (IDA_mem->ida_ewt == NULL) return(SUNFALSE);
 
-  ee = N_VClone(tmpl);
-  if (ee == NULL) {
-    N_VDestroy(ewt);
-    return(FALSE);
+  IDA_mem->ida_ee = N_VClone(tmpl);
+  if (IDA_mem->ida_ee == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    return(SUNFALSE);
   }
 
-  delta = N_VClone(tmpl);
-  if (delta == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(ee);
-    return(FALSE);
+  IDA_mem->ida_delta = N_VClone(tmpl);
+  if (IDA_mem->ida_delta == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    N_VDestroy(IDA_mem->ida_ee);
+    return(SUNFALSE);
   }
 
-  tempv1 = N_VClone(tmpl);
-  if (tempv1 == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(ee);
-    N_VDestroy(delta);
-    return(FALSE);
+  IDA_mem->ida_tempv1 = N_VClone(tmpl);
+  if (IDA_mem->ida_tempv1 == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    N_VDestroy(IDA_mem->ida_ee);
+    N_VDestroy(IDA_mem->ida_delta);
+    return(SUNFALSE);
   }
 
-  tempv2= N_VClone(tmpl);
-  if (tempv2 == NULL) {
-    N_VDestroy(ewt);
-    N_VDestroy(ee);
-    N_VDestroy(delta);
-    N_VDestroy(tempv1);
-    return(FALSE);
+  IDA_mem->ida_tempv2= N_VClone(tmpl);
+  if (IDA_mem->ida_tempv2 == NULL) {
+    N_VDestroy(IDA_mem->ida_ewt);
+    N_VDestroy(IDA_mem->ida_ee);
+    N_VDestroy(IDA_mem->ida_delta);
+    N_VDestroy(IDA_mem->ida_tempv1);
+    return(SUNFALSE);
   }
 
-  savres = tempv1;
+  IDA_mem->ida_savres = IDA_mem->ida_tempv1;
 
   /* Allocate phi[0] ... phi[maxord].  Make sure phi[2] and phi[3] are
   allocated (for use as temporary vectors), regardless of maxord.       */
 
-  maxcol = SUNMAX(maxord,3);
+  maxcol = SUNMAX(IDA_mem->ida_maxord,3);
   for (j=0; j <= maxcol; j++) {
-    phi[j] = N_VClone(tmpl);
-    if (phi[j] == NULL) {
-      N_VDestroy(ewt);
-      N_VDestroy(ee);
-      N_VDestroy(delta);
-      N_VDestroy(tempv1);
-      N_VDestroy(tempv2);
-      for (i=0; i < j; i++) N_VDestroy(phi[i]);
-      return(FALSE);
+    IDA_mem->ida_phi[j] = N_VClone(tmpl);
+    if (IDA_mem->ida_phi[j] == NULL) {
+      N_VDestroy(IDA_mem->ida_ewt);
+      N_VDestroy(IDA_mem->ida_ee);
+      N_VDestroy(IDA_mem->ida_delta);
+      N_VDestroy(IDA_mem->ida_tempv1);
+      N_VDestroy(IDA_mem->ida_tempv2);
+      for (i=0; i < j; i++)
+        N_VDestroy(IDA_mem->ida_phi[i]);
+      return(SUNFALSE);
     }
   }
 
   /* Update solver workspace lengths  */
-  lrw += (maxcol + 6)*lrw1;
-  liw += (maxcol + 6)*liw1;
+  IDA_mem->ida_lrw += (maxcol + 6)*IDA_mem->ida_lrw1;
+  IDA_mem->ida_liw += (maxcol + 6)*IDA_mem->ida_liw1;
 
   /* Store the value of maxord used here */
-  IDA_mem->ida_maxord_alloc = maxord;
+  IDA_mem->ida_maxord_alloc = IDA_mem->ida_maxord;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -3453,33 +3246,36 @@ static void IDAFreeVectors(IDAMem IDA_mem)
 {
   int j, maxcol;
   
-  N_VDestroy(ewt);       ewt = NULL;
-  N_VDestroy(ee);         ee = NULL;
-  N_VDestroy(delta);   delta = NULL;
-  N_VDestroy(tempv1); tempv1 = NULL;
-  N_VDestroy(tempv2); tempv2 = NULL;
+  N_VDestroy(IDA_mem->ida_ewt);       IDA_mem->ida_ewt = NULL;
+  N_VDestroy(IDA_mem->ida_ee);         IDA_mem->ida_ee = NULL;
+  N_VDestroy(IDA_mem->ida_delta);   IDA_mem->ida_delta = NULL;
+  N_VDestroy(IDA_mem->ida_tempv1); IDA_mem->ida_tempv1 = NULL;
+  N_VDestroy(IDA_mem->ida_tempv2); IDA_mem->ida_tempv2 = NULL;
   maxcol = SUNMAX(IDA_mem->ida_maxord_alloc,3);
-  for(j=0; j <= maxcol; j++) { N_VDestroy(phi[j]); phi[j] = NULL;}
+  for(j=0; j <= maxcol; j++) {
+    N_VDestroy(IDA_mem->ida_phi[j]);
+    IDA_mem->ida_phi[j] = NULL;
+  }
 
-  lrw -= (maxcol + 6)*lrw1;
-  liw -= (maxcol + 6)*liw1;
+  IDA_mem->ida_lrw -= (maxcol + 6)*IDA_mem->ida_lrw1;
+  IDA_mem->ida_liw -= (maxcol + 6)*IDA_mem->ida_liw1;
 
   if (IDA_mem->ida_VatolMallocDone) {
-    N_VDestroy(Vatol); Vatol = NULL;
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(IDA_mem->ida_Vatol); IDA_mem->ida_Vatol = NULL;
+    IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw -= IDA_mem->ida_liw1;
   }
 
   if (IDA_mem->ida_constraintsMallocDone) {
-    N_VDestroy(constraints); constraints = NULL;
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(IDA_mem->ida_constraints); IDA_mem->ida_constraints = NULL;
+    IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw -= IDA_mem->ida_liw1;
   }
 
   if (IDA_mem->ida_idMallocDone) {
-    N_VDestroy(id); id = NULL;
-    lrw -= lrw1;
-    liw -= liw1;
+    N_VDestroy(IDA_mem->ida_id); IDA_mem->ida_id = NULL;
+    IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw -= IDA_mem->ida_liw1;
   }
 
 }
@@ -3487,11 +3283,11 @@ static void IDAFreeVectors(IDAMem IDA_mem)
 /*
  * IDAQuadAllocVectors
  *
- * NOTE: Space for ewtQ is allocated even when errconQ=FALSE, 
+ * NOTE: Space for ewtQ is allocated even when errconQ=SUNFALSE, 
  * although in this case, ewtQ is never used. The reason for this
  * decision is to allow the user to re-initialize the quadrature
- * computation with errconQ=TRUE, after an initialization with
- * errconQ=FALSE, without new memory allocation within 
+ * computation with errconQ=SUNTRUE, after an initialization with
+ * errconQ=SUNFALSE, without new memory allocation within 
  * IDAQuadReInit.
  */
 
@@ -3500,51 +3296,51 @@ static booleantype IDAQuadAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
   int i, j;
 
   /* Allocate yyQ */
-  yyQ = N_VClone(tmpl);
-  if (yyQ == NULL) {
-    return (FALSE);
+  IDA_mem->ida_yyQ = N_VClone(tmpl);
+  if (IDA_mem->ida_yyQ == NULL) {
+    return (SUNFALSE);
   }
 
   /* Allocate ypQ */
-  ypQ = N_VClone(tmpl);
-  if (ypQ == NULL) {
-    N_VDestroy(yyQ);
-    return (FALSE);
+  IDA_mem->ida_ypQ = N_VClone(tmpl);
+  if (IDA_mem->ida_ypQ == NULL) {
+    N_VDestroy(IDA_mem->ida_yyQ);
+    return (SUNFALSE);
   }
 
   /* Allocate ewtQ */
-  ewtQ = N_VClone(tmpl);
-  if (ewtQ == NULL) {
-    N_VDestroy(yyQ);
-    N_VDestroy(ypQ);
-    return (FALSE);
+  IDA_mem->ida_ewtQ = N_VClone(tmpl);
+  if (IDA_mem->ida_ewtQ == NULL) {
+    N_VDestroy(IDA_mem->ida_yyQ);
+    N_VDestroy(IDA_mem->ida_ypQ);
+    return (SUNFALSE);
   }
 
   /* Allocate eeQ */
-  eeQ = N_VClone(tmpl);
-  if (eeQ == NULL) {
-    N_VDestroy(yyQ);
-    N_VDestroy(ypQ);
-    N_VDestroy(ewtQ);
-    return (FALSE);
-  }
-
-  for (j=0; j <= maxord; j++) {
-    phiQ[j] = N_VClone(tmpl);
-    if (phiQ[j] == NULL) {
-      N_VDestroy(yyQ);
-      N_VDestroy(ypQ);
-      N_VDestroy(ewtQ);
-      N_VDestroy(eeQ);
-      for (i=0; i < j; i++) N_VDestroy(phiQ[i]);
-      return(FALSE);
+  IDA_mem->ida_eeQ = N_VClone(tmpl);
+  if (IDA_mem->ida_eeQ == NULL) {
+    N_VDestroy(IDA_mem->ida_yyQ);
+    N_VDestroy(IDA_mem->ida_ypQ);
+    N_VDestroy(IDA_mem->ida_ewtQ);
+    return (SUNFALSE);
+  }
+
+  for (j=0; j <= IDA_mem->ida_maxord; j++) {
+    IDA_mem->ida_phiQ[j] = N_VClone(tmpl);
+    if (IDA_mem->ida_phiQ[j] == NULL) {
+      N_VDestroy(IDA_mem->ida_yyQ);
+      N_VDestroy(IDA_mem->ida_ypQ);
+      N_VDestroy(IDA_mem->ida_ewtQ);
+      N_VDestroy(IDA_mem->ida_eeQ);
+      for (i=0; i < j; i++) N_VDestroy(IDA_mem->ida_phiQ[i]);
+      return(SUNFALSE);
     }
   }
 
-  lrw += (maxord+4)*lrw1Q;
-  liw += (maxord+4)*liw1Q;
+  IDA_mem->ida_lrw += (IDA_mem->ida_maxord+4)*IDA_mem->ida_lrw1Q;
+  IDA_mem->ida_liw += (IDA_mem->ida_maxord+4)*IDA_mem->ida_liw1Q;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 
@@ -3559,22 +3355,25 @@ static void IDAQuadFreeVectors(IDAMem IDA_mem)
 {
   int j;
 
-  N_VDestroy(yyQ);   yyQ = NULL;
-  N_VDestroy(ypQ);   ypQ = NULL;
-  N_VDestroy(ewtQ); ewtQ = NULL;
-  N_VDestroy(eeQ);   eeQ = NULL;
-  for(j=0; j <= maxord; j++) { N_VDestroy(phiQ[j]); phiQ[j] = NULL;}
+  N_VDestroy(IDA_mem->ida_yyQ);   IDA_mem->ida_yyQ = NULL;
+  N_VDestroy(IDA_mem->ida_ypQ);   IDA_mem->ida_ypQ = NULL;
+  N_VDestroy(IDA_mem->ida_ewtQ); IDA_mem->ida_ewtQ = NULL;
+  N_VDestroy(IDA_mem->ida_eeQ);   IDA_mem->ida_eeQ = NULL;
+  for(j=0; j <= IDA_mem->ida_maxord; j++) {
+    N_VDestroy(IDA_mem->ida_phiQ[j]);
+    IDA_mem->ida_phiQ[j] = NULL;
+  }
 
-  lrw -= (maxord+5)*lrw1Q;
-  liw -= (maxord+5)*liw1Q;
+  IDA_mem->ida_lrw -= (IDA_mem->ida_maxord+5)*IDA_mem->ida_lrw1Q;
+  IDA_mem->ida_liw -= (IDA_mem->ida_maxord+5)*IDA_mem->ida_liw1Q;
 
   if (IDA_mem->ida_VatolQMallocDone) {
-    N_VDestroy(VatolQ); VatolQ = NULL;
-    lrw -= lrw1Q;
-    liw -= liw1Q;
+    N_VDestroy(IDA_mem->ida_VatolQ); IDA_mem->ida_VatolQ = NULL;
+    IDA_mem->ida_lrw -= IDA_mem->ida_lrw1Q;
+    IDA_mem->ida_liw -= IDA_mem->ida_liw1Q;
   }
 
-  IDA_mem->ida_VatolQMallocDone = FALSE;
+  IDA_mem->ida_VatolQMallocDone = SUNFALSE;
 }
 
 /*
@@ -3587,115 +3386,115 @@ static booleantype IDASensAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
 {
   int j, maxcol;
   
-  tmpS1 = tempv1;
-  tmpS2 = tempv2;
+  IDA_mem->ida_tmpS1 = IDA_mem->ida_tempv1;
+  IDA_mem->ida_tmpS2 = IDA_mem->ida_tempv2;
 
   /* Allocate space for workspace vectors */
 
-  tmpS3 = N_VClone(tmpl);
-  if (tmpS3==NULL) {
-    return(FALSE);
+  IDA_mem->ida_tmpS3 = N_VClone(tmpl);
+  if (IDA_mem->ida_tmpS3==NULL) {
+    return(SUNFALSE);
   }
   
-  ewtS = N_VCloneVectorArray(Ns, tmpl);
-  if (ewtS==NULL) {
-    N_VDestroy(tmpS3);
-    return(FALSE);
+  IDA_mem->ida_ewtS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_ewtS==NULL) {
+    N_VDestroy(IDA_mem->ida_tmpS3);
+    return(SUNFALSE);
   }
 
-  eeS = N_VCloneVectorArray(Ns, tmpl);
-  if (eeS==NULL) {
-    N_VDestroy(tmpS3);
-    N_VDestroyVectorArray(ewtS, Ns);
-    return(FALSE);
+  IDA_mem->ida_eeS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_eeS==NULL) {
+    N_VDestroy(IDA_mem->ida_tmpS3);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+    return(SUNFALSE);
   }
 
-  yyS = N_VCloneVectorArray(Ns, tmpl);
-  if (yyS==NULL) {
-    N_VDestroyVectorArray(eeS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroy(tmpS3);
-    return(FALSE);
+  IDA_mem->ida_yyS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_yyS==NULL) {
+    N_VDestroyVectorArray(IDA_mem->ida_eeS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+    N_VDestroy(IDA_mem->ida_tmpS3);
+    return(SUNFALSE);
   }
   
-  ypS = N_VCloneVectorArray(Ns, tmpl);
-  if (ypS==NULL) {
-    N_VDestroyVectorArray(yyS, Ns);
-    N_VDestroyVectorArray(eeS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroy(tmpS3);
-    return(FALSE);
+  IDA_mem->ida_ypS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_ypS==NULL) {
+    N_VDestroyVectorArray(IDA_mem->ida_yyS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_eeS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+    N_VDestroy(IDA_mem->ida_tmpS3);
+    return(SUNFALSE);
   }
   
-  deltaS = N_VCloneVectorArray(Ns, tmpl);
-  if (deltaS==NULL) {
-    N_VDestroyVectorArray(ypS, Ns);
-    N_VDestroyVectorArray(yyS, Ns);
-    N_VDestroyVectorArray(eeS, Ns);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroy(tmpS3);
-    return(FALSE);
+  IDA_mem->ida_deltaS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_deltaS==NULL) {
+    N_VDestroyVectorArray(IDA_mem->ida_ypS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_yyS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_eeS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+    N_VDestroy(IDA_mem->ida_tmpS3);
+    return(SUNFALSE);
   }
 
   /* Update solver workspace lengths */
-  lrw += (3*Ns+1)*lrw1;
-  liw += (3*Ns+1)*liw1;
+  IDA_mem->ida_lrw += (3*IDA_mem->ida_Ns+1)*IDA_mem->ida_lrw1;
+  IDA_mem->ida_liw += (3*IDA_mem->ida_Ns+1)*IDA_mem->ida_liw1;
 
   /* Allocate space for phiS */
   /*  Make sure phiS[2], phiS[3] and phiS[4] are
       allocated (for use as temporary vectors), regardless of maxord.*/
 
-  maxcol = SUNMAX(maxord,4);
+  maxcol = SUNMAX(IDA_mem->ida_maxord,4);
   for (j=0; j <= maxcol; j++) {
-    phiS[j] = N_VCloneVectorArray(Ns, tmpl);
-    if (phiS[j] == NULL) {
-      N_VDestroy(tmpS3);
-      N_VDestroyVectorArray(ewtS, Ns);
-      N_VDestroyVectorArray(eeS, Ns);
-      N_VDestroyVectorArray(yyS, Ns);
-      N_VDestroyVectorArray(ypS, Ns);
-      N_VDestroyVectorArray(deltaS, Ns);
-      return(FALSE);
+    IDA_mem->ida_phiS[j] = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+    if (IDA_mem->ida_phiS[j] == NULL) {
+      N_VDestroy(IDA_mem->ida_tmpS3);
+      N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_eeS, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_yyS, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_ypS, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_deltaS, IDA_mem->ida_Ns);
+      return(SUNFALSE);
     }
   }
 
   /* Update solver workspace lengths */
-  lrw += maxcol*Ns*lrw1;
-  liw += maxcol*Ns*liw1;
+  IDA_mem->ida_lrw += maxcol*IDA_mem->ida_Ns*IDA_mem->ida_lrw1;
+  IDA_mem->ida_liw += maxcol*IDA_mem->ida_Ns*IDA_mem->ida_liw1;
 
   /* Allocate space for pbar and plist */
 
-  pbar = NULL;
-  pbar = (realtype *)malloc(Ns*sizeof(realtype));
-  if (pbar == NULL) {
-    N_VDestroy(tmpS3);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroyVectorArray(eeS, Ns);
-    N_VDestroyVectorArray(yyS, Ns);
-    N_VDestroyVectorArray(ypS, Ns);
-    N_VDestroyVectorArray(deltaS, Ns);
-    for (j=0; j<=maxcol; j++) N_VDestroyVectorArray(phiS[j], Ns);
-    return(FALSE);
-  }
-
-  plist = NULL;
-  plist = (int *)malloc(Ns*sizeof(int));
-  if (plist == NULL) {
-    N_VDestroy(tmpS3);
-    N_VDestroyVectorArray(ewtS, Ns);
-    N_VDestroyVectorArray(eeS, Ns);
-    N_VDestroyVectorArray(yyS, Ns);
-    N_VDestroyVectorArray(ypS, Ns);
-    N_VDestroyVectorArray(deltaS, Ns);
-    free(pbar); pbar = NULL;
-    return(FALSE);
+  IDA_mem->ida_pbar = NULL;
+  IDA_mem->ida_pbar = (realtype *)malloc(IDA_mem->ida_Ns*sizeof(realtype));
+  if (IDA_mem->ida_pbar == NULL) {
+    N_VDestroy(IDA_mem->ida_tmpS3);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_eeS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_yyS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ypS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_deltaS, IDA_mem->ida_Ns);
+    for (j=0; j<=maxcol; j++) N_VDestroyVectorArray(IDA_mem->ida_phiS[j], IDA_mem->ida_Ns);
+    return(SUNFALSE);
+  }
+
+  IDA_mem->ida_plist = NULL;
+  IDA_mem->ida_plist = (int *)malloc(IDA_mem->ida_Ns*sizeof(int));
+  if (IDA_mem->ida_plist == NULL) {
+    N_VDestroy(IDA_mem->ida_tmpS3);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_eeS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_yyS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ypS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_deltaS, IDA_mem->ida_Ns);
+    free(IDA_mem->ida_pbar); IDA_mem->ida_pbar = NULL;
+    return(SUNFALSE);
   }
 
   /* Update solver workspace lengths */
-  lrw += Ns;
-  liw += Ns;
+  IDA_mem->ida_lrw += IDA_mem->ida_Ns;
+  IDA_mem->ida_liw += IDA_mem->ida_Ns;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -3708,33 +3507,33 @@ static void IDASensFreeVectors(IDAMem IDA_mem)
 {
   int j, maxcol;
 
-  N_VDestroyVectorArray(deltaS, Ns);
-  N_VDestroyVectorArray(ypS, Ns);
-  N_VDestroyVectorArray(yyS, Ns);
-  N_VDestroyVectorArray(eeS, Ns);
-  N_VDestroyVectorArray(ewtS, Ns);
-  N_VDestroy(tmpS3);
+  N_VDestroyVectorArray(IDA_mem->ida_deltaS, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_ypS, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_yyS, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_eeS, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_ewtS, IDA_mem->ida_Ns);
+  N_VDestroy(IDA_mem->ida_tmpS3);
 
   maxcol = SUNMAX(IDA_mem->ida_maxord_alloc, 4);
   for (j=0; j<=maxcol; j++) 
-    N_VDestroyVectorArray(phiS[j], Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_phiS[j], IDA_mem->ida_Ns);
 
-  free(pbar); pbar = NULL;
-  free(plist); plist = NULL;
+  free(IDA_mem->ida_pbar); IDA_mem->ida_pbar = NULL;
+  free(IDA_mem->ida_plist); IDA_mem->ida_plist = NULL;
 
-  lrw -= ( (maxcol+3)*Ns + 1 ) * lrw1 + Ns;
-  liw -= ( (maxcol+3)*Ns + 1 ) * liw1 + Ns;
+  IDA_mem->ida_lrw -= ( (maxcol+3)*IDA_mem->ida_Ns + 1 ) * IDA_mem->ida_lrw1 + IDA_mem->ida_Ns;
+  IDA_mem->ida_liw -= ( (maxcol+3)*IDA_mem->ida_Ns + 1 ) * IDA_mem->ida_liw1 + IDA_mem->ida_Ns;
 
   if (IDA_mem->ida_VatolSMallocDone) {
-    N_VDestroyVectorArray(VatolS, Ns);
-    lrw -= Ns*lrw1;
-    liw -= Ns*liw1;
-    IDA_mem->ida_VatolSMallocDone = FALSE;
+    N_VDestroyVectorArray(IDA_mem->ida_VatolS, IDA_mem->ida_Ns);
+    IDA_mem->ida_lrw -= IDA_mem->ida_Ns*IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw -= IDA_mem->ida_Ns*IDA_mem->ida_liw1;
+    IDA_mem->ida_VatolSMallocDone = SUNFALSE;
   } 
   if (IDA_mem->ida_SatolSMallocDone) {
-    free(SatolS); SatolS = NULL;
-    lrw -= Ns;
-    IDA_mem->ida_SatolSMallocDone = FALSE;
+    free(IDA_mem->ida_SatolS); IDA_mem->ida_SatolS = NULL;
+    IDA_mem->ida_lrw -= IDA_mem->ida_Ns;
+    IDA_mem->ida_SatolSMallocDone = SUNFALSE;
   }
 
 }
@@ -3752,62 +3551,63 @@ static booleantype IDAQuadSensAllocVectors(IDAMem IDA_mem, N_Vector tmpl)
   int i, j, maxcol;
 
   /* Allocate yQS */
-  yyQS = N_VCloneVectorArray(Ns, tmpl);
-  if (yyQS == NULL) {
-    return(FALSE);
+  IDA_mem->ida_yyQS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_yyQS == NULL) {
+    return(SUNFALSE);
   }
 
   /* Allocate ewtQS */
-  ewtQS = N_VCloneVectorArray(Ns, tmpl);
-  if (ewtQS == NULL) {
-    N_VDestroyVectorArray(yyQS, Ns);
-    return(FALSE);
+  IDA_mem->ida_ewtQS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_ewtQS == NULL) {
+    N_VDestroyVectorArray(IDA_mem->ida_yyQS, IDA_mem->ida_Ns);
+    return(SUNFALSE);
   }
 
   /* Allocate tempvQS */
-  tempvQS = N_VCloneVectorArray(Ns, tmpl);
-  if (tempvQS == NULL) {
-    N_VDestroyVectorArray(yyQS, Ns);
-    N_VDestroyVectorArray(ewtQS, Ns);
-    return(FALSE);
+  IDA_mem->ida_tempvQS = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_tempvQS == NULL) {
+    N_VDestroyVectorArray(IDA_mem->ida_yyQS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtQS, IDA_mem->ida_Ns);
+    return(SUNFALSE);
   }
 
-  eeQS =  N_VCloneVectorArray(Ns, tmpl);
-  if (eeQS == NULL) {
-    N_VDestroyVectorArray(yyQS, Ns);
-    N_VDestroyVectorArray(ewtQS, Ns);
-    N_VDestroyVectorArray(tempvQS, Ns);
-    return(FALSE);
+  IDA_mem->ida_eeQS =  N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+  if (IDA_mem->ida_eeQS == NULL) {
+    N_VDestroyVectorArray(IDA_mem->ida_yyQS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtQS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_tempvQS, IDA_mem->ida_Ns);
+    return(SUNFALSE);
   }
 
-  savrhsQ = N_VClone(tmpl);
-  if (savrhsQ == NULL) {
-    N_VDestroyVectorArray(yyQS, Ns);
-    N_VDestroyVectorArray(ewtQS, Ns);
-    N_VDestroyVectorArray(tempvQS, Ns);
-    N_VDestroyVectorArray(eeQS, Ns);
+  IDA_mem->ida_savrhsQ = N_VClone(tmpl);
+  if (IDA_mem->ida_savrhsQ == NULL) {
+    N_VDestroyVectorArray(IDA_mem->ida_yyQS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_ewtQS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_tempvQS, IDA_mem->ida_Ns);
+    N_VDestroyVectorArray(IDA_mem->ida_eeQS, IDA_mem->ida_Ns);
   }
 
-  maxcol = SUNMAX(maxord,4);
+  maxcol = SUNMAX(IDA_mem->ida_maxord,4);
   /* Allocate phiQS */
   for (j=0; j<=maxcol; j++) {
-    phiQS[j] = N_VCloneVectorArray(Ns, tmpl);
-    if (phiQS[j] == NULL) {
-      N_VDestroyVectorArray(yyQS, Ns);
-      N_VDestroyVectorArray(ewtQS, Ns);
-      N_VDestroyVectorArray(tempvQS, Ns);
-      N_VDestroyVectorArray(eeQS, Ns);
-      N_VDestroy(savrhsQ);
-      for (i=0; i<j; i++) N_VDestroyVectorArray(phiQS[i], Ns);
-      return(FALSE);
+    IDA_mem->ida_phiQS[j] = N_VCloneVectorArray(IDA_mem->ida_Ns, tmpl);
+    if (IDA_mem->ida_phiQS[j] == NULL) {
+      N_VDestroyVectorArray(IDA_mem->ida_yyQS, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_ewtQS, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_tempvQS, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_eeQS, IDA_mem->ida_Ns);
+      N_VDestroy(IDA_mem->ida_savrhsQ);
+      for (i=0; i<j; i++)
+        N_VDestroyVectorArray(IDA_mem->ida_phiQS[i], IDA_mem->ida_Ns);
+      return(SUNFALSE);
     }
   }
 
   /* Update solver workspace lengths */
-  lrw += (maxcol + 5)*Ns*lrw1Q;
-  liw += (maxcol + 5)*Ns*liw1Q;
+  IDA_mem->ida_lrw += (maxcol + 5)*IDA_mem->ida_Ns*IDA_mem->ida_lrw1Q;
+  IDA_mem->ida_liw += (maxcol + 5)*IDA_mem->ida_Ns*IDA_mem->ida_liw1Q;
 
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 
@@ -3821,30 +3621,30 @@ static void IDAQuadSensFreeVectors(IDAMem IDA_mem)
 {
   int j, maxcol;
 
-  maxcol = SUNMAX(maxord, 4);
+  maxcol = SUNMAX(IDA_mem->ida_maxord, 4);
 
-  N_VDestroyVectorArray(yyQS, Ns);
-  N_VDestroyVectorArray(ewtQS, Ns);
-  N_VDestroyVectorArray(eeQS, Ns);
-  N_VDestroyVectorArray(tempvQS, Ns);
-  N_VDestroy(savrhsQ);
+  N_VDestroyVectorArray(IDA_mem->ida_yyQS, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_ewtQS, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_eeQS, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_tempvQS, IDA_mem->ida_Ns);
+  N_VDestroy(IDA_mem->ida_savrhsQ);
 
-  for (j=0; j<=maxcol; j++) N_VDestroyVectorArray(phiQS[j], Ns);  
+  for (j=0; j<=maxcol; j++) N_VDestroyVectorArray(IDA_mem->ida_phiQS[j], IDA_mem->ida_Ns);  
 
-  lrw -= (maxcol + 5)*Ns*lrw1Q;
-  liw -= (maxcol + 5)*Ns*liw1Q;
+  IDA_mem->ida_lrw -= (maxcol + 5)*IDA_mem->ida_Ns*IDA_mem->ida_lrw1Q;
+  IDA_mem->ida_liw -= (maxcol + 5)*IDA_mem->ida_Ns*IDA_mem->ida_liw1Q;
 
   if (IDA_mem->ida_VatolQSMallocDone) {
-    N_VDestroyVectorArray(VatolQS, Ns);
-    lrw -= Ns*lrw1Q;
-    liw -= Ns*liw1Q;
+    N_VDestroyVectorArray(IDA_mem->ida_VatolQS, IDA_mem->ida_Ns);
+    IDA_mem->ida_lrw -= IDA_mem->ida_Ns*IDA_mem->ida_lrw1Q;
+    IDA_mem->ida_liw -= IDA_mem->ida_Ns*IDA_mem->ida_liw1Q;
   }
   if (IDA_mem->ida_SatolQSMallocDone) {
-    free(SatolQS); SatolQS = NULL;
-    lrw -= Ns;
+    free(IDA_mem->ida_SatolQS); IDA_mem->ida_SatolQS = NULL;
+    IDA_mem->ida_lrw -= IDA_mem->ida_Ns;
   }
-  IDA_mem->ida_VatolQSMallocDone = FALSE;
-  IDA_mem->ida_SatolQSMallocDone = FALSE;
+  IDA_mem->ida_VatolQSMallocDone = SUNFALSE;
+  IDA_mem->ida_SatolQSMallocDone = SUNFALSE;
 }
 
 
@@ -3872,43 +3672,45 @@ int IDAInitialSetup(IDAMem IDA_mem)
   int ier, retval;
 
   /* Test for more vector operations, depending on options */
-  if (suppressalg)
-    if (phi[0]->ops->nvwrmsnormmask == NULL) {
+  if (IDA_mem->ida_suppressalg)
+    if (IDA_mem->ida_phi[0]->ops->nvwrmsnormmask == NULL) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_NVECTOR);
       return(IDA_ILL_INPUT);
   }
 
   /* Test id vector for legality */
-  if (suppressalg && (id==NULL)){ 
+  if (IDA_mem->ida_suppressalg && (IDA_mem->ida_id==NULL)){ 
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_MISSING_ID);
     return(IDA_ILL_INPUT); 
   }
 
   /* Did the user specify tolerances? */
-  if (itol == IDA_NN) {
+  if (IDA_mem->ida_itol == IDA_NN) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NO_TOLS);
     return(IDA_ILL_INPUT);
   }
 
   /* Set data for efun */
-  if (IDA_mem->ida_user_efun) edata = user_data;
-  else                        edata = IDA_mem;
+  if (IDA_mem->ida_user_efun) IDA_mem->ida_edata = IDA_mem->ida_user_data;
+  else                        IDA_mem->ida_edata = IDA_mem;
 
   /* Initial error weight vectors */
-  ier = efun(phi[0], ewt, edata);
+  ier = IDA_mem->ida_efun(IDA_mem->ida_phi[0], IDA_mem->ida_ewt, IDA_mem->ida_edata);
   if (ier != 0) {
-    if (itol == IDA_WF) 
+    if (IDA_mem->ida_itol == IDA_WF) 
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_FAIL_EWT);
     else
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_EWT);
     return(IDA_ILL_INPUT);
   }
 
-  if (quadr) {
+  if (IDA_mem->ida_quadr) {
 
     /* Evaluate quadrature rhs and set phiQ[1] */
-    retval = rhsQ(tn, phi[0], phi[1], phiQ[1], user_data);
-    nrQe++;
+    retval = IDA_mem->ida_rhsQ(IDA_mem->ida_tn, IDA_mem->ida_phi[0],
+                               IDA_mem->ida_phi[1], IDA_mem->ida_phiQ[1],
+                               IDA_mem->ida_user_data);
+    IDA_mem->ida_nrQe++;
     if (retval < 0) {
       IDAProcessError(IDA_mem, IDA_QRHS_FAIL, "IDAS", "IDAInitialSetup", MSG_QRHSFUNC_FAILED);
       return(IDA_QRHS_FAIL);
@@ -3917,48 +3719,52 @@ int IDAInitialSetup(IDAMem IDA_mem)
       return(IDA_FIRST_QRHS_ERR);
     }
 
-    if (errconQ) {
+    if (IDA_mem->ida_errconQ) {
 
       /* Did the user specify tolerances? */
-      if (itolQ == IDA_NN) {
+      if (IDA_mem->ida_itolQ == IDA_NN) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NO_TOLQ);
         return(IDA_ILL_INPUT);
       }
       
       /* Load ewtQ */
-      ier = IDAQuadEwtSet(IDA_mem, phiQ[0], ewtQ);
+      ier = IDAQuadEwtSet(IDA_mem, IDA_mem->ida_phiQ[0], IDA_mem->ida_ewtQ);
       if (ier != 0) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_EWTQ);
         return(IDA_ILL_INPUT);
       }
     }
   } else {
-    errconQ = FALSE;
+    IDA_mem->ida_errconQ = SUNFALSE;
   }
 
-  if (sensi) {
+  if (IDA_mem->ida_sensi) {
 
     /* Did the user specify tolerances? */
-    if (itolS == IDA_NN) {
+    if (IDA_mem->ida_itolS == IDA_NN) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NO_TOLS);
       return(IDA_ILL_INPUT);
     }
     
     /* Load ewtS */
-    ier = IDASensEwtSet(IDA_mem, phiS[0], ewtS);
+    ier = IDASensEwtSet(IDA_mem, IDA_mem->ida_phiS[0], IDA_mem->ida_ewtS);
     if (ier != 0) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_EWTS);
       return(IDA_ILL_INPUT);
     }
   } else {
-    errconS = FALSE;
+    IDA_mem->ida_errconS = SUNFALSE;
   }
 
-  if (quadr_sensi) {
+  if (IDA_mem->ida_quadr_sensi) {
 
     /* store the quadrature sensitivity residual. */
-    retval = rhsQS(Ns, tn, phi[0], phi[1], phiS[0], phiS[1], phiQ[1], phiQS[1], user_dataQS, tmpS1, tmpS2, tmpS3);
-    nrQSe++;
+    retval = IDA_mem->ida_rhsQS(IDA_mem->ida_Ns, IDA_mem->ida_tn,
+                                IDA_mem->ida_phi[0], IDA_mem->ida_phi[1],
+                                IDA_mem->ida_phiS[0], IDA_mem->ida_phiS[1],
+                                IDA_mem->ida_phiQ[1], IDA_mem->ida_phiQS[1],
+                                IDA_mem->ida_user_dataQS, IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
+    IDA_mem->ida_nrQSe++;
     if (retval < 0) {
       IDAProcessError(IDA_mem, IDA_QSRHS_FAIL, "IDAS", "IDAInitialSetup", MSG_QSRHSFUNC_FAILED);
       return(IDA_QRHS_FAIL);
@@ -3970,54 +3776,54 @@ int IDAInitialSetup(IDAMem IDA_mem)
     /* If using the internal DQ functions, we must have access to fQ
      * (i.e. quadrature integration must be enabled) and to the problem parameters */
 
-    if (rhsQSDQ) {
+    if (IDA_mem->ida_rhsQSDQ) {
       
       /* Test if quadratures are defined, so we can use fQ */
-      if (!quadr) {
+      if (!IDA_mem->ida_quadr) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NULL_RHSQ);
         return(IDA_ILL_INPUT);
       }
       
       /* Test if we have the problem parameters */
-      if (p == NULL) {
+      if (IDA_mem->ida_p == NULL) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NULL_P);
         return(IDA_ILL_INPUT);
       }
     }
 
-    if (errconQS) {
+    if (IDA_mem->ida_errconQS) {
       /* Did the user specify tolerances? */
-      if (itolQS == IDA_NN) {
+      if (IDA_mem->ida_itolQS == IDA_NN) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NO_TOLQS);
         return(IDA_ILL_INPUT);
       }
 
       /* If needed, did the user provide quadrature tolerances? */
-      if ( (itolQS == IDA_EE) && (itolQ == IDA_NN) ) {
+      if ( (IDA_mem->ida_itolQS == IDA_EE) && (IDA_mem->ida_itolQ == IDA_NN) ) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_NO_TOLQ);
         return(IDA_ILL_INPUT);
       }
     
       /* Load ewtS */
-      ier = IDAQuadSensEwtSet(IDA_mem, phiQS[0], ewtQS);
+      ier = IDAQuadSensEwtSet(IDA_mem, IDA_mem->ida_phiQS[0], IDA_mem->ida_ewtQS);
       if (ier != 0) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_EWTQS);
         return(IDA_ILL_INPUT);
       }
     }
   } else {
-    errconQS = FALSE;
+    IDA_mem->ida_errconQS = SUNFALSE;
   }
 
   /* Check to see if y0 satisfies constraints. */
-  if (constraintsSet) {
+  if (IDA_mem->ida_constraintsSet) {
 
-    if (sensi && (ism==IDA_SIMULTANEOUS)) {
+    if (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS)) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_BAD_ISM_CONSTR);
       return(IDA_ILL_INPUT);
     }
 
-    conOK = N_VConstrMask(constraints, phi[0], tempv2);
+    conOK = N_VConstrMask(IDA_mem->ida_constraints, IDA_mem->ida_phi[0], IDA_mem->ida_tempv2);
     if (!conOK) { 
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_Y0_FAIL_CONSTR);
       return(IDA_ILL_INPUT); 
@@ -4025,13 +3831,13 @@ int IDAInitialSetup(IDAMem IDA_mem)
   }
 
   /* Check that lsolve exists and call linit function if it exists. */
-  if (lsolve == NULL) {
+  if (IDA_mem->ida_lsolve == NULL) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_LSOLVE_NULL);
     return(IDA_ILL_INPUT);
   }
 
-  if (linit != NULL) {
-    retval = linit(IDA_mem);
+  if (IDA_mem->ida_linit != NULL) {
+    retval = IDA_mem->ida_linit(IDA_mem);
     if (retval != 0) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDAInitialSetup", MSG_LINIT_FAIL);
       return(IDA_LINIT_FAIL);
@@ -4067,7 +3873,7 @@ int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
   IDA_mem = (IDAMem) data;
 
-  switch(itol) {
+  switch(IDA_mem->ida_itol) {
   case IDA_SS: 
     flag = IDAEwtSetSS(IDA_mem, ycur, weight); 
     break;
@@ -4090,11 +3896,11 @@ int IDAEwtSet(N_Vector ycur, N_Vector weight, void *data)
 
 static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv1);
-  N_VScale(rtol, tempv1, tempv1);
-  N_VAddConst(tempv1, Satol, tempv1);
-  if (N_VMin(tempv1) <= ZERO) return(-1);
-  N_VInv(tempv1, weight);
+  N_VAbs(ycur, IDA_mem->ida_tempv1);
+  N_VScale(IDA_mem->ida_rtol, IDA_mem->ida_tempv1, IDA_mem->ida_tempv1);
+  N_VAddConst(IDA_mem->ida_tempv1, IDA_mem->ida_Satol, IDA_mem->ida_tempv1);
+  if (N_VMin(IDA_mem->ida_tempv1) <= ZERO) return(-1);
+  N_VInv(IDA_mem->ida_tempv1, weight);
   return(0);
 }
 
@@ -4110,10 +3916,10 @@ static int IDAEwtSetSS(IDAMem IDA_mem, N_Vector ycur, N_Vector weight)
 
 static int IDAEwtSetSV(IDAMem IDA_mem, N_Vector ycur, N_Vector weight)
 {
-  N_VAbs(ycur, tempv1);
-  N_VLinearSum(rtol, tempv1, ONE, Vatol, tempv1);
-  if (N_VMin(tempv1) <= ZERO) return(-1);
-  N_VInv(tempv1, weight);
+  N_VAbs(ycur, IDA_mem->ida_tempv1);
+  N_VLinearSum(IDA_mem->ida_rtol, IDA_mem->ida_tempv1, ONE, IDA_mem->ida_Vatol, IDA_mem->ida_tempv1);
+  if (N_VMin(IDA_mem->ida_tempv1) <= ZERO) return(-1);
+  N_VInv(IDA_mem->ida_tempv1, weight);
   return(0);
 }
 
@@ -4126,7 +3932,7 @@ static int IDAQuadEwtSet(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ)
 {
   int flag=0;
 
-  switch (itolQ) {
+  switch (IDA_mem->ida_itolQ) {
   case IDA_SS: 
     flag = IDAQuadEwtSetSS(IDA_mem, qcur, weightQ);
     break;
@@ -4149,11 +3955,11 @@ static int IDAQuadEwtSetSS(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ)
   N_Vector tempvQ;
 
   /* Use ypQ as temporary storage */
-  tempvQ = ypQ;
+  tempvQ = IDA_mem->ida_ypQ;
 
   N_VAbs(qcur, tempvQ);
-  N_VScale(rtolQ, tempvQ, tempvQ);
-  N_VAddConst(tempvQ, SatolQ, tempvQ);
+  N_VScale(IDA_mem->ida_rtolQ, tempvQ, tempvQ);
+  N_VAddConst(tempvQ, IDA_mem->ida_SatolQ, tempvQ);
   if (N_VMin(tempvQ) <= ZERO) return(-1);
   N_VInv(tempvQ, weightQ);
 
@@ -4170,10 +3976,10 @@ static int IDAQuadEwtSetSV(IDAMem IDA_mem, N_Vector qcur, N_Vector weightQ)
   N_Vector tempvQ;
 
   /* Use ypQ as temporary storage */
-  tempvQ = ypQ;
+  tempvQ = IDA_mem->ida_ypQ;
 
   N_VAbs(qcur, tempvQ);
-  N_VLinearSum(rtolQ, tempvQ, ONE, VatolQ, tempvQ);
+  N_VLinearSum(IDA_mem->ida_rtolQ, tempvQ, ONE, IDA_mem->ida_VatolQ, tempvQ);
   if (N_VMin(tempvQ) <= ZERO) return(-1);
   N_VInv(tempvQ, weightQ);
 
@@ -4189,7 +3995,7 @@ int IDASensEwtSet(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS)
 {
   int flag=0;
 
-  switch (itolS) {
+  switch (IDA_mem->ida_itolS) {
   case IDA_EE:
     flag = IDASensEwtSetEE(IDA_mem, yScur, weightS);
     break;
@@ -4224,13 +4030,13 @@ static int IDASensEwtSetEE(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS)
   int flag;
 
   /* Use tempv1 as temporary storage for the scaled sensitivity */
-  pyS = tempv1;
+  pyS = IDA_mem->ida_tempv1;
 
-  for (is=0; is<Ns; is++) {
-    N_VScale(pbar[is], yScur[is], pyS);
-    flag = efun(pyS, weightS[is], edata);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VScale(IDA_mem->ida_pbar[is], yScur[is], pyS);
+    flag = IDA_mem->ida_efun(pyS, weightS[is], IDA_mem->ida_edata);
     if (flag != 0) return(-1);
-    N_VScale(pbar[is], weightS[is], weightS[is]);
+    N_VScale(IDA_mem->ida_pbar[is], weightS[is], weightS[is]);
   }
 
   return(0);
@@ -4245,12 +4051,12 @@ static int IDASensEwtSetSS(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS)
 {
   int is;
   
-  for (is=0; is<Ns; is++) {
-    N_VAbs(yScur[is], tempv1);
-    N_VScale(rtolS, tempv1, tempv1);
-    N_VAddConst(tempv1, SatolS[is], tempv1);
-    if (N_VMin(tempv1) <= ZERO) return(-1);
-    N_VInv(tempv1, weightS[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VAbs(yScur[is], IDA_mem->ida_tempv1);
+    N_VScale(IDA_mem->ida_rtolS, IDA_mem->ida_tempv1, IDA_mem->ida_tempv1);
+    N_VAddConst(IDA_mem->ida_tempv1, IDA_mem->ida_SatolS[is], IDA_mem->ida_tempv1);
+    if (N_VMin(IDA_mem->ida_tempv1) <= ZERO) return(-1);
+    N_VInv(IDA_mem->ida_tempv1, weightS[is]);
   }
   return(0);
 }
@@ -4264,11 +4070,11 @@ static int IDASensEwtSetSV(IDAMem IDA_mem, N_Vector *yScur, N_Vector *weightS)
 {
   int is;
   
-  for (is=0; is<Ns; is++) {
-    N_VAbs(yScur[is], tempv1);
-    N_VLinearSum(rtolS, tempv1, ONE, VatolS[is], tempv1);
-    if (N_VMin(tempv1) <= ZERO) return(-1);
-    N_VInv(tempv1, weightS[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VAbs(yScur[is], IDA_mem->ida_tempv1);
+    N_VLinearSum(IDA_mem->ida_rtolS, IDA_mem->ida_tempv1, ONE, IDA_mem->ida_VatolS[is], IDA_mem->ida_tempv1);
+    if (N_VMin(IDA_mem->ida_tempv1) <= ZERO) return(-1);
+    N_VInv(IDA_mem->ida_tempv1, weightS[is]);
   }
 
   return(0);
@@ -4283,7 +4089,7 @@ int IDAQuadSensEwtSet(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weightQS)
 {
   int flag=0;
 
-  switch (itolQS) {
+  switch (IDA_mem->ida_itolQS) {
   case IDA_EE:
     flag = IDAQuadSensEwtSetEE(IDA_mem, yQScur, weightQS);
     break;
@@ -4317,13 +4123,13 @@ static int IDAQuadSensEwtSetEE(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weigh
   int flag;
 
   /* Use tempvQS[0] as temporary storage for the scaled sensitivity */
-  pyS = tempvQS[0];
+  pyS = IDA_mem->ida_tempvQS[0];
 
-  for (is=0; is<Ns; is++) {
-    N_VScale(pbar[is], yQScur[is], pyS);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VScale(IDA_mem->ida_pbar[is], yQScur[is], pyS);
     flag = IDAQuadEwtSet(IDA_mem, pyS, weightQS[is]);
     if (flag != 0) return(-1);
-    N_VScale(pbar[is], weightQS[is], weightQS[is]);
+    N_VScale(IDA_mem->ida_pbar[is], weightQS[is], weightQS[is]);
   }
 
   return(0);
@@ -4335,12 +4141,12 @@ static int IDAQuadSensEwtSetSS(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weigh
   N_Vector tempvQ;
 
   /* Use ypQ as temporary storage */
-  tempvQ = ypQ;
+  tempvQ = IDA_mem->ida_ypQ;
 
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     N_VAbs(yQScur[is], tempvQ);
-    N_VScale(rtolQS, tempvQ, tempvQ);
-    N_VAddConst(tempvQ, SatolQS[is], tempvQ);
+    N_VScale(IDA_mem->ida_rtolQS, tempvQ, tempvQ);
+    N_VAddConst(tempvQ, IDA_mem->ida_SatolQS[is], tempvQ);
     if (N_VMin(tempvQ) <= ZERO) return(-1);
     N_VInv(tempvQ, weightQS[is]);
   }
@@ -4354,11 +4160,11 @@ static int IDAQuadSensEwtSetSV(IDAMem IDA_mem, N_Vector *yQScur, N_Vector *weigh
   N_Vector tempvQ;
 
   /* Use ypQ as temporary storage */
-  tempvQ = ypQ;
+  tempvQ = IDA_mem->ida_ypQ;
   
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     N_VAbs(yQScur[is], tempvQ);
-    N_VLinearSum(rtolQS, tempvQ, ONE, VatolQS[is], tempvQ);
+    N_VLinearSum(IDA_mem->ida_rtolQS, tempvQ, ONE, IDA_mem->ida_VatolQS[is], tempvQ);
     if (N_VMin(tempvQ) <= ZERO) return(-1);
     N_VInv(tempvQ, weightQS[is]);
   }
@@ -4400,84 +4206,88 @@ static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret,
     
   case IDA_NORMAL:
 
-    if (tstopset) {
+    if (IDA_mem->ida_tstopset) {
       /* Test for tn past tstop, tn = tretlast, tn past tout, tn near tstop. */
-      if ( (tn - tstop)*hh > ZERO) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+      if ( (IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) {
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve",
+                        MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
         return(IDA_ILL_INPUT);
       }
     }
 
     /* Test for tout = tretlast, and for tn past tout. */
-    if (tout == tretlast) {
-      *tret = tretlast = tout;
+    if (tout == IDA_mem->ida_tretlast) {
+      *tret = IDA_mem->ida_tretlast = tout;
       return(IDA_SUCCESS);
     }
-    if ((tn - tout)*hh >= ZERO) {
+    if ((IDA_mem->ida_tn - tout)*IDA_mem->ida_hh >= ZERO) {
       ier = IDAGetSolution(IDA_mem, tout, yret, ypret);
       if (ier != IDA_SUCCESS) {
         IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TOUT, tout);
         return(IDA_ILL_INPUT);
       }
-      *tret = tretlast = tout;
+      *tret = IDA_mem->ida_tretlast = tout;
       return(IDA_SUCCESS);
     }
 
-    if (tstopset) {
-      troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-      if (SUNRabs(tn - tstop) <= troundoff) {
-        ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+    if (IDA_mem->ida_tstopset) {
+      troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+      if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+        ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
         if (ier != IDA_SUCCESS) {
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve",
+                          MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
           return(IDA_ILL_INPUT);
         }
-        *tret = tretlast = tstop;
-        tstopset = FALSE;
+        *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+        IDA_mem->ida_tstopset = SUNFALSE;
         return(IDA_TSTOP_RETURN);
       }
-      if ((tn + hh - tstop)*hh > ZERO) 
-        hh = (tstop - tn)*(ONE-FOUR*uround);
+      if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+        IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
     }
 
     return(CONTINUE_STEPS);
     
   case IDA_ONE_STEP:
 
-    if (tstopset) {
+    if (IDA_mem->ida_tstopset) {
       /* Test for tn past tstop, tn past tretlast, and tn near tstop. */
-      if ((tn - tstop)*hh > ZERO) {
-        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+      if ((IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) {
+        IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve",
+                        MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
         return(IDA_ILL_INPUT);
       }
     }
 
     /* Test for tn past tretlast. */
-    if ((tn - tretlast)*hh > ZERO) {
-      ier = IDAGetSolution(IDA_mem, tn, yret, ypret);
-      *tret = tretlast = tn;
+    if ((IDA_mem->ida_tn - IDA_mem->ida_tretlast)*IDA_mem->ida_hh > ZERO) {
+      ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tn, yret, ypret);
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
       return(IDA_SUCCESS);
     }
 
-    if (tstopset) {
-      troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-      if (SUNRabs(tn - tstop) <= troundoff) {
-        ier = IDAGetSolution(IDA_mem, tstop, yret, ypret);
+    if (IDA_mem->ida_tstopset) {
+      troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+      if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+        ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
         if (ier != IDA_SUCCESS) {
-          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, tstop, tn);
+          IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve",
+                          MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn);
           return(IDA_ILL_INPUT);
         }
-        *tret = tretlast = tstop;
-        tstopset = FALSE;
+        *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+        IDA_mem->ida_tstopset = SUNFALSE;
         return(IDA_TSTOP_RETURN);
       }
-      if ((tn + hh - tstop)*hh > ZERO) 
-        hh = (tstop - tn)*(ONE-FOUR*uround);
+      if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+        IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
     }
 
     return(CONTINUE_STEPS);
         
   }
-  return(IDA_ILL_INPUT);
+  return(IDA_ILL_INPUT);  /* This return should never happen. */
 }
 
 /*
@@ -4490,6 +4300,7 @@ static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret,
  *  CONTINUE_STEPS     if no stop conditions were found
  *  IDA_SUCCESS        for a normal return to the user
  *  IDA_TSTOP_RETURN   for a tstop-reached return to the user
+ *  IDA_ILL_INPUT      for an illegal-input return to the user 
  *
  * In the two cases with tstop, this routine may reset the stepsize hh
  * to cause the next step to reach tstop exactly.
@@ -4512,47 +4323,47 @@ static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret,
     case IDA_NORMAL:  
 
       /* Test for tn past tout. */
-      if ((tn - tout)*hh >= ZERO) {
+      if ((IDA_mem->ida_tn - tout)*IDA_mem->ida_hh >= ZERO) {
         /* ier = */ IDAGetSolution(IDA_mem, tout, yret, ypret);
-        *tret = tretlast = tout;
+        *tret = IDA_mem->ida_tretlast = tout;
         return(IDA_SUCCESS);
       }
 
-      if (tstopset) {
+      if (IDA_mem->ida_tstopset) {
         /* Test for tn at tstop and for tn near tstop */
-        troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-        if (SUNRabs(tn - tstop) <= troundoff) {
-          /* ier = */ IDAGetSolution(IDA_mem, tstop, yret, ypret);
-          *tret = tretlast = tstop;
-          tstopset = FALSE;
+        troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+        if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+          /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
+          *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+          IDA_mem->ida_tstopset = SUNFALSE;
           return(IDA_TSTOP_RETURN);
         }
-        if ((tn + hh - tstop)*hh > ZERO) 
-          hh = (tstop - tn)*(ONE-FOUR*uround);
+        if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+          IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
       }
 
       return(CONTINUE_STEPS);
 
     case IDA_ONE_STEP:
 
-      if (tstopset) {
+      if (IDA_mem->ida_tstopset) {
         /* Test for tn at tstop and for tn near tstop */
-        troundoff = HUNDRED*uround*(SUNRabs(tn) + SUNRabs(hh));
-        if (SUNRabs(tn - tstop) <= troundoff) {
-          /* ier = */ IDAGetSolution(IDA_mem, tstop, yret, ypret);
-          *tret = tretlast = tstop;
-          tstopset = FALSE;
+        troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+        if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) {
+          /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret);
+          *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop;
+          IDA_mem->ida_tstopset = SUNFALSE;
           return(IDA_TSTOP_RETURN);
         }
-        if ((tn + hh - tstop)*hh > ZERO) 
-          hh = (tstop - tn)*(ONE-FOUR*uround);
+        if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) 
+          IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround);
       }
 
-      *tret = tretlast = tn;
+      *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tn;
       return(IDA_SUCCESS);
 
   }
-  return IDA_ILL_INPUT;
+  return IDA_ILL_INPUT;  /* This return should never happen. */
 }
 
 /* 
@@ -4575,36 +4386,36 @@ static int IDAHandleFailure(IDAMem IDA_mem, int sflag)
   switch (sflag) {
 
     case IDA_ERR_FAIL:
-      IDAProcessError(IDA_mem, IDA_ERR_FAIL, "IDAS", "IDASolve", MSG_ERR_FAILS, tn, hh);
+      IDAProcessError(IDA_mem, IDA_ERR_FAIL, "IDAS", "IDASolve", MSG_ERR_FAILS, IDA_mem->ida_tn, IDA_mem->ida_hh);
       return(IDA_ERR_FAIL);
 
     case IDA_CONV_FAIL:
-      IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDAS", "IDASolve", MSG_CONV_FAILS, tn, hh);
+      IDAProcessError(IDA_mem, IDA_CONV_FAIL, "IDAS", "IDASolve", MSG_CONV_FAILS, IDA_mem->ida_tn, IDA_mem->ida_hh);
       return(IDA_CONV_FAIL);
 
     case IDA_LSETUP_FAIL:  
-      IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDAS", "IDASolve", MSG_SETUP_FAILED, tn);
+      IDAProcessError(IDA_mem, IDA_LSETUP_FAIL, "IDAS", "IDASolve", MSG_SETUP_FAILED, IDA_mem->ida_tn);
       return(IDA_LSETUP_FAIL);
 
     case IDA_LSOLVE_FAIL: 
-      IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDAS", "IDASolve", MSG_SOLVE_FAILED, tn);
+      IDAProcessError(IDA_mem, IDA_LSOLVE_FAIL, "IDAS", "IDASolve", MSG_SOLVE_FAILED, IDA_mem->ida_tn);
       return(IDA_LSOLVE_FAIL);
 
     case IDA_REP_RES_ERR:
-      IDAProcessError(IDA_mem, IDA_REP_RES_ERR, "IDAS", "IDASolve", MSG_REP_RES_ERR, tn);
+      IDAProcessError(IDA_mem, IDA_REP_RES_ERR, "IDAS", "IDASolve", MSG_REP_RES_ERR, IDA_mem->ida_tn);
       return(IDA_REP_RES_ERR);
 
     case IDA_RES_FAIL: 
-      IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDAS", "IDASolve", MSG_RES_NONRECOV, tn);
+      IDAProcessError(IDA_mem, IDA_RES_FAIL, "IDAS", "IDASolve", MSG_RES_NONRECOV, IDA_mem->ida_tn);
       return(IDA_RES_FAIL);
 
     case IDA_CONSTR_FAIL: 
-      IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDAS", "IDASolve", MSG_FAILED_CONSTR, tn);
+      IDAProcessError(IDA_mem, IDA_CONSTR_FAIL, "IDAS", "IDASolve", MSG_FAILED_CONSTR, IDA_mem->ida_tn);
       return(IDA_CONSTR_FAIL);
 
   }
 
-  return (IDA_UNRECONGISED_ERROR);
+  return (IDA_UNRECONGISED_ERROR);  /* This return should never happen. */
 }
 
 /* 
@@ -4674,19 +4485,19 @@ static int IDAStep(IDAMem IDA_mem)
   booleantype sensi_stg;
 
   /* Are we computing sensitivities with the staggered approach? */
-  sensi_stg  = (sensi && (ism==IDA_STAGGERED));
+  sensi_stg  = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_STAGGERED));
 
-  saved_t = tn;
+  saved_t = IDA_mem->ida_tn;
   ncf = nef = 0;
 
-  if (nst == ZERO){
-    kk = 1;
-    kused = 0;
-    hused = ZERO;
-    psi[0] = hh;
-    cj = ONE/hh;
-    phase = 0;
-    ns = 0;
+  if (IDA_mem->ida_nst == ZERO){
+    IDA_mem->ida_kk = 1;
+    IDA_mem->ida_kused = 0;
+    IDA_mem->ida_hused = ZERO;
+    IDA_mem->ida_psi[0] = IDA_mem->ida_hh;
+    IDA_mem->ida_cj = ONE/IDA_mem->ida_hh;
+    IDA_mem->ida_phase = 0;
+    IDA_mem->ida_ns = 0;
   }
 
   /* To prevent 'unintialized variable' warnings */
@@ -4696,7 +4507,7 @@ static int IDAStep(IDAMem IDA_mem)
 
   /* Looping point for attempts to take a step */
 
-  loop {  
+  for(;;) {  
 
     /*-----------------------
       Set method coefficients
@@ -4710,9 +4521,10 @@ static int IDAStep(IDAMem IDA_mem)
       If tn is past tstop (by roundoff), reset it to tstop.
       -----------------------------------------------------*/
 
-    tn = tn + hh;
-    if (tstopset) {
-      if ((tn - tstop)*hh > ZERO) tn = tstop;
+    IDA_mem->ida_tn = IDA_mem->ida_tn + IDA_mem->ida_hh;
+    if (IDA_mem->ida_tstopset) {
+      if ((IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO)
+        IDA_mem->ida_tn = IDA_mem->ida_tstop;
     }
 
     /*-----------------------
@@ -4732,13 +4544,14 @@ static int IDAStep(IDAMem IDA_mem)
       /* restore and decide what to do */
       IDARestore(IDA_mem, saved_t);
       kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1, 
-                             &ncfn, &ncf, &netf, &nef);
+                             &(IDA_mem->ida_ncfn), &ncf,
+                             &(IDA_mem->ida_netf), &nef);
 
       /* exit on nonrecoverable failure */ 
       if (kflag != PREDICT_AGAIN) return(kflag);
 
       /* recoverable error; predict again */
-      if(nst==0) IDAReset(IDA_mem);
+      if(IDA_mem->ida_nst==0) IDAReset(IDA_mem);
       continue;
 
     }
@@ -4746,12 +4559,12 @@ static int IDAStep(IDAMem IDA_mem)
     /*----------------------------
       Advance quadrature variables 
       ----------------------------*/
-    if (quadr) {
+    if (IDA_mem->ida_quadr) {
 
       nflag = IDAQuadNls(IDA_mem);
 
       /* If NLS was successful, perform error test */
-      if (errconQ && (nflag == IDA_SUCCESS))
+      if (IDA_mem->ida_errconQ && (nflag == IDA_SUCCESS))
         nflag = IDAQuadTestError(IDA_mem, ck, &err_k, &err_km1, &err_km2);
 
       /* Test for convergence or error test failures */
@@ -4760,13 +4573,14 @@ static int IDAStep(IDAMem IDA_mem)
         /* restore and decide what to do */
         IDARestore(IDA_mem, saved_t);
         kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1, 
-                               &ncfnQ, &ncf, &netfQ, &nef);
+                               &(IDA_mem->ida_ncfnQ), &ncf,
+                               &(IDA_mem->ida_netfQ), &nef);
 
         /* exit on nonrecoverable failure */ 
         if (kflag != PREDICT_AGAIN) return(kflag);
         
         /* recoverable error; predict again */
-        if(nst==0) IDAReset(IDA_mem);
+        if(IDA_mem->ida_nst==0) IDAReset(IDA_mem);
         continue;
       }
     }
@@ -4780,7 +4594,7 @@ static int IDAStep(IDAMem IDA_mem)
          If res() fails recoverably, treat it as a convergence failure and 
          attempt the step again */
 
-      retval = res(tn, yy, yp, delta, user_data);
+      retval = IDA_mem->ida_res(IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp, IDA_mem->ida_delta, IDA_mem->ida_user_data);
 
       if (retval < 0)      return(IDA_RES_FAIL);
       else if (retval > 0) continue;
@@ -4788,7 +4602,7 @@ static int IDAStep(IDAMem IDA_mem)
       nflag = IDASensNls(IDA_mem);
       
       /* If NLS was successful, perform error test */
-      if (errconS && (nflag == IDA_SUCCESS))
+      if (IDA_mem->ida_errconS && (nflag == IDA_SUCCESS))
         nflag = IDASensTestError(IDA_mem, ck, &err_k, &err_km1, &err_km2);
 
       /* Test for convergence or error test failures */
@@ -4797,13 +4611,14 @@ static int IDAStep(IDAMem IDA_mem)
         /* restore and decide what to do */
         IDARestore(IDA_mem, saved_t);
         kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1, 
-                               &ncfnQ, &ncf, &netfQ, &nef);
+                               &(IDA_mem->ida_ncfnQ), &ncf,
+                               &(IDA_mem->ida_netfQ), &nef);
         
         /* exit on nonrecoverable failure */ 
         if (kflag != PREDICT_AGAIN) return(kflag);
         
         /* recoverable error; predict again */
-        if(nst==0) IDAReset(IDA_mem);
+        if(IDA_mem->ida_nst==0) IDAReset(IDA_mem);
         continue;
       }
     }
@@ -4811,12 +4626,12 @@ static int IDAStep(IDAMem IDA_mem)
     /*-------------------------------------------
       Advance quadrature sensitivity variables
       -------------------------------------------*/
-    if (quadr_sensi) {
+    if (IDA_mem->ida_quadr_sensi) {
 
       nflag = IDAQuadSensNls(IDA_mem);
 
       /* If NLS was successful, perform error test */
-      if (errconQS && (nflag == IDA_SUCCESS))
+      if (IDA_mem->ida_errconQS && (nflag == IDA_SUCCESS))
         nflag = IDAQuadSensTestError(IDA_mem, ck, &err_k, &err_km1, &err_km2);
 
       /* Test for convergence or error test failures */
@@ -4825,13 +4640,14 @@ static int IDAStep(IDAMem IDA_mem)
         /* restore and decide what to do */
         IDARestore(IDA_mem, saved_t);
         kflag = IDAHandleNFlag(IDA_mem, nflag, err_k, err_km1, 
-                               &ncfnQ, &ncf, &netfQ, &nef);
+                               &(IDA_mem->ida_ncfnQ), &ncf,
+                               &(IDA_mem->ida_netfQ), &nef);
 
         /* exit on nonrecoverable failure */ 
         if (kflag != PREDICT_AGAIN) return(kflag);
         
         /* recoverable error; predict again */
-        if(nst==0) IDAReset(IDA_mem);
+        if(IDA_mem->ida_nst==0) IDAReset(IDA_mem);
         continue;
       }
     }
@@ -4857,7 +4673,7 @@ static int IDAStep(IDAMem IDA_mem)
            returns either PREDICT_AGAIN or IDA_SUCCESS
   */
 
-  N_VScale(ck, ee, ee);
+  N_VScale(ck, IDA_mem->ida_ee, IDA_mem->ida_ee);
 
   return(IDA_SUCCESS);
 }
@@ -4893,32 +4709,33 @@ int IDAGetSolution(void *ida_mem, realtype t, N_Vector yret, N_Vector ypret)
 
   /* Check t for legality.  Here tn - hused is t_{n-1}. */
  
-  tfuzz = HUNDRED * uround * (SUNRabs(tn) + SUNRabs(hh));
-  if (hh < ZERO) tfuzz = - tfuzz;
-  tp = tn - hused - tfuzz;
-  if ((t - tp)*hh < ZERO) {
-    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetSolution", MSG_BAD_T, t, tn-hused, tn);
+  tfuzz = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh));
+  if (IDA_mem->ida_hh < ZERO) tfuzz = - tfuzz;
+  tp = IDA_mem->ida_tn - IDA_mem->ida_hused - tfuzz;
+  if ((t - tp)*IDA_mem->ida_hh < ZERO) {
+    IDAProcessError(IDA_mem, IDA_BAD_T, "IDAS", "IDAGetSolution", MSG_BAD_T,
+                    t, IDA_mem->ida_tn-IDA_mem->ida_hused, IDA_mem->ida_tn);
     return(IDA_BAD_T);
   }
 
   /* Initialize yret = phi[0], ypret = 0, and kord = (kused or 1). */
 
-  N_VScale (ONE, phi[0], yret);
+  N_VScale (ONE, IDA_mem->ida_phi[0], yret);
   N_VConst (ZERO, ypret);
-  kord = kused; 
-  if (kused == 0) kord = 1;
+  kord = IDA_mem->ida_kused; 
+  if (IDA_mem->ida_kused == 0) kord = 1;
 
   /* Accumulate multiples of columns phi[j] into yret and ypret. */
 
-  delt = t - tn;
+  delt = t - IDA_mem->ida_tn;
   c = ONE; d = ZERO;
-  gam = delt/psi[0];
+  gam = delt / IDA_mem->ida_psi[0];
   for (j=1; j <= kord; j++) {
-    d = d*gam + c/psi[j-1];
+    d = d*gam + c / IDA_mem->ida_psi[j-1];
     c = c*gam;
-    gam = (delt + psi[j-1])/psi[j];
-    N_VLinearSum(ONE,  yret, c, phi[j],  yret);
-    N_VLinearSum(ONE, ypret, d, phi[j], ypret);
+    gam = (delt + IDA_mem->ida_psi[j-1]) / IDA_mem->ida_psi[j];
+    N_VLinearSum(ONE,  yret, c, IDA_mem->ida_phi[j],  yret);
+    N_VLinearSum(ONE, ypret, d, IDA_mem->ida_phi[j], ypret);
   }
   return(IDA_SUCCESS);
 }
@@ -4942,59 +4759,62 @@ static void IDASetCoeffs(IDAMem IDA_mem, realtype *ck)
 
   /* Set coefficients for the current stepsize h */
 
-  if (hh != hused || kk != kused) ns = 0;
-  ns = SUNMIN(ns+1,kused+2);
-  if (kk+1 >= ns) {
-    beta[0] = ONE;
-    alpha[0] = ONE;
-    temp1 = hh;
-    gamma[0] = ZERO;
-    sigma[0] = ONE;
-    for(i=1;i<=kk;i++){
-      temp2 = psi[i-1];
-      psi[i-1] = temp1;
-      beta[i] = beta[i-1] * psi[i-1] / temp2;
-      temp1 = temp2 + hh;
-      alpha[i] = hh / temp1;
-      sigma[i] = i * sigma[i-1] * alpha[i]; 
-      gamma[i] = gamma[i-1] + alpha[i-1] / hh;
+  if ( (IDA_mem->ida_hh != IDA_mem->ida_hused) ||
+       (IDA_mem->ida_kk != IDA_mem->ida_kused) )
+    IDA_mem->ida_ns = 0;
+  IDA_mem->ida_ns = SUNMIN(IDA_mem->ida_ns+1, IDA_mem->ida_kused+2);
+  if (IDA_mem->ida_kk+1 >= IDA_mem->ida_ns) {
+    IDA_mem->ida_beta[0] = ONE;
+    IDA_mem->ida_alpha[0] = ONE;
+    temp1 = IDA_mem->ida_hh;
+    IDA_mem->ida_gamma[0] = ZERO;
+    IDA_mem->ida_sigma[0] = ONE;
+    for(i=1;i<=IDA_mem->ida_kk;i++){
+      temp2 = IDA_mem->ida_psi[i-1];
+      IDA_mem->ida_psi[i-1] = temp1;
+      IDA_mem->ida_beta[i] = IDA_mem->ida_beta[i-1] * IDA_mem->ida_psi[i-1] / temp2;
+      temp1 = temp2 + IDA_mem->ida_hh;
+      IDA_mem->ida_alpha[i] = IDA_mem->ida_hh / temp1;
+      IDA_mem->ida_sigma[i] = i * IDA_mem->ida_sigma[i-1] * IDA_mem->ida_alpha[i]; 
+      IDA_mem->ida_gamma[i] = IDA_mem->ida_gamma[i-1] + IDA_mem->ida_alpha[i-1] / IDA_mem->ida_hh;
    }
-    psi[kk] = temp1;
+    IDA_mem->ida_psi[IDA_mem->ida_kk] = temp1;
   }
   /* compute alphas, alpha0 */
   alphas = ZERO;
   alpha0 = ZERO;
-  for(i=0;i<kk;i++){
+  for(i=0;i<IDA_mem->ida_kk;i++){
     alphas = alphas - ONE/(i+1);
-    alpha0 = alpha0 - alpha[i];
+    alpha0 = alpha0 - IDA_mem->ida_alpha[i];
   }
 
   /* compute leading coefficient cj  */
-  cjlast = cj;
-  cj = -alphas/hh;
+  IDA_mem->ida_cjlast = IDA_mem->ida_cj;
+  IDA_mem->ida_cj = -alphas/IDA_mem->ida_hh;
   
   /* compute variable stepsize error coefficient ck */
 
-  *ck = SUNRabs(alpha[kk] + alphas - alpha0);
-  *ck = SUNMAX(*ck, alpha[kk]);
+  *ck = SUNRabs(IDA_mem->ida_alpha[IDA_mem->ida_kk] + alphas - alpha0);
+  *ck = SUNMAX(*ck, IDA_mem->ida_alpha[IDA_mem->ida_kk]);
 
  /* change phi to phi-star  */
 
-  for(i=ns;i<=kk;i++) N_VScale(beta[i], phi[i], phi[i]);
+  for(i=IDA_mem->ida_ns;i<=IDA_mem->ida_kk;i++)
+    N_VScale(IDA_mem->ida_beta[i], IDA_mem->ida_phi[i], IDA_mem->ida_phi[i]);
 
-  if (quadr)
-    for(i=ns;i<=kk;i++)
-      N_VScale(beta[i], phiQ[i], phiQ[i]);
+  if (IDA_mem->ida_quadr)
+    for(i=IDA_mem->ida_ns;i<=IDA_mem->ida_kk;i++)
+      N_VScale(IDA_mem->ida_beta[i], IDA_mem->ida_phiQ[i], IDA_mem->ida_phiQ[i]);
 
-  if (sensi)
-    for(is=0;is<Ns;is++)
-      for(i=ns;i<=kk;i++)
-        N_VScale(beta[i], phiS[i][is], phiS[i][is]);
+  if (IDA_mem->ida_sensi)
+    for(is=0;is<IDA_mem->ida_Ns;is++)
+      for(i=IDA_mem->ida_ns;i<=IDA_mem->ida_kk;i++)
+        N_VScale(IDA_mem->ida_beta[i], IDA_mem->ida_phiS[i][is], IDA_mem->ida_phiS[i][is]);
 
-  if (quadr_sensi)
-    for(is=0;is<Ns;is++)
-      for(i=ns;i<=kk;i++)
-        N_VScale(beta[i], phiQS[i][is], phiQS[i][is]);
+  if (IDA_mem->ida_quadr_sensi)
+    for(is=0;is<IDA_mem->ida_Ns;is++)
+      for(i=IDA_mem->ida_ns;i<=IDA_mem->ida_kk;i++)
+        N_VScale(IDA_mem->ida_beta[i], IDA_mem->ida_phiQS[i][is], IDA_mem->ida_phiQS[i][is]);
 
 }
 
@@ -5033,63 +4853,68 @@ static int IDANls(IDAMem IDA_mem)
   booleantype sensi_sim;
 
   /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
-  sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+  sensi_sim = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS));
 
-  callSetup = FALSE;
+  callSetup = SUNFALSE;
 
   /* Initialize if the first time called */
-  if (nst == 0){
-    cjold = cj;
-    ss = TWENTY;
-    ssS = TWENTY;
-    if (setupNonNull) callSetup = TRUE;
+  if (IDA_mem->ida_nst == 0){
+    IDA_mem->ida_cjold = IDA_mem->ida_cj;
+    IDA_mem->ida_ss = TWENTY;
+    IDA_mem->ida_ssS = TWENTY;
+    if (IDA_mem->ida_lsetup) callSetup = SUNTRUE;
   }
 
-  mm = tempv2;
-  tempv3 = ee;
+  IDA_mem->ida_mm = IDA_mem->ida_tempv2;
+  tempv3 = IDA_mem->ida_ee;
 
   /* Decide if lsetup is to be called */
-  if (setupNonNull){
-    cjratio = cj / cjold;
+  if (IDA_mem->ida_lsetup){
+    IDA_mem->ida_cjratio = IDA_mem->ida_cj / IDA_mem->ida_cjold;
     temp1 = (ONE - XRATE) / (ONE + XRATE);
     temp2 = ONE/temp1;
-    if (cjratio < temp1 || cjratio > temp2) callSetup = TRUE;
-    if (forceSetup) callSetup = TRUE;
-    if (cj != cjlast) {ss = HUNDRED; ssS = HUNDRED;}
+    if (IDA_mem->ida_cjratio < temp1 || IDA_mem->ida_cjratio > temp2) callSetup = SUNTRUE;
+    if (IDA_mem->ida_forceSetup) callSetup = SUNTRUE;
+    if (IDA_mem->ida_cj != IDA_mem->ida_cjlast) {
+      IDA_mem->ida_ss = HUNDRED;
+      IDA_mem->ida_ssS = HUNDRED;
+    }
   }
 
   /* Begin the main loop. This loop is traversed at most twice. 
      The second pass only occurs when the first pass had a recoverable
      failure with old Jacobian data */
-  loop{
+  for(;;) {
 
     /* Compute predicted values for yy and yp, and compute residual there. */
     IDAPredict(IDA_mem);
-    retval = res(tn, yy, yp, delta, user_data);
-    nre++;
+    retval = IDA_mem->ida_res(IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp, IDA_mem->ida_delta, IDA_mem->ida_user_data);
+    IDA_mem->ida_nre++;
     if (retval < 0) return(IDA_RES_FAIL);
     if (retval > 0) return(IDA_RES_RECVR);
 
     if (sensi_sim) {
-      for(is=0;is<Ns;is++) IDASensPredict(IDA_mem, is, yyS[is], ypS[is]);
-      retval = resS(Ns, tn, yy, yp, delta, yyS, ypS, deltaS,
-                    user_dataS, tmpS1, tmpS2, tmpS3);
-      nrSe++;
+      for(is=0;is<IDA_mem->ida_Ns;is++) IDASensPredict(IDA_mem, is, IDA_mem->ida_yyS[is], IDA_mem->ida_ypS[is]);
+      retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp, IDA_mem->ida_delta, IDA_mem->ida_yyS, IDA_mem->ida_ypS, IDA_mem->ida_deltaS,
+                                 IDA_mem->ida_user_dataS, IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
+      IDA_mem->ida_nrSe++;
       if (retval < 0) return(IDA_SRES_FAIL);
       if (retval > 0) return(IDA_SRES_RECVR);
     }
 
     /* If indicated, call linear solver setup function and reset parameters. */
     if (callSetup){
-      nsetups++;
-      forceSetup = FALSE;
+      IDA_mem->ida_nsetups++;
+      IDA_mem->ida_forceSetup = SUNFALSE;
       
-      retval = lsetup(IDA_mem, yy, yp, delta, tempv1, tempv2, tempv3);
-
-      cjold = cj;
-      cjratio = ONE;
-      ss = TWENTY;
-      ssS = TWENTY;
+      retval = IDA_mem->ida_lsetup(IDA_mem, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                                   IDA_mem->ida_delta, IDA_mem->ida_tempv1,
+                                   IDA_mem->ida_tempv2, tempv3);
+
+      IDA_mem->ida_cjold = IDA_mem->ida_cj;
+      IDA_mem->ida_cjratio = ONE;
+      IDA_mem->ida_ss = TWENTY;
+      IDA_mem->ida_ssS = TWENTY;
       if (retval < 0) return(IDA_LSETUP_FAIL);
       if (retval > 0) return(IDA_LSETUP_RECVR);
     }
@@ -5098,10 +4923,10 @@ static int IDANls(IDAMem IDA_mem)
     retval = IDANewtonIter(IDA_mem);
 
     /* Retry the current step on recoverable failure with old Jacobian data. */
-    tryAgain = (retval>0)&&(setupNonNull) &&(!callSetup);
+    tryAgain = (retval>0) && (IDA_mem->ida_lsetup) && (!callSetup);
 
     if (tryAgain){
-      callSetup = TRUE;
+      callSetup = SUNTRUE;
       continue;
     }
     else break;
@@ -5112,31 +4937,31 @@ static int IDANls(IDAMem IDA_mem)
 
   /* If otherwise successful, check and enforce inequality constraints. */
 
-  if (constraintsSet){  /* Check constraints and get mask vector mm, 
-                          set where constraints failed */
-    constraintsPassed = N_VConstrMask(constraints,yy,mm);
+  if (IDA_mem->ida_constraintsSet){  /* Check constraints and get mask vector mm, 
+                                        set where constraints failed */
+    constraintsPassed = N_VConstrMask(IDA_mem->ida_constraints,IDA_mem->ida_yy,IDA_mem->ida_mm);
     if (constraintsPassed) return(IDA_SUCCESS);
     else {
-      N_VCompare(ONEPT5, constraints, tempv1);  
+      N_VCompare(ONEPT5, IDA_mem->ida_constraints, IDA_mem->ida_tempv1);  
       /* a , where a[i] =1. when |c[i]| = 2 ,  c the vector of constraints */
-      N_VProd(tempv1, constraints, tempv1);       /* a * c */
-      N_VDiv(tempv1, ewt, tempv1);                /* a * c * wt */
-      N_VLinearSum(ONE, yy, -PT1, tempv1, tempv1);/* y - 0.1 * a * c * wt */
-      N_VProd(tempv1, mm, tempv1);               /*  v = mm*(y-.1*a*c*wt) */
-      vnorm = IDAWrmsNorm(IDA_mem, tempv1, ewt, FALSE); /*  ||v|| */
+      N_VProd(IDA_mem->ida_tempv1, IDA_mem->ida_constraints, IDA_mem->ida_tempv1);       /* a * c */
+      N_VDiv(IDA_mem->ida_tempv1, IDA_mem->ida_ewt, IDA_mem->ida_tempv1);                /* a * c * wt */
+      N_VLinearSum(ONE, IDA_mem->ida_yy, -PT1, IDA_mem->ida_tempv1, IDA_mem->ida_tempv1);/* y - 0.1 * a * c * wt */
+      N_VProd(IDA_mem->ida_tempv1, IDA_mem->ida_mm, IDA_mem->ida_tempv1);               /*  v = mm*(y-.1*a*c*wt) */
+      vnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_tempv1, IDA_mem->ida_ewt, SUNFALSE); /*  ||v|| */
       
       /* If vector v of constraint corrections is small
          in norm, correct and accept this step */      
-      if (vnorm <= epsNewt){  
-        N_VLinearSum(ONE, ee, -ONE, tempv1, ee);  /* ee <- ee - v */
+      if (vnorm <= IDA_mem->ida_epsNewt){  
+        N_VLinearSum(ONE, IDA_mem->ida_ee, -ONE, IDA_mem->ida_tempv1, IDA_mem->ida_ee);  /* ee <- ee - v */
         return(IDA_SUCCESS);
       }
       else {
         /* Constraints not met -- reduce h by computing rr = h'/h */
-        N_VLinearSum(ONE, phi[0], -ONE, yy, tempv1);
-        N_VProd(mm, tempv1, tempv1);
-        rr = PT9*N_VMinQuotient(phi[0], tempv1);
-        rr = SUNMAX(rr,PT1);
+        N_VLinearSum(ONE, IDA_mem->ida_phi[0], -ONE, IDA_mem->ida_yy, IDA_mem->ida_tempv1);
+        N_VProd(IDA_mem->ida_mm, IDA_mem->ida_tempv1, IDA_mem->ida_tempv1);
+        IDA_mem->ida_rr = PT9*N_VMinQuotient(IDA_mem->ida_phi[0], IDA_mem->ida_tempv1);
+        IDA_mem->ida_rr = SUNMAX(IDA_mem->ida_rr,PT1);
         return(IDA_CONSTR_RECVR);
       }
     }
@@ -5156,12 +4981,12 @@ static void IDAPredict(IDAMem IDA_mem)
 {
   int j;
 
-  N_VScale(ONE, phi[0], yy);
-  N_VConst(ZERO, yp);
+  N_VScale(ONE, IDA_mem->ida_phi[0], IDA_mem->ida_yy);
+  N_VConst(ZERO, IDA_mem->ida_yp);
   
-  for(j=1; j<=kk; j++) {
-    N_VLinearSum(ONE,      phi[j], ONE, yy, yy);
-    N_VLinearSum(gamma[j], phi[j], ONE, yp, yp);
+  for(j=1; j<=IDA_mem->ida_kk; j++) {
+    N_VLinearSum(ONE,      IDA_mem->ida_phi[j], ONE, IDA_mem->ida_yy, IDA_mem->ida_yy);
+    N_VLinearSum(IDA_mem->ida_gamma[j], IDA_mem->ida_phi[j], ONE, IDA_mem->ida_yp, IDA_mem->ida_yp);
   }
 }
 
@@ -5192,83 +5017,90 @@ static int IDANewtonIter(IDAMem IDA_mem)
   realtype delnrm, oldnrm, rate;
   booleantype sensi_sim;
 
-  sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+  sensi_sim = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS));
 
   /* Initialize counter mnewt and cumulative correction vectors ee and eeS. */
   mnewt = 0;
-  N_VConst(ZERO, ee);
+  N_VConst(ZERO, IDA_mem->ida_ee);
   if (sensi_sim)
-    for(is=0;is<Ns;is++) N_VConst(ZERO, eeS[is]);
+    for(is=0;is<IDA_mem->ida_Ns;is++) N_VConst(ZERO, IDA_mem->ida_eeS[is]);
   
   /* Initialize oldnrm to avoid compiler warning message */
   oldnrm = ZERO;
 
   /* Looping point for Newton iteration.  Break out on any error. */
-  loop {
+  for(;;) {
 
-    nni++;
+    IDA_mem->ida_nni++;
 
     /* Save a copy of the residual vector in savres. */
-    N_VScale(ONE, delta, savres);
+    N_VScale(ONE, IDA_mem->ida_delta, IDA_mem->ida_savres);
 
     /* Call the lsolve function to get correction vector delta. */
-    retval = lsolve(IDA_mem, delta, ewt, yy, yp, savres); 
+    retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt,
+                                 IDA_mem->ida_yy, IDA_mem->ida_yp, IDA_mem->ida_savres); 
     if (retval < 0) return(IDA_LSOLVE_FAIL);
     if (retval > 0) return(IDA_LSOLVE_RECVR);
 
     /* Call the lsolve function to get correction vectors deltaS. */
     if (sensi_sim) {
-      for(is=0;is<Ns;is++) {
-        retval = lsolve(IDA_mem, deltaS[is], ewtS[is], yy, yp, savres);
+      for(is=0;is<IDA_mem->ida_Ns;is++) {
+        retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_deltaS[is],
+                                     IDA_mem->ida_ewtS[is], IDA_mem->ida_yy,
+                                     IDA_mem->ida_yp, IDA_mem->ida_savres);
         if(retval < 0) return(IDA_LSOLVE_FAIL);
         if(retval > 0) return(IDA_LSOLVE_RECVR);
       }
     }
 
     /* Apply delta to yy, yp, and ee, and get norm(delta). */
-    N_VLinearSum(ONE, yy, -ONE, delta, yy);
-    N_VLinearSum(ONE, ee, -ONE, delta, ee);
-    N_VLinearSum(ONE, yp, -cj,  delta, yp);
-    delnrm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE);
+    N_VLinearSum(ONE, IDA_mem->ida_yy, -ONE, IDA_mem->ida_delta, IDA_mem->ida_yy);
+    N_VLinearSum(ONE, IDA_mem->ida_ee, -ONE, IDA_mem->ida_delta, IDA_mem->ida_ee);
+    N_VLinearSum(ONE, IDA_mem->ida_yp, -IDA_mem->ida_cj,  IDA_mem->ida_delta, IDA_mem->ida_yp);
+    delnrm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, SUNFALSE);
 
     /* Apply deltaS to yys, ypS, and ees, and get update norm(delta). */
     if (sensi_sim) {
-      for(is=0;is<Ns;is++) {
-        N_VLinearSum(ONE, eeS[is], -ONE, deltaS[is], eeS[is]);
-        N_VLinearSum(ONE, yyS[is], -ONE, deltaS[is], yyS[is]);
-        N_VLinearSum(ONE, ypS[is], -cj,  deltaS[is], ypS[is]);
+      for(is=0;is<IDA_mem->ida_Ns;is++) {
+        N_VLinearSum(ONE, IDA_mem->ida_eeS[is], -ONE, IDA_mem->ida_deltaS[is], IDA_mem->ida_eeS[is]);
+        N_VLinearSum(ONE, IDA_mem->ida_yyS[is], -ONE, IDA_mem->ida_deltaS[is], IDA_mem->ida_yyS[is]);
+        N_VLinearSum(ONE, IDA_mem->ida_ypS[is], -IDA_mem->ida_cj,  IDA_mem->ida_deltaS[is], IDA_mem->ida_ypS[is]);
       }
-      delnrm = IDASensWrmsNormUpdate(IDA_mem, delnrm, deltaS, ewtS, FALSE);
+      delnrm = IDASensWrmsNormUpdate(IDA_mem, delnrm, IDA_mem->ida_deltaS, IDA_mem->ida_ewtS, SUNFALSE);
     }
 
     /* Test for convergence, first directly, then with rate estimate. */
 
     if (mnewt == 0){ 
        oldnrm = delnrm;
-       if (delnrm <= toldel) return(IDA_SUCCESS);
+       if (delnrm <= IDA_mem->ida_toldel)
+         return(IDA_SUCCESS);
     }
     else {
       rate = SUNRpowerR( delnrm/oldnrm, ONE/mnewt );
       if (rate > RATEMAX) return(IDA_NCONV_RECVR); 
-      ss = rate/(ONE - rate);
+      IDA_mem->ida_ss = rate/(ONE - rate);
     }
 
-    if (ss*delnrm <= epsNewt) return(IDA_SUCCESS);
+    if (IDA_mem->ida_ss*delnrm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
 
     /* Not yet converged.  Increment mnewt and test for max allowed. */
     mnewt++;
-    if (mnewt >= maxcor) {retval = IDA_NCONV_RECVR; break;}
+    if (mnewt >= IDA_mem->ida_maxcor) {
+      retval = IDA_NCONV_RECVR;
+      break;
+    }
 
     /* Call res for new residual and check error flag from res. */
-    retval = res(tn, yy, yp, delta, user_data);
-    nre++;
+    retval = IDA_mem->ida_res(IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp, IDA_mem->ida_delta, IDA_mem->ida_user_data);
+    IDA_mem->ida_nre++;
     if (retval < 0) return(IDA_RES_FAIL);
     if (retval > 0) return(IDA_RES_RECVR);
 
     if (sensi_sim) {
-      retval = resS(Ns, tn, yy, yp, delta, yyS, ypS, deltaS,
-                    user_dataS, tmpS1, tmpS2, tmpS3);
-      nrSe++;
+      retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp, IDA_mem->ida_delta, IDA_mem->ida_yyS, IDA_mem->ida_ypS, IDA_mem->ida_deltaS,
+                                 IDA_mem->ida_user_dataS, IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
+      IDA_mem->ida_nrSe++;
       if(retval < 0) return(IDA_SRES_FAIL);
       if(retval > 0) return(IDA_SRES_RECVR);
     }
@@ -5300,19 +5132,21 @@ static int IDAQuadNls(IDAMem IDA_mem)
   IDAQuadPredict(IDA_mem);
   
   /* Compute correction eeQ */
-  retval = rhsQ(tn, yy, yp, eeQ, user_data);
-  nrQe++;
+  retval = IDA_mem->ida_rhsQ(IDA_mem->ida_tn, IDA_mem->ida_yy,
+                             IDA_mem->ida_yp, IDA_mem->ida_eeQ,
+                             IDA_mem->ida_user_data);
+  IDA_mem->ida_nrQe++;
   if (retval < 0) return(IDA_QRHS_FAIL);
   else if (retval > 0) return(IDA_QRHS_RECVR);
 
-  if (quadr_sensi)
-    N_VScale(ONE, eeQ, savrhsQ);
+  if (IDA_mem->ida_quadr_sensi)
+    N_VScale(ONE, IDA_mem->ida_eeQ, IDA_mem->ida_savrhsQ);
 
-  N_VLinearSum(ONE, eeQ, -ONE, ypQ, eeQ);
-  N_VScale(ONE/cj, eeQ, eeQ);
+  N_VLinearSum(ONE, IDA_mem->ida_eeQ, -ONE, IDA_mem->ida_ypQ, IDA_mem->ida_eeQ);
+  N_VScale(ONE/IDA_mem->ida_cj, IDA_mem->ida_eeQ, IDA_mem->ida_eeQ);
 
   /* Apply correction: yyQ = yyQ + eeQ */
-  N_VLinearSum(ONE, yyQ, ONE, eeQ, yyQ);
+  N_VLinearSum(ONE, IDA_mem->ida_yyQ, ONE, IDA_mem->ida_eeQ, IDA_mem->ida_yyQ);
 
   return(IDA_SUCCESS);
 }
@@ -5327,12 +5161,12 @@ static void IDAQuadPredict(IDAMem IDA_mem)
 {
   int j;
 
-  N_VScale(ONE, phiQ[0], yyQ);
-  N_VConst(ZERO, ypQ);
+  N_VScale(ONE, IDA_mem->ida_phiQ[0], IDA_mem->ida_yyQ);
+  N_VConst(ZERO, IDA_mem->ida_ypQ);
 
-  for(j=1; j<=kk; j++) {
-    N_VLinearSum(ONE,      phiQ[j], ONE, yyQ, yyQ);
-    N_VLinearSum(gamma[j], phiQ[j], ONE, ypQ, ypQ);
+  for(j=1; j<=IDA_mem->ida_kk; j++) {
+    N_VLinearSum(ONE,      IDA_mem->ida_phiQ[j], ONE, IDA_mem->ida_yyQ, IDA_mem->ida_yyQ);
+    N_VLinearSum(IDA_mem->ida_gamma[j], IDA_mem->ida_phiQ[j], ONE, IDA_mem->ida_ypQ, IDA_mem->ida_ypQ);
   }
 }
 
@@ -5349,31 +5183,32 @@ static int IDASensNls(IDAMem IDA_mem)
   booleantype callSetup, tryAgain;
   int is, retval;
 
-  callSetup = FALSE;
+  callSetup = SUNFALSE;
 
   /* Begin the main loop. This loop is traversed at most twice. 
      The second pass only occurs when the first pass had a recoverable
      failure with old Jacobian data */
-  loop{
+  for(;;) {
 
-    for(is=0;is<Ns;is++)
-      IDASensPredict(IDA_mem, is, yyS[is], ypS[is]);
+    for(is=0;is<IDA_mem->ida_Ns;is++)
+      IDASensPredict(IDA_mem, is, IDA_mem->ida_yyS[is], IDA_mem->ida_ypS[is]);
 
     /* Sensitivity residuals at predicted sensitivities -> in deltaS */
-    retval = resS(Ns, tn, yy, yp, delta, yyS, ypS, deltaS,
-                  user_dataS, tmpS1, tmpS2, tmpS3);
-    nrSe++;
+    retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_tn, IDA_mem->ida_yy, IDA_mem->ida_yp, IDA_mem->ida_delta, IDA_mem->ida_yyS, IDA_mem->ida_ypS, IDA_mem->ida_deltaS,
+                               IDA_mem->ida_user_dataS, IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
+    IDA_mem->ida_nrSe++;
     if(retval < 0) return(IDA_SRES_FAIL);
     if(retval > 0) return(IDA_SRES_RECVR);
 
     /* If indicated, call the linear solver setup function */
     if (callSetup) {
-      retval = lsetup(IDA_mem, yy, yp, delta, tmpS1, tmpS2, tmpS3);
-      nsetupsS++;
-      cjold = cj;
-      cjratio = ONE;
-      ss = TWENTY;
-      ssS = TWENTY;
+      retval = IDA_mem->ida_lsetup(IDA_mem, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                                   IDA_mem->ida_delta, IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
+      IDA_mem->ida_nsetupsS++;
+      IDA_mem->ida_cjold = IDA_mem->ida_cj;
+      IDA_mem->ida_cjratio = ONE;
+      IDA_mem->ida_ss = TWENTY;
+      IDA_mem->ida_ssS = TWENTY;
       if (retval < 0) return(IDA_LSETUP_FAIL);
       if (retval > 0) return(IDA_LSETUP_RECVR);
     }
@@ -5382,10 +5217,10 @@ static int IDASensNls(IDAMem IDA_mem)
     retval = IDASensNewtonIter(IDA_mem);
 
     /* Retry the current step on recoverable failure with old Jacobian data */
-    tryAgain = (retval>0) && (setupNonNull) && (!callSetup);
+    tryAgain = (retval>0) && (IDA_mem->ida_lsetup) && (!callSetup);
 
     if (tryAgain) {
-      callSetup = TRUE;
+      callSetup = SUNTRUE;
       continue;
     }
     else break;
@@ -5393,7 +5228,7 @@ static int IDASensNls(IDAMem IDA_mem)
   }
 
   if (retval != IDA_SUCCESS) 
-    ncfnS++;
+    IDA_mem->ida_ncfnS++;
 
   return(retval);
 
@@ -5413,12 +5248,12 @@ static void IDASensPredict(IDAMem IDA_mem, int is,
 {
   int j;
 
-  N_VScale(ONE, phiS[0][is], yySens);
+  N_VScale(ONE, IDA_mem->ida_phiS[0][is], yySens);
   N_VConst(ZERO, ypSens);
   
-  for(j=1; j<=kk; j++) {
-    N_VLinearSum(ONE,      phiS[j][is], ONE, yySens, yySens);
-    N_VLinearSum(gamma[j], phiS[j][is], ONE, ypSens, ypSens);
+  for(j=1; j<=IDA_mem->ida_kk; j++) {
+    N_VLinearSum(ONE,      IDA_mem->ida_phiS[j][is], ONE, yySens, yySens);
+    N_VLinearSum(IDA_mem->ida_gamma[j], IDA_mem->ida_phiS[j][is], ONE, ypSens, ypSens);
   }
 
 }
@@ -5449,44 +5284,54 @@ static int IDASensNewtonIter(IDAMem IDA_mem)
   realtype delSnrm, delSnrm1, rateS;
 
   mnewt = 0;                  /* local Newton iteration counter */
-  for(is=0;is<Ns;is++)
-    N_VConst(ZERO, eeS[is]);  /* cumulative sensi. corrections  */
+  for(is=0;is<IDA_mem->ida_Ns;is++)
+    N_VConst(ZERO, IDA_mem->ida_eeS[is]);  /* cumulative sensi. corrections  */
 
-  loop {
+  for(;;) {
 
-    nniS++;
+    IDA_mem->ida_nniS++;
 
-    for(is=0;is<Ns;is++) {
+    for(is=0;is<IDA_mem->ida_Ns;is++) {
 
-      retval = lsolve(IDA_mem, deltaS[is], ewtS[is], yy, yp, delta);
+      retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_deltaS[is],
+                                   IDA_mem->ida_ewtS[is], IDA_mem->ida_yy,
+                                   IDA_mem->ida_yp, IDA_mem->ida_delta);
       if(retval < 0) return(IDA_LSOLVE_FAIL);
       if(retval > 0) return(IDA_LSOLVE_RECVR);
 
-      N_VLinearSum(ONE, eeS[is], -ONE, deltaS[is], eeS[is]);
-      N_VLinearSum(ONE, yyS[is], -ONE, deltaS[is], yyS[is]);
-      N_VLinearSum(ONE, ypS[is], -cj,  deltaS[is], ypS[is]);
+      N_VLinearSum(ONE, IDA_mem->ida_eeS[is], -ONE,
+                   IDA_mem->ida_deltaS[is], IDA_mem->ida_eeS[is]);
+      N_VLinearSum(ONE, IDA_mem->ida_yyS[is], -ONE,
+                   IDA_mem->ida_deltaS[is], IDA_mem->ida_yyS[is]);
+      N_VLinearSum(ONE, IDA_mem->ida_ypS[is], -IDA_mem->ida_cj,
+                   IDA_mem->ida_deltaS[is], IDA_mem->ida_ypS[is]);
 
     }
 
-    delSnrm = IDASensWrmsNorm(IDA_mem, deltaS, ewtS, FALSE);
+    delSnrm = IDASensWrmsNorm(IDA_mem, IDA_mem->ida_deltaS, IDA_mem->ida_ewtS, SUNFALSE);
 
     if (mnewt == 0) {
-      if (delSnrm <= toldel) return(IDA_SUCCESS);
+      if (delSnrm <= IDA_mem->ida_toldel)
+        return(IDA_SUCCESS);
       delSnrm1 = delSnrm;
     } else {
       rateS = SUNRpowerR(delSnrm/delSnrm1, ONE/mnewt);
       if (rateS > RATEMAX) return(IDA_NCONV_RECVR);
-      ssS = rateS/(ONE - rateS);
+      IDA_mem->ida_ssS = rateS/(ONE - rateS);
     }
 
-    if (ssS * delSnrm <= epsNewt) return(IDA_SUCCESS);
+    if (IDA_mem->ida_ssS * delSnrm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
 
     mnewt++;
-    if(mnewt >= maxcorS) return(IDA_NCONV_RECVR);
-
-    retval = resS(Ns, tn, yy, yp, delta, yyS, ypS, deltaS,
-                  user_dataS, tmpS1, tmpS2, tmpS3);
-    nrSe++;
+    if(mnewt >= IDA_mem->ida_maxcorS)
+      return(IDA_NCONV_RECVR);
+
+    retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_tn, IDA_mem->ida_yy,
+                               IDA_mem->ida_yp, IDA_mem->ida_delta, IDA_mem->ida_yyS,
+                               IDA_mem->ida_ypS, IDA_mem->ida_deltaS,
+                               IDA_mem->ida_user_dataS, IDA_mem->ida_tmpS1,
+                               IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
+    IDA_mem->ida_nrSe++;
     if (retval < 0) return(IDA_SRES_FAIL);
     if (retval > 0) return(IDA_SRES_RECVR);
 
@@ -5514,24 +5359,28 @@ static int IDAQuadSensNls(IDAMem IDA_mem)
   /* Predict: load yyQS and ypQS for each sensitivity. Store 
    1st order information in tempvQS. */
   
-  ypQS = tempvQS;
-  IDAQuadSensPredict(IDA_mem, yyQS, ypQS);
+  ypQS = IDA_mem->ida_tempvQS;
+  IDAQuadSensPredict(IDA_mem, IDA_mem->ida_yyQS, ypQS);
 
   /* Compute correction eeQS */
-  retval = rhsQS(Ns, tn, yy, yp, yyS, ypS, savrhsQ, eeQS, user_dataQS, tmpS1, tmpS2, tmpS3);
-  nrQSe++;
+  retval = IDA_mem->ida_rhsQS(IDA_mem->ida_Ns, IDA_mem->ida_tn,
+                              IDA_mem->ida_yy, IDA_mem->ida_yp,
+                              IDA_mem->ida_yyS, IDA_mem->ida_ypS,
+                              IDA_mem->ida_savrhsQ, IDA_mem->ida_eeQS,
+                              IDA_mem->ida_user_dataQS, IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
+  IDA_mem->ida_nrQSe++;
 
   if (retval < 0) return(IDA_QSRHS_FAIL);
   else if (retval > 0) return(IDA_QSRHS_RECVR);
 
-  for (is=0; is<Ns; is++) {
-    N_VLinearSum(ONE, eeQS[is], -ONE, ypQS[is], eeQS[is]);
-    N_VScale(ONE/cj, eeQS[is], eeQS[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VLinearSum(ONE, IDA_mem->ida_eeQS[is], -ONE, ypQS[is], IDA_mem->ida_eeQS[is]);
+    N_VScale(ONE/IDA_mem->ida_cj, IDA_mem->ida_eeQS[is], IDA_mem->ida_eeQS[is]);
   }
 
   /* Apply correction: yyQS[is] = yyQ[is] + eeQ[is] */
-  for (is=0; is<Ns; is++) {
-    N_VLinearSum(ONE, yyQS[is], ONE, eeQS[is], yyQS[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VLinearSum(ONE, IDA_mem->ida_yyQS[is], ONE, IDA_mem->ida_eeQS[is], IDA_mem->ida_yyQS[is]);
   }
 
   return(IDA_SUCCESS);
@@ -5547,15 +5396,15 @@ static void IDAQuadSensPredict(IDAMem IDA_mem, N_Vector *yQS, N_Vector *ypQS)
 {
   int j, is;
 
-  for (is=0; is<Ns; is++) {
-    N_VScale(ONE, phiQS[0][is], yQS[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VScale(ONE, IDA_mem->ida_phiQS[0][is], yQS[is]);
     N_VConst(ZERO, ypQS[is]);
   }
 
-  for (is=0; is<Ns; is++) {
-    for(j=1; j<=kk; j++) {
-      N_VLinearSum(ONE,      phiQS[j][is], ONE,  yQS[is],  yQS[is]);
-      N_VLinearSum(gamma[j], phiQS[j][is], ONE, ypQS[is], ypQS[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
+    for(j=1; j<=IDA_mem->ida_kk; j++) {
+      N_VLinearSum(ONE,      IDA_mem->ida_phiQS[j][is], ONE,  yQS[is],  yQS[is]);
+      N_VLinearSum(IDA_mem->ida_gamma[j], IDA_mem->ida_phiQS[j][is], ONE, ypQS[is], ypQS[is]);
     }
   }
 }
@@ -5585,39 +5434,41 @@ static int IDATestError(IDAMem IDA_mem, realtype ck,
 
   /* Compute error for order k. */
 
-  enorm_k = IDAWrmsNorm(IDA_mem, ee, ewt, suppressalg);
-  *err_k = sigma[kk] * enorm_k;
-  terr_k = (kk+1) * (*err_k);
+  enorm_k = IDAWrmsNorm(IDA_mem, IDA_mem->ida_ee, IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+  *err_k = IDA_mem->ida_sigma[IDA_mem->ida_kk] * enorm_k;
+  terr_k = (IDA_mem->ida_kk+1) * (*err_k);
 
-  knew = kk;
+  IDA_mem->ida_knew = IDA_mem->ida_kk;
 
-  if ( kk > 1 ) {
+  if ( IDA_mem->ida_kk > 1 ) {
 
     /* Compute error at order k-1 */
 
-    N_VLinearSum(ONE, phi[kk], ONE, ee, delta);
-    enorm_km1 = IDAWrmsNorm(IDA_mem, delta, ewt, suppressalg);
-    *err_km1 = sigma[kk-1] * enorm_km1;
-    terr_km1 = kk * (*err_km1);
+    N_VLinearSum(ONE, IDA_mem->ida_phi[IDA_mem->ida_kk], ONE, IDA_mem->ida_ee, IDA_mem->ida_delta);
+    enorm_km1 = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+    *err_km1 = IDA_mem->ida_sigma[IDA_mem->ida_kk-1] * enorm_km1;
+    terr_km1 = IDA_mem->ida_kk * (*err_km1);
 
-    if ( kk > 2 ) {
+    if ( IDA_mem->ida_kk > 2 ) {
 
       /* Compute error at order k-2 */
 
-      N_VLinearSum(ONE, phi[kk-1], ONE, delta, delta);
-      enorm_km2 = IDAWrmsNorm(IDA_mem, delta, ewt, suppressalg);
-      *err_km2 = sigma[kk-2] * enorm_km2;
-      terr_km2 = (kk-1) * (*err_km2);
+      N_VLinearSum(ONE, IDA_mem->ida_phi[IDA_mem->ida_kk-1], ONE, IDA_mem->ida_delta, IDA_mem->ida_delta);
+      enorm_km2 = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
+      *err_km2 = IDA_mem->ida_sigma[IDA_mem->ida_kk-2] * enorm_km2;
+      terr_km2 = (IDA_mem->ida_kk-1) * (*err_km2);
 
       /* Reduce order if errors are reduced */
 
-      if (SUNMAX(terr_km1, terr_km2) <= terr_k)  knew = kk - 1;
+      if (SUNMAX(terr_km1, terr_km2) <= terr_k)
+        IDA_mem->ida_knew = IDA_mem->ida_kk - 1;
 
     } else {
 
       /* Reduce order to 1 if errors are reduced by at least 1/2 */
 
-      if (terr_km1 <= (HALF * terr_k) )  knew = kk - 1; 
+      if (terr_km1 <= (HALF * terr_k) )
+        IDA_mem->ida_knew = IDA_mem->ida_kk - 1; 
 
     }
 
@@ -5650,53 +5501,56 @@ static int IDAQuadTestError(IDAMem IDA_mem, realtype ck,
   realtype errQ_k, errQ_km1, errQ_km2;
   realtype terr_k, terr_km1, terr_km2;
   N_Vector tempv;
-  booleantype check_for_reduction = FALSE;
+  booleantype check_for_reduction = SUNFALSE;
 
   /* Rename ypQ */
-  tempv = ypQ;
+  tempv = IDA_mem->ida_ypQ;
 
   /* Update error for order k. */
-  enormQ = N_VWrmsNorm(eeQ, ewtQ);
-  errQ_k = sigma[kk] * enormQ;
+  enormQ = N_VWrmsNorm(IDA_mem->ida_eeQ, IDA_mem->ida_ewtQ);
+  errQ_k = IDA_mem->ida_sigma[IDA_mem->ida_kk] * enormQ;
   if (errQ_k > *err_k) {
     *err_k = errQ_k;
-    check_for_reduction = TRUE;
+    check_for_reduction = SUNTRUE;
   }
-  terr_k = (kk+1) * (*err_k);
+  terr_k = (IDA_mem->ida_kk+1) * (*err_k);
   
-  if ( kk > 1 ) {
+  if ( IDA_mem->ida_kk > 1 ) {
     
     /* Update error at order k-1 */
-    N_VLinearSum(ONE, phiQ[kk], ONE, eeQ, tempv);
-    errQ_km1 = sigma[kk-1] * N_VWrmsNorm(tempv, ewtQ);
+    N_VLinearSum(ONE, IDA_mem->ida_phiQ[IDA_mem->ida_kk], ONE, IDA_mem->ida_eeQ, tempv);
+    errQ_km1 = IDA_mem->ida_sigma[IDA_mem->ida_kk-1] * N_VWrmsNorm(tempv, IDA_mem->ida_ewtQ);
     if (errQ_km1 > *err_km1) {
       *err_km1 = errQ_km1;
-      check_for_reduction = TRUE;
+      check_for_reduction = SUNTRUE;
     }
-    terr_km1 = kk * (*err_km1);
+    terr_km1 = IDA_mem->ida_kk * (*err_km1);
 
     /* Has an order decrease already been decided in IDATestError? */
-    if (knew != kk) check_for_reduction = FALSE;
+    if (IDA_mem->ida_knew != IDA_mem->ida_kk)
+      check_for_reduction = SUNFALSE;
 
     if (check_for_reduction) {
 
-      if ( kk > 2 ) {
+      if ( IDA_mem->ida_kk > 2 ) {
 
         /* Update error at order k-2 */
-        N_VLinearSum(ONE, phiQ[kk-1], ONE, tempv, tempv);
-        errQ_km2 = sigma[kk-2] * N_VWrmsNorm(tempv, ewtQ);
+        N_VLinearSum(ONE, IDA_mem->ida_phiQ[IDA_mem->ida_kk-1], ONE, tempv, tempv);
+        errQ_km2 = IDA_mem->ida_sigma[IDA_mem->ida_kk-2] * N_VWrmsNorm(tempv, IDA_mem->ida_ewtQ);
         if (errQ_km2 > *err_km2) {
           *err_km2 = errQ_km2;
         }
-        terr_km2 = (kk-1) * (*err_km2);
+        terr_km2 = (IDA_mem->ida_kk-1) * (*err_km2);
 
         /* Decrease order if errors are reduced */
-        if (SUNMAX(terr_km1, terr_km2) <= terr_k)  knew = kk - 1;
+        if (SUNMAX(terr_km1, terr_km2) <= terr_k)
+          IDA_mem->ida_knew = IDA_mem->ida_kk - 1;
       
       } else {
         
         /* Decrease order to 1 if errors are reduced by at least 1/2 */
-        if (terr_km1 <= (HALF * terr_k) )  knew = kk - 1; 
+        if (terr_km1 <= (HALF * terr_k) )
+          IDA_mem->ida_knew = IDA_mem->ida_kk - 1; 
         
       }
 
@@ -5730,56 +5584,61 @@ static int IDASensTestError(IDAMem IDA_mem, realtype ck,
   realtype errS_k, errS_km1, errS_km2;
   realtype terr_k, terr_km1, terr_km2;
   N_Vector *tempv;
-  booleantype check_for_reduction = FALSE;
+  booleantype check_for_reduction = SUNFALSE;
   int is;
 
   /* Rename deltaS */
-  tempv = deltaS;
+  tempv = IDA_mem->ida_deltaS;
 
   /* Update error for order k. */
-  enormS = IDASensWrmsNorm(IDA_mem, eeS, ewtS, suppressalg);
-  errS_k  = sigma[kk] * enormS;
+  enormS = IDASensWrmsNorm(IDA_mem, IDA_mem->ida_eeS, IDA_mem->ida_ewtS, IDA_mem->ida_suppressalg);
+  errS_k  = IDA_mem->ida_sigma[IDA_mem->ida_kk] * enormS;
   if (errS_k > *err_k) {
     *err_k = errS_k;
-    check_for_reduction = TRUE;
+    check_for_reduction = SUNTRUE;
   }
-  terr_k = (kk+1) * (*err_k);
+  terr_k = (IDA_mem->ida_kk+1) * (*err_k);
   
-  if ( kk > 1 ) {
+  if ( IDA_mem->ida_kk > 1 ) {
     
     /* Update error at order k-1 */
-    for(is=0;is<Ns;is++)
-      N_VLinearSum(ONE, phiS[kk][is], ONE, eeS[is], tempv[is]);
-    errS_km1 = sigma[kk-1] * IDASensWrmsNorm(IDA_mem, tempv, ewtS, suppressalg);
+    for(is=0;is<IDA_mem->ida_Ns;is++)
+      N_VLinearSum(ONE, IDA_mem->ida_phiS[IDA_mem->ida_kk][is], ONE, IDA_mem->ida_eeS[is], tempv[is]);
+    errS_km1 = IDA_mem->ida_sigma[IDA_mem->ida_kk-1] *
+      IDASensWrmsNorm(IDA_mem, tempv, IDA_mem->ida_ewtS, IDA_mem->ida_suppressalg);
     if (errS_km1 > *err_km1) {
       *err_km1 = errS_km1;
-      check_for_reduction = TRUE;
+      check_for_reduction = SUNTRUE;
     }
-    terr_km1 = kk * (*err_km1);
+    terr_km1 = IDA_mem->ida_kk * (*err_km1);
 
     /* Has an order decrease already been decided in IDATestError? */
-    if (knew != kk) check_for_reduction = FALSE;
+    if (IDA_mem->ida_knew != IDA_mem->ida_kk)
+      check_for_reduction = SUNFALSE;
 
     if (check_for_reduction) {
 
-      if ( kk > 2 ) {
+      if ( IDA_mem->ida_kk > 2 ) {
 
         /* Update error at order k-2 */
-        for(is=0;is<Ns;is++)
-          N_VLinearSum(ONE, phiS[kk-1][is], ONE, tempv[is], tempv[is]);
-        errS_km2 = sigma[kk-2] * IDASensWrmsNorm(IDA_mem, tempv, ewtS, suppressalg);
+        for(is=0;is<IDA_mem->ida_Ns;is++)
+          N_VLinearSum(ONE, IDA_mem->ida_phiS[IDA_mem->ida_kk-1][is], ONE, tempv[is], tempv[is]);
+        errS_km2 = IDA_mem->ida_sigma[IDA_mem->ida_kk-2] *
+          IDASensWrmsNorm(IDA_mem, tempv, IDA_mem->ida_ewtS, IDA_mem->ida_suppressalg);
         if (errS_km2 > *err_km2) {
           *err_km2 = errS_km2;
         }
-        terr_km2 = (kk-1) * (*err_km2);
+        terr_km2 = (IDA_mem->ida_kk-1) * (*err_km2);
 
         /* Decrease order if errors are reduced */
-        if (SUNMAX(terr_km1, terr_km2) <= terr_k)  knew = kk - 1;
+        if (SUNMAX(terr_km1, terr_km2) <= terr_k)
+          IDA_mem->ida_knew = IDA_mem->ida_kk - 1;
       
       } else {
         
         /* Decrease order to 1 if errors are reduced by at least 1/2 */
-        if (terr_km1 <= (HALF * terr_k) )  knew = kk - 1; 
+        if (terr_km1 <= (HALF * terr_k) )
+          IDA_mem->ida_knew = IDA_mem->ida_kk - 1; 
         
       }
 
@@ -5815,56 +5674,62 @@ static int IDAQuadSensTestError(IDAMem IDA_mem, realtype ck,
   realtype errQS_k, errQS_km1, errQS_km2;
   realtype terr_k, terr_km1, terr_km2;
   N_Vector *tempv;
-  booleantype check_for_reduction = FALSE;
+  booleantype check_for_reduction = SUNFALSE;
   int is;
 
-  tempv = yyQS;
+  tempv = IDA_mem->ida_yyQS;
 
-  enormQS = IDAQuadSensWrmsNorm(IDA_mem, eeQS, ewtQS);
-  errQS_k = sigma[kk] * enormQS;
+  enormQS = IDAQuadSensWrmsNorm(IDA_mem, IDA_mem->ida_eeQS, IDA_mem->ida_ewtQS);
+  errQS_k = IDA_mem->ida_sigma[IDA_mem->ida_kk] * enormQS;
 
   if (errQS_k > *err_k) {
     *err_k = errQS_k;
-    check_for_reduction = TRUE;
+    check_for_reduction = SUNTRUE;
   }
-  terr_k = (kk+1) * (*err_k);
+  terr_k = (IDA_mem->ida_kk+1) * (*err_k);
   
-  if ( kk > 1 ) {
+  if ( IDA_mem->ida_kk > 1 ) {
     
     /* Update error at order k-1 */
-    for(is=0;is<Ns;is++)
-      N_VLinearSum(ONE, phiQS[kk][is], ONE, eeQS[is], tempv[is]);
+    for(is=0;is<IDA_mem->ida_Ns;is++)
+      N_VLinearSum(ONE, IDA_mem->ida_phiQS[IDA_mem->ida_kk][is],
+                   ONE, IDA_mem->ida_eeQS[is], tempv[is]);
 
-    errQS_km1 = sigma[kk-1] * IDAQuadSensWrmsNorm(IDA_mem, tempv, ewtQS);
+    errQS_km1 = IDA_mem->ida_sigma[IDA_mem->ida_kk-1] *
+      IDAQuadSensWrmsNorm(IDA_mem, tempv, IDA_mem->ida_ewtQS);
 
     if (errQS_km1 > *err_km1) {
       *err_km1 = errQS_km1;
-      check_for_reduction = TRUE;
+      check_for_reduction = SUNTRUE;
     }
-    terr_km1 = kk * (*err_km1);
+    terr_km1 = IDA_mem->ida_kk * (*err_km1);
 
     /* Has an order decrease already been decided in IDATestError? */
-    if (knew != kk) check_for_reduction = FALSE;
+    if (IDA_mem->ida_knew != IDA_mem->ida_kk)
+      check_for_reduction = SUNFALSE;
 
     if (check_for_reduction) {
-      if ( kk > 2 ) {
+      if ( IDA_mem->ida_kk > 2 ) {
 
         /* Update error at order k-2 */
-        for(is=0;is<Ns;is++)
-          N_VLinearSum(ONE, phiQS[kk-1][is], ONE, tempv[is], tempv[is]);
+        for(is=0;is<IDA_mem->ida_Ns;is++)
+          N_VLinearSum(ONE, IDA_mem->ida_phiQS[IDA_mem->ida_kk-1][is], ONE, tempv[is], tempv[is]);
 
-        errQS_km2 = sigma[kk-2] * IDAQuadSensWrmsNorm(IDA_mem, tempv, ewtQS);
+        errQS_km2 = IDA_mem->ida_sigma[IDA_mem->ida_kk-2] *
+          IDAQuadSensWrmsNorm(IDA_mem, tempv, IDA_mem->ida_ewtQS);
         if (errQS_km2 > *err_km2) {
           *err_km2 = errQS_km2;
         }
-        terr_km2 = (kk-1) * (*err_km2);
+        terr_km2 = (IDA_mem->ida_kk-1) * (*err_km2);
 
         /* Decrease order if errors are reduced */
-        if (SUNMAX(terr_km1, terr_km2) <= terr_k)  knew = kk - 1;
+        if (SUNMAX(terr_km1, terr_km2) <= terr_k)
+          IDA_mem->ida_knew = IDA_mem->ida_kk - 1;
 
       } else {
         /* Decrease order to 1 if errors are reduced by at least 1/2 */
-        if (terr_km1 <= (HALF * terr_k) )  knew = kk - 1; 
+        if (terr_km1 <= (HALF * terr_k) )
+          IDA_mem->ida_knew = IDA_mem->ida_kk - 1; 
       }
     }
   }
@@ -5876,7 +5741,7 @@ static int IDAQuadSensTestError(IDAMem IDA_mem, realtype ck,
 /*
  * IDARestore
  *
- * This routine restores tn, psi, and phi in the event of a failure.
+ * This routine restores IDA_mem->ida_tn, psi, and phi in the event of a failure.
  * It changes back phi-star to phi (changed in IDASetCoeffs)
  */
 
@@ -5885,27 +5750,27 @@ static void IDARestore(IDAMem IDA_mem, realtype saved_t)
   int j;
   int is;
 
-  tn = saved_t;
+  IDA_mem->ida_tn = saved_t;
   
-  for (j = 1; j <= kk; j++) 
-    psi[j-1] = psi[j] - hh;
+  for (j = 1; j <= IDA_mem->ida_kk; j++) 
+    IDA_mem->ida_psi[j-1] = IDA_mem->ida_psi[j] - IDA_mem->ida_hh;
 
-  for (j = ns; j <= kk; j++) 
-    N_VScale(ONE/beta[j], phi[j], phi[j]);
+  for (j = IDA_mem->ida_ns; j <= IDA_mem->ida_kk; j++) 
+    N_VScale(ONE/IDA_mem->ida_beta[j], IDA_mem->ida_phi[j], IDA_mem->ida_phi[j]);
 
-  if (quadr)
-    for (j = ns; j <= kk; j++) 
-      N_VScale(ONE/beta[j], phiQ[j], phiQ[j]);
+  if (IDA_mem->ida_quadr)
+    for (j = IDA_mem->ida_ns; j <= IDA_mem->ida_kk; j++) 
+      N_VScale(ONE/IDA_mem->ida_beta[j], IDA_mem->ida_phiQ[j], IDA_mem->ida_phiQ[j]);
 
-  if (sensi)
-    for (is = 0; is < Ns; is++)
-      for (j = ns; j<=kk; j++) 
-        N_VScale(ONE/beta[j], phiS[j][is], phiS[j][is]);
+  if (IDA_mem->ida_sensi)
+    for (is = 0; is < IDA_mem->ida_Ns; is++)
+      for (j = IDA_mem->ida_ns; j<=IDA_mem->ida_kk; j++) 
+        N_VScale(ONE/IDA_mem->ida_beta[j], IDA_mem->ida_phiS[j][is], IDA_mem->ida_phiS[j][is]);
 
-  if (quadr_sensi)
-    for (is = 0; is < Ns; is++)
-      for (j = ns; j<=kk; j++) 
-        N_VScale(ONE/beta[j], phiQS[j][is], phiQS[j][is]);
+  if (IDA_mem->ida_quadr_sensi)
+    for (is = 0; is < IDA_mem->ida_Ns; is++)
+      for (j = IDA_mem->ida_ns; j<=IDA_mem->ida_kk; j++) 
+        N_VScale(ONE/IDA_mem->ida_beta[j], IDA_mem->ida_phiQS[j][is], IDA_mem->ida_phiQS[j][is]);
 
 }
 
@@ -5962,7 +5827,7 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
 {
   realtype err_knew;
 
-  phase = 1;
+  IDA_mem->ida_phase = 1;
     
   if (nflag != ERROR_TEST_FAIL) {
 
@@ -5981,11 +5846,11 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
       
       /* Reduce step size for a new prediction
          Note that if nflag=IDA_CONSTR_RECVR then rr was already set in IDANls */
-      if (nflag != IDA_CONSTR_RECVR) rr = QUARTER;
-      hh *= rr;
+      if (nflag != IDA_CONSTR_RECVR) IDA_mem->ida_rr = QUARTER;
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
 
       /* Test if there were too many convergence failures */
-      if (*ncfPtr < maxncf)               return(PREDICT_AGAIN);
+      if (*ncfPtr < IDA_mem->ida_maxncf)  return(PREDICT_AGAIN);
       else if (nflag == IDA_RES_RECVR)    return(IDA_REP_RES_ERR);
       else if (nflag == IDA_SRES_RECVR)   return(IDA_REP_SRES_ERR);
       else if (nflag == IDA_QRHS_RECVR)   return(IDA_REP_QRHS_ERR);
@@ -6008,12 +5873,12 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
       /* On first error test failure, keep current order or lower order by one. 
          Compute new stepsize based on differences of the solution. */
       
-      err_knew = (kk==knew)? err_k : err_km1;
+      err_knew = (IDA_mem->ida_kk==IDA_mem->ida_knew)? err_k : err_km1;
 
-      kk = knew;      
-      rr = PT9 * SUNRpowerR( TWO * err_knew + PT0001,(-ONE/(kk+1)) );
-      rr = SUNMAX(QUARTER, SUNMIN(PT9,rr));
-      hh *=rr;
+      IDA_mem->ida_kk = IDA_mem->ida_knew;      
+      IDA_mem->ida_rr = PT9 * SUNRpowerR( TWO * err_knew + PT0001,(-ONE/(IDA_mem->ida_kk+1)) );
+      IDA_mem->ida_rr = SUNMAX(QUARTER, SUNMIN(PT9,IDA_mem->ida_rr));
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
       return(PREDICT_AGAIN);
       
     } else if (*nefPtr == 2) {
@@ -6021,18 +5886,18 @@ static int IDAHandleNFlag(IDAMem IDA_mem, int nflag, realtype err_k, realtype er
       /* On second error test failure, use current order or decrease order by one. 
          Reduce stepsize by factor of 1/4. */
 
-      kk = knew;
-      rr = QUARTER;
-      hh *= rr;
+      IDA_mem->ida_kk = IDA_mem->ida_knew;
+      IDA_mem->ida_rr = QUARTER;
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
       return(PREDICT_AGAIN);
       
-    } else if (*nefPtr < maxnef) {
+    } else if (*nefPtr < IDA_mem->ida_maxnef) {
       
       /* On third and subsequent error test failures, set order to 1.
          Reduce stepsize by factor of 1/4. */
-      kk = 1;
-      rr = QUARTER;
-      hh *= rr;
+      IDA_mem->ida_kk = 1;
+      IDA_mem->ida_rr = QUARTER;
+      IDA_mem->ida_hh *= IDA_mem->ida_rr;
       return(PREDICT_AGAIN);
 
     } else {
@@ -6057,20 +5922,20 @@ static void IDAReset(IDAMem IDA_mem)
 {
   int is;
 
-  psi[0] = hh;
+  IDA_mem->ida_psi[0] = IDA_mem->ida_hh;
 
-  N_VScale(rr, phi[1], phi[1]);
+  N_VScale(IDA_mem->ida_rr, IDA_mem->ida_phi[1], IDA_mem->ida_phi[1]);
 
-  if (quadr)
-    N_VScale(rr, phiQ[1], phiQ[1]);
+  if (IDA_mem->ida_quadr)
+    N_VScale(IDA_mem->ida_rr, IDA_mem->ida_phiQ[1], IDA_mem->ida_phiQ[1]);
 
-  if (sensi)
-    for(is=0;is<Ns;is++) 
-      N_VScale(rr, phiS[1][is], phiS[1][is]);
+  if (IDA_mem->ida_sensi)
+    for(is=0;is<IDA_mem->ida_Ns;is++) 
+      N_VScale(IDA_mem->ida_rr, IDA_mem->ida_phiS[1][is], IDA_mem->ida_phiS[1][is]);
 
-  if (quadr_sensi)
-    for(is=0;is<Ns;is++) 
-      N_VScale(rr, phiQS[1][is], phiQS[1][is]);
+  if (IDA_mem->ida_quadr_sensi)
+    for(is=0;is<IDA_mem->ida_Ns;is++) 
+      N_VScale(IDA_mem->ida_rr, IDA_mem->ida_phiQS[1][is], IDA_mem->ida_phiQS[1][is]);
 }
 
 /* 
@@ -6096,12 +5961,14 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
   realtype enorm, tmp, hnew;
   N_Vector tempvQ, *tempvS;
 
-  nst++;
-  kdiff = kk - kused;
-  kused = kk;
-  hused = hh;
+  IDA_mem->ida_nst++;
+  kdiff = IDA_mem->ida_kk - IDA_mem->ida_kused;
+  IDA_mem->ida_kused = IDA_mem->ida_kk;
+  IDA_mem->ida_hused = IDA_mem->ida_hh;
 
-  if ( (knew == kk-1) || (kk == maxord) ) phase = 1;
+  if ( (IDA_mem->ida_knew == IDA_mem->ida_kk-1) ||
+       (IDA_mem->ida_kk == IDA_mem->ida_maxord) )
+    IDA_mem->ida_phase = 1;
 
   /* For the first few steps, until either a step fails, or the order is 
      reduced, or the order reaches its maximum, we raise the order and double 
@@ -6111,13 +5978,14 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
      Note that, after the first step, the order is not increased, as not all 
      of the neccessary information is available yet. */
   
-  if (phase == 0) {
-
-    if(nst > 1) {
-      kk++;
-      hnew = TWO * hh;
-      if( (tmp = SUNRabs(hnew)*hmax_inv) > ONE ) hnew /= tmp;
-      hh = hnew;
+  if (IDA_mem->ida_phase == 0) {
+
+    if(IDA_mem->ida_nst > 1) {
+      IDA_mem->ida_kk++;
+      hnew = TWO * IDA_mem->ida_hh;
+      if( (tmp = SUNRabs(hnew) * IDA_mem->ida_hmax_inv) > ONE )
+        hnew /= tmp;
+      IDA_mem->ida_hh = hnew;
     }
 
   } else {
@@ -6126,47 +5994,55 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
     
     /* Set action = LOWER/MAINTAIN/RAISE to specify order decision */
     
-    if (knew == kk-1)                   {action = LOWER;    goto takeaction;}
-    if (kk == maxord)                   {action = MAINTAIN; goto takeaction;}
-    if ( (kk+1 >= ns ) || (kdiff == 1)) {action = MAINTAIN; goto takeaction;}
+    if (IDA_mem->ida_knew == IDA_mem->ida_kk-1)      {action = LOWER;    goto takeaction;}
+    if (IDA_mem->ida_kk == IDA_mem->ida_maxord)      {action = MAINTAIN; goto takeaction;}
+    if ( (IDA_mem->ida_kk+1 >= IDA_mem->ida_ns ) || (kdiff == 1)) {action = MAINTAIN; goto takeaction;}
     
     /* Estimate the error at order k+1, unless already decided to
        reduce order, or already using maximum order, or stepsize has not
        been constant, or order was just raised. */
     
-    N_VLinearSum (ONE, ee, -ONE, phi[kk+1], tempv1);
-    enorm = IDAWrmsNorm(IDA_mem, tempv1, ewt, suppressalg);
+    N_VLinearSum(ONE, IDA_mem->ida_ee, -ONE,
+                 IDA_mem->ida_phi[IDA_mem->ida_kk+1],
+                 IDA_mem->ida_tempv1);
+    enorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_tempv1,
+                        IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
     
-    if (errconQ) {
-      tempvQ = ypQ;
-      N_VLinearSum (ONE, eeQ, -ONE, phiQ[kk+1], tempvQ);
-      enorm = IDAQuadWrmsNormUpdate(IDA_mem, enorm, tempvQ, ewtQ);
+    if (IDA_mem->ida_errconQ) {
+      tempvQ = IDA_mem->ida_ypQ;
+      N_VLinearSum (ONE, IDA_mem->ida_eeQ, -ONE,
+                    IDA_mem->ida_phiQ[IDA_mem->ida_kk+1], tempvQ);
+      enorm = IDAQuadWrmsNormUpdate(IDA_mem, enorm, tempvQ, IDA_mem->ida_ewtQ);
     }
 
-    if (errconS) {
-      tempvS = ypS;
-      for (is=0; is<Ns; is++)
-        N_VLinearSum (ONE, eeS[is], -ONE, phiS[kk+1][is], tempvS[is]);
-      enorm = IDASensWrmsNormUpdate(IDA_mem, enorm, tempvS, ewtS, suppressalg);
+    if (IDA_mem->ida_errconS) {
+      tempvS = IDA_mem->ida_ypS;
+      for (is=0; is<IDA_mem->ida_Ns; is++)
+        N_VLinearSum(ONE, IDA_mem->ida_eeS[is], -ONE,
+                     IDA_mem->ida_phiS[IDA_mem->ida_kk+1][is], tempvS[is]);
+      enorm = IDASensWrmsNormUpdate(IDA_mem, enorm, tempvS,
+                                    IDA_mem->ida_ewtS, IDA_mem->ida_suppressalg);
     }
 
-    if (errconQS) {
-      for (is=0; is<Ns; is++)
-        N_VLinearSum(ONE, eeQS[is], -ONE, phiQS[kk+1][is], tempvQS[is]);
-      enorm = IDAQuadSensWrmsNormUpdate(IDA_mem, enorm, tempvQS, ewtQS);
+    if (IDA_mem->ida_errconQS) {
+      for (is=0; is<IDA_mem->ida_Ns; is++)
+        N_VLinearSum(ONE, IDA_mem->ida_eeQS[is], -ONE,
+                     IDA_mem->ida_phiQS[IDA_mem->ida_kk+1][is], IDA_mem->ida_tempvQS[is]);
+      enorm = IDAQuadSensWrmsNormUpdate(IDA_mem, enorm,
+                                        IDA_mem->ida_tempvQS, IDA_mem->ida_ewtQS);
     }
-    err_kp1= enorm/(kk+2);
+    err_kp1= enorm/(IDA_mem->ida_kk+2);
 
     /* Choose among orders k-1, k, k+1 using local truncation error norms. */
 
-    terr_k   = (kk+1) * err_k;
-    terr_kp1 = (kk+2) * err_kp1;
+    terr_k   = (IDA_mem->ida_kk+1) * err_k;
+    terr_kp1 = (IDA_mem->ida_kk+2) * err_kp1;
 
-    if (kk == 1) {
+    if (IDA_mem->ida_kk == 1) {
       if (terr_kp1 >= HALF * terr_k)         {action = MAINTAIN; goto takeaction;}
       else                                   {action = RAISE;    goto takeaction;}
     } else {
-      terr_km1 = kk * err_km1;
+      terr_km1 = IDA_mem->ida_kk * err_km1;
       if (terr_km1 <= SUNMIN(terr_k, terr_kp1)) {action = LOWER;    goto takeaction;}
       else if (terr_kp1  >= terr_k)          {action = MAINTAIN; goto takeaction;}
       else                                   {action = RAISE;    goto takeaction;}
@@ -6175,72 +6051,83 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
   takeaction:
     
     /* Set the estimated error norm and, on change of order, reset kk. */
-    if      (action == RAISE) { kk++; err_knew = err_kp1; }
-    else if (action == LOWER) { kk--; err_knew = err_km1; }
+    if      (action == RAISE) { IDA_mem->ida_kk++; err_knew = err_kp1; }
+    else if (action == LOWER) { IDA_mem->ida_kk--; err_knew = err_km1; }
     else                      {       err_knew = err_k;   }  
 
     /* Compute rr = tentative ratio hnew/hh from error norm.
        Reduce hh if rr <= 1, double hh if rr >= 2, else leave hh as is.
        If hh is reduced, hnew/hh is restricted to be between .5 and .9. */
     
-    hnew = hh;
-    rr = SUNRpowerR( (TWO * err_knew + PT0001) , (-ONE/(kk+1) ) );
+    hnew = IDA_mem->ida_hh;
+    IDA_mem->ida_rr = SUNRpowerR( (TWO * err_knew + PT0001) , (-ONE/(IDA_mem->ida_kk+1) ) );
     
-    if (rr >= TWO) {
-      hnew = TWO * hh;
-      if( (tmp = SUNRabs(hnew)*hmax_inv) > ONE ) hnew /= tmp;
-    } else if (rr <= ONE ) { 
-      rr = SUNMAX(HALF, SUNMIN(PT9,rr));
-      hnew = hh * rr;
+    if (IDA_mem->ida_rr >= TWO) {
+      hnew = TWO * IDA_mem->ida_hh;
+      if( (tmp = SUNRabs(hnew) * IDA_mem->ida_hmax_inv) > ONE )
+        hnew /= tmp;
+    } else if (IDA_mem->ida_rr <= ONE ) { 
+      IDA_mem->ida_rr = SUNMAX(HALF, SUNMIN(PT9,IDA_mem->ida_rr));
+      hnew = IDA_mem->ida_hh * IDA_mem->ida_rr;
     }
     
-    hh = hnew;
+    IDA_mem->ida_hh = hnew;
     
   } /* end of phase if block */
   
   /* Save ee etc. for possible order increase on next step */
   
-  if (kused < maxord) {
+  if (IDA_mem->ida_kused < IDA_mem->ida_maxord) {
 
-    N_VScale(ONE, ee, phi[kused+1]);
+    N_VScale(ONE, IDA_mem->ida_ee, IDA_mem->ida_phi[IDA_mem->ida_kused+1]);
 
-    if (quadr)
-      N_VScale(ONE, eeQ, phiQ[kused+1]);
+    if (IDA_mem->ida_quadr)
+      N_VScale(ONE, IDA_mem->ida_eeQ, IDA_mem->ida_phiQ[IDA_mem->ida_kused+1]);
 
-    if (sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(ONE, eeS[is], phiS[kused+1][is]);
+    if (IDA_mem->ida_sensi)
+      for (is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(ONE, IDA_mem->ida_eeS[is], IDA_mem->ida_phiS[IDA_mem->ida_kused+1][is]);
 
-    if (quadr_sensi)
-      for (is=0; is<Ns; is++)
-        N_VScale(ONE, eeQS[is], phiQS[kused+1][is]);
+    if (IDA_mem->ida_quadr_sensi)
+      for (is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(ONE, IDA_mem->ida_eeQS[is], IDA_mem->ida_phiQS[IDA_mem->ida_kused+1][is]);
   }
 
   /* Update phi arrays */
 
-  N_VLinearSum(ONE, ee, ONE, phi[kused], phi[kused]);
-  for (j= kused-1; j>=0; j--)
-    N_VLinearSum(ONE, phi[j], ONE, phi[j+1], phi[j]);
-
-  if (quadr) {
-    N_VLinearSum(ONE, eeQ, ONE, phiQ[kused], phiQ[kused]);
-    for (j= kused-1; j>=0; j--)
-      N_VLinearSum(ONE, phiQ[j], ONE, phiQ[j+1], phiQ[j]);
-  }
-
-  if (sensi) {
-    for (is=0; is<Ns; is++) {
-      N_VLinearSum(ONE, eeS[is], ONE, phiS[kused][is], phiS[kused][is]);
-      for (j=kused-1; j>=0; j--)
-        N_VLinearSum(ONE, phiS[j][is], ONE, phiS[j+1][is], phiS[j][is]);
+  N_VLinearSum(ONE, IDA_mem->ida_ee, ONE, IDA_mem->ida_phi[IDA_mem->ida_kused],
+               IDA_mem->ida_phi[IDA_mem->ida_kused]);
+  for (j= IDA_mem->ida_kused-1; j>=0; j--)
+    N_VLinearSum(ONE, IDA_mem->ida_phi[j], ONE,
+                 IDA_mem->ida_phi[j+1], IDA_mem->ida_phi[j]);
+
+  if (IDA_mem->ida_quadr) {
+    N_VLinearSum(ONE, IDA_mem->ida_eeQ, ONE, IDA_mem->ida_phiQ[IDA_mem->ida_kused],
+                 IDA_mem->ida_phiQ[IDA_mem->ida_kused]);
+    for (j= IDA_mem->ida_kused-1; j>=0; j--)
+      N_VLinearSum(ONE, IDA_mem->ida_phiQ[j], ONE,
+                   IDA_mem->ida_phiQ[j+1], IDA_mem->ida_phiQ[j]);
+  }
+
+  if (IDA_mem->ida_sensi) {
+    for (is=0; is<IDA_mem->ida_Ns; is++) {
+      N_VLinearSum(ONE, IDA_mem->ida_eeS[is], ONE,
+                   IDA_mem->ida_phiS[IDA_mem->ida_kused][is],
+                   IDA_mem->ida_phiS[IDA_mem->ida_kused][is]);
+      for (j=IDA_mem->ida_kused-1; j>=0; j--)
+        N_VLinearSum(ONE, IDA_mem->ida_phiS[j][is], ONE,
+                     IDA_mem->ida_phiS[j+1][is], IDA_mem->ida_phiS[j][is]);
     }
   }
 
-  if (quadr_sensi) {
-    for (is=0; is<Ns; is++) {
-      N_VLinearSum(ONE, eeQS[is], ONE, phiQS[kused][is], phiQS[kused][is]);
-      for (j=kused-1; j>=0; j--)
-        N_VLinearSum(ONE, phiQS[j][is], ONE, phiQS[j+1][is], phiQS[j][is]);
+  if (IDA_mem->ida_quadr_sensi) {
+    for (is=0; is<IDA_mem->ida_Ns; is++) {
+      N_VLinearSum(ONE, IDA_mem->ida_eeQS[is], ONE,
+                   IDA_mem->ida_phiQS[IDA_mem->ida_kused][is],
+                   IDA_mem->ida_phiQS[IDA_mem->ida_kused][is]);
+      for (j=IDA_mem->ida_kused-1; j>=0; j--)
+        N_VLinearSum(ONE, IDA_mem->ida_phiQS[j][is], ONE,
+                     IDA_mem->ida_phiQS[j+1][is], IDA_mem->ida_phiQS[j][is]);
     }
   }
 
@@ -6256,12 +6143,12 @@ static void IDACompleteStep(IDAMem IDA_mem, realtype err_k, realtype err_km1)
  * IDAWrmsNorm
  *
  *  Returns the WRMS norm of vector x with weights w.
- *  If mask = TRUE, the weight vector w is masked by id, i.e.,
+ *  If mask = SUNTRUE, the weight vector w is masked by id, i.e.,
  *      nrm = N_VWrmsNormMask(x,w,id);
  *  Otherwise,
  *      nrm = N_VWrmsNorm(x,w);
  * 
- * mask = FALSE       when the call is made from the nonlinear solver.
+ * mask = SUNFALSE       when the call is made from the nonlinear solver.
  * mask = suppressalg otherwise.
  */
 
@@ -6270,7 +6157,7 @@ realtype IDAWrmsNorm(IDAMem IDA_mem, N_Vector x, N_Vector w,
 {
   realtype nrm;
 
-  if (mask) nrm = N_VWrmsNormMask(x, w, id);
+  if (mask) nrm = N_VWrmsNormMask(x, w, IDA_mem->ida_id);
   else      nrm = N_VWrmsNorm(x, w);
 
   return(nrm);
@@ -6297,7 +6184,7 @@ realtype IDASensWrmsNorm(IDAMem IDA_mem, N_Vector *xS, N_Vector *wS,
   realtype nrm, snrm;
 
   nrm = IDAWrmsNorm(IDA_mem, xS[0], wS[0], mask);
-  for (is=1; is<Ns; is++) {
+  for (is=1; is<IDA_mem->ida_Ns; is++) {
     snrm = IDAWrmsNorm(IDA_mem, xS[is], wS[is], mask);
     if ( snrm > nrm ) nrm = snrm;
   }
@@ -6320,7 +6207,7 @@ static realtype IDAQuadSensWrmsNorm(IDAMem IDA_mem, N_Vector *xQS, N_Vector *wQS
   realtype nrm, snrm;
 
   nrm = N_VWrmsNorm(xQS[0], wQS[0]);
-  for (is=1; is<Ns; is++) {
+  for (is=1; is<IDA_mem->ida_Ns; is++) {
     snrm = N_VWrmsNorm(xQS[is], wQS[is]);
     if ( snrm > nrm ) nrm = snrm;
   }
@@ -6371,7 +6258,7 @@ static realtype IDAQuadSensWrmsNormUpdate(IDAMem IDA_mem, realtype old_nrm,
 
   qsnrm = old_nrm;
 
-  for (is=0; is<Ns; is++) {
+  for (is=0; is<IDA_mem->ida_Ns; is++) {
     old_nrm = N_VWrmsNorm(xQS[is], wQS[is]);
     if(old_nrm > qsnrm) qsnrm = old_nrm;
   }
@@ -6402,39 +6289,44 @@ static int IDARcheck1(IDAMem IDA_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  tlo = tn;
-  ttol = (SUNRabs(tn) + SUNRabs(hh))*uround*HUNDRED;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+    IDA_mem->ida_iroots[i] = 0;
+  IDA_mem->ida_tlo = IDA_mem->ida_tn;
+  IDA_mem->ida_ttol = (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)) *
+    IDA_mem->ida_uround * HUNDRED;
 
   /* Evaluate g at initial t and check for zero values. */
-  retval = gfun (tlo, phi[0], phi[1], glo, user_data);
-  nge = 1;
+  retval = IDA_mem->ida_gfun(IDA_mem->ida_tlo, IDA_mem->ida_phi[0], IDA_mem->ida_phi[1],
+                             IDA_mem->ida_glo, IDA_mem->ida_user_data);
+  IDA_mem->ida_nge = 1;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      gactive[i] = FALSE;
+  zroot = SUNFALSE;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (SUNRabs(IDA_mem->ida_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      IDA_mem->ida_gactive[i] = SUNFALSE;
     }
   }
   if (!zroot) return(IDA_SUCCESS);
 
   /* Some g_i is zero at t0; look at g at t0+(small increment). */
-  hratio = SUNMAX(ttol/SUNRabs(hh), PT1);
-  smallh = hratio*hh;
-  tplus = tlo + smallh;
-  N_VLinearSum(ONE, phi[0], smallh, phi[1], yy);
-  retval = gfun (tplus, yy, phi[1], ghi, user_data);  
-  nge++;
+  hratio = SUNMAX(IDA_mem->ida_ttol / SUNRabs(IDA_mem->ida_hh), PT1);
+  smallh = hratio*IDA_mem->ida_hh;
+  tplus = IDA_mem->ida_tlo + smallh;
+  N_VLinearSum(ONE, IDA_mem->ida_phi[0], smallh, IDA_mem->ida_phi[1], IDA_mem->ida_yy);
+  retval = IDA_mem->ida_gfun(tplus, IDA_mem->ida_yy, IDA_mem->ida_phi[1],
+                             IDA_mem->ida_ghi, IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
   /* We check now only the components of g which were exactly 0.0 at t0
    * to see if we can 'activate' them. */
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i] && SUNRabs(ghi[i]) != ZERO) {
-      gactive[i] = TRUE;
-      glo[i] = ghi[i];
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (!IDA_mem->ida_gactive[i] &&
+        SUNRabs(IDA_mem->ida_ghi[i]) != ZERO) {
+      IDA_mem->ida_gactive[i] = SUNTRUE;
+      IDA_mem->ida_glo[i] = IDA_mem->ida_ghi[i];
     }
   }
   return(IDA_SUCCESS);
@@ -6467,49 +6359,55 @@ static int IDARcheck2(IDAMem IDA_mem)
   realtype smallh, hratio, tplus;
   booleantype zroot;
 
-  if (irfnd == 0) return(IDA_SUCCESS);
+  if (IDA_mem->ida_irfnd == 0) return(IDA_SUCCESS);
 
-  (void) IDAGetSolution(IDA_mem, tlo, yy, yp);
-  retval = gfun (tlo, yy, yp, glo, user_data);  
-  nge++;
+  (void) IDAGetSolution(IDA_mem, IDA_mem->ida_tlo, IDA_mem->ida_yy, IDA_mem->ida_yp);
+  retval = IDA_mem->ida_gfun(IDA_mem->ida_tlo, IDA_mem->ida_yy,
+                             IDA_mem->ida_yp, IDA_mem->ida_glo,
+                             IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) iroots[i] = 0;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(glo[i]) == ZERO) {
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+    IDA_mem->ida_iroots[i] = 0;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (!IDA_mem->ida_gactive[i]) continue;
+    if (SUNRabs(IDA_mem->ida_glo[i]) == ZERO) {
+      zroot = SUNTRUE;
+      IDA_mem->ida_iroots[i] = 1;
     }
   }
   if (!zroot) return(IDA_SUCCESS);
 
   /* One or more g_i has a zero at tlo.  Check g at tlo+smallh. */
-  ttol = (SUNRabs(tn) + SUNRabs(hh))*uround*HUNDRED;
-  smallh = (hh > ZERO) ? ttol : -ttol;
-  tplus = tlo + smallh;
-  if ( (tplus - tn)*hh >= ZERO) {
-    hratio = smallh/hh;
-    N_VLinearSum(ONE, yy, hratio, phi[1], yy);
+  IDA_mem->ida_ttol = (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)) *
+    IDA_mem->ida_uround * HUNDRED;
+  smallh = (IDA_mem->ida_hh > ZERO) ? IDA_mem->ida_ttol : -IDA_mem->ida_ttol;
+  tplus = IDA_mem->ida_tlo + smallh;
+  if ( (tplus - IDA_mem->ida_tn)*IDA_mem->ida_hh >= ZERO) {
+    hratio = smallh/IDA_mem->ida_hh;
+    N_VLinearSum(ONE, IDA_mem->ida_yy, hratio, IDA_mem->ida_phi[1], IDA_mem->ida_yy);
   } else {
-    (void) IDAGetSolution(IDA_mem, tplus, yy, yp);
+    (void) IDAGetSolution(IDA_mem, tplus, IDA_mem->ida_yy, IDA_mem->ida_yp);
   }
-  retval = gfun (tplus, yy, yp, ghi, user_data);  
-  nge++;
+  retval = IDA_mem->ida_gfun(tplus, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                             IDA_mem->ida_ghi, IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
   /* Check for close roots (error return), for a new zero at tlo+smallh,
   and for a g_i that changed from zero to nonzero. */
-  zroot = FALSE;
-  for (i = 0; i < nrtfn; i++) {
-    if (!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if (iroots[i] == 1) return(CLOSERT);
-      zroot = TRUE;
-      iroots[i] = 1;
+  zroot = SUNFALSE;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    if (!IDA_mem->ida_gactive[i]) continue;
+    if (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) {
+      if (IDA_mem->ida_iroots[i] == 1) return(CLOSERT);
+      zroot = SUNTRUE;
+      IDA_mem->ida_iroots[i] = 1;
     } else {
-      if (iroots[i] == 1) glo[i] = ghi[i];
+      if (IDA_mem->ida_iroots[i] == 1)
+        IDA_mem->ida_glo[i] = IDA_mem->ida_ghi[i];
     }
   }
   if (zroot) return(RTFOUND);
@@ -6534,34 +6432,42 @@ static int IDARcheck3(IDAMem IDA_mem)
   int i, ier, retval;
 
   /* Set thi = tn or tout, whichever comes first. */
-  if (taskc == IDA_ONE_STEP) thi = tn;
-  if (taskc == IDA_NORMAL) {
-    thi = ( (toutc - tn)*hh >= ZERO) ? tn : toutc;
+  if (IDA_mem->ida_taskc == IDA_ONE_STEP)
+    IDA_mem->ida_thi = IDA_mem->ida_tn;
+  if (IDA_mem->ida_taskc == IDA_NORMAL) {
+    IDA_mem->ida_thi = ((IDA_mem->ida_toutc - IDA_mem->ida_tn)*IDA_mem->ida_hh >= ZERO) ?
+      IDA_mem->ida_tn : IDA_mem->ida_toutc;
   }
 
   /* Get y and y' at thi. */
-  (void) IDAGetSolution(IDA_mem, thi, yy, yp);
+  (void) IDAGetSolution(IDA_mem, IDA_mem->ida_thi, IDA_mem->ida_yy, IDA_mem->ida_yp);
 
 
   /* Set ghi = g(thi) and call IDARootfind to search (tlo,thi) for roots. */
-  retval = gfun (thi, yy, yp, ghi, user_data);  
-  nge++;
+  retval = IDA_mem->ida_gfun(IDA_mem->ida_thi, IDA_mem->ida_yy,
+                             IDA_mem->ida_yp, IDA_mem->ida_ghi,
+                             IDA_mem->ida_user_data);  
+  IDA_mem->ida_nge++;
   if (retval != 0) return(IDA_RTFUNC_FAIL);
 
-  ttol = (SUNRabs(tn) + SUNRabs(hh))*uround*HUNDRED;
+  IDA_mem->ida_ttol = (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)) *
+    IDA_mem->ida_uround * HUNDRED;
   ier = IDARootfind(IDA_mem);
   if (ier == IDA_RTFUNC_FAIL) return(IDA_RTFUNC_FAIL);
-  for(i=0; i<nrtfn; i++) {
-    if(!gactive[i] && grout[i] != ZERO) gactive[i] = TRUE;
+  for(i=0; i<IDA_mem->ida_nrtfn; i++) {
+    if(!IDA_mem->ida_gactive[i] &&
+       IDA_mem->ida_grout[i] != ZERO)
+      IDA_mem->ida_gactive[i] = SUNTRUE;
   }
-  tlo = trout;
-  for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+  IDA_mem->ida_tlo = IDA_mem->ida_trout;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+    IDA_mem->ida_glo[i] = IDA_mem->ida_grout[i];
 
   /* If no root found, return IDA_SUCCESS. */  
   if (ier == IDA_SUCCESS) return(IDA_SUCCESS);
 
   /* If a root was found, interpolate to get y(trout) and return.  */
-  (void) IDAGetSolution(IDA_mem, trout, yy, yp);
+  (void) IDAGetSolution(IDA_mem, IDA_mem->ida_trout, IDA_mem->ida_yy, IDA_mem->ida_yp);
   return(RTFOUND);
 }
 
@@ -6595,10 +6501,10 @@ static int IDARcheck3(IDAMem IDA_mem)
  *
  * gactive  = array specifying whether a component of g should
  *            or should not be monitored. gactive[i] is initially
- *            set to TRUE for all i=0,...,nrtfn-1, but it may be
- *            reset to FALSE if at the first step g[i] is 0.0
+ *            set to SUNTRUE for all i=0,...,nrtfn-1, but it may be
+ *            reset to SUNFALSE if at the first step g[i] is 0.0
  *            both at the I.C. and at a small perturbation of them.
- *            gactive[i] is then set back on TRUE only after the 
+ *            gactive[i] is then set back on SUNTRUE only after the 
  *            corresponding g function moves away from 0.0.
  *
  * nge      = cumulative counter for gfun calls.
@@ -6653,19 +6559,20 @@ static int IDARootfind(IDAMem IDA_mem)
 
   /* First check for change in sign in ghi or for a zero in ghi. */
   maxfrac = ZERO;
-  zroot = FALSE;
-  sgnchg = FALSE;
-  for (i = 0;  i < nrtfn; i++) {
-    if(!gactive[i]) continue;
-    if (SUNRabs(ghi[i]) == ZERO) {
-      if(rootdir[i]*glo[i] <= ZERO) {
-        zroot = TRUE;
+  zroot = SUNFALSE;
+  sgnchg = SUNFALSE;
+  for (i = 0;  i < IDA_mem->ida_nrtfn; i++) {
+    if(!IDA_mem->ida_gactive[i]) continue;
+    if (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) {
+      if(IDA_mem->ida_rootdir[i]*IDA_mem->ida_glo[i] <= ZERO) {
+        zroot = SUNTRUE;
       }
     } else {
-      if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-        gfrac = SUNRabs(ghi[i]/(ghi[i] - glo[i]));
+      if ( (IDA_mem->ida_glo[i]*IDA_mem->ida_ghi[i] < ZERO) &&
+           (IDA_mem->ida_rootdir[i]*IDA_mem->ida_glo[i] <= ZERO) ) {
+        gfrac = SUNRabs(IDA_mem->ida_ghi[i]/(IDA_mem->ida_ghi[i] - IDA_mem->ida_glo[i]));
         if (gfrac > maxfrac) {
-          sgnchg = TRUE;
+          sgnchg = SUNTRUE;
           maxfrac = gfrac;
           imax = i;
         }
@@ -6676,14 +6583,16 @@ static int IDARootfind(IDAMem IDA_mem)
   /* If no sign change was found, reset trout and grout.  Then return
      IDA_SUCCESS if no zero was found, or set iroots and return RTFOUND.  */ 
   if (!sgnchg) {
-    trout = thi;
-    for (i = 0; i < nrtfn; i++) grout[i] = ghi[i];
+    IDA_mem->ida_trout = IDA_mem->ida_thi;
+    for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+      IDA_mem->ida_grout[i] = IDA_mem->ida_ghi[i];
     if (!zroot) return(IDA_SUCCESS);
-    for (i = 0; i < nrtfn; i++) {
-      iroots[i] = 0;
-      if(!gactive[i]) continue;
-      if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-        iroots[i] = glo[i] > 0 ? -1:1;
+    for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+      IDA_mem->ida_iroots[i] = 0;
+      if(!IDA_mem->ida_gactive[i]) continue;
+      if ( (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) &&
+           (IDA_mem->ida_rootdir[i]*IDA_mem->ida_glo[i] <= ZERO) )
+        IDA_mem->ida_iroots[i] = IDA_mem->ida_glo[i] > 0 ? -1:1;
     }
     return(RTFOUND);
   }
@@ -6694,10 +6603,11 @@ static int IDARootfind(IDAMem IDA_mem)
   /* A sign change was found.  Loop to locate nearest root. */
 
   side = 0;  sideprev = -1;
-  loop {                                    /* Looping point */
+  for(;;) {                                    /* Looping point */
 
     /* If interval size is already less than tolerance ttol, break. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) <= IDA_mem->ida_ttol)
+        break;
 
     /* Set weight alph.
        On the first two passes, set alph = 1.  Thereafter, reset alph
@@ -6718,38 +6628,43 @@ static int IDARootfind(IDAMem IDA_mem)
     /* Set next root approximation tmid and get g(tmid).
        If tmid is too close to tlo or thi, adjust it inward,
        by a fractional distance that is between 0.1 and 0.5.  */
-    tmid = thi - (thi - tlo)*ghi[imax]/(ghi[imax] - alph*glo[imax]);
-    if (SUNRabs(tmid - tlo) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    tmid = IDA_mem->ida_thi - (IDA_mem->ida_thi - IDA_mem->ida_tlo) *
+      IDA_mem->ida_ghi[imax]/(IDA_mem->ida_ghi[imax] - alph*IDA_mem->ida_glo[imax]);
+    if (SUNRabs(tmid - IDA_mem->ida_tlo) < HALF * IDA_mem->ida_ttol) {
+      fracint = SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) / IDA_mem->ida_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = tlo + fracsub*(thi - tlo);
+      tmid = IDA_mem->ida_tlo + fracsub*(IDA_mem->ida_thi - IDA_mem->ida_tlo);
     }
-    if (SUNRabs(thi - tmid) < HALF*ttol) {
-      fracint = SUNRabs(thi - tlo)/ttol;
+    if (SUNRabs(IDA_mem->ida_thi - tmid) < HALF * IDA_mem->ida_ttol) {
+      fracint = SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) / IDA_mem->ida_ttol;
       fracsub = (fracint > FIVE) ? PT1 : HALF/fracint;
-      tmid = thi - fracsub*(thi - tlo);
+      tmid = IDA_mem->ida_thi - fracsub*(IDA_mem->ida_thi - IDA_mem->ida_tlo);
     }
 
-    (void) IDAGetSolution(IDA_mem, tmid, yy, yp);
-    retval = gfun (tmid, yy, yp, grout, user_data);  
-    nge++;
+    (void) IDAGetSolution(IDA_mem, tmid, IDA_mem->ida_yy, IDA_mem->ida_yp);
+    retval = IDA_mem->ida_gfun(tmid, IDA_mem->ida_yy, IDA_mem->ida_yp,
+                               IDA_mem->ida_grout, IDA_mem->ida_user_data);  
+    IDA_mem->ida_nge++;
     if (retval != 0) return(IDA_RTFUNC_FAIL);
 
     /* Check to see in which subinterval g changes sign, and reset imax.
        Set side = 1 if sign change is on low side, or 2 if on high side.  */  
     maxfrac = ZERO;
-    zroot = FALSE;
-    sgnchg = FALSE;
+    zroot = SUNFALSE;
+    sgnchg = SUNFALSE;
     sideprev = side;
-    for (i = 0;  i < nrtfn; i++) {
-      if(!gactive[i]) continue;
-      if (SUNRabs(grout[i]) == ZERO) {
-        if(rootdir[i]*glo[i] <= ZERO) zroot = TRUE;
+    for (i = 0;  i < IDA_mem->ida_nrtfn; i++) {
+      if(!IDA_mem->ida_gactive[i]) continue;
+      if (SUNRabs(IDA_mem->ida_grout[i]) == ZERO) {
+        if(IDA_mem->ida_rootdir[i]*IDA_mem->ida_glo[i] <= ZERO)
+          zroot = SUNTRUE;
       } else {
-        if ( (glo[i]*grout[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) {
-          gfrac = SUNRabs(grout[i]/(grout[i] - glo[i]));
+        if ( (IDA_mem->ida_glo[i]*IDA_mem->ida_grout[i] < ZERO) &&
+             (IDA_mem->ida_rootdir[i]*IDA_mem->ida_glo[i] <= ZERO) ) {
+          gfrac = SUNRabs(IDA_mem->ida_grout[i] /
+                          (IDA_mem->ida_grout[i] - IDA_mem->ida_glo[i]));
           if (gfrac > maxfrac) {
-            sgnchg = TRUE;
+            sgnchg = SUNTRUE;
             maxfrac = gfrac;
             imax = i;
           }
@@ -6758,41 +6673,48 @@ static int IDARootfind(IDAMem IDA_mem)
     }
     if (sgnchg) {
       /* Sign change found in (tlo,tmid); replace thi with tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      IDA_mem->ida_thi = tmid;
+      for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+        IDA_mem->ida_ghi[i] = IDA_mem->ida_grout[i];
       side = 1;
       /* Stop at root thi if converged; otherwise loop. */
-      if (SUNRabs(thi - tlo) <= ttol) break;
+      if (SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) <= IDA_mem->ida_ttol)
+        break;
       continue;  /* Return to looping point. */
     }
 
     if (zroot) {
       /* No sign change in (tlo,tmid), but g = 0 at tmid; return root tmid. */
-      thi = tmid;
-      for (i = 0; i < nrtfn; i++) ghi[i] = grout[i];
+      IDA_mem->ida_thi = tmid;
+      for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+        IDA_mem->ida_ghi[i] = IDA_mem->ida_grout[i];
       break;
     }
 
     /* No sign change in (tlo,tmid), and no zero at tmid.
        Sign change must be in (tmid,thi).  Replace tlo with tmid. */
-    tlo = tmid;
-    for (i = 0; i < nrtfn; i++) glo[i] = grout[i];
+    IDA_mem->ida_tlo = tmid;
+    for (i = 0; i < IDA_mem->ida_nrtfn; i++)
+      IDA_mem->ida_glo[i] = IDA_mem->ida_grout[i];
     side = 2;
     /* Stop at root thi if converged; otherwise loop back. */
-    if (SUNRabs(thi - tlo) <= ttol) break;
+    if (SUNRabs(IDA_mem->ida_thi - IDA_mem->ida_tlo) <= IDA_mem->ida_ttol)
+      break;
 
   } /* End of root-search loop */
 
   /* Reset trout and grout, set iroots, and return RTFOUND. */
-  trout = thi;
-  for (i = 0; i < nrtfn; i++) {
-    grout[i] = ghi[i];
-    iroots[i] = 0;
-    if(!gactive[i]) continue;
-    if ( (SUNRabs(ghi[i]) == ZERO) && (rootdir[i]*glo[i] <= ZERO) )
-      iroots[i] = glo[i] > 0 ? -1:1;
-    if ( (glo[i]*ghi[i] < ZERO) && (rootdir[i]*glo[i] <= ZERO) ) 
-      iroots[i] = glo[i] > 0 ? -1:1;
+  IDA_mem->ida_trout = IDA_mem->ida_thi;
+  for (i = 0; i < IDA_mem->ida_nrtfn; i++) {
+    IDA_mem->ida_grout[i] = IDA_mem->ida_ghi[i];
+    IDA_mem->ida_iroots[i] = 0;
+    if(!IDA_mem->ida_gactive[i]) continue;
+    if ( (SUNRabs(IDA_mem->ida_ghi[i]) == ZERO) &&
+         (IDA_mem->ida_rootdir[i]*IDA_mem->ida_glo[i] <= ZERO) )
+      IDA_mem->ida_iroots[i] = IDA_mem->ida_glo[i] > 0 ? -1:1;
+    if ( (IDA_mem->ida_glo[i]*IDA_mem->ida_ghi[i] < ZERO) &&
+         (IDA_mem->ida_rootdir[i]*IDA_mem->ida_glo[i] <= ZERO) ) 
+      IDA_mem->ida_iroots[i] = IDA_mem->ida_glo[i] > 0 ? -1:1;
   }
   return(RTFOUND);
 }
@@ -6803,11 +6725,6 @@ static int IDARootfind(IDAMem IDA_mem)
  * =================================================================
  */
 
-#undef Ns
-#undef yy
-#undef yp
-#undef yyS
-#undef ypS
 #undef user_dataS
 
 /*
@@ -6870,31 +6787,31 @@ static int IDASensRes1DQ(int Ns, realtype t,
   IDA_mem = (IDAMem) user_dataS;
 
   /* Set base perturbation del */
-  del  = SUNRsqrt(SUNMAX(rtol, uround));
+  del  = SUNRsqrt(SUNMAX(IDA_mem->ida_rtol, IDA_mem->ida_uround));
   rdel = ONE/del;
 
-  pbari = pbar[is];
+  pbari = IDA_mem->ida_pbar[is];
 
-  which = plist[is];
+  which = IDA_mem->ida_plist[is];
 
-  psave = p[which];
+  psave = IDA_mem->ida_p[which];
 
   Delp  = pbari * del;
   rDelp = ONE/Delp;
-  norms = N_VWrmsNorm(yyS, ewt) * pbari;
+  norms = N_VWrmsNorm(yyS, IDA_mem->ida_ewt) * pbari;
   rDely = SUNMAX(norms, rdel) / pbari;
   Dely  = ONE/rDely;
 
-  if (DQrhomax == ZERO) {
+  if (IDA_mem->ida_DQrhomax == ZERO) {
     /* No switching */
-    method = (DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
+    method = (IDA_mem->ida_DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
   } else {
     /* switch between simultaneous/separate DQ */
     ratio = Dely * rDelp;
-    if ( SUNMAX(ONE/ratio, ratio) <= DQrhomax )
-      method = (DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
+    if ( SUNMAX(ONE/ratio, ratio) <= IDA_mem->ida_DQrhomax )
+      method = (IDA_mem->ida_DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
     else
-      method = (DQtype==IDA_CENTERED) ? CENTERED2 : FORWARD2;
+      method = (IDA_mem->ida_DQtype==IDA_CENTERED) ? CENTERED2 : FORWARD2;
   }
   
   switch (method) {
@@ -6907,21 +6824,21 @@ static int IDASensRes1DQ(int Ns, realtype t,
     /* Forward perturb y, y' and parameter */
     N_VLinearSum(Del, yyS, ONE, yy, ytemp);
     N_VLinearSum(Del, ypS, ONE, yp, yptemp);
-    p[which] = psave + Del;
+    IDA_mem->ida_p[which] = psave + Del;
 
     /* Save residual in resvalS */
-    retval = res(t, ytemp, yptemp, resvalS, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, ytemp, yptemp, resvalS, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
     
     /* Backward perturb y, y' and parameter */
     N_VLinearSum(-Del, yyS, ONE, yy, ytemp);
     N_VLinearSum(-Del, ypS, ONE, yp, yptemp);
-    p[which] = psave - Del;
+    IDA_mem->ida_p[which] = psave - Del;
 
     /* Save residual in restemp */
-    retval = res(t, ytemp, yptemp, restemp, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, ytemp, yptemp, restemp, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
 
     /* Estimate the residual for the i-th sensitivity equation */
@@ -6939,8 +6856,8 @@ static int IDASensRes1DQ(int Ns, realtype t,
     N_VLinearSum(Dely, ypS, ONE, yp, yptemp);
     
     /* Save residual in resvalS */
-    retval = res(t, ytemp, yptemp, resvalS, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, ytemp, yptemp, resvalS, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
     
     /* Backward perturb y and y' */
@@ -6948,27 +6865,27 @@ static int IDASensRes1DQ(int Ns, realtype t,
     N_VLinearSum(-Dely, ypS, ONE, yp, yptemp);
 
     /* Save residual in restemp */
-    retval = res(t, ytemp, yptemp, restemp, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, ytemp, yptemp, restemp, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
 
     /* Save the first difference quotient in resvalS */
     N_VLinearSum(r2Dely, resvalS, -r2Dely, restemp, resvalS);
 
     /* Forward perturb parameter */
-    p[which] = psave + Delp;
+    IDA_mem->ida_p[which] = psave + Delp;
 
     /* Save residual in ytemp */
-    retval = res(t, yy, yp, ytemp, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, yy, yp, ytemp, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
 
     /* Backward perturb parameter */
-    p[which] = psave - Delp;
+    IDA_mem->ida_p[which] = psave - Delp;
 
     /* Save residual in yptemp */
-    retval = res(t, yy, yp, yptemp, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, yy, yp, yptemp, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
     
     /* Save the second difference quotient in restemp */
@@ -6987,11 +6904,11 @@ static int IDASensRes1DQ(int Ns, realtype t,
     /* Forward perturb y, y' and parameter */
     N_VLinearSum(Del, yyS, ONE, yy, ytemp);
     N_VLinearSum(Del, ypS, ONE, yp, yptemp);
-    p[which] = psave + Del;
+    IDA_mem->ida_p[which] = psave + Del;
 
     /* Save residual in resvalS */
-    retval = res(t, ytemp, yptemp, resvalS, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, ytemp, yptemp, resvalS, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
 
     /* Estimate the residual for the i-th sensitivity equation */
@@ -7006,19 +6923,19 @@ static int IDASensRes1DQ(int Ns, realtype t,
     N_VLinearSum(Dely, ypS, ONE, yp, yptemp);
 
     /* Save residual in resvalS */
-    retval = res(t, ytemp, yptemp, resvalS, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, ytemp, yptemp, resvalS, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
 
     /* Save the first difference quotient in resvalS */
     N_VLinearSum(rDely, resvalS, -rDely, resval, resvalS);
 
     /* Forward perturb parameter */
-    p[which] = psave + Delp;
+    IDA_mem->ida_p[which] = psave + Delp;
 
     /* Save residual in restemp */
-    retval = res(t, yy, yp, restemp, user_data);
-    nreS++;
+    retval = IDA_mem->ida_res(t, yy, yp, restemp, IDA_mem->ida_user_data);
+    IDA_mem->ida_nreS++;
     if (retval != 0) return(retval);
 
     /* Save the second difference quotient in restemp */
@@ -7032,7 +6949,7 @@ static int IDASensRes1DQ(int Ns, realtype t,
   }
 
   /* Restore original value of parameter */
-  p[which] = psave;
+  IDA_mem->ida_p[which] = psave;
   
   return(0);
 
@@ -7085,21 +7002,21 @@ static int IDAQuadSensRhs1InternalDQ(IDAMem IDA_mem, int is, realtype t,
   realtype Del , r2Del ;
   realtype norms;
 
-  del = SUNRsqrt(SUNMAX(rtol, uround));
+  del = SUNRsqrt(SUNMAX(IDA_mem->ida_rtol, IDA_mem->ida_uround));
   rdel = ONE/del;
   
-  pbari = pbar[is];
+  pbari = IDA_mem->ida_pbar[is];
 
-  which = plist[is];
+  which = IDA_mem->ida_plist[is];
 
-  psave = p[which];
+  psave = IDA_mem->ida_p[which];
   
   Delp  = pbari * del;
-  norms   = N_VWrmsNorm(yyS, ewt) * pbari;
+  norms   = N_VWrmsNorm(yyS, IDA_mem->ida_ewt) * pbari;
   rDely = SUNMAX(norms, rdel) / pbari;
   Dely  = ONE/rDely;
   
-  method = (DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
+  method = (IDA_mem->ida_DQtype==IDA_CENTERED) ? CENTERED1 : FORWARD1;
 
   switch(method) {
 
@@ -7110,18 +7027,18 @@ static int IDAQuadSensRhs1InternalDQ(IDAMem IDA_mem, int is, realtype t,
     
     N_VLinearSum(ONE, yy, Del, yyS, yytmp);
     N_VLinearSum(ONE, yp, Del, ypS, yptmp);
-    p[which] = psave + Del;
+    IDA_mem->ida_p[which] = psave + Del;
 
-    retval = rhsQ(t, yytmp, yptmp, resvalQS, user_data);
+    retval = IDA_mem->ida_rhsQ(t, yytmp, yptmp, resvalQS, IDA_mem->ida_user_data);
     nfel++;
     if (retval != 0) return(retval);
     
     N_VLinearSum(-Del, yyS, ONE, yy, yytmp);
     N_VLinearSum(-Del, ypS, ONE, yp, yptmp);
 
-    p[which] = psave - Del;
+    IDA_mem->ida_p[which] = psave - Del;
 
-    retval = rhsQ(t, yytmp, yptmp, tmpQS, user_data);
+    retval = IDA_mem->ida_rhsQ(t, yytmp, yptmp, tmpQS, IDA_mem->ida_user_data);
     nfel++;
     if (retval != 0) return(retval);
 
@@ -7136,9 +7053,9 @@ static int IDAQuadSensRhs1InternalDQ(IDAMem IDA_mem, int is, realtype t,
     
     N_VLinearSum(ONE, yy, Del, yyS, yytmp);
     N_VLinearSum(ONE, yp, Del, ypS, yptmp);
-    p[which] = psave + Del;
+    IDA_mem->ida_p[which] = psave + Del;
 
-    retval = rhsQ(t, yytmp, yptmp, resvalQS, user_data);
+    retval = IDA_mem->ida_rhsQ(t, yytmp, yptmp, resvalQS, IDA_mem->ida_user_data);
     nfel++;
     if (retval != 0) return(retval);
     
@@ -7147,9 +7064,9 @@ static int IDAQuadSensRhs1InternalDQ(IDAMem IDA_mem, int is, realtype t,
     break;
   }
 
-  p[which] = psave;
+  IDA_mem->ida_p[which] = psave;
   /* Increment counter nrQeS */
-  nrQeS += nfel;
+  IDA_mem->ida_nrQeS += nfel;
   
   return(0);
 }
@@ -7168,9 +7085,6 @@ static int IDAQuadSensRhs1InternalDQ(IDAMem IDA_mem, int is, realtype t,
  *   pointed to by ida_ehfun.
  */
 
-#define ehfun   (IDA_mem->ida_ehfun)
-#define eh_data (IDA_mem->ida_eh_data)
-
 void IDAProcessError(IDAMem IDA_mem, 
                     int error_code, const char *module, const char *fname, 
                     const char *msgfmt, ...)
@@ -7194,7 +7108,7 @@ void IDAProcessError(IDAMem IDA_mem,
 #endif
 
   } else {                 /* We can call ehfun */
-    ehfun(error_code, module, fname, msg, eh_data);
+    IDA_mem->ida_ehfun(error_code, module, fname, msg, IDA_mem->ida_eh_data);
   }
 
   /* Finalize argument processing */
@@ -7206,8 +7120,6 @@ void IDAProcessError(IDAMem IDA_mem,
 /* IDAErrHandler is the default error handling function.
    It sends the error message to the stream pointed to by ida_errfp */
 
-#define errfp (IDA_mem->ida_errfp)
-
 void IDAErrHandler(int error_code, const char *module,
                    const char *function, char *msg, void *data)
 {
@@ -7224,9 +7136,9 @@ void IDAErrHandler(int error_code, const char *module,
     sprintf(err_type,"ERROR");
 
 #ifndef NO_FPRINTF_OUTPUT
-  if (errfp!=NULL) {
-    fprintf(errfp,"\n[%s %s]  %s\n",module,err_type,function);
-    fprintf(errfp,"  %s\n\n",msg);
+  if (IDA_mem->ida_errfp != NULL) {
+    fprintf(IDA_mem->ida_errfp,"\n[%s %s]  %s\n",module,err_type,function);
+    fprintf(IDA_mem->ida_errfp,"  %s\n\n",msg);
   }
 #endif
 
diff --git a/src/idas/idas_band.c b/src/idas/idas_band.c
deleted file mode 100644
index f0c2935..0000000
--- a/src/idas/idas_band.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4909 $
- * $Date: 2016-09-14 16:51:27 -0700 (Wed, 14 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDAS banded linear
- * solver module, IDABAND. This module uses standard banded
- * matrix techniques to solve the linear systems generated by the
- * (nonlinear) Newton iteration process. The user may either
- * supply a banded Jacobian routine or use the routine supplied
- * with this module (IDABandDQJac).
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <idas/idas_band.h>
-#include "idas_direct_impl.h"
-#include "idas_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* IDABAND linit, lsetup, lsolve, and lfree routines */
- 
-static int IDABandInit(IDAMem IDA_mem);
-
-static int IDABandSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                        N_Vector rrp, N_Vector tmp1,
-                        N_Vector tmp2, N_Vector tmp3);
-
-static int IDABandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDABandFree(IDAMem IDA_mem);
-
-/* IDABAND lfreeB function */
-
-static int IDABandFreeB(IDABMem IDAB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define res         (IDA_mem->ida_res)
-#define tn          (IDA_mem->ida_tn)
-#define hh          (IDA_mem->ida_hh)
-#define cj          (IDA_mem->ida_cj)
-#define cjratio     (IDA_mem->ida_cjratio)
-#define ewt         (IDA_mem->ida_ewt)
-#define constraints (IDA_mem->ida_constraints)
-#define linit       (IDA_mem->ida_linit)
-#define lsetup      (IDA_mem->ida_lsetup)
-#define lsolve      (IDA_mem->ida_lsolve)
-#define lperf       (IDA_mem->ida_lperf)
-#define lfree       (IDA_mem->ida_lfree)
-#define lmem        (IDA_mem->ida_lmem)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define mtype       (idadls_mem->d_type)
-#define neq         (idadls_mem->d_n)
-#define ml          (idadls_mem->d_ml)
-#define mu          (idadls_mem->d_mu)
-#define jacDQ       (idadls_mem->d_jacDQ)
-#define bjac        (idadls_mem->d_bjac)
-#define JJ          (idadls_mem->d_J)
-#define smu         (idadls_mem->d_smu)
-#define lpivots     (idadls_mem->d_lpivots)
-#define nje         (idadls_mem->d_nje)
-#define nreDQ       (idadls_mem->d_nreDQ)
-#define jacdata     (idadls_mem->d_J_data)
-#define last_flag   (idadls_mem->d_last_flag)
-                  
-/*
- * -----------------------------------------------------------------
- * IDABand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDABAND linear solver module.
- * IDABand first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDABandInit, IDABandSetup,
- * IDABandSolve, NULL, and IDABandFree, respectively.
- * It allocates memory for a structure of type IDADlsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jacdata field in
- * the IDADlsMemRec structure to be the input parameter jdata, and sets
- * the d_bjac field to be:
- *   (1) the input parameter bjac, if bjac != NULL, or
- *   (2) IDABandDQJac, if bjac == NULL.
- * Finally, it allocates memory for JJ and lpivots.
- * IDABand returns IDADLS_SUCCESS = 0, IDADLS_LMEM_FAIL = -1,
- * or IDADLS_ILL_INPUT = -2.
- *
- * NOTE: The band linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDABand will first 
- *       test for a compatible N_Vector internal representation by
- *       checking that the N_VGetArrayPointer function exists
- * -----------------------------------------------------------------
- */
-
-int IDABand(void *ida_mem, long int Neq, long int mupper, long int mlower)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASBAND", "IDABand", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASBAND", "IDABand", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Test mlower and mupper for legality. */
-  if ((mlower < 0) || (mupper < 0) || (mlower >= Neq) || (mupper >= Neq)) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASBAND", "IDABand", MSGD_BAD_SIZES);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem. */
-  linit  = IDABandInit;
-  lsetup = IDABandSetup;
-  lsolve = IDABandSolve;
-  lperf  = NULL;
-  lfree  = IDABandFree;
-
-  /* Get memory for IDADlsMemRec. */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASBAND", "IDABand", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ   = TRUE;
-  bjac    = NULL;
-  jacdata = NULL;
-  last_flag = IDADLS_SUCCESS;
-
-  idaDlsInitializeCounters(idadls_mem); 
-
-  setupNonNull = TRUE;
-
-  /* Store problem size */
-  neq = Neq;
-
-  idadls_mem->d_ml = mlower;
-  idadls_mem->d_mu = mupper;
-    
-  /* Set extended upper half-bandwidth for JJ (required for pivoting). */
-  smu = SUNMIN(Neq-1, mupper + mlower);
-
-  /* Allocate memory for JJ and pivot array. */
-  JJ = NULL;
-  JJ = NewBandMat(Neq, mupper, mlower, smu);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASBAND", "IDABand", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  lpivots = NULL;
-  lpivots = NewLintArray(Neq);
-  if (lpivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASBAND", "IDABand", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }  
-  
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDABAND interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDABAND
-  linear solver module.  It returns 0.
-*/
-
-static int IDABandInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  /* Initialize nje and nreB */
-  idaDlsInitializeCounters(idadls_mem); 
-
-  if (jacDQ) {
-    bjac = idaDlsBandDQJac;
-    jacdata = IDA_mem;
-  } else {
-    jacdata = IDA_mem->ida_user_data;
-  }
-
-  last_flag = 0;
-  return(0);
-}
-
-
-/*
-  This routine does the setup operations for the IDABAND linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the band LU factorization routine.
-  The return value is either
-     IDADLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDABandSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                        N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-                        N_Vector tmp3)
-{
-  int retval;
-  long int retfac;
-  IDADlsMem idadls_mem;
-  
-  idadls_mem = (IDADlsMem) lmem;
-
-  /* Increment nje counter. */
-  nje++;
-
-  /* Zero out JJ; call Jacobian routine jac; return if it failed. */
-  SetToZero(JJ);
-  retval = bjac(neq, mu, ml, tn,  cj, yyp, ypp, rrp,
-                JJ, jacdata, tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDASBAND", "IDABandSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  /* Do LU factorization of JJ; return success or fail flag. */
-  retfac = BandGBTRF(JJ, lpivots);
-  
-  if (retfac != 0) {
-    last_flag = retfac;
-    return(+1);
-  }
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-/*
-  This routine handles the solve operation for the IDABAND linear
-  solver module.  It calls the band backsolve routine, scales the
-  solution vector according to cjratio, then returns IDADLS_SUCCESS = 0.
-*/
-
-static int IDABandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                        N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  bd = N_VGetArrayPointer(b);
-  BandGBTRS(JJ, lpivots, bd);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-  
-  last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine frees memory specific to the IDABAND linear solver.
-*/
-
-static int IDABandFree(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(lpivots);
-  free(lmem); lmem = NULL;
-
-  return(0);
-
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-
-/*
- * IDABandB is a wrapper around IDABand. It attaches the IDASBAND linear solver
- * to the backward problem memory block.
- */
-
-int IDABandB(void *ida_mem, int which,
-             long int NeqB, long int mupperB, long int mlowerB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDADlsMemB idadlsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASBAND", "IDABandB", MSGD_CAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASBAND", "IDABandB",  MSGD_NO_ADJ);
-    return(IDADLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASBAND", "IDABandB", MSGD_BAD_WHICH);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Get memory for IDADlsMemRecB */
-  idadlsB_mem = (IDADlsMemB) malloc(sizeof(struct IDADlsMemRecB));
-  if (idadlsB_mem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_MEM_FAIL, "IDASBAND", "IDABandB", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  
-  }
-
-  /* set matrix type and initialize Jacob function. */
-  idadlsB_mem->d_typeB = SUNDIALS_BAND;
-  idadlsB_mem->d_bjacB = NULL;
-
-
-  /* Attach lmemB data and lfreeB function. */
-  IDAB_mem->ida_lmem  = idadlsB_mem;
-  IDAB_mem->ida_lfree = IDABandFreeB;
-
-  /* Call IDABand to attach the IDABAND linear solver. */
-  ida_memB = (void *)IDAB_mem->IDA_mem;
-  flag = IDABand(ida_memB, NeqB, mupperB, mlowerB);
-
-  if (flag != IDADLS_SUCCESS) {
-    free(idadlsB_mem);
-    idadlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * IDABandFreeB 
- */
-
-static int IDABandFreeB(IDABMem IDAB_mem)
-{
-  IDADlsMemB idadlsB_mem;
-
-  idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
-
-  free(idadlsB_mem);
-
-  return(0);
-}
-
diff --git a/src/idas/idas_bbdpre.c b/src/idas/idas_bbdpre.c
index 2b93fba..af1ad25 100644
--- a/src/idas/idas_bbdpre.c
+++ b/src/idas/idas_bbdpre.c
@@ -1,24 +1,26 @@
 /*
- * -----------------------------------------------------------------
- * $Revision: 4921 $
- * $Date: 2016-09-19 14:35:11 -0700 (Mon, 19 Sep 2016) $
  * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *        Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
  * This file contains implementations of routines for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with IDAS and an IDASPILS
- * linear solver.
+ * matrix with banded blocks, for use with IDA, the IDASPILS 
+ * linear solver interface.
  *
  * NOTE: With only one processor in use, a banded matrix results
  * rather than a block-diagonal matrix with banded blocks.
@@ -32,102 +34,79 @@
 #include "idas_impl.h"
 #include "idas_spils_impl.h"
 #include "idas_bbdpre_impl.h"
-
-#include <idas/idas_spgmr.h>
-#include <idas/idas_spbcgs.h>
-#include <idas/idas_sptfqmr.h>
-
 #include <sundials/sundials_math.h>
+#include <nvector/nvector_serial.h>
+
 
 #define ZERO RCONST(0.0)
 #define ONE  RCONST(1.0)
 #define TWO  RCONST(2.0)
 
 /* Prototypes of IDABBDPrecSetup and IDABBDPrecSolve */
-
-static int IDABBDPrecSetup(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           realtype c_j, void *prec_data,
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
- 
-static int IDABBDPrecSolve(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           N_Vector rvec, N_Vector zvec,
-                           realtype c_j, realtype delta, void *prec_data,
-                           N_Vector tmp);
+static int IDABBDPrecSetup(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, realtype c_j, void *prec_data);
+static int IDABBDPrecSolve(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, N_Vector rvec, N_Vector zvec,
+                           realtype c_j, realtype delta, void *prec_data);
 
 /* Prototype for IDABBDPrecFree */
-
 static int IDABBDPrecFree(IDAMem ida_mem);
 
 /* Prototype for difference quotient Jacobian calculation routine */
-
 static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
                      N_Vector yy, N_Vector yp, N_Vector gref, 
                      N_Vector ytemp, N_Vector yptemp, N_Vector gtemp);
 
 /* Wrapper functions for adjoint code */
+static int IDAAglocal(sunindextype NlocalB, realtype tt, N_Vector yyB, 
+                      N_Vector ypB, N_Vector gvalB, void *user_dataB);
 
-static int IDAAglocal(long int NlocalB, realtype tt,
-                      N_Vector yyB, N_Vector ypB, N_Vector gvalB,
-                      void *user_dataB);
-
-static int IDAAgcomm(long int NlocalB, realtype tt,
-                     N_Vector yyB, N_Vector ypB,
-                     void *user_dataB);
+static int IDAAgcomm(sunindextype NlocalB, realtype tt, N_Vector yyB,
+                     N_Vector ypB, void *user_dataB);
 
 /* Prototype for the pfree routine for backward problems. */
-
 static int IDABBDPrecFreeB(IDABMem IDAB_mem);
 
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define uround   (IDA_mem->ida_uround)
-#define vec_tmpl (IDA_mem->ida_tempv1)
 
-/*
- * -----------------------------------------------------------------
- * User-Callable Functions : malloc, reinit and free
- * -----------------------------------------------------------------
- */
+/*================================================================
+  PART I - forward problems
+  ================================================================*/
 
-int IDABBDPrecInit(void *ida_mem, long int Nlocal, 
-                   long int mudq, long int mldq, 
-                   long int mukeep, long int mlkeep, 
+/*---------------------------------------------------------------
+  User-Callable Functions: initialization, reinit and free
+  ---------------------------------------------------------------*/
+int IDABBDPrecInit(void *ida_mem, sunindextype Nlocal, 
+                   sunindextype mudq, sunindextype mldq, 
+                   sunindextype mukeep, sunindextype mlkeep, 
                    realtype dq_rel_yy, 
                    IDABBDLocalFn Gres, IDABBDCommFn Gcomm)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
-  N_Vector tempv4;
-  long int muk, mlk, storage_mu;
+  sunindextype muk, mlk, storage_mu, lrw1, liw1;
+  long int lrw, liw;
   int flag;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  /* Test if the NVECTOR package is compatible with BLOCK BAND preconditioner */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_BAD_NVECTOR);
+  /* Test compatibility of NVECTOR package with the BBD preconditioner */
+  if(IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_BAD_NVECTOR);
     return(IDASPILS_ILL_INPUT);
   }
 
@@ -135,7 +114,8 @@ int IDABBDPrecInit(void *ida_mem, long int Nlocal,
   pdata = NULL;
   pdata = (IBBDPrecData) malloc(sizeof *pdata);
   if (pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL);
   }
 
@@ -155,91 +135,201 @@ int IDABBDPrecInit(void *ida_mem, long int Nlocal,
 
   /* Allocate memory for preconditioner matrix. */
   pdata->PP = NULL;
-  pdata->PP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+  pdata->PP = SUNBandMatrix(Nlocal, muk, mlk, storage_mu);
   if (pdata->PP == NULL) { 
     free(pdata); pdata = NULL;
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL); 
   }
 
-  /* Allocate memory for lpivots. */
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(Nlocal);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->PP);
+  /* Allocate memory for temporary N_Vectors */
+  pdata->zlocal = NULL;
+  pdata->zlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->zlocal == NULL) {
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE", 
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->rlocal = NULL;
+  pdata->rlocal = N_VNewEmpty_Serial(Nlocal);
+  if (pdata->rlocal == NULL) {
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE", 
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv1 = NULL;
+  pdata->tempv1 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv1 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv2 = NULL;
+  pdata->tempv2 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv2 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->tempv1);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv3 = NULL;
+  pdata->tempv3 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv3 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+  pdata->tempv4 = NULL;
+  pdata->tempv4 = N_VClone(IDA_mem->ida_tempv1); 
+  if (pdata->tempv4 == NULL){
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    SUNMatDestroy(pdata->PP);
     free(pdata); pdata = NULL;
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL);
   }
 
-  /* Allocate tempv4 for use by IBBDDQJac */
-  tempv4 = NULL;
-  tempv4 = N_VClone(vec_tmpl); 
-  if (tempv4 == NULL){
-    DestroyMat(pdata->PP);
-    DestroyArray(pdata->lpivots);
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(pdata->rlocal, pdata->PP);
+  if (pdata->LS == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    N_VDestroy(pdata->tempv4);
+    SUNMatDestroy(pdata->PP);
     free(pdata); pdata = NULL;
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInit", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL);
   }
-  pdata->tempv4 = tempv4;
-  
+
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    N_VDestroy(pdata->tempv4);
+    SUNMatDestroy(pdata->PP);
+    SUNLinSolFree(pdata->LS);
+    free(pdata); pdata = NULL;
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInit", MSGBBD_SUNLS_FAIL);
+    return(IDASPILS_SUNLS_FAIL);
+  }
+ 
   /* Set rel_yy based on input value dq_rel_yy (0 implies default). */
-  pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : SUNRsqrt(uround); 
+  pdata->rel_yy = (dq_rel_yy > ZERO) ?
+    dq_rel_yy : SUNRsqrt(IDA_mem->ida_uround); 
 
   /* Store Nlocal to be used in IDABBDPrecSetup */
   pdata->n_local = Nlocal;
   
   /* Set work space sizes and initialize nge. */
-  pdata->rpwsize = Nlocal*(mlk + storage_mu + 1);
-  pdata->ipwsize = Nlocal;
+  pdata->rpwsize = 0;
+  pdata->ipwsize = 0;
+  if (IDA_mem->ida_tempv1->ops->nvspace) {
+    N_VSpace(IDA_mem->ida_tempv1, &lrw1, &liw1);
+    pdata->rpwsize += 4*lrw1;
+    pdata->ipwsize += 4*liw1;
+  }
+  if (pdata->rlocal->ops->nvspace) {
+    N_VSpace(pdata->rlocal, &lrw1, &liw1);
+    pdata->rpwsize += 2*lrw1;
+    pdata->ipwsize += 2*liw1;
+  }
+  if (pdata->PP->ops->space) {
+    flag = SUNMatSpace(pdata->PP, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
   pdata->nge = 0;
 
-  /* make sure s_P_data is free from any previous allocations */
-  if (idaspils_mem->s_pfree != NULL) {
-    idaspils_mem->s_pfree(IDA_mem);
-  }
+  /* make sure pdata is free from any previous allocations */
+  if (idaspils_mem->pfree) 
+    idaspils_mem->pfree(IDA_mem);
 
   /* Point to the new pdata field in the SPILS memory */
-  idaspils_mem->s_pdata = pdata;
+  idaspils_mem->pdata = pdata;
 
   /* Attach the pfree function */
-  idaspils_mem->s_pfree = IDABBDPrecFree;
+  idaspils_mem->pfree = IDABBDPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = IDASpilsSetPreconditioner(ida_mem, IDABBDPrecSetup, IDABBDPrecSolve);
+  flag = IDASpilsSetPreconditioner(ida_mem,
+                                   IDABBDPrecSetup,
+                                   IDABBDPrecSolve);
 
   return(flag);
 }
 
-int IDABBDPrecReInit(void *ida_mem,
-		     long int mudq, long int mldq, 
-		     realtype dq_rel_yy)
+
+/*-------------------------------------------------------------*/
+int IDABBDPrecReInit(void *ida_mem, sunindextype mudq,
+                     sunindextype mldq, realtype dq_rel_yy)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
-  long int Nlocal;
+  sunindextype Nlocal;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecReInit", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecReInit", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
   /* Test if the preconditioner data is non-NULL */
-  if (idaspils_mem->s_pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecReInit", MSGBBD_PMEM_NULL);
+  if (idaspils_mem->pdata == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecReInit", MSGBBD_PMEM_NULL);
     return(IDASPILS_PMEM_NULL);
   } 
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
 
   /* Load half-bandwidths. */
   Nlocal = pdata->n_local;
@@ -247,7 +337,8 @@ int IDABBDPrecReInit(void *ida_mem,
   pdata->mldq = SUNMIN(Nlocal-1, SUNMAX(0, mldq));
 
   /* Set rel_yy based on input value dq_rel_yy (0 implies default). */
-  pdata->rel_yy = (dq_rel_yy > ZERO) ? dq_rel_yy : SUNRsqrt(uround); 
+  pdata->rel_yy = (dq_rel_yy > ZERO) ?
+    dq_rel_yy : SUNRsqrt(IDA_mem->ida_uround); 
 
   /* Re-initialize nge */
   pdata->nge = 0;
@@ -255,29 +346,36 @@ int IDABBDPrecReInit(void *ida_mem,
   return(IDASPILS_SUCCESS);
 }
 
-int IDABBDPrecGetWorkSpace(void *ida_mem, long int *lenrwBBDP, long int *leniwBBDP)
+
+/*-------------------------------------------------------------*/
+int IDABBDPrecGetWorkSpace(void *ida_mem,
+                           long int *lenrwBBDP,
+                           long int *leniwBBDP)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  if (idaspils_mem->s_pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
+  if (idaspils_mem->pdata == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
     return(IDASPILS_PMEM_NULL);
   } 
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
 
   *lenrwBBDP = pdata->rpwsize;
   *leniwBBDP = pdata->ipwsize;
@@ -285,29 +383,35 @@ int IDABBDPrecGetWorkSpace(void *ida_mem, long int *lenrwBBDP, long int *leniwBB
   return(IDASPILS_SUCCESS);
 }
 
-int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP)
+
+/*-------------------------------------------------------------*/
+int IDABBDPrecGetNumGfnEvals(void *ida_mem,
+                             long int *ngevalsBBDP)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   IBBDPrecData pdata;
 
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  if (idaspils_mem->s_pdata == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDABBDPRE", "IDABBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
+  if (idaspils_mem->pdata == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_PMEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
     return(IDASPILS_PMEM_NULL);
   } 
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
 
   *ngevalsBBDP = pdata->nge;
 
@@ -315,139 +419,118 @@ int IDABBDPrecGetNumGfnEvals(void *ida_mem, long int *ngevalsBBDP)
 }
 
 
-/* Readability Replacements */
 
-#define Nlocal  (pdata->n_local)
-#define mudq    (pdata->mudq)
-#define mldq    (pdata->mldq)
-#define mukeep  (pdata->mukeep)
-#define mlkeep  (pdata->mlkeep)
-#define glocal  (pdata->glocal)
-#define gcomm   (pdata->gcomm)
-#define lpivots (pdata->lpivots)
-#define PP      (pdata->PP)
-#define tempv4  (pdata->tempv4)
-#define nge     (pdata->nge)
-#define rel_yy  (pdata->rel_yy)
 
-/*
- * -----------------------------------------------------------------
- * Function : IDABBDPrecSetup                                     
- * -----------------------------------------------------------------
- * IDABBDPrecSetup generates a band-block-diagonal preconditioner
- * matrix, where the local block (on this processor) is a band
- * matrix. Each local block is computed by a difference quotient
- * scheme via calls to the user-supplied routines glocal, gcomm.
- * After generating the block in the band matrix PP, this routine
- * does an LU factorization in place in PP.
- *
- * The IDABBDPrecSetup parameters used here are as follows:
- *
- * tt is the current value of the independent variable t.
- *
- * yy is the current value of the dependent variable vector,
- *    namely the predicted value of y(t).
- *
- * yp is the current value of the derivative vector y',
- *    namely the predicted value of y'(t).
- *
- * c_j is the scalar in the system Jacobian, proportional to 1/hh.
- *
- * bbd_data is the pointer to BBD data set by IDABBDInit.
- *
- * tmp1, tmp2, tmp3 are pointers to vectors of type
- *                  N_Vector, used for temporary storage or
- *                  work space.
- *
- * The arguments Neq, rr, res, uround, and nrePtr are not used.
- *
- * Return value:
- * The value returned by this IDABBDPrecSetup function is a int
- * flag indicating whether it was successful. This value is
- *    0    if successful,
- *  > 0    for a recoverable error (step will be retried), or
- *  < 0    for a nonrecoverable error (step fails).
- * -----------------------------------------------------------------
- */
+/*---------------------------------------------------------------
+  IDABBDPrecSetup:
 
-static int IDABBDPrecSetup(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           realtype c_j, void *bbd_data,
-                           N_Vector tempv1, N_Vector tempv2, N_Vector tempv3)
+  IDABBDPrecSetup generates a band-block-diagonal preconditioner
+  matrix, where the local block (on this processor) is a band
+  matrix. Each local block is computed by a difference quotient
+  scheme via calls to the user-supplied routines glocal, gcomm.
+  After generating the block in the band matrix PP, this routine
+  does an LU factorization in place in PP.
+ 
+  The IDABBDPrecSetup parameters used here are as follows:
+ 
+  tt is the current value of the independent variable t.
+ 
+  yy is the current value of the dependent variable vector,
+     namely the predicted value of y(t).
+ 
+  yp is the current value of the derivative vector y',
+     namely the predicted value of y'(t).
+ 
+  c_j is the scalar in the system Jacobian, proportional to 1/hh.
+ 
+  bbd_data is the pointer to BBD memory set by IDABBDInit
+ 
+  The argument rr is not used.
+ 
+  Return value:
+  The value returned by this IDABBDPrecSetup function is a int
+  flag indicating whether it was successful. This value is
+     0    if successful,
+   > 0    for a recoverable error (step will be retried), or
+   < 0    for a nonrecoverable error (step fails).
+ ----------------------------------------------------------------*/
+static int IDABBDPrecSetup(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, realtype c_j, void *bbd_data)
 {
-  int retval;
-  long int ier;
+  sunindextype ier;
   IBBDPrecData pdata;
   IDAMem IDA_mem;
+  int retval;
 
   pdata =(IBBDPrecData) bbd_data;
 
   IDA_mem = (IDAMem) pdata->ida_mem;
 
   /* Call IBBDDQJac for a new Jacobian calculation and store in PP. */
-  SetToZero(PP);
-  retval = IBBDDQJac(pdata, tt, c_j, yy, yp,
-                     tempv1, tempv2, tempv3, tempv4);
+  retval = SUNMatZero(pdata->PP);
+  retval = IBBDDQJac(pdata, tt, c_j, yy, yp, pdata->tempv1,
+                     pdata->tempv2, pdata->tempv3, pdata->tempv4);
   if (retval < 0) {
-    IDAProcessError(IDA_mem, -1, "IDABBDPRE", "IDABBDPrecSetup", MSGBBD_FUNC_FAILED);
+    IDAProcessError(IDA_mem, -1, "IDASBBDPRE", "IDABBDPrecSetup",
+                    MSGBBD_FUNC_FAILED);
     return(-1);
   }
   if (retval > 0) {
     return(+1);
   } 
  
-  /* Do LU factorization of preconditioner block in place (in PP). */
-  ier = BandGBTRF(PP, lpivots);
-
-  /* Return 0 if the LU was complete, or +1 otherwise. */
-  if (ier > 0) return(+1);
-  return(0);
+  /* Do LU factorization of matrix and return error flag */
+  ier = SUNLinSolSetup_Band(pdata->LS, pdata->PP);
+  return(ier);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function: IDABBDPrecSolve
- * -----------------------------------------------------------------
- * The function IDABBDPrecSolve computes a solution to the linear
- * system P z = r, where P is the left preconditioner defined by
- * the routine IDABBDPrecSetup.
- *
- * The IDABBDPrecSolve parameters used here are as follows:
- *
- * rvec is the input right-hand side vector r.
- *
- * zvec is the computed solution vector z.
- *
- * bbd_data is the pointer to BBD data set by IDABBDInit.
- *
- * The arguments tt, yy, yp, rr, c_j, delta, and tmp are NOT used.
- *
- * IDABBDPrecSolve always returns 0, indicating success.
- * -----------------------------------------------------------------
- */
 
-static int IDABBDPrecSolve(realtype tt,
-                           N_Vector yy, N_Vector yp, N_Vector rr,
-                           N_Vector rvec, N_Vector zvec,
-                           realtype c_j, realtype delta, void *bbd_data,
-                           N_Vector tmp)
+/*---------------------------------------------------------------
+  IDABBDPrecSolve
+
+  The function IDABBDPrecSolve computes a solution to the linear
+  system P z = r, where P is the left preconditioner defined by
+  the routine IDABBDPrecSetup.
+ 
+  The IDABBDPrecSolve parameters used here are as follows:
+ 
+  rvec is the input right-hand side vector r.
+ 
+  zvec is the computed solution vector z.
+ 
+  bbd_data is the pointer to BBD data set by IDABBDInit.
+ 
+  The arguments tt, yy, yp, rr, c_j and delta are NOT used.
+ 
+  IDABBDPrecSolve returns the value returned from the linear 
+  solver object.
+  ---------------------------------------------------------------*/
+static int IDABBDPrecSolve(realtype tt, N_Vector yy, N_Vector yp,
+                           N_Vector rr, N_Vector rvec, N_Vector zvec,
+                           realtype c_j, realtype delta, void *bbd_data)
 {
   IBBDPrecData pdata;
-  realtype *zd;
+  int retval;
 
   pdata = (IBBDPrecData) bbd_data;
 
-  /* Copy rvec to zvec, do the backsolve, and return. */
-  N_VScale(ONE, rvec, zvec);
-
-  zd = N_VGetArrayPointer(zvec);
+  /* Attach local data arrays for rvec and zvec to rlocal and zlocal */
+  N_VSetArrayPointer(N_VGetArrayPointer(rvec), pdata->rlocal);
+  N_VSetArrayPointer(N_VGetArrayPointer(zvec), pdata->zlocal);
+  
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->PP, pdata->zlocal, 
+                          pdata->rlocal, ZERO);
 
-  BandGBTRS(PP, lpivots, zd);
+  /* Detach local data arrays from rlocal and zlocal */
+  N_VSetArrayPointer(NULL, pdata->rlocal);
+  N_VSetArrayPointer(NULL, pdata->zlocal);
 
-  return(0);
+  return(retval);
 }
 
 
+/*-------------------------------------------------------------*/
 static int IDABBDPrecFree(IDAMem IDA_mem)
 {
   IDASpilsMem idaspils_mem;
@@ -456,12 +539,17 @@ static int IDABBDPrecFree(IDAMem IDA_mem)
   if (IDA_mem->ida_lmem == NULL) return(0);
   idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
   
-  if (idaspils_mem->s_pdata == NULL) return(0);
-  pdata = (IBBDPrecData) idaspils_mem->s_pdata;
-
-  DestroyMat(PP);
-  DestroyArray(lpivots);
-  N_VDestroy(tempv4);
+  if (idaspils_mem->pdata == NULL) return(0);
+  pdata = (IBBDPrecData) idaspils_mem->pdata;
+
+  SUNLinSolFree(pdata->LS);
+  N_VDestroy(pdata->rlocal);
+  N_VDestroy(pdata->zlocal);
+  N_VDestroy(pdata->tempv1);
+  N_VDestroy(pdata->tempv2);
+  N_VDestroy(pdata->tempv3);
+  N_VDestroy(pdata->tempv4);
+  SUNMatDestroy(pdata->PP);
 
   free(pdata);
   pdata = NULL;
@@ -470,32 +558,24 @@ static int IDABBDPrecFree(IDAMem IDA_mem)
 }
 
 
-#define ewt         (IDA_mem->ida_ewt)
-#define user_data   (IDA_mem->ida_user_data)
-#define hh          (IDA_mem->ida_hh)
-#define constraints (IDA_mem->ida_constraints)
-
-/*
- * -----------------------------------------------------------------
- * IBBDDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation
- * to the local block of the Jacobian of G(t,y,y'). It assumes that
- * a band matrix of type BandMat is stored column-wise, and that
- * elements within each column are contiguous.
- *
- * All matrix elements are generated as difference quotients, by way
- * of calls to the user routine glocal. By virtue of the band
- * structure, the number of these calls is bandwidth + 1, where
- * bandwidth = mldq + mudq + 1. But the band matrix kept has
- * bandwidth = mlkeep + mukeep + 1. This routine also assumes that
- * the local elements of a vector are stored contiguously.
- *
- * Return values are: 0 (success), > 0 (recoverable error),
- * or < 0 (nonrecoverable error).
- * -----------------------------------------------------------------
- */
+/*---------------------------------------------------------------
+  IBBDDQJac
 
+  This routine generates a banded difference quotient approximation
+  to the local block of the Jacobian of G(t,y,y'). It assumes that
+  a band matrix of type SUNMatrix is stored column-wise, and that
+  elements within each column are contiguous.
+ 
+  All matrix elements are generated as difference quotients, by way
+  of calls to the user routine glocal. By virtue of the band
+  structure, the number of these calls is bandwidth + 1, where
+  bandwidth = mldq + mudq + 1. But the band matrix kept has
+  bandwidth = mlkeep + mukeep + 1. This routine also assumes that
+  the local elements of a vector are stored contiguously.
+ 
+  Return values are: 0 (success), > 0 (recoverable error),
+  or < 0 (nonrecoverable error).
+  ----------------------------------------------------------------*/
 static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
                      N_Vector yy, N_Vector yp, N_Vector gref, 
                      N_Vector ytemp, N_Vector yptemp, N_Vector gtemp)
@@ -503,7 +583,7 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
   IDAMem IDA_mem;
   realtype inc, inc_inv;
   int retval;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
   realtype *ydata, *ypdata, *ytempdata, *yptempdata, *grefdata, *gtempdata;
   realtype *cnsdata = NULL, *ewtdata;
   realtype *col_j, conj, yj, ypj, ewtj;
@@ -511,44 +591,39 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
   IDA_mem = (IDAMem) pdata->ida_mem;
 
   /* Initialize ytemp and yptemp. */
-
   N_VScale(ONE, yy, ytemp);
   N_VScale(ONE, yp, yptemp);
 
   /* Obtain pointers as required to the data array of vectors. */
-
   ydata     = N_VGetArrayPointer(yy);
   ypdata    = N_VGetArrayPointer(yp);
   gtempdata = N_VGetArrayPointer(gtemp);
-  ewtdata   = N_VGetArrayPointer(ewt);
-  if (constraints != NULL) 
-    cnsdata = N_VGetArrayPointer(constraints);
+  ewtdata   = N_VGetArrayPointer(IDA_mem->ida_ewt);
+  if (IDA_mem->ida_constraints != NULL) 
+    cnsdata = N_VGetArrayPointer(IDA_mem->ida_constraints);
   ytempdata = N_VGetArrayPointer(ytemp);
   yptempdata= N_VGetArrayPointer(yptemp);
   grefdata = N_VGetArrayPointer(gref);
 
   /* Call gcomm and glocal to get base value of G(t,y,y'). */
-
-  if (gcomm != NULL) {
-    retval = gcomm(Nlocal, tt, yy, yp, user_data);
+  if (pdata->gcomm != NULL) {
+    retval = pdata->gcomm(pdata->n_local, tt, yy, yp, IDA_mem->ida_user_data);
     if (retval != 0) return(retval);
   }
 
-  retval = glocal(Nlocal, tt, yy, yp, gref, user_data); 
-  nge++;
+  retval = pdata->glocal(pdata->n_local, tt, yy, yp, gref, IDA_mem->ida_user_data); 
+  pdata->nge++;
   if (retval != 0) return(retval);
 
-
   /* Set bandwidth and number of column groups for band differencing. */
-
-  width = mldq + mudq + 1;
-  ngroups = SUNMIN(width, Nlocal);
+  width = pdata->mldq + pdata->mudq + 1;
+  ngroups = SUNMIN(width, pdata->n_local);
 
   /* Loop over groups. */
   for(group = 1; group <= ngroups; group++) {
     
     /* Loop over the components in this group. */
-    for(j = group-1; j < Nlocal; j += width) {
+    for(j = group-1; j < pdata->n_local; j += width) {
       yj = ydata[j];
       ypj = ypdata[j];
       ewtj = ewtdata[j];
@@ -556,12 +631,13 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
       /* Set increment inc to yj based on rel_yy*abs(yj), with
          adjustments using ypj and ewtj if this is small, and a further
          adjustment to give it the same sign as hh*ypj. */
-      inc = rel_yy*SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(hh*ypj), ONE/ewtj));
-      if (hh*ypj < ZERO) inc = -inc;
+      inc = pdata->rel_yy *
+        SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(IDA_mem->ida_hh*ypj), ONE/ewtj));
+      if (IDA_mem->ida_hh*ypj < ZERO)  inc = -inc;
       inc = (yj + inc) - yj;
       
       /* Adjust sign(inc) again if yj has an inequality constraint. */
-      if (constraints != NULL) {
+      if (IDA_mem->ida_constraints != NULL) {
         conj = cnsdata[j];
         if (SUNRabs(conj) == ONE)      {if ((yj+inc)*conj <  ZERO) inc = -inc;}
         else if (SUNRabs(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
@@ -574,22 +650,23 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
     }
 
     /* Evaluate G with incremented y and yp arguments. */
-
-    retval = glocal(Nlocal, tt, ytemp, yptemp, gtemp, user_data); 
-    nge++;
+    retval = pdata->glocal(pdata->n_local, tt, ytemp, yptemp,
+                           gtemp, IDA_mem->ida_user_data); 
+    pdata->nge++;
     if (retval != 0) return(retval);
 
     /* Loop over components of the group again; restore ytemp and yptemp. */
-    for(j = group-1; j < Nlocal; j += width) {
+    for(j = group-1; j < pdata->n_local; j += width) {
       yj  = ytempdata[j]  = ydata[j];
       ypj = yptempdata[j] = ypdata[j];
       ewtj = ewtdata[j];
 
       /* Set increment inc as before .*/
-      inc = rel_yy*SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(hh*ypj), ONE/ewtj));
-      if (hh*ypj < ZERO) inc = -inc;
+      inc = pdata->rel_yy *
+        SUNMAX(SUNRabs(yj), SUNMAX( SUNRabs(IDA_mem->ida_hh*ypj), ONE/ewtj));
+      if (IDA_mem->ida_hh*ypj < ZERO)  inc = -inc;
       inc = (yj + inc) - yj;
-      if (constraints != NULL) {
+      if (IDA_mem->ida_constraints != NULL) {
         conj = cnsdata[j];
         if (SUNRabs(conj) == ONE)      {if ((yj+inc)*conj <  ZERO) inc = -inc;}
         else if (SUNRabs(conj) == TWO) {if ((yj+inc)*conj <= ZERO) inc = -inc;}
@@ -597,11 +674,12 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
 
       /* Form difference quotients and load into PP. */
       inc_inv = ONE/inc;
-      col_j = BAND_COL(PP,j);
-      i1 = SUNMAX(0, j-mukeep);
-      i2 = SUNMIN(j+mlkeep, Nlocal-1);
-      for(i = i1; i <= i2; i++) BAND_COL_ELEM(col_j,i,j) =
-                                  inc_inv * (gtempdata[i] - grefdata[i]);
+      col_j = SUNBandMatrix_Column(pdata->PP,j);
+      i1 = SUNMAX(0, j-pdata->mukeep);
+      i2 = SUNMIN(j + pdata->mlkeep, pdata->n_local-1);
+      for(i = i1; i <= i2; i++)
+        SM_COLUMN_ELEMENT_B(col_j,i,j) =
+          inc_inv * (gtempdata[i] - grefdata[i]);
     }
   }
   
@@ -609,31 +687,18 @@ static int IBBDDQJac(IBBDPrecData pdata, realtype tt, realtype cj,
 }
 
 
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/* Readability replacements */
-
-#define yyTmp       (IDAADJ_mem->ia_yyTmp)
-#define ypTmp       (IDAADJ_mem->ia_ypTmp)
-#define noInterp    (IDAADJ_mem->ia_noInterp)
+/*================================================================
+  PART II - backward problems
+  ================================================================*/
 
-/* 
- * ----------------------------------------------------------------
- * User-callable functions
- * ----------------------------------------------------------------
- */
-
-int IDABBDPrecInitB(void *ida_mem, int which, long int NlocalB,
-                     long int mudqB, long int mldqB,
-                     long int mukeepB, long int mlkeepB,
-                     realtype dq_rel_yyB,
-                     IDABBDLocalFnB glocalB, IDABBDCommFnB gcommB)
+/*---------------------------------------------------------------
+  User-Callable Functions: initialization, reinit and free
+  ---------------------------------------------------------------*/
+int IDABBDPrecInitB(void *ida_mem, int which, sunindextype NlocalB,
+                    sunindextype mudqB, sunindextype mldqB,
+                    sunindextype mukeepB, sunindextype mlkeepB,
+                    realtype dq_rel_yyB, IDABBDLocalFnB glocalB, 
+                    IDABBDCommFnB gcommB)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -644,21 +709,24 @@ int IDABBDPrecInitB(void *ida_mem, int which, long int NlocalB,
   
   /* Check if ida_mem is allright. */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecInitB", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecInitB", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDABBDPRE", "IDABBDPrecInitB",  MSGS_NO_ADJ);
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASBBDPRE",
+                    "IDABBDPrecInitB", MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDABBDPRE", "IDABBDPrecInitB", MSGS_BAD_WHICH);
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASBBDPRE",
+                    "IDABBDPrecInitB", MSGS_BAD_WHICH);
     return(IDASPILS_ILL_INPUT);
   }
 
@@ -673,36 +741,35 @@ int IDABBDPrecInitB(void *ida_mem, int which, long int NlocalB,
   ida_memB = (void *) IDAB_mem->IDA_mem;
 
   /* Initialize the BBD preconditioner for this backward problem. */
-  flag = IDABBDPrecInit(ida_memB, NlocalB, 
-                        mudqB, mldqB,
-                        mukeepB, mlkeepB, 
-                        dq_rel_yyB, 
-                        IDAAglocal, IDAAgcomm);
+  flag = IDABBDPrecInit(ida_memB, NlocalB, mudqB, mldqB, mukeepB,
+                        mlkeepB, dq_rel_yyB, IDAAglocal, IDAAgcomm);
   if (flag != IDA_SUCCESS) return(flag);
 
   /* Allocate memory for IDABBDPrecDataB to store the user-provided
-   * functions which will be called from the wrappers */
+     functions which will be called from the wrappers */
   idabbdB_mem = NULL;
   idabbdB_mem = (IDABBDPrecDataB) malloc(sizeof(* idabbdB_mem));
   if (idabbdB_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDABBDPRE", "IDABBDPrecInitB", MSGBBD_MEM_FAIL);
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASBBDPRE",
+                    "IDABBDPrecInitB", MSGBBD_MEM_FAIL);
     return(IDASPILS_MEM_FAIL);
   }
 
+  /* set pointers to user-provided functions */
   idabbdB_mem->glocalB = glocalB;
   idabbdB_mem->gcommB  = gcommB;
 
-
-  /* Attach pmem */
+  /* Attach pmem and pfree */
   IDAB_mem->ida_pmem  = idabbdB_mem;
-  /* Attach deallocation routine pfree. */
   IDAB_mem->ida_pfree = IDABBDPrecFreeB;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDABBDPrecReInitB(void *ida_mem, int which,
-                      long int mudqB, long int mldqB, realtype dq_rel_yyB)
+
+/*-------------------------------------------------------------*/
+int IDABBDPrecReInitB(void *ida_mem, int which, sunindextype mudqB,
+                      sunindextype mldqB, realtype dq_rel_yyB)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -712,21 +779,24 @@ int IDABBDPrecReInitB(void *ida_mem, int which,
   
   /* Check if ida_mem is allright. */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDABBDPRE", "IDABBDPrecReInitB", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASBBDPRE",
+                    "IDABBDPrecReInitB", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDABBDPRE", "IDABBDPrecReInitB",  MSGS_NO_ADJ);
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASBBDPRE",
+                    "IDABBDPrecReInitB",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDABBDPRE", "IDABBDPrecReInitB", MSGS_BAD_WHICH);
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASBBDPRE",
+                    "IDABBDPrecReInitB", MSGS_BAD_WHICH);
     return(IDASPILS_ILL_INPUT);
   }
 
@@ -740,10 +810,13 @@ int IDABBDPrecReInitB(void *ida_mem, int which,
   /* ida_mem corresponding to 'which' backward problem. */
   ida_memB = (void *) IDAB_mem->IDA_mem;
 
+  /* ReInitialize the BBD preconditioner for this backward problem. */
   flag = IDABBDPrecReInit(ida_memB, mudqB, mldqB, dq_rel_yyB);
   return(flag);
 }
 
+
+/*-------------------------------------------------------------*/
 static int IDABBDPrecFreeB(IDABMem IDAB_mem)
 {
   free(IDAB_mem->ida_pmem);
@@ -751,22 +824,19 @@ static int IDABBDPrecFreeB(IDABMem IDAB_mem)
   return(0);
 }
 
-/* 
- * ----------------------------------------------------------------
- * Wrapper functions
- * ----------------------------------------------------------------
- */
 
-/*
- * IDAAglocal
- *
- * This routine interfaces to the IDALocalFnB routine 
- * provided by the user.
- */
+/*----------------------------------------------------------------
+  Wrapper functions
+  ----------------------------------------------------------------*/
 
-static int IDAAglocal(long int NlocalB, realtype tt,
-                      N_Vector yyB, N_Vector ypB, N_Vector gvalB,
-                      void *ida_mem)
+/*----------------------------------------------------------------
+  IDAAglocal
+ 
+  This routine interfaces to the IDALocalFnB routine 
+  provided by the user.
+  ----------------------------------------------------------------*/
+static int IDAAglocal(sunindextype NlocalB, realtype tt, N_Vector yyB,
+                      N_Vector ypB, N_Vector gvalB, void *ida_mem)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -784,30 +854,30 @@ static int IDAAglocal(long int NlocalB, realtype tt,
   idabbdB_mem = (IDABBDPrecDataB) IDAB_mem->ida_pmem;
 
   /* Get forward solution from interpolation. */
-  if (noInterp == FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+  if (IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDA_mem, -1, "IDABBDPRE", "IDAAglocal", MSGBBD_BAD_T);
+      IDAProcessError(IDA_mem, -1, "IDASBBDPRE", "IDAAglocal",
+                      MSGBBD_BAD_T);
       return(-1);
     } 
   }
   /* Call user's adjoint LocalFnB function. */
-  return idabbdB_mem->glocalB(NlocalB, tt, 
-                              yyTmp, ypTmp, 
-                              yyB, ypB, gvalB, 
-                              IDAB_mem->ida_user_data);
-
+  return idabbdB_mem->glocalB(NlocalB, tt, IDAADJ_mem->ia_yyTmp,
+                              IDAADJ_mem->ia_ypTmp, yyB, ypB,
+                              gvalB, IDAB_mem->ida_user_data);
 }
 
-/*
- * IDAAgcomm
- *
- * This routine interfaces to the IDACommFnB routine 
- * provided by the user.
- */
-static int IDAAgcomm(long int NlocalB, realtype tt,
-                     N_Vector yyB, N_Vector ypB,
-                     void *ida_mem)
+
+/*----------------------------------------------------------------
+  IDAAgcomm
+ 
+  This routine interfaces to the IDACommFnB routine 
+  provided by the user.
+  ----------------------------------------------------------------*/
+static int IDAAgcomm(sunindextype NlocalB, realtype tt,
+                     N_Vector yyB, N_Vector ypB, void *ida_mem)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -826,16 +896,18 @@ static int IDAAgcomm(long int NlocalB, realtype tt,
   if (idabbdB_mem->gcommB == NULL) return(0);
 
   /* Get forward solution from interpolation. */
-  if (noInterp == FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+  if (IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDA_mem, -1, "IDABBDPRE", "IDAAgcomm", MSGBBD_BAD_T);
+      IDAProcessError(IDA_mem, -1, "IDASBBDPRE", "IDAAgcomm",
+                      MSGBBD_BAD_T);
       return(-1);
     } 
   }
 
   /* Call user's adjoint CommFnB routine */
-  return idabbdB_mem->gcommB(NlocalB, tt, yyTmp, 
-                             ypTmp, yyB, ypB, 
+  return idabbdB_mem->gcommB(NlocalB, tt, IDAADJ_mem->ia_yyTmp, 
+                             IDAADJ_mem->ia_ypTmp, yyB, ypB, 
                              IDAB_mem->ida_user_data);
 }
diff --git a/src/idas/idas_bbdpre_impl.h b/src/idas/idas_bbdpre_impl.h
index 9c05f4c..b5801de 100644
--- a/src/idas/idas_bbdpre_impl.h
+++ b/src/idas/idas_bbdpre_impl.h
@@ -1,32 +1,33 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*-----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
  * This is the header file (private version) for the IDABBDPRE
  * module, for a band-block-diagonal preconditioner, i.e. a
- * block-diagonal matrix with banded blocks, for use with IDAS
+ * block-diagonal matrix with banded blocks, for use with IDA
  * and an IDASPILS linear solver.
- * -----------------------------------------------------------------
- */
+ *-----------------------------------------------------------------*/
 
 #ifndef _IDASBBDPRE_IMPL_H
 #define _IDASBBDPRE_IMPL_H
 
 #include <idas/idas_bbdpre.h>
-#include <sundials/sundials_band.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -42,33 +43,29 @@ typedef struct IBBDPrecDataRec {
 
   /* passed by user to IDABBDPrecAlloc and used by
      IDABBDPrecSetup/IDABBDPrecSolve functions */
-
-  long int mudq, mldq, mukeep, mlkeep;
+  sunindextype mudq, mldq, mukeep, mlkeep;
   realtype rel_yy;
   IDABBDLocalFn glocal;
   IDABBDCommFn gcomm;
 
-  /* allocated for use by IDABBDPrecSetup */
-
+  /* set by IDABBDPrecSetup and used by IDABBDPrecSetup and 
+     IDABBDPrecSolve functions */
+  sunindextype n_local;
+  SUNMatrix PP;
+  SUNLinearSolver LS;
+  N_Vector zlocal;
+  N_Vector rlocal;
+  N_Vector tempv1;
+  N_Vector tempv2;
+  N_Vector tempv3;
   N_Vector tempv4;
 
-  /* set by IDABBDPrecon and used by IDABBDPrecSolve */
-
-  DlsMat PP;
-  long int *lpivots;
-
-  /* set by IDABBDPrecAlloc and used by IDABBDPrecSetup */
-
-  long int n_local;
-
   /* available for optional output */
-
   long int rpwsize;
   long int ipwsize;
   long int nge;
 
   /* pointer to ida_mem */
-
   void *ida_mem;
 
 } *IBBDPrecData;
@@ -79,15 +76,12 @@ typedef struct IBBDPrecDataRec {
  * -----------------------------------------------------------------
  */
 
-typedef struct IDABBDPrecDataRecB{
+typedef struct IDABBDPrecDataRecB {
 
   /* BBD user functions (glocB and cfnB) for backward run */
   IDABBDLocalFnB glocalB;
   IDABBDCommFnB  gcommB;
     
-  /* BBD prec data */
-  /* //!void *bbd_dataB; */
-
 } *IDABBDPrecDataB;
 
 
@@ -101,6 +95,8 @@ typedef struct IDABBDPrecDataRecB{
 #define MSGBBD_LMEM_NULL   "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBBD_MEM_FAIL    "A memory request failed."
 #define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented."
+#define MSGBBD_SUNMAT_FAIL "An error arose from a SUNBandMatrix routine."
+#define MSGBBD_SUNLS_FAIL  "An error arose from a SUNBandLinearSolver routine."
 #define MSGBBD_PMEM_NULL   "BBD peconditioner memory is NULL. IDABBDPrecInit must be called."
 #define MSGBBD_FUNC_FAILED "The Glocal or Gcomm routine failed in an unrecoverable manner."
 
diff --git a/src/idas/idas_dense.c b/src/idas/idas_dense.c
deleted file mode 100644
index ed02e2b..0000000
--- a/src/idas/idas_dense.c
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4909 $
- * $Date: 2016-09-14 16:51:27 -0700 (Wed, 14 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDASDENSE linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <idas/idas_dense.h>
-#include "idas_direct_impl.h"
-#include "idas_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* IDASDENSE linit, lsetup, lsolve, and lfree routines */
- 
-static int IDADenseInit(IDAMem IDA_mem);
-
-static int IDADenseSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                         N_Vector rrp, N_Vector tmp1,
-                         N_Vector tmp2, N_Vector tmp3);
-
-static int IDADenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                         N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDADenseFree(IDAMem IDA_mem);
-
-/* IDADENSE lfreeB function */
-
-static int IDADenseFreeB(IDABMem IDAB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define res          (IDA_mem->ida_res)
-#define tn           (IDA_mem->ida_tn)
-#define hh           (IDA_mem->ida_hh)
-#define cj           (IDA_mem->ida_cj)
-#define cjratio      (IDA_mem->ida_cjratio)
-#define ewt          (IDA_mem->ida_ewt)
-#define constraints  (IDA_mem->ida_constraints)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define mtype        (idadls_mem->d_type)
-#define neq          (idadls_mem->d_n)
-#define jacDQ        (idadls_mem->d_jacDQ)
-#define djac         (idadls_mem->d_djac)
-#define JJ           (idadls_mem->d_J)
-#define lpivots      (idadls_mem->d_lpivots)
-#define nje          (idadls_mem->d_nje)
-#define nreDQ        (idadls_mem->d_nreDQ)
-#define jacdata      (idadls_mem->d_J_data)
-#define last_flag    (idadls_mem->d_last_flag)
-                  
-/*
- * -----------------------------------------------------------------
- * IDADense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDADENSE linear solver module.  
- * IDADense first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDADenseInit, IDADenseSetup,
- * IDADenseSolve, NULL, and IDADenseFree, respectively.
- * It allocates memory for a structure of type IDADlsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jdata field
- * in the IDADlsMemRec structure to be the input parameter jdata,
- * and sets the d_jac field to be:
- *   (1) the input parameter djac, if djac != NULL, or                
- *   (2) IDADenseDQJac, if djac == NULL.                             
- * Finally, it allocates memory for JJ and lpivots.
- * The return value is IDADLS_SUCCESS = 0, IDADLS_LMEM_FAIL = -1,
- * or IDADLS_ILL_INPUT = -2.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDADense will first 
- *       test for a compatible N_Vector internal
- *       representation by checking that the functions N_VGetArrayPointer
- *       and N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-int IDADense(void *ida_mem, long int Neq)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDENSE", "IDADense", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if(vec_tmpl->ops->nvgetarraypointer == NULL ||
-     vec_tmpl->ops->nvsetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDENSE", "IDADense", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(IDA_mem);
-
-  /* Set five main function fields in IDA_mem. */
-  linit  = IDADenseInit;
-  lsetup = IDADenseSetup;
-  lsolve = IDADenseSolve;
-  lperf  = NULL;
-  lfree  = IDADenseFree;
-
-  /* Get memory for IDADlsMemRec. */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASDENSE", "IDADense", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ   = TRUE;
-  djac    = NULL;
-  jacdata = NULL;
-
-  last_flag = IDADLS_SUCCESS;
-
-  idaDlsInitializeCounters(idadls_mem); 
-
-  setupNonNull = TRUE;
-
-  /* Store problem size */
-  neq = Neq;
-
-  /* Allocate memory for JJ and pivot array. */
-  JJ = NULL;
-  JJ = NewDenseMat(Neq, Neq);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASDENSE", "IDADense", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  lpivots = NULL;
-  lpivots = NewLintArray(Neq);
-  if (lpivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASDENSE", "IDADense", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDADENSE interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDADENSE
-  linear solver module.  It returns 0.
-*/
-
-static int IDADenseInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-  
-  idadls_mem = (IDADlsMem) lmem;
-
-  idaDlsInitializeCounters(idadls_mem); 
-
-  if (jacDQ) {
-    djac = idaDlsDenseDQJac;
-    jacdata = IDA_mem;
-  } else {
-    jacdata = IDA_mem->ida_user_data;
-  }
-  
-  last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the IDADENSE linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the dense LU factorization routine.
-  The return value is either
-     IDADLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDADenseSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-                         N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-                         N_Vector tmp3)
-{
-  int retval;
-  long int retfac;
-  IDADlsMem idadls_mem;
-  
-  idadls_mem = (IDADlsMem) lmem;
-
-  /* Increment nje counter. */
-  nje++;
-
-  /* Zero out JJ; call Jacobian routine jac; return if it failed. */
-  SetToZero(JJ);
-  retval = djac(neq, tn, cj, yyp, ypp, rrp, JJ, jacdata, 
-                tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDASDENSE", "IDADenseSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  /* Do LU factorization of JJ; return success or fail flag. */
-  retfac = DenseGETRF(JJ, lpivots);
-
-  if (retfac != 0) {
-    last_flag = retfac;
-    return(+1);
-  }
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the IDADENSE linear
-  solver module.  It calls the dense backsolve routine, scales the
-  solution vector according to cjratio, then returns IDADLS_SUCCESS = 0.
-*/
-
-static int IDADenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                         N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd;
-  
-  idadls_mem = (IDADlsMem) lmem;
-  
-  bd = N_VGetArrayPointer(b);
-
-  DenseGETRS(JJ, lpivots, bd);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-
-  last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine frees memory specific to the IDADENSE linear solver.
-*/
-
-static int IDADenseFree(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(lpivots);
-  free(lmem); lmem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * IDADenseB is a wrapper around IDADense.
- */
-
-int IDADenseB(void *ida_mem, int which, long int NeqB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDADlsMemB idadlsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDENSE", "IDADenseB", MSGD_CAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDENSE", "IDADenseB",  MSGD_NO_ADJ);
-    return(IDADLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDENSE", "IDADenseB", MSGD_BAD_WHICH);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Alloc memory for IDADlsMemRecB */
-  idadlsB_mem = (IDADlsMemB) malloc(sizeof(struct IDADlsMemRecB));
-  if (idadlsB_mem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_MEM_FAIL, "IDASDENSE", "IDADenseB", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  
-  }
-
-  /* Set matrix type and initialize Jac function. */
-  idadlsB_mem->d_typeB = SUNDIALS_DENSE;
-  idadlsB_mem->d_bjacB = NULL;
-
-  /* Attach lmemB data and lfreeB function. */
-  IDAB_mem->ida_lmem  = idadlsB_mem;
-  IDAB_mem->ida_lfree = IDADenseFreeB;
-
-  /* Call IDADense to attach the IDADENSE linear solver. */
-  ida_memB = (void *)IDAB_mem->IDA_mem;
-  flag = IDADense(ida_memB, NeqB);
-
-  if (flag != IDADLS_SUCCESS) {
-    free(idadlsB_mem);
-    idadlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * IDADenseFreeB frees the linear solver's memory for that backward problem passed 
- * as argument. 
- */
-
-static int IDADenseFreeB(IDABMem IDAB_mem)
-{
-  IDADlsMemB idadlsB_mem;
-
-  idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
-
-  free(idadlsB_mem);
-
-  return(0);
-}
-
diff --git a/src/idas/idas_direct.c b/src/idas/idas_direct.c
index 033d6b3..b50a02f 100644
--- a/src/idas/idas_direct.c
+++ b/src/idas/idas_direct.c
@@ -1,29 +1,24 @@
-/*
+/* -----------------------------------------------------------------
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
+ * LLNS/SMU Copyright End
  * -----------------------------------------------------------------
- * This is the implementation file for an IDASDLS linear solver.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
+ * This is the implementation file for an IDASDLS linear solver 
+ * interface
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,243 +26,274 @@
 #include "idas_impl.h"
 #include "idas_direct_impl.h"
 #include <sundials/sundials_math.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
 
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
+/*=================================================================
+  FUNCTION SPECIFIC CONSTANTS
+  =================================================================*/
 
 #define ZERO         RCONST(0.0)
 #define ONE          RCONST(1.0)
 #define TWO          RCONST(2.0)
 
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-static int idaDlsDenseJacBWrapper(long int NeqB, realtype tt, realtype c_jB,
-                                  N_Vector yyB, N_Vector ypB, N_Vector rBr, 
-                                  DlsMat JacB, void *ida_mem,
-                                  N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-static int idaDlsDenseJacBSWrapper(long int NeqB, realtype tt, realtype c_jB,
-                                   N_Vector yyB, N_Vector ypB, N_Vector rBr, 
-                                   DlsMat JacB, void *ida_mem,
-                                   N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-static int idaDlsBandJacBWrapper(long int NeqB, long int mupperB, long int mlowerB,
-                                 realtype tt, realtype c_jB, 
-                                 N_Vector yyB, N_Vector ypB, N_Vector rrB,
-                                 DlsMat JacB, void *ida_mem,
-                                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-static int idaDlsBandJacBSWrapper(long int NeqB, long int mupperB, long int mlowerB,
-                                  realtype tt, realtype c_jB, 
-                                  N_Vector yyB, N_Vector ypB, N_Vector rrB,
-                                  DlsMat JacB, void *ida_mem,
-                                  N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define res            (IDA_mem->ida_res)
-#define user_data      (IDA_mem->ida_user_data)
-#define uround         (IDA_mem->ida_uround)
-#define nst            (IDA_mem->ida_nst)
-#define tn             (IDA_mem->ida_tn)
-#define hh             (IDA_mem->ida_hh)
-#define cj             (IDA_mem->ida_cj)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define ewt            (IDA_mem->ida_ewt)
-#define constraints    (IDA_mem->ida_constraints)
-
-#define linit          (IDA_mem->ida_linit)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve)
-#define lfree          (IDA_mem->ida_lfree)
-#define lperf          (IDA_mem->ida_lperf)
-#define lmem           (IDA_mem->ida_lmem)
-#define tempv          (IDA_mem->ida_tempv1)
-#define setupNonNull   (IDA_mem->ida_setupNonNull)
-
-#define mtype          (idadls_mem->d_type)
-#define n              (idadls_mem->d_n)
-#define ml             (idadls_mem->d_ml)
-#define mu             (idadls_mem->d_mu)
-#define smu            (idadls_mem->d_smu)
-#define jacDQ          (idadls_mem->d_jacDQ)
-#define djac           (idadls_mem->d_djac)
-#define bjac           (idadls_mem->d_bjac)
-#define M              (idadls_mem->d_J)
-#define pivots         (idadls_mem->d_pivots)
-#define nje            (idadls_mem->d_nje)
-#define nreDQ          (idadls_mem->d_nreDQ)
-#define last_flag      (idadls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * IDADlsSetDenseJacFn specifies the dense Jacobian function.
- */
-int IDADlsSetDenseJacFn(void *ida_mem, IDADlsDenseJacFn jac)
+/*=================================================================
+  PROTOTYPES FOR PRIVATE FUNCTIONS
+  =================================================================*/
+
+static int idaDlsJacBWrapper(realtype tt, realtype c_jB, N_Vector yyB,
+                             N_Vector ypB, N_Vector rBr, SUNMatrix JacB,
+                             void *ida_mem, N_Vector tmp1B,
+                             N_Vector tmp2B, N_Vector tmp3B);
+
+static int idaDlsJacBSWrapper(realtype tt, realtype c_jB, N_Vector yyB,
+                              N_Vector ypB, N_Vector rBr, SUNMatrix JacB,
+                              void *ida_mem, N_Vector tmp1B,
+                              N_Vector tmp2B, N_Vector tmp3B);
+
+
+/*===============================================================
+  IDASDLS Exported functions -- Required
+  ===============================================================*/
+
+/*---------------------------------------------------------------
+  IDADlsSetLinearSolver specifies the direct linear solver.
+  ---------------------------------------------------------------*/
+int IDADlsSetLinearSolver(void *ida_mem, SUNLinearSolver LS,
+                          SUNMatrix A)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetDenseJacFn", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", 
+                    "IDADlsSetLinearSolver", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
+  if ( (LS == NULL)  || (A == NULL) ) {
+    IDAProcessError(NULL, IDADLS_ILL_INPUT, "IDASDLS", 
+                    "IDADlsSetLinearSolver",
+                    "Both LS and A must be non-NULL");
+    return(IDADLS_ILL_INPUT);
+  }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", "IDADlsSetDenseJacFn", MSGD_LMEM_NULL);
-    return(IDADLS_LMEM_NULL);
+  /* Test if solver and vector are compatible with DLS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
+    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS", 
+                    "IDADlsSetLinearSolver", 
+                    "Non-direct LS supplied to IDADls interface");
+    return(IDADLS_ILL_INPUT);
+  }
+  if (IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL ||
+      IDA_mem->ida_tempv1->ops->nvsetarraypointer == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS", 
+                    "IDADlsSetLinearSolver", MSGD_BAD_NVECTOR);
+    return(IDADLS_ILL_INPUT);
   }
-  idadls_mem = (IDADlsMem) lmem;
 
-  if (jac != NULL) {
-    jacDQ = FALSE;
-    djac = jac;
-  } else {
-    jacDQ = TRUE;
+  /* free any existing system solver attached to IDA */
+  if (IDA_mem->ida_lfree)  IDA_mem->ida_lfree(IDA_mem);
+
+  /* Set four main system linear solver function fields in IDA_mem */
+  IDA_mem->ida_linit  = idaDlsInitialize;
+  IDA_mem->ida_lsetup = idaDlsSetup;
+  IDA_mem->ida_lsolve = idaDlsSolve;
+  IDA_mem->ida_lperf  = NULL;
+  IDA_mem->ida_lfree  = idaDlsFree;
+  
+  /* Get memory for IDADlsMemRec */
+  idadls_mem = NULL;
+  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
+  if (idadls_mem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASDLS",
+                    "IDADlsSetLinearSolver", MSGD_MEM_FAIL);
+    return(IDADLS_MEM_FAIL);
   }
 
+  /* set SUNLinearSolver pointer */
+  idadls_mem->LS = LS;
+  
+  /* set SUNMatrix pointer */
+  idadls_mem->J = A;
+
+  /* Initialize Jacobian-related data */
+  idadls_mem->jacDQ     = SUNTRUE;
+  idadls_mem->jac       = idaDlsDQJac;
+  idadls_mem->J_data    = IDA_mem;
+  idadls_mem->last_flag = IDADLS_SUCCESS;
+
+  /* Initialize counters */
+  idaDlsInitializeCounters(idadls_mem);
+
+  /* Allocate memory for x */
+  idadls_mem->x = N_VClone(IDA_mem->ida_tempv1);
+  if (idadls_mem->x == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASDLS", 
+                    "IDADlsSetLinearSolver", MSGD_MEM_FAIL);
+    free(idadls_mem); idadls_mem = NULL;
+    return(IDADLS_MEM_FAIL);
+  }
+  
+  /* Attach linear solver memory to integrator memory */
+  IDA_mem->ida_lmem = idadls_mem;
+
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsSetBandJacFn specifies the band Jacobian function.
- */
-int IDADlsSetBandJacFn(void *ida_mem, IDADlsBandJacFn jac)
+
+/*===============================================================
+  IDASDLS Exported functions -- Optional input/output
+  ===============================================================*/
+
+/*---------------------------------------------------------------
+  IDADlsSetJacFn specifies the Jacobian function.
+  ---------------------------------------------------------------*/
+int IDADlsSetJacFn(void *ida_mem, IDADlsJacFn jac)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetBandJacFn", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsSetJacFn", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", "IDADlsSetBandJacFn", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS",
+                    "IDADlsSetJacFn", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
   if (jac != NULL) {
-    jacDQ = FALSE;
-    bjac = jac;
+    idadls_mem->jacDQ  = SUNFALSE;
+    idadls_mem->jac    = jac;
+    idadls_mem->J_data = IDA_mem->ida_user_data;
   } else {
-    jacDQ = TRUE;
+    idadls_mem->jacDQ  = SUNTRUE;
+    idadls_mem->jac    = idaDlsDQJac;
+    idadls_mem->J_data = IDA_mem;
   }
 
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetWorkSpace returns the length of workspace allocated for the
- * IDALAPACK linear solver.
- */
-int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS)
+
+/*---------------------------------------------------------------
+  IDADlsGetWorkSpace returns the length of workspace allocated 
+  for the IDADLS linear solver interface
+  ---------------------------------------------------------------*/
+int IDADlsGetWorkSpace(void *ida_mem, long int *lenrwLS,
+                       long int *leniwLS)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsGetWorkSpace", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsGetWorkSpace", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", "IDADlsGetWorkSpace", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS",
+                    "IDADlsGetWorkSpace", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
-
-  if (mtype == SUNDIALS_DENSE) {
-    *lenrwLS = n*n;
-    *leniwLS = n;
-  } else if (mtype == SUNDIALS_BAND) {
-    *lenrwLS = n*(smu + ml + 1);
-    *leniwLS = n;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* initialize outputs with requirements from IDADlsMem structure */
+  *lenrwLS = 0;
+  *leniwLS = 3;
+
+  /* add vector sizes */
+  if (idadls_mem->x->ops->nvspace) {
+    N_VSpace(idadls_mem->x, &lrw1, &liw1);
+    *lenrwLS += lrw1;
+    *leniwLS += liw1;
+  }
+
+  /* add LS sizes */
+  if (idadls_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(idadls_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
-    
+
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetNumJacEvals returns the number of Jacobian evaluations.
+  ---------------------------------------------------------------*/
 int IDADlsGetNumJacEvals(void *ida_mem, long int *njevals)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsGetNumJacEvals", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsGetNumJacEvals", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", "IDADlsGetNumJacEvals", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS",
+                    "IDADlsGetNumJacEvals", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  *njevals = nje;
+  *njevals = idadls_mem->nje;
 
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetNumResEvals returns the number of calls to the DAE function
- * needed for the DQ Jacobian approximation.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetNumResEvals returns the number of calls to the DAE 
+  function needed for the DQ Jacobian approximation.
+  ---------------------------------------------------------------*/
 int IDADlsGetNumResEvals(void *ida_mem, long int *nrevalsLS)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsGetNumFctEvals", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsGetNumResEvals", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", "IDADlsGetNumFctEvals", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS",
+                    "IDADlsGetNumResEvals", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  *nrevalsLS = nreDQ;
+  *nrevalsLS = idadls_mem->nreDQ;
 
   return(IDADLS_SUCCESS);
 }
 
-/*
- * IDADlsGetReturnFlagName returns the name associated with a IDALAPACK
- * return value.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetReturnFlagName returns the name associated with a 
+  IDASDLS return value.
+  ---------------------------------------------------------------*/
 char *IDADlsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -296,6 +322,9 @@ char *IDADlsGetReturnFlagName(long int flag)
   case IDADLS_JACFUNC_RECVR:
     sprintf(name,"IDADLS_JACFUNC_RECVR");
     break;
+  case IDADLS_SUNMAT_FAIL:
+    sprintf(name,"IDADLS_SUNMAT_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -303,91 +332,133 @@ char *IDADlsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * IDADlsGetLastFlag returns the last flag set in a IDALAPACK function.
- */
+
+/*---------------------------------------------------------------
+  IDADlsGetLastFlag returns the last flag set in a IDASDLS function.
+  ---------------------------------------------------------------*/
 int IDADlsGetLastFlag(void *ida_mem, long int *flag)
 {
   IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsGetLastFlag", MSGD_IDAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsGetLastFlag", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", "IDADlsGetLastFlag", MSGD_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS",
+                    "IDADlsGetLastFlag", MSGD_LMEM_NULL);
     return(IDADLS_LMEM_NULL);
   }
-  idadls_mem = (IDADlsMem) lmem;
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  *flag = last_flag;
+  *flag = idadls_mem->last_flag;
 
   return(IDADLS_SUCCESS);
 }
 
-/* 
- * =================================================================
- * DQ JACOBIAN APPROXIMATIONS
- * =================================================================
- */
 
-/*
- * -----------------------------------------------------------------
- * idaDlsDenseDQJac 
- * -----------------------------------------------------------------
- * This routine generates a dense difference quotient approximation to
- * the Jacobian F_y + c_j*F_y'. It assumes that a dense matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. The address of the jth column of J is obtained via
- * the macro LAPACK_DENSE_COL and this pointer is associated with an N_Vector
- * using the N_VGetArrayPointer/N_VSetArrayPointer functions. 
- * Finally, the actual computation of the jth column of the Jacobian is 
- * done with a call to N_VLinearSum.
- * -----------------------------------------------------------------
- */ 
-int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
-                     N_Vector yy, N_Vector yp, N_Vector rr, 
-                     DlsMat Jac, void *data,
-                     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+/*===============================================================
+  IDASDLS Private functions
+  ===============================================================*/
+
+
+/*---------------------------------------------------------------
+  idaDlsDQJac:
+
+  This routine is a wrapper for the Dense and Band 
+  implementations of the difference quotient Jacobian 
+  approximation routines.
+---------------------------------------------------------------*/
+int idaDlsDQJac(realtype t, realtype c_j, N_Vector y,  
+                N_Vector yp, N_Vector r, SUNMatrix Jac, 
+                void *ida_mem, N_Vector tmp1, N_Vector tmp2,
+                N_Vector tmp3)
+{
+  int retval;
+  IDAMem IDA_mem;
+  IDA_mem = (IDAMem) ida_mem;
+
+  /* verify that Jac is non-NULL */
+  if (Jac == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", 
+		    "idaDlsDQJac", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
+  }
+
+  if (SUNMatGetID(Jac) == SUNMATRIX_DENSE) {
+    retval = idaDlsDenseDQJac(t, c_j, y, yp, r, Jac, IDA_mem, tmp1);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_BAND) {
+    retval = idaDlsBandDQJac(t, c_j, y, yp, r, Jac, IDA_mem, tmp1, tmp2, tmp3);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_SPARSE) {
+    IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDASDLS", 
+		    "idaDlsDQJac", 
+                    "idaDlsDQJac not implemented for SUNMATRIX_SPARSE");
+    retval = IDA_ILL_INPUT;
+  } else {
+    IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDASDLS", 
+		    "idaDlsDQJac", 
+                    "unrecognized matrix type for idaDlsDQJac");
+    retval = IDA_ILL_INPUT;
+  }
+  return(retval);
+}
+
+
+/*---------------------------------------------------------------
+  idaDlsDenseDQJac 
+
+  This routine generates a dense difference quotient approximation
+  to the Jacobian F_y + c_j*F_y'. It assumes a dense SUNmatrix 
+  input (stored column-wise, and that elements within each column
+  are contiguous). The address of the jth column of J is obtained 
+  via the function SUNDenseMatrix_Column() and this pointer is 
+  associated with an N_Vector using the 
+  N_VGetArrayPointer/N_VSetArrayPointer functions.  Finally, the 
+  actual computation of the jth column of the Jacobian is 
+  done with a call to N_VLinearSum.
+---------------------------------------------------------------*/
+int idaDlsDenseDQJac(realtype tt, realtype c_j, N_Vector yy,
+                     N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                     IDAMem IDA_mem, N_Vector tmp1)
 {
   realtype inc, inc_inv, yj, ypj, srur, conj;
-  realtype *tmp2_data, *y_data, *yp_data, *ewt_data, *cns_data = NULL;
+  realtype *y_data, *yp_data, *ewt_data, *cns_data = NULL;
   N_Vector rtemp, jthCol;
-  long int j;
+  sunindextype j, N;
   int retval = 0;
-
-  IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* data points to IDA_mem */
-  IDA_mem = (IDAMem) data;
-  idadls_mem = (IDADlsMem) lmem;
+  /* access DlsMem interface structure */
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  /* Save pointer to the array in tmp2 */
-  tmp2_data = N_VGetArrayPointer(tmp2);
+  /* access matrix dimension */
+  N = SUNDenseMatrix_Rows(Jac);
 
   /* Rename work vectors for readibility */
-  rtemp  = tmp1;
-  jthCol = tmp2;
+  rtemp = tmp1;
 
+  /* Create an empty vector for matrix column calculations */
+  jthCol = N_VCloneEmpty(tmp1);
+  
   /* Obtain pointers to the data for ewt, yy, yp. */
-  ewt_data = N_VGetArrayPointer(ewt);
+  ewt_data = N_VGetArrayPointer(IDA_mem->ida_ewt);
   y_data   = N_VGetArrayPointer(yy);
   yp_data  = N_VGetArrayPointer(yp);
-  if(constraints!=NULL) cns_data = N_VGetArrayPointer(constraints);
+  if(IDA_mem->ida_constraints!=NULL)
+    cns_data = N_VGetArrayPointer(IDA_mem->ida_constraints);
 
-  srur = SUNRsqrt(uround);
+  srur = SUNRsqrt(IDA_mem->ida_uround);
 
   for (j=0; j < N; j++) {
 
     /* Generate the jth col of J(tt,yy,yp) as delta(F)/delta(y_j). */
 
     /* Set data address of jthCol, and save y_j and yp_j values. */
-    N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol);
+    N_VSetArrayPointer(SUNDenseMatrix_Column(Jac,j), jthCol);
     yj = y_data[j];
     ypj = yp_data[j];
 
@@ -395,13 +466,14 @@ int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
     adjustments using yp_j and ewt_j if this is small, and a further
     adjustment to give it the same sign as hh*yp_j. */
 
-    inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(hh*ypj) ) , ONE/ewt_data[j] );
+    inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(IDA_mem->ida_hh*ypj) ),
+                  ONE/ewt_data[j] );
 
-    if (hh*ypj < ZERO) inc = -inc;
+    if (IDA_mem->ida_hh * ypj < ZERO) inc = -inc;
     inc = (yj + inc) - yj;
 
     /* Adjust sign(inc) again if y_j has an inequality constraint. */
-    if (constraints != NULL) {
+    if (IDA_mem->ida_constraints != NULL) {
       conj = cns_data[j];
       if (SUNRabs(conj) == ONE)      {if((yj+inc)*conj <  ZERO) inc = -inc;}
       else if (SUNRabs(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
@@ -411,93 +483,87 @@ int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
     y_data[j] += inc;
     yp_data[j] += c_j*inc;
 
-    retval = res(tt, yy, yp, rtemp, user_data);
-
-    nreDQ++;
+    retval = IDA_mem->ida_res(tt, yy, yp, rtemp, IDA_mem->ida_user_data);
+    idadls_mem->nreDQ++;
     if (retval != 0) break;
 
     /* Construct difference quotient in jthCol */
     inc_inv = ONE/inc;
     N_VLinearSum(inc_inv, rtemp, -inc_inv, rr, jthCol);
 
-    DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);
+    /* DENSE_COL(Jac,j) = N_VGetArrayPointer(jthCol);  /\* UNNECESSARY *\/ */
 
     /*  reset y_j, yp_j */     
     y_data[j] = yj;
     yp_data[j] = ypj;
   }
 
-  /* Restore original array pointer in tmp2 */
-  N_VSetArrayPointer(tmp2_data, tmp2);
+  /* Destroy jthCol vector */
+  N_VSetArrayPointer(NULL, jthCol);  /* SHOULDN'T BE NEEDED */
+  N_VDestroy(jthCol);
 
   return(retval);
 
 }
 
-/*
- * -----------------------------------------------------------------
- * idaDlsBandDQJac 
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation JJ
- * to the DAE system Jacobian J.  It assumes that a band matrix of type
- * BandMat is stored column-wise, and that elements within each column
- * are contiguous.  The address of the jth column of JJ is obtained via
- * the macros BAND_COL and BAND_COL_ELEM. The columns of the Jacobian are 
- * constructed using mupper + mlower + 1 calls to the res routine, and
- * appropriate differencing.
- * The return value is either IDABAND_SUCCESS = 0, or the nonzero value returned
- * by the res routine, if any.
- */
-
-int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
-                    realtype tt, realtype c_j, 
-                    N_Vector yy, N_Vector yp, N_Vector rr,
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
+
+/*---------------------------------------------------------------
+  idaDlsBandDQJac 
+
+  This routine generates a banded difference quotient approximation 
+  JJ to the DAE system Jacobian J.  It assumes a band SUNMatrix 
+  input (stored column-wise, and that elements within each column
+  are contiguous).  This makes it possible to get the address 
+  of a column of JJ via the function SUNBandMatrix_Column(). The 
+  columns of the Jacobian are constructed using mupper + mlower + 1 
+  calls to the res routine, and appropriate differencing.
+  The return value is either IDABAND_SUCCESS = 0, or the nonzero 
+  value returned by the res routine, if any.
+  ---------------------------------------------------------------*/
+int idaDlsBandDQJac(realtype tt, realtype c_j, N_Vector yy,
+                    N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                    IDAMem IDA_mem, N_Vector tmp1, N_Vector tmp2,
+                    N_Vector tmp3)
 {
   realtype inc, inc_inv, yj, ypj, srur, conj, ewtj;
   realtype *y_data, *yp_data, *ewt_data, *cns_data = NULL;
   realtype *ytemp_data, *yptemp_data, *rtemp_data, *r_data, *col_j;
-  
   N_Vector rtemp, ytemp, yptemp;
-  long int group, i, j, i1, i2, width, ngroups;
+  sunindextype i, j, i1, i2, width, ngroups, group;
+  sunindextype N, mupper, mlower;
   int retval = 0;
-
-  IDAMem IDA_mem;
   IDADlsMem idadls_mem;
 
-  /* data points to IDA_mem */
-  IDA_mem = (IDAMem) data;
-  idadls_mem = (IDADlsMem) lmem;
+  /* access DlsMem interface structure */
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
 
-  rtemp = tmp1; /* Rename work vector for use as the perturbed residual. */
+  /* access matrix dimensions */
+  N = SUNBandMatrix_Columns(Jac);
+  mupper = SUNBandMatrix_UpperBandwidth(Jac);
+  mlower = SUNBandMatrix_LowerBandwidth(Jac);
 
-  ytemp = tmp2; /* Rename work vector for use as a temporary for yy. */
-
-
-  yptemp= tmp3; /* Rename work vector for use as a temporary for yp. */
+  /* Rename work vectors for use as temporary values of r, y and yp */
+  rtemp = tmp1;
+  ytemp = tmp2;
+  yptemp= tmp3;
 
   /* Obtain pointers to the data for all eight vectors used.  */
-
-  ewt_data = N_VGetArrayPointer(ewt);
-  r_data   = N_VGetArrayPointer(rr);
-  y_data   = N_VGetArrayPointer(yy);
-  yp_data  = N_VGetArrayPointer(yp);
-
+  ewt_data    = N_VGetArrayPointer(IDA_mem->ida_ewt);
+  r_data      = N_VGetArrayPointer(rr);
+  y_data      = N_VGetArrayPointer(yy);
+  yp_data     = N_VGetArrayPointer(yp);
   rtemp_data  = N_VGetArrayPointer(rtemp);
   ytemp_data  = N_VGetArrayPointer(ytemp);
   yptemp_data = N_VGetArrayPointer(yptemp);
-
-  if (constraints != NULL) cns_data = N_VGetArrayPointer(constraints);
+  if (IDA_mem->ida_constraints != NULL)
+    cns_data = N_VGetArrayPointer(IDA_mem->ida_constraints);
 
   /* Initialize ytemp and yptemp. */
-
   N_VScale(ONE, yy, ytemp);
   N_VScale(ONE, yp, yptemp);
 
   /* Compute miscellaneous values for the Jacobian computation. */
-
-  srur = SUNRsqrt(uround);
+  srur = SUNRsqrt(IDA_mem->ida_uround);
   width = mlower + mupper + 1;
   ngroups = SUNMIN(width, N);
 
@@ -505,7 +571,6 @@ int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
   for (group=1; group <= ngroups; group++) {
 
     /* Increment all yy[j] and yp[j] for j in this group. */
-
     for (j=group-1; j<N; j+=width) {
         yj = y_data[j];
         ypj = yp_data[j];
@@ -514,64 +579,55 @@ int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
         /* Set increment inc to yj based on sqrt(uround)*abs(yj), with
         adjustments using ypj and ewtj if this is small, and a further
         adjustment to give it the same sign as hh*ypj. */
-
-        inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(hh*ypj) ) , ONE/ewtj );
-
-        if (hh*ypj < ZERO) inc = -inc;
+        inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(IDA_mem->ida_hh * ypj) ),
+                      ONE/ewtj );
+        if (IDA_mem->ida_hh * ypj < ZERO) inc = -inc;
         inc = (yj + inc) - yj;
 
         /* Adjust sign(inc) again if yj has an inequality constraint. */
-
-        if (constraints != NULL) {
+        if (IDA_mem->ida_constraints != NULL) {
           conj = cns_data[j];
           if (SUNRabs(conj) == ONE)      {if((yj+inc)*conj <  ZERO) inc = -inc;}
           else if (SUNRabs(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
         }
 
         /* Increment yj and ypj. */
-
-        ytemp_data[j] += inc;
-        yptemp_data[j] += cj*inc;
+        ytemp_data[j]  += inc;
+        yptemp_data[j] += IDA_mem->ida_cj * inc;
     }
 
     /* Call res routine with incremented arguments. */
-
-    retval = res(tt, ytemp, yptemp, rtemp, user_data);
-    nreDQ++;
+    retval = IDA_mem->ida_res(tt, ytemp, yptemp, rtemp, IDA_mem->ida_user_data);
+    idadls_mem->nreDQ++;
     if (retval != 0) break;
 
     /* Loop over the indices j in this group again. */
-
     for (j=group-1; j<N; j+=width) {
 
       /* Reset ytemp and yptemp components that were perturbed. */
-
       yj = ytemp_data[j]  = y_data[j];
       ypj = yptemp_data[j] = yp_data[j];
-      col_j = BAND_COL(Jac, j);
+      col_j = SUNBandMatrix_Column(Jac, j);
       ewtj = ewt_data[j];
       
       /* Set increment inc exactly as above. */
-
-      inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(hh*ypj) ) , ONE/ewtj );
-      if (hh*ypj < ZERO) inc = -inc;
+      inc = SUNMAX( srur * SUNMAX( SUNRabs(yj), SUNRabs(IDA_mem->ida_hh * ypj) ),
+                    ONE/ewtj );
+      if (IDA_mem->ida_hh * ypj < ZERO)  inc = -inc;
       inc = (yj + inc) - yj;
-      if (constraints != NULL) {
+      if (IDA_mem->ida_constraints != NULL) {
         conj = cns_data[j];
         if (SUNRabs(conj) == ONE)      {if((yj+inc)*conj <  ZERO) inc = -inc;}
         else if (SUNRabs(conj) == TWO) {if((yj+inc)*conj <= ZERO) inc = -inc;}
       }
       
       /* Load the difference quotient Jacobian elements for column j. */
-
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-mupper);
       i2 = SUNMIN(j+mlower,N-1);
-      
       for (i=i1; i<=i2; i++) 
-            BAND_COL_ELEM(col_j,i,j) = inc_inv*(rtemp_data[i]-r_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (rtemp_data[i]-r_data[i]);
     }
-    
   }
   
   return(retval);
@@ -579,93 +635,198 @@ int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
 }
 
 
-int idaDlsInitializeCounters(IDADlsMem idadls_mem)
+
+
+/*---------------------------------------------------------------
+ idaDlsInitialize performs remaining initializations specific
+ to the direct linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int idaDlsInitialize(IDAMem IDA_mem)
 {
-  idadls_mem->d_nje   = 0;
-  idadls_mem->d_nreDQ = 0;
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", 
+                    "idaDlsInitialize", MSGD_IDAMEM_NULL);
+    return(IDADLS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", 
+                    "idaDlsInitialize", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
+  }
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
   
-  return(0);
+  idaDlsInitializeCounters(idadls_mem);
+
+  /* Set Jacobian function and data, depending on jacDQ (in case 
+     it has changed based on user input) */
+  if (idadls_mem->jacDQ) {
+    idadls_mem->jac    = idaDlsDQJac;
+    idadls_mem->J_data = IDA_mem;
+  } else {
+    idadls_mem->J_data = IDA_mem->ida_user_data;
+  }
+
+  /* Call LS initialize routine */
+  idadls_mem->last_flag = SUNLinSolInitialize(idadls_mem->LS);
+  return(idadls_mem->last_flag);
 }
 
-/* 
- * =================================================================
- * BACKWARD INTEGRATION SUPPORT
- * =================================================================
- */
-
-/* Additional readability replacements */
-#define yyTmp       (IDAADJ_mem->ia_yyTmp)
-#define ypTmp       (IDAADJ_mem->ia_ypTmp)
-#define yySTmp      (IDAADJ_mem->ia_yySTmp)
-#define ypSTmp      (IDAADJ_mem->ia_ypSTmp)
-#define noInterp    (IDAADJ_mem->ia_noInterp)
-#define interpSensi (IDAADJ_mem->ia_interpSensi)
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS
- * -----------------------------------------------------------------
- */
 
-int IDADlsSetDenseJacFnB(void *ida_mem, int which, IDADlsDenseJacFnB jacB)
+/*---------------------------------------------------------------
+  idaDlsSetup does the setup operations for the IDASDLS linear 
+  solver interface.  It calls the Jacobian evaluation routine, 
+  updates counters, and calls the LS 'setup' routine to prepare
+  for subsequent calls to the LS 'solve' routine.
+
+  The return value is either
+     IDADLS_SUCCESS = 0  if successful,
+      1  if the jac or LS 'setup' routine failed recoverably, or
+     -1  if the jac or LS 'setup' routines failed unrecoverably.
+---------------------------------------------------------------*/
+int idaDlsSetup(IDAMem IDA_mem, N_Vector y, N_Vector yp, N_Vector r, 
+                N_Vector vt1, N_Vector vt2, N_Vector vt3)
 {
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDADlsMemB idadlsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetDenseJacFnB", MSGD_CAMEM_NULL);
+  int retval;
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", 
+                    "idaDlsSetup", MSGD_IDAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS", "IDADlsSetDenseJacFnB",  MSGD_NO_ADJ);
-    return(IDADLS_NO_ADJ);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", 
+                    "idaDlsSetup", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
   }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS", "IDADlsSetDenseJacFnB", MSGD_BAD_WHICH);
-    return(IDADLS_ILL_INPUT);
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* Increment nje counter. */
+  idadls_mem->nje++;
+
+  /* Zero out J; call Jacobian routine jac; return if it failed. */
+  retval = SUNMatZero(idadls_mem->J);
+  if (retval != 0) {
+    IDAProcessError(IDA_mem, IDADLS_SUNMAT_FAIL, "IDADLS",
+                    "idaDlsSetup", MSGD_MATZERO_FAILED);
+    idadls_mem->last_flag = IDADLS_SUNMAT_FAIL;
+    return(-1);
   }
 
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
+  retval = idadls_mem->jac(IDA_mem->ida_tn, IDA_mem->ida_cj, y,
+                           yp, r, idadls_mem->J,
+                           idadls_mem->J_data, vt1, vt2, vt3);
+  if (retval < 0) {
+    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDASDLS",
+                    "idaDlsSetup", MSGD_JACFUNC_FAILED);
+    idadls_mem->last_flag = IDADLS_JACFUNC_UNRECVR;
+    return(-1);
+  }
+  if (retval > 0) {
+    idadls_mem->last_flag = IDADLS_JACFUNC_RECVR;
+    return(1);
   }
 
-  /* Get the IDAMem corresponding to this backward problem. */
-  ida_memB = (void*) IDAB_mem->IDA_mem;
+  /* Call generic linear solver 'setup' with this system matrix, and
+     return success/failure flag */
+  idadls_mem->last_flag = SUNLinSolSetup(idadls_mem->LS, idadls_mem->J);
+  return(idadls_mem->last_flag);
+}
 
-  if (IDAB_mem->ida_lmem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_LMEMB_NULL, 
-                    "IDASDLS", "IDADlsSetDenseJacFnB", MSGD_LMEMB_NULL);
-    return(IDADLS_LMEMB_NULL);
+
+/*---------------------------------------------------------------
+ idaDlsSolve interfaces between IDA and the generic 
+ SUNLinearSolver object LS, by calling the LS 'solve' routine 
+ and scaling the result if cjratio does not equal one.
+---------------------------------------------------------------*/
+int idaDlsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                N_Vector ycur, N_Vector ypcur, N_Vector rescur)
+{
+  int retval;
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", 
+		    "idaDlsSolve", MSGD_IDAMEM_NULL);
+    return(IDADLS_MEM_NULL);
   }
-  idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEM_NULL, "IDASDLS", 
+		    "idaDlsSolve", MSGD_LMEM_NULL);
+    return(IDADLS_LMEM_NULL);
+  }
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* call the generic linear system solver, and copy x to b */
+  retval = SUNLinSolSolve(idadls_mem->LS, idadls_mem->J, idadls_mem->x, b, ZERO);
+  N_VScale(ONE, idadls_mem->x, b);
+  
+  /* scale the correction to account for change in cj */
+  if (IDA_mem->ida_cjratio != ONE) 
+    N_VScale(TWO/(ONE + IDA_mem->ida_cjratio), b, b);
+  
+  /* store solver return value and return */
+  idadls_mem->last_flag = retval;
+  return(retval);
+}
 
-  idadlsB_mem->d_djacB = jacB;
 
-  if (jacB != NULL) {
-    flag = IDADlsSetDenseJacFn(ida_memB, idaDlsDenseJacBWrapper);
-  } else {
-    flag = IDADlsSetDenseJacFn(ida_memB, NULL);
+/*---------------------------------------------------------------
+ idaDlsFree frees memory associates with the IDADls system
+ solver interface.
+---------------------------------------------------------------*/
+int idaDlsFree(IDAMem IDA_mem)
+{
+  IDADlsMem idadls_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL)  return (IDADLS_SUCCESS);
+  if (IDA_mem->ida_lmem == NULL)  return(IDADLS_SUCCESS);
+  idadls_mem = (IDADlsMem) IDA_mem->ida_lmem;
+
+  /* Free x vector */
+  if (idadls_mem->x) {
+    N_VDestroy(idadls_mem->x);
+    idadls_mem->x = NULL;
   }
 
-  return(flag);
+  /* Nullify SUNMatrix pointer */
+  idadls_mem->J = NULL;
+
+  /* free IDADls interface structure */
+  free(IDA_mem->ida_lmem);
+  
+  return(IDADLS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+  idaDlsInitializeCounters resets counters for the DLS interface
+  ---------------------------------------------------------------*/
+int idaDlsInitializeCounters(IDADlsMem idadls_mem)
+{
+  idadls_mem->nje   = 0;
+  idadls_mem->nreDQ = 0;
+  return(0);
 }
 
-int IDADlsSetDenseJacFnBS(void *ida_mem, int which, IDADlsDenseJacFnBS jacBS)
+
+/*=================================================================
+  BACKWARD INTEGRATION SUPPORT
+  =================================================================*/
+
+
+/*---------------------------------------------------------------
+  IDADlsSetLinearSolverB specifies the direct linear solver for 
+  backward integration
+  ---------------------------------------------------------------*/
+int IDADlsSetLinearSolverB(void *ida_mem, int which,
+                           SUNLinearSolver LS, SUNMatrix A)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -673,24 +834,27 @@ int IDADlsSetDenseJacFnBS(void *ida_mem, int which, IDADlsDenseJacFnBS jacBS)
   IDADlsMemB idadlsB_mem;
   void *ida_memB;
   int flag;
-  
+
   /* Is ida_mem allright? */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetDenseJacFnBS", MSGD_CAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsSetLinearSolverB", MSGD_CAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS", "IDADlsSetDenseJacFnBS",  MSGD_NO_ADJ);
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS",
+                    "IDADlsSetLinearSolverB",  MSGD_NO_ADJ);
     return(IDADLS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS", "IDADlsSetDenseJacFnBS", MSGD_BAD_WHICH);
+    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS",
+                    "IDADlsSetLinearSolverB", MSGD_BAD_WHICH);
     return(IDADLS_ILL_INPUT);
   }
 
@@ -702,28 +866,43 @@ int IDADlsSetDenseJacFnBS(void *ida_mem, int which, IDADlsDenseJacFnBS jacBS)
     IDAB_mem = IDAB_mem->ida_next;
   }
 
-  /* Get the IDAMem corresponding to this backward problem. */
-  ida_memB = (void*) IDAB_mem->IDA_mem;
-
-  if (IDAB_mem->ida_lmem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_LMEMB_NULL, 
-                    "IDASDLS", "IDADlsSetDenseJacFnBS", MSGD_LMEMB_NULL);
-    return(IDADLS_LMEMB_NULL);
+  /* Alloc memory for IDADlsMemRecB */
+  idadlsB_mem = (IDADlsMemB) malloc(sizeof(struct IDADlsMemRecB));
+  if (idadlsB_mem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_MEM_FAIL, "IDASDLS",
+                    "IDADlsSetLinearSolverB", MSGD_MEM_FAIL);
+    return(IDADLS_MEM_FAIL);
+  
   }
-  idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
 
-  idadlsB_mem->d_djacBS = jacBS;
+  /* free any existing system solver attached to IDAB */
+  if (IDAB_mem->ida_lfree)  IDAB_mem->ida_lfree(IDAB_mem);
 
-  if (jacBS != NULL) {
-    flag = IDADlsSetDenseJacFn(ida_memB, idaDlsDenseJacBSWrapper);
-  } else {
-    flag = IDADlsSetDenseJacFn(ida_memB, NULL);
+  /* Attach lmemB data and lfreeB function. */
+  IDAB_mem->ida_lmem  = idadlsB_mem;
+  IDAB_mem->ida_lfree = idaDlsFreeB;
+
+  /* initialize jacB and jacBS pointers */
+  idadlsB_mem->jacB  = NULL;
+  idadlsB_mem->jacBS = NULL;
+
+  /* set the linear solver for this backward problem */
+  ida_memB = (void *)IDAB_mem->IDA_mem;
+  flag = IDADlsSetLinearSolver(ida_memB, LS, A);
+  if (flag != IDADLS_SUCCESS) {
+    free(idadlsB_mem);
+    idadlsB_mem = NULL;
   }
 
   return(flag);
 }
 
-int IDADlsSetBandJacFnB(void *ida_mem, int which, IDADlsBandJacFnB jacB)
+
+/*===============================================================
+  IDASDLS Exported functions -- Optional input/output
+  ===============================================================*/
+
+int IDADlsSetJacFnB(void *ida_mem, int which, IDADlsJacFnB jacB)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -734,21 +913,24 @@ int IDADlsSetBandJacFnB(void *ida_mem, int which, IDADlsBandJacFnB jacB)
   
   /* Is ida_mem allright? */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetBandJacFnB", MSGD_CAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsSetJacFnB", MSGD_CAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS", "IDADlsSetBandJacFnB",  MSGD_NO_ADJ);
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS",
+                    "IDADlsSetJacFnB",  MSGD_NO_ADJ);
     return(IDADLS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS", "IDADlsSetBandJacFnB", MSGD_BAD_WHICH);
+    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS",
+                    "IDADlsSetJacFnB", MSGD_BAD_WHICH);
     return(IDADLS_ILL_INPUT);
   }
 
@@ -765,23 +947,24 @@ int IDADlsSetBandJacFnB(void *ida_mem, int which, IDADlsBandJacFnB jacB)
 
   if (IDAB_mem->ida_lmem == NULL) {
     IDAProcessError(IDAB_mem->IDA_mem, IDADLS_LMEMB_NULL, 
-                    "IDASDLS", "IDADlsSetBandJacFnB", MSGD_LMEMB_NULL);
+                    "IDASDLS", "IDADlsSetJacFnB", MSGD_LMEMB_NULL);
     return(IDADLS_LMEMB_NULL);
   }
   idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
 
-  idadlsB_mem->d_bjacB = jacB;
+  idadlsB_mem->jacB = jacB;
 
   if (jacB != NULL) {
-    flag = IDADlsSetBandJacFn(ida_memB, idaDlsBandJacBWrapper);
+    flag = IDADlsSetJacFn(ida_memB, idaDlsJacBWrapper);
   } else {
-    flag = IDADlsSetBandJacFn(ida_memB, NULL);
+    flag = IDADlsSetJacFn(ida_memB, NULL);
   }
 
   return(flag);
 }
 
-int IDADlsSetBandJacFnBS(void *ida_mem, int which, IDADlsBandJacFnBS jacBS)
+
+int IDADlsSetJacFnBS(void *ida_mem, int which, IDADlsJacFnBS jacBS)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -792,21 +975,24 @@ int IDADlsSetBandJacFnBS(void *ida_mem, int which, IDADlsBandJacFnBS jacBS)
   
   /* Is ida_mem allright? */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS", "IDADlsSetBandJacFnBS", MSGD_CAMEM_NULL);
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "IDADlsSetJacFnBS", MSGD_CAMEM_NULL);
     return(IDADLS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS", "IDADlsSetBandJacFnBS",  MSGD_NO_ADJ);
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS",
+                    "IDADlsSetJacFnBS",  MSGD_NO_ADJ);
     return(IDADLS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS", "IDADlsSetBandJacFnBS", MSGD_BAD_WHICH);
+    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASDLS",
+                    "IDADlsSetJacFnBS", MSGD_BAD_WHICH);
     return(IDADLS_ILL_INPUT);
   }
 
@@ -823,87 +1009,54 @@ int IDADlsSetBandJacFnBS(void *ida_mem, int which, IDADlsBandJacFnBS jacBS)
 
   if (IDAB_mem->ida_lmem == NULL) {
     IDAProcessError(IDAB_mem->IDA_mem, IDADLS_LMEMB_NULL, 
-                    "IDASDLS", "IDADlsSetBandJacFnBS", MSGD_LMEMB_NULL);
+                    "IDASDLS", "IDADlsSetJacFnBS", MSGD_LMEMB_NULL);
     return(IDADLS_LMEMB_NULL);
   }
   idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
 
-  idadlsB_mem->d_bjacBS = jacBS;
+  idadlsB_mem->jacBS = jacBS;
 
   if (jacBS != NULL) {
-    flag = IDADlsSetBandJacFn(ida_memB, idaDlsBandJacBSWrapper);
+    flag = IDADlsSetJacFn(ida_memB, idaDlsJacBSWrapper);
   } else {
-    flag = IDADlsSetBandJacFn(ida_memB, NULL);
+    flag = IDADlsSetJacFn(ida_memB, NULL);
   }
 
   return(flag);
 }
 
 
-/*
- * -----------------------------------------------------------------
- * PRIVATE INTERFACE FUNCTIONS
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  PRIVATE INTERFACE FUNCTIONS
+  -----------------------------------------------------------------*/
 
-/*
- * idaDlsDenseJacBWrapper
- *
- * This routine interfaces to the IDADenseJacFnB routine provided 
- * by the user. idaDlsDenseJacBWrapper is of type IDADlsDenseJacFn.
- * NOTE: data actually contains ida_mem
- */
-
-static int idaDlsDenseJacBWrapper(long int NeqB, realtype tt, realtype c_jB,
-                                  N_Vector yyB, N_Vector ypB, N_Vector rrB,
-                                  DlsMat JacB, void *ida_mem, 
-                                  N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+int idaDlsFreeB(IDABMem IDAB_mem)
 {
-  IDAadjMem IDAADJ_mem;
-  IDAMem IDA_mem;
-  IDABMem IDAB_mem;
   IDADlsMemB idadlsB_mem;
-  int flag;
 
-  IDA_mem = (IDAMem) ida_mem;
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Get current backward problem. */
-  IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  
-  /* Get linear solver's data for this backward problem. */
+  /* Return immediately if IDAB_mem or IDAB_mem->ida_lmem are NULL */
+  if (IDAB_mem == NULL)  return (IDADLS_SUCCESS);
+  if (IDAB_mem->ida_lmem == NULL)  return(IDADLS_SUCCESS);
   idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
 
-  /* Forward solution from interpolation */
-  if (noInterp == FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
-    if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASDLS", "idaDlsDenseJacBWrapper", MSGD_BAD_T);
-      return(-1);
-    }
-  }
-
-  /* Call user's adjoint dense djacB routine */
-  flag = idadlsB_mem->d_djacB(NeqB, tt, c_jB, 
-                              yyTmp, ypTmp, 
-                              yyB, ypB, rrB, 
-                              JacB, IDAB_mem->ida_user_data, 
-                              tmp1B, tmp2B, tmp3B);
-  return(flag);
+  /* free IDADlsMemB interface structure */
+  free(idadlsB_mem);
+  
+  return(IDADLS_SUCCESS);
 }
 
-/*
- * idaDlsDenseJacBSWrapper
- *
- * This routine interfaces to the IDADenseJacFnBS routine provided 
- * by the user. idaDlsDenseJacBSWrapper is of type IDADlsDenseJacFn.
- * NOTE: data actually contains ida_mem
- */
-
-static int idaDlsDenseJacBSWrapper(long int NeqB, realtype tt, realtype c_jB,
-                                  N_Vector yyB, N_Vector ypB, N_Vector rrB,
-                                  DlsMat JacB, void *ida_mem, 
-                                  N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+
+/*---------------------------------------------------------------
+  idaDlsJacBWrapper
+ 
+  This routine interfaces to the IDAJacFnB routine provided 
+  by the user. idaDlsJacBWrapper is of type IDADlsJacFn.
+  NOTE: data actually contains ida_mem
+  ---------------------------------------------------------------*/
+static int idaDlsJacBWrapper(realtype tt, realtype c_jB, N_Vector yyB, 
+                             N_Vector ypB, N_Vector rrB, SUNMatrix JacB,
+                             void *ida_mem, N_Vector tmp1B,
+                             N_Vector tmp2B, N_Vector tmp3B)
 {
   IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
@@ -911,98 +1064,68 @@ static int idaDlsDenseJacBSWrapper(long int NeqB, realtype tt, realtype c_jB,
   IDADlsMemB idadlsB_mem;
   int flag;
 
+  /* Is ida_mem allright? */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "idaDlsJacBWrapper", MSGD_CAMEM_NULL);
+    return(IDADLS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
 
-  /* Get current backward problem. */
-  IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  
-  /* Get linear solver's data for this backward problem. */
-  idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
-
-  /* Get forward solution from interpolation. */
-  if( noInterp == FALSE) {
-    if (interpSensi)
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, yySTmp, ypSTmp);
-    else
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
-  
-    if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASDLS", "idaDlsDenseJacBSWrapper", MSGD_BAD_T);
-      return(-1);
-    }
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS",
+                    "idaDlsJacBWrapper",  MSGD_NO_ADJ);
+    return(IDADLS_NO_ADJ);
   }
-
-  /* Call user's adjoint dense djacBS routine */
-  flag = idadlsB_mem->d_djacBS(NeqB, tt, c_jB, 
-                              yyTmp, ypTmp, yySTmp, ypSTmp, 
-                              yyB, ypB, rrB, 
-                              JacB, IDAB_mem->ida_user_data, 
-                              tmp1B, tmp2B, tmp3B);
-  return(flag);
-}
-
-/*
- * idaDlsBandJacBWrapper
- *
- * This routine interfaces to the IDABandJacFnB routine provided 
- * by the user. idaDlsBandJacBWrapper is of type IDADlsBandJacFn.
- * NOTE: data actually contains ida_mem
- */
-
-static int idaDlsBandJacBWrapper(long int NeqB, long int mupperB, long int mlowerB, 
-                                 realtype tt, realtype c_jB, 
-                                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                                 DlsMat JacB, void *ida_mem, 
-                                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
-{
-  IDAadjMem IDAADJ_mem;
-  IDAMem IDA_mem;
-  IDABMem IDAB_mem;
-  IDADlsMemB idadlsB_mem;
-  int flag;
-
-  IDA_mem = (IDAMem) ida_mem;
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEMB_NULL, 
+                    "IDASDLS", "idaDlsJacBWrapper", MSGD_LMEMB_NULL);
+    return(IDADLS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
   
   /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_LMEMB_NULL, 
+                    "IDASDLS", "idaDlsJacBWrapper", MSGD_LMEMB_NULL);
+    return(IDADLS_LMEMB_NULL);
+  }
   idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
 
   /* Forward solution from interpolation */
-  if (noInterp == FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+  if (IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASDLS", "idaDlsBandJacBWrapper", MSGD_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASDLS",
+                      "idaDlsJacBWrapper", MSGD_BAD_T);
       return(-1);
     }
   }
 
-  /* Call user's adjoint band bjacB routine */
-  flag = idadlsB_mem->d_bjacB(NeqB, mupperB, mlowerB, 
-                              tt, c_jB,
-                              yyTmp, ypTmp, 
-                              yyB, ypB, rrB,
-                              JacB, IDAB_mem->ida_user_data, 
-                              tmp1B, tmp2B, tmp3B);
+  /* Call user's adjoint jacB routine */
+  flag = idadlsB_mem->jacB(tt, c_jB, IDAADJ_mem->ia_yyTmp,
+                           IDAADJ_mem->ia_ypTmp, yyB, ypB,
+                           rrB, JacB, IDAB_mem->ida_user_data, 
+                           tmp1B, tmp2B, tmp3B);
   return(flag);
 }
 
-/*
- * idaDlsBandJacBSWrapper
- *
- * This routine interfaces to the IDABandJacFnBS routine provided 
- * by the user. idaDlsBandJacBSWrapper is of type IDADlsBandJacFn.
- * NOTE: data actually contains ida_mem
- */
-
-static int idaDlsBandJacBSWrapper(long int NeqB, long int mupperB, long int mlowerB, 
-                                 realtype tt, realtype c_jB, 
-                                 N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                                 DlsMat JacB, void *ida_mem, 
-                                 N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+/*---------------------------------------------------------------
+  idaDlsJacBSWrapper
+ 
+  This routine interfaces to the IDAJacFnBS routine provided 
+  by the user. idaDlsJacBSWrapper is of type IDADlsJacFn.
+  NOTE: data actually contains ida_mem
+  ---------------------------------------------------------------*/
+static int idaDlsJacBSWrapper(realtype tt, realtype c_jB, N_Vector yyB,
+                              N_Vector ypB, N_Vector rrB, SUNMatrix JacB,
+                              void *ida_mem, N_Vector tmp1B,
+                              N_Vector tmp2B, N_Vector tmp3B)
 {
   IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
@@ -1010,35 +1133,61 @@ static int idaDlsBandJacBSWrapper(long int NeqB, long int mupperB, long int mlow
   IDADlsMemB idadlsB_mem;
   int flag;
 
+  /* Is ida_mem allright? */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASDLS",
+                    "idaDlsJacBSWrapper", MSGD_CAMEM_NULL);
+    return(IDADLS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASDLS",
+                    "idaDlsJacBSWrapper",  MSGD_NO_ADJ);
+    return(IDADLS_NO_ADJ);
+  }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDADLS_LMEMB_NULL, 
+                    "IDASDLS", "idaDlsJacBSWrapper", MSGD_LMEMB_NULL);
+    return(IDADLS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
   
   /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_LMEMB_NULL, 
+                    "IDASDLS", "idaDlsJacBSWrapper", MSGD_LMEMB_NULL);
+    return(IDADLS_LMEMB_NULL);
+  }
   idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
 
   /* Get forward solution from interpolation. */
-  if( noInterp == FALSE) {
-    if (interpSensi)
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, yySTmp, ypSTmp);
+  if( IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    if (IDAADJ_mem->ia_interpSensi)
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp, IDAADJ_mem->ia_yySTmp,
+                                 IDAADJ_mem->ia_ypSTmp);
     else
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp, NULL, NULL);
   
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASDLS", "idaDlsBandJacBSWrapper", MSGD_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASDLS",
+                      "idaDlsJacBSWrapper", MSGD_BAD_T);
       return(-1);
     }
   }
 
-  /* Call user's adjoint band bjacBS routine */
-  flag = idadlsB_mem->d_bjacBS(NeqB, mupperB, mlowerB, 
-                              tt, c_jB,
-                              yyTmp, ypTmp, yySTmp, ypSTmp, 
-                              yyB, ypB, rrB,
-                              JacB, IDAB_mem->ida_user_data, 
-                              tmp1B, tmp2B, tmp3B);
+  /* Call user's adjoint jacBS routine */
+  flag = idadlsB_mem->jacBS(tt, c_jB, IDAADJ_mem->ia_yyTmp,
+                            IDAADJ_mem->ia_ypTmp, IDAADJ_mem->ia_yySTmp,
+                            IDAADJ_mem->ia_ypSTmp, yyB, ypB, rrB, 
+                            JacB, IDAB_mem->ida_user_data, 
+                            tmp1B, tmp2B, tmp3B);
   return(flag);
 }
 
diff --git a/src/idas/idas_direct_impl.h b/src/idas/idas_direct_impl.h
index 8898560..8a7d9ec 100644
--- a/src/idas/idas_direct_impl.h
+++ b/src/idas/idas_direct_impl.h
@@ -1,135 +1,126 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Implementation header file for the IDADLS linear solvers.
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Implementation header file for the IDADLS linear solver 
+ * interface
+ *-----------------------------------------------------------------*/
 
 #ifndef _IDASDLS_IMPL_H
 #define _IDASDLS_IMPL_H
 
 #include <idas/idas_direct.h>
+#include "idas_impl.h"
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * =================================================================
- * I D A S D I R E C T    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDADlsMemRec, IDADlsMem                             
- * -----------------------------------------------------------------
- * IDADlsMem is pointer to a IDADlsMemRec structure.
- * -----------------------------------------------------------------
- */
+/*=================================================================
+  PART I:  Forward Problems
+  =================================================================*/
 
-typedef struct IDADlsMemRec {
-
-  int d_type;               /* Type of Jacobians (DENSE or BAND)             */
+/*-----------------------------------------------------------------
+  Types : IDADlsMemRec, IDADlsMem                             
 
-  long int d_n;             /* problem dimension                             */
+  IDADlsMem is pointer to a IDADlsMemRec structure.
+  -----------------------------------------------------------------*/
+typedef struct IDADlsMemRec {
 
-  long int d_ml;            /* b_ml = lower bandwidth of savedJ              */
-  long int d_mu;            /* b_mu = upper bandwidth of savedJ              */ 
-  long int d_smu;           /* upper bandwith of M = MIN(N-1,b_mu+b_ml)      */
+  booleantype jacDQ;    /* SUNTRUE if using internal DQ Jacobian approx.  */
+  IDADlsJacFn jac;      /* dense Jacobian routine to be called            */
+  void *J_data;         /* J_data is passed to jac                        */
 
-  booleantype d_jacDQ;      /* TRUE if using internal DQ Jacobian approx.    */
-  IDADlsDenseJacFn d_djac;  /* dense Jacobian routine to be called           */
-  IDADlsBandJacFn d_bjac;   /* band Jacobian routine to be called            */
-  void *d_J_data;           /* J_data is passed to djac or bjac              */
+  SUNLinearSolver LS;   /* generic direct linear solver object            */
 
-  DlsMat d_J;               /* J = dF/dy + cj*dF/dy'                         */
+  SUNMatrix J;          /* J = dF/dy + cj*dF/dy'                          */
 
-  int *d_pivots;            /* pivots = int pivot array for PM = LU          */
-  long int *d_lpivots;      /* lpivots = long int pivot array for PM = LU    */
+  N_Vector x;           /* solution vector used by SUNLinearSolver        */
   
-  long int d_nje;           /* nje = no. of calls to jac                     */
+  long int nje;         /* nje = no. of calls to jac                      */
 
-  long int d_nreDQ;         /* no. of calls to res due to DQ Jacobian approx.*/
+  long int nreDQ;       /* no. of calls to res due to DQ Jacobian approx. */
 
-  long int d_last_flag;     /* last error return flag                        */
+  long int last_flag;   /* last error return flag                         */
   
 } *IDADlsMem;
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
+/*---------------------------------------------------------------
+  Prototypes of internal functions
+  ---------------------------------------------------------------*/
   
-int idaDlsDenseDQJac(long int N, realtype tt, realtype c_j,
-                     N_Vector yy, N_Vector yp, N_Vector rr, 
-                     DlsMat Jac, void *data,
-                     N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-  
-int idaDlsBandDQJac(long int N, long int mupper, long int mlower,
-                    realtype tt, realtype c_j, 
-                    N_Vector yy, N_Vector yp, N_Vector rr,
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
+/* difference-quotient Jacobian approximation routines */
+int idaDlsDQJac(realtype tt, realtype c_j, N_Vector yy, 
+                N_Vector yp, N_Vector rr, SUNMatrix Jac, 
+                void *data, N_Vector tmp1, N_Vector tmp2, 
+                N_Vector tmp3);
+int idaDlsDenseDQJac(realtype tt, realtype c_j, N_Vector yy, 
+                     N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                     IDAMem IDA_mem, N_Vector tmp1);
+ int idaDlsBandDQJac(realtype tt, realtype c_j, N_Vector yy,
+                     N_Vector yp, N_Vector rr, SUNMatrix Jac,
+                    IDAMem IDA_mem, N_Vector tmp1,
+                    N_Vector tmp2, N_Vector tmp3);
+
+/* generic linit/lsetup/lsolve/lfree interface routines for IDA to call */
+int idaDlsInitialize(IDAMem IDA_mem);
+
+int idaDlsSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
+                N_Vector resp, N_Vector vtemp1,
+                N_Vector vtemp2, N_Vector vtemp3); 
+
+int idaDlsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                N_Vector ycur, N_Vector ypcur, N_Vector rescur);
+
+int idaDlsFree(IDAMem IDA_mem);
 
 /* Auxilliary functions */
-
 int idaDlsInitializeCounters(IDADlsMem idadls_mem);
 
 
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDADlsMemRecB, IDADlsMemB       
- * -----------------------------------------------------------------
- * An IDADLS linear solver's specification function attaches such
- * a structure to the lmemB filed of IDABMem
- * -----------------------------------------------------------------
- */
-
+  
+/*=================================================================
+  PART II:  Backward Problems
+  =================================================================*/
+
+/*-----------------------------------------------------------------
+  Types : IDADlsMemRecB, IDADlsMemB       
+  -----------------------------------------------------------------
+  An IDADLS linear solver's specification function attaches such
+  a structure to the lmemB filed of IDABMem
+  -----------------------------------------------------------------*/
 typedef struct IDADlsMemRecB {
 
-  int d_typeB;
+  IDADlsJacFnB jacB;
+  IDADlsJacFnBS jacBS;
+  
+} *IDADlsMemB;
+
 
-  IDADlsDenseJacFnB d_djacB;
-  IDADlsDenseJacFnBS d_djacBS;
-  IDADlsBandJacFnB d_bjacB;
-  IDADlsBandJacFnBS d_bjacBS;
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
 
-} *IDADlsMemB;
+int idaDlsFreeB(IDABMem IDAB_mem);
 
 
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
+/*=================================================================
+  Error Messages
+  =================================================================*/
 
 #define MSGD_IDAMEM_NULL "Integrator memory is NULL."
 #define MSGD_BAD_NVECTOR "A required vector operation is not implemented."
@@ -137,6 +128,7 @@ typedef struct IDADlsMemRecB {
 #define MSGD_MEM_FAIL "A memory request failed."
 #define MSGD_LMEM_NULL "Linear solver memory is NULL."
 #define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
+#define MSGD_MATZERO_FAILED "The SUNMatZero routine failed in an unrecoverable manner."
 
 #define MSGD_CAMEM_NULL "idaadj_mem = NULL illegal."
 #define MSGD_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
diff --git a/src/idas/idas_ic.c b/src/idas/idas_ic.c
index f854b65..1332fb3 100644
--- a/src/idas/idas_ic.c
+++ b/src/idas/idas_ic.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4539 $
- * $Date: 2015-09-16 15:39:33 -0700 (Wed, 16 Sep 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmers: Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -26,9 +26,6 @@
 #include "idas_impl.h"
 #include <sundials/sundials_math.h>
 
-/* Macro: loop */
-#define loop for(;;)
-
 /*
  * =================================================================
  * IDA Constants 
@@ -91,71 +88,6 @@ static int IDASensNlsIC(IDAMem IDA_mem);
 
 static int IDAICFailFlag(IDAMem IDA_mem, int retval);
 
-/*
- * =================================================================
- * Readibility Constants
- * =================================================================
- */
-
-#define t0             (IDA_mem->ida_t0)
-#define yy0            (IDA_mem->ida_yy0)
-#define yp0            (IDA_mem->ida_yp0)
-
-#define user_data      (IDA_mem->ida_user_data)
-#define res            (IDA_mem->ida_res)
-#define efun           (IDA_mem->ida_efun)
-#define edata          (IDA_mem->ida_edata)
-#define uround         (IDA_mem->ida_uround)  
-#define phi            (IDA_mem->ida_phi) 
-#define ewt            (IDA_mem->ida_ewt)  
-#define delta          (IDA_mem->ida_delta)
-#define ee             (IDA_mem->ida_ee)
-#define savres         (IDA_mem->ida_savres)
-#define tempv2         (IDA_mem->ida_tempv2) 
-#define hh             (IDA_mem->ida_hh)
-#define tn             (IDA_mem->ida_tn)
-#define cj             (IDA_mem->ida_cj)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define nbacktr        (IDA_mem->ida_nbacktr)
-#define maxbacks       (IDA_mem->ida_maxbacks)
-#define nre            (IDA_mem->ida_nre)
-#define ncfn           (IDA_mem->ida_ncfn)
-#define nni            (IDA_mem->ida_nni)
-#define nsetups        (IDA_mem->ida_nsetups)
-#define ns             (IDA_mem->ida_ns)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve) 
-#define hused          (IDA_mem->ida_hused)         
-#define epsNewt        (IDA_mem->ida_epsNewt)
-#define id             (IDA_mem->ida_id)
-#define setupNonNull   (IDA_mem->ida_setupNonNull) 
-#define suppressalg    (IDA_mem->ida_suppressalg)
-#define constraints    (IDA_mem->ida_constraints)
-#define constraintsSet (IDA_mem->ida_constraintsSet)
-
-#define epiccon        (IDA_mem->ida_epiccon)
-#define maxnh          (IDA_mem->ida_maxnh)
-#define maxnj          (IDA_mem->ida_maxnj)
-#define maxnit         (IDA_mem->ida_maxnit)
-#define lsoff          (IDA_mem->ida_lsoff)
-#define steptol        (IDA_mem->ida_steptol)
-
-#define sensi          (IDA_mem->ida_sensi)
-#define Ns             (IDA_mem->ida_Ns)
-#define resS           (IDA_mem->ida_resS)
-#define phiS           (IDA_mem->ida_phiS)
-#define ism            (IDA_mem->ida_ism)
-#define ewtS           (IDA_mem->ida_ewtS)
-#define ncfnS          (IDA_mem->ida_ncfnS)
-#define nniS           (IDA_mem->ida_nniS)
-#define nsetupsS       (IDA_mem->ida_nsetupsS)
-#define yyS0           (IDA_mem->ida_yyS0)
-#define ypS0           (IDA_mem->ida_ypS0)
-#define delnewS        (IDA_mem->ida_delnewS)
-#define savresS        (IDA_mem->ida_savresS)
-#define yyS0new        (IDA_mem->ida_yyS0new)
-#define ypS0new        (IDA_mem->ida_ypS0new)
-#define eeS            (IDA_mem->ida_eeS)
 
 /*
  * =================================================================
@@ -210,7 +142,7 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   /* Check if problem was malloc'ed */
   
-  if(IDA_mem->ida_MallocDone == FALSE) {
+  if(IDA_mem->ida_MallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_MALLOC, "IDAS", "IDACalcIC", MSG_NO_MALLOC);
     return(IDA_NO_MALLOC);
   }
@@ -219,7 +151,7 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   ier = IDAInitialSetup(IDA_mem);
   if(ier != IDA_SUCCESS) return(IDA_ILL_INPUT);
-  IDA_mem->ida_SetupDone = TRUE;
+  IDA_mem->ida_SetupDone = SUNTRUE;
 
   /* Check legality of input arguments, and set IDA memory copies. */
 
@@ -229,47 +161,47 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
   }
   IDA_mem->ida_icopt = icopt;
 
-  if(icopt == IDA_YA_YDP_INIT && (id == NULL)) {
+  if(icopt == IDA_YA_YDP_INIT && (IDA_mem->ida_id == NULL)) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDACalcIC", MSG_IC_MISSING_ID);
     return(IDA_ILL_INPUT);
   }
 
-  tdist = SUNRabs(tout1 - tn);
-  troundoff = TWO*uround*(SUNRabs(tn) + SUNRabs(tout1));
+  tdist = SUNRabs(tout1 - IDA_mem->ida_tn);
+  troundoff = TWO * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(tout1));
   if(tdist < troundoff) {
     IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDACalcIC", MSG_IC_TOO_CLOSE);
     return(IDA_ILL_INPUT);
   }
 
   /* Are we computing sensitivities? */
-  sensi_stg  = (sensi && (ism==IDA_STAGGERED));
-  sensi_sim  = (sensi && (ism==IDA_SIMULTANEOUS));
+  sensi_stg  = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_STAGGERED));
+  sensi_sim  = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS));
 
   /* Allocate space and initialize temporary vectors */
 
-  yy0 = N_VClone(ee);
-  yp0 = N_VClone(ee);
-  t0  = tn;
-  N_VScale(ONE, phi[0], yy0);
-  N_VScale(ONE, phi[1], yp0);
+  IDA_mem->ida_yy0 = N_VClone(IDA_mem->ida_ee);
+  IDA_mem->ida_yp0 = N_VClone(IDA_mem->ida_ee);
+  IDA_mem->ida_t0  = IDA_mem->ida_tn;
+  N_VScale(ONE, IDA_mem->ida_phi[0], IDA_mem->ida_yy0);
+  N_VScale(ONE, IDA_mem->ida_phi[1], IDA_mem->ida_yp0);
 
-  if (sensi) {
+  if (IDA_mem->ida_sensi) {
 
     /* Allocate temporary space required for sensitivity IC: yyS0 and ypS0. */      
-    yyS0 = N_VCloneVectorArray(Ns, ee);
-    ypS0 = N_VCloneVectorArray(Ns, ee);
+    IDA_mem->ida_yyS0 = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_ee);
+    IDA_mem->ida_ypS0 = N_VCloneVectorArray(IDA_mem->ida_Ns, IDA_mem->ida_ee);
     
     /* Initialize sensitivity vector. */
-    for (is=0; is<Ns; is++) {
-      N_VScale(ONE, phiS[0][is], yyS0[is]);  
-      N_VScale(ONE, phiS[1][is], ypS0[is]);  
+    for (is=0; is<IDA_mem->ida_Ns; is++) {
+      N_VScale(ONE, IDA_mem->ida_phiS[0][is], IDA_mem->ida_yyS0[is]);  
+      N_VScale(ONE, IDA_mem->ida_phiS[1][is], IDA_mem->ida_ypS0[is]);  
     }
     
     /* Initialize work space vectors needed for sensitivities. */
-    savresS = phiS[2];
-    delnewS = phiS[3];
-    yyS0new = phiS[4];
-    ypS0new = eeS;
+    IDA_mem->ida_savresS = IDA_mem->ida_phiS[2];
+    IDA_mem->ida_delnewS = IDA_mem->ida_phiS[3];
+    IDA_mem->ida_yyS0new = IDA_mem->ida_phiS[4];
+    IDA_mem->ida_ypS0new = IDA_mem->ida_eeS;
   }
 
   /* For use in the IDA_YA_YP_INIT case, set sysindex and tscale. */
@@ -277,7 +209,7 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
   IDA_mem->ida_sysindex = 1;
   IDA_mem->ida_tscale   = tdist;
   if(icopt == IDA_YA_YDP_INIT) {
-    minid = N_VMin(id);
+    minid = N_VMin(IDA_mem->ida_id);
     if(minid < ZERO) {
       IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDACalcIC", MSG_IC_BAD_ID);
       return(IDA_ILL_INPUT);
@@ -287,32 +219,32 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   /* Set the test constant in the Newton convergence test */
 
-  IDA_mem->ida_epsNewt = epiccon;
+  IDA_mem->ida_epsNewt = IDA_mem->ida_epiccon;
 
   /* Initializations: 
      cjratio = 1 (for use in direct linear solvers); 
      set nbacktr = 0; */
 
-  cjratio = ONE;
-  nbacktr = 0;
+  IDA_mem->ida_cjratio = ONE;
+  IDA_mem->ida_nbacktr = 0;
 
   /* Set hic, hh, cj, and mxnh. */
 
   hic = PT001*tdist;
-  ypnorm = IDAWrmsNorm(IDA_mem, yp0, ewt, suppressalg);
+  ypnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_yp0, IDA_mem->ida_ewt, IDA_mem->ida_suppressalg);
 
   if (sensi_sim) 
-    ypnorm = IDASensWrmsNormUpdate(IDA_mem, ypnorm, ypS0, ewtS, FALSE);
+    ypnorm = IDASensWrmsNormUpdate(IDA_mem, ypnorm, IDA_mem->ida_ypS0, IDA_mem->ida_ewtS, SUNFALSE);
 
   if(ypnorm > HALF/hic) hic = HALF/ypnorm;
-  if(tout1 < tn) hic = -hic;
-  hh = hic;
+  if(tout1 < IDA_mem->ida_tn) hic = -hic;
+  IDA_mem->ida_hh = hic;
   if(icopt == IDA_YA_YDP_INIT) {
-    cj = ONE/hic;
-    mxnh = maxnh;
+    IDA_mem->ida_cj = ONE/hic;
+    mxnh = IDA_mem->ida_maxnh;
   }
   else {
-    cj = ZERO;
+    IDA_mem->ida_cj = ZERO;
     mxnh = 1;
   }
 
@@ -328,54 +260,54 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
       /* Cut h and loop on recoverable IDA_YA_YDP_INIT failure; else break. */
       if(retval == IDA_SUCCESS) break;
-      ncfn++;
+      IDA_mem->ida_ncfn++;
       if(retval < 0) break;
       if(nh == mxnh) break;
 
       /* If looping to try again, reset yy0 and yp0 if not converging. */
       if(retval != IC_SLOW_CONVRG) {
-        N_VScale(ONE, phi[0], yy0);
-        N_VScale(ONE, phi[1], yp0);
+        N_VScale(ONE, IDA_mem->ida_phi[0], IDA_mem->ida_yy0);
+        N_VScale(ONE, IDA_mem->ida_phi[1], IDA_mem->ida_yp0);
         if (sensi_sim) {
 
           /* Reset yyS0 and ypS0. */
           /* Copy phiS[0] and phiS[1] into yyS0 and ypS0. */
-          for (is=0; is<Ns; is++) {
-            N_VScale(ONE, phiS[0][is], yyS0[is]);         
-            N_VScale(ONE, phiS[1][is], ypS0[is]);         
+          for (is=0; is<IDA_mem->ida_Ns; is++) {
+            N_VScale(ONE, IDA_mem->ida_phiS[0][is], IDA_mem->ida_yyS0[is]);         
+            N_VScale(ONE, IDA_mem->ida_phiS[1][is], IDA_mem->ida_ypS0[is]);         
           }
         }
       }
       hic *= PT1;
-      cj = ONE/hic;
-      hh = hic;
+      IDA_mem->ida_cj = ONE/hic;
+      IDA_mem->ida_hh = hic;
     }   /* End of nh loop */
 
     /* Break on failure */
     if(retval != IDA_SUCCESS) break;
     
     /* Reset ewt, save yy0, yp0 in phi, and loop. */
-    ewtsetOK = efun(yy0, ewt, edata);
+    ewtsetOK = IDA_mem->ida_efun(IDA_mem->ida_yy0, IDA_mem->ida_ewt, IDA_mem->ida_edata);
     if(ewtsetOK != 0) { 
       retval = IDA_BAD_EWT; 
       break; 
     }
-    N_VScale(ONE, yy0, phi[0]);
-    N_VScale(ONE, yp0, phi[1]);
+    N_VScale(ONE, IDA_mem->ida_yy0, IDA_mem->ida_phi[0]);
+    N_VScale(ONE, IDA_mem->ida_yp0, IDA_mem->ida_phi[1]);
     
     if (sensi_sim) {
       
       /* Reevaluate ewtS. */
-      ewtsetOK = IDASensEwtSet(IDA_mem, yyS0, ewtS);
+      ewtsetOK = IDASensEwtSet(IDA_mem, IDA_mem->ida_yyS0, IDA_mem->ida_ewtS);
       if(ewtsetOK != 0) { 
         retval = IDA_BAD_EWT; 
         break; 
       }
       
       /* Save yyS0 and ypS0. */
-      for (is=0; is<Ns; is++) {
-            N_VScale(ONE, yyS0[is], phiS[0][is]);         
-            N_VScale(ONE, ypS0[is], phiS[1][is]);        
+      for (is=0; is<IDA_mem->ida_Ns; is++) {
+            N_VScale(ONE, IDA_mem->ida_yyS0[is], IDA_mem->ida_phiS[0][is]);         
+            N_VScale(ONE, IDA_mem->ida_ypS0[is], IDA_mem->ida_phiS[1][is]);        
       }
     }
 
@@ -383,17 +315,17 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   /* Load the optional outputs. */
 
-  if(icopt == IDA_YA_YDP_INIT)   hused = hic;
+  if(icopt == IDA_YA_YDP_INIT)   IDA_mem->ida_hused = hic;
 
   /* On any failure, free memory, print error message and return */
 
   if(retval != IDA_SUCCESS) {
-    N_VDestroy(yy0);
-    N_VDestroy(yp0);
+    N_VDestroy(IDA_mem->ida_yy0);
+    N_VDestroy(IDA_mem->ida_yp0);
 
-    if(sensi) {
-      N_VDestroyVectorArray(yyS0, Ns);
-      N_VDestroyVectorArray(ypS0, Ns);
+    if(IDA_mem->ida_sensi) {
+      N_VDestroyVectorArray(IDA_mem->ida_yyS0, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_ypS0, IDA_mem->ida_Ns);
     }
 
     icret = IDAICFailFlag(IDA_mem, retval);
@@ -404,12 +336,12 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
 
   if (!sensi_stg) {
 
-    N_VDestroy(yy0);
-    N_VDestroy(yp0);
+    N_VDestroy(IDA_mem->ida_yy0);
+    N_VDestroy(IDA_mem->ida_yp0);
 
-    if(sensi) {
-      N_VDestroyVectorArray(yyS0, Ns);
-      N_VDestroyVectorArray(ypS0, Ns);
+    if(IDA_mem->ida_sensi) {
+      N_VDestroyVectorArray(IDA_mem->ida_yyS0, IDA_mem->ida_Ns);
+      N_VDestroyVectorArray(IDA_mem->ida_ypS0, IDA_mem->ida_Ns);
     }
 
     return(IDA_SUCCESS);
@@ -422,8 +354,10 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
      If res() fails recoverably, treat it as a convergence failure and 
      attempt the step again */
         
-  retval = res(t0, yy0, yp0, delta, user_data);
-  nre++;
+  retval = IDA_mem->ida_res(IDA_mem->ida_t0, IDA_mem->ida_yy0,
+                            IDA_mem->ida_yp0, IDA_mem->ida_delta,
+                            IDA_mem->ida_user_data);
+  IDA_mem->ida_nre++;
   if(retval < 0) 
     /* res function failed unrecoverably. */
     return(IDA_RES_FAIL);
@@ -442,21 +376,21 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
       if(retval == IDA_SUCCESS) break;
 
       /* Increment the number of the sensitivity related corrector convergence failures. */
-      ncfnS++;
+      IDA_mem->ida_ncfnS++;
 
       if(retval < 0) break;
       if(nh == mxnh) break;
 
       /* If looping to try again, reset yyS0 and ypS0 if not converging. */
       if(retval != IC_SLOW_CONVRG) {
-        for (is=0; is<Ns; is++) {
-          N_VScale(ONE, phiS[0][is], yyS0[is]);  
-          N_VScale(ONE, phiS[1][is], ypS0[is]);  
+        for (is=0; is<IDA_mem->ida_Ns; is++) {
+          N_VScale(ONE, IDA_mem->ida_phiS[0][is], IDA_mem->ida_yyS0[is]);  
+          N_VScale(ONE, IDA_mem->ida_phiS[1][is], IDA_mem->ida_ypS0[is]);  
         }
       }
       hic *= PT1;
-      cj = ONE/hic;
-      hh = hic;
+      IDA_mem->ida_cj = ONE/hic;
+      IDA_mem->ida_hh = hic;
         
     }   /* End of nh loop */
 
@@ -468,31 +402,31 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
        maybe correct the  new sensitivities IC with respect to the new weights. */
     
     /* Reevaluate ewtS. */
-    ewtsetOK = IDASensEwtSet(IDA_mem, yyS0, ewtS);
+    ewtsetOK = IDASensEwtSet(IDA_mem, IDA_mem->ida_yyS0, IDA_mem->ida_ewtS);
     if(ewtsetOK != 0) { 
       retval = IDA_BAD_EWT; 
       break; 
     }
 
     /* Save yyS0 and ypS0. */
-    for (is=0; is<Ns; is++) {
-      N_VScale(ONE, yyS0[is], phiS[0][is]);         
-      N_VScale(ONE, ypS0[is], phiS[1][is]);        
+    for (is=0; is<IDA_mem->ida_Ns; is++) {
+      N_VScale(ONE, IDA_mem->ida_yyS0[is], IDA_mem->ida_phiS[0][is]);         
+      N_VScale(ONE, IDA_mem->ida_ypS0[is], IDA_mem->ida_phiS[1][is]);        
     }
 
   }   /* End of nwt loop */
 
 
   /* Load the optional outputs. */
-  if(icopt == IDA_YA_YDP_INIT)   hused = hic;
+  if(icopt == IDA_YA_YDP_INIT)   IDA_mem->ida_hused = hic;
 
   /* Free temporary space */
-  N_VDestroy(yy0);
-  N_VDestroy(yp0);
+  N_VDestroy(IDA_mem->ida_yy0);
+  N_VDestroy(IDA_mem->ida_yp0);
 
-  /* Here sensi is TRUE, so deallocate sensitivity temporary vectors. */
-  N_VDestroyVectorArray(yyS0, Ns);
-  N_VDestroyVectorArray(ypS0, Ns);
+  /* Here sensi is SUNTRUE, so deallocate sensitivity temporary vectors. */
+  N_VDestroyVectorArray(IDA_mem->ida_yyS0, IDA_mem->ida_Ns);
+  N_VDestroyVectorArray(IDA_mem->ida_ypS0, IDA_mem->ida_Ns);
 
 
   /* On any failure, print message and return proper flag. */
@@ -513,22 +447,6 @@ int IDACalcIC(void *ida_mem, int icopt, realtype tout1)
  * =================================================================
  */
 
-#define icopt          (IDA_mem->ida_icopt)
-#define sysindex       (IDA_mem->ida_sysindex)
-#define tscale         (IDA_mem->ida_tscale)
-#define ynew           (IDA_mem->ida_ynew)
-#define ypnew          (IDA_mem->ida_ypnew)
-#define delnew         (IDA_mem->ida_delnew)
-#define dtemp          (IDA_mem->ida_dtemp)
-
-#define user_dataS     (IDA_mem->ida_user_dataS)
-#define deltaS         (IDA_mem->ida_deltaS)
-
-#define tmpS1          (IDA_mem->ida_tmpS1)
-#define tmpS2          (IDA_mem->ida_tmpS2)
-#define tmpS3          (IDA_mem->ida_tmpS3)
-
-#define nrSe           (IDA_mem->ida_nrSe)
 /*
  * -----------------------------------------------------------------
  * IDANlsIC
@@ -561,43 +479,50 @@ static int IDANlsIC(IDAMem IDA_mem)
   booleantype sensi_sim;
 
   /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
-  sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+  sensi_sim = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS));
 
-  tv1 = ee;
-  tv2 = tempv2;
-  tv3 = phi[2];
+  tv1 = IDA_mem->ida_ee;
+  tv2 = IDA_mem->ida_tempv2;
+  tv3 = IDA_mem->ida_phi[2];
   
   /* Evaluate RHS. */
-  retval = res(t0, yy0, yp0, delta, user_data);
-  nre++;
+  retval = IDA_mem->ida_res(IDA_mem->ida_t0, IDA_mem->ida_yy0, IDA_mem->ida_yp0,
+                            IDA_mem->ida_delta, IDA_mem->ida_user_data);
+  IDA_mem->ida_nre++;
   if(retval < 0) return(IDA_RES_FAIL);
   if(retval > 0) return(IDA_FIRST_RES_FAIL);
 
   /* Save the residual. */
-  N_VScale(ONE, delta, savres);
+  N_VScale(ONE, IDA_mem->ida_delta, IDA_mem->ida_savres);
 
   if(sensi_sim) {
     
     /*Evaluate sensitivity RHS and save it in savresS. */
-    retval = resS(Ns, t0, 
-                  yy0, yp0, delta,
-                  yyS0, ypS0, deltaS,
-                  user_dataS, tmpS1, tmpS2, tmpS3);
-    nrSe++;
+    retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_t0, 
+                               IDA_mem->ida_yy0, IDA_mem->ida_yp0,
+                               IDA_mem->ida_delta,
+                               IDA_mem->ida_yyS0, IDA_mem->ida_ypS0,
+                               IDA_mem->ida_deltaS,
+                               IDA_mem->ida_user_dataS,
+                               IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2,
+                               IDA_mem->ida_tmpS3);
+    IDA_mem->ida_nrSe++;
     if(retval < 0) return(IDA_RES_FAIL);
     if(retval > 0) return(IDA_FIRST_RES_FAIL);
 
-    for(is=0; is<Ns; is++)
-      N_VScale(ONE, deltaS[is], savresS[is]);
+    for(is=0; is<IDA_mem->ida_Ns; is++)
+      N_VScale(ONE, IDA_mem->ida_deltaS[is], IDA_mem->ida_savresS[is]);
   }
 
   /* Loop over nj = number of linear solve Jacobian setups. */
-  for(nj = 1; nj <= maxnj; nj++) {
+  for(nj = 1; nj <= IDA_mem->ida_maxnj; nj++) {
 
     /* If there is a setup routine, call it. */
-    if(setupNonNull) {
-      nsetups++;
-      retval = lsetup(IDA_mem, yy0, yp0, delta, tv1, tv2, tv3);
+    if(IDA_mem->ida_lsetup) {
+      IDA_mem->ida_nsetups++;
+      retval = IDA_mem->ida_lsetup(IDA_mem, IDA_mem->ida_yy0,
+                                   IDA_mem->ida_yp0, IDA_mem->ida_delta,
+                                   tv1, tv2, tv3);
       if(retval < 0) return(IDA_LSETUP_FAIL);
       if(retval > 0) return(IC_FAIL_RECOV);
     }
@@ -607,12 +532,12 @@ static int IDANlsIC(IDAMem IDA_mem)
     if(retval == IDA_SUCCESS) return(IDA_SUCCESS);
 
     /* If converging slowly and lsetup is nontrivial, retry. */
-    if(retval == IC_SLOW_CONVRG && setupNonNull) {
-      N_VScale(ONE, savres, delta);
+    if(retval == IC_SLOW_CONVRG && IDA_mem->ida_lsetup) {
+      N_VScale(ONE, IDA_mem->ida_savres, IDA_mem->ida_delta);
 
       if(sensi_sim)
-        for(is=0; is<Ns; is++)
-          N_VScale(ONE, savresS[is], deltaS[is]);
+        for(is=0; is<IDA_mem->ida_Ns; is++)
+          N_VScale(ONE, IDA_mem->ida_savresS[is], IDA_mem->ida_deltaS[is]);
 
       continue;
     } else {
@@ -658,33 +583,39 @@ static int IDANewtonIC(IDAMem IDA_mem)
   booleantype sensi_sim;
 
   /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
-  sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+  sensi_sim = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS));
 
   /* Set pointer for vector delnew */
-  delnew = phi[2];
+  IDA_mem->ida_delnew = IDA_mem->ida_phi[2];
 
   /* Call the linear solve function to get the Newton step, delta. */
-  retval = lsolve(IDA_mem, delta, ewt, yy0, yp0, savres);
+  retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delta,
+                               IDA_mem->ida_ewt, IDA_mem->ida_yy0,
+                               IDA_mem->ida_yp0, IDA_mem->ida_savres);
   if(retval < 0) return(IDA_LSOLVE_FAIL);
   if(retval > 0) return(IC_FAIL_RECOV);
 
   /* Compute the norm of the step. */
-  fnorm = IDAWrmsNorm(IDA_mem, delta, ewt, FALSE);
+  fnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delta, IDA_mem->ida_ewt, SUNFALSE);
 
   /* Call the lsolve function to get correction vectors deltaS. */
   if (sensi_sim) {
-    for(is=0;is<Ns;is++) {
-      retval = lsolve(IDA_mem, deltaS[is], ewtS[is], yy0, yp0, savres);
+    for(is=0;is<IDA_mem->ida_Ns;is++) {
+      retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_deltaS[is],
+                                   IDA_mem->ida_ewtS[is], IDA_mem->ida_yy0,
+                                   IDA_mem->ida_yp0, IDA_mem->ida_savres);
       if(retval < 0) return(IDA_LSOLVE_FAIL);
       if(retval > 0) return(IC_FAIL_RECOV);
     }
     /* Update the norm of delta. */
-    fnorm = IDASensWrmsNormUpdate(IDA_mem, fnorm, deltaS, ewtS, FALSE);
+    fnorm = IDASensWrmsNormUpdate(IDA_mem, fnorm, IDA_mem->ida_deltaS,
+                                  IDA_mem->ida_ewtS, SUNFALSE);
   }
 
   /* Test for convergence. Return now if the norm is small. */
-  if(sysindex == 0) fnorm *= tscale*SUNRabs(cj);
-  if(fnorm <= epsNewt) return(IDA_SUCCESS);
+  if(IDA_mem->ida_sysindex == 0)
+    fnorm *= IDA_mem->ida_tscale * SUNRabs(IDA_mem->ida_cj);
+  if(fnorm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
   fnorm0 = fnorm;
 
   /* Initialize rate to avoid compiler warning message */
@@ -692,9 +623,9 @@ static int IDANewtonIC(IDAMem IDA_mem)
 
   /* Newton iteration loop */
 
-  for(mnewt = 0; mnewt < maxnit; mnewt++) {
+  for(mnewt = 0; mnewt < IDA_mem->ida_maxnit; mnewt++) {
 
-    nni++;
+    IDA_mem->ida_nni++;
     delnorm = fnorm;
     oldfnrm = fnorm;
 
@@ -704,15 +635,15 @@ static int IDANewtonIC(IDAMem IDA_mem)
 
     /* Set the observed convergence rate and test for convergence. */
     rate = fnorm/oldfnrm;
-    if(fnorm <= epsNewt) return(IDA_SUCCESS);
+    if(fnorm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
 
     /* If not converged, copy new step vector, and loop. */
-    N_VScale(ONE, delnew, delta);
+    N_VScale(ONE, IDA_mem->ida_delnew, IDA_mem->ida_delta);
 
     if(sensi_sim) {
       /* Update the iteration's step for sensitivities. */
-      for(is=0; is<Ns; is++)
-        N_VScale(ONE, delnewS[is], deltaS[is]);
+      for(is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(ONE, IDA_mem->ida_delnewS[is], IDA_mem->ida_deltaS[is]);
     }
 
   }   /* End of Newton iteration loop */
@@ -760,87 +691,90 @@ static int IDALineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm)
 
   /* Initialize work space pointers, f1norm, ratio.
      (Use of mc in constraint check does not conflict with ypnew.) */
-  mc = ee;
-  dtemp = phi[3];
-  ynew = tempv2;
-  ypnew = ee;
+  mc = IDA_mem->ida_ee;
+  IDA_mem->ida_dtemp = IDA_mem->ida_phi[3];
+  IDA_mem->ida_ynew = IDA_mem->ida_tempv2;
+  IDA_mem->ida_ypnew = IDA_mem->ida_ee;
   f1norm = (*fnorm)*(*fnorm)*HALF;
   ratio = ONE;
 
   /* If there are constraints, check and reduce step if necessary. */
-  if(constraintsSet) {
+  if(IDA_mem->ida_constraintsSet) {
 
     /* Update y and check constraints. */
     IDANewy(IDA_mem);
-    conOK = N_VConstrMask(constraints, ynew, mc);
+    conOK = N_VConstrMask(IDA_mem->ida_constraints,
+                          IDA_mem->ida_ynew, mc);
 
     if(!conOK) {
       /* Not satisfied.  Compute scaled step to satisfy constraints. */
-      N_VProd(mc, delta, dtemp);
-      ratio = PT99*N_VMinQuotient(yy0, dtemp);
+      N_VProd(mc, IDA_mem->ida_delta, IDA_mem->ida_dtemp);
+      ratio = PT99*N_VMinQuotient(IDA_mem->ida_yy0, IDA_mem->ida_dtemp);
       (*delnorm) *= ratio;
-      if((*delnorm) <= steptol) return(IC_CONSTR_FAILED);
-      N_VScale(ratio, delta, delta);
+      if((*delnorm) <= IDA_mem->ida_steptol)
+        return(IC_CONSTR_FAILED);
+      N_VScale(ratio, IDA_mem->ida_delta, IDA_mem->ida_delta);
     }
 
   } /* End of constraints check */
 
   slpi = -TWO*f1norm*ratio;
-  minlam = steptol/(*delnorm);
+  minlam = IDA_mem->ida_steptol / (*delnorm);
   lambda = ONE;
   nbacks = 0;
 
   /* Are we computing sensitivities with the IDA_SIMULTANEOUS approach? */
-  sensi_sim = (sensi && (ism==IDA_SIMULTANEOUS));
+  sensi_sim = (IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS));
 
   /* In IDA_Y_INIT case, set ypnew = yp0 (fixed) for linesearch. */
-  if(icopt == IDA_Y_INIT) {
-    N_VScale(ONE, yp0, ypnew);
+  if(IDA_mem->ida_icopt == IDA_Y_INIT) {
+    N_VScale(ONE, IDA_mem->ida_yp0, IDA_mem->ida_ypnew);
 
     /* do the same for sensitivities. */
     if(sensi_sim) {
-      for(is=0; is<Ns; is++)
-        N_VScale(ONE, ypS0[is], ypS0new[is]);
+      for(is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(ONE, IDA_mem->ida_ypS0[is], IDA_mem->ida_ypS0new[is]);
     }
   }
 
   /* Loop on linesearch variable lambda. */
 
-  loop {
+  for(;;) {
 
-    if (nbacks == maxbacks) return(IC_LINESRCH_FAILED);
+    if (nbacks == IDA_mem->ida_maxbacks)
+      return(IC_LINESRCH_FAILED);
     /* Get new (y,y') = (ynew,ypnew) and norm of new function value. */
     IDANewyyp(IDA_mem, lambda);
     retval = IDAfnorm(IDA_mem, &fnormp);
     if(retval != IDA_SUCCESS) return(retval);
 
     /* If lsoff option is on, break out. */
-    if(lsoff) break;
+    if(IDA_mem->ida_lsoff) break;
 
     /* Do alpha-condition test. */
     f1normp = fnormp*fnormp*HALF;
     if(f1normp <= f1norm + ALPHALS*slpi*lambda) break;
     if(lambda < minlam) return(IC_LINESRCH_FAILED);
     lambda /= TWO;
-    nbacktr++; nbacks++;
+    IDA_mem->ida_nbacktr++; nbacks++;
 
   }  /* End of breakout linesearch loop */
 
   /* Update yy0, yp0. */
-  N_VScale(ONE, ynew, yy0);
+  N_VScale(ONE, IDA_mem->ida_ynew, IDA_mem->ida_yy0);
 
   if(sensi_sim) {
     /* Update yyS0 and ypS0. */
-    for(is=0; is<Ns; is++)
-      N_VScale(ONE, yyS0new[is], yyS0[is]);
+    for(is=0; is<IDA_mem->ida_Ns; is++)
+      N_VScale(ONE, IDA_mem->ida_yyS0new[is], IDA_mem->ida_yyS0[is]);
   }
 
-  if(icopt == IDA_YA_YDP_INIT) {
-    N_VScale(ONE, ypnew, yp0);
+  if(IDA_mem->ida_icopt == IDA_YA_YDP_INIT) {
+    N_VScale(ONE, IDA_mem->ida_ypnew, IDA_mem->ida_yp0);
     
     if(sensi_sim)
-      for(is=0; is<Ns; is++)
-        N_VScale(ONE, ypS0new[is], ypS0[is]);
+      for(is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(ONE, IDA_mem->ida_ypS0new[is], IDA_mem->ida_ypS0[is]);
 
   }
   /* Update fnorm, then return. */
@@ -872,53 +806,68 @@ static int IDAfnorm(IDAMem IDA_mem, realtype *fnorm)
   int retval, is;
 
   /* Get residual vector F, return if failed, and save F in savres. */
-  retval = res(t0, ynew, ypnew, delnew, user_data);
-  nre++;
+  retval = IDA_mem->ida_res(IDA_mem->ida_t0, IDA_mem->ida_ynew,
+                            IDA_mem->ida_ypnew, IDA_mem->ida_delnew,
+                            IDA_mem->ida_user_data);
+  IDA_mem->ida_nre++;
   if(retval < 0) return(IDA_RES_FAIL);
   if(retval > 0) return(IC_FAIL_RECOV);
 
-  N_VScale(ONE, delnew, savres);
+  N_VScale(ONE, IDA_mem->ida_delnew, IDA_mem->ida_savres);
 
   /* Call the linear solve function to get J-inverse F; return if failed. */
-  retval = lsolve(IDA_mem, delnew, ewt, ynew, ypnew, savres);
+  retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delnew, IDA_mem->ida_ewt,
+                               IDA_mem->ida_ynew, IDA_mem->ida_ypnew,
+                               IDA_mem->ida_savres);
   if(retval < 0) return(IDA_LSOLVE_FAIL);
   if(retval > 0) return(IC_FAIL_RECOV);
 
   /* Compute the WRMS-norm. */
-  *fnorm = IDAWrmsNorm(IDA_mem, delnew, ewt, FALSE);
+  *fnorm = IDAWrmsNorm(IDA_mem, IDA_mem->ida_delnew, IDA_mem->ida_ewt, SUNFALSE);
 
 
   /* Are we computing SENSITIVITIES with the IDA_SIMULTANEOUS approach? */
 
-  if(sensi && (ism==IDA_SIMULTANEOUS)) {
+  if(IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS)) {
 
     /* Evaluate the residual for sensitivities. */
-    retval = resS(Ns, t0, 
-                  ynew, ypnew, savres,
-                  yyS0new, ypS0new, delnewS,
-                  user_dataS, tmpS1, tmpS2, tmpS3);
-    nrSe++;
+    retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_t0, 
+                               IDA_mem->ida_ynew, IDA_mem->ida_ypnew,
+                               IDA_mem->ida_savres,
+                               IDA_mem->ida_yyS0new,
+                               IDA_mem->ida_ypS0new,
+                               IDA_mem->ida_delnewS,
+                               IDA_mem->ida_user_dataS,
+                               IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2,
+                               IDA_mem->ida_tmpS3);
+    IDA_mem->ida_nrSe++;
     if(retval < 0) return(IDA_RES_FAIL);
     if(retval > 0) return(IC_FAIL_RECOV);
 
     /* Save delnewS in savresS. */
-    for(is=0; is<Ns; is++)
-      N_VScale(ONE, delnewS[is], savresS[is]);
+    for(is=0; is<IDA_mem->ida_Ns; is++)
+      N_VScale(ONE, IDA_mem->ida_delnewS[is], IDA_mem->ida_savresS[is]);
 
     /* Call the linear solve function to get J-inverse deltaS. */
-    for(is=0; is<Ns; is++) {
+    for(is=0; is<IDA_mem->ida_Ns; is++) {
 
-      retval = lsolve(IDA_mem, delnewS[is], ewtS[is], ynew, ypnew, savres);
+      retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delnewS[is],
+                                   IDA_mem->ida_ewtS[is],
+                                   IDA_mem->ida_ynew,
+                                   IDA_mem->ida_ypnew,
+                                   IDA_mem->ida_savres);
       if(retval < 0) return(IDA_LSOLVE_FAIL);
       if(retval > 0) return(IC_FAIL_RECOV);
     }
       
     /* Include sensitivities in norm. */
-    *fnorm = IDASensWrmsNormUpdate(IDA_mem, *fnorm, delnewS, ewtS, FALSE);
+    *fnorm = IDASensWrmsNormUpdate(IDA_mem, *fnorm, IDA_mem->ida_delnewS,
+                                   IDA_mem->ida_ewtS, SUNFALSE);
   }
 
   /* Rescale norm if index = 0. */
-  if(sysindex == 0) (*fnorm) *= tscale*SUNRabs(cj);
+  if(IDA_mem->ida_sysindex == 0)
+    (*fnorm) *= IDA_mem->ida_tscale * SUNRabs(IDA_mem->ida_cj);
 
   return(IDA_SUCCESS);
 
@@ -944,20 +893,24 @@ static int IDANewyyp(IDAMem IDA_mem, realtype lambda)
 
   /* IDA_YA_YDP_INIT case: ynew  = yy0 - lambda*delta    where id_i = 0
                            ypnew = yp0 - cj*lambda*delta where id_i = 1. */
-  if(icopt == IDA_YA_YDP_INIT) {
+  if(IDA_mem->ida_icopt == IDA_YA_YDP_INIT) {
 
-    N_VProd(id, delta, dtemp);
-    N_VLinearSum(ONE, yp0, -cj*lambda, dtemp, ypnew);
-    N_VLinearSum(ONE, delta, -ONE, dtemp, dtemp);
-    N_VLinearSum(ONE, yy0, -lambda, dtemp, ynew);
+    N_VProd(IDA_mem->ida_id, IDA_mem->ida_delta, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_yp0, -IDA_mem->ida_cj*lambda,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_ypnew);
+    N_VLinearSum(ONE, IDA_mem->ida_delta, -ONE,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_yy0, -lambda,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_ynew);
 
-  }else if(icopt == IDA_Y_INIT) {
+  }else if(IDA_mem->ida_icopt == IDA_Y_INIT) {
 
     /* IDA_Y_INIT case: ynew = yy0 - lambda*delta. (ypnew = yp0 preset.) */
-    N_VLinearSum(ONE, yy0, -lambda, delta, ynew);
+    N_VLinearSum(ONE, IDA_mem->ida_yy0, -lambda, IDA_mem->ida_delta,
+                 IDA_mem->ida_ynew);
   }
 
-  if(sensi && (ism==IDA_SIMULTANEOUS))
+  if(IDA_mem->ida_sensi && (IDA_mem->ida_ism==IDA_SIMULTANEOUS))
     retval = IDASensNewyyp(IDA_mem, lambda);
   
   return(retval);
@@ -980,15 +933,18 @@ static int IDANewy(IDAMem IDA_mem)
 {
   
   /* IDA_YA_YDP_INIT case: ynew = yy0 - delta    where id_i = 0. */
-  if(icopt == IDA_YA_YDP_INIT) {
-    N_VProd(id, delta, dtemp);
-    N_VLinearSum(ONE, delta, -ONE, dtemp, dtemp);
-    N_VLinearSum(ONE, yy0, -ONE, dtemp, ynew);
+  if(IDA_mem->ida_icopt == IDA_YA_YDP_INIT) {
+    N_VProd(IDA_mem->ida_id, IDA_mem->ida_delta, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_delta, -ONE,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_dtemp);
+    N_VLinearSum(ONE, IDA_mem->ida_yy0, -ONE,
+                 IDA_mem->ida_dtemp, IDA_mem->ida_ynew);
     return(IDA_SUCCESS);
   }
 
   /* IDA_Y_INIT case: ynew = yy0 - delta. */
-  N_VLinearSum(ONE, yy0, -ONE, delta, ynew);
+  N_VLinearSum(ONE, IDA_mem->ida_yy0, -ONE, IDA_mem->ida_delta,
+               IDA_mem->ida_ynew);
   return(IDA_SUCCESS);
 
 }
@@ -1027,16 +983,21 @@ static int IDASensNlsIC(IDAMem IDA_mem)
   int retval;
   int is, nj;
 
-  retval = resS(Ns, t0, 
-                yy0,  yp0,  delta,
-                yyS0, ypS0, deltaS,
-                user_dataS, tmpS1, tmpS2, tmpS3);
-  nrSe++;
+  retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_t0,
+                             IDA_mem->ida_yy0, IDA_mem->ida_yp0,
+                             IDA_mem->ida_delta, IDA_mem->ida_yyS0,
+                             IDA_mem->ida_ypS0,
+                             IDA_mem->ida_deltaS,
+                             IDA_mem->ida_user_dataS,
+                             IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2,
+                             IDA_mem->ida_tmpS3);
+  IDA_mem->ida_nrSe++;
   if(retval < 0) return(IDA_RES_FAIL);
   if(retval > 0) return(IDA_FIRST_RES_FAIL);
   
   /* Save deltaS */
-  for(is=0; is<Ns; is++) N_VScale(ONE, deltaS[is], savresS[is]);
+  for(is=0; is<IDA_mem->ida_Ns; is++)
+    N_VScale(ONE, IDA_mem->ida_deltaS[is], IDA_mem->ida_savresS[is]);
 
   /* Loop over nj = number of linear solve Jacobian setups. */
 
@@ -1048,13 +1009,16 @@ static int IDASensNlsIC(IDAMem IDA_mem)
 
     /* If converging slowly and lsetup is nontrivial and this is the first pass, 
        update Jacobian and retry. */
-    if(retval == IC_SLOW_CONVRG && setupNonNull && nj==1) {
+    if(retval == IC_SLOW_CONVRG && IDA_mem->ida_lsetup && nj==1) {
 
       /* Restore deltaS. */
-      for(is=0; is<Ns; is++) N_VScale(ONE, savresS[is], deltaS[is]);
+      for(is=0; is<IDA_mem->ida_Ns; is++)
+        N_VScale(ONE, IDA_mem->ida_savresS[is], IDA_mem->ida_deltaS[is]);
 
-      nsetupsS++;
-      retval = lsetup(IDA_mem, yy0, yp0, delta, tmpS1, tmpS2, tmpS3);
+      IDA_mem->ida_nsetupsS++;
+      retval = IDA_mem->ida_lsetup(IDA_mem, IDA_mem->ida_yy0, IDA_mem->ida_yp0,
+                                   IDA_mem->ida_delta, IDA_mem->ida_tmpS1,
+                                   IDA_mem->ida_tmpS2, IDA_mem->ida_tmpS3);
       if(retval < 0) return(IDA_LSETUP_FAIL);
       if(retval > 0) return(IC_FAIL_RECOV);
 
@@ -1097,26 +1061,30 @@ static int IDASensNewtonIC(IDAMem IDA_mem)
   int retval, is, mnewt;
   realtype delnorm, fnorm, fnorm0, oldfnrm, rate;
 
-  for(is=0;is<Ns;is++) {
+  for(is=0;is<IDA_mem->ida_Ns;is++) {
    
     /* Call the linear solve function to get the Newton step, delta. */
-    retval = lsolve(IDA_mem, deltaS[is], ewtS[is],  yy0, yp0, delta);
+    retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_deltaS[is],
+                                 IDA_mem->ida_ewtS[is], IDA_mem->ida_yy0,
+                                 IDA_mem->ida_yp0, IDA_mem->ida_delta);
     if(retval < 0) return(IDA_LSOLVE_FAIL);
     if(retval > 0) return(IC_FAIL_RECOV);
 
   }
     /* Compute the norm of the step and return if it is small enough */
-  fnorm = IDASensWrmsNorm(IDA_mem, deltaS, ewtS, FALSE);
-  if(sysindex == 0) fnorm *= tscale*SUNRabs(cj);
-  if(fnorm <= epsNewt) return(IDA_SUCCESS);
+  fnorm = IDASensWrmsNorm(IDA_mem, IDA_mem->ida_deltaS,
+                          IDA_mem->ida_ewtS, SUNFALSE);
+  if(IDA_mem->ida_sysindex == 0)
+    fnorm *= IDA_mem->ida_tscale * SUNRabs(IDA_mem->ida_cj);
+  if(fnorm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
   fnorm0 = fnorm;
 
   rate = ZERO;
 
   /* Newton iteration loop */
-  for(mnewt = 0; mnewt < maxnit; mnewt++) {
+  for(mnewt = 0; mnewt < IDA_mem->ida_maxnit; mnewt++) {
 
-    nniS++;
+    IDA_mem->ida_nniS++;
     delnorm = fnorm;
     oldfnrm = fnorm;
       
@@ -1126,10 +1094,11 @@ static int IDASensNewtonIC(IDAMem IDA_mem)
       
     /* Set the observed convergence rate and test for convergence. */
     rate = fnorm/oldfnrm;
-    if(fnorm <= epsNewt) return(IDA_SUCCESS);
+    if(fnorm <= IDA_mem->ida_epsNewt) return(IDA_SUCCESS);
     
     /* If not converged, copy new step vectors, and loop. */
-    for(is=0; is<Ns; is++) N_VScale(ONE, delnewS[is], deltaS[is]);
+    for(is=0; is<IDA_mem->ida_Ns; is++)
+      N_VScale(ONE, IDA_mem->ida_delnewS[is], IDA_mem->ida_deltaS[is]);
     
   }   /* End of Newton iteration loop */
 
@@ -1174,20 +1143,21 @@ static int IDASensLineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm)
   realtype lambda, ratio;
   
   /* Set work space pointer. */
-  dtemp = phi[3];
+  IDA_mem->ida_dtemp = IDA_mem->ida_phi[3];
 
   f1norm = (*fnorm)*(*fnorm)*HALF;
   
   /* Initialize local variables. */
   ratio = ONE;
   slpi = -TWO*f1norm*ratio;
-  minlam = steptol/(*delnorm);
+  minlam = IDA_mem->ida_steptol / (*delnorm);
   lambda = ONE;
   nbacks = 0;
 
-  loop {
+  for(;;) {
 
-    if (nbacks == maxbacks) return(IC_LINESRCH_FAILED);
+    if (nbacks == IDA_mem->ida_maxbacks)
+      return(IC_LINESRCH_FAILED);
     /* Get new iteration in (ySnew, ypSnew). */
     IDASensNewyyp(IDA_mem, lambda);
 
@@ -1196,24 +1166,24 @@ static int IDASensLineSrch(IDAMem IDA_mem, realtype *delnorm, realtype *fnorm)
     if (retval!=IDA_SUCCESS) return retval;
 
     /* If lsoff option is on, break out. */
-    if(lsoff) break;
+    if(IDA_mem->ida_lsoff) break;
 
     /* Do alpha-condition test. */
     f1normp = fnormp*fnormp*HALF;
     if(f1normp <= f1norm + ALPHALS*slpi*lambda) break;
     if(lambda < minlam) return(IC_LINESRCH_FAILED);
     lambda /= TWO;
-    nbacktr++; nbacks++;
+    IDA_mem->ida_nbacktr++; nbacks++;
   }
   
   /* Update yyS0, ypS0 and fnorm and return. */
-  for(is=0; is<Ns; is++) {
-    N_VScale(ONE, yyS0new[is], yyS0[is]);
+  for(is=0; is<IDA_mem->ida_Ns; is++) {
+    N_VScale(ONE, IDA_mem->ida_yyS0new[is], IDA_mem->ida_yyS0[is]);
   }
 
-  if (icopt == IDA_YA_YDP_INIT)
-    for(is=0; is<Ns; is++) 
-      N_VScale(ONE, ypS0new[is], ypS0[is]);
+  if (IDA_mem->ida_icopt == IDA_YA_YDP_INIT)
+    for(is=0; is<IDA_mem->ida_Ns; is++) 
+      N_VScale(ONE, IDA_mem->ida_ypS0new[is], IDA_mem->ida_ypS0[is]);
 
   *fnorm = fnormp;
   return(IDA_SUCCESS);
@@ -1242,27 +1212,38 @@ static int IDASensfnorm(IDAMem IDA_mem, realtype *fnorm)
   int is, retval;
   
   /* Get sensitivity residual */
-  retval = resS(Ns, t0, 
-                yy0,  yp0,  delta,
-                yyS0new, ypS0new, delnewS,
-                user_dataS, tmpS1, tmpS2, tmpS3);
-  nrSe++;
+  retval = IDA_mem->ida_resS(IDA_mem->ida_Ns, IDA_mem->ida_t0,
+                             IDA_mem->ida_yy0, IDA_mem->ida_yp0,
+                             IDA_mem->ida_delta,
+                             IDA_mem->ida_yyS0new,
+                             IDA_mem->ida_ypS0new,
+                             IDA_mem->ida_delnewS,
+                             IDA_mem->ida_user_dataS,
+                             IDA_mem->ida_tmpS1, IDA_mem->ida_tmpS2,
+                             IDA_mem->ida_tmpS3);
+  IDA_mem->ida_nrSe++;
   if(retval < 0) return(IDA_RES_FAIL);
   if(retval > 0) return(IC_FAIL_RECOV);
   
-  for(is=0; is<Ns; is++) N_VScale(ONE, delnewS[is], savresS[is]);
+  for(is=0; is<IDA_mem->ida_Ns; is++)
+    N_VScale(ONE, IDA_mem->ida_delnewS[is], IDA_mem->ida_savresS[is]);
   
   /* Call linear solve function */
-  for(is=0; is<Ns; is++) {
+  for(is=0; is<IDA_mem->ida_Ns; is++) {
     
-    retval = lsolve(IDA_mem, delnewS[is], ewtS[is],  yy0, yp0, delta);
+    retval = IDA_mem->ida_lsolve(IDA_mem, IDA_mem->ida_delnewS[is],
+                                 IDA_mem->ida_ewtS[is],
+                                 IDA_mem->ida_yy0,
+                                 IDA_mem->ida_yp0,
+                                 IDA_mem->ida_delta);
     if(retval < 0) return(IDA_LSOLVE_FAIL);
     if(retval > 0) return(IC_FAIL_RECOV);
   }
 
   /* Compute the WRMS-norm; rescale if index = 0. */
-  *fnorm = IDASensWrmsNorm(IDA_mem, delnewS, ewtS, FALSE);
-  if(sysindex == 0) (*fnorm) *= tscale*SUNRabs(cj);
+  *fnorm = IDASensWrmsNorm(IDA_mem, IDA_mem->ida_delnewS, IDA_mem->ida_ewtS, SUNFALSE);
+  if(IDA_mem->ida_sysindex == 0)
+    (*fnorm) *= IDA_mem->ida_tscale * SUNRabs(IDA_mem->ida_cj);
 
   return(IDA_SUCCESS);
 }
@@ -1283,27 +1264,31 @@ static int IDASensNewyyp(IDAMem IDA_mem, realtype lambda)
 {
   int is;
 
-  if(icopt == IDA_YA_YDP_INIT) {
+  if(IDA_mem->ida_icopt == IDA_YA_YDP_INIT) {
 
   /* IDA_YA_YDP_INIT case: 
      - ySnew  = yS0  - lambda*deltaS    where id_i = 0
      - ypSnew = ypS0 - cj*lambda*delta  where id_i = 1. */    
 
-    for(is=0; is<Ns; is++) {
+    for(is=0; is<IDA_mem->ida_Ns; is++) {
       
       /* It is ok to use dtemp as temporary vector here. */
-      N_VProd(id, deltaS[is], dtemp);
-      N_VLinearSum(ONE, ypS0[is], -cj*lambda, dtemp, ypS0new[is]);
-      N_VLinearSum(ONE, deltaS[is], -ONE, dtemp, dtemp);
-      N_VLinearSum(ONE, yyS0[is], -lambda, dtemp, yyS0new[is]);
+      N_VProd(IDA_mem->ida_id, IDA_mem->ida_deltaS[is], IDA_mem->ida_dtemp);
+      N_VLinearSum(ONE, IDA_mem->ida_ypS0[is], -IDA_mem->ida_cj*lambda,
+                   IDA_mem->ida_dtemp, IDA_mem->ida_ypS0new[is]);
+      N_VLinearSum(ONE, IDA_mem->ida_deltaS[is], -ONE,
+                   IDA_mem->ida_dtemp, IDA_mem->ida_dtemp);
+      N_VLinearSum(ONE, IDA_mem->ida_yyS0[is], -lambda,
+                   IDA_mem->ida_dtemp, IDA_mem->ida_yyS0new[is]);
     } /* end loop is */
   }else { 
 
     /* IDA_Y_INIT case: 
        - ySnew = yS0 - lambda*deltaS. (ypnew = yp0 preset.) */
 
-    for(is=0; is<Ns; is++)
-      N_VLinearSum(ONE, yyS0[is], -lambda, deltaS[is], yyS0new[is]);
+    for(is=0; is<IDA_mem->ida_Ns; is++)
+      N_VLinearSum(ONE, IDA_mem->ida_yyS0[is], -lambda,
+                   IDA_mem->ida_deltaS[is], IDA_mem->ida_yyS0new[is]);
   } /* end loop is */
   return(IDA_SUCCESS);
 }
diff --git a/src/idas/idas_impl.h b/src/idas/idas_impl.h
index 3deb98c..18b0456 100644
--- a/src/idas/idas_impl.h
+++ b/src/idas/idas_impl.h
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4921 $
- * $Date: 2016-09-19 14:35:11 -0700 (Mon, 19 Sep 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -77,7 +77,7 @@ typedef struct IDAMemRec {
   realtype       ida_rtol;           /* relative tolerance                    */
   realtype       ida_Satol;          /* scalar absolute tolerance             */  
   N_Vector       ida_Vatol;          /* vector absolute tolerance             */  
-  booleantype    ida_user_efun;      /* TRUE if user provides efun            */
+  booleantype    ida_user_efun;      /* SUNTRUE if user provides efun         */
   IDAEwtFn       ida_efun;           /* function to set ewt                   */
   void          *ida_edata;          /* user pointer passed to efun           */
   
@@ -115,7 +115,7 @@ typedef struct IDAMemRec {
   int            ida_DQtype;
   realtype       ida_DQrhomax;
 
-  booleantype    ida_errconS;       /* TRUE if sensitivities in err. control  */
+  booleantype    ida_errconS;       /* SUNTRUE if sensitivities in err. control  */
 
   int            ida_itolS;
   realtype       ida_rtolS;         /* relative tolerance for sensitivities   */
@@ -126,13 +126,13 @@ typedef struct IDAMemRec {
     Quadrature Sensitivity Related Data 
     -----------------------------------*/
 
-  booleantype ida_quadr_sensi;   /* TRUE if computing sensitivities of quadrs.*/
+  booleantype ida_quadr_sensi;   /* SUNTRUE if computing sensitivities of quadrs. */
 
-  IDAQuadSensRhsFn ida_rhsQS;    /* fQS = (dfQ/dy)*yS + (dfQ/dp)              */
-  void *ida_user_dataQS;         /* data pointer passed to fQS                */
-  booleantype ida_rhsQSDQ;       /* TRUE if using internal DQ functions       */
+  IDAQuadSensRhsFn ida_rhsQS;    /* fQS = (dfQ/dy)*yS + (dfQ/dp)                  */
+  void *ida_user_dataQS;         /* data pointer passed to fQS                    */
+  booleantype ida_rhsQSDQ;       /* SUNTRUE if using internal DQ functions        */
 
-  booleantype ida_errconQS;      /* TRUE if yQS are considered in err. con.   */
+  booleantype ida_errconQS;      /* SUNTRUE if yQS are considered in err. con.    */
 
   int ida_itolQS;
   realtype ida_rtolQS;           /* relative tolerance for yQS                */
@@ -320,12 +320,12 @@ typedef struct IDAMemRec {
     Space requirements for IDAS
     ---------------------------*/
 
-  long int ida_lrw1;     /* no. of realtype words in 1 N_Vector               */
-  long int ida_liw1;     /* no. of integer words in 1 N_Vector                */
-  long int ida_lrw1Q;
-  long int ida_liw1Q;
-  long int ida_lrw;      /* number of realtype words in IDA work vectors      */
-  long int ida_liw;      /* no. of integer words in IDA work vectors          */
+  sunindextype ida_lrw1; /* no. of realtype words in 1 N_Vector               */
+  sunindextype ida_liw1; /* no. of integer words in 1 N_Vector                */
+  sunindextype ida_lrw1Q;
+  sunindextype ida_liw1Q;
+  long int     ida_lrw;  /* number of realtype words in IDA work vectors      */
+  long int     ida_liw;  /* no. of integer words in IDA work vectors          */
 
 
   /*-------------------------------------------
@@ -338,15 +338,15 @@ typedef struct IDAMemRec {
 
   /* Flags to verify correct calling sequence */
     
-  booleantype ida_SetupDone;     /* set to FALSE by IDAInit and IDAReInit
-				    set to TRUE by IDACalcIC or IDASolve       */
+  booleantype ida_SetupDone;     /* set to SUNFALSE by IDAInit and IDAReInit
+				    set to SUNTRUE by IDACalcIC or IDASolve    */
 
   booleantype ida_VatolMallocDone;
   booleantype ida_constraintsMallocDone;
   booleantype ida_idMallocDone;
 
-  booleantype ida_MallocDone;    /* set to FALSE by IDACreate
-				    set to TRUE by IDAInit
+  booleantype ida_MallocDone;    /* set to SUNFALSE by IDACreate
+				    set to SUNTRUE by IDAInit
 				    tested by IDAReInit and IDASolve           */
 
   booleantype ida_VatolQMallocDone;
@@ -395,14 +395,13 @@ typedef struct IDAMemRec {
     Saved Values
     ------------*/
 
-  booleantype    ida_setupNonNull;   /* Does setup do something?              */
-  booleantype    ida_constraintsSet; /* constraints vector present            */
-  booleantype    ida_suppressalg;    /* TRUE if suppressing algebraic vars.
-					in local error tests                  */
-  int ida_kused;         /* method order used on last successful step         */
-  realtype ida_h0u;      /* actual initial stepsize                           */
-  realtype ida_hused;    /* step size used on last successful step            */
-  realtype ida_tolsf;    /* tolerance scale factor (saved value)              */
+  booleantype    ida_constraintsSet; /* constraints vector present             */
+  booleantype    ida_suppressalg;    /* SUNTRUE if suppressing algebraic vars.
+					in local error tests                   */
+  int ida_kused;         /* method order used on last successful step          */
+  realtype ida_h0u;      /* actual initial stepsize                            */
+  realtype ida_hused;    /* step size used on last successful step             */
+  realtype ida_tolsf;    /* tolerance scale factor (saved value)               */
 
   /*----------------
     Rootfinding Data
@@ -430,7 +429,7 @@ typedef struct IDAMemRec {
     Adjoint sensitivity data
     ------------------------*/
 
-  booleantype ida_adj;              /* TRUE if performing ASA                 */
+  booleantype ida_adj;              /* SUNTRUE if performing ASA              */
 
   struct IDAadjMemRec *ida_adj_mem; /* Pointer to adjoint memory structure    */
 
@@ -770,8 +769,8 @@ struct IDAadjMemRec {
 /*
  * -----------------------------------------------------------------
  * int (*ida_lsetup)(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,   
- *                  N_Vector resp,                                 
- *            N_Vector tempv1, N_Vector tempv2, N_Vector tempv3);  
+ *                  N_Vector resp, N_Vector tempv1, 
+ *                  N_Vector tempv2, N_Vector tempv3);  
  * -----------------------------------------------------------------
  * The job of ida_lsetup is to prepare the linear solver for       
  * subsequent calls to ida_lsolve. Its parameters are as follows:  
@@ -779,7 +778,6 @@ struct IDAadjMemRec {
  * idamem - problem memory pointer of type IDAMem. See the big     
  *          typedef earlier in this file.                          
  *                                                                 
- *                                                                 
  * yyp   - the predicted y vector for the current IDA internal     
  *         step.                                                   
  *                                                                 
@@ -829,6 +827,17 @@ struct IDAadjMemRec {
  */                                                                 
 
 /*
+ * -----------------------------------------------------------------
+ * int (*ida_lfree)(IDAMem IDA_mem);                               
+ * -----------------------------------------------------------------
+ * ida_lfree should free up any memory allocated by the linear     
+ * solver. This routine is called once a problem has been          
+ * completed and the linear solver is no longer needed.  It should 
+ * return 0 upon success, nonzero on failure.
+ * -----------------------------------------------------------------
+ */
+  
+/*
  * =================================================================
  *   I D A S    I N T E R N A L   F U N C T I O N S
  * =================================================================
diff --git a/src/idas/idas_io.c b/src/idas/idas_io.c
index cbd8722..8252fb2 100644
--- a/src/idas/idas_io.c
+++ b/src/idas/idas_io.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4539 $
- * $Date: 2015-09-16 15:39:33 -0700 (Wed, 16 Sep 2015) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Cosmin Petra @ LLNL
  * -----------------------------------------------------------------
@@ -38,15 +38,6 @@
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define lrw  (IDA_mem->ida_lrw)
-#define liw  (IDA_mem->ida_liw)
-#define lrw1 (IDA_mem->ida_lrw1)
-#define liw1 (IDA_mem->ida_liw1)
-
 int IDASetErrHandlerFn(void *ida_mem, IDAErrHandlerFn ehfun, void *eh_data)
 {
   IDAMem IDA_mem;
@@ -229,7 +220,7 @@ int IDASetStopTime(void *ida_mem, realtype tstop)
   }
 
   IDA_mem->ida_tstop = tstop;
-  IDA_mem->ida_tstopset = TRUE;
+  IDA_mem->ida_tstopset = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
@@ -345,18 +336,18 @@ int IDASetId(void *ida_mem, N_Vector id)
   if (id == NULL) {
     if (IDA_mem->ida_idMallocDone) {
       N_VDestroy(IDA_mem->ida_id);
-      lrw -= lrw1;
-      liw -= liw1;
+      IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+      IDA_mem->ida_liw -= IDA_mem->ida_liw1;
     }
-    IDA_mem->ida_idMallocDone = FALSE;    
+    IDA_mem->ida_idMallocDone = SUNFALSE;    
     return(IDA_SUCCESS);
   }
 
   if ( !(IDA_mem->ida_idMallocDone) ) {
     IDA_mem->ida_id = N_VClone(id);
-    lrw += lrw1;
-    liw += liw1;
-    IDA_mem->ida_idMallocDone = TRUE;
+    IDA_mem->ida_lrw += IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw += IDA_mem->ida_liw1;
+    IDA_mem->ida_idMallocDone = SUNTRUE;
   }
 
   /* Load the id vector */
@@ -383,11 +374,11 @@ int IDASetConstraints(void *ida_mem, N_Vector constraints)
   if (constraints == NULL) {
     if (IDA_mem->ida_constraintsMallocDone) {
       N_VDestroy(IDA_mem->ida_constraints);
-      lrw -= lrw1;
-      liw -= liw1;
+      IDA_mem->ida_lrw -= IDA_mem->ida_lrw1;
+      IDA_mem->ida_liw -= IDA_mem->ida_liw1;
     }
-    IDA_mem->ida_constraintsMallocDone = FALSE;
-    IDA_mem->ida_constraintsSet = FALSE;
+    IDA_mem->ida_constraintsMallocDone = SUNFALSE;
+    IDA_mem->ida_constraintsSet = SUNFALSE;
     return(IDA_SUCCESS);
   }
 
@@ -412,16 +403,16 @@ int IDASetConstraints(void *ida_mem, N_Vector constraints)
 
   if ( !(IDA_mem->ida_constraintsMallocDone) ) {
     IDA_mem->ida_constraints = N_VClone(constraints);
-    lrw += lrw1;
-    liw += liw1;
-    IDA_mem->ida_constraintsMallocDone = TRUE;
+    IDA_mem->ida_lrw += IDA_mem->ida_lrw1;
+    IDA_mem->ida_liw += IDA_mem->ida_liw1;
+    IDA_mem->ida_constraintsMallocDone = SUNTRUE;
   }
 
   /* Load the constraints vector */
 
   N_VScale(ONE, constraints, IDA_mem->ida_constraints);
 
-  IDA_mem->ida_constraintsSet = TRUE;
+  IDA_mem->ida_constraintsSet = SUNTRUE;
 
   return(IDA_SUCCESS);
 }
@@ -646,13 +637,6 @@ int IDASetStepToleranceIC(void *ida_mem, realtype steptol)
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define lrw1Q (IDA_mem->ida_lrw1Q)
-#define liw1Q (IDA_mem->ida_liw1Q)
-
 /*-----------------------------------------------------------------*/
 
 int IDASetQuadErrCon(void *ida_mem, booleantype errconQ)
@@ -665,7 +649,7 @@ int IDASetQuadErrCon(void *ida_mem, booleantype errconQ)
   }  
   IDA_mem = (IDAMem) ida_mem;
 
-  if (IDA_mem->ida_quadMallocDone == FALSE) {
+  if (IDA_mem->ida_quadMallocDone == SUNFALSE) {
     IDAProcessError(NULL, IDA_NO_QUAD, "IDAS", "IDASetQuadErrCon", MSG_NO_QUAD);    
     return(IDA_NO_QUAD);
   }
@@ -759,7 +743,7 @@ int IDASetSensParams(void *ida_mem, realtype *p, realtype *pbar, int *plist)
 
   /* Was sensitivity initialized? */
 
-  if (IDA_mem->ida_sensMallocDone == FALSE) {
+  if (IDA_mem->ida_sensMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASetSensParams", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
@@ -820,13 +804,13 @@ int IDASetQuadSensErrCon(void *ida_mem, booleantype errconQS)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Was sensitivity initialized? */
-  if (IDA_mem->ida_sensMallocDone == FALSE) {
+  if (IDA_mem->ida_sensMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDASetQuadSensErrCon", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
   /* Was quadrature sensitivity initialized? */
-  if (IDA_mem->ida_quadSensMallocDone == FALSE) {
+  if (IDA_mem->ida_quadSensMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDASetQuadSensErrCon", MSG_NO_SENSI);
     return(IDA_NO_QUADSENS);
   }
@@ -842,33 +826,6 @@ int IDASetQuadSensErrCon(void *ida_mem, booleantype errconQS)
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define ewt         (IDA_mem->ida_ewt)
-#define kk          (IDA_mem->ida_kk)
-#define hh          (IDA_mem->ida_hh)
-#define h0u         (IDA_mem->ida_h0u)
-#define tn          (IDA_mem->ida_tn)
-#define nbacktr     (IDA_mem->ida_nbacktr)
-#define nst         (IDA_mem->ida_nst)
-#define nre         (IDA_mem->ida_nre)
-#define ncfn        (IDA_mem->ida_ncfn)
-#define netf        (IDA_mem->ida_netf)
-#define nni         (IDA_mem->ida_nni)
-#define nsetups     (IDA_mem->ida_nsetups)
-#define lrw         (IDA_mem->ida_lrw)
-#define liw         (IDA_mem->ida_liw)
-#define kused       (IDA_mem->ida_kused)          
-#define hused       (IDA_mem->ida_hused)         
-#define tolsf       (IDA_mem->ida_tolsf) 
-#define efun        (IDA_mem->ida_efun)
-#define edata       (IDA_mem->ida_edata)
-#define nge         (IDA_mem->ida_nge)
-#define iroots      (IDA_mem->ida_iroots)
-#define ee          (IDA_mem->ida_ee)
-
 int IDAGetNumSteps(void *ida_mem, long int *nsteps)
 {
   IDAMem IDA_mem;
@@ -880,7 +837,7 @@ int IDAGetNumSteps(void *ida_mem, long int *nsteps)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nsteps = nst;
+  *nsteps = IDA_mem->ida_nst;
 
   return(IDA_SUCCESS);
 }
@@ -898,7 +855,7 @@ int IDAGetNumResEvals(void *ida_mem, long int *nrevals)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nrevals = nre;
+  *nrevals = IDA_mem->ida_nre;
 
   return(IDA_SUCCESS);
 }
@@ -916,7 +873,7 @@ int IDAGetNumLinSolvSetups(void *ida_mem, long int *nlinsetups)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nlinsetups = nsetups;
+  *nlinsetups = IDA_mem->ida_nsetups;
 
   return(IDA_SUCCESS);
 }
@@ -934,7 +891,7 @@ int IDAGetNumErrTestFails(void *ida_mem, long int *netfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *netfails = netf;
+  *netfails = IDA_mem->ida_netf;
 
   return(IDA_SUCCESS);
 }
@@ -952,7 +909,7 @@ int IDAGetNumBacktrackOps(void *ida_mem, long int *nbacktracks)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nbacktracks = nbacktr;
+  *nbacktracks = IDA_mem->ida_nbacktr;
 
   return(IDA_SUCCESS);
 }
@@ -994,7 +951,7 @@ int IDAGetLastOrder(void *ida_mem, int *klast)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *klast = kused;
+  *klast = IDA_mem->ida_kused;
 
   return(IDA_SUCCESS);
 }
@@ -1012,7 +969,7 @@ int IDAGetCurrentOrder(void *ida_mem, int *kcur)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *kcur = kk;
+  *kcur = IDA_mem->ida_kk;
 
   return(IDA_SUCCESS);
 }
@@ -1030,7 +987,7 @@ int IDAGetActualInitStep(void *ida_mem, realtype *hinused)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *hinused = h0u;
+  *hinused = IDA_mem->ida_h0u;
 
   return(IDA_SUCCESS);
 }
@@ -1048,7 +1005,7 @@ int IDAGetLastStep(void *ida_mem, realtype *hlast)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *hlast = hused;
+  *hlast = IDA_mem->ida_hused;
 
   return(IDA_SUCCESS);
 }
@@ -1066,7 +1023,7 @@ int IDAGetCurrentStep(void *ida_mem, realtype *hcur)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *hcur = hh;
+  *hcur = IDA_mem->ida_hh;
 
   return(IDA_SUCCESS);
 }
@@ -1084,7 +1041,7 @@ int IDAGetCurrentTime(void *ida_mem, realtype *tcur)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *tcur = tn;
+  *tcur = IDA_mem->ida_tn;
 
   return(IDA_SUCCESS);
 }
@@ -1102,7 +1059,7 @@ int IDAGetTolScaleFactor(void *ida_mem, realtype *tolsfact)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *tolsfact = tolsf;
+  *tolsfact = IDA_mem->ida_tolsf;
 
   return(IDA_SUCCESS);
 }
@@ -1120,7 +1077,7 @@ int IDAGetErrWeights(void *ida_mem, N_Vector eweight)
 
   IDA_mem = (IDAMem) ida_mem; 
 
-  N_VScale(ONE, ewt, eweight);
+  N_VScale(ONE, IDA_mem->ida_ewt, eweight);
 
   return(IDA_SUCCESS);
 }
@@ -1137,7 +1094,7 @@ int IDAGetEstLocalErrors(void *ida_mem, N_Vector ele)
   }
   IDA_mem = (IDAMem) ida_mem;
 
-  N_VScale(ONE, ee, ele);
+  N_VScale(ONE, IDA_mem->ida_ee, ele);
 
   return(IDA_SUCCESS);
 }
@@ -1155,8 +1112,8 @@ int IDAGetWorkSpace(void *ida_mem, long int *lenrw, long int *leniw)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *leniw = liw;
-  *lenrw = lrw;
+  *leniw = IDA_mem->ida_liw;
+  *lenrw = IDA_mem->ida_lrw;
 
   return(IDA_SUCCESS);
 }
@@ -1177,16 +1134,16 @@ int IDAGetIntegratorStats(void *ida_mem, long int *nsteps, long int *nrevals,
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nsteps     = nst;
-  *nrevals    = nre;
-  *nlinsetups = nsetups;
-  *netfails   = netf;
-  *klast      = kused;
-  *kcur       = kk;
-  *hinused    = h0u;
-  *hlast      = hused;
-  *hcur       = hh;  
-  *tcur       = tn;
+  *nsteps     = IDA_mem->ida_nst;
+  *nrevals    = IDA_mem->ida_nre;
+  *nlinsetups = IDA_mem->ida_nsetups;
+  *netfails   = IDA_mem->ida_netf;
+  *klast      = IDA_mem->ida_kused;
+  *kcur       = IDA_mem->ida_kk;
+  *hinused    = IDA_mem->ida_h0u;
+  *hlast      = IDA_mem->ida_hused;
+  *hcur       = IDA_mem->ida_hh;  
+  *tcur       = IDA_mem->ida_tn;
 
   return(IDA_SUCCESS);
 }
@@ -1204,7 +1161,7 @@ int IDAGetNumGEvals(void *ida_mem, long int *ngevals)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *ngevals = nge;
+  *ngevals = IDA_mem->ida_nge;
 
   return(IDA_SUCCESS);
 }
@@ -1225,7 +1182,8 @@ int IDAGetRootInfo(void *ida_mem, int *rootsfound)
 
   nrt = IDA_mem->ida_nrtfn;
 
-  for (i=0; i<nrt; i++) rootsfound[i] = iroots[i];
+  for (i=0; i<nrt; i++)
+    rootsfound[i] = IDA_mem->ida_iroots[i];
 
   return(IDA_SUCCESS);
 }
@@ -1243,7 +1201,7 @@ int IDAGetNumNonlinSolvIters(void *ida_mem, long int *nniters)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nniters = nni;
+  *nniters = IDA_mem->ida_nni;
 
   return(IDA_SUCCESS);
 }
@@ -1261,7 +1219,7 @@ int IDAGetNumNonlinSolvConvFails(void *ida_mem, long int *nncfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nncfails = ncfn;
+  *nncfails = IDA_mem->ida_ncfn;
 
   return(IDA_SUCCESS);
 }
@@ -1279,8 +1237,8 @@ int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters, long int *nncfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  *nniters  = nni;
-  *nncfails = ncfn;
+  *nniters  = IDA_mem->ida_nni;
+  *nncfails = IDA_mem->ida_ncfn;
 
   return(IDA_SUCCESS);
 }
@@ -1291,16 +1249,6 @@ int IDAGetNonlinSolvStats(void *ida_mem, long int *nniters, long int *nncfails)
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define quadr          (IDA_mem->ida_quadr)
-#define nrQe           (IDA_mem->ida_nrQe)
-#define netfQ          (IDA_mem->ida_netfQ)
-#define ewtQ           (IDA_mem->ida_ewtQ)
-#define errconQ        (IDA_mem->ida_errconQ)
-
 /*-----------------------------------------------------------------*/
 
 int IDAGetQuadNumRhsEvals(void *ida_mem, long int *nrQevals)
@@ -1314,12 +1262,12 @@ int IDAGetQuadNumRhsEvals(void *ida_mem, long int *nrQevals)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr==FALSE) {
+  if (IDA_mem->ida_quadr==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadNumRhsEvals", MSG_NO_QUAD); 
     return(IDA_NO_QUAD);
   }
 
-  *nrQevals = nrQe;
+  *nrQevals = IDA_mem->ida_nrQe;
 
   return(IDA_SUCCESS);
 }
@@ -1337,12 +1285,12 @@ int IDAGetQuadNumErrTestFails(void *ida_mem, long int *nQetfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr==FALSE) {
+  if (IDA_mem->ida_quadr==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadNumErrTestFails", MSG_NO_QUAD); 
     return(IDA_NO_QUAD);
   }
 
-  *nQetfails = netfQ;
+  *nQetfails = IDA_mem->ida_netfQ;
 
   return(IDA_SUCCESS);
 }
@@ -1360,12 +1308,13 @@ int IDAGetQuadErrWeights(void *ida_mem, N_Vector eQweight)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr==FALSE) {
+  if (IDA_mem->ida_quadr==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadErrWeights", MSG_NO_QUAD); 
     return(IDA_NO_QUAD);
   }
 
-  if(errconQ) N_VScale(ONE, ewtQ, eQweight);
+  if(IDA_mem->ida_errconQ)
+    N_VScale(ONE, IDA_mem->ida_ewtQ, eQweight);
 
   return(IDA_SUCCESS);
 }
@@ -1383,13 +1332,13 @@ int IDAGetQuadStats(void *ida_mem, long int *nrQevals, long int *nQetfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr==FALSE) {
+  if (IDA_mem->ida_quadr==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUAD, "IDAS", "IDAGetQuadStats", MSG_NO_QUAD); 
     return(IDA_NO_QUAD);
   }
 
-  *nrQevals = nrQe;
-  *nQetfails = netfQ;
+  *nrQevals = IDA_mem->ida_nrQe;
+  *nQetfails = IDA_mem->ida_netfQ;
 
   return(IDA_SUCCESS);
 }
@@ -1401,16 +1350,6 @@ int IDAGetQuadStats(void *ida_mem, long int *nrQevals, long int *nQetfails)
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define quadr_sensi    (IDA_mem->ida_quadr_sensi)
-#define nrQSe          (IDA_mem->ida_nrQSe)
-#define netfQS         (IDA_mem->ida_netfQS)
-#define ewtQS          (IDA_mem->ida_ewtQS)
-#define errconQS       (IDA_mem->ida_errconQS)
-
 /*-----------------------------------------------------------------*/
 
 int IDAGetQuadSensNumRhsEvals(void *ida_mem, long int *nrhsQSevals)
@@ -1424,12 +1363,12 @@ int IDAGetQuadSensNumRhsEvals(void *ida_mem, long int *nrhsQSevals)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (IDA_mem->ida_quadr_sensi == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensNumRhsEvals", MSG_NO_QUADSENSI); 
     return(IDA_NO_QUADSENS);
   }
 
-  *nrhsQSevals = nrQSe;
+  *nrhsQSevals = IDA_mem->ida_nrQSe;
 
   return(IDA_SUCCESS);
 }
@@ -1447,12 +1386,12 @@ int IDAGetQuadSensNumErrTestFails(void *ida_mem, long int *nQSetfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (IDA_mem->ida_quadr_sensi == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensNumErrTestFails", MSG_NO_QUADSENSI); 
     return(IDA_NO_QUADSENS);
   }
 
-  *nQSetfails = netfQS;
+  *nQSetfails = IDA_mem->ida_netfQS;
 
   return(IDA_SUCCESS);
 }
@@ -1471,15 +1410,15 @@ int IDAGetQuadSensErrWeights(void *ida_mem, N_Vector *eQSweight)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (IDA_mem->ida_quadr_sensi == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensErrWeights", MSG_NO_QUADSENSI); 
     return(IDA_NO_QUADSENS);
   }
   Ns = IDA_mem->ida_Ns;
 
-  if (errconQS)
+  if (IDA_mem->ida_errconQS)
     for (is=0; is<Ns; is++)
-      N_VScale(ONE, ewtQS[is], eQSweight[is]);
+      N_VScale(ONE, IDA_mem->ida_ewtQS[is], eQSweight[is]);
 
   return(IDA_SUCCESS);
 }
@@ -1497,13 +1436,13 @@ int IDAGetQuadSensStats(void *ida_mem, long int *nrhsQSevals, long int *nQSetfai
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (quadr_sensi == FALSE) {
+  if (IDA_mem->ida_quadr_sensi == SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_QUADSENS, "IDAS", "IDAGetQuadSensStats", MSG_NO_QUADSENSI); 
     return(IDA_NO_QUADSENS);
   }
 
-  *nrhsQSevals = nrQSe;
-  *nQSetfails = netfQS;
+  *nrhsQSevals = IDA_mem->ida_nrQSe;
+  *nQSetfails = IDA_mem->ida_netfQS;
 
   return(IDA_SUCCESS);
 }
@@ -1516,21 +1455,6 @@ int IDAGetQuadSensStats(void *ida_mem, long int *nrhsQSevals, long int *nQSetfai
  * =================================================================
  */
 
-/* 
- * Readability constants
- */
-
-#define sensi          (IDA_mem->ida_sensi)
-#define Ns             (IDA_mem->ida_Ns)
-#define ism            (IDA_mem->ida_ism)
-#define ewtS           (IDA_mem->ida_ewtS)
-#define nrSe           (IDA_mem->ida_nrSe)
-#define nreS           (IDA_mem->ida_nreS)
-#define nniS           (IDA_mem->ida_nniS)
-#define ncfnS          (IDA_mem->ida_ncfnS)
-#define netfS          (IDA_mem->ida_netfS)
-#define nsetupsS       (IDA_mem->ida_nsetupsS)
-
 /*-----------------------------------------------------------------*/
 
 int IDAGetSensConsistentIC(void *ida_mem, N_Vector *yyS0, N_Vector *ypS0)
@@ -1545,7 +1469,7 @@ int IDAGetSensConsistentIC(void *ida_mem, N_Vector *yyS0, N_Vector *ypS0)
 
   IDA_mem = (IDAMem) ida_mem; 
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensConsistentIC", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
@@ -1556,12 +1480,12 @@ int IDAGetSensConsistentIC(void *ida_mem, N_Vector *yyS0, N_Vector *ypS0)
   }
 
   if(yyS0 != NULL) {
-    for (is=0; is<Ns; is++)
+    for (is=0; is<IDA_mem->ida_Ns; is++)
       N_VScale(ONE, IDA_mem->ida_phiS[0][is], yyS0[is]);
   }
 
   if(ypS0 != NULL) {
-    for (is=0; is<Ns; is++)
+    for (is=0; is<IDA_mem->ida_Ns; is++)
       N_VScale(ONE, IDA_mem->ida_phiS[1][is], ypS0[is]);
   }
 
@@ -1581,12 +1505,12 @@ int IDAGetSensNumResEvals(void *ida_mem, long int *nrSevals)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumResEvals", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nrSevals = nrSe;
+  *nrSevals = IDA_mem->ida_nrSe;
 
   return(IDA_SUCCESS);
 }
@@ -1604,12 +1528,12 @@ int IDAGetNumResEvalsSens(void *ida_mem, long int *nrevalsS)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetNumResEvalsSens", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nrevalsS = nreS;
+  *nrevalsS = IDA_mem->ida_nreS;
 
   return(IDA_SUCCESS);
 }
@@ -1627,12 +1551,12 @@ int IDAGetSensNumErrTestFails(void *ida_mem, long int *nSetfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumErrTestFails", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nSetfails = netfS;
+  *nSetfails = IDA_mem->ida_netfS;
 
   return(IDA_SUCCESS);
 }
@@ -1650,12 +1574,12 @@ int IDAGetSensNumLinSolvSetups(void *ida_mem, long int *nlinsetupsS)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumLinSolvSetups", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nlinsetupsS = nsetupsS;
+  *nlinsetupsS = IDA_mem->ida_nsetupsS;
 
   return(IDA_SUCCESS);
 }
@@ -1674,13 +1598,13 @@ int IDAGetSensErrWeights(void *ida_mem, N_Vector_S eSweight)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensErrWeights", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  for (is=0; is<Ns; is++)
-    N_VScale(ONE, ewtS[is], eSweight[is]);
+  for (is=0; is<IDA_mem->ida_Ns; is++)
+    N_VScale(ONE, IDA_mem->ida_ewtS[is], eSweight[is]);
 
   return(IDA_SUCCESS);
 }
@@ -1699,15 +1623,15 @@ int IDAGetSensStats(void *ida_mem, long int *nrSevals, long int *nrevalsS,
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensStats", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nrSevals = nrSe;
-  *nrevalsS = nreS;
-  *nSetfails = netfS;
-  *nlinsetupsS = nsetupsS;
+  *nrSevals = IDA_mem->ida_nrSe;
+  *nrevalsS = IDA_mem->ida_nreS;
+  *nSetfails = IDA_mem->ida_netfS;
+  *nlinsetupsS = IDA_mem->ida_nsetupsS;
 
   return(IDA_SUCCESS);
 }
@@ -1725,12 +1649,12 @@ int IDAGetSensNumNonlinSolvIters(void *ida_mem, long int *nSniters)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumNonlinSolvIters", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nSniters = nniS;
+  *nSniters = IDA_mem->ida_nniS;
 
   return(IDA_SUCCESS);
 }
@@ -1748,12 +1672,12 @@ int IDAGetSensNumNonlinSolvConvFails(void *ida_mem, long int *nSncfails)
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNumNonlinSolvConvFails", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nSncfails = ncfnS;
+  *nSncfails = IDA_mem->ida_ncfnS;
 
   return(IDA_SUCCESS);
 }
@@ -1771,13 +1695,13 @@ int IDAGetSensNonlinSolvStats(void *ida_mem, long int *nSniters, long int *nSncf
 
   IDA_mem = (IDAMem) ida_mem;
 
-  if (sensi==FALSE) {
+  if (IDA_mem->ida_sensi==SUNFALSE) {
     IDAProcessError(IDA_mem, IDA_NO_SENS, "IDAS", "IDAGetSensNonlinSolvStats", MSG_NO_SENSI);
     return(IDA_NO_SENS);
   }
 
-  *nSniters = nniS;
-  *nSncfails = ncfnS;
+  *nSniters = IDA_mem->ida_nniS;
+  *nSncfails = IDA_mem->ida_ncfnS;
 
   return(IDA_SUCCESS);
 }
diff --git a/src/idas/idas_klu.c b/src/idas/idas_klu.c
deleted file mode 100644
index 80efb38..0000000
--- a/src/idas/idas_klu.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4951 $
- * $Date: 2016-09-22 10:21:00 -0700 (Thu, 22 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDASKLU linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "idas/idas_klu.h"
-#include "idas_impl.h"
-#include "idas_sparse_impl.h"
-#include "sundials/sundials_klu_impl.h"
-#include "sundials/sundials_math.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-#define TWOTHIRDS    RCONST(0.6666666666666667)
-
-/* IDASKLU linit, lsetup, lsolve, and lfree routines */
- 
-static int IDAKLUInit(IDAMem IDA_mem);
-
-static int IDAKLUSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-		       N_Vector rrp, N_Vector tmp1,
-		       N_Vector tmp2, N_Vector tmp3);
-
-static int IDAKLUSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-			     N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDAKLUFree(IDAMem IDA_mem);
-
-/* IDAKLU lfreeB function */
-
-static int IDAKLUFreeB(IDABMem IDAB_mem);
-
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * IDAKLU
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDA / KLU linear solver module.  
- * IDAKLU first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDAKLUInit, IDAKLUSetup,
- * IDAKLUSolve, NULL, and IDAKLUFree, respectively.
- * It allocates memory for a structure of type IDAkluMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE.
- * Finally, it allocates memory for KLU.
- * The return value is IDASLS_SUCCESS = 0, IDASLS_LMEM_FAIL = -1,
- * or IDASLS_ILL_INPUT = -2.
- *
- * NOTE: The KLU linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDAKLU will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int IDAKLU(void *ida_mem, int n, int nnz, int sparsetype)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-  int flag;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDAKLU", 
-                    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDAKLU", 
-                    MSGSP_BAD_NVECTOR);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  if (IDA_mem->ida_lfree != NULL) flag = IDA_mem->ida_lfree(IDA_mem);
-
-  /* Set five main function fields in IDA_mem. */
-  IDA_mem->ida_linit  = IDAKLUInit;
-  IDA_mem->ida_lsetup = IDAKLUSetup;
-  IDA_mem->ida_lsolve = IDAKLUSolve;
-  IDA_mem->ida_lperf  = NULL;
-  IDA_mem->ida_lfree  = IDAKLUFree;
-
-  /* Get memory for IDASlsMemRec. */
-  idasls_mem = (IDASlsMem) malloc(sizeof(struct IDASlsMemRec));
-  if (idasls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDAKLU", 
-                    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* Get memory for KLUData. */
-  klu_data = (KLUData)malloc(sizeof(struct KLUDataRec));
-  if (klu_data == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDAKLU", 
-                    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  IDA_mem->ida_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  idasls_mem->s_jaceval = NULL;
-  idasls_mem->s_jacdata = NULL;
-  idasls_mem->sparsetype = sparsetype;
-
-  /* Allocate memory for the sparse Jacobian */
-  idasls_mem->s_JacMat = SparseNewMat(n, n, nnz, sparsetype);
-  if (idasls_mem->s_JacMat == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDAKLU", 
-                    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* Initialize KLU structures */
-  switch (sparsetype) {
-    case CSC_MAT:
-      klu_data->sun_klu_solve = &klu_solve;
-      break;
-    case CSR_MAT:
-      klu_data->sun_klu_solve = &klu_tsolve;
-      break;
-    default:
-      SparseDestroyMat(idasls_mem->s_JacMat);
-      free(klu_data);
-      free(idasls_mem);
-      return(IDASLS_ILL_INPUT);
-  }
-  klu_data->s_Symbolic = NULL;
-  klu_data->s_Numeric = NULL;
-
-  /* Set default parameters for KLU */
-  flag = klu_defaults(&klu_data->s_Common);
-  if (flag == 0) {
-    IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASSLS", "IDAKLU", 
-                    MSGSP_PACKAGE_FAIL);
-    return(IDASLS_PACKAGE_FAIL);
-  }
-
-  /* Set ordering to COLAMD as the idas default use.
-     Users can set a different value with IDAKLUSetOrdering,
-     and the user-set value is loaded before any call to klu_analyze in
-     IDAKLUSetup.  */
-  klu_data->s_ordering = 1;
-  klu_data->s_Common.ordering = klu_data->s_ordering;
-
-  /* Attach linear solver memory to the integrator memory */
-  idasls_mem->s_solver_data = (void *) klu_data;
-  IDA_mem->ida_lmem = idasls_mem;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDAKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to IDAKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is IDASLS_SUCCESS = 0, IDASLS_MEM_NULL = -1, 
- * IDASLS_LMEM_NULL = -2, IDASLS_ILL_INPUT = -3, or IDASLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-int IDAKLUReInit(void *ida_mem_v, int n, int nnz, int reinit_type)
-{
-  IDAMem ida_mem;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem_v == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDAKLUReInit", 
-                    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  ida_mem = (IDAMem) ida_mem_v;
-
-  /* Return immediately if ida_lmem is NULL. */
-  if (ida_mem->ida_lmem == NULL) {
-    IDAProcessError(NULL, IDASLS_LMEM_NULL, "IDASLS", "IDAKLUReInit", 
-                    MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-
-  idasls_mem = (IDASlsMem) (ida_mem->ida_lmem);
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  /* Return if reinit_type is not valid */
-  if ((reinit_type != 1) && (reinit_type != 2)) {
-    IDAProcessError(NULL, IDASLS_ILL_INPUT, "IDASLS", "IDAKLUReInit", 
-                    MSGSP_ILL_INPUT);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  if (reinit_type == 1) {
-
-    /* Destroy previous Jacobian information */
-    if (idasls_mem->s_JacMat) {
-      SparseDestroyMat(idasls_mem->s_JacMat);
-    }
-
-    /* Allocate memory for the sparse Jacobian */
-    idasls_mem->s_JacMat = SparseNewMat(n, n, nnz, idasls_mem->sparsetype);
-    if (idasls_mem->s_JacMat == NULL) {
-      IDAProcessError(ida_mem, IDASLS_MEM_FAIL, "IDASLS", "IDAKLU", 
-                      MSGSP_MEM_FAIL);
-      return(IDASLS_MEM_FAIL);
-    }
-  }
-
-  /* Free the prior factorazation and reset for first factorization */
-  if( klu_data->s_Symbolic != NULL)
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  if( klu_data->s_Numeric != NULL)
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  idasls_mem->s_first_factorize = 1;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDAKLU interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDAKLU
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int IDAKLUInit(IDAMem IDA_mem)
-{
-  IDASlsMem idasls_mem;
-
-  idasls_mem = (IDASlsMem)IDA_mem->ida_lmem;
-
-  idasls_mem->s_jacdata = IDA_mem->ida_user_data;
-
-  idasls_mem->s_nje = 0;
-  /* Force factorization every call to IDAS */
-  idasls_mem->s_first_factorize = 1;
-
-  idasls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the IDAKLU linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     IDASLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDAKLUSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-		       N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-		       N_Vector tmp3)
-{
-  int retval;
-  realtype tn, cj;
-  IDASlsMem idasls_mem;
-  IDASlsSparseJacFn jaceval;
-  KLUData klu_data;
-  SlsMat JacMat;
-  void *jacdata;
-  
-  realtype uround_twothirds;
-
-  uround_twothirds = SUNRpowerR(IDA_mem->ida_uround,TWOTHIRDS);
-
-  idasls_mem = (IDASlsMem) (IDA_mem->ida_lmem);
-  tn = IDA_mem->ida_tn; 
-  cj = IDA_mem->ida_cj;
-
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  jaceval = idasls_mem->s_jaceval;
-  jacdata = idasls_mem->s_jacdata;
-  JacMat = idasls_mem->s_JacMat;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_JAC_NOSET, "IDASSLS", "IDAKLUSetup", 
-		    MSGSP_JAC_NOSET);
-    free(idasls_mem); idasls_mem = NULL;
-    return(IDASLS_JAC_NOSET);
-  }
-
-  /* Increment nje counter and call Jacobian eval routine. */
-  idasls_mem->s_nje++;
-  retval = jaceval(tn, cj, yyp, ypp, rrp, JacMat, jacdata, 
-		   tmp1, tmp2, tmp3);
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDASLS_JACFUNC_UNRECVR, "IDASSLS", 
-		    "IDAKLUSetup", MSGSP_JACFUNC_FAILED);
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_UNRECVR;
-    return(IDASLS_JACFUNC_UNRECVR);
-  }
-  if (retval > 0) {
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  if (idasls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get the symbolic factorization
-       ------------------------------------------------------------*/ 
-    /* Update the ordering option with any user-updated values from 
-       calls to IDAKLUSetOrdering */
-    klu_data->s_Common.ordering = klu_data->s_ordering;
-
-    if (klu_data->s_Symbolic != NULL) {
-       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    }
-    klu_data->s_Symbolic = klu_analyze(JacMat->NP, JacMat->indexptrs, 
-				       JacMat->indexvals, &(klu_data->s_Common));
-    if (klu_data->s_Symbolic == NULL) {
-      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASSLS", "IDAKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(IDASLS_PACKAGE_FAIL);
-    }
-
-    /* ------------------------------------------------------------
-       Compute the LU factorization of  the Jacobian.
-       ------------------------------------------------------------*/
-    if( klu_data->s_Numeric != NULL) {
-       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    }
-    klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
-				     klu_data->s_Symbolic, &(klu_data->s_Common));
-
-    if (klu_data->s_Numeric == NULL) {
-      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "IDAKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(IDASLS_PACKAGE_FAIL);
-    }
-
-    idasls_mem->s_first_factorize = 0;
-  }
-  else {
-
-    retval = klu_refactor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
-			  klu_data->s_Symbolic, klu_data->s_Numeric,
-			  &(klu_data->s_Common));
-    if (retval == 0) {
-      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(IDASLS_PACKAGE_FAIL);
-    }
-    
-    /*-----------------------------------------------------------
-      Check if a cheap estimate of the reciprocal of the condition 
-      number is getting too small.  If so, delete
-      the prior numeric factorization and recompute it.
-      -----------------------------------------------------------*/
-    
-    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
-		       &(klu_data->s_Common));
-    if (retval == 0) {
-      IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(IDASLS_PACKAGE_FAIL);
-    }
-
-    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
-      
-      /* Condition number may be getting large.  
-	 Compute more accurate estimate */
-      retval = klu_condest(JacMat->indexptrs, JacMat->data, 
-			   klu_data->s_Symbolic, klu_data->s_Numeric,
-			   &(klu_data->s_Common));
-      if (retval == 0) {
-	IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", "idaKLUSetup", 
-			MSGSP_PACKAGE_FAIL);
-	return(IDASLS_PACKAGE_FAIL);
-      }
-      
-      if ( (klu_data->s_Common.condest) > 
-	   (1.0/uround_twothirds) ) {
-
-	/* More accurate estimate also says condition number is 
-	   large, so recompute the numeric factorization */
-
-	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-	
-	klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-					 JacMat->data, klu_data->s_Symbolic, 
-					 &(klu_data->s_Common));
-
-	if (klu_data->s_Numeric == NULL) {
-	  IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASLS", 
-			  "IDAKLUSetup", MSGSP_PACKAGE_FAIL);
-	  return(IDASLS_PACKAGE_FAIL);
-	}
-      }
-    }
-  }
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the IDAKLU linear
-  solver module.  It calls the KLU solve routine, scales the
-  solution vector according to cjratio, then returns IDASLS_SUCCESS = 0.
-*/
-
-static int IDAKLUSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-		       N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  int flag;
-  realtype cjratio;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-  SlsMat JacMat;
-  realtype *bd;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-  JacMat = idasls_mem->s_JacMat;
-  cjratio = IDA_mem->ida_cjratio;
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-  bd = N_VGetArrayPointer(b);
-
-  /* Call KLU to solve the linear system */
-  flag = klu_data->sun_klu_solve(klu_data->s_Symbolic, klu_data->s_Numeric, JacMat->NP, 1, bd, 
-                                 &(klu_data->s_Common));
-  if (flag == 0) {
-    IDAProcessError(IDA_mem, IDASLS_PACKAGE_FAIL, "IDASSLS", "IDAKLUSolve", 
-		    MSGSP_PACKAGE_FAIL);
-    return(IDASLS_PACKAGE_FAIL);
-  }
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-  return(IDASLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the IDAKLU linear solver.
-*/
-
-static int IDAKLUFree(IDAMem IDA_mem)
-{
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  if( klu_data->s_Numeric != NULL)
-  {
-     klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  }
-  if( klu_data->s_Symbolic != NULL)
-  {
-     klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  }
-
-  if (idasls_mem->s_JacMat) {
-    SparseDestroyMat(idasls_mem->s_JacMat);
-    idasls_mem->s_JacMat = NULL;
-  }
-
-  free(klu_data); 
-  free(IDA_mem->ida_lmem); 
-
-  return(IDASLS_SUCCESS);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * IDAKLUB is a wrapper around IDAKLU.
- */
-
-int IDAKLUB(void *ida_mem, int which, int n, int nnz, int sparsetype)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDASlsMemB idaslsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDAKLUB", 
-		    MSGSP_CAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASLS_NO_ADJ, "IDASSLS", "IDAKLUB",  
-		    MSGSP_NO_ADJ);
-    return(IDASLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDAKLUB", 
-		    MSGSP_BAD_WHICH);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Alloc memory for IDASlsMemRecB */
-  idaslsB_mem = (IDASlsMemB) malloc(sizeof(struct IDASlsMemRecB));
-  if (idaslsB_mem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", 
-		    "IDAKLUB", MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  
-  }
-
-  /* set matrix type and initialize Jacob function. */
-  idaslsB_mem->s_djacB = NULL;
-
-  /* Attach lmemB data and lfreeB function. */
-  IDAB_mem->ida_lmem  = idaslsB_mem;
-  IDAB_mem->ida_lfree = IDAKLUFreeB;
-
-  /* Call IDAKLU to the IDAS data of the backward problem. */
-  ida_memB = (void *)IDAB_mem->IDA_mem;
-  flag = IDAKLU(ida_memB, n, nnz, sparsetype);
-
-  if (flag != IDASLS_SUCCESS) {
-    free(idaslsB_mem);
-    idaslsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-
-/*
- * IDAKLUReInitB is a wrapper around IDAKLUReInit.
- */
-
-int IDAKLUReInitB(void *ida_mem, int which, int n, int nnz, int reinit_type)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  /* IDASlsMemB idaslsB_mem; */
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDAKLUReInitB", 
-		    MSGSP_CAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASLS_NO_ADJ, "IDASSLS", "IDAKLUReInitB",  
-		    MSGSP_NO_ADJ);
-    return(IDASLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDAKLUReInitB", 
-		    MSGSP_BAD_WHICH);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  ida_memB = (void *)(IDAB_mem->IDA_mem);
-  
-  flag = IDAKLUReInit(ida_memB, n, nnz, reinit_type);
-
-  return(flag);
-}
-
-
-/*
- * IDAKLUSetOrderingB is a wrapper around IDAKLUSetOrdering.
- */
-
-int IDAKLUSetOrderingB(void *ida_mem, int which, int ordering_choiceB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  /* IDASlsMemB idaslsB_mem; */
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDAKLUSetOrderingB", 
-		    MSGSP_CAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASLS_NO_ADJ, "IDASSLS", "IDAKLUSetOrderingB",  
-		    MSGSP_NO_ADJ);
-    return(IDASLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDAKLUSetOrderingB", 
-		    MSGSP_BAD_WHICH);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  ida_memB = (void *)(IDAB_mem->IDA_mem);
-  
-  flag = IDAKLUSetOrdering(ida_memB, ordering_choiceB);
-
-  return(flag);
-}
-
-
-/*
- * IDAKLUFreeB frees the linear solver's memory for that backward problem passed 
- * as argument. 
- */
-
-static int IDAKLUFreeB(IDABMem IDAB_mem)
-{
-  IDASlsMemB idaslsB_mem;
-
-  idaslsB_mem = (IDASlsMemB) IDAB_mem->ida_lmem;
-
-  free(idaslsB_mem);
-
-  return(0);
-}
-
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDAKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in IDA is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int IDAKLUSetOrdering(void *ida_mem_v, int ordering_choice)
-{
-  IDAMem ida_mem;
-  IDASlsMem idasls_mem;
-  KLUData klu_data;
-
- /* Return immediately if ida_mem_v is NULL */
-  if (ida_mem_v == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDAKLUSetOrdering",
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  ida_mem = (IDAMem) ida_mem_v;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) ) {
-    IDAProcessError(NULL, IDASLS_ILL_INPUT, "IDASLS", "IDAKLUSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  idasls_mem = (IDASlsMem) ida_mem->ida_lmem;
-  klu_data = (KLUData) idasls_mem->s_solver_data;
-
-  klu_data->s_ordering = ordering_choice;
-
-  return(IDASLS_SUCCESS);
-}
diff --git a/src/idas/idas_lapack.c b/src/idas/idas_lapack.c
deleted file mode 100644
index 460067f..0000000
--- a/src/idas/idas_lapack.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4909 $
- * $Date: 2016-09-14 16:51:27 -0700 (Wed, 14 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for a IDAS dense linear solver
- * using BLAS and LAPACK functions.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <idas/idas_lapack.h>
-#include "idas_direct_impl.h"
-#include "idas_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/* IDALAPACK DENSE linit, lsetup, lsolve, and lfree routines */ 
-static int idaLapackDenseInit(IDAMem IDA_mem);
-static int idaLapackDenseSetup(IDAMem IDA_mem,
-                               N_Vector yP, N_Vector ypP, N_Vector fctP, 
-                               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int idaLapackDenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                               N_Vector yC, N_Vector ypC, N_Vector fctC);
-static int idaLapackDenseFree(IDAMem IDA_mem);
-
-/* IDALAPACK BAND linit, lsetup, lsolve, and lfree routines */ 
-static int idaLapackBandInit(IDAMem IDA_mem);
-static int idaLapackBandSetup(IDAMem IDA_mem,
-                              N_Vector yP, N_Vector ypP, N_Vector fctP, 
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-static int idaLapackBandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector ypC, N_Vector fctC);
-static int idaLapackBandFree(IDAMem IDA_mem);
-
-static int IDALapackDenseFreeB(IDABMem IDAB_mem);
-static int IDALapackBandFreeB(IDABMem IDAB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define res            (IDA_mem->ida_res)
-#define nst            (IDA_mem->ida_nst)
-#define tn             (IDA_mem->ida_tn)
-#define hh             (IDA_mem->ida_hh)
-#define cj             (IDA_mem->ida_cj)
-#define cjratio        (IDA_mem->ida_cjratio)
-#define ewt            (IDA_mem->ida_ewt)
-#define constraints    (IDA_mem->ida_constraints)
-
-#define linit          (IDA_mem->ida_linit)
-#define lsetup         (IDA_mem->ida_lsetup)
-#define lsolve         (IDA_mem->ida_lsolve)
-#define lfree          (IDA_mem->ida_lfree)
-#define lperf          (IDA_mem->ida_lperf)
-#define lmem           (IDA_mem->ida_lmem)
-#define tempv          (IDA_mem->ida_tempv1)
-#define setupNonNull   (IDA_mem->ida_setupNonNull)
-
-#define mtype          (idadls_mem->d_type)
-#define n              (idadls_mem->d_n)
-#define ml             (idadls_mem->d_ml)
-#define mu             (idadls_mem->d_mu)
-#define smu            (idadls_mem->d_smu)
-#define jacDQ          (idadls_mem->d_jacDQ)
-#define djac           (idadls_mem->d_djac)
-#define bjac           (idadls_mem->d_bjac)
-#define JJ             (idadls_mem->d_J)
-#define pivots         (idadls_mem->d_pivots)
-#define nje            (idadls_mem->d_nje)
-#define nreDQ          (idadls_mem->d_nreDQ)
-#define J_data         (idadls_mem->d_J_data)
-#define last_flag      (idadls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * -----------------------------------------------------------------
- * IDALapackDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the linear solver module.  IDALapackDense first
- * calls the existing lfree routine if this is not NULL.  Then it sets
- * the ida_linit, ida_lsetup, ida_lsolve, ida_lfree fields in (*ida_mem)
- * to be idaLapackDenseInit, idaLapackDenseSetup, idaLapackDenseSolve, 
- * and idaLapackDenseFree, respectively.  It allocates memory for a 
- * structure of type IDADlsMemRec and sets the ida_lmem field in 
- * (*ida_mem) to the address of this structure.  It sets setupNonNull 
- * in (*ida_mem) to TRUE, and the d_jac field to the default 
- * idaLapackDenseDQJac. Finally, it allocates memory for M, pivots.
- *
- * The return value is SUCCESS = 0, or LMEM_FAIL = -1.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDALapackDense will first 
- *       test for a compatible N_Vector internal representation 
- *       by checking that N_VGetArrayPointer and N_VSetArrayPointer 
- *       exist.
- * -----------------------------------------------------------------
- */
-int IDALapackDense(void *ida_mem, int N)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASLAPACK", "IDALapackDense", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the LAPACK solver */
-  if (tempv->ops->nvgetarraypointer == NULL ||
-      tempv->ops->nvsetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASLAPACK", "IDALapackDense", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(IDA_mem);
-
-  /* Set four main function fields in IDA_mem */
-  linit  = idaLapackDenseInit;
-  lsetup = idaLapackDenseSetup;
-  lsolve = idaLapackDenseSolve;
-  lperf  = NULL;
-  lfree  = idaLapackDenseFree;
-
-  /* Get memory for IDADlsMemRec */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACK", "IDALapackDense", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  djac   = NULL;
-  J_data = NULL;
-
-  last_flag = IDADLS_SUCCESS;
-  idaDlsInitializeCounters(idadls_mem); 
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = (long int) N;
-
-  /* Allocate memory for JJ and pivot array */
-  JJ = NULL;
-  pivots = NULL;
-
-  JJ = NewDenseMat(n, n);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACK", "IDALapackDense", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACK", "IDALapackDense", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDALapackBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module. It first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * ida_linit, ida_lsetup, ida_lsolve, and ida_lfree fields in (*ida_mem)
- * to be idaLapackBandInit, idaLapackBandSetup, idaLapackBandSolve, 
- * and idaLapackBandFree, respectively.  It allocates memory for a 
- * structure of type IDALapackBandMemRec and sets the ida_lmem field in 
- * (*ida_mem) to the address of this structure.  It sets setupNonNull 
- * in (*ida_mem) to be TRUE, mu to be mupper, ml to be mlower, and 
- * the jacE and jacI field to NULL.
- * Finally, it allocates memory for M and pivots.
- * The IDALapackBand return value is IDADLS_SUCCESS = 0, 
- * IDADLS_MEM_FAIL = -1, or IDADLS_ILL_INPUT = -2.
- *
- * NOTE: The IDALAPACK linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDALapackBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */                  
-int IDALapackBand(void *ida_mem, int N, int mupper, int mlower)
-{
-  IDAMem IDA_mem;
-  IDADlsMem idadls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASLAPACK", "IDALapackBand", MSGD_IDAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (tempv->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASLAPACK", "IDALapackBand", MSGD_BAD_NVECTOR);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(IDA_mem);
-
-  /* Set four main function fields in IDA_mem */  
-  linit  = idaLapackBandInit;
-  lsetup = idaLapackBandSetup;
-  lsolve = idaLapackBandSolve;
-  lperf  = NULL;
-  lfree  = idaLapackBandFree;
-  
-  /* Get memory for IDADlsMemRec */
-  idadls_mem = NULL;
-  idadls_mem = (IDADlsMem) malloc(sizeof(struct IDADlsMemRec));
-  if (idadls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACK", "IDALapackBand", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  bjac   = NULL;
-  J_data = NULL;
-
-  last_flag = IDADLS_SUCCESS;
-  idaDlsInitializeCounters(idadls_mem); 
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = (long int) N;
-
-  /* Load half-bandwiths in idadls_mem */
-  ml = (long int) mlower;
-  mu = (long int) mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= n) || (mu >= n)) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASLAPACK", "IDALapackBand", MSGD_BAD_SIZES);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = mu + ml;
-
-  /* Allocate memory for JJ and pivot arrays */
-  JJ = NULL;
-  pivots = NULL;
-
-  JJ = NewBandMat(n, mu, ml, smu);
-  if (JJ == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACK", "IDALapackBand", MSGD_MEM_FAIL);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }  
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    IDAProcessError(IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACK", "IDALapackBand", MSGD_MEM_FAIL);
-    DestroyMat(JJ);
-    free(idadls_mem); idadls_mem = NULL;
-    return(IDADLS_MEM_FAIL);
-  }
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = idadls_mem;
-
-  return(IDADLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH DENSE JACOBIANS
- * =================================================================
- */
-
-/*
- * idaLapackDenseInit does remaining initializations specific to the dense
- * linear solver.
- */
-static int idaLapackDenseInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  idaDlsInitializeCounters(idadls_mem); 
-  
-  if (jacDQ) {
-    djac = idaDlsDenseDQJac;
-    J_data = IDA_mem;
-  } else {
-    J_data = IDA_mem->ida_user_data;
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackDenseSetup does the setup operations for the dense linear solver. 
- * It calls the Jacobian function to obtain the Newton matrix M = F_y + c_j*F_y', 
- * updates counters, and calls the dense LU factorization routine.
- */
-static int idaLapackDenseSetup(IDAMem IDA_mem,
-                               N_Vector yP, N_Vector ypP, N_Vector fctP,
-                               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  IDADlsMem idadls_mem;
-  int ier, retval;
-  int intn;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  intn = (int) n;
-
-  /* Call Jacobian function */
-  nje++;
-  SetToZero(JJ);
-  retval = djac(n, tn, cj, yP, ypP, fctP, JJ, J_data, tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDASLAPACK", "idaLapackDenseSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  } else if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(1);
-  }
-  
-  /* Do LU factorization of M */
-  dgetrf_f77(&intn, &intn, JJ->data, &intn, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-}
-
-/*
- * idaLapackDenseSolve handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.
- */
-static int idaLapackDenseSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                               N_Vector yC, N_Vector ypC, N_Vector fctC)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  intn = (int) n;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgetrs_f77("N", &intn, &one, JJ->data, &intn, pivots, bd, &intn, &ier, 1); 
-  if (ier > 0) return(1);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) {
-    fact = TWO/(ONE + cjratio);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackDenseFree frees memory specific to the dense linear solver.
- */
-static int idaLapackDenseFree(IDAMem IDA_mem)
-{
-  IDADlsMem  idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(pivots);
-  free(idadls_mem); 
-  idadls_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR IMPLICIT INTEGRATION WITH BAND JACOBIANS
- * =================================================================
- */
-
-/*
- * idaLapackBandInit does remaining initializations specific to the band
- * linear solver.
- */
-static int idaLapackBandInit(IDAMem IDA_mem)
-{
-  IDADlsMem idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  idaDlsInitializeCounters(idadls_mem); 
-
-  if (jacDQ) {
-    bjac = idaDlsBandDQJac;
-    J_data = IDA_mem;
-  } else {
-    J_data = IDA_mem->ida_user_data;
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackBandSetup does the setup operations for the band linear solver.
- * It calls the Jacobian function to obtain the Newton matrix M = F_y + c_j*F_y', 
- * updates counters, and calls the band LU factorization routine.
- */
-static int idaLapackBandSetup(IDAMem IDA_mem,
-                              N_Vector yP, N_Vector ypP, N_Vector fctP, 
-                              N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  IDADlsMem idadls_mem;
-  int ier, retval;
-  int intn, iml, imu, ldmat;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = JJ->ldim;
-
-  /* Call Jacobian function */
-  nje++;
-  SetToZero(JJ);
-  retval = bjac(n, mu, ml, tn, cj, yP, ypP, fctP, JJ, J_data, tmp1, tmp2, tmp3);
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDADLS_JACFUNC_UNRECVR, "IDASLAPACK", "idaLapackBandSetup", MSGD_JACFUNC_FAILED);
-    last_flag = IDADLS_JACFUNC_UNRECVR;
-    return(-1);
-  } else if (retval > 0) {
-    last_flag = IDADLS_JACFUNC_RECVR;
-    return(+1);
-  }
-  
-  /* Do LU factorization of M */
-  dgbtrf_f77(&intn, &intn, &iml, &imu, JJ->data, &ldmat, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return 1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(1);
-  return(0);
-
-}
-
-/*
- * idaLapackBandSolve handles the solve operation for the band linear solver
- * by calling the band backsolve routine.
- */
-static int idaLapackBandSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-                              N_Vector yC, N_Vector ypC, N_Vector fctC)
-{
-  IDADlsMem idadls_mem;
-  realtype *bd, fact;
-  int ier, one = 1;
-  int intn, iml, imu, ldmat;
-
-  idadls_mem = (IDADlsMem) lmem;
-
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = JJ->ldim;
-
-  bd = N_VGetArrayPointer(b);
-
-  dgbtrs_f77("N", &intn, &iml, &imu, &one, JJ->data, &ldmat, pivots, bd, &intn, &ier, 1);
-  if (ier > 0) return(1);
-
-  /* For BDF, scale the correction to account for change in cj */
-  if (cjratio != ONE) {
-    fact = TWO/(ONE + cjratio);
-    dscal_f77(&intn, &fact, bd, &one); 
-  }
-
-  last_flag = IDADLS_SUCCESS;
-  return(0);
-}
-
-/*
- * idaLapackBandFree frees memory specific to the band linear solver.
- */
-static int idaLapackBandFree(IDAMem IDA_mem)
-{
-  IDADlsMem  idadls_mem;
-
-  idadls_mem = (IDADlsMem) lmem;
-  
-  DestroyMat(JJ);
-  DestroyArray(pivots);
-  free(idadls_mem); 
-  idadls_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * IDALapackDenseB is a wrapper around IDALapackDense.
- */
-
-int IDALapackDenseB(void *ida_mem, int which, int NeqB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDADlsMemB idadlsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASLAPACK", "IDALapackDenseB", MSGD_CAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASLAPACK", "IDALapackDenseB",  MSGD_NO_ADJ);
-    return(IDADLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASLAPACK", "IDALapackDenseB", MSGD_BAD_WHICH);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Alloc memory for IDADlsMemRecB */
-  idadlsB_mem = (IDADlsMemB) malloc(sizeof(struct IDADlsMemRecB));
-  if (idadlsB_mem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACK", "IDALapackDenseB", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  
-  }
-
-  /* Set matrix type and initialize Jac function. */
-  idadlsB_mem->d_typeB = SUNDIALS_DENSE;
-  idadlsB_mem->d_bjacB = NULL;
-
-  /* Attach lmemB data and lfreeB function. */
-  IDAB_mem->ida_lmem  = idadlsB_mem;
-  IDAB_mem->ida_lfree = IDALapackDenseFreeB;
-
-  /* Call IDALapackDense to attach the IDALAPACKDENSE linear solver. */
-  ida_memB = (void *)IDAB_mem->IDA_mem;
-  flag = IDALapackDense(ida_memB, NeqB);
-
-  if (flag != IDADLS_SUCCESS) {
-    free(idadlsB_mem);
-    idadlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * IDALapackDenseFreeB frees the linear solver's memory for that backward problem passed 
- * as argument. 
- */
-
-static int IDALapackDenseFreeB(IDABMem IDAB_mem)
-{
-  IDADlsMemB idadlsB_mem;
-
-  idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
-
-  free(idadlsB_mem);
-
-  return(0);
-}
-
-/*
- * IDALapackBandB is a wrapper around IDALapackBand. It attaches the IDASLAPACKBAND linear solver
- * to the backward problem memory block.
- */
-
-int IDALapackBandB(void *ida_mem, int which,
-             int NeqB, int mupperB, int mlowerB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDADlsMemB idadlsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDADLS_MEM_NULL, "IDASLAPACKBAND", "IDALapackBandB", MSGD_CAMEM_NULL);
-    return(IDADLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDADLS_NO_ADJ, "IDASLAPACKBAND", "IDALapackBandB",  MSGD_NO_ADJ);
-    return(IDADLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDADLS_ILL_INPUT, "IDASLAPACKBAND", "IDALapackBandB", MSGD_BAD_WHICH);
-    return(IDADLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Get memory for IDADlsMemRecB */
-  idadlsB_mem = (IDADlsMemB) malloc(sizeof(struct IDADlsMemRecB));
-  if (idadlsB_mem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDADLS_MEM_FAIL, "IDASLAPACKBAND", "IDALapackBandB", MSGD_MEM_FAIL);
-    return(IDADLS_MEM_FAIL);
-  
-  }
-
-  /* set matrix type and initialize Jacob function. */
-  idadlsB_mem->d_typeB = SUNDIALS_BAND;
-  idadlsB_mem->d_bjacB = NULL;
-
-
-  /* Attach lmemB data and lfreeB function. */
-  IDAB_mem->ida_lmem  = idadlsB_mem;
-  IDAB_mem->ida_lfree = IDALapackBandFreeB;
-
-  /* Call IDALapackBand to attach the IDALAPACKBAND linear solver. */
-  ida_memB = (void *)IDAB_mem->IDA_mem;
-  flag = IDALapackBand(ida_memB, NeqB, mupperB, mlowerB);
-
-  if (flag != IDADLS_SUCCESS) {
-    free(idadlsB_mem);
-    idadlsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * IDALapackBandFreeB 
- */
-
-static int IDALapackBandFreeB(IDABMem IDAB_mem)
-{
-  IDADlsMemB idadlsB_mem;
-
-  idadlsB_mem = (IDADlsMemB) IDAB_mem->ida_lmem;
-
-  free(idadlsB_mem);
-
-  return(0);
-}
-
diff --git a/src/idas/idas_sparse.c b/src/idas/idas_sparse.c
deleted file mode 100644
index 9009457..0000000
--- a/src/idas/idas_sparse.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for an IDASSLS linear solver.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "idas_impl.h"
-#include "idas_sparse_impl.h"
-#include <sundials/sundials_math.h>
-
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-static int idaSlsSparseJacBWrapper(realtype tt, realtype c_jB,
-		            N_Vector yyB, N_Vector ypB, N_Vector rBr, 
-		            SlsMat JacMat, void *ida_mem,
-			    N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-static int idaSlsSparseJacBSWrapper(realtype tt, realtype c_jB,
-			      N_Vector yyB, N_Vector ypB, N_Vector rBr, 
-			      SlsMat JacMat, void *ida_mem,
-			      N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS FOR IMPLICIT INTEGRATION
- * =================================================================
- */
-              
-/*
- * IDASlsSetSparseJacFn specifies the sparse Jacobian function.
- */
-int IDASlsSetSparseJacFn(void *ida_mem, IDASlsSparseJacFn jac)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDASlsSetSparseJacFn", 
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_LMEM_NULL, "IDASSLS", 
-		    "IDASlsSetSparseJacFn", MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  idasls_mem->s_jaceval = jac;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * IDASlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
-int IDASlsGetNumJacEvals(void *ida_mem, long int *njevals)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDASlsGetNumJacEvals", MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_LMEM_NULL, "IDASSLS", 
-		    "IDASlsGetNumJacEvals", MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  *njevals = idasls_mem->s_nje;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * IDASlsGetReturnFlagName returns the name associated with a IDASLS
- * return value.
- */
-char *IDASlsGetReturnFlagName(long int flag)
-{
-  char *name;
-
-  name = (char *)malloc(30*sizeof(char));
-
-  switch(flag) {
-  case IDASLS_SUCCESS:
-    sprintf(name,"IDASLS_SUCCESS");
-    break;   
-  case IDASLS_MEM_NULL:
-    sprintf(name,"IDASLS_MEM_NULL");
-    break;
-  case IDASLS_LMEM_NULL:
-    sprintf(name,"IDASLS_LMEM_NULL");
-    break;
-  case IDASLS_ILL_INPUT:
-    sprintf(name,"IDASLS_ILL_INPUT");
-    break;
-  case IDASLS_MEM_FAIL:
-    sprintf(name,"IDASLS_MEM_FAIL");
-    break;
-  case IDASLS_JAC_NOSET:
-    sprintf(name,"IDASLS_JAC_NOSET");
-    break;
-  case IDASLS_JACFUNC_UNRECVR:
-    sprintf(name,"IDASLS_JACFUNC_UNRECVR");
-    break;
-  case IDASLS_JACFUNC_RECVR:
-    sprintf(name,"IDASLS_JACFUNC_RECVR");
-    break;
-  default:
-    sprintf(name,"NONE");
-  }
-
-  return(name);
-}
-
-/*
- * IDASlsGetLastFlag returns the last flag set in a IDASLS function.
- */
-int IDASlsGetLastFlag(void *ida_mem, long int *flag)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDASlsGetLastFlag", 
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  if (IDA_mem->ida_lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_LMEM_NULL, "IDASSLS", 
-		    "IDASlsGetLastFlag", MSGSP_LMEM_NULL);
-    return(IDASLS_LMEM_NULL);
-  }
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  *flag = idasls_mem->s_last_flag;
-
-  return(IDASLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- * BACKWARD INTEGRATION SUPPORT
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * EXPORTED FUNCTIONS
- * -----------------------------------------------------------------
- */
-
-int IDASlsSetSparseJacFnB(void *ida_mem, int which, IDASlsSparseJacFnB jacB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDASlsMemB idaslsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDASlsSetSparseJacFnB", 
-		    MSGSP_CAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASLS_NO_ADJ, "IDASSLS", "IDASlsSetSparseJacFnB", 
-		    MSGSP_NO_ADJ);
-    return(IDASLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", 
-		    "IDASlsSetSparseJacFnB", MSGSP_BAD_WHICH);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Get the IDAMem corresponding to this backward problem. */
-  ida_memB = (void*) IDAB_mem->IDA_mem;
-
-  if (IDAB_mem->ida_lmem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDASLS_LMEMB_NULL, 
-                    "IDASSLS", "IDASlsSetSparseJacFnB", MSGSP_LMEMB_NULL);
-    return(IDASLS_LMEMB_NULL);
-  }
-  idaslsB_mem = (IDASlsMemB) IDAB_mem->ida_lmem;
-
-  idaslsB_mem->s_djacB = jacB;
-
-  if (jacB != NULL) {
-    flag = IDASlsSetSparseJacFn(ida_memB, idaSlsSparseJacBWrapper);
-  } else {
-    flag = IDASlsSetSparseJacFn(ida_memB, NULL);
-  }
-
-  return(flag);
-}
-
-int IDASlsSetSparseJacFnBS(void *ida_mem, int which, IDASlsSparseJacFnBS jacBS)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDASlsMemB idaslsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASDLS", "IDASlsSetSparseJacFnBS", MSGSP_CAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASLS_NO_ADJ, "IDASSLS", "IDASlsSetSparseJacFnBS",  MSGSP_NO_ADJ);
-    return(IDASLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDASlsSetSparseJacFnBS", MSGSP_BAD_WHICH);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Get the IDAMem corresponding to this backward problem. */
-  ida_memB = (void*) IDAB_mem->IDA_mem;
-
-  if (IDAB_mem->ida_lmem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDASLS_LMEMB_NULL, 
-                    "IDASSLS", "IDASlsSetSparseJacFnBS", MSGSP_LMEMB_NULL);
-    return(IDASLS_LMEMB_NULL);
-  }
-  idaslsB_mem = (IDASlsMemB) IDAB_mem->ida_lmem;
-
-  idaslsB_mem->s_djacBS = jacBS;
-
-  if (jacBS != NULL) {
-    flag = IDASlsSetSparseJacFn(ida_memB, idaSlsSparseJacBSWrapper);
-  } else {
-    flag = IDASlsSetSparseJacFn(ida_memB, NULL);
-  }
-
-  return(flag);
-}
-
-/*
- * -----------------------------------------------------------------
- * PRIVATE INTERFACE FUNCTIONS
- * -----------------------------------------------------------------
- */
-
-/*
- * idaSlsSparseJacBWrapper
- *
- * This routine interfaces to the IDASlsSparseJacFnB routine provided 
- * by the user. idaSlsSparseJacBWrapper is of type IDASlsSparseJacFn.
- * NOTE: data actually contains ida_mem
- */
-
-static int idaSlsSparseJacBWrapper(realtype tt, realtype c_jB,
-                       N_Vector yyB, N_Vector ypB, N_Vector rrB,
-  		       SlsMat JacMat, void *ida_mem, 
-                       N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
-{
-  IDAadjMem IDAADJ_mem;
-  IDAMem IDA_mem;
-  IDABMem IDAB_mem;
-  IDASlsMemB idaslsB_mem;
-  int flag;
-
-  IDA_mem = (IDAMem) ida_mem;
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Get current backward problem. */
-  IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  
-  /* Get linear solver's data for this backward problem. */
-  idaslsB_mem = (IDASlsMemB) IDAB_mem->ida_lmem;
-
-  /* Forward solution from interpolation */
-  if (IDAADJ_mem->ia_noInterp == FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp, 
-			       IDAADJ_mem->ia_ypTmp, NULL, NULL);
-    if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSLS",
-		      "idaSlsSparseJacBWrapper", MSGSP_BAD_T);
-      return(-1);
-    }
-  }
-
-  /* Call user's adjoint sparse djacB routine */
-  flag = idaslsB_mem->s_djacB(tt, c_jB, 
-                              IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, 
-                              yyB, ypB, rrB, 
-                              JacMat, IDAB_mem->ida_user_data,
-                              tmp1B, tmp2B, tmp3B);
-  return(flag);
-}
-
-/*
- * idaSlsSparseJacBSWrapper
- *
- * This routine interfaces to the IDASlsSparseJacFnBS routine provided 
- * by the user. idaSlsSparseJacBSWrapper is of type IDASlsSparseJacFn.
- * NOTE: data actually contains ida_mem
- */
-
-static int idaSlsSparseJacBSWrapper(realtype tt, realtype c_jB,
-                       N_Vector yyB, N_Vector ypB, N_Vector rrB,
-  		       SlsMat JacMat, void *ida_mem, 
-                       N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
-{
-  IDAadjMem IDAADJ_mem;
-  IDAMem IDA_mem;
-  IDABMem IDAB_mem;
-  IDASlsMemB idaslsB_mem;
-  int flag;
-
-  IDA_mem = (IDAMem) ida_mem;
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Get current backward problem. */
-  IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  
-  /* Get linear solver's data for this backward problem. */
-  idaslsB_mem = (IDASlsMemB) IDAB_mem->ida_lmem;
-
-  /* Forward solution from interpolation */
-  if (IDAADJ_mem->ia_noInterp == FALSE) {
-    if (IDAADJ_mem->ia_interpSensi)
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp, 
-				 IDAADJ_mem->ia_ypTmp,
-				 IDAADJ_mem->ia_yySTmp,IDAADJ_mem->ia_yySTmp);
-    else
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp, 
-			       IDAADJ_mem->ia_ypTmp, NULL, NULL);
-    if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSLS",
-		      "idaSlsSparseJacBSWrapper", MSGSP_BAD_T);
-      return(-1);
-    }
-  }
-
-  /* Call user's adjoint sparse djacB routine */
-  flag = idaslsB_mem->s_djacBS(tt, c_jB, 
-                              IDAADJ_mem->ia_yyTmp, IDAADJ_mem->ia_ypTmp, 
-			      IDAADJ_mem->ia_yySTmp, IDAADJ_mem->ia_ypSTmp,
-			      yyB, ypB, rrB, 
-                              JacMat, IDAB_mem->ida_user_data,
-                              tmp1B, tmp2B, tmp3B);
-  return(flag);
-}
diff --git a/src/idas/idas_sparse_impl.h b/src/idas/idas_sparse_impl.h
deleted file mode 100644
index b9cedd5..0000000
--- a/src/idas/idas_sparse_impl.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Implementation header file for the IDASLS linear solvers.
- * -----------------------------------------------------------------
- */
-
-#ifndef _IDASSPARSE_IMPL_H
-#define _IDASSPARSE_IMPL_H
-
-#include "idas/idas_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * I D A S S P A R S E    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/*
- * =================================================================
- * PART I:  F O R W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASlsMemRec, IDASlsMem                             
- * -----------------------------------------------------------------
- * IDASlsMem is pointer to a IDASlsMemRec structure.
- * -----------------------------------------------------------------
- */
-
-typedef struct IDASlsMemRec {
-
-  IDASlsSparseJacFn s_jaceval; /* user Jacobian evaluation routine 
-				  to be called */
-  void *s_jacdata;           /* J_data is passed to djac or bjac */
-
-  long int s_nje;           /* nje = no. of calls to jac */
-
-  long int s_last_flag;     /* last error return flag */
-
-  int s_first_factorize;    /* flag telling whether the first 
-			       factorization needs to happen */
-  SlsMat s_JacMat;          /* J = dF/dy + cj*dF/dy' */
-  
-  int sparsetype;           /* matrix type: compressed sparse column or row */
-
-  void *s_solver_data;      /* structure for solver-specific data */
-  
-
-} *IDASlsMem;
-
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-  
-
-/*
- * =================================================================
- * PART II:  B A C K W A R D    P R O B L E M S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASlsMemRecB, IDASlsMemB       
- * -----------------------------------------------------------------
- * An IDASLS linear solver's specification function attaches such
- * a structure to the lmemB filed of IDABMem
- * -----------------------------------------------------------------
- */
-
-typedef struct IDASlsMemRecB {
-
-  IDASlsSparseJacFnB s_djacB;
-  IDASlsSparseJacFnBS s_djacBS;
-
-} *IDASlsMemB;
-
-
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
-
-#define MSGSP_IDAMEM_NULL "Integrator memory is NULL."
-#define MSGSP_BAD_NVECTOR "A required vector operation is not implemented."
-#define MSGSP_MEM_FAIL "A memory request failed."
-#define MSGSP_LMEM_NULL "Linear solver memory is NULL."
-#define MSGSP_ILL_INPUT "Invalid input detected."
-#define MSGSP_JAC_NOSET "Jacobian evaluation function has not been set."
-#define MSGSP_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
-#define MSGSP_PACKAGE_FAIL "A call to an external package failed."
-
-#define MSGSP_CAMEM_NULL "idaadj_mem = NULL illegal."
-#define MSGSP_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
-#define MSGSP_BAD_T "Bad t for interpolation."
-#define MSGSP_BAD_WHICH "Illegal value for which."
-#define MSGSP_NO_ADJ "Illegal attempt to call before calling IDAAdjInit."
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/idas/idas_spbcgs.c b/src/idas/idas_spbcgs.c
deleted file mode 100644
index 6bf329d..0000000
--- a/src/idas/idas_spbcgs.c
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4909 $
- * $Date: 2016-09-14 16:51:27 -0700 (Wed, 14 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDAS scaled preconditioned
- * Bi-CGSTAB linear solver module, IDASPBCG.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <idas/idas_spbcgs.h>
-#include "idas_spils_impl.h"
-#include "idas_impl.h"
-
-#include <sundials/sundials_spbcgs.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-#define PT9  RCONST(0.9)
-#define PT05 RCONST(0.05)
-
-/* IDASPBCG linit, lsetup, lsolve, lperf, and lfree routines */
-
-static int IDASpbcgInit(IDAMem IDA_mem);
-
-static int IDASpbcgSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int IDASpbcgSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now);
-
-static int IDASpbcgPerf(IDAMem IDA_mem, int perftask);
-
-static int IDASpbcgFree(IDAMem IDA_mem);
-
-/* IDASPBCG lfreeB function */
-
-static int IDASpbcgFreeB(IDABMem IDAB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define nst          (IDA_mem->ida_nst)
-#define tn           (IDA_mem->ida_tn)
-#define cj           (IDA_mem->ida_cj)
-#define epsNewt      (IDA_mem->ida_epsNewt)
-#define res          (IDA_mem->ida_res)
-#define user_data    (IDA_mem->ida_user_data)
-#define ewt          (IDA_mem->ida_ewt)
-#define errfp        (IDA_mem->ida_errfp)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define nni          (IDA_mem->ida_nni)
-#define ncfn         (IDA_mem->ida_ncfn)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define sqrtN     (idaspils_mem->s_sqrtN)
-#define epslin    (idaspils_mem->s_epslin)
-#define ytemp     (idaspils_mem->s_ytemp)
-#define yptemp    (idaspils_mem->s_yptemp)
-#define xx        (idaspils_mem->s_xx)
-#define ycur      (idaspils_mem->s_ycur)
-#define ypcur     (idaspils_mem->s_ypcur)
-#define rcur      (idaspils_mem->s_rcur)
-#define npe       (idaspils_mem->s_npe)
-#define nli       (idaspils_mem->s_nli)
-#define nps       (idaspils_mem->s_nps)
-#define ncfl      (idaspils_mem->s_ncfl)
-#define nst0      (idaspils_mem->s_nst0)
-#define nni0      (idaspils_mem->s_nni0)
-#define nli0      (idaspils_mem->s_nli0)
-#define ncfn0     (idaspils_mem->s_ncfn0)
-#define ncfl0     (idaspils_mem->s_ncfl0)
-#define nwarn     (idaspils_mem->s_nwarn)
-#define njtimes   (idaspils_mem->s_njtimes)
-#define nres      (idaspils_mem->s_nres)
-#define spils_mem (idaspils_mem->s_spils_mem)
-
-#define jtimesDQ  (idaspils_mem->s_jtimesDQ)
-#define jtimes    (idaspils_mem->s_jtimes)
-#define jdata     (idaspils_mem->s_jdata)
-
-#define last_flag (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcg
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDASPBCG linear solver module.
- *
- * IDASpbcg first calls the existing lfree routine if this is not NULL.
- * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASpbcgInit, IDASpbcgSetup,
- * IDASpbcgSolve, IDASpbcgPerf, and IDASpbcgFree, respectively.
- * It allocates memory for a structure of type IDASpilsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem). It then sets various fields
- * in the IDASpilsMemRec structure. Finally, IDASpbcg allocates memory
- * for ytemp, yptemp, and xx, and calls SpbcgMalloc to allocate memory
- * for the Spbcg solver.
- *
- * The return value of IDASpbcg is:
- *   IDASPILS_SUCCESS   =  0 if successful
- *   IDASPILS_MEM_FAIL  = -1 if IDA_mem is NULL or a memory
- *                           allocation failed
- *   IDASPILS_ILL_INPUT = -2 if a required vector operation is not
- *                           implemented.
- * -----------------------------------------------------------------
- */
-
-int IDASpbcg(void *ida_mem, int maxl)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-  int maxl1;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPBCG", "IDASpbcg", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPBCG", "IDASpbcg", MSGS_BAD_NVECTOR);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem */
-  linit  = IDASpbcgInit;
-  lsetup = IDASpbcgSetup;
-  lsolve = IDASpbcgSolve;
-  lperf  = IDASpbcgPerf;
-  lfree  = IDASpbcgFree;
-
-  /* Get memory for IDASpilsMemRec */
-  idaspils_mem = NULL;
-  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
-  if (idaspils_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  idaspils_mem->s_type = SPILS_SPBCG;
-
-  /* Set SPBCG parameters that were passed in call sequence */
-  maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
-  idaspils_mem->s_maxl = maxl1;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  jdata    = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  idaspils_mem->s_pset   = NULL;
-  idaspils_mem->s_psolve = NULL;
-  idaspils_mem->s_pfree  = NULL;
-  idaspils_mem->s_pdata  = IDA_mem->ida_user_data;
-
-  /* Set default values for the rest of the Spbcg parameters */
-  idaspils_mem->s_eplifac   = PT05;
-  idaspils_mem->s_dqincfac  = ONE;
-
-  idaspils_mem->s_last_flag = IDASPILS_SUCCESS;
-
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to FALSE */
-  setupNonNull = FALSE;
-
-  /* Allocate memory for ytemp, yptemp, and xx */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  yptemp = N_VClone(vec_tmpl);
-  if (yptemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  xx = N_VClone(vec_tmpl);
-  if (xx == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SpbcgMalloc to allocate workspace for Spbcg */
-  spbcg_mem = NULL;
-  spbcg_mem = SpbcgMalloc(maxl1, vec_tmpl);
-  if (spbcg_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcg", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    N_VDestroy(xx);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Attach SPBCG memory to spils memory structure */
-  spils_mem = (void *)spbcg_mem;
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idaspils_mem;
-
-  return(IDASPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASPBCG interface routines
- * -----------------------------------------------------------------
- */
-
-/* Additional readability Replacements */
-
-#define maxl     (idaspils_mem->s_maxl)
-#define eplifac  (idaspils_mem->s_eplifac)
-#define psolve   (idaspils_mem->s_psolve)
-#define pset     (idaspils_mem->s_pset)
-#define pdata    (idaspils_mem->s_pdata)
-
-static int IDASpbcgInit(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-  /* Initialize counters */
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to TRUE iff there is preconditioning with setup */
-  setupNonNull = (psolve != NULL) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = IDASpilsDQJtimes;
-    jdata = IDA_mem;
-  } else {
-    jdata = user_data;
-  }
-
-  /*  Set maxl in the SPBCG memory in case it was changed by the user */
-  spbcg_mem->l_max  = maxl;
-
-  last_flag = IDASPILS_SUCCESS;
-
-  return(0);
-}
-
-static int IDASpbcgSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  int retval;
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Call user setup routine pset and update counter npe */
-  retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata,
-                tmp1, tmp2, tmp3);
-  npe++;
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, SPBCG_PSET_FAIL_UNREC, "IDASPBCG", "IDASpbcgSetup", MSGS_PSET_FAILED);
-    last_flag = SPBCG_PSET_FAIL_UNREC;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = SPBCG_PSET_FAIL_REC;
-    return(+1);
-  }
-
-  last_flag = SPBCG_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcgSolve
- * -----------------------------------------------------------------
- * Note: The x-scaling and b-scaling arrays are both equal to weight.
- *
- * We set the initial guess, x = 0, then call SpbcgSolve.
- * We copy the solution x into b, and update the counters nli, nps,
- * and ncfl. If SpbcgSolve returned nli_inc = 0 (hence x = 0), we
- * take the SPBCG vtemp vector (= P_inverse F) as the correction
- * vector instead. Finally, we set the return value according to the
- * success of SpbcgSolve.
- * -----------------------------------------------------------------
- */
-
-static int IDASpbcgSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now)
-{
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-  int pretype, nli_inc, nps_inc, retval;
-  realtype res_norm;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  spbcg_mem = (SpbcgMem)spils_mem;
-
-  /* Set SpbcgSolve convergence test constant epslin, in terms of the
-     Newton convergence test constant epsNewt and safety factors. The factor
-     sqrt(Neq) assures that the Bi-CGSTAB convergence test is applied to the
-     WRMS norm of the residual vector, rather than the weighted L2 norm. */
-  epslin = sqrtN*eplifac*epsNewt;
-
-  /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */
-  ycur = yy_now;
-  ypcur = yp_now;
-  rcur = rr_now;
-
-  /* Set SpbcgSolve inputs pretype and initial guess xx = 0 */  
-  pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT;
-  N_VConst(ZERO, xx);
-  
-  /* Call SpbcgSolve and copy xx to bb */
-  retval = SpbcgSolve(spbcg_mem, IDA_mem, xx, bb, pretype, epslin,
-                      IDA_mem, weight, weight, IDASpilsAtimes,
-                      IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-  last_flag = retval;
-  if (nli_inc == 0) N_VScale(ONE, SPBCG_VTEMP(spbcg_mem), bb);
-  else N_VScale(ONE, xx, bb);
-  
-  /* Increment counters nli, nps, and return if successful */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPBCG_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpbcgSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPBCG_SUCCESS:
-    return(0);
-    break;
-  case SPBCG_RES_REDUCED:
-    return(1);
-    break;
-  case SPBCG_CONV_FAIL:
-    return(1);
-    break;
-  case SPBCG_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPBCG_MEM_NULL:
-    return(-1);
-    break;
-  case SPBCG_ATIMES_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPBCG_ATIMES_FAIL_UNREC, "IDaSPBCG", "IDASpbcgSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPBCG_PSOLVE_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPBCG_PSOLVE_FAIL_UNREC, "IDASPBCG", "IDASpbcgSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASpbcgPerf
- * -----------------------------------------------------------------
- * This routine handles performance monitoring specific to the
- * IDASPBCG linear solver. When perftask = 0, it saves values of
- * various counters. When perftask = 1, it examines difference
- * quotients in these counters, and depending on their values, it
- * prints up to three warning messages. Messages are printed up to
- * a maximum of 10 times.
- * -----------------------------------------------------------------
- */
-
-static int IDASpbcgPerf(IDAMem IDA_mem, int perftask)
-{
-  IDASpilsMem idaspils_mem;
-  realtype avdim, rcfn, rcfl;
-  long int nstd, nnid;
-  booleantype lavd, lcfn, lcfl;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (perftask == 0) {
-    nst0 = nst;  nni0 = nni;  nli0 = nli;
-    ncfn0 = ncfn;  ncfl0 = ncfl;  
-    nwarn = 0;
-    return(0);
-  }
-
-  nstd = nst - nst0;  nnid = nni - nni0;
-  if (nstd == 0 || nnid == 0) return(0);
-  avdim = (realtype) ((nli - nli0)/((realtype) nnid));
-  rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd));
-  rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid));
-  lavd = (avdim > ((realtype) maxl));
-  lcfn = (rcfn > PT9);
-  lcfl = (rcfl > PT9);
-  if (!(lavd || lcfn || lcfl)) return(0);
-  nwarn++;
-  if (nwarn > 10) return(1);
-  if (lavd) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_AVD_WARN, tn, avdim);
-  if (lcfn) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_CFN_WARN, tn, rcfn);
-  if (lcfl) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPBCG", "IDASpbcgPerf", MSGS_CFL_WARN, tn, rcfl);
-
-  return(0);
-}
-
-static int IDASpbcgFree(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SpbcgMem spbcg_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(yptemp);
-  N_VDestroy(xx);
-
-  spbcg_mem = (SpbcgMem)spils_mem;
-  SpbcgFree(spbcg_mem);
-
-  if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem);
-
-  free(idaspils_mem); idaspils_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/* Additional readability replacements */
-
-#define lmemB       (IDAADJ_mem->ia_lmemB)
-#define lfreeB      (IDAADJ_mem->ia_lfreeB)
-
-/*
- * IDASpbcgB
- *
- * Wrapper for the backward phase
- *
- */
-
-int IDASpbcgB(void *ida_mem, int which, int maxlB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDASpilsMemB idaspilsB_mem;
-  int flag;
-  
-  /* Check if ida_mem is allright. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPBCG", "IDASpbcgB", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASPBCG", "IDASpbcgB",  MSGS_NO_ADJ);
-    return(IDASPILS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPBCG", "IDASpbcgB", MSGS_BAD_WHICH);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  
-  /* Get memory for IDASpilsMemRecB */
-  idaspilsB_mem = NULL;
-  idaspilsB_mem = (IDASpilsMemB) malloc(sizeof(struct IDASpilsMemRecB));
-  if (idaspilsB_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPBCG", "IDASpbcgB", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  idaspilsB_mem->s_psetB = NULL;
-  idaspilsB_mem->s_psolveB = NULL;
-  idaspilsB_mem->s_P_dataB = NULL;
-
-  /* initialize Jacobian function */
-  idaspilsB_mem->s_jtimesB = NULL;
-
-  /* attach lmem and lfree */
-  IDAB_mem->ida_lmem = idaspilsB_mem;
-  IDAB_mem->ida_lfree = IDASpbcgFreeB;
-
-  flag = IDASpbcg(IDAB_mem->IDA_mem, maxlB);
-
-  if (flag != IDASPILS_SUCCESS) {
-    free(idaspilsB_mem);
-    idaspilsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * IDASpbcgFreeB 
- */
-
-static int IDASpbcgFreeB(IDABMem IDAB_mem)
-{
-  IDASpilsMemB idaspilsB_mem;
-
-  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
-
-  free(idaspilsB_mem);
-
-  return(0);
-}
diff --git a/src/idas/idas_spgmr.c b/src/idas/idas_spgmr.c
deleted file mode 100644
index 60953be..0000000
--- a/src/idas/idas_spgmr.c
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4909 $
- * $Date: 2016-09-14 16:51:27 -0700 (Wed, 14 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan C. Hindmarsh, and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDAS Scaled              
- * Preconditioned GMRES linear solver module, IDASPGMR.            
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <idas/idas_spgmr.h>
-#include "idas_spils_impl.h"
-#include "idas_impl.h"
-
-#include <sundials/sundials_spgmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define PT9          RCONST(0.9)
-#define PT05         RCONST(0.05)
-
-/* IDASPGMR linit, lsetup, lsolve, lperf, and lfree routines */
-
-static int IDASpgmrInit(IDAMem IDA_mem);
-
-static int IDASpgmrSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int IDASpgmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now);
-
-static int IDASpgmrPerf(IDAMem IDA_mem, int perftask);
-
-static int IDASpgmrFree(IDAMem IDA_mem);
-
-/* IDASPGMR lfreeB function */
-static int IDASpgmrFreeB(IDABMem IDAB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define nst          (IDA_mem->ida_nst)
-#define tn           (IDA_mem->ida_tn)
-#define cj           (IDA_mem->ida_cj)
-#define epsNewt      (IDA_mem->ida_epsNewt)
-#define res          (IDA_mem->ida_res)
-#define user_data    (IDA_mem->ida_user_data)
-#define ewt          (IDA_mem->ida_ewt)
-#define errfp        (IDA_mem->ida_errfp)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define nni          (IDA_mem->ida_nni)
-#define ncfn         (IDA_mem->ida_ncfn)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define sqrtN     (idaspils_mem->s_sqrtN)
-#define epslin    (idaspils_mem->s_epslin)
-#define ytemp     (idaspils_mem->s_ytemp)
-#define yptemp    (idaspils_mem->s_yptemp)
-#define xx        (idaspils_mem->s_xx)
-#define ycur      (idaspils_mem->s_ycur)
-#define ypcur     (idaspils_mem->s_ypcur)
-#define rcur      (idaspils_mem->s_rcur)
-#define npe       (idaspils_mem->s_npe)
-#define nli       (idaspils_mem->s_nli)
-#define nps       (idaspils_mem->s_nps)
-#define ncfl      (idaspils_mem->s_ncfl)
-#define nst0      (idaspils_mem->s_nst0)
-#define nni0      (idaspils_mem->s_nni0)
-#define nli0      (idaspils_mem->s_nli0)
-#define ncfn0     (idaspils_mem->s_ncfn0)
-#define ncfl0     (idaspils_mem->s_ncfl0)
-#define nwarn     (idaspils_mem->s_nwarn)
-#define njtimes   (idaspils_mem->s_njtimes)
-#define nres      (idaspils_mem->s_nres)
-#define spils_mem (idaspils_mem->s_spils_mem)
-
-#define jtimesDQ  (idaspils_mem->s_jtimesDQ)
-#define jtimes    (idaspils_mem->s_jtimes)
-#define jdata     (idaspils_mem->s_jdata)
-
-#define last_flag (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * IDASpgmr
- * -----------------------------------------------------------------
- *
- * This routine initializes the memory record and sets various function
- * fields specific to the IDASPGMR linear solver module.  
- *
- * IDASpgmr first calls the existing lfree routine if this is not NULL.
- * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASpgmrInit, IDASpgmrSetup,
- * IDASpgmrSolve, IDASpgmrPerf, and IDASpgmrFree, respectively.
- * It allocates memory for a structure of type IDASpilsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem).  It then various fields in the
- * IDASpilsMemRec structure. Finally, IDASpgmr allocates memory for 
- * ytemp, yptemp, and xx, and calls SpgmrMalloc to allocate memory
- * for the Spgmr solver.
- *
- * The return value of IDASpgmr is:
- *   IDASPILS_SUCCESS       = 0  if successful
- *   IDASPILS_MEM_FAIL     = -1 if IDA_mem is NULL or a memory allocation failed
- *   IDASPILS_ILL_INPUT = -2 if the gstype argument is illegal.
- *
- * -----------------------------------------------------------------
- */
-
-int IDASpgmr(void *ida_mem, int maxl)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-  SpgmrMem spgmr_mem;
-  int maxl1;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPGMR", "IDASpgmr", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Check if N_VDotProd is present */
-  if(vec_tmpl->ops->nvdotprod == NULL) {
-    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPGMR", "IDASpgmr", MSGS_BAD_NVECTOR);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem */
-  linit  = IDASpgmrInit;
-  lsetup = IDASpgmrSetup;
-  lsolve = IDASpgmrSolve;
-  lperf  = IDASpgmrPerf;
-  lfree  = IDASpgmrFree;
-
-  /* Get memory for IDASpilsMemRec */
-  idaspils_mem = NULL;
-  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
-  if (idaspils_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  idaspils_mem->s_type = SPILS_SPGMR;
-
-  /* Set SPGMR parameters that were passed in call sequence */
-  maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
-  idaspils_mem->s_maxl     = maxl1;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  jdata    = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  idaspils_mem->s_pset   = NULL;
-  idaspils_mem->s_psolve = NULL;
-  idaspils_mem->s_pfree  = NULL;
-  idaspils_mem->s_pdata  = IDA_mem->ida_user_data;
-
-  /* Set default values for the rest of the Spgmr parameters */
-  idaspils_mem->s_gstype   = MODIFIED_GS;
-  idaspils_mem->s_maxrs    = IDA_SPILS_MAXRS;
-  idaspils_mem->s_eplifac  = PT05;
-  idaspils_mem->s_dqincfac = ONE;
-
-  idaspils_mem->s_last_flag  = IDASPILS_SUCCESS;
-
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to FALSE */
-  setupNonNull = FALSE;
-
-  /* Allocate memory for ytemp, yptemp, and xx */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  yptemp = N_VClone(vec_tmpl);
-  if (yptemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  xx = N_VClone(vec_tmpl);
-  if (xx == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt( N_VDotProd(ytemp, ytemp) );
-
-  /* Call SpgmrMalloc to allocate workspace for Spgmr */
-  spgmr_mem = NULL;
-  spgmr_mem = SpgmrMalloc(maxl1, vec_tmpl);
-  if (spgmr_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    N_VDestroy(xx);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Attach SPGMR memory to spils memory structure */
-  spils_mem = (void *)spgmr_mem;
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idaspils_mem;
-
-  return(IDASPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASPGMR interface routines
- * -----------------------------------------------------------------
- */
-
-/* Additional readability Replacements */
-
-#define gstype   (idaspils_mem->s_gstype)
-#define maxl     (idaspils_mem->s_maxl)
-#define maxrs    (idaspils_mem->s_maxrs)
-#define eplifac  (idaspils_mem->s_eplifac)
-#define psolve   (idaspils_mem->s_psolve)
-#define pset     (idaspils_mem->s_pset)
-#define pdata    (idaspils_mem->s_pdata)
-
-static int IDASpgmrInit(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Initialize counters */
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to TRUE iff there is preconditioning with setup */
-  setupNonNull = (psolve != NULL) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = IDASpilsDQJtimes;
-    jdata = IDA_mem;
-  } else {
-    jdata = user_data;
-  }
-
-  last_flag = IDASPILS_SUCCESS;
-  return(0);
-}
-
-static int IDASpgmrSetup(IDAMem IDA_mem, 
-                         N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                         N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  int retval;
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Call user setup routine pset and update counter npe. */
-  retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata,
-                tmp1, tmp2, tmp3);
-  npe++;
-
-  /* Return flag showing success or failure of pset. */
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, SPGMR_PSET_FAIL_UNREC, "IDASPGMR", "IDASpgmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPGMR_PSET_FAIL_UNREC;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = SPGMR_PSET_FAIL_REC;
-    return(+1);
-  }
-
-  last_flag = SPGMR_SUCCESS;
-  return(0);
-}
-
-
-/*
- * The x-scaling and b-scaling arrays are both equal to weight.
- *  
- * We set the initial guess, x = 0, then call SpgmrSolve.  
- * We copy the solution x into b, and update the counters nli, nps, ncfl.
- * If SpgmrSolve returned nli_inc = 0 (hence x = 0), we take the SPGMR
- * vtemp vector (= P_inverse F) as the correction vector instead.
- *  Finally, we set the return value according to the success of SpgmrSolve.
- */
-
-static int IDASpgmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                         N_Vector yy_now, N_Vector yp_now, N_Vector rr_now)
-{
-  IDASpilsMem idaspils_mem;
-  SpgmrMem spgmr_mem;
-  int pretype, nli_inc, nps_inc, retval;
-  realtype res_norm;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-
-  /* Set SpgmrSolve convergence test constant epslin, in terms of the
-    Newton convergence test constant epsNewt and safety factors.  The factor 
-    sqrt(Neq) assures that the GMRES convergence test is applied to the
-    WRMS norm of the residual vector, rather than the weighted L2 norm. */
-  epslin = sqrtN*eplifac*epsNewt;
-
-  /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */
-  ycur = yy_now;
-  ypcur = yp_now;
-  rcur = rr_now;
-
-  /* Set SpgmrSolve inputs pretype and initial guess xx = 0. */  
-  pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT;
-  N_VConst(ZERO, xx);
-  
-  /* Call SpgmrSolve and copy xx to bb. */
-  retval = SpgmrSolve(spgmr_mem, IDA_mem, xx, bb, pretype, gstype, epslin,
-                      maxrs, IDA_mem, weight, weight, IDASpilsAtimes,
-                      IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  if (nli_inc == 0) N_VScale(ONE, SPGMR_VTEMP(spgmr_mem), bb);
-  else N_VScale(ONE, xx, bb);
-  
-  /* Increment counters nli, nps, and return if successful. */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPGMR_SUCCESS) ncfl++;
-
-  /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPGMR_SUCCESS:
-    return(0);
-    break;
-  case SPGMR_RES_REDUCED:
-    return(1);
-    break;
-  case SPGMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPGMR_QRFACT_FAIL:
-    return(1);
-    break;
-  case SPGMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPGMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPGMR_ATIMES_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPGMR_ATIMES_FAIL_UNREC, "IDASPGMR", "IDASpgmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPGMR_PSOLVE_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPGMR_PSOLVE_FAIL_UNREC, "IDASPGMR", "IDASpgmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  case SPGMR_GS_FAIL:
-    return(-1);
-    break;
-  case SPGMR_QRSOL_FAIL:
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * This routine handles performance monitoring specific to the IDASPGMR
- * linear solver.  When perftask = 0, it saves values of various counters.
- * When perftask = 1, it examines difference quotients in these counters,
- * and depending on their values, it prints up to three warning messages.
- * Messages are printed up to a maximum of 10 times.
- */
-
-static int IDASpgmrPerf(IDAMem IDA_mem, int perftask)
-{
-  IDASpilsMem idaspils_mem;
-  realtype avdim, rcfn, rcfl;
-  long int nstd, nnid;
-  booleantype lavd, lcfn, lcfl;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (perftask == 0) {
-    nst0 = nst;  nni0 = nni;  nli0 = nli;
-    ncfn0 = ncfn;  ncfl0 = ncfl;  
-    nwarn = 0;
-    return(0);
-  }
-
-  nstd = nst - nst0;  nnid = nni - nni0;
-  if (nstd == 0 || nnid == 0) return(0);
-  avdim = (realtype) ((nli - nli0)/((realtype) nnid));
-  rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd));
-  rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid));
-  lavd = (avdim > ((realtype) maxl ));
-  lcfn = (rcfn > PT9);
-  lcfl = (rcfl > PT9);
-  if (!(lavd || lcfn || lcfl)) return(0);
-  nwarn++;
-  if (nwarn > 10) return(1);
-  if (lavd) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_AVD_WARN, tn, avdim);
-  if (lcfn) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_CFN_WARN, tn, rcfn);
-  if (lcfl) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPGMR", "IDASpgmrPerf", MSGS_CFL_WARN, tn, rcfl);
-
-  return(0);
-}
-
-static int IDASpgmrFree(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SpgmrMem spgmr_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-  
-  N_VDestroy(ytemp);
-  N_VDestroy(yptemp);
-  N_VDestroy(xx);
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-  SpgmrFree(spgmr_mem);
-
-  if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem);
-
-  free(idaspils_mem); idaspils_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * IDASpgmrB
- *
- * Wrapper for the backward phase
- *
- */
-
-int IDASpgmrB(void *ida_mem, int which, int maxlB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDASpilsMemB idaspilsB_mem;
-  int flag;
-  
-  /* Check if ida_mem is allright. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPGMR", "IDASpbcgB", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASPGMR", "IDASpgmrB",  MSGS_NO_ADJ);
-    return(IDASPILS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPGMR", "IDASpgmrB", MSGS_BAD_WHICH);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  
-  /* Get memory for IDASpilsMemRecB */
-  idaspilsB_mem = NULL;
-  idaspilsB_mem = (IDASpilsMemB) malloc(sizeof(struct IDASpilsMemRecB));
-  if (idaspilsB_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmrB", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  idaspilsB_mem->s_psetB = NULL;
-  idaspilsB_mem->s_psolveB = NULL;
-  idaspilsB_mem->s_P_dataB = NULL;
-
-  /* initialize Jacobian function */
-  idaspilsB_mem->s_jtimesB = NULL;
-
-  /* attach lmem and lfree */
-  IDAB_mem->ida_lmem = idaspilsB_mem;
-  IDAB_mem->ida_lfree = IDASpgmrFreeB;
-
-  flag = IDASpgmr(IDAB_mem->IDA_mem, maxlB);
-
-  if (flag != IDASPILS_SUCCESS) {
-    free(idaspilsB_mem);
-    idaspilsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * IDASpgmrFreeB 
- */
-
-static int IDASpgmrFreeB(IDABMem IDAB_mem)
-{
-  IDASpilsMemB idaspilsB_mem;
-
-  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
-
-  free(idaspilsB_mem);
-
-  return(0);
-}
diff --git a/src/idas/idas_spils.c b/src/idas/idas_spils.c
index 7de6bf8..f27a044 100644
--- a/src/idas/idas_spils.c
+++ b/src/idas/idas_spils.c
@@ -1,40 +1,40 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the common implementation file for the IDAS Scaled              
- * Preconditioned Linear Solver modules.
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * This is the implementation file for the IDASPILS linear solver
+ * interface
+ *-----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "idas_spils_impl.h"
 #include "idas_impl.h"
+#include "idas_spils_impl.h"
+#include <sundials/sundials_math.h>
 
 /* Private constants */
-
 #define ZERO   RCONST(0.0)
 #define PT25   RCONST(0.25)
 #define PT05   RCONST(0.05)
+#define PT9    RCONST(0.9)
 #define ONE    RCONST(1.0)
 
 /* Algorithmic constants */
-
 #define MAX_ITERS  3  /* max. number of attempts to recover in DQ J*v */
 
 /* 
@@ -43,496 +43,614 @@
  * =================================================================
  */
 
-static int IDAAspilsPrecSetupB(realtype tt, 
-                               N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                               realtype c_jB, void *idaadj_mem,
-                               N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+static int IDAAspilsPrecSetupB(realtype tt, N_Vector yyB,
+                               N_Vector ypB, N_Vector rrB, 
+                               realtype c_jB, void *idaadj_mem);
 
-static int IDAAspilsPrecSetupBS(realtype tt, 
-                                N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                                realtype c_jB, void *idaadj_mem,
-                                N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B);
+static int IDAAspilsPrecSetupBS(realtype tt, N_Vector yyB,
+                                N_Vector ypB, N_Vector rrB, 
+                                realtype c_jB, void *idaadj_mem);
 
-static int IDAAspilsPrecSolveB(realtype tt, 
-                               N_Vector yyB, N_Vector ypB, N_Vector rrB, 
+static int IDAAspilsPrecSolveB(realtype tt, N_Vector yyB, 
+                               N_Vector ypB, N_Vector rrB, 
                                N_Vector rvecB, N_Vector zvecB,
                                realtype c_jB, realtype deltaB,
-                               void *idaadj_mem, N_Vector tmpB);
+                               void *idaadj_mem);
 
-static int IDAAspilsPrecSolveBS(realtype tt, 
-                                N_Vector yyB, N_Vector ypB, N_Vector rrB, 
+static int IDAAspilsPrecSolveBS(realtype tt, N_Vector yyB, 
+                                N_Vector ypB, N_Vector rrB, 
                                 N_Vector rvecB, N_Vector zvecB,
                                 realtype c_jB, realtype deltaB,
-                                void *idaadj_mem, N_Vector tmpB);
+                                void *idaadj_mem);
+
+static int IDAAspilsJacTimesSetupB(realtype tt, N_Vector yyB, 
+                                   N_Vector ypB, N_Vector rrB,
+                                   realtype c_jB, void *idaadj_mem);
+
+static int IDAAspilsJacTimesSetupBS(realtype tt, N_Vector yyB, 
+                                    N_Vector ypB, N_Vector rrB,
+                                    realtype c_jB, void *idaadj_mem);
 
-static int IDAAspilsJacTimesVecB(realtype tt,
-                                 N_Vector yyB, N_Vector ypB, N_Vector rrB,
+static int IDAAspilsJacTimesVecB(realtype tt, N_Vector yyB, 
+                                 N_Vector ypB, N_Vector rrB,
                                  N_Vector vB, N_Vector JvB, 
                                  realtype c_jB, void *idaadj_mem, 
                                  N_Vector tmp1B, N_Vector tmp2B);
 
-static int IDAAspilsJacTimesVecBS(realtype tt,
-                                  N_Vector yyB, N_Vector ypB, N_Vector rrB,
+static int IDAAspilsJacTimesVecBS(realtype tt, N_Vector yyB, 
+                                  N_Vector ypB, N_Vector rrB,
                                   N_Vector vB, N_Vector JvB, 
                                   realtype c_jB, void *idaadj_mem, 
                                   N_Vector tmp1B, N_Vector tmp2B);
 
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
 
-/* Readability Replacements */
-
-#define lrw1      (IDA_mem->ida_lrw1)
-#define liw1      (IDA_mem->ida_liw1)
-#define tn        (IDA_mem->ida_tn)
-#define cj        (IDA_mem->ida_cj)
-#define res       (IDA_mem->ida_res)
-#define user_data (IDA_mem->ida_user_data)
-#define ewt       (IDA_mem->ida_ewt)
-#define lmem      (IDA_mem->ida_lmem)
-
-#define ils_type  (idaspils_mem->s_type)
-#define sqrtN     (idaspils_mem->s_sqrtN)
-#define epslin    (idaspils_mem->s_epslin)
-#define ytemp     (idaspils_mem->s_ytemp)
-#define yptemp    (idaspils_mem->s_yptemp)
-#define xx        (idaspils_mem->s_xx)
-#define ycur      (idaspils_mem->s_ycur)
-#define ypcur     (idaspils_mem->s_ypcur)
-#define rcur      (idaspils_mem->s_rcur)
-#define npe       (idaspils_mem->s_npe)
-#define nli       (idaspils_mem->s_nli)
-#define nps       (idaspils_mem->s_nps)
-#define ncfl      (idaspils_mem->s_ncfl)
-#define njtimes   (idaspils_mem->s_njtimes)
-#define nres      (idaspils_mem->s_nres)
-
-#define jtimesDQ  (idaspils_mem->s_jtimesDQ)
-#define jtimes    (idaspils_mem->s_jtimes)
-#define jdata     (idaspils_mem->s_jdata)
-
-#define last_flag (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * OPTIONAL INPUT and OUTPUT
- * -----------------------------------------------------------------
- */
+/*================================================================
+  PART I - forward problems
+  ================================================================*/
 
-int IDASpilsSetGSType(void *ida_mem, int gstype)
+
+/*---------------------------------------------------------------
+  IDASSPILS Exported functions -- Required
+  ---------------------------------------------------------------*/
+
+/* IDASpilsSetLinearSolver specifies the iterative linear solver */
+int IDASpilsSetLinearSolver(void *ida_mem, SUNLinearSolver LS)
 {
+  int retval;
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if any input is NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetGSType", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "IDASpilsSetLinearSolver", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
+  if (LS == NULL) {
+    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASSPILS", 
+		    "IDASpilsSetLinearSolver", 
+                    "LS must be non-NULL");
+    return(IDASPILS_ILL_INPUT);
+  }
   IDA_mem = (IDAMem) ida_mem;
 
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetGSType", MSGS_LMEM_NULL);
-    return(IDASPILS_LMEM_NULL);
+  /* Test if solver and vector are compatible with SPILS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_ITERATIVE) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", 
+                    "Non-iterative LS supplied to IDASpils interface");
+    return(IDASPILS_ILL_INPUT);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (ils_type != SPILS_SPGMR) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetGSType", MSGS_BAD_LSTYPE);
+  if ( (IDA_mem->ida_tempv1->ops->nvdotprod == NULL) ||
+       (IDA_mem->ida_tempv1->ops->nvconst == NULL) ||
+       (IDA_mem->ida_tempv1->ops->nvscale == NULL) ||
+       (IDA_mem->ida_tempv1->ops->nvlinearsum == NULL) ) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_BAD_NVECTOR);
     return(IDASPILS_ILL_INPUT);
   }
 
-  /* Check for legal gstype */
-  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetGSType", MSGS_BAD_GSTYPE);
-    return(IDASPILS_ILL_INPUT);
+  /* free any existing system solver attached to IDA */
+  if (IDA_mem->ida_lfree)  IDA_mem->ida_lfree(IDA_mem);
+
+  /* Set four main system linear solver function fields in IDA_mem */
+  IDA_mem->ida_linit  = idaSpilsInitialize;
+  IDA_mem->ida_lsetup = idaSpilsSetup;
+  IDA_mem->ida_lsolve = idaSpilsSolve;
+  IDA_mem->ida_lperf  = idaSpilsPerf;
+  IDA_mem->ida_lfree  = idaSpilsFree;
+  
+  /* Get memory for IDASpilsMemRec */
+  idaspils_mem = NULL;
+  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
+  if (idaspils_mem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
   }
 
-  idaspils_mem->s_gstype = gstype;
+  /* set SUNLinearSolver pointer */
+  idaspils_mem->LS = LS;
+  
+  /* Set defaults for Jacobian-related fields */
+  idaspils_mem->jtimesDQ = SUNTRUE;
+  idaspils_mem->jtsetup  = NULL;
+  idaspils_mem->jtimes   = IDASpilsDQJtimes;
+  idaspils_mem->jdata    = IDA_mem;
+
+  /* Set defaults for preconditioner-related fields */
+  idaspils_mem->pset   = NULL;
+  idaspils_mem->psolve = NULL;
+  idaspils_mem->pfree  = NULL;
+  idaspils_mem->pdata  = IDA_mem->ida_user_data;
+
+  /* Set default values for the rest of the Spils parameters */
+  idaspils_mem->eplifac  = PT05;
+  idaspils_mem->dqincfac = ONE;
+
+  /* Initialize counters */
+  idaSpilsInitializeCounters(idaspils_mem);
+
+  /* Set default values for the rest of the SPILS parameters */
+  idaspils_mem->last_flag = IDASPILS_SUCCESS;
+
+  /* Attach default IDASpils interface routines to iterative LS */
+  retval = SUNLinSolSetATimes(LS, IDA_mem, IDASpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetATimes");
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_SUNLS_FAIL);
+  }
+  retval = SUNLinSolSetPreconditioner(LS, IDA_mem, NULL, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_SUNLS_FAIL);
+  }
+
+  /* Allocate memory for ytemp, yptemp and x */
+  idaspils_mem->ytemp = N_VClone(IDA_mem->ida_tempv1);
+  if (idaspils_mem->ytemp == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_MEM_FAIL);
+  }
+
+  idaspils_mem->yptemp = N_VClone(IDA_mem->ida_tempv1);
+  if (idaspils_mem->yptemp == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    N_VDestroy(idaspils_mem->ytemp);
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_MEM_FAIL);
+  }
+
+  idaspils_mem->x = N_VClone(IDA_mem->ida_tempv1);
+  if (idaspils_mem->x == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASSPILS", 
+                    "IDASpilsSetLinearSolver", MSGS_MEM_FAIL);
+    N_VDestroy(idaspils_mem->ytemp);
+    N_VDestroy(idaspils_mem->yptemp);
+    free(idaspils_mem); idaspils_mem = NULL;
+    return(IDASPILS_MEM_FAIL);
+  }
+
+  /* Compute sqrtN from a dot product */
+  N_VConst(ONE, idaspils_mem->ytemp);
+  idaspils_mem->sqrtN = SUNRsqrt( N_VDotProd(idaspils_mem->ytemp, 
+                                             idaspils_mem->ytemp) );
+
+  /* Attach linear solver memory to integrator memory */
+  IDA_mem->ida_lmem = idaspils_mem;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsSetMaxRestarts(void *ida_mem, int maxrs)
+
+/*---------------------------------------------------------------
+  IDASSPILS Exported functions -- Optional input/output
+  ---------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------*/
+int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetMaxRestarts", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsSetEpsLin", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetMaxRestarts", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsSetEpsLin", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  if (ils_type != SPILS_SPGMR) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetMaxRestarts", MSGS_BAD_LSTYPE);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  /* Check for legal maxrs */
-  if (maxrs < 0) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetMaxRestarts", MSGS_NEG_MAXRS);
+  /* Check for legal eplifac */
+  if (eplifac < ZERO) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS",
+                    "IDASpilsSetEpsLin", MSGS_NEG_EPLIFAC);
     return(IDASPILS_ILL_INPUT);
   }
 
-  idaspils_mem->s_maxrs = maxrs;
+  if (eplifac == ZERO)
+    idaspils_mem->eplifac = PT05;
+  else
+    idaspils_mem->eplifac = eplifac;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsSetMaxl(void *ida_mem, int maxl)
+
+/*---------------------------------------------------------------*/
+int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetMaxl", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsSetIncrementFactor", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetMaxl", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsSetIncrementFactor", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  if (ils_type == SPILS_SPGMR) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetMaxl", MSGS_BAD_LSTYPE);
+  /* Check for legal maxrs */
+  if (dqincfac <= ZERO) {
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS",
+                    "IDASpilsSetIncrementFactor", MSGS_NEG_DQINCFAC);
     return(IDASPILS_ILL_INPUT);
   }
 
-  idaspils_mem->s_maxl = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
+  idaspils_mem->dqincfac = dqincfac;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsSetEpsLin(void *ida_mem, realtype eplifac)
+
+/*---------------------------------------------------------------*/
+int IDASpilsSetPreconditioner(void *ida_mem,
+                              IDASpilsPrecSetupFn psetup,
+                              IDASpilsPrecSolveFn psolve)
 {
+  int retval;
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
+  PSetupFn idaspils_psetup;
+  PSolveFn idaspils_psolve;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetEpsLin", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsSetPreconditioner", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetEpsLin", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsSetPreconditioner", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  /* Check for legal maxrs */
-  if (eplifac < ZERO) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetEpsLin", MSGS_NEG_EPLIFAC);
-    return(IDASPILS_ILL_INPUT);
-  }
+  idaspils_mem->pset   = psetup;
+  idaspils_mem->psolve = psolve;
 
-  if (eplifac == ZERO)
-    idaspils_mem->s_eplifac = PT05;
-  else
-    idaspils_mem->s_eplifac = eplifac;
+  /* notify iterative linear solver to call IDASpils interface routines */
+  idaspils_psetup = (psetup == NULL) ? NULL : IDASpilsPSetup;
+  idaspils_psolve = (psolve == NULL) ? NULL : IDASpilsPSolve;
+  retval = SUNLinSolSetPreconditioner(idaspils_mem->LS, IDA_mem, 
+                                      idaspils_psetup, idaspils_psolve);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASSPILS", 
+                    "IDASpilsSetPreconditioner", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    return(IDASPILS_SUNLS_FAIL);
+  }
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsSetIncrementFactor(void *ida_mem, realtype dqincfac)
+
+/*---------------------------------------------------------------*/
+int IDASpilsSetJacTimes(void *ida_mem,
+                        IDASpilsJacTimesSetupFn jtsetup,
+                        IDASpilsJacTimesVecFn jtimes)
 {
+  int retval;
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetIncrementFactor", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsSetJacTimes", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetIncrementFactor", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsSetJacTimes", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  /* Check for legal maxrs */
-  if (dqincfac <= ZERO) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetIncrementFactor", MSGS_NEG_DQINCFAC);
-    return(IDASPILS_ILL_INPUT);
+  /* store function pointers for user-supplied routines in IDASpils 
+     interface (NULL jtimes implies use of DQ default) */
+  if (jtimes != NULL) {
+    idaspils_mem->jtimesDQ = SUNFALSE;
+    idaspils_mem->jtimes   = jtimes;
+  } else {
+    idaspils_mem->jtimesDQ = SUNTRUE;
   }
+  idaspils_mem->jtsetup = jtsetup;
 
-  idaspils_mem->s_dqincfac = dqincfac;
+  /* notify iterative linear solver to call IDASpils interface routines */
+  retval = SUNLinSolSetATimes(idaspils_mem->LS, IDA_mem, IDASpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASSPILS", 
+                    "IDASpilsSetJacTimes", 
+                    "Error in calling SUNLinSolSetATimes");
+    return(IDASPILS_SUNLS_FAIL);
+  }
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsSetPreconditioner(void *ida_mem,
-                              IDASpilsPrecSetupFn pset, IDASpilsPrecSolveFn psolve)
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS,
+                         long int *leniwLS)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetPreconditioner", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetWorkSpace", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetPreconditioner", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetWorkSpace", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  idaspils_mem->s_pset = pset;
-  idaspils_mem->s_psolve = psolve;
+  /* start with fixed sizes */
+  *lenrwLS = 4;
+  *leniwLS = 14;
 
-  return(IDASPILS_SUCCESS);
-}
-
-int IDASpilsSetJacTimesVecFn(void *ida_mem, IDASpilsJacTimesVecFn jtv)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetJacTimesVecFn", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
+  /* add N_Vector sizes */
+  if (IDA_mem->ida_tempv1->ops->nvspace) {
+    N_VSpace(IDA_mem->ida_tempv1, &lrw1, &liw1);
+    *lenrwLS += 3*lrw1;
+    *leniwLS += 3*liw1;
   }
-  IDA_mem = (IDAMem) ida_mem;
 
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
-    return(IDASPILS_LMEM_NULL);
-  }
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (jtv != NULL) {
-    jtimesDQ = FALSE;
-    jtimes = jtv;
-  } else {
-    jtimesDQ = TRUE;
+  /* add LS sizes */
+  if (idaspils_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(idaspils_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsGetWorkSpace(void *ida_mem, long int *lenrwLS, long int *leniwLS)
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
-  int maxl;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetWorkSpace", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumPrecEvals", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetWorkSpace", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumPrecEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  switch(ils_type) {
-  case SPILS_SPGMR:
-    maxl = idaspils_mem->s_maxl;
-    *lenrwLS = lrw1*(maxl + 6) + maxl*(maxl + 4) + 1;
-    *leniwLS = liw1*(maxl + 6);
-    break;
-  case SPILS_SPBCG:
-    *lenrwLS = lrw1 * 10;
-    *leniwLS = liw1 * 10;
-    break;
-  case SPILS_SPTFQMR:
-    *lenrwLS = lrw1*13;
-    *leniwLS = liw1*13;
-    break;
-  }
+  *npevals = idaspils_mem->npe;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsGetNumPrecEvals(void *ida_mem, long int *npevals)
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetNumPrecEvals", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumPrecSolves", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumPrecSolves", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *npevals = npe;
+  *npsolves = idaspils_mem->nps;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsGetNumPrecSolves(void *ida_mem, long int *npsolves)
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetNumPrecSolves", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumLinIters", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumLinIters", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *npsolves = nps;
+  *nliters = idaspils_mem->nli;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsGetNumLinIters(void *ida_mem, long int *nliters)
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetNumLinIters", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumConvFails", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetNumLinIters", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumConvFails", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *nliters = nli;
+  *nlcfails = idaspils_mem->ncfl;
 
   return(IDASPILS_SUCCESS);
 }
 
-int IDASpilsGetNumConvFails(void *ida_mem, long int *nlcfails)
+
+/*---------------------------------------------------------------*/
+int IDASpilsGetNumJTSetupEvals(void *ida_mem, long int *njtsetups)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetNumConvFails", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumJTSetupEvals", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetNumConvFails", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumJTSetupEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *nlcfails = ncfl;
+  *njtsetups = idaspils_mem->njtsetup;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumJtimesEvals(void *ida_mem, long int *njvevals)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetNumJtimesEvals", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumJtimesEvals", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *njvevals = njtimes;
+  *njvevals = idaspils_mem->njtimes;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetNumResEvals(void *ida_mem, long int *nrevalsLS)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetNumResEvals", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumResEvals", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetNumResEvals", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetNumResEvals", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *nrevalsLS = nres;
+  *nrevalsLS = idaspils_mem->nres;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsGetLastFlag(void *ida_mem, long int *flag)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
 
-  /* Return immediately if ida_mem is NULL */
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsGetLastFlag", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsGetLastFlag", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
-
-  if (lmem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", "IDASpilsGetLastFlag", MSGS_LMEM_NULL);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS",
+                    "IDASpilsGetLastFlag", MSGS_LMEM_NULL);
     return(IDASPILS_LMEM_NULL);
   }
-  idaspils_mem = (IDASpilsMem) lmem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  *flag = last_flag;
+  *flag = idaspils_mem->last_flag;
 
   return(IDASPILS_SUCCESS);
 }
 
+
+/*---------------------------------------------------------------*/
 char *IDASpilsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -558,6 +676,9 @@ char *IDASpilsGetReturnFlagName(long int flag)
   case IDASPILS_PMEM_NULL:
     sprintf(name,"IDASPILS_PMEM_NULL");
     break;
+  case IDASPILS_SUNLS_FAIL:
+    sprintf(name,"IDASPILS_SUNLS_FAIL");
+    break;
   default:
     sprintf(name,"NONE");
   }
@@ -565,78 +686,158 @@ char *IDASpilsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * -----------------------------------------------------------------
- * IDASPILS private functions
- * -----------------------------------------------------------------
- */
-
-#define psolve   (idaspils_mem->s_psolve)
-#define pdata    (idaspils_mem->s_pdata)
-#define dqincfac (idaspils_mem->s_dqincfac)
+/*-----------------------------------------------------------------
+  IDASSPILS Private functions
+  -----------------------------------------------------------------*/
 
-/*
- * This routine generates the matrix-vector product z = Jv, where
- * J is the system Jacobian, by calling either the user provided
- * routine or the internal DQ routine.
- */
+/*---------------------------------------------------------------
+  IDASpilsATimes:
 
-int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z)
+  This routine generates the matrix-vector product z = Jv, where
+  J is the system Jacobian, by calling either the user provided
+  routine or the internal DQ routine.  The return value is 
+  the same as the value returned by jtimes -- 
+  0 if successful, nonzero otherwise.
+  ---------------------------------------------------------------*/
+int IDASpilsATimes(void *ida_mem, N_Vector v, N_Vector z)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   int jtflag;
 
+  /* Return immediately if ida_mem or ida_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDASpilsATimes", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
-  idaspils_mem = (IDASpilsMem) lmem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+                    "IDASpilsATimes", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  jtflag = idaspils_mem->jtimes(IDA_mem->ida_tn,
+                                idaspils_mem->ycur,
+                                idaspils_mem->ypcur,
+                                idaspils_mem->rcur, v, z,
+                                IDA_mem->ida_cj,
+                                idaspils_mem->jdata,
+                                idaspils_mem->ytemp,
+                                idaspils_mem->yptemp);
+  idaspils_mem->njtimes++;
+  return(jtflag);
+}
 
-  jtflag = jtimes(tn, ycur, ypcur, rcur, v, z, cj, jdata, ytemp, yptemp);
-  njtimes++;
 
-  return(jtflag);
+
+/*---------------------------------------------------------------
+  IDASpilsPSetup:
+
+  This routine interfaces between the generic iterative linear 
+  solvers and the user's psetup routine.  It passes to psetup all 
+  required state information from ida_mem.  Its return value 
+  is the same as that returned by psetup. Note that the generic
+  iterative linear solvers guarantee that IDASpilsPSetup will only
+  be called in the case that the user's psetup routine is non-NULL.
+  ---------------------------------------------------------------*/
+int IDASpilsPSetup(void *ida_mem)
+{
+  int         retval;
+  IDAMem      IDA_mem;
+  IDASpilsMem idaspils_mem;
+
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "IDASpilsPSetup", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  IDA_mem = (IDAMem) ida_mem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+		    "IDASpilsPSetup", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  /* Call user pset routine to update preconditioner and possibly 
+     reset jcur (pass !jbad as update suggestion) */
+  retval = idaspils_mem->pset(IDA_mem->ida_tn, 
+                              idaspils_mem->ycur, 
+                              idaspils_mem->ypcur, 
+                              idaspils_mem->rcur, 
+                              IDA_mem->ida_cj, 
+                              idaspils_mem->pdata);
+  idaspils_mem->npe++;
+  return(retval);
 }
 
-/*
- * This routine interfaces between the generic Solve routine and
- * the user's psolve routine.  It passes to psolve all required state 
- * information from ida_mem.  Its return value is the same as that
- * returned by psolve.  Note that the generic solver guarantees
- * that IDASilsPSolve will not be called in the case psolve = NULL.
- */
 
-int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z, int lr)
+/*---------------------------------------------------------------
+  IDASpilsPSolve:
+
+  This routine interfaces between the generic SUNLinSolSolve 
+  routine and the user's psolve routine.  It passes to psolve all 
+  required state information from ida_mem.  Its return value is
+  the same as that returned by psolve.  Note that the generic 
+  SUNLinSol solver guarantees that IDASilsPSolve will not be 
+  called in the case in which preconditioning is not done. This 
+  is the only case in which the user's psolve routine is allowed 
+  to be NULL.
+  ---------------------------------------------------------------*/
+int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z,
+                   realtype tol, int lr)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
   int retval;
 
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "IDASpilsPSolve", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  retval = psolve(tn, ycur, ypcur, rcur, r, z, cj, epslin, pdata, ytemp);
-
-  /* This call is counted in nps within the IDASp**Solve routine */
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+		    "IDASpilsPSolve", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
+  retval = idaspils_mem->psolve(IDA_mem->ida_tn,
+                                idaspils_mem->ycur,
+                                idaspils_mem->ypcur,
+                                idaspils_mem->rcur, r, z, 
+                                IDA_mem->ida_cj, tol,
+                                idaspils_mem->pdata);
+  idaspils_mem->nps++;
   return(retval);
 
 }
 
-/*
- * This routine generates the matrix-vector product z = Jv, where
- * J is the system Jacobian, by using a difference quotient approximation.
- * The approximation is 
- *      Jv = [F(t,y1,yp1) - F(t,y,yp)]/sigma,  where
- *        y1 = y + sigma*v,  yp1 = yp + cj*sigma*v,
- *        sigma = sqrt(Neq)*dqincfac.
- * The return value from the call to res is saved in order to set the
- * return flag from IDASp**Solve.
- */
 
-int IDASpilsDQJtimes(realtype tt,
-                     N_Vector yy, N_Vector yp, N_Vector rr,
-                     N_Vector v, N_Vector Jv, 
-                     realtype c_j, void *data, 
-                     N_Vector work1, N_Vector work2)
+/*---------------------------------------------------------------
+  IDASpilsDQJtimes:
+
+  This routine generates a difference quotient approximation to 
+  the matrix-vector product z = Jv, where J is the system 
+  Jacobian. The approximation is 
+       Jv = [F(t,y1,yp1) - F(t,y,yp)]/sigma,  
+  where
+       y1 = y + sigma*v,  yp1 = yp + cj*sigma*v,
+       sigma = sqrt(Neq)*dqincfac.
+  The return value from the call to res is saved in order to set 
+  the return flag from IDASpilsSolve.
+  ---------------------------------------------------------------*/
+int IDASpilsDQJtimes(realtype tt, N_Vector yy, N_Vector yp,
+                     N_Vector rr, N_Vector v, N_Vector Jv, 
+                     realtype c_j, void *ida_mem, N_Vector work1, 
+                     N_Vector work2)
 {
   IDAMem IDA_mem;
   IDASpilsMem idaspils_mem;
@@ -644,21 +845,22 @@ int IDASpilsDQJtimes(realtype tt,
   realtype sig=ZERO, siginv;
   int iter, retval;
 
-  /* data is ida_mem */
-  IDA_mem = (IDAMem) data;
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  switch(ils_type) {
-  case SPILS_SPGMR:
-    sig = sqrtN*dqincfac;
-    break;
-  case SPILS_SPBCG:
-    sig = dqincfac/N_VWrmsNorm(v, ewt);
-    break;
-  case SPILS_SPTFQMR:
-    sig = dqincfac/N_VWrmsNorm(v, ewt);
-    break;
+  /* Return immediately if ida_mem or IDA_mem->ida_lmem are NULL */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "IDASpilsDQJtimes", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  IDA_mem = (IDAMem) ida_mem;
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+		    "IDASpilsDQJtimes", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
   }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  sig = idaspils_mem->sqrtN * idaspils_mem->dqincfac;  /* GMRES */
+  /*sig = idaspils_mem->dqincfac / N_VWrmsNorm(v, IDA_mem->ida_ewt);*/  /* BiCGStab/TFQMR */ 
 
   /* Rename work1 and work2 for readibility */
   y_tmp  = work1;
@@ -671,8 +873,8 @@ int IDASpilsDQJtimes(realtype tt,
     N_VLinearSum(c_j*sig, v, ONE, yp, yp_tmp);
     
     /* Call res for Jv = F(t, y_tmp, yp_tmp), and return if it failed. */
-    retval = res(tt, y_tmp, yp_tmp, Jv, user_data); 
-    nres++;
+    retval = IDA_mem->ida_res(tt, y_tmp, yp_tmp, Jv, IDA_mem->ida_user_data); 
+    idaspils_mem->nres++;
     if (retval == 0) break;
     if (retval < 0)  return(-1);
 
@@ -686,152 +888,371 @@ int IDASpilsDQJtimes(realtype tt,
   N_VLinearSum(siginv, Jv, -siginv, rr, Jv);
 
   return(0);
-
 }
 
 
-int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem)
+/*---------------------------------------------------------------
+ idaSpilsInitialize performs remaining initializations specific
+ to the iterative linear solver interface (and solver itself)
+---------------------------------------------------------------*/
+int idaSpilsInitialize(IDAMem IDA_mem)
 {
-  idaspils_mem->s_npe     = 0;
-  idaspils_mem->s_nli     = 0;
-  idaspils_mem->s_nps     = 0;
-  idaspils_mem->s_ncfl    = 0;
-  idaspils_mem->s_njtimes = 0;
-  idaspils_mem->s_nres    = 0;
+  IDASpilsMem idaspils_mem;
 
-  return(0);
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "idaSpilsInitialize", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+		    "idaSpilsInitialize", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+  
+  idaSpilsInitializeCounters(idaspils_mem);
+
+  /* Set Jacobian-related fields, based on jtimesDQ */
+  if (idaspils_mem->jtimesDQ) {
+    idaspils_mem->jtsetup = NULL;
+    idaspils_mem->jtimes  = IDASpilsDQJtimes;
+    idaspils_mem->jdata   = IDA_mem;
+  } else {
+    idaspils_mem->jdata   = IDA_mem->ida_user_data;
+  }
+
+  /* if psetup is not present, then idaSpilsSetup does not need to be 
+     called, so set the lsetup function to NULL */
+  if (idaspils_mem->pset == NULL)  IDA_mem->ida_lsetup = NULL;
+
+  /* Call LS initialize routine */
+  idaspils_mem->last_flag = SUNLinSolInitialize(idaspils_mem->LS);
+  return(idaspils_mem->last_flag);
 }
 
 
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
+/*---------------------------------------------------------------
+ idaSpilsSetup calls the LS 'setup' routine.
+---------------------------------------------------------------*/
+int idaSpilsSetup(IDAMem IDA_mem, N_Vector y, N_Vector yp, N_Vector r, 
+                  N_Vector vt1, N_Vector vt2, N_Vector vt3)
+{
+  int  retval;
+  IDASpilsMem idaspils_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "idaSpilsSetup", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+		    "idaSpilsSetup", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
+  }
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-/* Readability replacements */
+  /* Set IDASpils N_Vector pointers to inputs */
+  idaspils_mem->ycur  = y;
+  idaspils_mem->ypcur = yp;
+  idaspils_mem->rcur  = r;
 
-#define yyTmp        (IDAADJ_mem->ia_yyTmp)
-#define ypTmp        (IDAADJ_mem->ia_ypTmp)
-#define noInterp     (IDAADJ_mem->ia_noInterp)
-#define interpSensi  (IDAADJ_mem->ia_interpSensi)
-#define yySTmp      (IDAADJ_mem->ia_yySTmp)
-#define ypSTmp      (IDAADJ_mem->ia_ypSTmp)
+  /* Call LS setup routine -- the LS will call IDASpilsPSetup if applicable */
+  retval = SUNLinSolSetup(idaspils_mem->LS, NULL);
+  return(retval);
+}
 
-/*
- * -----------------------------------------------------------------
- * OPTIONAL INPUT and OUTPUT FUNCTIONS
- * -----------------------------------------------------------------
- */
 
-int IDASpilsSetGSTypeB(void *ida_mem, int which, int gstypeB)
+/*---------------------------------------------------------------
+ idaSpilsSolve: interfaces between IDA and the generic 
+ SUNLinearSolver object LS, by setting the appropriate tolerance 
+ and scaling vectors, calling the solver, and accumulating 
+ statistics from the solve for use/reporting by IDA.
+---------------------------------------------------------------*/
+int idaSpilsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                  N_Vector ycur, N_Vector ypcur, N_Vector rescur)
 {
-  IDAadjMem IDAADJ_mem;
-  IDAMem IDA_mem;
-  IDABMem IDAB_mem;
-  void *ida_memB;
+  IDASpilsMem idaspils_mem;
+  int nli_inc, retval;
   
-  /* Check if ida_mem is allright. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetGSTypeB", MSGS_IDAMEM_NULL);
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "idaSpilsSolve", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", "IDASpilsSetGSTypeB",  MSGS_NO_ADJ);
-    return(IDASPILS_NO_ADJ);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+		    "idaSpilsSolve", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
   }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetGSTypeB", MSGS_BAD_WHICH);
-    return(IDASPILS_ILL_INPUT);
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  /* Set convergence test constant epslin, in terms of the
+     Newton convergence test constant epsNewt and safety factors. The factor
+     sqrt(Neq) assures that the convergence test is applied to the WRMS norm 
+     of the residual vector, rather than the weighted L2 norm. */
+  idaspils_mem->epslin = idaspils_mem->sqrtN *
+    idaspils_mem->eplifac * IDA_mem->ida_epsNewt;
+
+  /* Set vectors ycur, ypcur and rcur for use by the Atimes and 
+     Psolve interface routines */
+  idaspils_mem->ycur  = ycur;
+  idaspils_mem->ypcur = ypcur;
+  idaspils_mem->rcur  = rescur;
+
+  /* Set initial guess x = 0 to LS */  
+  N_VConst(ZERO, idaspils_mem->x);
+
+  /* Set scaling vectors for LS to use */
+  retval = SUNLinSolSetScalingVectors(idaspils_mem->LS, weight, weight);
+  if (retval != SUNLS_SUCCESS) {
+    IDAProcessError(IDA_mem, IDASPILS_SUNLS_FAIL, "IDASPILS", "idaSpilsSolve", 
+                    "Error in calling SUNLinSolSetScalingVectors");
+    return(IDASPILS_SUNLS_FAIL);
+  }
+
+  /* If a user-provided jtsetup routine is supplied, call that here */
+  if (idaspils_mem->jtsetup) {
+    retval = idaspils_mem->jtsetup(IDA_mem->ida_tn, ycur, ypcur, rescur,
+                                   IDA_mem->ida_cj, idaspils_mem->jdata);
+    idaspils_mem->njtsetup++;
+    if (retval != 0) {
+      IDAProcessError(IDA_mem, retval, "IDASPILS", 
+                      "idaSpilsSolve", MSGS_JTSETUP_FAILED);
+      return(retval);
+    }
   }
+  
+  /* Call solver */
+  retval = SUNLinSolSolve(idaspils_mem->LS, NULL, idaspils_mem->x,
+                          b, idaspils_mem->epslin);
 
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-  /* ida_mem corresponding to 'which' problem. */
-  ida_memB = (void *) IDAB_mem->IDA_mem;
+  /* Retrieve solver statistics */
+  nli_inc = SUNLinSolNumIters(idaspils_mem->LS);
+  
+  /* Copy x (or preconditioned residual vector if no iterations required) to b */
+  if (nli_inc == 0) N_VScale(ONE, SUNLinSolResid(idaspils_mem->LS), b);
+  else N_VScale(ONE, idaspils_mem->x, b);
 
-  /* Call the corresponding Set* function for the backward problem. */
-  return IDASpilsSetGSType(ida_memB, gstypeB);
+  /* Increment counters nli and ncfl */
+  idaspils_mem->nli += nli_inc;
+  if (retval != SUNLS_SUCCESS) idaspils_mem->ncfl++;
+
+  /* Interpret solver return value  */
+  idaspils_mem->last_flag = retval;
+
+  switch(retval) {
+
+  case SUNLS_SUCCESS:
+    return(0);
+    break;
+  case SUNLS_RES_REDUCED:
+  case SUNLS_CONV_FAIL:
+  case SUNLS_ATIMES_FAIL_REC:
+  case SUNLS_PSOLVE_FAIL_REC:
+  case SUNLS_PACKAGE_FAIL_REC:
+  case SUNLS_QRFACT_FAIL:
+  case SUNLS_LUFACT_FAIL:
+    return(1);
+    break;
+  case SUNLS_MEM_NULL:
+  case SUNLS_ILL_INPUT:
+  case SUNLS_MEM_FAIL:
+  case SUNLS_GS_FAIL:
+  case SUNLS_QRSOL_FAIL:
+    return(-1);
+    break;
+  case SUNLS_PACKAGE_FAIL_UNREC:
+    IDAProcessError(IDA_mem, SUNLS_PACKAGE_FAIL_UNREC, "IDASSPILS", 
+                    "idaSpilsSolve",
+                    "Failure in SUNLinSol external package");
+    return(-1);
+    break;
+  case SUNLS_ATIMES_FAIL_UNREC:
+    IDAProcessError(IDA_mem, SUNLS_ATIMES_FAIL_UNREC, "IDASSPILS", 
+                    "idaSpilsSolve", MSGS_JTIMES_FAILED);    
+    return(-1);
+    break;
+  case SUNLS_PSOLVE_FAIL_UNREC:
+    IDAProcessError(IDA_mem, SUNLS_PSOLVE_FAIL_UNREC, "IDASSPILS", 
+                    "idaSpilsSolve", MSGS_PSOLVE_FAILED);
+    return(-1);
+    break;
+  }
+  
+  return(0); 
 }
 
-int IDASpilsSetMaxRestartsB(void *ida_mem, int which, int maxrsB)
+
+/*---------------------------------------------------------------
+ idaSpilsPerf: accumulates performance statistics information 
+ for IDA
+---------------------------------------------------------------*/
+int idaSpilsPerf(IDAMem IDA_mem, int perftask)
 {
-  IDAadjMem IDAADJ_mem;
-  IDAMem IDA_mem;
-  IDABMem IDAB_mem;
-  void *ida_memB;
-  
-  /* Check if ida_mem is allright. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetMaxRestartsB", MSGS_IDAMEM_NULL);
+  IDASpilsMem idaspils_mem;
+  realtype rcfn, rcfl;
+  long int nstd, nnid;
+  booleantype lcfn, lcfl;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+		    "idaSpilsPerf", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", "IDASpilsSetMaxRestartsB",  MSGS_NO_ADJ);
-    return(IDASPILS_NO_ADJ);
+  if (IDA_mem->ida_lmem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEM_NULL, "IDASSPILS", 
+		    "idaSpilsPerf", MSGS_LMEM_NULL);
+    return(IDASPILS_LMEM_NULL);
   }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
 
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetMaxRestartsB", MSGS_BAD_WHICH);
-    return(IDASPILS_ILL_INPUT);
+  /* when perftask == 0, store current performance statistics */
+  if (perftask == 0) {
+    idaspils_mem->nst0  = IDA_mem->ida_nst;
+    idaspils_mem->nni0  = IDA_mem->ida_nni;
+    idaspils_mem->ncfn0 = IDA_mem->ida_ncfn;
+    idaspils_mem->ncfl0 = idaspils_mem->ncfl;  
+    idaspils_mem->nwarn = 0;
+    return(0);
   }
 
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
+  /* Compute statistics since last call
+
+     Note: the performance monitor that checked whether the average 
+       number of linear iterations was too close to maxl has been 
+       removed, since the 'maxl' value is no longer owned by the 
+       IDASpils interface.
+   */
+  nstd = IDA_mem->ida_nst - idaspils_mem->nst0;
+  nnid = IDA_mem->ida_nni - idaspils_mem->nni0;
+  if (nstd == 0 || nnid == 0) return(0);
+  
+  rcfn = (realtype) ( (IDA_mem->ida_ncfn - idaspils_mem->ncfn0) /
+                      ((realtype) nstd) );
+  rcfl = (realtype) ( (idaspils_mem->ncfl - idaspils_mem->ncfl0) /
+                      ((realtype) nnid) );
+  lcfn = (rcfn > PT9);
+  lcfl = (rcfl > PT9);
+  if (!(lcfn || lcfl)) return(0);
+  idaspils_mem->nwarn++;
+  if (idaspils_mem->nwarn > 10) return(1);
+  if (lcfn) 
+    IDAProcessError(IDA_mem, IDA_WARNING, "IDASSPILS", "idaSpilsPerf",
+                    MSGS_CFN_WARN, IDA_mem->ida_tn, rcfn);
+  if (lcfl) 
+    IDAProcessError(IDA_mem, IDA_WARNING, "IDASSPILS", "idaSpilsPerf",
+                    MSGS_CFL_WARN, IDA_mem->ida_tn, rcfl);
+  return(0);
+}
+
+
+/*---------------------------------------------------------------
+ idaSpilsFree frees memory associates with the IDASpils system
+ solver interface.
+---------------------------------------------------------------*/
+int idaSpilsFree(IDAMem IDA_mem)
+{
+  IDASpilsMem idaspils_mem;
+
+  /* Return immediately if IDA_mem or IDA_mem->ida_lmem are NULL */
+  if (IDA_mem == NULL)  return (IDASPILS_SUCCESS);
+  if (IDA_mem->ida_lmem == NULL)  return(IDASPILS_SUCCESS);
+  idaspils_mem = (IDASpilsMem) IDA_mem->ida_lmem;
+
+  /* Free N_Vector memory */
+  if (idaspils_mem->ytemp) {
+    N_VDestroy(idaspils_mem->ytemp);
+    idaspils_mem->ytemp = NULL;
   }
-  /* ida_mem corresponding to 'which' problem. */
-  ida_memB = (void *) IDAB_mem->IDA_mem;
+  if (idaspils_mem->yptemp) {
+    N_VDestroy(idaspils_mem->yptemp);
+    idaspils_mem->yptemp = NULL;
+  }
+  if (idaspils_mem->x) {
+    N_VDestroy(idaspils_mem->x);
+    idaspils_mem->x = NULL;
+  }
+
+  /* Nullify other N_Vector pointers */
+  idaspils_mem->ycur  = NULL;
+  idaspils_mem->ypcur = NULL;
+  idaspils_mem->rcur  = NULL;
+
+  /* Free preconditioner memory (if applicable) */
+  if (idaspils_mem->pfree)  idaspils_mem->pfree(IDA_mem);
+  
+  /* free IDASpils interface structure */
+  free(IDA_mem->ida_lmem);
+  
+  return(IDASPILS_SUCCESS);
+}
+
+
+/*---------------------------------------------------------------
+ idaSpilsInitializeCounters resets all counters from an 
+ IDASpilsMem structure.
+---------------------------------------------------------------*/
+int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem)
+{
+  idaspils_mem->npe      = 0;
+  idaspils_mem->nli      = 0;
+  idaspils_mem->nps      = 0;
+  idaspils_mem->ncfl     = 0;
+  idaspils_mem->njtsetup = 0;
+  idaspils_mem->njtimes  = 0;
+  idaspils_mem->nres     = 0;
 
-  /* Call the corresponding Set* function for the backward problem. */
-  return IDASpilsSetMaxRestarts(ida_memB,maxrsB);
+  return(0);
 }
 
-int IDASpilsSetEpsLinB(void *ida_mem, int which, realtype eplifacB)
+
+/*================================================================
+  PART II - backward problems
+  ================================================================*/
+
+
+/*---------------------------------------------------------------
+  IDASSPILS Exported functions -- Required
+  ---------------------------------------------------------------*/
+
+/* IDASpilsSetLinearSolverB specifies the iterative linear solver 
+   for backward integration */
+int IDASpilsSetLinearSolverB(void *ida_mem, int which,
+                             SUNLinearSolver LS)
 {
-  IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
+  IDAadjMem IDAADJ_mem;
   IDABMem IDAB_mem;
+  IDASpilsMemB idaspilsB_mem;
   void *ida_memB;
-  
-  /* Check if ida_mem is allright. */
+  int flag;
+
+  /* Is ida_mem allright? */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetEpsLinB", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsSetLinearSolverB", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", "IDASpilsSetEpsLinB",  MSGS_NO_ADJ);
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS",
+                    "IDASpilsSetLinearSolverB",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetEpsLinB", MSGS_BAD_WHICH);
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS",
+                    "IDASpilsSetLinearSolverB", MSGS_BAD_WHICH);
     return(IDASPILS_ILL_INPUT);
   }
 
@@ -842,14 +1263,50 @@ int IDASpilsSetEpsLinB(void *ida_mem, int which, realtype eplifacB)
     /* advance */
     IDAB_mem = IDAB_mem->ida_next;
   }
-  /* ida_mem corresponding to 'which' problem. */
-  ida_memB = (void *) IDAB_mem->IDA_mem;
 
-  /* Call the corresponding Set* function for the backward problem. */
-  return IDASpilsSetEpsLin(ida_memB, eplifacB);
+  /* Get memory for IDASpilsMemRecB */
+  idaspilsB_mem = NULL;
+  idaspilsB_mem = (IDASpilsMemB) malloc(sizeof(struct IDASpilsMemRecB));
+  if (idaspilsB_mem == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPGMR", "IDASpgmrB", MSGS_MEM_FAIL);
+    return(IDASPILS_MEM_FAIL);
+  }
+
+  /* initialize Jacobian and preconditioner functions */
+  idaspilsB_mem->jtsetupB  = NULL;
+  idaspilsB_mem->jtsetupBS = NULL;
+  idaspilsB_mem->jtimesB   = NULL;
+  idaspilsB_mem->jtimesBS  = NULL;
+  idaspilsB_mem->psetB     = NULL;
+  idaspilsB_mem->psetBS    = NULL;
+  idaspilsB_mem->psolveB   = NULL;
+  idaspilsB_mem->psolveBS  = NULL;
+  idaspilsB_mem->P_dataB   = NULL;
+
+  /* free any existing system solver attached to IDAB */
+  if (IDAB_mem->ida_lfree)  IDAB_mem->ida_lfree(IDAB_mem);
+
+  /* Attach lmemB data and lfreeB function. */
+  IDAB_mem->ida_lmem  = idaspilsB_mem;
+  IDAB_mem->ida_lfree = idaSpilsFreeB;
+
+  /* set the linear solver for this backward problem */
+  ida_memB = (void *)IDAB_mem->IDA_mem;
+  flag = IDASpilsSetLinearSolver(ida_memB, LS);
+  if (flag != IDASPILS_SUCCESS) {
+    free(idaspilsB_mem);
+    idaspilsB_mem = NULL;
+  }
+
+  return(flag);
 }
 
-int IDASpilsSetMaxlB(void *ida_mem, int which, int maxlB)
+
+/*---------------------------------------------------------------
+  IDASSPILS Exported functions -- Optional input/output
+  ---------------------------------------------------------------*/
+
+int IDASpilsSetEpsLinB(void *ida_mem, int which, realtype eplifacB)
 {
   IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
@@ -858,25 +1315,28 @@ int IDASpilsSetMaxlB(void *ida_mem, int which, int maxlB)
   
   /* Check if ida_mem is allright. */
   if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", "IDASpilsSetMaxlB", MSGS_IDAMEM_NULL);
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS",
+                    "IDASpilsSetEpsLinB", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", "IDASpilsSetMaxlB",  MSGS_NO_ADJ);
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS",
+                    "IDASpilsSetEpsLinB",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
 
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", "IDASpilsSetMaxlB", MSGS_BAD_WHICH);
+    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS",
+                    "IDASpilsSetEpsLinB", MSGS_BAD_WHICH);
     return(IDASPILS_ILL_INPUT);
   }
 
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
+  /* Find the IDABMem entry in the linked list corresponding to 'which' */
   IDAB_mem = IDAADJ_mem->IDAB_mem;
   while (IDAB_mem != NULL) {
     if( which == IDAB_mem->ida_index ) break;
@@ -886,11 +1346,14 @@ int IDASpilsSetMaxlB(void *ida_mem, int which, int maxlB)
   /* ida_mem corresponding to 'which' problem. */
   ida_memB = (void *) IDAB_mem->IDA_mem;
 
-  /* Call the corresponding Set* function for the backward problem. */
-  return IDASpilsSetMaxl(ida_memB, maxlB);
+  /* Call the corresponding Set* function for the backward problem */
+  return IDASpilsSetEpsLin(ida_memB, eplifacB);
 }
 
-int IDASpilsSetIncrementFactorB(void *ida_mem, int which, realtype dqincfacB)
+
+/*---------------------------------------------------------------*/
+int IDASpilsSetIncrementFactorB(void *ida_mem, int which,
+                                realtype dqincfacB)
 {
   IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
@@ -906,7 +1369,7 @@ int IDASpilsSetIncrementFactorB(void *ida_mem, int which, realtype dqincfacB)
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
                     "IDASpilsSetIncrementFactorB",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
@@ -934,14 +1397,19 @@ int IDASpilsSetIncrementFactorB(void *ida_mem, int which, realtype dqincfacB)
   return IDASpilsSetIncrementFactor(ida_memB, dqincfacB);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsSetPreconditionerB(void *ida_mem, int which, 
-                               IDASpilsPrecSetupFnB psetB, IDASpilsPrecSolveFnB psolveB)
+                               IDASpilsPrecSetupFnB psetupB,
+                               IDASpilsPrecSolveFnB psolveB)
 {
   IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
   IDABMem IDAB_mem;
   void *ida_memB;
   IDASpilsMemB idaspilsB_mem;
+  IDASpilsPrecSetupFn idaspils_psetup;
+  IDASpilsPrecSolveFn idaspils_psolve;
   
   /* Check if ida_mem is allright. */
   if (ida_mem == NULL) {
@@ -952,7 +1420,7 @@ int IDASpilsSetPreconditionerB(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
                     "IDASpilsSetPreconditionerB",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
@@ -986,18 +1454,19 @@ int IDASpilsSetPreconditionerB(void *ida_mem, int which,
   idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
 
   /* Set preconditioners for the backward problem. */
-  idaspilsB_mem->s_psetB   = psetB;
-  idaspilsB_mem->s_psolveB = psolveB;
+  idaspilsB_mem->psetB   = psetupB;
+  idaspilsB_mem->psolveB = psolveB;
 
-  if (psetB == NULL) {
-    return IDASpilsSetPreconditioner(ida_memB, NULL, IDAAspilsPrecSolveB);
-  } else {
-    return IDASpilsSetPreconditioner(ida_memB, IDAAspilsPrecSetupB, IDAAspilsPrecSolveB);
-  }
+  /* Call the corresponding "set" routine for the backward problem */
+  idaspils_psetup = (psetupB == NULL) ? NULL : IDAAspilsPrecSetupB;
+  idaspils_psolve = (psolveB == NULL) ? NULL : IDAAspilsPrecSolveB;
+  return IDASpilsSetPreconditioner(ida_memB, idaspils_psetup, idaspils_psolve);
 }
 
+
+/*---------------------------------------------------------------*/
 int IDASpilsSetPreconditionerBS(void *ida_mem, int which, 
-                                IDASpilsPrecSetupFnBS psetBS,
+                                IDASpilsPrecSetupFnBS psetupBS,
                                 IDASpilsPrecSolveFnBS psolveBS)
 {
   IDAadjMem IDAADJ_mem;
@@ -1005,6 +1474,8 @@ int IDASpilsSetPreconditionerBS(void *ida_mem, int which,
   IDABMem IDAB_mem;
   void *ida_memB;
   IDASpilsMemB idaspilsB_mem;
+  IDASpilsPrecSetupFn idaspils_psetup;
+  IDASpilsPrecSolveFn idaspils_psolve;
   
   /* Check if ida_mem is allright. */
   if (ida_mem == NULL) {
@@ -1015,7 +1486,7 @@ int IDASpilsSetPreconditionerBS(void *ida_mem, int which,
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
                     "IDASpilsSetPreconditionerBS",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
@@ -1049,38 +1520,41 @@ int IDASpilsSetPreconditionerBS(void *ida_mem, int which,
   idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
 
   /* Set preconditioners for the backward problem. */
-  idaspilsB_mem->s_psetBS   = psetBS;
-  idaspilsB_mem->s_psolveBS = psolveBS;
+  idaspilsB_mem->psetBS   = psetupBS;
+  idaspilsB_mem->psolveBS = psolveBS;
 
-  if (psetBS == NULL) {
-    return IDASpilsSetPreconditioner(ida_memB, NULL, IDAAspilsPrecSolveBS);
-  } else {
-    return IDASpilsSetPreconditioner(ida_memB, IDAAspilsPrecSetupBS, IDAAspilsPrecSolveBS);
-  }
+  /* Call the corresponding "set" routine for the backward problem */
+  idaspils_psetup = (psetupBS == NULL) ? NULL : IDAAspilsPrecSetupBS;
+  idaspils_psolve = (psolveBS == NULL) ? NULL : IDAAspilsPrecSolveBS;
+  return IDASpilsSetPreconditioner(ida_memB, idaspils_psetup, idaspils_psolve);
 }
 
 
-int IDASpilsSetJacTimesVecFnB(void *ida_mem, int which, IDASpilsJacTimesVecFnB jtvB)
+/*---------------------------------------------------------------*/
+int IDASpilsSetJacTimesB(void *ida_mem, int which,
+                         IDASpilsJacTimesSetupFnB jtsetupB,
+                         IDASpilsJacTimesVecFnB jtimesB)
 {
   IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
   IDABMem IDAB_mem;
-  IDASpilsMemB idaspilsB_mem;
   void *ida_memB;
-  int flag;
+  IDASpilsMemB idaspilsB_mem;
+  IDASpilsJacTimesSetupFn idaspils_jtsetup;
+  IDASpilsJacTimesVecFn idaspils_jtimes;
   
   /* Check if ida_mem is allright. */
   if (ida_mem == NULL) {
     IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnB", MSGS_IDAMEM_NULL);
+                    "IDASpilsSetJacTimesB", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnB",  MSGS_NO_ADJ);
+                    "IDASpilsSetJacTimesB",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
@@ -1088,7 +1562,7 @@ int IDASpilsSetJacTimesVecFnB(void *ida_mem, int which, IDASpilsJacTimesVecFnB j
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnB", MSGS_BAD_WHICH);
+                    "IDASpilsSetJacTimesB", MSGS_BAD_WHICH);
     return(IDASPILS_ILL_INPUT);
   }
 
@@ -1104,45 +1578,49 @@ int IDASpilsSetJacTimesVecFnB(void *ida_mem, int which, IDASpilsJacTimesVecFnB j
 
   if ( IDAB_mem->ida_lmem == NULL) {
     IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnB", MSGS_LMEMB_NULL);
+                    "IDASpilsSetJacTimesB", MSGS_LMEMB_NULL);
     return(IDASPILS_ILL_INPUT);
   }
 
+  /* Get the IDASpilsMemB data */
   idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
 
-  /* Call the corresponding Set* function for the backward problem. */
-
-  idaspilsB_mem->s_jtimesB   = jtvB;
-
-  if (jtvB != NULL) {
-    flag = IDASpilsSetJacTimesVecFn(ida_memB, IDAAspilsJacTimesVecB);
-  } else {
-    flag = IDASpilsSetJacTimesVecFn(ida_memB, NULL);
-  }
-  return(flag);
+  /* Set jacobian routines for the backward problem. */
+  idaspilsB_mem->jtsetupB = jtsetupB;
+  idaspilsB_mem->jtimesB  = jtimesB;
+  
+  /* Call the corresponding "set" routine for the backward problem */
+  idaspils_jtsetup = (jtsetupB == NULL) ? NULL : IDAAspilsJacTimesSetupB;
+  idaspils_jtimes  = (jtimesB == NULL)  ? NULL : IDAAspilsJacTimesVecB;
+  return IDASpilsSetJacTimes(ida_memB, idaspils_jtsetup, idaspils_jtimes);
 }
 
-int IDASpilsSetJacTimesVecFnBS(void *ida_mem, int which, IDASpilsJacTimesVecFnBS jtvBS)
+
+/*---------------------------------------------------------------*/
+int IDASpilsSetJacTimesBS(void *ida_mem, int which,
+                          IDASpilsJacTimesSetupFnBS jtsetupBS,
+                          IDASpilsJacTimesVecFnBS jtimesBS)
 {
   IDAadjMem IDAADJ_mem;
   IDAMem IDA_mem;
   IDABMem IDAB_mem;
-  IDASpilsMemB idaspilsB_mem;
   void *ida_memB;
-  int flag;
+  IDASpilsMemB idaspilsB_mem;
+  IDASpilsJacTimesSetupFn idaspils_jtsetup;
+  IDASpilsJacTimesVecFn idaspils_jtimes;
   
   /* Check if ida_mem is allright. */
   if (ida_mem == NULL) {
     IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnBS", MSGS_IDAMEM_NULL);
+                    "IDASpilsSetJacTimesBS", MSGS_IDAMEM_NULL);
     return(IDASPILS_MEM_NULL);
   }
   IDA_mem = (IDAMem) ida_mem;
 
   /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
     IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnBS",  MSGS_NO_ADJ);
+                    "IDASpilsSetJacTimesBS",  MSGS_NO_ADJ);
     return(IDASPILS_NO_ADJ);
   }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
@@ -1150,7 +1628,7 @@ int IDASpilsSetJacTimesVecFnBS(void *ida_mem, int which, IDASpilsJacTimesVecFnBS
   /* Check the value of which */
   if ( which >= IDAADJ_mem->ia_nbckpbs ) {
     IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnBS", MSGS_BAD_WHICH);
+                    "IDASpilsSetJacTimesBS", MSGS_BAD_WHICH);
     return(IDASPILS_ILL_INPUT);
   }
 
@@ -1166,39 +1644,31 @@ int IDASpilsSetJacTimesVecFnBS(void *ida_mem, int which, IDASpilsJacTimesVecFnBS
 
   if ( IDAB_mem->ida_lmem == NULL) {
     IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, "IDASSPILS", 
-                    "IDASpilsSetJacTimesVecFnBS", MSGS_LMEMB_NULL);
+                    "IDASpilsSetJacTimesBS", MSGS_LMEMB_NULL);
     return(IDASPILS_ILL_INPUT);
   }
 
+  /* Get the IDASpilsMemB data */
   idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
 
-  /* Call the corresponding Set* function for the backward problem. */
-
-  idaspilsB_mem->s_jtimesBS = jtvBS;
-
-  if (jtvBS != NULL) {
-    flag = IDASpilsSetJacTimesVecFn(ida_memB, IDAAspilsJacTimesVecBS);
-  } else {
-    flag = IDASpilsSetJacTimesVecFn(ida_memB, NULL);
-  }
-  return(flag);
+  /* Set jacobian routines for the backward problem. */
+  idaspilsB_mem->jtsetupBS = jtsetupBS;
+  idaspilsB_mem->jtimesBS  = jtimesBS;
+  
+  /* Call the corresponding "set" routine for the backward problem */
+  idaspils_jtsetup = (jtsetupBS == NULL) ? NULL : IDAAspilsJacTimesSetupBS;
+  idaspils_jtimes  = (jtimesBS == NULL)  ? NULL : IDAAspilsJacTimesVecBS;
+  return IDASpilsSetJacTimes(ida_memB, idaspils_jtsetup, idaspils_jtimes);
 }
 
 
-/*
- * -----------------------------------------------------------------
- * IDASSPILS private functions
- *
- * These routines are interfaces to the routines provided by the
- * user for backward problems.
- *
- * -----------------------------------------------------------------
- */
+/*-----------------------------------------------------------------
+  IDASSPILS Private functions for backwards problems
+  -----------------------------------------------------------------*/
 
-static int IDAAspilsPrecSetupB(realtype tt, 
-                              N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                              realtype c_jB, void *ida_mem,
-                              N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+/*---------------------------------------------------------------*/
+static int IDAAspilsPrecSetupB(realtype tt, N_Vector yyB, N_Vector ypB,
+                               N_Vector rrB, realtype c_jB, void *ida_mem)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -1206,31 +1676,60 @@ static int IDAAspilsPrecSetupB(realtype tt,
   IDABMem IDAB_mem;
   int flag;
 
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsPrecSetupB", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsPrecSetupB",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSetupB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  idaspilsB_mem = (IDASpilsMemB)IDAB_mem->ida_lmem;
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSetupB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
   
   /* Get forward solution from interpolation. */
-  if (noInterp==FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+  if (IDAADJ_mem->ia_noInterp==SUNFALSE) {
+    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS", "IDAAspilsPrecSetupB", MSGS_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsPrecSetupB", MSGS_BAD_T);
       return(-1);
     }
   }
 
   /* Call user's adjoint precondB routine */
-  flag = idaspilsB_mem->s_psetB(tt, yyTmp, ypTmp, yyB, ypB, rrB, 
-                                c_jB, IDAB_mem->ida_user_data,
-                                tmp1B, tmp2B, tmp3B);
+  flag = idaspilsB_mem->psetB(tt, IDAADJ_mem->ia_yyTmp,
+                              IDAADJ_mem->ia_ypTmp, yyB, ypB, rrB, 
+                              c_jB, IDAB_mem->ida_user_data);
   return(flag);
 }
 
-static int IDAAspilsPrecSetupBS(realtype tt, 
-                               N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                               realtype c_jB, void *ida_mem,
-                               N_Vector tmp1B, N_Vector tmp2B, N_Vector tmp3B)
+
+/*---------------------------------------------------------------*/
+static int IDAAspilsPrecSetupBS(realtype tt, N_Vector yyB, N_Vector ypB,
+                                N_Vector rrB, realtype c_jB, void *ida_mem)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -1238,37 +1737,70 @@ static int IDAAspilsPrecSetupBS(realtype tt,
   IDABMem IDAB_mem;
   int flag;
 
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsPrecSetupBS", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsPrecSetupBS",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSetupBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  idaspilsB_mem = (IDASpilsMemB)IDAB_mem->ida_lmem;
-  
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSetupBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
   /* Get forward solution from interpolation. */
-  if( noInterp == FALSE) {
-    if (interpSensi)
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, yySTmp, ypSTmp);
+  if( IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    if (IDAADJ_mem->ia_interpSensi)
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp,
+                                 IDAADJ_mem->ia_yySTmp,
+                                 IDAADJ_mem->ia_ypSTmp);
     else
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS", "IDAAspilsPrecSetupBS", MSGS_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsPrecSetupBS", MSGS_BAD_T);
       return(-1);
     }
   }
 
   /* Call user's adjoint precondBS routine */
-  flag = idaspilsB_mem->s_psetBS(tt, yyTmp, ypTmp, yySTmp, ypSTmp,
-                                 yyB, ypB, rrB,
-                                 c_jB, IDAB_mem->ida_user_data,
-                                 tmp1B, tmp2B, tmp3B);
+  flag = idaspilsB_mem->psetBS(tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp,
+                               IDAADJ_mem->ia_yySTmp,
+                               IDAADJ_mem->ia_ypSTmp, yyB, ypB, 
+                               rrB, c_jB, IDAB_mem->ida_user_data);
   return(flag);
 }
 
 
-static int IDAAspilsPrecSolveB(realtype tt, 
-                               N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                               N_Vector rvecB, N_Vector zvecB,
-                               realtype c_jB, realtype deltaB,
-                               void *ida_mem, N_Vector tmpB)
+/*---------------------------------------------------------------*/
+static int IDAAspilsPrecSolveB(realtype tt, N_Vector yyB, N_Vector ypB,
+                               N_Vector rrB, N_Vector rvecB,
+                               N_Vector zvecB, realtype c_jB,
+                               realtype deltaB, void *ida_mem)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -1276,33 +1808,62 @@ static int IDAAspilsPrecSolveB(realtype tt,
   IDABMem IDAB_mem;
   int flag;
 
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsPrecSolveB", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsPrecSolveB",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSolveB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  idaspilsB_mem = (IDASpilsMemB)IDAB_mem->ida_lmem;
-  
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSolveB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
   /* Get forward solution from interpolation. */
-  if (noInterp==FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+  if (IDAADJ_mem->ia_noInterp==SUNFALSE) {
+    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS", "IDAAspilsPrecSolveB", MSGS_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsPrecSolveB", MSGS_BAD_T);
       return(-1);
     }
   }
   /* Call user's adjoint psolveB routine */
-  flag = idaspilsB_mem->s_psolveB(tt, yyTmp, ypTmp, 
-                                  yyB, ypB, rrB, 
-                                  rvecB, zvecB, 
-                                  c_jB, deltaB, 
-                                  IDAB_mem->ida_user_data, tmpB);
+  flag = idaspilsB_mem->psolveB(tt, IDAADJ_mem->ia_yyTmp,
+                                IDAADJ_mem->ia_ypTmp, yyB, ypB, 
+                                rrB, rvecB, zvecB, c_jB, deltaB, 
+                                IDAB_mem->ida_user_data);
   return(flag);
 }
 
-static int IDAAspilsPrecSolveBS(realtype tt, 
-                                N_Vector yyB, N_Vector ypB, N_Vector rrB, 
-                                N_Vector rvecB, N_Vector zvecB,
-                                realtype c_jB, realtype deltaB,
-                                void *ida_mem, N_Vector tmpB)
+
+/*---------------------------------------------------------------*/
+static int IDAAspilsPrecSolveBS(realtype tt, N_Vector yyB, N_Vector ypB,
+                                N_Vector rrB, N_Vector rvecB,
+                                N_Vector zvecB, realtype c_jB,
+                                realtype deltaB, void *ida_mem)
 {
   IDAMem IDA_mem;
   IDAadjMem IDAADJ_mem;
@@ -1310,36 +1871,200 @@ static int IDAAspilsPrecSolveBS(realtype tt,
   IDABMem IDAB_mem;
   int flag;
 
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsPrecSolveBS", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsPrecSolveBS",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSolveBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  idaspilsB_mem = (IDASpilsMemB)IDAB_mem->ida_lmem;
-  
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsPrecSolveBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
   /* Get forward solution from interpolation. */
-  if( noInterp == FALSE) {
-    if (interpSensi)
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, yySTmp, ypSTmp);
+  if( IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    if (IDAADJ_mem->ia_interpSensi)
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp,
+                                 IDAADJ_mem->ia_yySTmp,
+                                 IDAADJ_mem->ia_ypSTmp);
     else
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS", "IDAAspilsPrecSolveBS", MSGS_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsPrecSolveBS", MSGS_BAD_T);
       return(-1);
     }
   }
 
   /* Call user's adjoint psolveBS routine */
-  flag = idaspilsB_mem->s_psolveBS(tt, yyTmp, ypTmp, yySTmp, ypSTmp,
-                                   yyB, ypB, rrB,
-                                   rvecB, zvecB,
-                                   c_jB, deltaB,
-                                   IDAB_mem->ida_user_data, tmpB);
+  flag = idaspilsB_mem->psolveBS(tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp,
+                                 IDAADJ_mem->ia_yySTmp,
+                                 IDAADJ_mem->ia_ypSTmp,
+                                 yyB, ypB, rrB, rvecB, zvecB, c_jB, 
+                                 deltaB, IDAB_mem->ida_user_data);
   return(flag);
 }
 
 
-static int IDAAspilsJacTimesVecB(realtype tt,
-                                 N_Vector yyB, N_Vector ypB, N_Vector rrB,
-                                 N_Vector vB, N_Vector JvB, 
+/*---------------------------------------------------------------*/
+static int IDAAspilsJacTimesSetupB(realtype tt, N_Vector yyB, N_Vector ypB,
+                                   N_Vector rrB, realtype c_jB, void *ida_mem)
+{
+  IDAMem IDA_mem;
+  IDAadjMem IDAADJ_mem;
+  IDASpilsMemB idaspilsB_mem; 
+  IDABMem IDAB_mem;
+  int flag;
+
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsJacTimesSetupB", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsJacTimesSetupB",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
+  IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesSetupB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesSetupB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
+  /* Get forward solution from interpolation. */
+  if (IDAADJ_mem->ia_noInterp==SUNFALSE) {
+    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp, NULL, NULL);
+    if (flag != IDA_SUCCESS) {
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsJacTimesSetupB", MSGS_BAD_T);
+      return(-1);
+    }
+  }
+  /* Call user's adjoint jtsetupB routine */
+  flag = idaspilsB_mem->jtsetupB(tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp, yyB,
+                                 ypB, rrB, c_jB,
+                                 IDAB_mem->ida_user_data);
+  return(flag);
+}
+
+
+/*---------------------------------------------------------------*/
+static int IDAAspilsJacTimesSetupBS(realtype tt, N_Vector yyB, N_Vector ypB,
+                                    N_Vector rrB, realtype c_jB, void *ida_mem)
+{
+  IDAMem IDA_mem;
+  IDAadjMem IDAADJ_mem;
+  IDASpilsMemB idaspilsB_mem;
+  IDABMem IDAB_mem;
+  int flag;
+
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsJacTimesSetupBS", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
+  IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsJacTimesSetupBS",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
+  IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesSetupBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesSetupBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
+  /* Get forward solution from interpolation. */
+  if( IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    if (IDAADJ_mem->ia_interpSensi)
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp,
+                                 IDAADJ_mem->ia_yySTmp,
+                                 IDAADJ_mem->ia_ypSTmp);
+    else
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp, NULL, NULL);
+    if (flag != IDA_SUCCESS) {
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsJacTimesSetupBS", MSGS_BAD_T);
+      return(-1);
+    }
+  }
+
+  /* Call user's adjoint jtimesBS routine */
+  flag = idaspilsB_mem->jtsetupBS(tt, IDAADJ_mem->ia_yyTmp,
+                                  IDAADJ_mem->ia_ypTmp,
+                                  IDAADJ_mem->ia_yySTmp,
+                                  IDAADJ_mem->ia_ypSTmp,
+                                  yyB, ypB, rrB, c_jB, 
+                                  IDAB_mem->ida_user_data);
+  return(flag);
+}
+
+
+/*---------------------------------------------------------------*/
+static int IDAAspilsJacTimesVecB(realtype tt, N_Vector yyB, N_Vector ypB,
+                                 N_Vector rrB, N_Vector vB, N_Vector JvB, 
                                  realtype c_jB, void *ida_mem, 
                                  N_Vector tmp1B, N_Vector tmp2B)
 {
@@ -1349,31 +2074,61 @@ static int IDAAspilsJacTimesVecB(realtype tt,
   IDABMem IDAB_mem;
   int flag;
 
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsJacTimesVecB", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsJacTimesVecB",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesVecB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  idaspilsB_mem = (IDASpilsMemB)IDAB_mem->ida_lmem;
-  
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesVecB", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
   /* Get forward solution from interpolation. */
-  if (noInterp==FALSE) {
-    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+  if (IDAADJ_mem->ia_noInterp==SUNFALSE) {
+    flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                               IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS", "IDAAspilsJacTimesVecB", MSGS_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsJacTimesVecB", MSGS_BAD_T);
       return(-1);
     }
   }
   /* Call user's adjoint jtimesB routine */
-  flag = idaspilsB_mem->s_jtimesB(tt, yyTmp, ypTmp, 
-                                  yyB, ypB, rrB, 
-                                  vB, JvB, 
-                                  c_jB, IDAB_mem->ida_user_data, 
-                                  tmp1B, tmp2B);
+  flag = idaspilsB_mem->jtimesB(tt, IDAADJ_mem->ia_yyTmp,
+                                IDAADJ_mem->ia_ypTmp, yyB,
+                                ypB, rrB, vB, JvB, c_jB,
+                                IDAB_mem->ida_user_data,
+                                tmp1B, tmp2B);
   return(flag);
 }
 
-static int IDAAspilsJacTimesVecBS(realtype tt,
-                                  N_Vector yyB, N_Vector ypB, N_Vector rrB,
-                                  N_Vector vB, N_Vector JvB, 
+
+/*---------------------------------------------------------------*/
+static int IDAAspilsJacTimesVecBS(realtype tt, N_Vector yyB, N_Vector ypB,
+                                  N_Vector rrB, N_Vector vB, N_Vector JvB, 
                                   realtype c_jB, void *ida_mem, 
                                   N_Vector tmp1B, N_Vector tmp2B)
 {
@@ -1383,28 +2138,78 @@ static int IDAAspilsJacTimesVecBS(realtype tt,
   IDABMem IDAB_mem;
   int flag;
 
+  /* Check if ida_mem is allright. */
+  if (ida_mem == NULL) {
+    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASSPILS", 
+                    "IDAAspilsJacTimesVecBS", MSGS_IDAMEM_NULL);
+    return(IDASPILS_MEM_NULL);
+  }
   IDA_mem = (IDAMem) ida_mem;
+
+  /* Is ASA initialized? */
+  if (IDA_mem->ida_adjMallocDone == SUNFALSE) {
+    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASSPILS", 
+                    "IDAAspilsJacTimesVecBS",  MSGS_NO_ADJ);
+    return(IDASPILS_NO_ADJ);
+  }
   IDAADJ_mem = IDA_mem->ida_adj_mem;
+
+  /* Get current backward problem. */
+  if (IDAADJ_mem->ia_bckpbCrt == NULL) {
+    IDAProcessError(IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesVecBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
   IDAB_mem = IDAADJ_mem->ia_bckpbCrt;
-  idaspilsB_mem = (IDASpilsMemB)IDAB_mem->ida_lmem;
-  
+
+  /* Get linear solver's data for this backward problem. */
+  if (IDAB_mem->ida_lmem == NULL) {
+    IDAProcessError(IDAB_mem->IDA_mem, IDASPILS_LMEMB_NULL, 
+                    "IDASSPILS", "IDAAspilsJacTimesVecBS", MSGS_LMEMB_NULL);
+    return(IDASPILS_LMEMB_NULL);
+  }
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
   /* Get forward solution from interpolation. */
-  if( noInterp == FALSE) {
-    if (interpSensi)
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, yySTmp, ypSTmp);
+  if( IDAADJ_mem->ia_noInterp == SUNFALSE) {
+    if (IDAADJ_mem->ia_interpSensi)
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp,
+                                 IDAADJ_mem->ia_yySTmp,
+                                 IDAADJ_mem->ia_ypSTmp);
     else
-      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, yyTmp, ypTmp, NULL, NULL);
+      flag = IDAADJ_mem->ia_getY(IDA_mem, tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp, NULL, NULL);
     if (flag != IDA_SUCCESS) {
-      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS", "IDAAspilsJacTimesVecBS", MSGS_BAD_T);
+      IDAProcessError(IDAB_mem->IDA_mem, -1, "IDASSPILS",
+                      "IDAAspilsJacTimesVecBS", MSGS_BAD_T);
       return(-1);
     }
   }
 
   /* Call user's adjoint jtimesBS routine */
-  flag = idaspilsB_mem->s_jtimesBS(tt, yyTmp, ypTmp, yySTmp, ypSTmp,
-                                   yyB, ypB, rrB,
-                                   vB, JvB,
-                                   c_jB, IDAB_mem->ida_user_data,
-                                   tmp1B, tmp2B);
+  flag = idaspilsB_mem->jtimesBS(tt, IDAADJ_mem->ia_yyTmp,
+                                 IDAADJ_mem->ia_ypTmp,
+                                 IDAADJ_mem->ia_yySTmp,
+                                 IDAADJ_mem->ia_ypSTmp,
+                                 yyB, ypB, rrB, vB, JvB, c_jB, 
+                                 IDAB_mem->ida_user_data, tmp1B, tmp2B);
   return(flag);
 }
+
+
+/*---------------------------------------------------------------*/
+int idaSpilsFreeB(IDABMem IDAB_mem)
+{
+  IDASpilsMemB idaspilsB_mem;
+
+  /* Return immediately if IDAB_mem or IDAB_mem->ida_lmem are NULL */
+  if (IDAB_mem == NULL)  return (IDASPILS_SUCCESS);
+  if (IDAB_mem->ida_lmem == NULL)  return(IDASPILS_SUCCESS);
+  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
+
+  /* free IDASpilsMemB interface structure */
+  free(idaspilsB_mem);
+  
+  return(IDASPILS_SUCCESS);
+}
diff --git a/src/idas/idas_spils_impl.h b/src/idas/idas_spils_impl.h
index 6cbaac6..acc7a8b 100644
--- a/src/idas/idas_spils_impl.h
+++ b/src/idas/idas_spils_impl.h
@@ -1,24 +1,24 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4921 $
- * $Date: 2016-09-19 14:35:11 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmers: Alan C. Hindmarsh and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
+/*----------------------------------------------------------------- 
+ * Programmer(s): Daniel R. Reynolds @ SMU
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
+ *-----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
  * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
  * All rights reserved.
  * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the common header file (private version) for the Scaled
- * Preconditioned Iterative Linear Solver modules.
- * -----------------------------------------------------------------
- */
+ * LLNS/SMU Copyright End
+ *-----------------------------------------------------------------
+ * Implementation header file for the Scaled Preconditioned 
+ * Iterative Linear Solver interface.
+ *-----------------------------------------------------------------*/
 
 #ifndef _IDASSPILS_IMPL_H
 #define _IDASSPILS_IMPL_H
@@ -30,120 +30,105 @@
 extern "C" {
 #endif
 
-/* Types of iterative linear solvers */
+/*-----------------------------------------------------------------
+  Types : IDASpilsMemRec, IDASpilsMem                             
+  -----------------------------------------------------------------*/
 
-#define SPILS_SPGMR   1
-#define SPILS_SPBCG   2
-#define SPILS_SPTFQMR 3
+typedef struct IDASpilsMemRec {
 
-/* Constants */
+  realtype sqrtN;    /* sqrt(N)                                      */
+  realtype eplifac;  /* eplifac = linear convergence factor          */
+  realtype dqincfac; /* dqincfac = optional increment factor in Jv   */
+  realtype epslin;   /* SpgrmSolve tolerance parameter               */
 
-#define IDA_SPILS_MAXL    5
-#define IDA_SPILS_MAXRS   5
+  long int npe;      /* npe = total number of precond calls          */   
+  long int nli;      /* nli = total number of linear iterations      */
+  long int nps;      /* nps = total number of psolve calls           */
+  long int ncfl;     /* ncfl = total number of convergence failures  */
+  long int nres;     /* nres = total number of calls to res          */
+  long int njtsetup; /* njtsetup = total number of calls to jtsetup  */
+  long int njtimes;  /* njtimes = total number of calls to jtimes    */
 
-/*
- * -----------------------------------------------------------------
- * Types : IDASpilsMemRec, IDASpilsMem                             
- * -----------------------------------------------------------------
- */
+  long int nst0;     /* nst0 = saved nst (for performance monitor)   */   
+  long int nni0;     /* nni0 = saved nni (for performance monitor)   */   
+  long int ncfn0;    /* ncfn0 = saved ncfn (for performance monitor) */   
+  long int ncfl0;    /* ncfl0 = saved ncfl (for performance monitor) */   
+  long int nwarn;    /* nwarn = no. of warnings (for perf. monitor)  */   
 
-typedef struct IDASpilsMemRec {
+  N_Vector ytemp;    /* temp vector used by IDAAtimesDQ              */ 
+  N_Vector yptemp;   /* temp vector used by IDAAtimesDQ              */ 
+  N_Vector x;        /* temp vector used by the solve function       */
+  N_Vector ycur;     /* current y vector in Newton iteration         */
+  N_Vector ypcur;    /* current yp vector in Newton iteration        */
+  N_Vector rcur;     /* rcur = F(tn, ycur, ypcur)                    */
+
+  SUNLinearSolver LS; /* generic iterative linear solver object      */
 
-  int s_type;          /* type of scaled preconditioned iterative LS   */
-
-  int  s_gstype;       /* type of Gram-Schmidt orthogonalization       */
-  realtype s_sqrtN;    /* sqrt(N)                                      */
-  int  s_maxl;         /* maxl = maximum dimension of the Krylov space */
-  int  s_maxrs;        /* maxrs = max. number of GMRES restarts        */
-  realtype s_eplifac;  /* eplifac = linear convergence factor          */
-  realtype s_dqincfac; /* dqincfac = optional increment factor in Jv   */
-  realtype s_epslin;   /* SpgrmSolve tolerance parameter               */
-
-  long int s_npe;      /* npe = total number of precond calls          */   
-  long int s_nli;      /* nli = total number of linear iterations      */
-  long int s_nps;      /* nps = total number of psolve calls           */
-  long int s_ncfl;     /* ncfl = total number of convergence failures  */
-  long int s_nres;     /* nres = total number of calls to res          */
-  long int s_njtimes;  /* njtimes = total number of calls to jtimes    */
-
-  long int s_nst0;     /* nst0 = saved nst (for performance monitor)   */   
-  long int s_nni0;     /* nni0 = saved nni (for performance monitor)   */   
-  long int s_nli0;     /* nli0 = saved nli (for performance monitor)   */   
-  long int s_ncfn0;    /* ncfn0 = saved ncfn (for performance monitor) */   
-  long int s_ncfl0;    /* ncfl0 = saved ncfl (for performance monitor) */   
-  long int s_nwarn;    /* nwarn = no. of warnings (for perf. monitor)  */   
-
-  N_Vector s_ytemp;    /* temp vector used by IDAAtimesDQ              */ 
-  N_Vector s_yptemp;   /* temp vector used by IDAAtimesDQ              */ 
-  N_Vector s_xx;       /* temp vector used by the solve function       */
-  N_Vector s_ycur;     /* current y vector in Newton iteration         */
-  N_Vector s_ypcur;    /* current yp vector in Newton iteration        */
-  N_Vector s_rcur;     /* rcur = F(tn, ycur, ypcur)                    */
-
-  void *s_spils_mem;   /* memory used by the generic solver            */
-
-  long int s_last_flag; /* last error return flag                      */
+  long int last_flag; /* last error return flag                      */
 
   /* Preconditioner computation
    * (a) user-provided:
    *     - pdata == user_data
-   *     - pfree == NULL (the user dealocates memory for f_data)
+   *     - pfree == NULL (the user dealocates memory)
    * (b) internal preconditioner module
    *     - pdata == ida_mem
-   *     - pfree == set by the prec. module and called in IDASpilsFree
-   */
-
-  IDASpilsPrecSetupFn s_pset;
-  IDASpilsPrecSolveFn s_psolve;
-  int (*s_pfree)(IDAMem IDA_mem);
-  void *s_pdata;
+   *     - pfree == set by the prec. module and called in IDASpilsFree */
+  IDASpilsPrecSetupFn pset;
+  IDASpilsPrecSolveFn psolve;
+  int (*pfree)(IDAMem IDA_mem);
+  void *pdata;
   
   /* Jacobian times vector compuation
    * (a) jtimes function provided by the user:
    *     - jdata == user_data
-   *     - jtimesDQ == FALSE
+   *     - jtimesDQ == SUNFALSE
    * (b) internal jtimes
    *     - jdata == ida_mem
-   *     - jtimesDQ == TRUE
-   */
-
-  booleantype s_jtimesDQ;
-  IDASpilsJacTimesVecFn s_jtimes;
-  void *s_jdata;
+   *     - jtimesDQ == SUNTRUE */
+  booleantype jtimesDQ;
+  IDASpilsJacTimesSetupFn jtsetup;
+  IDASpilsJacTimesVecFn jtimes;
+  void *jdata;
 
 } *IDASpilsMem;
 
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-
-/* Atimes and PSolve routines called by generic solver */
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
 
-int IDASpilsAtimes(void *ida_mem, N_Vector v, N_Vector z);
-
-int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z, int lr);
+/* Interface routines called by system SUNLinearSolver */
+int IDASpilsATimes(void *ida_mem, N_Vector v, N_Vector z);
+int IDASpilsPSetup(void *ida_mem);
+int IDASpilsPSolve(void *ida_mem, N_Vector r, N_Vector z,
+                   realtype tol, int lr);
 
 /* Difference quotient approximation for Jac times vector */
-
-int IDASpilsDQJtimes(realtype tt,
-                     N_Vector yy, N_Vector yp, N_Vector rr,
-                     N_Vector v, N_Vector Jv, 
+int IDASpilsDQJtimes(realtype tt, N_Vector yy, N_Vector yp,
+                     N_Vector rr, N_Vector v, N_Vector Jv, 
                      realtype c_j, void *data, 
                      N_Vector work1, N_Vector work2);
 
-/* Auxilliary functions */
+/* Generic linit/lsetup/lsolve/lfree interface routines for IDA to call */
+int idaSpilsInitialize(IDAMem IDA_mem);
 
-int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem);
+int idaSpilsSetup(IDAMem IDA_mem, N_Vector y, N_Vector yp, N_Vector r, 
+                  N_Vector vt1, N_Vector vt2, N_Vector vt3); 
+
+int idaSpilsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
+                  N_Vector ycur, N_Vector ypcur, N_Vector rescur);
+
+int idaSpilsPerf(IDAMem IDA_mem, int perftask);
 
-/*
- * -----------------------------------------------------------------
- * Error and Warning Messages
- * -----------------------------------------------------------------
- */
+int idaSpilsFree(IDAMem IDA_mem);
 
+/* Auxilliary functions */
+int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem);
+
+  
+/*---------------------------------------------------------------
+  Error and Warning Messages
+  ---------------------------------------------------------------*/
 #if defined(SUNDIALS_EXTENDED_PRECISION)
 
 #define MSGS_TIME "at t = %Lg, "
@@ -163,7 +148,6 @@ int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem);
 
 
 /* Error Messages */
-
 #define MSGS_IDAMEM_NULL   "Integrator memory is NULL."
 #define MSGS_MEM_FAIL      "A memory request failed."
 #define MSGS_BAD_NVECTOR   "A required vector operation is not implemented."
@@ -176,49 +160,52 @@ int idaSpilsInitializeCounters(IDASpilsMem idaspils_mem);
 
 #define MSGS_PSET_FAILED "The preconditioner setup routine failed in an unrecoverable manner."
 #define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner."
+#define MSGS_JTSETUP_FAILED "The Jacobian x vector setup routine failed in an unrecoverable manner."
 #define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
 
 /* Warning Messages */
-
 #define MSGS_WARN  "Warning: " MSGS_TIME "poor iterative algorithm performance. "
 
-#define MSGS_AVD_WARN  MSGS_WARN "Average number of linear iterations is " MSGS_FRMT
 #define MSGS_CFN_WARN  MSGS_WARN "Nonlinear convergence failure rate is " MSGS_FRMT
 #define MSGS_CFL_WARN  MSGS_WARN "Linear convergence failure rate is " MSGS_FRMT
 
-/* 
- * -----------------------------------------------------------------
- * PART II - backward problems
- * -----------------------------------------------------------------
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : IDASpilsMemRecB, IDASpilsMemB       
- * -----------------------------------------------------------------
- * IDASpgmrB, IDASpbcgB, and IDASptfqmr attach such a structure to the 
- * lmemB filed of IDAadjMem
- * -----------------------------------------------------------------
- */
+  
+/*-----------------------------------------------------------------
+  PART II - backward problems
+  -----------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------
+  Types : IDASpilsMemRecB, IDASpilsMemB       
+
+  IDASpilsSetLinearSolverB attaches such a structure to the lmemB 
+  field of IDAadjMem
+  -----------------------------------------------------------------*/
 
 typedef struct IDASpilsMemRecB {
 
-  IDASpilsJacTimesVecFnB s_jtimesB;
-  IDASpilsJacTimesVecFnBS s_jtimesBS;
-  IDASpilsPrecSetupFnB s_psetB;
-  IDASpilsPrecSetupFnBS s_psetBS;
-  IDASpilsPrecSolveFnB s_psolveB;
-  IDASpilsPrecSolveFnBS s_psolveBS;
-  void *s_P_dataB;
+  IDASpilsJacTimesSetupFnB jtsetupB;
+  IDASpilsJacTimesSetupFnBS jtsetupBS;
+  IDASpilsJacTimesVecFnB jtimesB;
+  IDASpilsJacTimesVecFnBS jtimesBS;
+  IDASpilsPrecSetupFnB psetB;
+  IDASpilsPrecSetupFnBS psetBS;
+  IDASpilsPrecSolveFnB psolveB;
+  IDASpilsPrecSolveFnBS psolveBS;
+  void *P_dataB;
 
 } *IDASpilsMemB;
 
-/*
- * -----------------------------------------------------------------
- * Error Messages 
- * -----------------------------------------------------------------
- */
 
+/*-----------------------------------------------------------------
+  Prototypes of internal functions
+  -----------------------------------------------------------------*/
+
+int idaSpilsFreeB(IDABMem IDAB_mem);
+
+  
+/*-----------------------------------------------------------------
+  Error Messages 
+  -----------------------------------------------------------------*/
 #define MSGS_LMEMB_NULL "Linear solver memory is NULL for the backward integration."
 #define MSGS_BAD_T      "Bad t for interpolation."
 #define MSGS_BAD_WHICH  "Illegal value for which."
diff --git a/src/idas/idas_sptfqmr.c b/src/idas/idas_sptfqmr.c
deleted file mode 100644
index 3920213..0000000
--- a/src/idas/idas_sptfqmr.c
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4909 $
- * $Date: 2016-09-14 16:51:27 -0700 (Wed, 14 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDAS scaled preconditioned
- * TFQMR linear solver module, IDASPTFQMR.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <idas/idas_sptfqmr.h>
-#include "idas_spils_impl.h"
-#include "idas_impl.h"
-
-#include <sundials/sundials_sptfqmr.h>
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO RCONST(0.0)
-#define ONE  RCONST(1.0)
-#define PT9  RCONST(0.9)
-#define PT05 RCONST(0.05)
-
-/* IDASPTFQMR linit, lsetup, lsolve, lperf, and lfree routines */
-
-static int IDASptfqmrInit(IDAMem IDA_mem);
-
-static int IDASptfqmrSetup(IDAMem IDA_mem, 
-                           N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-                           N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
-
-static int IDASptfqmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-                           N_Vector yy_now, N_Vector yp_now, N_Vector rr_now);
-
-static int IDASptfqmrPerf(IDAMem IDA_mem, int perftask);
-
-static int IDASptfqmrFree(IDAMem IDA_mem);
-
-/* IDASPTFQMR lfree function for backward problem. */
-static int IDASptfqmrFreeB(IDABMem IDAB_mem);
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/* Readability Replacements */
-
-#define nst          (IDA_mem->ida_nst)
-#define tn           (IDA_mem->ida_tn)
-#define cj           (IDA_mem->ida_cj)
-#define epsNewt      (IDA_mem->ida_epsNewt)
-#define res          (IDA_mem->ida_res)
-#define user_data    (IDA_mem->ida_user_data)
-#define ewt          (IDA_mem->ida_ewt)
-#define errfp        (IDA_mem->ida_errfp)
-#define linit        (IDA_mem->ida_linit)
-#define lsetup       (IDA_mem->ida_lsetup)
-#define lsolve       (IDA_mem->ida_lsolve)
-#define lperf        (IDA_mem->ida_lperf)
-#define lfree        (IDA_mem->ida_lfree)
-#define lmem         (IDA_mem->ida_lmem)
-#define nni          (IDA_mem->ida_nni)
-#define ncfn         (IDA_mem->ida_ncfn)
-#define setupNonNull (IDA_mem->ida_setupNonNull)
-#define vec_tmpl     (IDA_mem->ida_tempv1)
-
-#define sqrtN       (idaspils_mem->s_sqrtN)
-#define epslin      (idaspils_mem->s_epslin)
-#define ytemp       (idaspils_mem->s_ytemp)
-#define yptemp      (idaspils_mem->s_yptemp)
-#define xx          (idaspils_mem->s_xx)
-#define ycur        (idaspils_mem->s_ycur)
-#define ypcur       (idaspils_mem->s_ypcur)
-#define rcur        (idaspils_mem->s_rcur)
-#define npe         (idaspils_mem->s_npe)
-#define nli         (idaspils_mem->s_nli)
-#define nps         (idaspils_mem->s_nps)
-#define ncfl        (idaspils_mem->s_ncfl)
-#define nst0        (idaspils_mem->s_nst0)
-#define nni0        (idaspils_mem->s_nni0)
-#define nli0        (idaspils_mem->s_nli0)
-#define ncfn0       (idaspils_mem->s_ncfn0)
-#define ncfl0       (idaspils_mem->s_ncfl0)
-#define nwarn       (idaspils_mem->s_nwarn)
-#define njtimes     (idaspils_mem->s_njtimes)
-#define nres        (idaspils_mem->s_nres)
-#define spils_mem   (idaspils_mem->s_spils_mem)
-
-#define jtimesDQ    (idaspils_mem->s_jtimesDQ)
-#define jtimes      (idaspils_mem->s_jtimes)
-#define jdata       (idaspils_mem->s_jdata)
-
-#define last_flag   (idaspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmr
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDASPTFQMR linear solver module.
- *
- * IDASptfqmr first calls the existing lfree routine if this is not NULL.
- * It then sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASptfqmrInit, IDASptfqmrSetup,
- * IDASptfqmrSolve, IDASptfqmrPerf, and IDASptfqmrFree, respectively.
- * It allocates memory for a structure of type IDASpilsMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem). It then sets various fields
- * in the IDASpilsMemRec structure. Finally, IDASptfqmr allocates 
- * memory for ytemp, yptemp, and xx, and calls SptfqmrMalloc to 
- * allocate memory for the Sptfqmr solver.
- *
- * The return value of IDASptfqmr is:
- *   IDASPILS_SUCCESS   =  0 if successful
- *   IDASPILS_MEM_FAIL  = -1 if IDA_mem is NULL or a memory
- *                             allocation failed
- *   IDASPILS_ILL_INPUT = -2 if a required vector operation is not
- *                             implemented.
- * -----------------------------------------------------------------
- */
-
-int IDASptfqmr(void *ida_mem, int maxl)
-{
-  IDAMem IDA_mem;
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int maxl1;
-
-  /* Return immediately if ida_mem is NULL */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPTFQMR", "IDASptfqmr", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Check if N_VDotProd is present */
-  if (vec_tmpl->ops->nvdotprod == NULL) {
-    IDAProcessError(NULL, IDASPILS_ILL_INPUT, "IDASPTFQMR", "IDASptfqmr", MSGS_BAD_NVECTOR);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree((IDAMem) ida_mem);
-
-  /* Set five main function fields in ida_mem */
-  linit  = IDASptfqmrInit;
-  lsetup = IDASptfqmrSetup;
-  lsolve = IDASptfqmrSolve;
-  lperf  = IDASptfqmrPerf;
-  lfree  = IDASptfqmrFree;
-
-  /* Get memory for IDASpilsMemRec */
-  idaspils_mem = NULL;
-  idaspils_mem = (IDASpilsMem) malloc(sizeof(struct IDASpilsMemRec));
-  if (idaspils_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Set ILS type */
-  idaspils_mem->s_type = SPILS_SPTFQMR;
-
-  /* Set SPTFQMR parameters that were passed in call sequence */
-  maxl1 = (maxl <= 0) ? IDA_SPILS_MAXL : maxl;
-  idaspils_mem->s_maxl = maxl1;
-
-  /* Set defaults for Jacobian-related fileds */
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  jdata    = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-  idaspils_mem->s_pset   = NULL;
-  idaspils_mem->s_psolve = NULL;
-  idaspils_mem->s_pfree  = NULL;
-  idaspils_mem->s_pdata  = IDA_mem->ida_user_data;
-
-  /* Set default values for the rest of the Sptfqmr parameters */
-  idaspils_mem->s_eplifac   = PT05;
-  idaspils_mem->s_dqincfac  = ONE;
-
-  idaspils_mem->s_last_flag = IDASPILS_SUCCESS;
-
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to FALSE */
-  setupNonNull = FALSE;
-
-  /* Allocate memory for ytemp, yptemp, and xx */
-
-  ytemp = N_VClone(vec_tmpl);
-  if (ytemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  yptemp = N_VClone(vec_tmpl);
-  if (yptemp == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  xx = N_VClone(vec_tmpl);
-  if (xx == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Compute sqrtN from a dot product */
-  N_VConst(ONE, ytemp);
-  sqrtN = SUNRsqrt(N_VDotProd(ytemp, ytemp));
-
-  /* Call SptfqmrMalloc to allocate workspace for Sptfqmr */
-  sptfqmr_mem = NULL;
-  sptfqmr_mem = SptfqmrMalloc(maxl1, vec_tmpl);
-  if (sptfqmr_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmr", MSGS_MEM_FAIL);
-    N_VDestroy(ytemp);
-    N_VDestroy(yptemp);
-    N_VDestroy(xx);
-    free(idaspils_mem); idaspils_mem = NULL;
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  /* Attach SPTFQMR memory to spils memory structure */
-  spils_mem = (void *)sptfqmr_mem;
-
-  /* Attach linear solver memory to the integrator memory */
-  lmem = idaspils_mem;
-
-  return(IDASPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASPTFQMR interface routines
- * -----------------------------------------------------------------
- */
-
-/* Additional readability Replacements */
-
-#define maxl     (idaspils_mem->s_maxl)
-#define eplifac  (idaspils_mem->s_eplifac)
-#define psolve   (idaspils_mem->s_psolve)
-#define pset     (idaspils_mem->s_pset)
-#define pdata    (idaspils_mem->s_pdata)
-
-static int IDASptfqmrInit(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-
-  /* Initialize counters */
-  idaSpilsInitializeCounters(idaspils_mem);
-
-  /* Set setupNonNull to TRUE iff there is preconditioning with setup */
-  setupNonNull = (psolve != NULL) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (jtimesDQ) {
-    jtimes = IDASpilsDQJtimes;
-    jdata = IDA_mem;
-  } else {
-    jdata = user_data;
-  }
-
-  /*  Set maxl in the SPTFQMR memory in case it was changed by the user */
-  sptfqmr_mem->l_max  = maxl;
-
-  last_flag = IDASPILS_SUCCESS;
-
-  return(0);
-}
-
-static int IDASptfqmrSetup(IDAMem IDA_mem, 
-			   N_Vector yy_p, N_Vector yp_p, N_Vector rr_p, 
-			   N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
-{
-  int retval;
-  IDASpilsMem idaspils_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  /* Call user setup routine pset and update counter npe */
-  retval = pset(tn, yy_p, yp_p, rr_p, cj, pdata,
-                tmp1, tmp2, tmp3);
-  npe++;
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, SPTFQMR_PSET_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSetup", MSGS_PSET_FAILED);
-    last_flag = SPTFQMR_PSET_FAIL_UNREC;
-    return(-1);
-  }
-  if (retval > 0) {
-    last_flag = SPTFQMR_PSET_FAIL_REC;
-    return(+1);
-  }
-
-  last_flag = SPTFQMR_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmrSolve
- * -----------------------------------------------------------------
- * Note: The x-scaling and b-scaling arrays are both equal to weight.
- *
- * We set the initial guess, x = 0, then call SptfqmrSolve.
- * We copy the solution x into b, and update the counters nli, nps,
- * and ncfl. If SptfqmrSolve returned nli_inc = 0 (hence x = 0), we
- * take the SPTFQMR vtemp vector (= P_inverse F) as the correction
- * vector instead. Finally, we set the return value according to the
- * success of SptfqmrSolve.
- * -----------------------------------------------------------------
- */
-
-static int IDASptfqmrSolve(IDAMem IDA_mem, N_Vector bb, N_Vector weight,
-			   N_Vector yy_now, N_Vector yp_now, N_Vector rr_now)
-{
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int pretype, nli_inc, nps_inc, retval;
-  realtype res_norm;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  sptfqmr_mem = (SptfqmrMem)spils_mem;
-
-  /* Set SptfqmrSolve convergence test constant epslin, in terms of the
-     Newton convergence test constant epsNewt and safety factors. The factor
-     sqrt(Neq) assures that the TFQMR convergence test is applied to the
-     WRMS norm of the residual vector, rather than the weighted L2 norm. */
-  epslin = sqrtN*eplifac*epsNewt;
-
-  /* Set vectors ycur, ypcur, and rcur for use by the Atimes and Psolve */
-  ycur = yy_now;
-  ypcur = yp_now;
-  rcur = rr_now;
-
-  /* Set SptfqmrSolve inputs pretype and initial guess xx = 0 */  
-  pretype = (psolve == NULL) ? PREC_NONE : PREC_LEFT;
-  N_VConst(ZERO, xx);
-  
-  /* Call SptfqmrSolve and copy xx to bb */
-  retval = SptfqmrSolve(sptfqmr_mem, IDA_mem, xx, bb, pretype, epslin,
-                      IDA_mem, weight, weight, IDASpilsAtimes,
-                      IDASpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  if (nli_inc == 0) N_VScale(ONE, SPTFQMR_VTEMP(sptfqmr_mem), bb);
-  else N_VScale(ONE, xx, bb);
-  
-  /* Increment counters nli, nps, and return if successful */
-  nli += nli_inc;
-  nps += nps_inc;
-  if (retval != SPTFQMR_SUCCESS) ncfl++;
-
-    /* Interpret return value from SpgmrSolve */
-
-  last_flag = retval;
-
-  switch(retval) {
-
-  case SPTFQMR_SUCCESS:
-    return(0);
-    break;
-  case SPTFQMR_RES_REDUCED:
-    return(1);
-    break;
-  case SPTFQMR_CONV_FAIL:
-    return(1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_REC:
-    return(1);
-    break;
-  case SPTFQMR_MEM_NULL:
-    return(-1);
-    break;
-  case SPTFQMR_ATIMES_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPTFQMR_ATIMES_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSolve", MSGS_JTIMES_FAILED);    
-    return(-1);
-    break;
-  case SPTFQMR_PSOLVE_FAIL_UNREC:
-    IDAProcessError(IDA_mem, SPTFQMR_PSOLVE_FAIL_UNREC, "IDASPTFQMR", "IDASptfqmrSolve", MSGS_PSOLVE_FAILED);
-    return(-1);
-    break;
-  }
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : IDASptfqmrPerf
- * -----------------------------------------------------------------
- * This routine handles performance monitoring specific to the
- * IDASPTFQMR linear solver. When perftask = 0, it saves values of
- * various counters. When perftask = 1, it examines difference
- * quotients in these counters, and depending on their values, it
- * prints up to three warning messages. Messages are printed up to
- * a maximum of 10 times.
- * -----------------------------------------------------------------
- */
-
-static int IDASptfqmrPerf(IDAMem IDA_mem, int perftask)
-{
-  IDASpilsMem idaspils_mem;
-  realtype avdim, rcfn, rcfl;
-  long int nstd, nnid;
-  booleantype lavd, lcfn, lcfl;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  if (perftask == 0) {
-    nst0 = nst;  nni0 = nni;  nli0 = nli;
-    ncfn0 = ncfn;  ncfl0 = ncfl;  
-    nwarn = 0;
-    return(0);
-  }
-
-  nstd = nst - nst0;  nnid = nni - nni0;
-  if (nstd == 0 || nnid == 0) return(0);
-  avdim = (realtype) ((nli - nli0)/((realtype) nnid));
-  rcfn = (realtype) ((ncfn - ncfn0)/((realtype) nstd));
-  rcfl = (realtype) ((ncfl - ncfl0)/((realtype) nnid));
-  lavd = (avdim > ((realtype) maxl));
-  lcfn = (rcfn > PT9);
-  lcfl = (rcfl > PT9);
-  if (!(lavd || lcfn || lcfl)) return(0);
-  nwarn++;
-  if (nwarn > 10) return(1);
-  if (lavd) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_AVD_WARN, tn, avdim);
-  if (lcfn) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_CFN_WARN, tn, rcfn);
-  if (lcfl) 
-    IDAProcessError(IDA_mem, IDA_WARNING, "IDASPTFQMR", "IDASptfqmrPerf", MSGS_CFL_WARN, tn, rcfl);
-
-  return(0);
-}
-
-static int IDASptfqmrFree(IDAMem IDA_mem)
-{
-  IDASpilsMem idaspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  idaspils_mem = (IDASpilsMem) lmem;
-
-  N_VDestroy(ytemp);
-  N_VDestroy(yptemp);
-  N_VDestroy(xx);
-  
-  sptfqmr_mem = (SptfqmrMem)spils_mem;
-  SptfqmrFree(sptfqmr_mem);
-
-  if (idaspils_mem->s_pfree != NULL) (idaspils_mem->s_pfree)(IDA_mem);
-
-  free(idaspils_mem); idaspils_mem = NULL;
-
-  return(0);
-}
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-/*
- * IDASptfqmrB
- *
- * Wrapper for the backward phase
- *
- */
-
-int IDASptfqmrB(void *ida_mem, int which, int maxlB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDASpilsMemB idaspilsB_mem;
-  int flag;
-  
-  /* Check if ida_mem is allright. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASPILS_MEM_NULL, "IDASPTFQMR", "IDASptfqmrB", MSGS_IDAMEM_NULL);
-    return(IDASPILS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASPILS_NO_ADJ, "IDASPTFQMR", "IDASptfqmrB",  MSGS_NO_ADJ);
-    return(IDASPILS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASPILS_ILL_INPUT, "IDASPTFQMR", "IDASptfqmrB", MSGS_BAD_WHICH);
-    return(IDASPILS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  
-  /* Get memory for IDASpilsMemRecB */
-  idaspilsB_mem = NULL;
-  idaspilsB_mem = (IDASpilsMemB) malloc(sizeof(struct IDASpilsMemRecB));
-  if (idaspilsB_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASPILS_MEM_FAIL, "IDASPTFQMR", "IDASptfqmrB", MSGS_MEM_FAIL);
-    return(IDASPILS_MEM_FAIL);
-  }
-
-  idaspilsB_mem->s_psetB = NULL;
-  idaspilsB_mem->s_psolveB = NULL;
-  idaspilsB_mem->s_P_dataB = NULL;
-
-  /* initialize Jacobian function */
-  idaspilsB_mem->s_jtimesB = NULL;
-
-  /* attach lmem and lfree */
-  IDAB_mem->ida_lmem = idaspilsB_mem;
-  IDAB_mem->ida_lfree = IDASptfqmrFreeB;
-
-  flag = IDASptfqmr(IDAB_mem->IDA_mem, maxlB);
-
-  if (flag != IDASPILS_SUCCESS) {
-    free(idaspilsB_mem);
-    idaspilsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-/*
- * IDASptfqmrFreeB 
- */
-
-static int IDASptfqmrFreeB(IDABMem IDAB_mem)
-{
-  IDASpilsMemB idaspilsB_mem;
-
-  idaspilsB_mem = (IDASpilsMemB) IDAB_mem->ida_lmem;
-
-  free(idaspilsB_mem);
-
-  return(0);
-}
diff --git a/src/idas/idas_superlumt.c b/src/idas/idas_superlumt.c
deleted file mode 100644
index 4bab266..0000000
--- a/src/idas/idas_superlumt.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4938 $
- * $Date: 2016-09-21 14:33:08 -0700 (Wed, 21 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the IDASSUPERLUMT linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "sundials/sundials_math.h"
-#include "sundials/sundials_superlumt_impl.h"
-
-#include "idas_impl.h"
-#include "idas_sparse_impl.h"
-#include "idas/idas_superlumt.h"
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* IDASSSUPERLUMT linit, lsetup, lsolve, and lfree routines */
- 
-static int IDASuperLUMTInit(IDAMem IDA_mem);
-
-static int IDASuperLUMTSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-			     N_Vector rrp, N_Vector tmp1,
-			     N_Vector tmp2, N_Vector tmp3);
-
-static int IDASuperLUMTSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-			     N_Vector ycur, N_Vector ypcur, N_Vector rrcur);
-
-static int IDASuperLUMTFree(IDAMem IDA_mem);
-
-/* IDASUPERLUMT lfreeB function */
-
-static int IDASuperLUMTFreeB(IDABMem IDAB_mem);
-
-
-/* 
- * ================================================================
- *
- *                   PART I - forward problems
- *
- * ================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * IDASuperLUMT
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the IDA / SuperLUMT linear solver module.  
- * IDASuperLUMT first calls the existing lfree routine if this is not NULL.
- * Then it sets the ida_linit, ida_lsetup, ida_lsolve, ida_lperf, and
- * ida_lfree fields in (*IDA_mem) to be IDASuperLUMTInit, IDASuperLUMTSetup,
- * IDASuperLUMTSolve, NULL, and IDASuperLUMTFree, respectively.
- * It allocates memory for a structure of type IDAsluMemRec and sets
- * the ida_lmem field in (*IDA_mem) to the address of this structure.
- * It sets setupNonNull in (*IDA_mem) to TRUE, sets the d_jdata field
- * in the IDAsluMemRec structure to be the input parameter jdata,
- * and sets the d_jac field to be:
- *   (1) the input parameter djac, if djac != NULL, or                
- *   (2) throws an error, if djac == NULL.                             
- * Finally, it allocates memory for SuperLUMT.
- * The return value is IDASLS_SUCCESS = 0, IDASLS_LMEM_FAIL = -1,
- * or IDASLS_ILL_INPUT = -2.
- *
- * NOTE: The SuperLUMT linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, IDASuperLUMT will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int IDASuperLUMT(void *ida_mem, int num_threads, int n, int nnz)
-{
-  IDAMem IDA_mem;
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-  int *perm_c, *perm_r;
-  int nrhs, panel_size, relax;
-  double *bd;
-  SuperMatrix *B;
-
-  /* Return immediately if ida_mem is NULL. */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDASuperLUMT", 
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (IDA_mem->ida_tempv1->ops->nvgetarraypointer == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDASuperLUMT", 
-		    MSGSP_BAD_NVECTOR);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  if (IDA_mem->ida_lfree != NULL) IDA_mem->ida_lfree(IDA_mem);
-
-  /* Set five main function fields in IDA_mem. */
-  IDA_mem->ida_linit  = IDASuperLUMTInit;
-  IDA_mem->ida_lsetup = IDASuperLUMTSetup;
-  IDA_mem->ida_lsolve = IDASuperLUMTSolve;
-  IDA_mem->ida_lperf  = NULL;
-  IDA_mem->ida_lfree  = IDASuperLUMTFree;
-
-  /* Get memory for IDASlsMemRec. */
-  idasls_mem = NULL;
-  idasls_mem = (IDASlsMem) malloc(sizeof(struct IDASlsMemRec));
-  if (idasls_mem == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* Get memory for SLUMT_data. */
-  slumt_data = NULL;
-  slumt_data = (SLUMTData)malloc(sizeof(struct SLUMTDataRec));
-  if (slumt_data == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  IDA_mem->ida_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  idasls_mem->s_jaceval = NULL;
-  idasls_mem->s_jacdata = IDA_mem->ida_user_data;
-
-  /* Allocate memory for the sparse Jacobian */
-  idasls_mem->s_JacMat = NULL;
-  idasls_mem->s_JacMat = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (idasls_mem->s_JacMat == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-
-  /* Set up memory for the permutations */
-  perm_r = (int *)malloc(n*sizeof(int));
-  if (perm_r == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  }
-  perm_c = (int *)malloc(n*sizeof(int));
-  if (perm_c == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", "IDASuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    free(perm_r);
-    return(IDASLS_MEM_FAIL);
-  }
-  slumt_data->perm_r = perm_r;
-  slumt_data->perm_c = perm_c;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  /* Set default parameters for SuperLU */
-  slumt_data->num_threads = num_threads;
-  slumt_data->diag_pivot_thresh = 1.0;
-
-  /* Allocate structures for SuperLU */
-  slumt_data->Gstat = (Gstat_t *)malloc(sizeof(Gstat_t));
-  slumt_data->s_A = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_AC = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_L = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_U = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_A->Store  = NULL;
-  slumt_data->s_AC->Store = NULL;
-  slumt_data->s_L->Store  = NULL;
-  slumt_data->s_U->Store  = NULL;
-  slumt_data->superlumt_options = (superlumt_options_t *)malloc(sizeof(superlumt_options_t));
-
-  dCreate_CompCol_Matrix(slumt_data->s_A, idasls_mem->s_JacMat->M, idasls_mem->s_JacMat->N, 
-			 idasls_mem->s_JacMat->NNZ, idasls_mem->s_JacMat->data, 
-			 idasls_mem->s_JacMat->indexvals, idasls_mem->s_JacMat->indexptrs, 
-			 SLU_NC, SLU_D, SLU_GE);
-
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  StatAlloc(idasls_mem->s_JacMat->N, num_threads, panel_size, relax, slumt_data->Gstat);
-  
-  /* Create RHS matrix */
-  nrhs = 1;
-  bd = NULL;
-  B = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  B->Store = NULL;
-  dCreate_Dense_Matrix(B, n, nrhs, bd, n, 
-		       SLU_DN, SLU_D, SLU_GE);
-  slumt_data->s_B = B;
-
-  /* Set ordering to COLAMD as the idas default use.
-     Users can set a different value with IDASuperLUMTSetOrdering,
-     and the user-set value is loaded before any call to factorize the
-     matrix in IDASuperLUMTSetup.  */
-  slumt_data->s_ordering = 3;
-
-  /* Attach linear solver memory to the integrator memory */
-  idasls_mem->s_solver_data = (void *) slumt_data;
-  IDA_mem->ida_lmem = idasls_mem;
-
-  return(IDASLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * IDASuperLUMT interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the IDASuperLUMT
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int IDASuperLUMTInit(IDAMem IDA_mem)
-{
-  int num_threads, n;
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-
-  idasls_mem = (IDASlsMem)IDA_mem->ida_lmem;
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  idasls_mem->s_nje = 0;
-  idasls_mem->s_first_factorize = 1;
-
-  /* ------------------------------------------------------------
-     Allocate storage and initialize statistics variables. 
-     ------------------------------------------------------------*/
-  n = idasls_mem->s_JacMat->N;
-  num_threads = slumt_data->num_threads;
-
-  StatInit(n, num_threads, slumt_data->Gstat);
-
-  idasls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the IDASuperLUMT linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     IDASLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int IDASuperLUMTSetup(IDAMem IDA_mem, N_Vector yyp, N_Vector ypp,
-			     N_Vector rrp, N_Vector tmp1, N_Vector tmp2,
-			     N_Vector tmp3)
-{
-  int retval, info;
-  int nprocs, panel_size, relax, permc_spec, lwork;
-  int *perm_r, *perm_c;
-  realtype tn, cj;
-  double diag_pivot_thresh, drop_tol;
-  fact_t fact;
-  trans_t trans;
-  yes_no_t refact, usepr;
-  IDASlsMem idasls_mem;
-  IDASlsSparseJacFn jaceval;
-  SuperMatrix *A, *AC, *L, *U;
-  Gstat_t *Gstat;
-  superlumt_options_t *superlumt_options;
-  SLUMTData slumt_data;
-  SlsMat JacMat;
-  void *jacdata;
-  void *work;
-  
-  idasls_mem = (IDASlsMem) (IDA_mem->ida_lmem);
-  tn = IDA_mem->ida_tn; 
-  cj = IDA_mem->ida_cj;
-
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-  jaceval = idasls_mem->s_jaceval;
-  jacdata = idasls_mem->s_jacdata;
-  JacMat = idasls_mem->s_JacMat;
-
-  superlumt_options = slumt_data->superlumt_options;
-  A = slumt_data->s_A;
-  AC = slumt_data->s_AC;
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  Gstat = slumt_data->Gstat;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  nprocs = slumt_data->num_threads;
-  diag_pivot_thresh = slumt_data->diag_pivot_thresh;
-
-  /* Set option values for SuperLU_MT */
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  fact = EQUILIBRATE;
-  trans = NOTRANS;
-  usepr = NO;
-  drop_tol = 0.0;
-  lwork = 0;
-  work = NULL;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    IDAProcessError(IDA_mem, IDASLS_JAC_NOSET, "IDASSLS", "IDASuperLUMTSetup", 
-		    MSGSP_JAC_NOSET);
-    free(idasls_mem); idasls_mem = NULL;
-    return(IDASLS_JAC_NOSET);
-  }
-
-  /* Increment nje counter and call Jacobian eval routine. */
-  idasls_mem->s_nje++;
-  retval = jaceval(tn, cj, yyp, ypp, rrp, JacMat, jacdata, 
-		   tmp1, tmp2, tmp3);
-
-  if (retval < 0) {
-    IDAProcessError(IDA_mem, IDASLS_JACFUNC_UNRECVR, "IDASSLS", 
-		    "IDASuperLUMTSetup", MSGSP_JACFUNC_FAILED);
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_UNRECVR;
-    return(IDASLS_JACFUNC_UNRECVR);
-  }
-  if (retval > 0) {
-    idasls_mem->s_last_flag = IDASLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  if (idasls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get column permutation vector perm_c[], according to permc_spec:
-       permc_spec = 3: approximate minimum degree for unsymmetric matrices
-       ------------------------------------------------------------*/ 
-    permc_spec = 3;
-    get_perm_c(permc_spec, A, perm_c);
- 
-    refact= NO;
-    idasls_mem->s_first_factorize = 0;
-  }
-  else {
-    /* ------------------------------------------------------------
-       Re-initialize statistics variables 
-       ------------------------------------------------------------*/
-    StatInit(JacMat->N, nprocs, Gstat);
-    Destroy_CompCol_Permuted(AC);
-    refact= YES;
-  }
-
-  /* ------------------------------------------------------------
-     Initialize the option structure superlumt_options using the
-     user-input parameters;  Subsequent calls will re-initialize
-     options.
-     Apply perm_c to the columns of original A to form AC.
-     ------------------------------------------------------------*/
-  pdgstrf_init(nprocs, fact, trans, refact, panel_size, relax,
-	       diag_pivot_thresh, usepr, drop_tol, perm_c, perm_r,
-	       work, lwork, A, AC, superlumt_options, Gstat);
-  /* ------------------------------------------------------------
-     Compute the LU factorization of A.
-     The following routine will create nprocs threads.
-     ------------------------------------------------------------*/
-  pdgstrf(superlumt_options, AC, perm_r, L, U, Gstat, &info);
-    
-  if (info != 0) {
-    idasls_mem->s_last_flag = info;
-    return(+1);
-  }
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the IDASuperLUMT linear
-  solver module.  It calls the SuperLUMT solve routine, scales the
-  solution vector according to cjratio, then returns IDASLU_SUCCESS = 0.
-*/
-
-static int IDASuperLUMTSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
-			     N_Vector ycur, N_Vector ypcur, N_Vector rrcur)
-{
-  int info, trans;
-  int *perm_r, *perm_c;
-  double cjratio;
-  IDASlsMem idasls_mem;
-  SuperMatrix *L, *U, *B;
-  Gstat_t *Gstat;
-  DNformat *Bstore;
-  SLUMTData slumt_data;
-  realtype *bd;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-  cjratio = IDA_mem->ida_cjratio;
-
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  Gstat = slumt_data->Gstat;
-  B = slumt_data->s_B;
-   
-  bd = N_VGetArrayPointer(b);
-  Bstore = (DNformat *) (B->Store);
-  Bstore->nzval = bd;
-
-  /* Call SuperLUMT to solve the linear system using L and U */
-  trans = NOTRANS;
-  dgstrs(trans, L, U, perm_r, perm_c, B, Gstat, &info);
-
-  /* Scale the correction to account for change in cj. */
-  if (cjratio != ONE) N_VScale(TWO/(ONE + cjratio), b, b);
-
-  Bstore->nzval = NULL;
-
-  idasls_mem->s_last_flag = IDASLS_SUCCESS;
-  return(IDASLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the IDASuperLUMT linear solver.
-*/
-
-static int IDASuperLUMTFree(IDAMem IDA_mem)
-{
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-  
-  idasls_mem = (IDASlsMem) IDA_mem->ida_lmem;
-
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  pxgstrf_finalize(slumt_data->superlumt_options, slumt_data->s_AC);
-
-  free(slumt_data->perm_r);
-  free(slumt_data->perm_c);
-  free(slumt_data->superlumt_options);
-  Destroy_SuperNode_SCP( (slumt_data->s_L) );
-  Destroy_CompCol_NCP( (slumt_data->s_U) );
-  StatFree( (slumt_data->Gstat) );
-  free(slumt_data->Gstat);
-  
-  Destroy_SuperMatrix_Store(slumt_data->s_B);
-  SUPERLU_FREE(slumt_data->s_A->Store);
-  if (idasls_mem->s_JacMat) {
-    SparseDestroyMat(idasls_mem->s_JacMat);
-    idasls_mem->s_JacMat = NULL;
-  }
-
-  free(slumt_data->s_B);
-  free(slumt_data->s_A);
-  free(slumt_data->s_AC);
-  free(slumt_data->s_L);
-  free(slumt_data->s_U);
-
-  free(slumt_data); 
-  slumt_data = NULL;
- 
-  free(IDA_mem->ida_lmem); 
-  IDA_mem->ida_lmem = NULL;
-
-  return(IDASLS_SUCCESS);
-}
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * IDASuperLUMTSetOrdering sets the ordering used by SuperLUMT for reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int IDASuperLUMTSetOrdering(void *ida_mem_v, int ordering_choice)
-{
-  IDAMem ida_mem;
-  IDASlsMem idasls_mem;
-  SLUMTData slumt_data;
-
- /* Return immediately if ida_mem is NULL */
-  if (ida_mem_v == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASLS", "IDASuperLUMTSetOrdering",
-		    MSGSP_IDAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  ida_mem = (IDAMem) ida_mem_v;
-  idasls_mem = (IDASlsMem) ida_mem->ida_lmem;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) && (ordering_choice != 3) ) {
-    IDAProcessError(NULL, IDASLS_ILL_INPUT, "IDASLS", "IDASuperLUMTSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  slumt_data = (SLUMTData) idasls_mem->s_solver_data;
-
-  slumt_data->s_ordering = ordering_choice;
-
-  return(IDASLS_SUCCESS);
-}
-
-
-
-/* 
- * ================================================================
- *
- *                   PART II - backward problems
- *
- * ================================================================
- */
-
-/*
- * IDASuperLUMTB is a wrapper around IDASuperLUMT.
- */
-
-int IDASuperLUMTB(void *ida_mem, int which, int num_threads, int n, int nnz)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  IDASlsMemB idaslsB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDASuperLUMTB", 
-		    MSGSP_CAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASLS_NO_ADJ, "IDASSLS", "IDASuperLUMTB",  
-		    MSGSP_NO_ADJ);
-    return(IDASLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDASuperLUMTB", 
-		    MSGSP_BAD_WHICH);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  /* Alloc memory for IDASlsMemRecB */
-  idaslsB_mem = (IDASlsMemB) malloc(sizeof(struct IDASlsMemRecB));
-  if (idaslsB_mem == NULL) {
-    IDAProcessError(IDAB_mem->IDA_mem, IDASLS_MEM_FAIL, "IDASSLS", 
-		    "IDASuperLUMTB", MSGSP_MEM_FAIL);
-    return(IDASLS_MEM_FAIL);
-  
-  }
-
-  /* set matrix type and initialize Jacob function. */
-  idaslsB_mem->s_djacB = NULL;
-
-  /* Attach lmemB data and lfreeB function. */
-  IDAB_mem->ida_lmem  = idaslsB_mem;
-  IDAB_mem->ida_lfree = IDASuperLUMTFreeB;
-
-  /* Call IDASuperLUMT to the IDAS data of the backward problem. */
-  ida_memB = (void *)IDAB_mem->IDA_mem;
-  flag = IDASuperLUMT(ida_memB, num_threads, n, nnz);
-
-  if (flag != IDASLS_SUCCESS) {
-    free(idaslsB_mem);
-    idaslsB_mem = NULL;
-  }
-
-  return(flag);
-}
-
-
-/*
- * IDASuperLUMTSetOrderingB is a wrapper around IDASuperLUMTSetOrdering.
- */
-int IDASuperLUMTSetOrderingB(void *ida_mem, int which, int ordering_choiceB)
-{
-  IDAMem IDA_mem;
-  IDAadjMem IDAADJ_mem;
-  IDABMem IDAB_mem;
-  void *ida_memB;
-  int flag;
-  
-  /* Is ida_mem allright? */
-  if (ida_mem == NULL) {
-    IDAProcessError(NULL, IDASLS_MEM_NULL, "IDASSLS", "IDASuperLUMTB", 
-		    MSGSP_CAMEM_NULL);
-    return(IDASLS_MEM_NULL);
-  }
-  IDA_mem = (IDAMem) ida_mem;
-
-  /* Is ASA initialized? */
-  if (IDA_mem->ida_adjMallocDone == FALSE) {
-    IDAProcessError(IDA_mem, IDASLS_NO_ADJ, "IDASSLS", "IDASuperLUMTB",  
-		    MSGSP_NO_ADJ);
-    return(IDASLS_NO_ADJ);
-  }
-  IDAADJ_mem = IDA_mem->ida_adj_mem;
-
-  /* Check the value of which */
-  if ( which >= IDAADJ_mem->ia_nbckpbs ) {
-    IDAProcessError(IDA_mem, IDASLS_ILL_INPUT, "IDASSLS", "IDASuperLUMTB", 
-		    MSGSP_BAD_WHICH);
-    return(IDASLS_ILL_INPUT);
-  }
-
-  /* Find the IDABMem entry in the linked list corresponding to 'which'. */
-  IDAB_mem = IDAADJ_mem->IDAB_mem;
-  while (IDAB_mem != NULL) {
-    if( which == IDAB_mem->ida_index ) break;
-    /* advance */
-    IDAB_mem = IDAB_mem->ida_next;
-  }
-
-  ida_memB = (void *)(IDAB_mem->IDA_mem);
-  
-  flag = IDASuperLUMTSetOrdering(ida_memB, ordering_choiceB);
-
-  return(flag);
-}
-
-
-
-
-/*
- * IDASuperLUMTFreeB frees the linear solver's memory for that backward problem passed 
- * as argument. 
- */
-
-static int IDASuperLUMTFreeB(IDABMem IDAB_mem)
-{
-  IDASlsMemB idaslsB_mem;
-
-  idaslsB_mem = (IDASlsMemB) IDAB_mem->ida_lmem;
-
-  free(idaslsB_mem);
-
-  return(0);
-}
-
diff --git a/src/kinsol/CMakeLists.txt b/src/kinsol/CMakeLists.txt
index d22ed62..5f2b1f1 100644
--- a/src/kinsol/CMakeLists.txt
+++ b/src/kinsol/CMakeLists.txt
@@ -1,18 +1,20 @@
 # ---------------------------------------------------------------
-# $Revision: 4917 $
-# $Date: 2016-09-18 23:24:29 -0700 (Sun, 18 Sep 2016) $
+# Programmer(s):  Daniel R. Reynolds @ SMU
+#                 Radu Serban @ LLNL
 # ---------------------------------------------------------------
-# Programmer:  Radu Serban @ LLNL
-# ---------------------------------------------------------------
-# LLNS Copyright Start
-# Copyright (c) 2014, Lawrence Livermore National Security
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
 # This work was performed under the auspices of the U.S. Department 
-# of Energy by Lawrence Livermore National Laboratory in part under 
-# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
-# Produced at the Lawrence Livermore National Laboratory.
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
 # All rights reserved.
 # For details, see the LICENSE file.
-# LLNS Copyright End
+# LLNS/SMU Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the KINSOL library
 
@@ -23,97 +25,56 @@ SET(kinsol_SOURCES
   kinsol.c
   kinsol_io.c
   kinsol_direct.c
-  kinsol_band.c
-  kinsol_dense.c
-  kinsol_sparse.c
   kinsol_spils.c
-  kinsol_spbcgs.c
-  kinsol_spfgmr.c
-  kinsol_spgmr.c
-  kinsol_sptfqmr.c
   kinsol_bbdpre.c
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND kinsol_SOURCES kinsol_klu.c)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND kinsol_SOURCES kinsol_superlumt.c)
-ENDIF()
-
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the KINSOL library
 SET(shared_SOURCES
-  sundials_nvector.c
-  sundials_math.c
-  sundials_direct.c
-  sundials_band.c
-  sundials_dense.c
-  sundials_iterative.c
-  sundials_sparse.c
-  sundials_spbcgs.c
-  sundials_spfgmr.c
-  sundials_spgmr.c
-  sundials_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_band.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_dense.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_direct.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_version.c
+  ${sundials_SOURCE_DIR}/src/nvec_ser/nvector_serial.c
+  )
+
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the KINSOL library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/sunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/sunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/sunmatrix_sparse.c
   )
 
-# Add prefix with complete path to the common SUNDIALS sources
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the KINSOL library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/sunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/sunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/sunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/sunlinsol_pcg.c
+  )
 
 # Add variable kinsol_HEADERS with the exported KINSOL header files
 SET(kinsol_HEADERS
-  kinsol_band.h
   kinsol_bbdpre.h
-  kinsol_dense.h
   kinsol_direct.h
   kinsol.h
-  kinsol_spbcgs.h
-  kinsol_spfgmr.h
-  kinsol_spgmr.h
   kinsol_spils.h
-  kinsol_sptfqmr.h
   )
 
-IF(KLU_FOUND)
-    LIST(APPEND kinsol_HEADERS kinsol_klu.h kinsol_sparse.h)
-ENDIF()
-
-IF(SUPERLUMT_FOUND)
-    LIST(APPEND kinsol_HEADERS kinsol_superlumt.h kinsol_sparse.h)
-ENDIF()
-
 # Add prefix with complete path to the KINSOL header files
 ADD_PREFIX(${sundials_SOURCE_DIR}/include/kinsol/ kinsol_HEADERS)
 
-# If Blas/Lapack support was enabled, set-up additional file lists
-IF(LAPACK_FOUND)
-  SET(kinsol_BL_SOURCES kinsol_lapack.c)
-  SET(kinsol_BL_HEADERS kinsol_lapack.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/kinsol/ kinsol_BL_HEADERS)
-ELSE(LAPACK_FOUND)
-  SET(kinsol_BL_SOURCES "")
-  SET(kinsol_BL_HEADERS "")
-ENDIF(LAPACK_FOUND)
-
-IF(SUPERLUMT_FOUND)
-  SET(kinsol_SLU_SOURCES kinsol_superlumt.c)
-  SET(kinsol_SLU_HEADERS kinsol_superlumt.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/kinsol/ kinsol_SLU_HEADERS)
-ELSE(SUPERLUMT_FOUND)
-  SET(kinsol_SLU_SOURCES "")
-  SET(kinsol_SLU_HEADERS "")
-ENDIF(SUPERLUMT_FOUND)
-
-IF(KLU_FOUND)
-  SET(kinsol_KLU_SOURCES kinsol_klu.c)
-  SET(kinsol_KLU_HEADERS kinsol_klu.h)
-  ADD_PREFIX(${sundials_SOURCE_DIR}/include/kinsol/ kinsol_KLU_HEADERS)
-ELSE(KLU_FOUND)
-  SET(kinsol_KLU_SOURCES "")
-  SET(kinsol_KLU_HEADERS "")
-ENDIF(KLU_FOUND)
-
 # Add source directories to include directories for access to
 # implementation only header files.
 INCLUDE_DIRECTORIES(.)
@@ -127,7 +88,7 @@ IF(BUILD_STATIC_LIBS)
 
   # Add the build target for the static KINSOL library
   ADD_LIBRARY(sundials_kinsol_static STATIC
-    ${kinsol_SOURCES} ${kinsol_BL_SOURCES} ${kinsol_SLU_SOURCES} ${kinsol_KLU_SOURCES} ${shared_SOURCES})
+    ${kinsol_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_kinsol_static
@@ -143,7 +104,11 @@ IF(BUILD_SHARED_LIBS)
 
   # Add the build target for the KINSOL library
   ADD_LIBRARY(sundials_kinsol_shared SHARED
-    ${kinsol_SOURCES} ${kinsol_BL_SOURCES} ${kinsol_SLU_SOURCES} ${kinsol_KLU_SOURCES} ${shared_SOURCES})
+    ${kinsol_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_kinsol_shared m)
+  ENDIF()
 
   # Set the library name and make sure it is not deleted
   SET_TARGET_PROPERTIES(sundials_kinsol_shared
@@ -159,7 +124,7 @@ IF(BUILD_SHARED_LIBS)
 ENDIF(BUILD_SHARED_LIBS)
 
 # Install the KINSOL header files
-INSTALL(FILES ${kinsol_HEADERS} ${kinsol_BL_HEADERS} ${kinsol_SLU_HEADERS} ${kinsol_KLU_HEADERS} DESTINATION include/kinsol)
+INSTALL(FILES ${kinsol_HEADERS} DESTINATION include/kinsol)
 
 # Install the KINSOL implementation header file
 INSTALL(FILES kinsol_impl.h DESTINATION include/kinsol)
diff --git a/src/kinsol/README b/src/kinsol/README
index f087a61..5d07772 100644
--- a/src/kinsol/README
+++ b/src/kinsol/README
@@ -1,5 +1,5 @@
                              KINSOL
-                   Release 2.9.0, September 2016
+                   Release 3.1.0, November 2017
      Aaron Collier, Alan C. Hindmarsh, Radu Serban, and Carol S. Woodward
              Center for Applied Scientific Computing, LLNL
 
@@ -85,6 +85,8 @@ C. References
 D. Releases
 -----------
 
+v. 3.1.0   - Nov. 2017
+v. 3.0.0   - Sep. 2017
 v. 2.9.0   - Sep. 2016
 v. 2.8.2   - Aug. 2015
 v. 2.8.1   - Mar. 2015
diff --git a/src/kinsol/fcmix/CMakeLists.txt b/src/kinsol/fcmix/CMakeLists.txt
index 16377cf..3a4fbf9 100644
--- a/src/kinsol/fcmix/CMakeLists.txt
+++ b/src/kinsol/fcmix/CMakeLists.txt
@@ -1,3 +1,20 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Southern Methodist University and Lawrence Livermore
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
 # CMakeLists.txt file for the FKINSOL library
 
 # Add variable fcvode_SOURCES with the sources for the FCVODE library
@@ -8,31 +25,54 @@ SET(fkinsol_SOURCES
   fkinjtimes.c
   fkinpreco.c
   fkinsol.c
+  fkinsparse.c
+  )
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the ARKODE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/nvec_ser/fnvector_serial.c
+  )
+
+# Add variable sunmatrix_SOURCES with the common SUNMatrix sources which will
+# also be included in the ARKODE library
+SET(sunmatrix_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunmat_band/fsunmatrix_band.c
+  ${sundials_SOURCE_DIR}/src/sunmat_dense/fsunmatrix_dense.c
+  ${sundials_SOURCE_DIR}/src/sunmat_sparse/fsunmatrix_sparse.c
+  )
+
+# Add variable sunlinsol_SOURCES with the common SUNLinearSolver sources which will
+# also be included in the ARKODE library
+SET(sunlinsol_SOURCES
+  ${sundials_SOURCE_DIR}/src/sunlinsol_band/fsunlinsol_band.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_dense/fsunlinsol_dense.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_spgmr/fsunlinsol_spgmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c
+  ${sundials_SOURCE_DIR}/src/sunlinsol_pcg/fsunlinsol_pcg.c
   )
 
-IF(LAPACK_FOUND)
-  SET(fkinsol_BL_SOURCES fkinlapack.c fkinlapdense.c fkinlapband.c)
-ELSE(LAPACK_FOUND)
-  SET(fkinsol_BL_SOURCES "")
-ENDIF(LAPACK_FOUND)
-
-IF(KLU_FOUND OR SUPERLUMT_FOUND)
-  SET(fkinsol_SPARSE_SOURCES fkinsparse.c)
-ELSE(SPARSE_FOUND)
-  SET(fkinsol_SPARSE_SOURCES "")
-ENDIF(KLU_FOUND OR SUPERLUMT_FOUND)
- 
 IF(KLU_FOUND)
-  SET(fkinsol_KLU_SOURCES fkinklu.c)
-ELSE(KLU_FOUND)
-  SET(fkinsol_KLU_SOURCES "")
-ENDIF(KLU_FOUND)
- 
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_klu/fsunlinsol_klu.c
+    )
+ENDIF()
+
 IF(SUPERLUMT_FOUND)
-  SET(fkinsol_SUPERLUMT_SOURCES fkinsuperlumt.c)
-ELSE(SUPERLUMT_FOUND)
-  SET(fkinsol_SUPERLUMT_SOURCES "")
-ENDIF(SUPERLUMT_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_superlumt/fsunlinsol_superlumt.c
+    )
+ENDIF()
+
+IF(LAPACK_FOUND)
+  LIST(APPEND sunlinsol_SOURCES
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackband/fsunlinsol_lapackband.c
+    ${sundials_SOURCE_DIR}/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c
+    )
+ENDIF()
+
 
 # Add source directories to include directories for access to
 # implementation only header files (both for fkinsol and kinsol)
@@ -47,7 +87,8 @@ ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
 # coming from inexistent user-provided functions)
 
 # Add the build target for the FKINSOL library
-ADD_LIBRARY(sundials_fkinsol_static STATIC ${fkinsol_SOURCES} ${fkinsol_BL_SOURCES} ${fkinsol_SPARSE_SOURCES} ${fkinsol_KLU_SOURCES} ${fkinsol_SUPERLUMT_SOURCES})
+ADD_LIBRARY(sundials_fkinsol_static STATIC
+  ${fkinsol_SOURCES} ${shared_SOURCES} ${sunmatrix_SOURCES} ${sunlinsol_SOURCES} )
 
 # Set the library name and make sure it is not deleted
 SET_TARGET_PROPERTIES(sundials_fkinsol_static
diff --git a/src/kinsol/fcmix/fkinband.c b/src/kinsol/fcmix/fkinband.c
index fb949e6..9d80d11 100644
--- a/src/kinsol/fcmix/fkinband.c
+++ b/src/kinsol/fcmix/fkinband.c
@@ -1,14 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
+/* -----------------------------------------------------------------
  * Programmer(s): Radu Serban @ LLNL
+ *                David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -17,8 +14,7 @@
  * -----------------------------------------------------------------
  * Fortran/C interface routines for KINSOL/KINBAND, for the case
  * of a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -26,7 +22,8 @@
 #include "fkinsol.h"     /* standard interfaces and global vars.*/
 #include "kinsol_impl.h" /* definition of KINMem type           */
 
-#include <kinsol/kinsol_band.h>
+#include <kinsol/kinsol_direct.h>
+#include <sunmatrix/sunmatrix_band.h>
 
 /*
  * ----------------------------------------------------------------
@@ -38,10 +35,11 @@
 extern "C" {
 #endif
 
-extern void FK_BJAC(long int*, long int*, long int*, long int*,
-                    realtype*, realtype*,
-                    realtype*,
-                    realtype*, realtype*, int*);
+extern void FK_BJAC(long int* N, long int* MU, long int* ML,
+                    long int* EBAND,
+                    realtype* UU, realtype* FU,
+                    realtype* BJAC,
+                    realtype* WK1, realtype* WK2, int* IER);
 
 #ifdef __cplusplus
 }
@@ -56,10 +54,10 @@ extern void FK_BJAC(long int*, long int*, long int*, long int*,
 void FKIN_BANDSETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = KINDlsSetBandJacFn(KIN_kinmem, NULL);
+    *ier = KINDlsSetJacFn(KIN_kinmem, NULL);
   }
   else {
-    *ier = KINDlsSetBandJacFn(KIN_kinmem, FKINBandJac);
+    *ier = KINDlsSetJacFn(KIN_kinmem, FKINBandJac);
   }
 
   return;
@@ -77,13 +75,12 @@ void FKIN_BANDSETJAC(int *flag, int *ier)
  * ----------------------------------------------------------------
  */
 
-int FKINBandJac(long int N, long int mupper, long int mlower,
-                N_Vector uu, N_Vector fval, 
-                DlsMat J, void *user_data,
+int FKINBandJac(N_Vector uu, N_Vector fval,
+                SUNMatrix J, void *user_data,
                 N_Vector vtemp1, N_Vector vtemp2)
 {
   realtype *uu_data, *fval_data, *jacdata, *v1_data, *v2_data;
-  long int eband;
+  long int N, mupper, mlower, smu, eband;
   int ier;
 
   /* Initialize all pointers to NULL */
@@ -101,8 +98,12 @@ int FKINBandJac(long int N, long int mupper, long int mlower,
   v1_data   = N_VGetArrayPointer(vtemp1);
   v2_data   = N_VGetArrayPointer(vtemp2);
 
-  eband = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
+  N       = SUNBandMatrix_Columns(J);
+  mupper  = SUNBandMatrix_UpperBandwidth(J);
+  mlower  = SUNBandMatrix_LowerBandwidth(J);
+  smu     = SUNBandMatrix_StoredUpperBandwidth(J);
+  eband   = smu + mlower + 1;
+  jacdata = SUNBandMatrix_Column(J,0) - mupper;
 
   /* Call user-supplied routine */
   FK_BJAC(&N, &mupper, &mlower, &eband,
diff --git a/src/kinsol/fcmix/fkinbbd.c b/src/kinsol/fcmix/fkinbbd.c
index dfb6cad..507300e 100644
--- a/src/kinsol/fcmix/fkinbbd.c
+++ b/src/kinsol/fcmix/fkinbbd.c
@@ -1,15 +1,12 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
+ *                David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -21,8 +18,7 @@
  * names are used (e.g. FK_COMMFN). The routines here call the
  * generically named routines and provide a standard interface to
  * the C code of the KINBBDPRE package.
- * ----------------------------------------------------------------
- */
+ * ----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,9 +27,6 @@
 #include "fkinbbd.h"               /* prototypes of interfaces to KINBBDPRE        */
 
 #include <kinsol/kinsol_bbdpre.h>  /* prototypes of KINBBDPRE functions and macros */
-#include <kinsol/kinsol_sptfqmr.h> /* prototypes of KINSPTFQMR interface routines  */
-#include <kinsol/kinsol_spbcgs.h>  /* prototypes of KINSPBCG interface routines    */
-#include <kinsol/kinsol_spgmr.h>   /* prototypes of KINSPGMR interface routines    */
 
 /*
  * ----------------------------------------------------------------
@@ -53,8 +46,8 @@
 extern "C" {
 #endif
 
-extern void FK_LOCFN(long int*, realtype*, realtype*, int*);
-extern void FK_COMMFN(long int*, realtype*, int*);
+extern void FK_LOCFN(long int* NLOC, realtype* ULOC, realtype* GLOC, int* IER);
+extern void FK_COMMFN(long int* NLOC, realtype* ULOC, int* IER);
 
 #ifdef __cplusplus
 }
@@ -69,8 +62,8 @@ extern void FK_COMMFN(long int*, realtype*, int*);
 void FKIN_BBDINIT(long int *nlocal, long int *mudq, long int *mldq,
 		  long int *mu, long int *ml, int *ier)
 {
-  *ier = KINBBDPrecInit(KIN_kinmem, *nlocal, *mudq, *mldq,
-                        *mu, *ml, ZERO, FKINgloc, FKINgcomm);
+  *ier = KINBBDPrecInit(KIN_kinmem, *nlocal, *mudq, *mldq, *mu, *ml, ZERO,
+                        (KINBBDLocalFn) FKINgloc, (KINBBDCommFn) FKINgcomm);
 
   return;
 }
@@ -89,16 +82,23 @@ int FKINgloc(long int Nloc, N_Vector uu, N_Vector gval, void *user_data)
   realtype *uloc, *gloc;
   int ier;
 
+  /* Initialize all pointers to NULL */
   uloc = gloc = NULL;
 
+  /* NOTE: The user-supplied routine should set ier to an
+     appropriate value, but we preset the value to zero
+     (meaning SUCCESS) so the user need only reset the
+     value if an error occurred */
+  ier = 0;
+
+  /* Get pointers to vector data */
   uloc = N_VGetArrayPointer(uu);
   gloc = N_VGetArrayPointer(gval);
 
+  /* Call user-supplied routine */
   FK_LOCFN(&Nloc, uloc, gloc, &ier);
 
-  N_VSetArrayPointer(gloc, gval);
-
-  return(0);
+  return(ier);
 }
 
 /*
@@ -115,13 +115,22 @@ int FKINgcomm(long int Nloc, N_Vector uu, void *user_data)
   realtype *uloc;
   int ier;
 
+  /* Initialize all pointers to NULL */
   uloc = NULL;
 
+  /* NOTE: The user-supplied routine should set ier to an
+     appropriate value, but we preset the value to zero
+     (meaning SUCCESS) so the user need only reset the
+     value if an error occurred */
+  ier = 0;
+
+  /* Get pointers to vector data */
   uloc = N_VGetArrayPointer(uu);
   
+  /* Call user-supplied routine */
   FK_COMMFN(&Nloc, uloc, &ier);
 
-  return(0);
+  return(ier);
 }
 
 /*
diff --git a/src/kinsol/fcmix/fkinbbd.h b/src/kinsol/fcmix/fkinbbd.h
index a045ac1..1690828 100644
--- a/src/kinsol/fcmix/fkinbbd.h
+++ b/src/kinsol/fcmix/fkinbbd.h
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4398 $
- * $Date: 2015-02-28 14:29:35 -0800 (Sat, 28 Feb 2015) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -18,33 +14,27 @@
  * -----------------------------------------------------------------
  * This is the Fortran interface include file for the BBD
  * preconditioner module KINBBDPRE.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 /*******************************************************************************
 
                   FKINBBD Interface Package
 
  The FKINBBD Interface Package is a package of C functions which support the
- use of the KINSOL solver with the KINBBDPRE preconditioner module, for the
- solution of nonlinear systems in a mixed Fortran/C setting. The combination
- of KINSOL and KINBBDPRE solves systems f(u) = 0 with the SPGMR (scaled
- preconditioned GMRES), SPFGMR (scaled preconditioned flexible GMRES), 
- SPBCG (scaled preconditioned Bi-CGSTAB), or SPTFQMR
- (scaled preconditioned TFQMR) method for the linear systems that arise, and
- with a preconditioner that is block-diagonal with banded blocks. While KINSOL
- and KINBBDPRE are written in C, it is assumed here that the user's calling
- program and user-supplied problem-defining routines are written in Fortran.
+ use of the KINSOL solver and MPI-parallel N_Vector module, along with the 
+ KINBBDPRE preconditioner module, for the solution of nonlinear systems in a
+ mixed Fortran/C setting. The combination of KINSOL and KINBBDPRE solves systems
+ linear system arising from the solution of f(u) = 0 using a Krylov iterative
+ linear solver via the KINSPILS interface, and with a preconditioner that is
+ block-diagonal with banded blocks. While KINSOL and KINBBDPRE are written in C,
+ it is assumed here that the user's calling program and user-supplied
+ problem-defining routines are written in Fortran.
 
  The user-callable functions in this package, with the corresponding KINSOL and
  KINBBDPRE functions, are as follows:
 
    FKINBBDINIT : interfaces to KINBBDPrecInit
-   FKINBBDSPTFQMR: interfaces with KINSptfqmr
-   FKINBBDSPBCG : interfaces with KINSpbcg
-   FKINBBDSPGMR : interfaces with KINSpgmr
-   FKINBBDSPFGMR : interfaces with KINSpfgmr
-   FKINBBDOPT : accesses optional outputs
+   FKINBBDOPT  : accesses optional outputs
    FKINBBDFREE : interfaces to KINBBDPrecFree
 
  In addition to the Fortran system function FKFUN, and optional Jacobian vector
@@ -52,8 +42,8 @@
  required by this package, each with the corresponding interface function which
  calls it (and its type within KINBBDPRE):
 
-   FKLOCFN : called by the interface function FKINgloc of type KINLocalFn
-   FKCOMMFN : called by the interface function FKINgcomm of type KINCommFn
+   FKLOCFN  : called by the interface function FKINgloc of type KINBBDLocalFn
+   FKCOMMFN : called by the interface function FKINgcomm of type KINBBDCommFn
 
  Note: The names of all user-supplied routines here are fixed, in order to
  maximize portability for the resulting mixed-language program.
@@ -179,35 +169,52 @@
                        input values in IOPT[] array are to be used for
                        input: 0 = no and 1 = yes.
          IOPT        = array for integer optional inputs and outputs (declare
-                       as INTEGER*4 or INTEGER*8 according to C type long int)
+                       as INTEGER*8
          ROPT        = array of real optional inputs and outputs
          IER         = return completion flag. Values are 0 = success, and
                        -1 = failure.
 
        Note: See printed message for details in case of failure.
 
- (4.3) Attach one of the SPILS linear solvers. Make one of the 
-       following calls (see fkinsol.h) for more details.
-          CALL FKINSPGMR (MAXL, MAXLRST, IER)
-          CALL FKINSPFGMR (MAXL, MAXLRST, IER)
-          CALL FKINSPBCG (MAXL, IER)
-          CALL FKINSPTFQMR (MAXL, IER)
+ (4.3) Initialize and attach one of the SPILS linear solvers. Make one of the 
+       following calls to initialize a solver (see fkinsol.h for more details):
 
- (4.4) To allocate memory and initialize data associated with the BBD
-       preconditioner, make the following call:
+         CALL FSUNPCGINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPBCGSINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPFGMRINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPGMRINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPTFQMRINIT(3, PRETYPE, MAXL, IER)
 
-         CALL FKINBBDINIT (NLOCAL, MU, ML, IER)
+       Then to attach the iterative linear solver structure the user must call:
 
-       The arguments are:
-         NLOCAL   = local size of vectors associated with process
-         MU, ML   = upper and lower half-bandwidths to be used during the
-                    computation of the local Jacobian blocks. These may be
-                    smaller than the true half-bandwidths of the Jacobian
-                    of the local block of g, when smaller values may provide
-                    greater efficiency.
-         IER      = return completion flag. Values are 0 = success, and
-                    -1 = failure.
+         CALL FKINSPILSINIT(IER)
+
+ (4.4) To allocate memory and initialize data associated with the BBD
+       preconditioner, make the following call:
 
+        CALL FKINBBDINIT(NLOCAL, MUDQ, MLDQ, MU, ML, IER)
+
+      The arguments are:
+        NLOCAL = local vector size on this process [long int, input]
+        MUDQ   = upper half-bandwidth to be used in the computation
+                 of the local Jacobian blocks by difference 
+                 quotients.  These may be smaller than the true 
+                 half-bandwidths of the Jacobian of the local block 
+                 of g, when smaller values may provide greater 
+                 efficiency [long int, input]
+        MLDQ   = lower half-bandwidth to be used in the computation
+                 of the local Jacobian blocks by difference 
+                 quotients [long int, input]
+        MU     = upper half-bandwidth of the band matrix that is
+                 retained as an approximation of the local Jacobian
+                 block (may be smaller than MUDQ) [long int, input]
+        ML     = lower half-bandwidth of the band matrix that is
+                 retained as an approximation of the local Jacobian
+                 block (may be smaller than MLDQ) [long int, input]
+        IER    = return completion flag [int, output]:
+                    0 = success
+                   <0 = an error occurred
+ 
  (5) To solve the system, make the following call:
 
        CALL FKINSOL (UU, GLOBALSTRAT, USCALE, FSCALE, IER)
diff --git a/src/kinsol/fcmix/fkindense.c b/src/kinsol/fcmix/fkindense.c
index 77551a5..90bd27e 100644
--- a/src/kinsol/fcmix/fkindense.c
+++ b/src/kinsol/fcmix/fkindense.c
@@ -1,24 +1,20 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
+/* -----------------------------------------------------------------
  * Programmer(s): Aaron Collier @ LLNL
+ *                David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS Copyright End
  * -----------------------------------------------------------------
- * Fortran/C interface routines for KINSOL/KINDENSE, for the case
+ * Fortran/C interface routines for KINSOL/KINDLS, for the case
  * of a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -26,7 +22,8 @@
 #include "fkinsol.h"     /* prototypes of standard interfaces and global vars.*/
 #include "kinsol_impl.h" /* definition of KINMem type                         */
 
-#include <kinsol/kinsol_dense.h>
+#include <kinsol/kinsol_direct.h>
+#include <sunmatrix/sunmatrix_dense.h>
 
 /*
  * ----------------------------------------------------------------
@@ -38,8 +35,9 @@
 extern "C" {
 #endif
 
-extern void FK_DJAC(long int*, realtype*, realtype*, realtype*,
-		    realtype*, realtype*, int*);
+extern void FK_DJAC(long int* N, realtype* uudata , realtype* fdata,
+                    realtype* jacdata, realtype* v1, realtype* v2,
+                    int* ier);
 
 #ifdef __cplusplus
 }
@@ -54,10 +52,10 @@ extern void FK_DJAC(long int*, realtype*, realtype*, realtype*,
 void FKIN_DENSESETJAC(int *flag, int *ier)
 {
   if (*flag == 0) {
-    *ier = KINDlsSetDenseJacFn(KIN_kinmem, NULL);
+    *ier = KINDlsSetJacFn(KIN_kinmem, NULL);
   }
   else {
-    *ier = KINDlsSetDenseJacFn(KIN_kinmem, FKINDenseJac);
+    *ier = KINDlsSetJacFn(KIN_kinmem, FKINDenseJac);
   }
   return;
 }
@@ -69,16 +67,16 @@ void FKIN_DENSESETJAC(int *flag, int *ier)
  * C function FKINDenseJac interfaces between KINSOL and a Fortran
  * subroutine FKDJAC for solution of a linear system with dense
  * Jacobian approximation. Addresses are passed to FKDJAC, using
- * the macro DENSE_COL from DENSE and the routine N_VGetArrayPointer
- * from NVECTOR. Auxiliary data is assumed to be communicated by
- * Common.
+ * the SUNDenseMatrix_Columns function. Auxiliary data is assumed
+ * to be communicated by Common.
  * ----------------------------------------------------------------
  */
 
-int FKINDenseJac(long int N, N_Vector uu, N_Vector fval,
-		 DlsMat J, void *user_data, N_Vector vtemp1, N_Vector vtemp2)
+int FKINDenseJac(N_Vector uu, N_Vector fval, SUNMatrix J,
+                 void *user_data, N_Vector vtemp1, N_Vector vtemp2)
 {
   realtype *uu_data, *fval_data, *jacdata, *v1_data, *v2_data;
+  long int N;
   int ier;
 
   /* Initialize all pointers to NULL */
@@ -96,7 +94,8 @@ int FKINDenseJac(long int N, N_Vector uu, N_Vector fval,
   v1_data   = N_VGetArrayPointer(vtemp1);
   v2_data   = N_VGetArrayPointer(vtemp2);
 
-  jacdata = DENSE_COL(J,0);
+  N       = SUNDenseMatrix_Columns(J);
+  jacdata = SUNDenseMatrix_Column(J,0);
 
   /* Call user-supplied routine */
   FK_DJAC(&N, uu_data, fval_data, jacdata, v1_data, v2_data, &ier);
diff --git a/src/kinsol/fcmix/fkinjtimes.c b/src/kinsol/fcmix/fkinjtimes.c
index c85fe68..e92f810 100644
--- a/src/kinsol/fcmix/fkinjtimes.c
+++ b/src/kinsol/fcmix/fkinjtimes.c
@@ -1,10 +1,7 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
+ *                David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -18,8 +15,7 @@
  * -----------------------------------------------------------------
  * Routines used to interface between KINSOL and a Fortran
  * user-supplied routine FKJTIMES (Jacobian J times vector v).
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -29,27 +25,23 @@
 
 #include <kinsol/kinsol_spils.h>
 
-/*
- * ----------------------------------------------------------------
- * prototype of the user-supplied fortran routine
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  prototype of the user-supplied fortran routine
+  ------------------------------------------------------------------*/
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-extern void FK_JTIMES(realtype*, realtype*, int*, realtype*, int*);
+extern void FK_JTIMES(realtype* vdata, realtype* Jvdata, int* new_uu,
+                      realtype* uudata, int* ier);
 
 #ifdef __cplusplus
 }
 #endif
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SPILSSETJAC
- * ----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  Function : FKIN_SPILSSETJAC
+  ------------------------------------------------------------------*/
 void FKIN_SPILSSETJAC(int *flag, int *ier)
 {
   if ((*flag) == 0) KINSpilsSetJacTimesVecFn(KIN_kinmem, NULL);
@@ -58,16 +50,13 @@ void FKIN_SPILSSETJAC(int *flag, int *ier)
   return;
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKINJtimes
- * ----------------------------------------------------------------
- * C function FKINJtimes is used to interface between
- * KINSp* / KINSp*JTimes and FK_JTIMES (user-supplied Fortran
- * routine).
- * ----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  Function : FKINJtimes
+  ------------------------------------------------------------------
+  C function FKINJtimes is used to interface between
+  KINSp* / KINSp*JTimes and FK_JTIMES (user-supplied Fortran
+  routine).
+  ------------------------------------------------------------------*/
 int FKINJtimes(N_Vector v, N_Vector Jv,
                N_Vector uu, booleantype *new_uu, 
                void *user_data)
diff --git a/src/kinsol/fcmix/fkinklu.c b/src/kinsol/fcmix/fkinklu.c
deleted file mode 100644
index 867d871..0000000
--- a/src/kinsol/fcmix/fkinklu.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4654 $
- * $Date: 2016-02-17 20:12:58 -0800 (Wed, 17 Feb 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the Fortran interface to
- * the KINKLU solver. See fkinsol.h for usage.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "fkinsol.h"
-#include "kinsol_impl.h"
-#include <kinsol/kinsol_klu.h>
- 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_KLU
- * ----------------------------------------------------------------
- */
-
-void FKIN_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier)
-{
-  *ier = KINKLU(KIN_kinmem, *neq, *nnz, *sparsetype);
-  KINKLUSetOrdering(KIN_kinmem, *ordering);
-  KIN_ls = KIN_LS_KLU;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_KLUReinit
- * ----------------------------------------------------------------
- */
-
-void FKIN_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier)
-{
-  *ier = KINKLUReInit(KIN_kinmem, *neq, *nnz, *reinit_type);
-}
-
diff --git a/src/kinsol/fcmix/fkinlapack.c b/src/kinsol/fcmix/fkinlapack.c
deleted file mode 100644
index e117b69..0000000
--- a/src/kinsol/fcmix/fkinlapack.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for KINSOL/KINLAPACK
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fkinsol.h"
-#include "kinsol_impl.h"
-
-#include <kinsol/kinsol_lapack.h>
-
-/***************************************************************************/
-
-void FKIN_LAPACKDENSE(int *neq, int *ier)
-{
-  *ier = KINLapackDense(KIN_kinmem, *neq);
-  KIN_ls = KIN_LS_LAPACKDENSE;
-}
-
-/***************************************************************************/
-
-void FCV_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier)
-{
-  *ier = KINLapackBand(KIN_kinmem, *neq, *mupper, *mlower);
-  KIN_ls = KIN_LS_LAPACKBAND;
-}
-
-/***************************************************************************/
-
diff --git a/src/kinsol/fcmix/fkinlapband.c b/src/kinsol/fcmix/fkinlapband.c
deleted file mode 100644
index 97d5288..0000000
--- a/src/kinsol/fcmix/fkinlapband.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for KINSOL/KINBAND, for the case
- * of a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fkinsol.h"     /* standard interfaces and global vars.*/
-#include "kinsol_impl.h" /* definition of KINMem type           */
-
-#include <kinsol/kinsol_lapack.h>
-
-/*
- * ----------------------------------------------------------------
- * prototypes of the user-supplied fortran routines
- * ----------------------------------------------------------------
- */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-extern void FK_BJAC(long int*, long int*, long int*, long int*,
-                    realtype*, realtype*,
-                    realtype*,
-                    realtype*, realtype*, int*);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_LAPACKBANDSETJAC
- * ----------------------------------------------------------------
- */
-
-void FKIN_LAPACKBANDSETJAC(int *flag, int *ier)
-{
-  if (*flag == 0) {
-    *ier = KINDlsSetBandJacFn(KIN_kinmem, NULL);
-  }
-  else {
-    *ier = KINDlsSetBandJacFn(KIN_kinmem, FKINLapackBandJac);
-  }
-
-  return;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FKINLapackBandJac
- * ----------------------------------------------------------------
- * C function FKINLapackBandJac interfaces between KINSOL and a
- * Fortran subroutine FKBJAC for solution of a linear system with
- * band Jacobian approximation using Lapack functions.
- * Addresses are passed to FKBJAC for the banded Jacobian and 
- * vector data.
- * Auxiliary data is assumed to be communicated by common blocks.
- * ----------------------------------------------------------------
- */
-
-int FKINLapackBandJac(long int N, long int mupper, long int mlower,
-                      N_Vector uu, N_Vector fval, 
-                      DlsMat J, void *user_data,
-                      N_Vector vtemp1, N_Vector vtemp2)
-{
-  realtype *uu_data, *fval_data, *jacdata, *v1_data, *v2_data;
-  long int eband;
-  int ier;
-
-  /* Initialize all pointers to NULL */
-  uu_data = fval_data = jacdata = v1_data = v2_data = NULL;
-
-  /* NOTE: The user-supplied routine should set ier to an
-     appropriate value, but we preset the value to zero
-     (meaning SUCCESS) so the user need only reset the
-     value if an error occurred */
-  ier = 0;
-
-  /* Get pointers to vector data */
-  uu_data   = N_VGetArrayPointer(uu);
-  fval_data = N_VGetArrayPointer(fval);
-  v1_data   = N_VGetArrayPointer(vtemp1);
-  v2_data   = N_VGetArrayPointer(vtemp2);
-
-  eband = (J->s_mu) + mlower + 1;
-  jacdata = BAND_COL(J,0) - mupper;
-
-  /* Call user-supplied routine */
-  FK_BJAC(&N, &mupper, &mlower, &eband,
-          uu_data, fval_data, 
-          jacdata,
-          v1_data, v2_data, &ier);
-
-  return(ier);
-}
-
-
diff --git a/src/kinsol/fcmix/fkinlapdense.c b/src/kinsol/fcmix/fkinlapdense.c
deleted file mode 100644
index 03f04f4..0000000
--- a/src/kinsol/fcmix/fkinlapdense.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Fortran/C interface routines for KINSOL/KINLAPACKDENSE, for the
- * case of a user-supplied Jacobian approximation routine.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "fkinsol.h"     /* prototypes of standard interfaces and global vars.*/
-#include "kinsol_impl.h" /* definition of KINMem type                         */
-
-#include <kinsol/kinsol_lapack.h>
-
-/*
- * ----------------------------------------------------------------
- * prototypes of the user-supplied fortran routines
- * ----------------------------------------------------------------
- */
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-extern void FK_DJAC(long int*, realtype*, realtype*, realtype*,
-                    realtype*, realtype*, int*);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_LAPACKDENSESETJAC
- * ----------------------------------------------------------------
- */
-
-void FKIN_LAPACKDENSESETJAC(int *flag, int *ier)
-{
-  if (*flag == 0) {
-    *ier = KINDlsSetDenseJacFn(KIN_kinmem, NULL);
-  }
-  else {
-    *ier = KINDlsSetDenseJacFn(KIN_kinmem, FKINLapackDenseJac);
-  }
-  return;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FKINLapackDenseJac
- * ----------------------------------------------------------------
- * C function FKINLapackDenseJac interfaces between KINSOL and a
- * Fortran subroutine FKDJAC for solution of a linear system
- * with dense Jacobian approximation using lapack functinos.
- * Addresses are passed to FKDJAC, using the macro DENSE_COL 
- * and the routine N_VGetArrayPointer from NVECTOR. 
- * Auxiliary data is assumed to be communicated by common blocks.
- * ----------------------------------------------------------------
- */
-
-int FKINLapackDenseJac(long int N, N_Vector uu, N_Vector fval,
-                       DlsMat J, void *user_data, N_Vector vtemp1, N_Vector vtemp2)
-{
-  realtype *uu_data, *fval_data, *jacdata, *v1_data, *v2_data;
-  int ier;
-
-  /* Initialize all pointers to NULL */
-  uu_data = fval_data = jacdata = v1_data = v2_data = NULL;
-
-  /* NOTE: The user-supplied routine should set ier to an
-     appropriate value, but we preset the value to zero
-     (meaning SUCCESS) so the user need only reset the
-     value if an error occurred */
-  ier = 0;
-
-  /* Get pointers to vector data */
-  uu_data   = N_VGetArrayPointer(uu);
-  fval_data = N_VGetArrayPointer(fval);
-  v1_data   = N_VGetArrayPointer(vtemp1);
-  v2_data   = N_VGetArrayPointer(vtemp2);
-
-  jacdata = DENSE_COL(J,0);
-
-  /* Call user-supplied routine */
-  FK_DJAC(&N, uu_data, fval_data, jacdata, v1_data, v2_data, &ier);
-
-  return(ier);
-}
diff --git a/src/kinsol/fcmix/fkinpreco.c b/src/kinsol/fcmix/fkinpreco.c
index d1882f9..8a28a81 100644
--- a/src/kinsol/fcmix/fkinpreco.c
+++ b/src/kinsol/fcmix/fkinpreco.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh and
  *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -26,8 +22,7 @@
  * the Fortran user-supplied preconditioner solve routine.
  *
  * Note: The use of the generic names FK_PSET and FK_PSOL below.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,31 +32,29 @@
 
 #include <kinsol/kinsol_spils.h>
 
-/*
- * ----------------------------------------------------------------
- * prototype of the user-supplied fortran routine
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  prototype of the user-supplied fortran routine
+  ------------------------------------------------------------------*/
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-extern void FK_PSET(realtype*, realtype*, realtype*, realtype*, 
-		    realtype*, realtype*, int*);
-extern void FK_PSOL(realtype*, realtype*, realtype*, realtype*, 
-		    realtype*, realtype*, int*);
+extern void FK_PSET(realtype* uudata,     realtype* uscaledata,
+                    realtype* fvaldata,   realtype* fscaledata,
+                    int* ier);
+
+extern void FK_PSOL(realtype* uudata,   realtype* uscaledata,
+                    realtype* fvaldata, realtype* fscaledata,
+                    realtype* vvdata,   int* ier);
 
 #ifdef __cplusplus
 }
 #endif
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SPILSSETPREC
- * ----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  Function : FKIN_SPILSSETPREC
+  ------------------------------------------------------------------*/
 void FKIN_SPILSSETPREC(int *flag, int *ier)
 {
   if ((*flag) == 0) {
@@ -73,67 +66,71 @@ void FKIN_SPILSSETPREC(int *flag, int *ier)
   return;
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKINPSet
- * ----------------------------------------------------------------
- * C function FKINPSet is used to interface between FK_PSET and
- * the user-supplied Fortran preconditioner setup routine.
- * ----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  Function : FKINPSet
+  ------------------------------------------------------------------
+  C function FKINPSet is used to interface between FK_PSET and
+  the user-supplied Fortran preconditioner setup routine.
+  ------------------------------------------------------------------*/
 int FKINPSet(N_Vector uu, N_Vector uscale,
              N_Vector fval, N_Vector fscale,
-             void *user_data,
-             N_Vector vtemp1, N_Vector vtemp2)
+             void *user_data)
 {
-  realtype *udata, *uscaledata, *fdata, *fscaledata, *vtemp1data, *vtemp2data;
-  int retcode;
+  realtype *udata, *uscaledata, *fdata, *fscaledata;
+  int ier;
+
+  /* Initialize all pointers to NULL */
+  udata = uscaledata = fdata = fscaledata = NULL;
 
-  udata = uscaledata = fdata = fscaledata = vtemp1data = vtemp2data = NULL;
+  /* NOTE: The user-supplied routine should set ier to an
+     appropriate value, but we preset the value to zero
+     (meaning SUCCESS) so the user need only reset the
+     value if an error occurred */
+  ier = 0;
 
+  /* Get pointers to vector data */
   udata      = N_VGetArrayPointer(uu);
   uscaledata = N_VGetArrayPointer(uscale);
   fdata      = N_VGetArrayPointer(fval);
   fscaledata = N_VGetArrayPointer(fscale);
-  vtemp1data = N_VGetArrayPointer(vtemp1);
-  vtemp2data = N_VGetArrayPointer(vtemp2);
-
-  FK_PSET(udata, uscaledata, fdata, fscaledata, vtemp1data, vtemp2data, &retcode);
 
- /* Note: There is no need to use N_VSetArrayPointer since we are not getting back
-    any information that should go into an N_Vector */
+  /* Call user-supplied routine */
+  FK_PSET(udata, uscaledata, fdata, fscaledata, &ier);
 
- return(retcode);
+  return(ier);
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKINPSol
- * ----------------------------------------------------------------
- * C function FKINPSol is used to interface between FK_PSOL and
- * the user-supplied Fortran preconditioner solve routine.
- * ----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  Function : FKINPSol
+  ------------------------------------------------------------------
+  C function FKINPSol is used to interface between FK_PSOL and
+  the user-supplied Fortran preconditioner solve routine.
+  ------------------------------------------------------------------*/
 int FKINPSol(N_Vector uu, N_Vector uscale, 
              N_Vector fval, N_Vector fscale, 
-             N_Vector vv, void *user_data,
-             N_Vector ftem)
+             N_Vector vv, void *user_data)
 {
-  realtype *udata, *uscaledata, *fdata, *fscaledata, *vvdata, *ftemdata;
-  int retcode;
+  realtype *udata, *uscaledata, *fdata, *fscaledata, *vvdata;
+  int ier;
+
+  /* Initialize all pointers to NULL */
+  udata = uscaledata = fdata = fscaledata = vvdata = NULL;
 
-  udata = uscaledata = fdata = fscaledata = vvdata = ftemdata = NULL;
+  /* NOTE: The user-supplied routine should set ier to an
+     appropriate value, but we preset the value to zero
+     (meaning SUCCESS) so the user need only reset the
+     value if an error occurred */
+  ier = 0;
 
+  /* Get pointers to vector data */
   udata      = N_VGetArrayPointer(uu);
   uscaledata = N_VGetArrayPointer(uscale);
   fdata      = N_VGetArrayPointer(fval);
   fscaledata = N_VGetArrayPointer(fscale);
   vvdata     = N_VGetArrayPointer(vv);
-  ftemdata   = N_VGetArrayPointer(ftem);
 
-  FK_PSOL(udata, uscaledata, fdata, fscaledata, vvdata, ftemdata, &retcode);
+  /* Call user-supplied routine */
+  FK_PSOL(udata, uscaledata, fdata, fscaledata, vvdata, &ier);
 
-  return(retcode);
+  return(ier);
 }
diff --git a/src/kinsol/fcmix/fkinsol.c b/src/kinsol/fcmix/fkinsol.c
index f8d5e41..d4f2184 100644
--- a/src/kinsol/fcmix/fkinsol.c
+++ b/src/kinsol/fcmix/fkinsol.c
@@ -1,10 +1,7 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4906 $
- * $Date: 2016-09-14 16:05:17 -0700 (Wed, 14 Sep 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
+ *                David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -22,49 +19,36 @@
  * Note: Some routines are necessarily stored elsewhere to avoid
  * linking problems. See also, therefore, fkinpreco.c, fkinjtimes.c,
  * and fkinbbd.c.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "fkinsol.h"               /* prototypes of interfaces and global vars.   */
-#include "kinsol_impl.h"           /* definition of KINMem type                   */
+#include "fkinsol.h"     /* prototypes of interfaces and global vars. */
+#include "kinsol_impl.h" /* definition of KINMem type                 */
 
-#include <kinsol/kinsol_band.h>    /* prototypes of KINBAND interface routines    */
-#include <kinsol/kinsol_dense.h>   /* prototypes of KINDENSE interface routines   */
-#include <kinsol/kinsol_klu.h>     /* prototypes of KINKLU interface routines     */
-#include <kinsol/kinsol_superlumt.h> /* prototypes of KINSUPERLU interface routines */
-#include <kinsol/kinsol_sptfqmr.h> /* prototypes of KINSPTFQMR interface routines */
-#include <kinsol/kinsol_spbcgs.h>  /* prototypes of KINSPBCG interface routines   */
-#include <kinsol/kinsol_spgmr.h>   /* prototypes of KINSPGMR interface routines   */
-#include <kinsol/kinsol_spfgmr.h>  /* prototypes of KINSPFGMR interface routines  */
+#include <kinsol/kinsol_direct.h> /* prototypes for KINDLS interface routines   */
+#include <kinsol/kinsol_spils.h>  /* prototypes for KINSPILS interface routines */
 
-/*
- * ----------------------------------------------------------------
- * definitions of global variables shared amongst various routines
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  definitions of global variables shared amongst various routines
+  ------------------------------------------------------------------*/
 
 void *KIN_kinmem;
 long int *KIN_iout;
 realtype *KIN_rout;
 int KIN_ls;
 
-/*
- * ----------------------------------------------------------------
- * private constants
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  private constants
+  ------------------------------------------------------------------*/
 
 #define ZERO RCONST(0.0)
 
-/*
- * ----------------------------------------------------------------
- * prototype of user-supplied fortran routine
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  prototype of user-supplied fortran routine
+  ------------------------------------------------------------------*/
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
@@ -76,11 +60,9 @@ extern void FK_FUN(realtype*, realtype*, int*);
 }
 #endif
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_CREATE
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_CREATE
+  ------------------------------------------------------------------*/
 
 void FKIN_CREATE(int *ier)
 {
@@ -90,7 +72,7 @@ void FKIN_CREATE(int *ier)
   if ((F2C_KINSOL_vec->ops->nvgetarraypointer == NULL) ||
       (F2C_KINSOL_vec->ops->nvsetarraypointer == NULL)) {
     *ier = -1;
-    printf("FKINCREATE: A required vector operation is not implemented.\n\n");
+    fprintf(stderr, "FKINCREATE: A required vector operation is not implemented.\n\n");
     return;
   }
 
@@ -105,11 +87,9 @@ void FKIN_CREATE(int *ier)
   }
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_INIT
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_INIT
+  ------------------------------------------------------------------*/
 
 void FKIN_INIT(long int *iout, realtype *rout, int *ier)
 {
@@ -131,11 +111,9 @@ void FKIN_INIT(long int *iout, realtype *rout, int *ier)
   return;
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_MALLOC
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_MALLOC
+  ------------------------------------------------------------------*/
 
 void FKIN_MALLOC(long int *iout, realtype *rout, int *ier)
 {
@@ -144,7 +122,7 @@ void FKIN_MALLOC(long int *iout, realtype *rout, int *ier)
   if ((F2C_KINSOL_vec->ops->nvgetarraypointer == NULL) ||
       (F2C_KINSOL_vec->ops->nvsetarraypointer == NULL)) {
     *ier = -1;
-    printf("A required vector operation is not implemented.\n\n");
+    fprintf(stderr, "A required vector operation is not implemented.\n\n");
     return;
   }
 
@@ -175,44 +153,40 @@ void FKIN_MALLOC(long int *iout, realtype *rout, int *ier)
   return;
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SETIIN
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_SETIIN
+  ------------------------------------------------------------------*/
 
 void FKIN_SETIIN(char key_name[], long int *ival, int *ier)
 {
   if (!strncmp(key_name,"PRNT_LEVEL",10))
     *ier = KINSetPrintLevel(KIN_kinmem, (int) *ival);
   else if (!strncmp(key_name,"MAX_NITERS",10))
-    *ier = KINSetNumMaxIters(KIN_kinmem, (int) *ival);
+    *ier = KINSetNumMaxIters(KIN_kinmem, (long int) *ival);
   else if (!strncmp(key_name,"ETA_FORM",8))
     *ier = KINSetEtaForm(KIN_kinmem, (int) *ival);
   else if (!strncmp(key_name,"MAA",3))
-    *ier = KINSetMAA(KIN_kinmem, (int) *ival);
+    *ier = KINSetMAA(KIN_kinmem, (long int) *ival);
   else if (!strncmp(key_name,"MAX_SETUPS",10))
-    *ier = KINSetMaxSetupCalls(KIN_kinmem, (int) *ival);
+    *ier = KINSetMaxSetupCalls(KIN_kinmem, (long int) *ival);
   else if (!strncmp(key_name,"MAX_SP_SETUPS",13))
-    *ier = KINSetMaxSubSetupCalls(KIN_kinmem, (int) *ival);
+    *ier = KINSetMaxSubSetupCalls(KIN_kinmem, (long int) *ival);
   else if (!strncmp(key_name,"NO_INIT_SETUP",13))
-    *ier = KINSetNoInitSetup(KIN_kinmem, (int) *ival);
+    *ier = KINSetNoInitSetup(KIN_kinmem, (booleantype) *ival);
   else if (!strncmp(key_name,"NO_MIN_EPS",10))
-    *ier = KINSetNoMinEps(KIN_kinmem, (int) *ival);
+    *ier = KINSetNoMinEps(KIN_kinmem, (booleantype) *ival);
   else if (!strncmp(key_name,"NO_RES_MON",10))
-    *ier = KINSetNoResMon(KIN_kinmem, (int) *ival);
+    *ier = KINSetNoResMon(KIN_kinmem, (booleantype) *ival);
   else {
     *ier = -99;
-    printf("FKINSETIIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FKINSETIIN: Unrecognized key.\n\n");
   }
 
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SETRIN
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_SETRIN
+  ------------------------------------------------------------------*/
 
 void FKIN_SETRIN(char key_name[], realtype *rval, int *ier)
 {
@@ -235,16 +209,14 @@ void FKIN_SETRIN(char key_name[], realtype *rval, int *ier)
     *ier = KINSetResMonParams(KIN_kinmem, rval[0], rval[1]);
   else {
     *ier = -99;
-    printf("FKINSETRIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FKINSETRIN: Unrecognized key.\n\n");
   }
 
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SETVIN
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_SETVIN
+  ------------------------------------------------------------------*/
 
 void FKIN_SETVIN(char key_name[], realtype *vval, int *ier)
 {
@@ -263,90 +235,46 @@ void FKIN_SETVIN(char key_name[], realtype *vval, int *ier)
     N_VDestroy(Vec);
   } else {
     *ier = -99;
-    printf("FKINSETVIN: Unrecognized key.\n\n");
+    fprintf(stderr, "FKINSETVIN: Unrecognized key.\n\n");
   }
 
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_DENSE
- * ----------------------------------------------------------------
- */
-
-void FKIN_DENSE(long int *neq, int *ier)
-{
-  *ier = KINDense(KIN_kinmem, *neq);
-  KIN_ls = KIN_LS_DENSE;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_BAND
- * ----------------------------------------------------------------
- */
-
-void FKIN_BAND(long int *neq, long int *mupper, long int *mlower, int *ier)
-{
-  *ier = KINBand(KIN_kinmem, *neq, *mupper, *mlower);
-  KIN_ls = KIN_LS_BAND;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SPTFQMR
- * ----------------------------------------------------------------
- */
-
-void FKIN_SPTFQMR(int *maxl, int *ier)
-{
-  *ier = KINSptfqmr(KIN_kinmem, *maxl);
-  KIN_ls = KIN_LS_SPTFQMR;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SPBCG
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_DLSINIT
+  ------------------------------------------------------------------*/
 
-void FKIN_SPBCG(int *maxl, int *ier)
-{
-  *ier = KINSpbcg(KIN_kinmem, *maxl);
-  KIN_ls = KIN_LS_SPBCG;
-}
-
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SPGMR
- * ----------------------------------------------------------------
- */
-
-void FKIN_SPGMR(int *maxl, int *maxlrst, int *ier)
-{
-  *ier = KINSpgmr(KIN_kinmem, *maxl);
-  KINSpilsSetMaxRestarts(KIN_kinmem, *maxlrst);
-  KIN_ls = KIN_LS_SPGMR;
+/* Fortran interface to C routine KINDlsSetLinearSolver */
+void FKIN_DLSINIT(int *ier) {
+  if ( (KIN_kinmem == NULL) || (F2C_KINSOL_linsol == NULL) ||
+       (F2C_KINSOL_matrix == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = KINDlsSetLinearSolver(KIN_kinmem, F2C_KINSOL_linsol,
+                               F2C_KINSOL_matrix);
+  KIN_ls = KIN_LS_DIRECT;
+  return;
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SPFGMR
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_DLSINIT
+  ------------------------------------------------------------------*/
 
-void FKIN_SPFGMR(int *maxl, int *maxlrst, int *ier)
-{
-  *ier = KINSpfgmr(KIN_kinmem, *maxl);
-  KINSpilsSetMaxRestarts(KIN_kinmem, *maxlrst);
-  KIN_ls = KIN_LS_SPFGMR;
+/* Fortran interface to C routine KINSpilsSetLinearSolver */
+void FKIN_SPILSINIT(int *ier) {
+  if ( (KIN_kinmem == NULL) || (F2C_KINSOL_linsol == NULL) ) {
+    *ier = -1;
+    return;
+  }
+  *ier = KINSpilsSetLinearSolver(KIN_kinmem, F2C_KINSOL_linsol);
+  KIN_ls = KIN_LS_ITERATIVE;
+  return;
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SOL
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_SOL
+  ------------------------------------------------------------------*/
 
 void FKIN_SOL(realtype *uu, int *globalstrategy, 
               realtype *uscale , realtype *fscale, int *ier)
@@ -400,23 +328,13 @@ void FKIN_SOL(realtype *uu, int *globalstrategy,
 
   switch(KIN_ls) {
 
-  case KIN_LS_DENSE:
-  case KIN_LS_BAND:
-  case KIN_LS_LAPACKDENSE:
-  case KIN_LS_LAPACKBAND:
+  case KIN_LS_DIRECT:
     KINDlsGetWorkSpace(KIN_kinmem, &KIN_iout[6], &KIN_iout[7]); /* LRW & LIW */
     KINDlsGetLastFlag(KIN_kinmem, &KIN_iout[8]);                /* LSTF */
     KINDlsGetNumFuncEvals(KIN_kinmem, &KIN_iout[9]);            /* NFE */
     KINDlsGetNumJacEvals(KIN_kinmem, &KIN_iout[10]);            /* NJE */    
-  case KIN_LS_KLU:
-  case KIN_LS_SUPERLUMT:
-    KINSlsGetLastFlag(KIN_kinmem, &KIN_iout[8]);                /* LSTF  */
-    KINSlsGetNumJacEvals(KIN_kinmem, &KIN_iout[10]);            /* NJE   */
     break;
-  case KIN_LS_SPTFQMR:
-  case KIN_LS_SPBCG:
-  case KIN_LS_SPFGMR:
-  case KIN_LS_SPGMR:
+  case KIN_LS_ITERATIVE:
     KINSpilsGetWorkSpace(KIN_kinmem, &KIN_iout[6], &KIN_iout[7]); /* LRW & LIW */
     KINSpilsGetLastFlag(KIN_kinmem, &KIN_iout[8]);                /* LSTF */
     KINSpilsGetNumFuncEvals(KIN_kinmem, &KIN_iout[9]);            /* NFE */
@@ -432,38 +350,51 @@ void FKIN_SOL(realtype *uu, int *globalstrategy,
   return;
 }
 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_FREE
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKIN_FREE
+  ------------------------------------------------------------------*/
 
 void FKIN_FREE(void)
 {
+  KINMem kin_mem;
+
+  kin_mem = (KINMem) KIN_kinmem;
+
+  /* free DLS/SPILS interface */
+  if (kin_mem->kin_lfree)
+    kin_mem->kin_lfree(kin_mem);
+  kin_mem->kin_lmem = NULL;
 
-  /* call KINFree: KIN_kinmem is the pointer to the KINSOL memory block */
+  /* free user_data structure */
+  if (kin_mem->kin_user_data)
+    free(kin_mem->kin_user_data);
+  kin_mem->kin_user_data = NULL;
 
+  /* free main solver memory structure */
   KINFree(&KIN_kinmem);
 
-  N_VSetArrayPointer(NULL , F2C_KINSOL_vec);
+  /* free interface vectors / matrices / linear solvers */
+  N_VSetArrayPointer(NULL, F2C_KINSOL_vec);
   N_VDestroy(F2C_KINSOL_vec);
+  if (F2C_KINSOL_matrix)
+    SUNMatDestroy(F2C_KINSOL_matrix);
+  if (F2C_KINSOL_linsol)
+    SUNLinSolFree(F2C_KINSOL_linsol);
 
   return;
 }
 
 
-/*
- * ----------------------------------------------------------------
- * Function : FKINfunc
- * ----------------------------------------------------------------
- * The C function FKINfunc acts as an interface between KINSOL and
- * the Fortran user-supplied subroutine FKFUN. Addresses of the
- * data uu and fdata are passed to FKFUN, using the routine
- * N_VGetArrayPointer from the NVECTOR module. The data in the
- * returned N_Vector fval is set using N_VSetArrayPointer. Auxiliary
- * data is assumed to be communicated by 'Common'.
- * ----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Function : FKINfunc
+  ------------------------------------------------------------------
+  The C function FKINfunc acts as an interface between KINSOL and
+  the Fortran user-supplied subroutine FKFUN. Addresses of the
+  data uu and fdata are passed to FKFUN, using the routine
+  N_VGetArrayPointer from the NVECTOR module. The data in the
+  returned N_Vector fval is set using N_VSetArrayPointer. Auxiliary
+  data is assumed to be communicated by 'Common'.
+  ------------------------------------------------------------------*/
 
 int FKINfunc(N_Vector uu, N_Vector fval, void *user_data)
 {
diff --git a/src/kinsol/fcmix/fkinsol.h b/src/kinsol/fcmix/fkinsol.h
index f253221..4a6dce4 100644
--- a/src/kinsol/fcmix/fkinsol.h
+++ b/src/kinsol/fcmix/fkinsol.h
@@ -1,11 +1,8 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4905 $
- * $Date: 2016-09-14 16:04:36 -0700 (Wed, 14 Sep 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
  *                Daniel R. Reynolds @ SMU
+ *                David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -19,8 +16,7 @@
  * -----------------------------------------------------------------
  * This is the header file for the FKINSOL Interface Package.
  * See below for usage details.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 /***************************************************************************
 
@@ -44,27 +40,26 @@
    FKINCREATE interfaces to KINCreate
    FKININIT interfaces to KINInit
    FKINSETIIN, FKINSETRIN, FKINSETVIN interface to KINSet* functions
-   FKINDENSE interfaces to KINDense
-   FKINKLU interfaces to KINKLU
-   FKINSUPERLUMT interfaces to KINSUPERLUMT
-   FKINSPARSESETJAC interfaces to KINSlsSetSparseJacFn
-   FKINSPTFQMR interfaces to KINSptfqmr
-   FKINSPGMR interfaces to KINSpgmr
-   FKINSPFGMR interfaces to KINSpfgmr
-   FKINSPBCG interfaces to KINSpbcg
    FKINSOL interfaces to KINSol and KINGet* functions
    FKINFREE interfaces to KINFree
+   FKINDLSINIT interface to KINDlsSetLineaerSolver
+   FKINSPILSINIT interface to KINSpilsSetLineaerSolver
+   FKINDENSESETJAC interface to KINDlsSetJacFn
+   FKINBANDSETJAC interface to KINDlsSetJacFn
+   FKINSPARSESETJAC interface to KINDlsSetJacFn
+   FKINSPILSSETJAC interface to KINSpilsSetJacTimes
+   FKINSPILSSETPREC interface to KINSpilsSetPreconditioner
 
  The user-supplied functions, each with the corresponding interface function
  which calls it (and its type within KINSOL), are as follows:
 
    FKFUN    : called by the interface function FKINfunc of type KINSysFn
    FKDJAC   : called by the interface function FKINDenseJac of type
-              KINDenseJacFn
+              KINDlsJacFn
    FKBJAC   : called by the interface function FKINBandJac of type
-              KINBandJacFn
+              KINDlsJacFn
    FKINSPJAC: called by the interface function FKINSparseJac of type 
-              KINSlsSparseJacFn
+              KINDlsJacFn
    FKJTIMES : called by the interface function FKINJtimes of type
               KINSpilsJacTimesVecFn
    FKPSOL   : called by the interface function FKINPSol of type
@@ -76,6 +71,12 @@
  user-supplied routines here are fixed, in order to maximize portability for
  the resulting mixed-language program.
 
+ Important note on portability:
+ In this package, the names of the interface functions, and the names of
+ the Fortran user routines called by them, appear as dummy names
+ which are mapped to actual values by a series of definitions, in this
+ and other header files.
+
  =========================================================================
 
                   Usage of the FKINSOL Interface Package
@@ -107,7 +108,6 @@
      IER is a return flag, which should be 0 if FKFUN was successful.
      Return IER > 0 if a recoverable error occurred (and KINSOL is to try
      to recover).  Return IER < 0 if an unrecoverable error occurred.
-     
 
  (2s) Optional user-supplied dense Jacobian approximation routine: FKDJAC
   
@@ -277,8 +277,7 @@
 
        The arguments are:
          IOUT        = array of length at least 15 for integer optional outputs
-                       (declare as INTEGER*4 or INTEGER*8 according to
-                       C type long int)
+                       (declare as INTEGER*8)
          ROUT        = array of length at least 2 for real optional outputs
          IER         = return completion flag. Values are 0 = success, and
                        -1 = failure.
@@ -291,180 +290,242 @@
      related to the Jacobian J = dF/du of the nonlinear system.
 
  (6.1s) DENSE treatment of the linear systems (NVECTOR_SERIAL only):
+  
+        To initialize a dense matrix structure for stroing the system Jacobian
+        and for use within a direct linear solver, the user must call:
+  
+          CALL FSUNDENSEMATINIT(3, M, N, IER)
+  
+        The integer 3 is the KINSOL solver ID and the other arguments are:
+          M   = the number of rows of the matrix [long int, input]
+          N   = the number of columns of the matrix [long int, input]
+          IER = return completion flag [int, output]:
+                  0 = success, 
+                 -1 = failure.
+  
+        To initialize a dense linear solver structure the user must call
+        the following to use the SUNDIALS or LAPACK dense solvers:
+          
+          CALL FSUNDENSELINSOLINIT(3, IER)
+  
+          OR 
+  
+          CALL FSUNLAPACKDENSEINIT(3, IER)
+  
+        In the above routines, 3 is the KINSOL solver ID and IER is the return
+        return completion flag (0 = success and -1 = failure).
+  
+        To attach the dense linear solver structure the user must call
+        the following:
 
-       The user must make the following call:
-
-         CALL FKINDENSE(NEQ, IER)
-
-       In the above routine, the arguments are as follows:
-         NEQ = problem size.
-         IER = return completion flag.
-
-       If the user program includes the FKDJAC routine for the evaluation
-       of the dense approximation to the system Jacobian, the following call
-       must be made:
+          CALL FKINDLSINIT(IER)
 
-         CALL FKINDENSESETJAC(FLAG, IER)
+        The arguments are:
+            IER  = return completion flag [int, output]:
+                    0 = SUCCESS,
+                   -1 = failure (see printed message for failure details).
 
-       with FLAG = 1 to specify that FKDJAC is provided.  (FLAG = 0 specifies
-       using the internal finite difference approximation to the Jacobian.)
+        If the user program includes the FKDJAC routine for the evaluation
+        of the dense approximation to the system Jacobian, the following call
+        must be made:
+  
+          CALL FKINDENSESETJAC(FLAG, IER)
+  
+        with FLAG = 1 to specify that FKDJAC is provided.  (FLAG = 0 specifies
+        using the internal finite difference approximation to the Jacobian.)
 
  (6.2s) BAND treatment of the linear systems (NVECTOR_SERIAL only):
+  
+        To initialize a banded matrix structure for stroing the system Jacobian
+        and for use within a banded linear solver, the user must call:
+  
+          CALL FSUNBANDMATINIT(3, N, MU, ML, SMU, IER)
+  
+        The integer 3 is the KINSOL solver ID and the other arguments are:
+          N   = the number of columns of the matrix [long int, input]
+          MU  = the number of upper bands (diagonal not included) in a banded 
+                matrix [long int, input]
+          ML  = the number of lower bands (diagonal not included) in a banded 
+                matrix [long int, input]
+          SMU = the number of upper bands to store (diagonal not included) 
+                for factorization of a banded matrix [long int, input]
+  
+        To initialize a banded linear solver structure the user must call
+        the following to use the SUNDIALS or LAPACK banded solvers:
+  
+          CALL FSUNBANDLINSOLINIT(3, IER)
+  
+          OR 
+  
+          CALL FSUNLAPACKBANDINIT(3, IER)
+  
+        In the above routines, 3 is the KINSOL solver ID and IER is the return
+        return completion flag (0 = success and -1 = failure).
+  
+        To attach the banded linear solver structure the user must call
+        the following:
 
-       The user must make the following call:
-
-         CALL FKINBAND(NEQ, MU, ML, IER)
-
-       In the above routine, the arguments are as follows:
-         NEQ = problem size.
-         MU  = upper half-bandwidth
-         ML  = lower half-bandwidth
-         IER = return completion flag.
-
-       If the user program includes the FKBJAC routine for the evaluation
-       of the band approximation to the system Jacobian, the following call
-       must be made:
-
-         CALL FKINBANDSETJAC(FLAG, IER)
-
-       with FLAG = 1 to specify that FKBJAC is provided.  (FLAG = 0 specifies
-       using the internal finite difference approximation to the Jacobian.)
-
-
- (6.3s) SPARSE treatment of the linear system using the KLU solver.
-
-     The user must make the call
-
-       CALL FKINKLU(NEQ, NNZ, SPARSETYPE, ORDERING, IER)
-
-     The arguments are:
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	SPARSETYPE = choice between CSC and CSR format
-           (0 = CSC, 1 = CSR) [int; input]
-	ORDERING = the matrix ordering desired, possible values
-	   come from the KLU package (0 = AMD, 1 = COLAMD) [int; input]
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
- 
-     When using the KLU solver the user must provide the FKINSPJAC routine for the 
-     evalution of the sparse approximation to the Jacobian. To indicate that this
-     routine has been provided, after the call to FKINKLU, the following call must 
-     be made    
-
-       CALL FKINSPARSESETJAC(IER) 
-
-     The int return flag IER=0 if successful, and nonzero otherwise.
-
-
-     The KINSOL KLU solver will reuse much of the factorization information from one
-     nonlinear iteration to the next.  If at any time the user wants to force a full
-     refactorization or if the number of nonzeros in the Jacobian matrix changes, the
-     user should make the call
-
-       CALL FKINKLUREINIT(NEQ, NNZ, REINIT_TYPE)
+          CALL FKINDLSINIT(IER)
 
-     The arguments are:
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be destroyed and 
-          a new one will be allocated with NNZ nonzeros.  For a value of 2, 
-	  only symbolic and numeric factorizations will be completed. 
- 
-     When using FKINKLU, the user is required to supply the FKINSPJAC 
-     routine for the evaluation of the sparse approximation to the 
-     Jacobian, as discussed above with the other user-supplied routines.
- 
-     Optional outputs specific to the KLU case are:
-        LSTF    = IOUT(8)  from KINSlsGetLastFlag
-        NJES    = IOUT(10) from KINSlsGetNumJacEvals
-     See the KINSOL manual for descriptions.
- 
- (6.4s) SPARSE treatment of the linear system using the SuperLUMT solver.
-
-     The user must make the call
+        The arguments are:
+            IER  = return completion flag [int, output]:
+                    0 = SUCCESS,
+                   -1 = failure (see printed message for failure details).
 
-       CALL FKINSUPERLUMT(NTHREADS, NEQ, NNZ, ORDERING, IER)
+        If the user program includes the FKBJAC routine for the evaluation
+        of the band approximation to the system Jacobian, the following call
+        must be made:
+  
+          CALL FKINBANDSETJAC(FLAG, IER)
+  
+        with FLAG = 1 to specify that FKBJAC is provided.  (FLAG = 0 specifies
+        using the internal finite difference approximation to the Jacobian.)
 
-     The arguments are:
-        NTHREADS = desired number of threads to use [int; input]
-        NEQ = the problem size [int; input]
-        NNZ = the maximum number of nonzeros [int; input]
-	ORDERING = the matrix ordering desired, possible values
-	   come from the SuperLU_MT package [int; input]
-           0 = Natural
-           1 = Minimum degree on A^T A
-           2 = Minimum degree on A^T + A
-           3 = COLAMD
-	IER = error return flag [int, output]: 
-	         0 = success, 
-		 negative = error.
- 
-     At this time, there is no reinitialization capability for the SUNDIALS 
-     interfaces to the SuperLUMT solver.
+ (6.3s) SPARSE treatment of the linear system using the KLU or SuperLU_MT solver.
+  
+        To initialize a sparse matrix structure for stroing the system Jacobian
+        and for use within a sparse linear solver, the user must call:
+  
+          CALL FSUNSPARSEMATINIT(3, M, N, NNZ, SPARSETYPE, IER)
+  
+        The integer 3 is the KINSOL solver ID and the other arguments are:
+          M   = the number of rows of the matrix [long int, input]
+          N   = the number of columns of the matrix [long int, input]
+          NNZ = the storage size (upper bound on the number of nonzeros) for 
+                a sparse matrix [long int, input]
+          SPARSETYPE = integer denoting use of CSC (0) vs CSR (1) storage 
+                       for a sparse matrix [int, input]
+          IER = return completion flag [int, output]:
+                   0 = success, 
+                  -1 = failure.
+  
+        To initialize a sparse linear solver structure the user must call
+        the following to use the KLU or SuperLU_MT sparse solvers:
+  
+          CALL FSUNKLUINIT(3, IER)
+  
+          OR
+  
+          CALL FSUNSUPERLUMTINIT(3, NUM_THREADS, IER)
+  
+        In the above routines, 3 is the KINSOL solver ID, NUM_THREADS is the number
+        of threads, and IER is the return completion flag (0 = success and
+        -1 = failure).
 
-     When using FKINSUPERLUMT, the user is required to supply the FKINSPJAC 
-     routine for the evaluation of the CSC approximation to the 
-     Jacobian (note: the current SuperLU_MT interface in SUNDIALS does not 
-     support CSR matrices). To indicate that this routine has been provided, 
-     after the call to FKINSUPERLUMT, the following call must be made    
+        To attach the sparse linear solver structure the user must call
+        the following:
 
-         CALL FKINSPARSESETJAC(IER) 
+          CALL FKINDLSINIT(IER)
 
-     The int return flag IER=0 if successful, and nonzero otherwise.
- 
-     Optional outputs specific to the SUPERLUMT case are:
-        LSTF    = IOUT(8)  from KINSlsGetLastFlag
-        NJES    = IOUT(10) from KINSlsGetNumJacEvals
-     See the KINSOL manual for descriptions.
+        The arguments are:
+            IER  = return completion flag [int, output]:
+                    0 = SUCCESS,
+                   -1 = failure (see printed message for failure details).
+  
+        When using a sparse solver the user must provide the FKINSPJAC routine for the 
+        evalution of the sparse approximation to the Jacobian. To indicate that this
+        routine has been provided, after the call to FKINKLU, the following call must 
+        be made    
+  
+          CALL FKINSPARSESETJAC(IER) 
+  
+        The int return flag IER=0 if successful, and nonzero otherwise.
+  
+        The KLU solver will reuse much of the factorization information from one
+        nonlinear iteration to the next.  If at any time the user wants to force a full
+        refactorization or if the number of nonzeros in the Jacobian matrix changes, the
+        user should make the call:
+  
+          CALL FKINKLUREINIT(NEQ, NNZ, REINIT_TYPE)
+  
+        The arguments are:
+          NEQ = the problem size [int; input]
+          NNZ = the maximum number of nonzeros [int; input]
+          REINIT_TYPE = 1 or 2.  For a value of 1, the matrix will be destroyed and 
+            a new one will be allocated with NNZ nonzeros.  For a value of 2, 
+            only symbolic and numeric factorizations will be completed. 
+
+        At this time, there is no reinitialization capability for the SUNDIALS
+        interface to the SuperLUMT solver.
+
+        Once these the solvers have been initialized, their solver parameters may be
+        modified via calls to the functions:
+
+           CALL FSUNKLUSETORDERING(3, ORD_CHOICE, IER)
+           CALL FSUNSUPERLUMTSETORDERING(3, ORD_CHOICE, IER)
+
+        In the above routines, 3 is the KINSOL solver ID and ORD_CHOICE is an integer
+        denoting ordering choice (see SUNKLUSetOrdering and SUNSuperLUMTSetOrdering
+        documentation for details), and IER is the return completion flag (0 = success
+        and -1 = failure).
+
+        Optional outputs specific to the KLU case are:
+          LSTF    = IOUT(8)  from KINSlsGetLastFlag
+          NJES    = IOUT(10) from KINSlsGetNumJacEvals
+        See the KINSOL manual for descriptions.
+    
+        Optional outputs specific to the SUPERLUMT case are:
+          LSTF    = IOUT(8)  from KINSlsGetLastFlag
+          NJES    = IOUT(10) from KINSlsGetNumJacEvals
+        See the KINSOL manual for descriptions.
   
- (6.5) SPTFQMR treatment of the linear systems:
+ (6.4) Scaled Preconditioned Iterative linear Solvers (SPILS):
 
-       For the Scaled Preconditioned TFQMR solution of the linear systems,
-       the user must make the call:
+       To initialize a SPILS treatment of the linear system, the user must call one
+       of the following:
 
-         CALL FKINSPTFQMR(MAXL, IER)
+         CALL FSUNPCGINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPBCGSINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPFGMRINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPGMRINIT(3, PRETYPE, MAXL, IER)
+         CALL FSUNSPTFQMRINIT(3, PRETYPE, MAXL, IER)
 
-       In the above routine, the arguments are as follows:
-         MAXL     = maximum Krylov subspace dimension; 0 indicates default.
-         IER      = return completion flag.  Values are 0 = succes, and
-                    -1 = failure.
+       The integer 3 is the KINSOL solver ID and the other arguments are:
+         PRETYPE = type of preconditioning to perform (0=none, 1=left,
+                   2=right, 3=both) [int, input]
+         MAXL    = maximum Krylov subspace dimension [int, input]
+         IER     = return completion flag [int, output]:
+                    0 = success, 
+                   -1 = failure.
 
-       Note: See printed message for details in case of failure.
+        To attach the iterative linear solver structure the user must call
+        the following:
 
- (6.6) SPBCG treatment of the linear systems:
+          CALL FKINSPILSINIT(IER)
 
-       For the Scaled Preconditioned Bi-CGSTAB solution of the linear systems,
-       the user must make the call:
+        The arguments are:
+            IER  = return completion flag [int, output]:
+                    0 = SUCCESS,
+                   -1 = failure (see printed message for failure details).
 
-         CALL FKINSPBCG(MAXL, IER)
+       Once these the solvers have been initialized, their solver parameters may be
+       modified via calls to the functions:
 
-       In the above routine, the arguments are as follows:
-         MAXL     = maximum Krylov subspace dimension; 0 indicates default.
-         IER      = return completion flag.  Values are 0 = succes, and
-                    -1 = failure.
+         CALL FSUNPCGSETPRECTYPE(3, PRETYPE, IER)
+         CALL FSUNPCGSETMAXL(3, MAXL, IER)
 
-       Note: See printed message for details in case of failure.
+         CALL FSUNSPBCGSSETPRECTYPE(3, PRETYPE, IER)
+         CALL FSUNSPBCGSSETMAXL(3, MAXL, IER)
 
- (6.7) SPGMR and SPFGMR treatment of the linear systems:
+         CALL FSUNSPFGMRSETGSTYPE(3, GSTYPE, IER)
+         CALL FSUNSPFGMRSETPRECTYPE(3, PRETYPE, IER)
 
-       For the Scaled Preconditioned GMRES or Scaled Preconditioned Flexible 
-       GMRES solution of the linear systems, the user must make one of the calls:
+         CALL FSUNSPGMRSETGSTYPE(3, GSTYPE, IER)
+         CALL FSUNSPGMRSETPRECTYPE(3, PRETYPE, IER)
 
-         CALL FKINSPGMR(MAXL, MAXLRST, IER)
-         CALL FKINSPFGMR(MAXL, MAXLRST, IER)
+         CALL FSUNSPTFQMRSETPRECTYPE(3, PRETYPE, IER)
+         CALL FSUNSPTFQMRSETMAXL(3, MAXL, IER)
 
-       In the above routine, the arguments are as follows:
-         MAXL     = maximum Krylov subspace dimension; 0 indicates default.
-         MAXLRST  = maximum number of linear system restarts; 0 indicates
-                    default (SPGMR and SPFGMR only).
-         IER      = return completion flag.  Values are 0 = succes, and
-                    -1 = failure.
+       The integer 3 is the KINSOL solver ID and the other arguments are:
+         PRETYPE = type of preconditioning to perform (0=none, 1=left, 
+                   2=right, 3=both) [int, input]
+         GSTYPE  = choice of Gram-Schmidt orthogonalization algorithm 
+                   (0=modified, 1=classical) [int, input]
+         IER     = return completion flag [int, output]:
+                    0 = success, 
+                   -1 = failure.       
 
-       Note: See printed message for details in case of failure.
-
- (6.8) Specifying user-provided functions for the iterative linear solvers
+ (6.5) Specifying user-provided functions for the iterative linear solvers (SPILS)
 
        If the user program includes the FKJTIMES routine for the evaluation
        of the Jacobian-vector product, the following call must be made:
@@ -484,25 +545,24 @@
        specifies using FKPSET and FKPSOL. The user-supplied routines FKPSET
        and FKPSOL must be of the form:
 
-         SUBROUTINE FKPSET (UU, USCALE, FVAL, FSCALE, VTEMP1, VTEMP2, IER)
-         DIMENSION UU(*), USCALE(*), FVAL(*), FSCALE(*), VTEMP1(*), VTEMP2(*)
+         SUBROUTINE FKPSET (UU, USCALE, FVAL, FSCALE, IER)
+         DIMENSION UU(*), USCALE(*), FVAL(*), FSCALE(*)
 
        It must perform any evaluation of Jacobian-related data and
        preprocessing needed for the solution of the preconditioned linear
        systems by FKPSOL. The variables UU through FSCALE are for use in the
        preconditioning setup process. Typically, the system function FKFUN is
        called, so that FVAL will have been updated. UU is the current solution
-       iterate. VTEMP1 and VTEMP2 are available for work space. If scaling is
-       being used, USCALE and FSCALE are available for those operatins
-       requiring scaling. NEQ is the (global) problem size.
+       iterate. If scaling is being used, USCALE and FSCALE are available for
+       those operatins requiring scaling.
 
        On return, set IER = 0 if FKPSET was successful, set IER = 1 if
        an error occurred.
 
-         SUBROUTINE FKPSOL (UU, USCALE, FVAL, FSCALE, VTEM, FTEM, IER)
-         DIMENSION UU(*), USCALE(*), FVAL(*), FSCALE(*), VTEM(*), FTEM(*)
+         SUBROUTINE FKPSOL (UU, USCALE, FVAL, FSCALE, VTEM, IER)
+         DIMENSION UU(*), USCALE(*), FVAL(*), FSCALE(*), VTEM(*)
 
-       Typically this routine will use only UU, FVAL, VTEM and FTEM.
+       Typically this routine will use only UU, FVAL, and VTEM.
        It must solve the preconditioned linear system Pz = r, where
        r = VTEM is input, and store the solution z in VTEM as well. Here
        P is the right preconditioner. If scaling is being used, the
@@ -581,26 +641,23 @@
 #ifndef _FKINSOL_H
 #define _FKINSOL_H
 
-/*
- * -----------------------------------------------------------------
- * header files
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  header files
+  ------------------------------------------------------------------*/
+
 #include <kinsol/kinsol.h>
-#include <sundials/sundials_direct.h>  /* definition of type DlsMat   */
-#include <sundials/sundials_sparse.h>  /* definition of type SlsMat   */
-#include <sundials/sundials_nvector.h> /* definition of type N_Vector */
-#include <sundials/sundials_types.h>   /* definition of type realtype */
+#include <sundials/sundials_linearsolver.h> /* definition of SUNLinearSolver */
+#include <sundials/sundials_matrix.h>       /* definition of SUNMatrix       */
+#include <sundials/sundials_nvector.h>      /* definition of type N_Vector   */
+#include <sundials/sundials_types.h>        /* definition of type realtype   */
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * generic names are translated through the define statements below
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  generic names are translated through the define statements below
+  ------------------------------------------------------------------*/
 
 #if defined(SUNDIALS_F77_FUNC)
 
@@ -610,32 +667,22 @@ extern "C" {
 #define FKIN_SETIIN         SUNDIALS_F77_FUNC(fkinsetiin, FKINSETIIN)
 #define FKIN_SETRIN         SUNDIALS_F77_FUNC(fkinsetrin, FKINSETRIN)
 #define FKIN_SETVIN         SUNDIALS_F77_FUNC(fkinsetvin, FKINSETVIN)
-#define FKIN_DENSE          SUNDIALS_F77_FUNC(fkindense, FKINDENSE)
+#define FKIN_SOL            SUNDIALS_F77_FUNC(fkinsol, FKINSOL)
+#define FKIN_FREE           SUNDIALS_F77_FUNC(fkinfree, FKINFREE)
+#define FKIN_DLSINIT        SUNDIALS_F77_FUNC(fkindlsinit, FKINDLSINIT)
+#define FKIN_SPILSINIT      SUNDIALS_F77_FUNC(fkinspilsinit, FKINSPILSINIT)
 #define FKIN_DENSESETJAC    SUNDIALS_F77_FUNC(fkindensesetjac, FKINDENSESETJAC)
-#define FKIN_BAND           SUNDIALS_F77_FUNC(fkinband, FKINBAND)
+#define FK_DJAC             SUNDIALS_F77_FUNC(fkdjac, FKDJAC)
 #define FKIN_BANDSETJAC     SUNDIALS_F77_FUNC(fkinbandsetjac, FKINBANDSETJAC)
-#define FKIN_LAPACKDENSE       SUNDIALS_F77_FUNC(fkinlapackdense, FKINLAPACKDENSE)
-#define FKIN_LAPACKDENSESETJAC SUNDIALS_F77_FUNC(fkinlapackdensesetjac, FKINLAPACKDENSESETJAC)
-#define FKIN_LAPACKBAND        SUNDIALS_F77_FUNC(fkinlapackband, FKINLAPACKBAND)
-#define FKIN_LAPACKBANDSETJAC  SUNDIALS_F77_FUNC(fkinlapackbandsetjac, FKINLAPACKBANDSETJAC)
-#define FKIN_KLU            SUNDIALS_F77_FUNC(fkinklu, FKLUKLU)
-#define FKIN_KLUREINIT      SUNDIALS_F77_FUNC(fkinklureinit, FKLUKLUREINIT)
-#define FKIN_SUPERLUMT      SUNDIALS_F77_FUNC(fkinsuperlumt, FKLUSUPERLUMT)
+#define FK_BJAC             SUNDIALS_F77_FUNC(fkbjac, FKBJAC)
 #define FKIN_SPARSESETJAC   SUNDIALS_F77_FUNC(fkinsparsesetjac, FKINSPARSESETJAC)  
-#define FKIN_SPTFQMR        SUNDIALS_F77_FUNC(fkinsptfqmr, FKINSPTFQMR)
-#define FKIN_SPBCG          SUNDIALS_F77_FUNC(fkinspbcg, FKINSPBCG)
-#define FKIN_SPGMR          SUNDIALS_F77_FUNC(fkinspgmr, FKINSPGMR)
-#define FKIN_SPFGMR         SUNDIALS_F77_FUNC(fkinspfgmr, FKINSPFGMR)
+#define FKIN_SPJAC          SUNDIALS_F77_FUNC(fkinspjac, FKINSPJAC)
 #define FKIN_SPILSSETJAC    SUNDIALS_F77_FUNC(fkinspilssetjac, FKINSPILSSETJAC)
+#define FK_JTIMES           SUNDIALS_F77_FUNC(fkjtimes, FKJTIMES)
 #define FKIN_SPILSSETPREC   SUNDIALS_F77_FUNC(fkinspilssetprec, FKINSPILSSETPREC)
-#define FKIN_SOL            SUNDIALS_F77_FUNC(fkinsol, FKINSOL)
-#define FKIN_FREE           SUNDIALS_F77_FUNC(fkinfree, FKINFREE)
-#define FK_FUN              SUNDIALS_F77_FUNC(fkfun, FKFUN)
 #define FK_PSET             SUNDIALS_F77_FUNC(fkpset, FKPSET)
 #define FK_PSOL             SUNDIALS_F77_FUNC(fkpsol, FKPSOL)
-#define FK_JTIMES           SUNDIALS_F77_FUNC(fkjtimes, FKJTIMES)
-#define FK_DJAC             SUNDIALS_F77_FUNC(fkdjac, FKDJAC)
-#define FK_BJAC             SUNDIALS_F77_FUNC(fkbjac, FKBJAC)
+#define FK_FUN              SUNDIALS_F77_FUNC(fkfun, FKFUN)
 
 #else
 
@@ -645,40 +692,28 @@ extern "C" {
 #define FKIN_SETIIN         fkinsetiin_
 #define FKIN_SETRIN         fkinsetrin_
 #define FKIN_SETVIN         fkinsetvin_
-#define FKIN_DENSE          fkindense_
+#define FKIN_SOL            fkinsol_
+#define FKIN_FREE           fkinfree_
+#define FKIN_DLSINIT        fkindlsinit_
+#define FKIN_SPILSINIT      fkinspilsinit_
 #define FKIN_DENSESETJAC    fkindensesetjac_
-#define FKIN_BAND           fkinband_
+#define FK_DJAC             fkdjac_
 #define FKIN_BANDSETJAC     fkinbandsetjac_
-#define FKIN_LAPACKDENSE       fkinlapackdense_
-#define FKIN_LAPACKDENSESETJAC fkinlapackdensesetjac_
-#define FKIN_LAPACKBAND        fkinlapackband_
-#define FKIN_LAPACKBANDSETJAC  fkinlapackbandsetjac_
-#define FKIN_KLU            fkinklu_
-#define FKIN_KLUREINIT      fkinklureinit_
-#define FKIN_SUPERLUMT      fkinsuperlumt_
+#define FK_BJAC             fkbjac_
 #define FKIN_SPARSESETJAC   fkinsparsesetjac_
-#define FKIN_SPTFQMR        fkinsptfqmr_
-#define FKIN_SPBCG          fkinspbcg_
-#define FKIN_SPGMR          fkinspgmr_
-#define FKIN_SPFGMR         fkinspgmr_
+#define FKIN_SPJAC          fkinspjac_
 #define FKIN_SPILSSETJAC    fkinspilssetjac_
+#define FK_JTIMES           fkjtimes_
 #define FKIN_SPILSSETPREC   fkinspilssetprec_
-#define FKIN_SOL            fkinsol_
-#define FKIN_FREE           fkinfree_
-#define FK_FUN              fkfun_
 #define FK_PSET             fkpset_
 #define FK_PSOL             fkpsol_
-#define FK_JTIMES           fkjtimes_
-#define FK_DJAC             fkdjac_
-#define FK_BJAC             fkbjac_
+#define FK_FUN              fkfun_
 
 #endif
 
-/*
- * -----------------------------------------------------------------
- * Prototypes : exported functions
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Prototypes : exported functions
+  ------------------------------------------------------------------*/
 
 void FKIN_MALLOC(long int *iout, realtype *rout, int *ier);
 void FKIN_CREATE(int *ier);
@@ -688,27 +723,12 @@ void FKIN_SETIIN(char key_name[], long int *ival, int *ier);
 void FKIN_SETRIN(char key_name[], realtype *rval, int *ier);
 void FKIN_SETVIN(char key_name[], realtype *vval, int *ier);
 
-void FKIN_DENSE(long int *neq, int *ier);
+void FKIN_DLSINIT(int *ier);
 void FKIN_DENSESETJAC(int *flag, int *ier);
-
-void FKIN_BAND(long int *neq, long int *mupper, long int *mlower, int *ier);
 void FKIN_BANDSETJAC(int *flag, int *ier);
-
-void FKIN_LAPACKDENSE(int *neq, int *ier);
-void FKIN_LAPACKDENSESETJAC(int *flag, int *ier);
-void FKIN_LAPACKBAND(int *neq, int *mupper, int *mlower, int *ier);
-void FKIN_LAPACKBANDSETJAC(int *flag, int *ier);
-
-void FKIN_KLU(int *neq, int *nnz, int *sparsetype, int *ordering, int *ier);
-void FKIN_KLUREINIT(int *neq, int *nnz, int *reinit_type, int *ier);
-void FKIN_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier);
 void FKIN_SPARSESETJAC(int *ier);
 
-void FKIN_SPTFQMR(int *maxl, int *ier);
-void FKIN_SPBCG(int *maxl, int *ier);
-void FKIN_SPGMR(int *maxl, int *maxlrst, int *ier);
-void FKIN_SPFGMR(int *maxl, int *maxlrst, int *ier);
-
+void FKIN_SPILSINIT(int *ier);
 void FKIN_SPILSSETJAC(int *flag, int *ier);
 void FKIN_SPILSSETPREC(int *flag, int *ier);
 
@@ -717,70 +737,48 @@ void FKIN_SOL(realtype *uu, int *globalstrategy,
 
 void FKIN_FREE(void);
 
-/*
- * -----------------------------------------------------------------
- * Prototypes : functions called by the solver
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Prototypes : functions called by the solver
+  ------------------------------------------------------------------*/
 
 int FKINfunc(N_Vector uu, N_Vector fval, void *user_data);
 
-int FKINDenseJac(long int N,
-                 N_Vector uu, N_Vector fval,
-                 DlsMat J, void *user_data, 
-                 N_Vector vtemp1, N_Vector vtemp2);
+int FKINDenseJac(N_Vector uu, N_Vector fval, SUNMatrix J,
+                 void *user_data, N_Vector vtemp1, N_Vector vtemp2);
 
-int FKINBandJac(long int N, long int mupper, long int mlower,
-                N_Vector uu, N_Vector fval, 
-                DlsMat J, void *user_data,
-                N_Vector vtemp1, N_Vector vtemp2);
+int FKINBandJac(N_Vector uu, N_Vector fval, SUNMatrix J,
+                void *user_data, N_Vector vtemp1, N_Vector vtemp2);
 
-int FKINLapackDenseJac(long int N,
-                       N_Vector uu, N_Vector fval,
-                       DlsMat J, void *user_data, 
-                       N_Vector vtemp1, N_Vector vtemp2);
-
-int FKINLapackBandJac(long int N, long int mupper, long int mlower,
-                      N_Vector uu, N_Vector fval, 
-                      DlsMat J, void *user_data,
-                      N_Vector vtemp1, N_Vector vtemp2);
-
-int FKINSparseJac(N_Vector y, N_Vector fval, SlsMat J,
+int FKINSparseJac(N_Vector uu, N_Vector fval, SUNMatrix J,
 		  void *user_data, N_Vector vtemp1, N_Vector vtemp2);
 
+int FKINJtimes(N_Vector v, N_Vector Jv, N_Vector uu,
+               booleantype *new_uu, void *user_data);
+
 int FKINPSet(N_Vector uu, N_Vector uscale,
              N_Vector fval, N_Vector fscale,
-             void *user_data,
-             N_Vector vtemp1, N_Vector vtemp2);
+             void *user_data);
 
 int FKINPSol(N_Vector uu, N_Vector uscale, 
              N_Vector fval, N_Vector fscale, 
-             N_Vector vv, void *user_data,
-             N_Vector vtemp);
+             N_Vector vv, void *user_data);
 
-int FKINJtimes(N_Vector v, N_Vector Jv,
-               N_Vector uu, booleantype *new_uu, 
-               void *user_data);
+/*------------------------------------------------------------------
+  declarations for global variables shared amongst various routines
+  ------------------------------------------------------------------*/
 
-/*
- * -----------------------------------------------------------------
- * declarations for global variables shared amongst various
- * routines
- * -----------------------------------------------------------------
- */
-
-extern N_Vector F2C_KINSOL_vec;
-extern void *KIN_kinmem;
-extern long int *KIN_iout;
-extern realtype *KIN_rout;
-extern int KIN_ls;
+extern N_Vector F2C_KINSOL_vec;           /* defined in FNVECTOR module   */
+extern SUNMatrix F2C_KINSOL_matrix;       /* defined in FSUNMATRIX module */
+extern SUNLinearSolver F2C_KINSOL_linsol; /* defined in FSUNLINSOL module */
+extern void *KIN_kinmem;                  /* defined in fkinsol.c         */
+extern long int *KIN_iout;                /* defined in fkinsol.c         */
+extern realtype *KIN_rout;                /* defined in fkinsol.c         */
+extern int KIN_ls;                        /* defined in fkinsol.c         */
 
 /* Linear solver IDs */
-
-  enum { KIN_LS_SPGMR = 1, KIN_LS_SPFGMR = 2, KIN_LS_SPBCG = 3, KIN_LS_SPTFQMR = 4, 
-	 KIN_LS_DENSE = 5, KIN_LS_BAND  = 6,
-	 KIN_LS_LAPACKDENSE = 7, KIN_LS_LAPACKBAND = 8,
-         KIN_LS_KLU = 9, KIN_LS_SUPERLUMT = 10 };
+enum { KIN_LS_ITERATIVE = 0,
+       KIN_LS_DIRECT = 1,
+       KIN_LS_CUSTOM = 2 };
 
 #ifdef __cplusplus
 }
diff --git a/src/kinsol/fcmix/fkinsparse.c b/src/kinsol/fcmix/fkinsparse.c
index c123b07..ddf8a89 100644
--- a/src/kinsol/fcmix/fkinsparse.c
+++ b/src/kinsol/fcmix/fkinsparse.c
@@ -1,10 +1,7 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4815 $
- * $Date: 2016-07-20 16:51:55 -0700 (Wed, 20 Jul 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Carol Woodward @ LLNL
  *                Daniel R. Reynolds @ SMU
+ *                David J. Gardner @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2015, Lawrence Livermore National Security
@@ -15,14 +12,18 @@
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS Copyright End
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
+
 #include "fkinsol.h"
 #include "kinsol_impl.h"
-#include <kinsol/kinsol_sparse.h>
+
+#include <kinsol/kinsol_direct.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+
+/*=============================================================*/
 
 /* Prototype of the Fortran routine */
  
@@ -30,8 +31,9 @@
 extern "C" {
 #endif
  
-extern void FKIN_SPJAC(realtype *Y, realtype *FY, int *N, int *NNZ, 
-                       realtype *JDATA, int *JRVALS, int *JCPTRS, 
+extern void FKIN_SPJAC(realtype *Y, realtype *FY, long int *N,
+                       long int *NNZ, realtype *JDATA,
+                       long int *JRVALS, long int *JCPTRS,
                        realtype *V1, realtype *V2, int *ier);
  
 #ifdef __cplusplus
@@ -44,28 +46,42 @@ extern void FKIN_SPJAC(realtype *Y, realtype *FY, int *N, int *NNZ,
    fkinsol.h for further information */
 void FKIN_SPARSESETJAC(int *ier)
 {
-  *ier = KINSlsSetSparseJacFn(KIN_kinmem, FKINSparseJac);
+#if defined(SUNDIALS_INT32_T)
+  KINProcessError((KINMem) KIN_kinmem, KIN_ILL_INPUT, "KIN",
+                  "FKINSPARSESETJAC",
+                  "Sparse Fortran users must configure SUNDIALS with 64-bit integers.");
+  *ier = 1;
+#else
+  *ier = KINDlsSetJacFn(KIN_kinmem, FKINSparseJac);
+#endif
 }
 
 /*=============================================================*/
  
 /* C interface to user-supplied Fortran routine FKINSPJAC; see 
    fkinsol.h for additional information  */
-int FKINSparseJac(N_Vector y, N_Vector fy, 
-                  SlsMat J, void *user_data, N_Vector vtemp1, 
+int FKINSparseJac(N_Vector y, N_Vector fy, SUNMatrix J,
+                  void *user_data, N_Vector vtemp1,
                   N_Vector vtemp2)
 {
   int ier;
-  realtype *ydata, *fydata, *v1data, *v2data;
+  realtype *ydata, *fydata, *v1data, *v2data, *Jdata;
+  long int NP, NNZ, *indexvals, *indexptrs;
  
   ydata   = N_VGetArrayPointer(y);
   fydata  = N_VGetArrayPointer(fy);
   v1data  = N_VGetArrayPointer(vtemp1);
   v2data  = N_VGetArrayPointer(vtemp2);
+
+  NP = SUNSparseMatrix_NP(J);
+  NNZ = SUNSparseMatrix_NNZ(J);
+  Jdata = SUNSparseMatrix_Data(J);
+  indexvals = SUNSparseMatrix_IndexValues(J);
+  indexptrs = SUNSparseMatrix_IndexPointers(J);
  
-  FKIN_SPJAC(ydata, fydata, &(J->NP), &(J->NNZ),
-             J->data, J->indexvals, J->indexptrs,  
-             v1data, v2data, &ier); 
+  FKIN_SPJAC(ydata, fydata, &NP, &NNZ,
+             Jdata, indexvals, indexptrs,
+             v1data, v2data, &ier);
   return(ier);
 }
 
diff --git a/src/kinsol/fcmix/fkinsuperlumt.c b/src/kinsol/fcmix/fkinsuperlumt.c
deleted file mode 100644
index 61874dc..0000000
--- a/src/kinsol/fcmix/fkinsuperlumt.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4402 $
- * $Date: 2015-02-28 19:35:39 -0800 (Sat, 28 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2015, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the Fortran interface to
- * the KINSuperLUMT solver. See fkinsol.h for usage.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "fkinsol.h"
-#include "kinsol_impl.h"
-#include <kinsol/kinsol_superlumt.h>
- 
-/*
- * ----------------------------------------------------------------
- * Function : FKIN_SUPERLUMT
- * ----------------------------------------------------------------
- */
-
-void FKIN_SUPERLUMT(int *nthreads, int *neq, int *nnz, int *ordering, int *ier)
-{
-  *ier = KINSuperLUMT(KIN_kinmem, *nthreads, *neq, *nnz);
-  KINSuperLUMTSetOrdering(KIN_kinmem, *ordering);
-  KIN_ls = KIN_LS_SUPERLUMT;
-}
-
-
diff --git a/src/kinsol/kinsol.c b/src/kinsol/kinsol.c
index 72903fc..65d7b22 100644
--- a/src/kinsol/kinsol.c
+++ b/src/kinsol/kinsol.c
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4888 $
- * $Date: 2016-09-02 13:34:35 -0700 (Fri, 02 Sep 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, Carol Woodward,
  *                John Loffeld, and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -79,15 +76,6 @@
 
 /* 
  * =================================================================
- * MACRO DEFINITIONS
- * =================================================================
- */
-
-/* Macro: loop */
-#define loop for(;;)
-
-/* 
- * =================================================================
  * KINSOL PRIVATE CONSTANTS
  * =================================================================
  */
@@ -255,7 +243,7 @@ void *KINCreate(void)
   kin_mem->kin_m_aa             = ZERO;
   kin_mem->kin_aamem_aa         = 0;
   kin_mem->kin_setstop_aa       = 0;
-  kin_mem->kin_constraintsSet   = FALSE;
+  kin_mem->kin_constraintsSet   = SUNFALSE;
   kin_mem->kin_ehfun            = KINErrHandler;
   kin_mem->kin_eh_data          = kin_mem;
   kin_mem->kin_errfp            = stderr;
@@ -264,14 +252,14 @@ void *KINCreate(void)
   kin_mem->kin_infofp           = stdout;
   kin_mem->kin_printfl          = PRINTFL_DEFAULT;
   kin_mem->kin_mxiter           = MXITER_DEFAULT;
-  kin_mem->kin_noInitSetup      = FALSE;
+  kin_mem->kin_noInitSetup      = SUNFALSE;
   kin_mem->kin_msbset           = MSBSET_DEFAULT;
-  kin_mem->kin_noResMon         = FALSE;
+  kin_mem->kin_noResMon         = SUNFALSE;
   kin_mem->kin_msbset_sub       = MSBSET_SUB_DEFAULT;
-  kin_mem->kin_update_fnorm_sub = FALSE;
+  kin_mem->kin_update_fnorm_sub = SUNFALSE;
   kin_mem->kin_mxnbcf           = MXNBCF_DEFAULT;
   kin_mem->kin_sthrsh           = TWO;
-  kin_mem->kin_noMinEps         = FALSE;
+  kin_mem->kin_noMinEps         = SUNFALSE;
   kin_mem->kin_mxnstepin        = ZERO;
   kin_mem->kin_sqrt_relfunc     = SUNRsqrt(uround);
   kin_mem->kin_scsteptol        = SUNRpowerR(uround,TWOTHIRDS);
@@ -280,9 +268,8 @@ void *KINCreate(void)
   kin_mem->kin_eta              = POINT1;     /* default for KIN_ETACONSTANT */
   kin_mem->kin_eta_alpha        = TWO;        /* default for KIN_ETACHOICE2  */
   kin_mem->kin_eta_gamma        = POINT9;     /* default for KIN_ETACHOICE2  */
-  kin_mem->kin_MallocDone       = FALSE;
-  kin_mem->kin_setupNonNull     = FALSE;
-  kin_mem->kin_eval_omega       = TRUE;
+  kin_mem->kin_MallocDone       = SUNFALSE;
+  kin_mem->kin_eval_omega       = SUNTRUE;
   kin_mem->kin_omega            = ZERO;       /* default to using min/max    */
   kin_mem->kin_omega_min        = OMEGA_MIN;
   kin_mem->kin_omega_max        = OMEGA_MAX;
@@ -300,10 +287,6 @@ void *KINCreate(void)
   return((void *) kin_mem);
 }
 
-#define errfp (kin_mem->kin_errfp)
-#define liw   (kin_mem->kin_liw)
-#define lrw   (kin_mem->kin_lrw)
-
 /*
  * Function : KINInit
  *
@@ -315,7 +298,7 @@ void *KINCreate(void)
 
 int KINInit(void *kinmem, KINSysFn func, N_Vector tmpl)
 {
-  long int liw1, lrw1;
+  sunindextype liw1, lrw1;
   KINMem kin_mem;
   booleantype allocOK, nvectorOK;
   
@@ -375,94 +358,11 @@ int KINInit(void *kinmem, KINSysFn func, N_Vector tmpl)
   
   /* problem memory has been successfully allocated */
 
-  kin_mem->kin_MallocDone = TRUE;
+  kin_mem->kin_MallocDone = SUNTRUE;
 
   return(KIN_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Readability constants
- * -----------------------------------------------------------------
- */
-
-#define func             (kin_mem->kin_func)
-#define user_data        (kin_mem->kin_user_data)
-#define printfl          (kin_mem->kin_printfl)
-#define mxiter           (kin_mem->kin_mxiter)
-#define noInitSetup      (kin_mem->kin_noInitSetup)
-#define retry_nni        (kin_mem->kin_retry_nni)
-#define msbset           (kin_mem->kin_msbset)
-#define etaflag          (kin_mem->kin_etaflag)
-#define eta              (kin_mem->kin_eta)
-#define ealpha           (kin_mem->kin_eta_alpha)
-#define egamma           (kin_mem->kin_eta_gamma)
-#define noMinEps         (kin_mem->kin_noMinEps)
-#define mxnewtstep       (kin_mem->kin_mxnewtstep)
-#define mxnstepin        (kin_mem->kin_mxnstepin)
-#define mxnbcf           (kin_mem->kin_mxnbcf)
-#define relfunc          (kin_mem->kin_sqrt_relfunc)
-#define fnormtol         (kin_mem->kin_fnormtol)
-#define scsteptol        (kin_mem->kin_scsteptol)
-#define constraints      (kin_mem->kin_constraints)
-
-#define uround           (kin_mem->kin_uround)
-#define nni              (kin_mem->kin_nni)
-#define nfe              (kin_mem->kin_nfe)
-#define nbcf             (kin_mem->kin_nbcf)  
-#define nbktrk           (kin_mem->kin_nbktrk)
-#define ncscmx           (kin_mem->kin_ncscmx)
-#define stepl            (kin_mem->kin_stepl)
-#define stepmul          (kin_mem->kin_stepmul)
-#define sthrsh           (kin_mem->kin_sthrsh)
-#define linit            (kin_mem->kin_linit)
-#define lsetup           (kin_mem->kin_lsetup)
-#define lsolve           (kin_mem->kin_lsolve) 
-#define lfree            (kin_mem->kin_lfree)
-#define constraintsSet   (kin_mem->kin_constraintsSet) 
-#define jacCurrent       (kin_mem->kin_jacCurrent)          
-#define nnilset          (kin_mem->kin_nnilset)
-#define lmem             (kin_mem->kin_lmem)        
-#define inexact_ls       (kin_mem->kin_inexact_ls)
-#define setupNonNull     (kin_mem->kin_setupNonNull)
-#define fval             (kin_mem->kin_fval)      
-#define fnorm            (kin_mem->kin_fnorm)
-#define f1norm           (kin_mem->kin_f1norm)
-#define etaflag          (kin_mem->kin_etaflag)
-#define callForcingTerm  (kin_mem->kin_callForcingTerm)
-#define uu               (kin_mem->kin_uu)
-#define uscale           (kin_mem->kin_uscale)
-#define fscale           (kin_mem->kin_fscale)
-#define sJpnorm          (kin_mem->kin_sJpnorm)
-#define sFdotJp          (kin_mem->kin_sFdotJp)
-#define unew             (kin_mem->kin_unew)
-#define pp               (kin_mem->kin_pp)
-#define vtemp1           (kin_mem->kin_vtemp1)
-#define vtemp2           (kin_mem->kin_vtemp2)
-#define eps              (kin_mem->kin_eps)
-#define liw1             (kin_mem->kin_liw1)
-#define lrw1             (kin_mem->kin_lrw1)
-
-#define noResMon         (kin_mem->kin_noResMon)
-#define fnorm_sub        (kin_mem->kin_fnorm_sub)
-#define msbset_sub       (kin_mem->kin_msbset_sub)
-#define nnilset_sub      (kin_mem->kin_nnilset_sub)
-#define update_fnorm_sub (kin_mem->kin_update_fnorm_sub)
-#define eval_omega       (kin_mem->kin_eval_omega)
-#define omega            (kin_mem->kin_omega)
-#define omega_min        (kin_mem->kin_omega_min)
-#define omega_max        (kin_mem->kin_omega_max)
-
-#define fold             (kin_mem->kin_fold_aa)
-#define gold             (kin_mem->kin_gold_aa)
-#define df               (kin_mem->kin_df_aa)
-#define dg               (kin_mem->kin_dg_aa)
-#define Q                (kin_mem->kin_q_aa)
-#define maa              (kin_mem->kin_m_aa)
-#define aamem            (kin_mem->kin_aamem_aa)
-#define setstop          (kin_mem->kin_setstop_aa)
-#define strategy         (kin_mem->kin_globalstrategy)
-
 /* 
  * -----------------------------------------------------------------
  * Main solver function
@@ -501,7 +401,7 @@ int KINSol(void *kinmem, N_Vector u, int strategy_in,
 
   /* intialize to avoid compiler warning messages */
 
-  maxStepTaken = FALSE;
+  maxStepTaken = SUNFALSE;
   f1normp = fnormp = -ONE;
 
   /* initialize epsmin to avoid compiler warning message */
@@ -516,37 +416,37 @@ int KINSol(void *kinmem, N_Vector u, int strategy_in,
   }
   kin_mem = (KINMem) kinmem;
 
-  if(kin_mem->kin_MallocDone == FALSE) {
+  if(kin_mem->kin_MallocDone == SUNFALSE) {
     KINProcessError(NULL, KIN_NO_MALLOC, "KINSOL", "KINSol", MSG_NO_MALLOC);    
     return(KIN_NO_MALLOC);
   }
 
   /* load input arguments */
 
-  uu = u;
-  uscale = u_scale;
-  fscale = f_scale;
-  strategy = strategy_in;
+  kin_mem->kin_uu = u;
+  kin_mem->kin_uscale = u_scale;
+  kin_mem->kin_fscale = f_scale;
+  kin_mem->kin_globalstrategy = strategy_in;
 
   /* CSW:  
      Call fixed point solver if requested.  Note that this should probably
      be forked off to a FPSOL solver instead of kinsol in the future. */
-  if ( strategy == KIN_FP ) {
-    if (uu == NULL) {
+  if ( kin_mem->kin_globalstrategy == KIN_FP ) {
+    if (kin_mem->kin_uu == NULL) {
       KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSol", MSG_UU_NULL);
       return(KIN_ILL_INPUT);
     }
 
-    if (kin_mem->kin_constraintsSet != FALSE) {
+    if (kin_mem->kin_constraintsSet != SUNFALSE) {
       KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSol", MSG_CONSTRAINTS_NOTOK);
       return(KIN_ILL_INPUT);
     }
 
-    if (printfl > 0)
-      KINPrintInfo(kin_mem, PRNT_TOL, "KINSOL", "KINSol", INFO_TOL, scsteptol, fnormtol);
+    if (kin_mem->kin_printfl > 0)
+      KINPrintInfo(kin_mem, PRNT_TOL, "KINSOL", "KINSol", INFO_TOL, kin_mem->kin_scsteptol, kin_mem->kin_fnormtol);
 
-    nfe = nnilset = nnilset_sub = nni = nbcf = nbktrk = 0;
-    ret = KINFP(kin_mem, &nni, kin_mem->kin_R_aa, kin_mem->kin_gamma_aa, &fmax);
+    kin_mem->kin_nfe = kin_mem->kin_nnilset = kin_mem->kin_nnilset_sub = kin_mem->kin_nni = kin_mem->kin_nbcf = kin_mem->kin_nbktrk = 0;
+    ret = KINFP(kin_mem, &(kin_mem->kin_nni), kin_mem->kin_R_aa, kin_mem->kin_gamma_aa, &fmax);
 
     switch(ret) {
     case KIN_SYSFUNC_FAIL:
@@ -564,53 +464,53 @@ int KINSol(void *kinmem, N_Vector u, int strategy_in,
   ret = KINSolInit(kin_mem);
   if (ret != KIN_SUCCESS) return(ret);
 
-  ncscmx = 0;
+  kin_mem->kin_ncscmx = 0;
 
   /* Note: The following logic allows the choice of whether or not
      to force a call to the linear solver setup upon a given call to
      KINSol */
 
-  if (noInitSetup) sthrsh = ONE;
-  else             sthrsh = TWO;
+  if (kin_mem->kin_noInitSetup) kin_mem->kin_sthrsh = ONE;
+  else                          kin_mem->kin_sthrsh = TWO;
 
   /* if eps is to be bounded from below, set the bound */
 
-  if (inexact_ls && !noMinEps) epsmin = POINT01 * fnormtol;
+  if (kin_mem->kin_inexact_ls && !(kin_mem->kin_noMinEps)) epsmin = POINT01 * kin_mem->kin_fnormtol;
 
 
   /* if omega is zero at this point, make sure it will be evaluated
      at each iteration based on the provided min/max bounds and the
      current function norm. */
-  if (omega == ZERO) eval_omega = TRUE;
-  else               eval_omega = FALSE;
+  if (kin_mem->kin_omega == ZERO) kin_mem->kin_eval_omega = SUNTRUE;
+  else               kin_mem->kin_eval_omega = SUNFALSE;
  
 
   /* CSW:  
      Call fixed point solver for Picard method if requested.  
      Note that this should probably be forked off to a part of an 
      FPSOL solver instead of kinsol in the future. */
-  if ( strategy == KIN_PICARD ) {
+  if ( kin_mem->kin_globalstrategy == KIN_PICARD ) {
 
-    kin_mem->kin_gval = N_VClone(unew);
-    lrw += lrw1;
-    ret = KINPicardAA(kin_mem, &nni, kin_mem->kin_R_aa, kin_mem->kin_gamma_aa, &fmax);
+    kin_mem->kin_gval = N_VClone(kin_mem->kin_unew);
+    kin_mem->kin_lrw += kin_mem->kin_lrw1;
+    ret = KINPicardAA(kin_mem, &(kin_mem->kin_nni), kin_mem->kin_R_aa, kin_mem->kin_gamma_aa, &fmax);
 
     return(ret);
   }
 
 
-  loop{
+  for(;;){
 
-    retry_nni = FALSE;
+    kin_mem->kin_retry_nni = SUNFALSE;
 
-    nni++;
+    kin_mem->kin_nni++;
 
     /* calculate the epsilon (stopping criteria for iterative linear solver)
        for this iteration based on eta from the routine KINForcingTerm */
 
-    if (inexact_ls) {
-      eps = (eta + uround) * fnorm;
-      if(!noMinEps) eps = SUNMAX(epsmin, eps);
+    if (kin_mem->kin_inexact_ls) {
+      kin_mem->kin_eps = (kin_mem->kin_eta + kin_mem->kin_uround) * kin_mem->kin_fnorm;
+      if(!(kin_mem->kin_noMinEps)) kin_mem->kin_eps = SUNMAX(epsmin, kin_mem->kin_eps);
     }
 
     repeat_nni:
@@ -619,7 +519,7 @@ int KINSol(void *kinmem, N_Vector u, int strategy_in,
 
     sflag = 0;
 
-    if (strategy == KIN_NONE) {
+    if (kin_mem->kin_globalstrategy == KIN_NONE) {
 
       /* Full Newton Step*/
 
@@ -635,7 +535,7 @@ int KINSol(void *kinmem, N_Vector u, int strategy_in,
         break;
       }
 
-    } else if (strategy == KIN_LINESEARCH) {
+    } else if (kin_mem->kin_globalstrategy == KIN_LINESEARCH) {
 
       /* Line Search */
 
@@ -652,48 +552,48 @@ int KINSol(void *kinmem, N_Vector u, int strategy_in,
       }
 
       /* if too many beta condition failures, then stop iteration */
-      if (nbcf > mxnbcf) {
+      if (kin_mem->kin_nbcf > kin_mem->kin_mxnbcf) {
         ret = KIN_LINESEARCH_BCFAIL;
         break;
       }
 
     }
 
-    if ( (strategy != KIN_PICARD) && (strategy != KIN_FP) ) {
+    if ( (kin_mem->kin_globalstrategy != KIN_PICARD) && (kin_mem->kin_globalstrategy != KIN_FP) ) {
       
       /* evaluate eta by calling the forcing term routine */
-      if (callForcingTerm) KINForcingTerm(kin_mem, fnormp);
+      if (kin_mem->kin_callForcingTerm) KINForcingTerm(kin_mem, fnormp);
 
-      fnorm = fnormp;
+      kin_mem->kin_fnorm = fnormp;
 
       /* call KINStop to check if tolerances where met by this iteration */
       ret = KINStop(kin_mem, maxStepTaken, sflag); 
 
       if (ret == RETRY_ITERATION) {
-	retry_nni = TRUE;
+	kin_mem->kin_retry_nni = SUNTRUE;
 	goto repeat_nni;
       }
     }
 
     /* update uu after the iteration */
-    N_VScale(ONE, unew, uu);
+    N_VScale(ONE, kin_mem->kin_unew, kin_mem->kin_uu);
 
-    f1norm = f1normp;
+    kin_mem->kin_f1norm = f1normp;
 
     /* print the current nni, fnorm, and nfe values if printfl > 0 */
 
-    if (printfl>0)
-      KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINSol", INFO_NNI, nni, nfe, fnorm);
+    if (kin_mem->kin_printfl > 0)
+      KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINSol", INFO_NNI, kin_mem->kin_nni, kin_mem->kin_nfe, kin_mem->kin_fnorm);
 
     if (ret != CONTINUE_ITERATIONS) break; 
 
-    fflush(errfp);
+    fflush(kin_mem->kin_errfp);
     
   }  /* end of loop; return */
 
 
 
-  if (printfl > 0)
+  if (kin_mem->kin_printfl > 0)
     KINPrintInfo(kin_mem, PRNT_RETVAL, "KINSOL", "KINSol", INFO_RETVAL, ret);
 
   switch(ret) {
@@ -755,7 +655,7 @@ void KINFree(void **kinmem)
 
   /* call lfree if non-NULL */
 
-  if (lfree != NULL) lfree(kin_mem);
+  if (kin_mem->kin_lfree != NULL) kin_mem->kin_lfree(kin_mem);
 
   free(*kinmem);
   *kinmem = NULL;
@@ -773,7 +673,7 @@ void KINFree(void **kinmem)
  * This routine checks if all required vector operations are
  * implemented (excluding those required by KINConstraint). If all
  * necessary operations are present, then KINCheckNvector returns
- * TRUE. Otherwise, FALSE is returned.
+ * SUNTRUE. Otherwise, SUNFALSE is returned.
  */
 
 static booleantype KINCheckNvector(N_Vector tmpl)
@@ -788,8 +688,8 @@ static booleantype KINCheckNvector(N_Vector tmpl)
       (tmpl->ops->nvinv       == NULL) ||
       (tmpl->ops->nvmaxnorm   == NULL) ||
       (tmpl->ops->nvmin       == NULL) ||
-      (tmpl->ops->nvwl2norm   == NULL)) return(FALSE);
-  else return(TRUE);
+      (tmpl->ops->nvwl2norm   == NULL)) return(SUNFALSE);
+  else return(SUNTRUE);
 }
 
 /* 
@@ -802,9 +702,9 @@ static booleantype KINCheckNvector(N_Vector tmpl)
  * Function : KINAllocVectors
  *
  * This routine allocates the KINSol vectors. If all memory
- * allocations are successful, KINAllocVectors returns TRUE.
+ * allocations are successful, KINAllocVectors returns SUNTRUE.
  * Otherwise all allocated memory is freed and KINAllocVectors
- * returns FALSE.
+ * returns SUNFALSE.
  */
 
 static booleantype KINAllocVectors(KINMem kin_mem, N_Vector tmpl)
@@ -812,160 +712,160 @@ static booleantype KINAllocVectors(KINMem kin_mem, N_Vector tmpl)
   /* allocate unew, fval, pp, vtemp1 and vtemp2. */  
   /* allocate df, dg, q, for Anderson Acceleration, Broyden and EN */
  
-  unew = N_VClone(tmpl);
-  if (unew == NULL) return(FALSE);
+  kin_mem->kin_unew = N_VClone(tmpl);
+  if (kin_mem->kin_unew == NULL) return(SUNFALSE);
 
-  fval = N_VClone(tmpl);
-  if (fval == NULL) {
-    N_VDestroy(unew);
-    return(FALSE);
+  kin_mem->kin_fval = N_VClone(tmpl);
+  if (kin_mem->kin_fval == NULL) {
+    N_VDestroy(kin_mem->kin_unew);
+    return(SUNFALSE);
   }
 
-  pp = N_VClone(tmpl);
-  if (pp == NULL) {
-    N_VDestroy(unew);
-    N_VDestroy(fval);
-    return(FALSE);
+  kin_mem->kin_pp = N_VClone(tmpl);
+  if (kin_mem->kin_pp == NULL) {
+    N_VDestroy(kin_mem->kin_unew);
+    N_VDestroy(kin_mem->kin_fval);
+    return(SUNFALSE);
   }
 
-  vtemp1 = N_VClone(tmpl);
-  if (vtemp1 == NULL) {
-    N_VDestroy(unew);
-    N_VDestroy(fval);
-    N_VDestroy(pp);
-    return(FALSE);
+  kin_mem->kin_vtemp1 = N_VClone(tmpl);
+  if (kin_mem->kin_vtemp1 == NULL) {
+    N_VDestroy(kin_mem->kin_unew);
+    N_VDestroy(kin_mem->kin_fval);
+    N_VDestroy(kin_mem->kin_pp);
+    return(SUNFALSE);
   }
 
-  vtemp2 = N_VClone(tmpl);
-  if (vtemp2 == NULL) {
-    N_VDestroy(unew);
-    N_VDestroy(fval);
-    N_VDestroy(pp);
-    N_VDestroy(vtemp1);
-    return(FALSE);
+  kin_mem->kin_vtemp2 = N_VClone(tmpl);
+  if (kin_mem->kin_vtemp2 == NULL) {
+    N_VDestroy(kin_mem->kin_unew);
+    N_VDestroy(kin_mem->kin_fval);
+    N_VDestroy(kin_mem->kin_pp);
+    N_VDestroy(kin_mem->kin_vtemp1);
+    return(SUNFALSE);
   }
 
   /* update solver workspace lengths */
 
-  liw += 5*liw1;
-  lrw += 5*lrw1;
+  kin_mem->kin_liw += 5*kin_mem->kin_liw1;
+  kin_mem->kin_lrw += 5*kin_mem->kin_lrw1;
 
-  if (maa) {
-    kin_mem->kin_R_aa = (realtype *) malloc((maa*maa) * sizeof(realtype));
+  if (kin_mem->kin_m_aa) {
+    kin_mem->kin_R_aa = (realtype *) malloc((kin_mem->kin_m_aa*kin_mem->kin_m_aa) * sizeof(realtype));
     if (kin_mem->kin_R_aa == NULL) {
       KINProcessError(kin_mem, 0, "KINSOL", "KINAllocVectors", MSG_MEM_FAIL);
-      N_VDestroy(unew);
-      N_VDestroy(fval);
-      N_VDestroy(pp);
-      N_VDestroy(vtemp1);
-      N_VDestroy(vtemp2);
+      N_VDestroy(kin_mem->kin_unew);
+      N_VDestroy(kin_mem->kin_fval);
+      N_VDestroy(kin_mem->kin_pp);
+      N_VDestroy(kin_mem->kin_vtemp1);
+      N_VDestroy(kin_mem->kin_vtemp2);
       return(KIN_MEM_FAIL);
     }
-    kin_mem->kin_gamma_aa = (realtype *)malloc(maa * sizeof(realtype));
+    kin_mem->kin_gamma_aa = (realtype *)malloc(kin_mem->kin_m_aa * sizeof(realtype));
     if (kin_mem->kin_gamma_aa == NULL) {
       KINProcessError(kin_mem, 0, "KINSOL", "KINAllocVectors", MSG_MEM_FAIL);
-      N_VDestroy(unew);
-      N_VDestroy(fval);
-      N_VDestroy(pp);
-      N_VDestroy(vtemp1);
-      N_VDestroy(vtemp2);
+      N_VDestroy(kin_mem->kin_unew);
+      N_VDestroy(kin_mem->kin_fval);
+      N_VDestroy(kin_mem->kin_pp);
+      N_VDestroy(kin_mem->kin_vtemp1);
+      N_VDestroy(kin_mem->kin_vtemp2);
       free(kin_mem->kin_R_aa);
       return(KIN_MEM_FAIL);
     }
-    kin_mem->kin_ipt_map = (int *)malloc(maa * sizeof(int));
+    kin_mem->kin_ipt_map = (int *)malloc(kin_mem->kin_m_aa * sizeof(int));
     if (kin_mem->kin_ipt_map == NULL) {
       KINProcessError(kin_mem, 0, "KINSOL", "KINAllocVectors", MSG_MEM_FAIL);
-      N_VDestroy(unew);
-      N_VDestroy(fval);
-      N_VDestroy(pp);
-      N_VDestroy(vtemp1);
-      N_VDestroy(vtemp2);
+      N_VDestroy(kin_mem->kin_unew);
+      N_VDestroy(kin_mem->kin_fval);
+      N_VDestroy(kin_mem->kin_pp);
+      N_VDestroy(kin_mem->kin_vtemp1);
+      N_VDestroy(kin_mem->kin_vtemp2);
       free(kin_mem->kin_R_aa);
       free(kin_mem->kin_gamma_aa);
       return(KIN_MEM_FAIL);
     }
   } 
 
-  if (maa) {
-    fold = N_VClone(tmpl);
-    if (fold == NULL) {
-      N_VDestroy(unew);
-      N_VDestroy(fval);
-      N_VDestroy(pp);
-      N_VDestroy(vtemp1);
-      N_VDestroy(vtemp2);
+  if (kin_mem->kin_m_aa) {
+    kin_mem->kin_fold_aa = N_VClone(tmpl);
+    if (kin_mem->kin_fold_aa == NULL) {
+      N_VDestroy(kin_mem->kin_unew);
+      N_VDestroy(kin_mem->kin_fval);
+      N_VDestroy(kin_mem->kin_pp);
+      N_VDestroy(kin_mem->kin_vtemp1);
+      N_VDestroy(kin_mem->kin_vtemp2);
       free(kin_mem->kin_R_aa);
       free(kin_mem->kin_gamma_aa);
       free(kin_mem->kin_ipt_map);
-      return(FALSE);
+      return(SUNFALSE);
     }
-    gold = N_VClone(tmpl);
-    if (gold == NULL) {
-      N_VDestroy(unew);
-      N_VDestroy(fval);
-      N_VDestroy(pp);
-      N_VDestroy(vtemp1);
-      N_VDestroy(vtemp2);
-      N_VDestroy(fold);
-      return(FALSE);
+    kin_mem->kin_gold_aa = N_VClone(tmpl);
+    if (kin_mem->kin_gold_aa == NULL) {
+      N_VDestroy(kin_mem->kin_unew);
+      N_VDestroy(kin_mem->kin_fval);
+      N_VDestroy(kin_mem->kin_pp);
+      N_VDestroy(kin_mem->kin_vtemp1);
+      N_VDestroy(kin_mem->kin_vtemp2);
+      N_VDestroy(kin_mem->kin_fold_aa);
+      return(SUNFALSE);
     }
-    df = N_VCloneVectorArray(maa,tmpl);
-    if (df == NULL) {
-      N_VDestroy(unew);
-      N_VDestroy(fval);
-      N_VDestroy(pp);
-      N_VDestroy(vtemp1);
-      N_VDestroy(vtemp2);
+    kin_mem->kin_df_aa = N_VCloneVectorArray(kin_mem->kin_m_aa,tmpl);
+    if (kin_mem->kin_df_aa == NULL) {
+      N_VDestroy(kin_mem->kin_unew);
+      N_VDestroy(kin_mem->kin_fval);
+      N_VDestroy(kin_mem->kin_pp);
+      N_VDestroy(kin_mem->kin_vtemp1);
+      N_VDestroy(kin_mem->kin_vtemp2);
       free(kin_mem->kin_R_aa);
       free(kin_mem->kin_gamma_aa);
       free(kin_mem->kin_ipt_map);
-      N_VDestroy(fold);
-      N_VDestroy(gold);
-      return(FALSE);
+      N_VDestroy(kin_mem->kin_fold_aa);
+      N_VDestroy(kin_mem->kin_gold_aa);
+      return(SUNFALSE);
     }
-    dg = N_VCloneVectorArray(maa,tmpl);
-    if (dg == NULL) {
-      N_VDestroy(unew);
-      N_VDestroy(fval);
-      N_VDestroy(pp);
-      N_VDestroy(vtemp1);
-      N_VDestroy(vtemp2);
+    kin_mem->kin_dg_aa = N_VCloneVectorArray(kin_mem->kin_m_aa,tmpl);
+    if (kin_mem->kin_dg_aa == NULL) {
+      N_VDestroy(kin_mem->kin_unew);
+      N_VDestroy(kin_mem->kin_fval);
+      N_VDestroy(kin_mem->kin_pp);
+      N_VDestroy(kin_mem->kin_vtemp1);
+      N_VDestroy(kin_mem->kin_vtemp2);
       free(kin_mem->kin_R_aa);
       free(kin_mem->kin_gamma_aa);
       free(kin_mem->kin_ipt_map);
-      N_VDestroy(fold);
-      N_VDestroy(gold);
-      N_VDestroyVectorArray(df, maa);
-      return(FALSE);
+      N_VDestroy(kin_mem->kin_fold_aa);
+      N_VDestroy(kin_mem->kin_gold_aa);
+      N_VDestroyVectorArray(kin_mem->kin_df_aa, kin_mem->kin_m_aa);
+      return(SUNFALSE);
     }
 
     /* update solver workspace lengths */
 
-    liw += 2*maa*liw1+2;
-    lrw += 2*maa*lrw1+2;
-
-    if (aamem) {
-      Q = N_VCloneVectorArray(maa,tmpl);
-      if (Q == NULL) {
-	N_VDestroy(unew);
-	N_VDestroy(fval);
-	N_VDestroy(pp);
-	N_VDestroy(vtemp1);
-	N_VDestroy(vtemp2);
+    kin_mem->kin_liw += 2*kin_mem->kin_m_aa*kin_mem->kin_liw1+2;
+    kin_mem->kin_lrw += 2*kin_mem->kin_m_aa*kin_mem->kin_lrw1+2;
+
+    if (kin_mem->kin_aamem_aa) {
+      kin_mem->kin_q_aa = N_VCloneVectorArray(kin_mem->kin_m_aa,tmpl);
+      if (kin_mem->kin_q_aa == NULL) {
+	N_VDestroy(kin_mem->kin_unew);
+	N_VDestroy(kin_mem->kin_fval);
+	N_VDestroy(kin_mem->kin_pp);
+	N_VDestroy(kin_mem->kin_vtemp1);
+	N_VDestroy(kin_mem->kin_vtemp2);
 	free(kin_mem->kin_R_aa);
 	free(kin_mem->kin_gamma_aa);
 	free(kin_mem->kin_ipt_map);
-	N_VDestroy(fold);
-	N_VDestroy(gold);
-	N_VDestroyVectorArray(df, maa);
-	N_VDestroyVectorArray(dg, maa);
-	return(FALSE);
+	N_VDestroy(kin_mem->kin_fold_aa);
+	N_VDestroy(kin_mem->kin_gold_aa);
+	N_VDestroyVectorArray(kin_mem->kin_df_aa, kin_mem->kin_m_aa);
+	N_VDestroyVectorArray(kin_mem->kin_dg_aa, kin_mem->kin_m_aa);
+	return(SUNFALSE);
       }
-      liw += maa*liw1;
-      lrw += maa*lrw1;
+      kin_mem->kin_liw += kin_mem->kin_m_aa*kin_mem->kin_liw1;
+      kin_mem->kin_lrw += kin_mem->kin_m_aa*kin_mem->kin_lrw1;
     }
   }
-  return(TRUE);
+  return(SUNTRUE);
 }
 
 /*
@@ -977,44 +877,44 @@ static booleantype KINAllocVectors(KINMem kin_mem, N_Vector tmpl)
 
 static void KINFreeVectors(KINMem kin_mem)
 {
-  if (unew != NULL)   N_VDestroy(unew);
-  if (fval != NULL)   N_VDestroy(fval);
-  if (pp != NULL)     N_VDestroy(pp);
-  if (vtemp1 != NULL) N_VDestroy(vtemp1);
-  if (vtemp2 != NULL) N_VDestroy(vtemp2);
+  if (kin_mem->kin_unew != NULL)   N_VDestroy(kin_mem->kin_unew);
+  if (kin_mem->kin_fval != NULL)   N_VDestroy(kin_mem->kin_fval);
+  if (kin_mem->kin_pp != NULL)     N_VDestroy(kin_mem->kin_pp);
+  if (kin_mem->kin_vtemp1 != NULL) N_VDestroy(kin_mem->kin_vtemp1);
+  if (kin_mem->kin_vtemp2 != NULL) N_VDestroy(kin_mem->kin_vtemp2);
 
   if ( (kin_mem->kin_globalstrategy == KIN_PICARD) && (kin_mem->kin_gval != NULL) ) 
     N_VDestroy(kin_mem->kin_gval);
 
-  if ( ((strategy == KIN_PICARD) || (strategy == KIN_FP)) && (maa > 0) ) {
+  if ( ((kin_mem->kin_globalstrategy == KIN_PICARD) || (kin_mem->kin_globalstrategy == KIN_FP)) && (kin_mem->kin_m_aa > 0) ) {
     free(kin_mem->kin_R_aa);
     free(kin_mem->kin_gamma_aa);
     free(kin_mem->kin_ipt_map);
   }
 
-  if (maa)
+  if (kin_mem->kin_m_aa)
   {
-     if (fold != NULL) N_VDestroy(fold);
-     if (gold != NULL) N_VDestroy(gold);
-     N_VDestroyVectorArray(df,maa);
-     N_VDestroyVectorArray(dg,maa);
-     lrw -= (2*maa*lrw1+2);
-     liw -= (2*maa*liw1+2);
-     if (aamem)
+     if (kin_mem->kin_fold_aa != NULL) N_VDestroy(kin_mem->kin_fold_aa);
+     if (kin_mem->kin_gold_aa != NULL) N_VDestroy(kin_mem->kin_gold_aa);
+     N_VDestroyVectorArray(kin_mem->kin_df_aa,kin_mem->kin_m_aa);
+     N_VDestroyVectorArray(kin_mem->kin_dg_aa,kin_mem->kin_m_aa);
+     kin_mem->kin_lrw -= (2*kin_mem->kin_m_aa*kin_mem->kin_lrw1+2);
+     kin_mem->kin_liw -= (2*kin_mem->kin_m_aa*kin_mem->kin_liw1+2);
+     if (kin_mem->kin_aamem_aa)
      {
-        N_VDestroyVectorArray(Q,maa);
-        lrw -= maa*lrw1;
-        liw -= maa*liw1;
+        N_VDestroyVectorArray(kin_mem->kin_q_aa,kin_mem->kin_m_aa);
+        kin_mem->kin_lrw -= kin_mem->kin_m_aa*kin_mem->kin_lrw1;
+        kin_mem->kin_liw -= kin_mem->kin_m_aa*kin_mem->kin_liw1;
      }
   }
 
-  lrw -= 5*lrw1;
-  liw -= 5*liw1;
+  kin_mem->kin_lrw -= 5*kin_mem->kin_lrw1;
+  kin_mem->kin_liw -= 5*kin_mem->kin_liw1;
 
   if (kin_mem->kin_constraintsSet) {
-    if (constraints != NULL) N_VDestroy(constraints);
-    lrw -= lrw1;
-    liw -= liw1;
+    if (kin_mem->kin_constraints != NULL) N_VDestroy(kin_mem->kin_constraints);
+    kin_mem->kin_lrw -= kin_mem->kin_lrw1;
+    kin_mem->kin_liw -= kin_mem->kin_liw1;
   }
 
   return;
@@ -1052,38 +952,38 @@ static int KINSolInit(KINMem kin_mem)
   
   /* check for illegal input parameters */
 
-  if (uu == NULL) {
+  if (kin_mem->kin_uu == NULL) {
     KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_UU_NULL);
     return(KIN_ILL_INPUT);
   }
 
-  if ( (strategy != KIN_NONE) && (strategy != KIN_LINESEARCH) && 
-       (strategy != KIN_PICARD) && (strategy != KIN_FP) ) {
+  if ( (kin_mem->kin_globalstrategy != KIN_NONE) && (kin_mem->kin_globalstrategy != KIN_LINESEARCH) && 
+       (kin_mem->kin_globalstrategy != KIN_PICARD) && (kin_mem->kin_globalstrategy != KIN_FP) ) {
     KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_GLSTRAT);
     return(KIN_ILL_INPUT);
   }
 
-  if (uscale == NULL)  {
+  if (kin_mem->kin_uscale == NULL)  {
     KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_USCALE);
     return(KIN_ILL_INPUT);
   }
 
-  if (N_VMin(uscale) <= ZERO){
+  if (N_VMin(kin_mem->kin_uscale) <= ZERO){
     KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_USCALE_NONPOSITIVE);
     return(KIN_ILL_INPUT);
   }
 
-  if (fscale == NULL)  {
+  if (kin_mem->kin_fscale == NULL)  {
     KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_FSCALE);
     return(KIN_ILL_INPUT);
   }
 
-  if (N_VMin(fscale) <= ZERO){
+  if (N_VMin(kin_mem->kin_fscale) <= ZERO){
     KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_FSCALE_NONPOSITIVE);
     return(KIN_ILL_INPUT);
   }
 
-  if ( (constraints != NULL) && ( (strategy == KIN_PICARD) || (strategy == KIN_FP) ) ) {
+  if ( (kin_mem->kin_constraints != NULL) && ( (kin_mem->kin_globalstrategy == KIN_PICARD) || (kin_mem->kin_globalstrategy == KIN_FP) ) ) {
     KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_CONSTRAINTS_NOTOK);
     return(KIN_ILL_INPUT);
   }
@@ -1091,12 +991,12 @@ static int KINSolInit(KINMem kin_mem)
 
   /* set the constraints flag */
 
-  if (constraints == NULL) 
-    constraintsSet = FALSE;
+  if (kin_mem->kin_constraints == NULL) 
+    kin_mem->kin_constraintsSet = SUNFALSE;
   else {
-    constraintsSet = TRUE;
-    if ((constraints->ops->nvconstrmask  == NULL) ||
-	(constraints->ops->nvminquotient == NULL)) {
+    kin_mem->kin_constraintsSet = SUNTRUE;
+    if ((kin_mem->kin_constraints->ops->nvconstrmask  == NULL) ||
+	(kin_mem->kin_constraints->ops->nvminquotient == NULL)) {
       KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_BAD_NVECTOR);
       return(KIN_ILL_INPUT);
     }
@@ -1104,8 +1004,8 @@ static int KINSolInit(KINMem kin_mem)
 
   /* check the initial guess uu against the constraints */
 
-  if (constraintsSet) {
-    if (!N_VConstrMask(constraints, uu, vtemp1)) {
+  if (kin_mem->kin_constraintsSet) {
+    if (!N_VConstrMask(kin_mem->kin_constraints, kin_mem->kin_uu, kin_mem->kin_vtemp1)) {
       KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSolInit", MSG_INITIAL_CNSTRNT);
       return(KIN_ILL_INPUT);
     }
@@ -1113,49 +1013,49 @@ static int KINSolInit(KINMem kin_mem)
   
   /* all error checking is complete at this point */
 
-  if (printfl > 0)
-    KINPrintInfo(kin_mem, PRNT_TOL, "KINSOL", "KINSolInit", INFO_TOL, scsteptol, fnormtol);
+  if (kin_mem->kin_printfl > 0)
+    KINPrintInfo(kin_mem, PRNT_TOL, "KINSOL", "KINSolInit", INFO_TOL, kin_mem->kin_scsteptol, kin_mem->kin_fnormtol);
 
   /* calculate the default value for mxnewtstep (maximum Newton step) */
 
-  if (mxnstepin == ZERO) mxnewtstep = THOUSAND * N_VWL2Norm(uu, uscale);
-  else                   mxnewtstep = mxnstepin;
-  if (mxnewtstep < ONE) mxnewtstep = ONE;
+  if (kin_mem->kin_mxnstepin == ZERO) kin_mem->kin_mxnewtstep = THOUSAND * N_VWL2Norm(kin_mem->kin_uu, kin_mem->kin_uscale);
+  else                                kin_mem->kin_mxnewtstep = kin_mem->kin_mxnstepin;
 
+  if (kin_mem->kin_mxnewtstep < ONE) kin_mem->kin_mxnewtstep = ONE;
 
   /* additional set-up for inexact linear solvers */
 
-  if (inexact_ls) {
+  if (kin_mem->kin_inexact_ls) {
 
     /* set up the coefficients for the eta calculation */
 
-    callForcingTerm = (etaflag != KIN_ETACONSTANT);
+    kin_mem->kin_callForcingTerm = (kin_mem->kin_etaflag != KIN_ETACONSTANT);
 
     /* this value is always used for choice #1 */
 
-    if (etaflag == KIN_ETACHOICE1) ealpha = (ONE + SUNRsqrt(FIVE)) * HALF;
+    if (kin_mem->kin_etaflag == KIN_ETACHOICE1) kin_mem->kin_eta_alpha = (ONE + SUNRsqrt(FIVE)) * HALF;
 
     /* initial value for eta set to 0.5 for other than the 
        KIN_ETACONSTANT option */
 
-    if (etaflag != KIN_ETACONSTANT) eta = HALF;
+    if (kin_mem->kin_etaflag != KIN_ETACONSTANT) kin_mem->kin_eta = HALF;
 
     /* disable residual monitoring if using an inexact linear solver */
 
-    noResMon = TRUE;
+    kin_mem->kin_noResMon = SUNTRUE;
 
   } else {
 
-    callForcingTerm = FALSE;
+    kin_mem->kin_callForcingTerm = SUNFALSE;
 
   }
 
   /* initialize counters */
 
-  nfe = nnilset = nnilset_sub = nni = nbcf = nbktrk = 0;
+  kin_mem->kin_nfe = kin_mem->kin_nnilset = kin_mem->kin_nnilset_sub = kin_mem->kin_nni = kin_mem->kin_nbcf = kin_mem->kin_nbktrk = 0;
 
   /* see if the initial guess uu satisfies the nonlinear system */
-  retval = func(uu, fval, user_data); nfe++;
+  retval = kin_mem->kin_func(kin_mem->kin_uu, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
 
   if (retval < 0) {
     KINProcessError(kin_mem, KIN_SYSFUNC_FAIL, "KINSOL", "KINSolInit", 
@@ -1167,19 +1067,19 @@ static int KINSolInit(KINMem kin_mem)
     return(KIN_FIRST_SYSFUNC_ERR);
   }
 
-  fmax = KINScFNorm(kin_mem, fval, fscale);
-  if (fmax <= (POINT01 * fnormtol)) {
-    kin_mem->kin_fnorm = N_VWL2Norm(fval, fscale);
+  fmax = KINScFNorm(kin_mem, kin_mem->kin_fval, kin_mem->kin_fscale);
+  if (fmax <= (POINT01 * kin_mem->kin_fnormtol)) {
+    kin_mem->kin_fnorm = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
     return(KIN_INITIAL_GUESS_OK);
   }
 
-  if (printfl > 1)
+  if (kin_mem->kin_printfl > 1)
     KINPrintInfo(kin_mem, PRNT_FMAX, "KINSOL", "KINSolInit", INFO_FMAX, fmax);
   
   /* initialize the linear solver if linit != NULL */
 
-  if (linit != NULL) {
-    retval = linit(kin_mem);
+  if (kin_mem->kin_linit != NULL) {
+    retval = kin_mem->kin_linit(kin_mem);
     if (retval != 0) {
       KINProcessError(kin_mem, KIN_LINIT_FAIL, "KINSOL", "KINSolInit", MSG_LINIT_FAIL);
       return(KIN_LINIT_FAIL);
@@ -1188,13 +1088,13 @@ static int KINSolInit(KINMem kin_mem)
 
   /* initialize the L2 (Euclidean) norms of f for the linear iteration steps */
 
-  fnorm = N_VWL2Norm(fval, fscale);
-  f1norm = HALF * fnorm * fnorm;
-  fnorm_sub = fnorm;
+  kin_mem->kin_fnorm = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
+  kin_mem->kin_f1norm = HALF * kin_mem->kin_fnorm * kin_mem->kin_fnorm;
+  kin_mem->kin_fnorm_sub = kin_mem->kin_fnorm;
 
-  if (printfl > 0)
+  if (kin_mem->kin_printfl > 0)
     KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINSolInit", 
-		 INFO_NNI, nni, nfe, fnorm);
+		 INFO_NNI, kin_mem->kin_nni, kin_mem->kin_nfe, kin_mem->kin_fnorm);
 
   /* problem has now been successfully initialized */
 
@@ -1221,44 +1121,44 @@ static int KINLinSolDrv(KINMem kin_mem)
   N_Vector x, b;
   int retval;
 
-  if ((nni - nnilset) >= msbset) {
-    sthrsh = TWO;
-    update_fnorm_sub = TRUE;
+  if ((kin_mem->kin_nni - kin_mem->kin_nnilset) >= kin_mem->kin_msbset) {
+    kin_mem->kin_sthrsh = TWO;
+    kin_mem->kin_update_fnorm_sub = SUNTRUE;
   }
 
-  loop{
+  for(;;){
 
-    jacCurrent = FALSE;
+    kin_mem->kin_jacCurrent = SUNFALSE;
 
-    if ((sthrsh > ONEPT5) && setupNonNull) {
-      retval = lsetup(kin_mem);
-      jacCurrent = TRUE;
-      nnilset = nni;
-      nnilset_sub = nni;
+    if ((kin_mem->kin_sthrsh > ONEPT5) && (kin_mem->kin_lsetup != NULL)) {
+      retval = kin_mem->kin_lsetup(kin_mem);
+      kin_mem->kin_jacCurrent = SUNTRUE;
+      kin_mem->kin_nnilset = kin_mem->kin_nni;
+      kin_mem->kin_nnilset_sub = kin_mem->kin_nni;
       if (retval != 0) return(KIN_LSETUP_FAIL);
     }
 
     /* rename vectors for readability */
 
-    b = unew;
-    x = pp;
+    b = kin_mem->kin_unew;
+    x = kin_mem->kin_pp;
 
     /* load b with the current value of -fval */
 
-    N_VScale(-ONE, fval, b);
+    N_VScale(-ONE, kin_mem->kin_fval, b);
 
     /* call the generic 'lsolve' routine to solve the system Jx = b */
 
-    retval = lsolve(kin_mem, x, b, &sJpnorm, &sFdotJp);
+    retval = kin_mem->kin_lsolve(kin_mem, x, b, &(kin_mem->kin_sJpnorm), &(kin_mem->kin_sFdotJp));
 
     if (retval == 0)                          return(KIN_SUCCESS);
     else if (retval < 0)                      return(KIN_LSOLVE_FAIL);
-    else if ((!setupNonNull) || (jacCurrent)) return(KIN_LINSOLV_NO_RECOVERY);
+    else if ((kin_mem->kin_lsetup == NULL) || (kin_mem->kin_jacCurrent)) return(KIN_LINSOLV_NO_RECOVERY);
 
     /* loop back only if the linear solver setup is in use 
        and Jacobian information is not current */
 
-    sthrsh = TWO;
+    kin_mem->kin_sthrsh = TWO;
 
   }
 }
@@ -1280,61 +1180,61 @@ static int KINFullNewton(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
   booleantype fOK;
   int ircvr, retval;
 
-  *maxStepTaken = FALSE;
-  pnorm = N_VWL2Norm(pp, uscale);
+  *maxStepTaken = SUNFALSE;
+  pnorm = N_VWL2Norm(kin_mem->kin_pp, kin_mem->kin_uscale);
   ratio = ONE;
-  if (pnorm > mxnewtstep) {
-    ratio = mxnewtstep / pnorm;
-    N_VScale(ratio, pp, pp);
-    pnorm = mxnewtstep;
+  if (pnorm > kin_mem->kin_mxnewtstep) {
+    ratio = kin_mem->kin_mxnewtstep / pnorm;
+    N_VScale(ratio, kin_mem->kin_pp, kin_mem->kin_pp);
+    pnorm = kin_mem->kin_mxnewtstep;
   }
 
-  if (printfl > 0)
+  if (kin_mem->kin_printfl > 0)
     KINPrintInfo(kin_mem, PRNT_PNORM, "KINSOL", "KINFullNewton", INFO_PNORM, pnorm);
 
   /* If constraints are active, then constrain the step accordingly */
 
-  stepl = pnorm;
-  stepmul = ONE;
-  if (constraintsSet) {
+  kin_mem->kin_stepl = pnorm;
+  kin_mem->kin_stepmul = ONE;
+  if (kin_mem->kin_constraintsSet) {
     retval = KINConstraint(kin_mem);
     if (retval == CONSTR_VIOLATED) {
       /* Apply stepmul set in KINConstraint */
-      ratio *= stepmul;
-      N_VScale(stepmul, pp, pp);
-      pnorm *= stepmul;
-      stepl = pnorm;
-      if (printfl > 0)
+      ratio *= kin_mem->kin_stepmul;
+      N_VScale(kin_mem->kin_stepmul, kin_mem->kin_pp, kin_mem->kin_pp);
+      pnorm *= kin_mem->kin_stepmul;
+      kin_mem->kin_stepl = pnorm;
+      if (kin_mem->kin_printfl > 0)
         KINPrintInfo(kin_mem, PRNT_PNORM, "KINSOL", "KINFullNewton", INFO_PNORM, pnorm);
-      if (pnorm <= scsteptol) {
-        N_VLinearSum(ONE, uu, ONE, pp, unew);
+      if (pnorm <= kin_mem->kin_scsteptol) {
+        N_VLinearSum(ONE, kin_mem->kin_uu, ONE, kin_mem->kin_pp, kin_mem->kin_unew);
         return(STEP_TOO_SMALL);}
     }
   }
  
   /* Attempt (at most MAX_RECVR times) to evaluate function at the new iterate */
   
-  fOK = FALSE;
+  fOK = SUNFALSE;
 
   for (ircvr = 1; ircvr <= MAX_RECVR; ircvr++) {
 
     /* compute the iterate unew = uu + pp */
-    N_VLinearSum(ONE, uu, ONE, pp, unew);
+    N_VLinearSum(ONE, kin_mem->kin_uu, ONE, kin_mem->kin_pp, kin_mem->kin_unew);
 
     /* evaluate func(unew) and its norm, and return */
-    retval = func(unew, fval, user_data); nfe++;
+    retval = kin_mem->kin_func(kin_mem->kin_unew, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
 
     /* if func was successful, accept pp */
-    if (retval == 0) {fOK = TRUE; break;}
+    if (retval == 0) {fOK = SUNTRUE; break;}
 
     /* if func failed unrecoverably, give up */
     else if (retval < 0) return(KIN_SYSFUNC_FAIL);
 
     /* func failed recoverably; cut step in half and try again */
     ratio *= HALF;
-    N_VScale(HALF, pp, pp);
+    N_VScale(HALF, kin_mem->kin_pp, kin_mem->kin_pp);
     pnorm *= HALF;
-    stepl = pnorm;
+    kin_mem->kin_stepl = pnorm;
   }
 
   /* If func() failed recoverably MAX_RECVR times, give up */
@@ -1343,18 +1243,18 @@ static int KINFullNewton(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 
   /* Evaluate function norms */
 
-  *fnormp = N_VWL2Norm(fval,fscale);
+  *fnormp = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
   *f1normp = HALF * (*fnormp) * (*fnormp);
 
   /* scale sFdotJp and sJpnorm by ratio for later use in KINForcingTerm */
 
-  sFdotJp *= ratio;
-  sJpnorm *= ratio;
+  kin_mem->kin_sFdotJp *= ratio;
+  kin_mem->kin_sJpnorm *= ratio;
  
-  if (printfl > 1) 
+  if (kin_mem->kin_printfl > 1) 
     KINPrintInfo(kin_mem, PRNT_FNORM, "KINSOL", "KINFullNewton", INFO_FNORM, *fnormp);
 
-  if (pnorm > (POINT99 * mxnewtstep)) *maxStepTaken = TRUE; 
+  if (pnorm > (POINT99 * kin_mem->kin_mxnewtstep)) *maxStepTaken = SUNTRUE; 
 
   return(KIN_SUCCESS);
 }
@@ -1422,71 +1322,71 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
   alpha    = POINT0001;
   beta     = POINT9;
 
-  firstBacktrack = TRUE;
-  *maxStepTaken = FALSE;
+  firstBacktrack = SUNTRUE;
+  *maxStepTaken = SUNFALSE;
 
   rlprev = f1nprv = ZERO;
 
   /* Compute length of Newton step */
 
-  pnorm = N_VWL2Norm(pp, uscale);
-  rlmax = mxnewtstep / pnorm;
-  stepl = pnorm;
+  pnorm = N_VWL2Norm(kin_mem->kin_pp, kin_mem->kin_uscale);
+  rlmax = kin_mem->kin_mxnewtstep / pnorm;
+  kin_mem->kin_stepl = pnorm;
 
   /* If the full Newton step is too large, set it to the maximum allowable value */
 
-  if(pnorm > mxnewtstep ) {
-    ratio = mxnewtstep / pnorm;
-    N_VScale(ratio, pp, pp);
-    pnorm = mxnewtstep;
+  if(pnorm > kin_mem->kin_mxnewtstep ) {
+    ratio = kin_mem->kin_mxnewtstep / pnorm;
+    N_VScale(ratio, kin_mem->kin_pp, kin_mem->kin_pp);
+    pnorm = kin_mem->kin_mxnewtstep;
     rlmax = ONE;
-    stepl = pnorm;
+    kin_mem->kin_stepl = pnorm;
   }
 
   /* If constraint checking is activated, check and correct violations */
 
-  stepmul = ONE;
+  kin_mem->kin_stepmul = ONE;
 
-  if(constraintsSet){
+  if(kin_mem->kin_constraintsSet){
     retval = KINConstraint(kin_mem);
     if(retval == CONSTR_VIOLATED){
       /* Apply stepmul set in KINConstraint */
-      N_VScale(stepmul, pp, pp);
-      ratio *= stepmul;
-      pnorm *= stepmul;
+      N_VScale(kin_mem->kin_stepmul, kin_mem->kin_pp, kin_mem->kin_pp);
+      ratio *= kin_mem->kin_stepmul;
+      pnorm *= kin_mem->kin_stepmul;
       rlmax = ONE;
-      stepl = pnorm;
-      if (printfl > 0) KINPrintInfo(kin_mem, PRNT_PNORM1, "KINSOL", "KINLineSearch", INFO_PNORM1, pnorm);
-      if (pnorm <= scsteptol) {
-        N_VLinearSum(ONE, uu, ONE, pp, unew);
+      kin_mem->kin_stepl = pnorm;
+      if (kin_mem->kin_printfl > 0) KINPrintInfo(kin_mem, PRNT_PNORM1, "KINSOL", "KINLineSearch", INFO_PNORM1, pnorm);
+      if (pnorm <= kin_mem->kin_scsteptol) {
+        N_VLinearSum(ONE, kin_mem->kin_uu, ONE, kin_mem->kin_pp, kin_mem->kin_unew);
         return(STEP_TOO_SMALL);}
     }
   }
 
   /* Attempt (at most MAX_RECVR times) to evaluate function at the new iterate */
   
-  fOK = FALSE;
+  fOK = SUNFALSE;
 
   for (ircvr = 1; ircvr <= MAX_RECVR; ircvr++) {
 
     /* compute the iterate unew = uu + pp */
-    N_VLinearSum(ONE, uu, ONE, pp, unew);
+    N_VLinearSum(ONE, kin_mem->kin_uu, ONE, kin_mem->kin_pp, kin_mem->kin_unew);
 
     /* evaluate func(unew) and its norm, and return */
-    retval = func(unew, fval, user_data); nfe++;
+    retval = kin_mem->kin_func(kin_mem->kin_unew, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
 
     /* if func was successful, accept pp */
-    if (retval == 0) {fOK = TRUE; break;}
+    if (retval == 0) {fOK = SUNTRUE; break;}
 
     /* if func failed unrecoverably, give up */
     else if (retval < 0) return(KIN_SYSFUNC_FAIL);
 
     /* func failed recoverably; cut step in half and try again */
-    N_VScale(HALF, pp, pp);
+    N_VScale(HALF, kin_mem->kin_pp, kin_mem->kin_pp);
     ratio *= HALF;
     pnorm *= HALF;
     rlmax = ONE;
-    stepl = pnorm;
+    kin_mem->kin_stepl = pnorm;
 
   }
 
@@ -1496,28 +1396,28 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 
   /* Evaluate function norms */
 
-  *fnormp = N_VWL2Norm(fval, fscale);
+  *fnormp = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
   *f1normp = HALF * (*fnormp) * (*fnormp) ;
 
   /* Estimate the line search value rl (lambda) to satisfy both ALPHA and BETA conditions */
 
-  slpi = sFdotJp * ratio;
-  rlength = KINScSNorm(kin_mem, pp, uu);
-  rlmin = scsteptol / rlength;
+  slpi = kin_mem->kin_sFdotJp * ratio;
+  rlength = KINScSNorm(kin_mem, kin_mem->kin_pp, kin_mem->kin_uu);
+  rlmin = (kin_mem->kin_scsteptol) / rlength;
   rl = ONE;
 
-  if (printfl > 2)
-    KINPrintInfo(kin_mem, PRNT_LAM, "KINSOL", "KINLineSearch", INFO_LAM, rlmin, f1norm, pnorm);
+  if (kin_mem->kin_printfl > 2)
+    KINPrintInfo(kin_mem, PRNT_LAM, "KINSOL", "KINLineSearch", INFO_LAM, rlmin, kin_mem->kin_f1norm, pnorm);
 
   /* Loop until the ALPHA condition is satisfied. Terminate if rl becomes too small */
 
-  loop {
+  for(;;) {
     
     /* Evaluate test quantity */
 
-    alpha_cond = f1norm + (alpha * slpi * rl);
+    alpha_cond = kin_mem->kin_f1norm + (alpha * slpi * rl);
 
-    if (printfl > 2)
+    if (kin_mem->kin_printfl > 2)
       KINPrintInfo(kin_mem, PRNT_ALPHA, "KINSOL", "KINLinesearch", 
                    INFO_ALPHA, *fnormp, *f1normp, alpha_cond, rl);
 
@@ -1529,13 +1429,13 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 
     if (firstBacktrack) {
 
-      rltmp = -slpi / (TWO * ((*f1normp) - f1norm - slpi));
-      firstBacktrack = FALSE;
+      rltmp = -slpi / (TWO * ((*f1normp) - kin_mem->kin_f1norm - slpi));
+      firstBacktrack = SUNFALSE;
 
     } else {
 
-      tmp1 = (*f1normp) - f1norm - (rl * slpi);
-      tmp2 = f1nprv - f1norm - (rlprev * slpi);
+      tmp1 = (*f1normp) - kin_mem->kin_f1norm - (rl * slpi);
+      tmp2 = f1nprv - kin_mem->kin_f1norm - (rlprev * slpi);
       rl_a = ((ONE / (rl * rl)) * tmp1) - ((ONE / (rlprev * rlprev)) * tmp2);
       rl_b = ((-rlprev / (rl * rl)) * tmp1) + ((rl / (rlprev * rlprev)) * tmp2);
       tmp1 = ONE / (rl - rlprev);
@@ -1543,7 +1443,7 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
       rl_b *= tmp1;
       disc = (rl_b * rl_b) - (THREE * rl_a * slpi);
 
-      if (SUNRabs(rl_a) < uround) {        /* cubic is actually just a quadratic (rl_a ~ 0) */
+      if (SUNRabs(rl_a) < kin_mem->kin_uround) {        /* cubic is actually just a quadratic (rl_a ~ 0) */
         rltmp = -slpi / (TWO * rl_b);
       } else {                         /* real cubic */
         rltmp = (-rl_b + SUNRsqrt(disc)) / (THREE * rl_a);
@@ -1561,12 +1461,12 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 
     /* Update unew and re-evaluate function */
 
-    N_VLinearSum(ONE, uu, rl, pp, unew);
+    N_VLinearSum(ONE, kin_mem->kin_uu, rl, kin_mem->kin_pp, kin_mem->kin_unew);
 
-    retval = func(unew, fval, user_data); nfe++;
+    retval = kin_mem->kin_func(kin_mem->kin_unew, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
     if (retval != 0) return(KIN_SYSFUNC_FAIL);
 
-    *fnormp = N_VWL2Norm(fval, fscale);
+    *fnormp = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
     *f1normp = HALF * (*fnormp) * (*fnormp) ;
 
     /* Check if rl (lambda) is too small */
@@ -1575,7 +1475,7 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
       /* unew sufficiently distinct from uu cannot be found.
          copy uu into unew (step remains unchanged) and 
          return STEP_TOO_SMALL */
-      N_VScale(ONE, uu, unew);
+      N_VScale(ONE, kin_mem->kin_uu, kin_mem->kin_unew);
       return(STEP_TOO_SMALL);
     }
 
@@ -1584,13 +1484,13 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 
   /* ALPHA condition is satisfied. Now check the BETA condition */
 
-  beta_cond = f1norm + (beta * slpi * rl);
+  beta_cond = kin_mem->kin_f1norm + (beta * slpi * rl);
 
   if ((*f1normp) < beta_cond) {
 
     /* BETA condition not satisfied */
 
-    if ((rl == ONE) && (pnorm < mxnewtstep)) {
+    if ((rl == ONE) && (pnorm < kin_mem->kin_mxnewtstep)) {
 
       do {
 
@@ -1599,16 +1499,16 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
         rl = SUNMIN((TWO * rl), rlmax);
         nbktrk_l++;
 
-        N_VLinearSum(ONE, uu, rl, pp, unew);
-        retval = func(unew, fval, user_data); nfe++;
+        N_VLinearSum(ONE, kin_mem->kin_uu, rl, kin_mem->kin_pp, kin_mem->kin_unew);
+        retval = kin_mem->kin_func(kin_mem->kin_unew, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
         if (retval != 0) return(KIN_SYSFUNC_FAIL);
-        *fnormp = N_VWL2Norm(fval, fscale);
+        *fnormp = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
         *f1normp = HALF * (*fnormp) * (*fnormp);
 
-        alpha_cond = f1norm + (alpha * slpi * rl);
-        beta_cond = f1norm + (beta * slpi * rl);
+        alpha_cond = kin_mem->kin_f1norm + (alpha * slpi * rl);
+        beta_cond = kin_mem->kin_f1norm + (beta * slpi * rl);
 
-        if (printfl > 2)
+        if (kin_mem->kin_printfl > 2)
           KINPrintInfo(kin_mem, PRNT_BETA, "KINSOL", "KINLineSearch", 
                        INFO_BETA, *f1normp, beta_cond, rl);
 
@@ -1628,16 +1528,16 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
         rl = rllo + rlinc;
         nbktrk_l++;
 
-        N_VLinearSum(ONE, uu, rl, pp, unew);
-        retval = func(unew, fval, user_data); nfe++;
+        N_VLinearSum(ONE, kin_mem->kin_uu, rl, kin_mem->kin_pp, kin_mem->kin_unew);
+        retval = kin_mem->kin_func(kin_mem->kin_unew, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
         if (retval != 0) return(KIN_SYSFUNC_FAIL);
-        *fnormp = N_VWL2Norm(fval, fscale);
+        *fnormp = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
         *f1normp = HALF * (*fnormp) * (*fnormp);
 
-        alpha_cond = f1norm + (alpha * slpi * rl);
-        beta_cond = f1norm + (beta * slpi * rl);
+        alpha_cond = kin_mem->kin_f1norm + (alpha * slpi * rl);
+        beta_cond = kin_mem->kin_f1norm + (beta * slpi * rl);
 
-        if (printfl > 2)
+        if (kin_mem->kin_printfl > 2)
           KINPrintInfo(kin_mem, PRNT_ALPHABETA, "KINSOL", "KINLineSearch", 
                        INFO_ALPHABETA, *f1normp, alpha_cond, beta_cond, rl);
 
@@ -1656,15 +1556,15 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 	   and alpha_cond not satisfied, so set unew to last u value
 	   that satisfied the alpha condition and continue */
 
-        N_VLinearSum(ONE, uu, rllo, pp, unew);
-        retval = func(unew, fval, user_data); nfe++;
+        N_VLinearSum(ONE, kin_mem->kin_uu, rllo, kin_mem->kin_pp, kin_mem->kin_unew);
+        retval = kin_mem->kin_func(kin_mem->kin_unew, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
         if (retval != 0) return(KIN_SYSFUNC_FAIL);
-        *fnormp = N_VWL2Norm(fval, fscale);
+        *fnormp = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
         *f1normp = HALF * (*fnormp) * (*fnormp);   
 
 	/* increment beta-condition failures counter */
 
-        nbcf++;
+        kin_mem->kin_nbcf++;
 
       }
 
@@ -1674,17 +1574,17 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 
   /* Update number of backtracking operations */
 
-  nbktrk += nbktrk_l;
+  kin_mem->kin_nbktrk += nbktrk_l;
 
-  if (printfl > 1)
+  if (kin_mem->kin_printfl > 1)
     KINPrintInfo(kin_mem, PRNT_ADJ, "KINSOL", "KINLineSearch", INFO_ADJ, nbktrk_l);
 
   /* scale sFdotJp and sJpnorm by rl * ratio for later use in KINForcingTerm */
 
-  sFdotJp = sFdotJp * rl * ratio;
-  sJpnorm = sJpnorm * rl * ratio;
+  kin_mem->kin_sFdotJp = kin_mem->kin_sFdotJp * rl * ratio;
+  kin_mem->kin_sJpnorm = kin_mem->kin_sJpnorm * rl * ratio;
 
-  if ((rl * pnorm) > (POINT99 * mxnewtstep)) *maxStepTaken = TRUE;
+  if ((rl * pnorm) > (POINT99 * kin_mem->kin_mxnewtstep)) *maxStepTaken = SUNTRUE;
 
   return(KIN_SUCCESS);
 }
@@ -1703,23 +1603,23 @@ static int KINLineSearch(KINMem kin_mem, realtype *fnormp, realtype *f1normp,
 
 static int KINConstraint(KINMem kin_mem)
 {
-  N_VLinearSum(ONE, uu, ONE, pp, vtemp1);
+  N_VLinearSum(ONE, kin_mem->kin_uu, ONE, kin_mem->kin_pp, kin_mem->kin_vtemp1);
 
   /* if vtemp1[i] violates constraint[i] then vtemp2[i] = 1
      else vtemp2[i] = 0 (vtemp2 is the mask vector) */
 
-  if(N_VConstrMask(constraints, vtemp1, vtemp2)) return(KIN_SUCCESS);
+  if(N_VConstrMask(kin_mem->kin_constraints, kin_mem->kin_vtemp1, kin_mem->kin_vtemp2)) return(KIN_SUCCESS);
 
   /* vtemp1[i] = SUNRabs(pp[i]) */
 
-  N_VAbs(pp, vtemp1);
+  N_VAbs(kin_mem->kin_pp, kin_mem->kin_vtemp1);
 
   /* consider vtemp1[i] only if vtemp2[i] = 1 (constraint violated) */
 
-  N_VProd(vtemp2, vtemp1, vtemp1);
+  N_VProd(kin_mem->kin_vtemp2, kin_mem->kin_vtemp1, kin_mem->kin_vtemp1);
 
-  N_VAbs(uu, vtemp2);
-  stepmul = POINT9 * N_VMinQuotient(vtemp2, vtemp1);
+  N_VAbs(kin_mem->kin_uu, kin_mem->kin_vtemp2);
+  kin_mem->kin_stepmul = POINT9 * N_VMinQuotient(kin_mem->kin_vtemp2, kin_mem->kin_vtemp1);
 
   return(CONSTR_VIOLATED);
 }
@@ -1749,13 +1649,13 @@ static int KINStop(KINMem kin_mem, booleantype maxStepTaken, int sflag)
 
   if (sflag == STEP_TOO_SMALL) {
 
-    if (setupNonNull && !jacCurrent) {
+    if ((kin_mem->kin_lsetup != NULL) && !(kin_mem->kin_jacCurrent)) {
       /* If the Jacobian is out of date, update it and retry */
-      sthrsh = TWO;
+      kin_mem->kin_sthrsh = TWO;
       return(RETRY_ITERATION);
     } else {
       /* Give up */
-      if (strategy == KIN_NONE)  return(KIN_STEP_LT_STPTOL);
+      if (kin_mem->kin_globalstrategy == KIN_NONE)  return(KIN_STEP_LT_STPTOL);
       else                       return(KIN_LINESEARCH_NONCONV);
     }
 
@@ -1763,25 +1663,25 @@ static int KINStop(KINMem kin_mem, booleantype maxStepTaken, int sflag)
 
   /* Check tolerance on scaled function norm at the current iterate */
 
-  fmax = KINScFNorm(kin_mem, fval, fscale);
+  fmax = KINScFNorm(kin_mem, kin_mem->kin_fval, kin_mem->kin_fscale);
 
-  if (printfl > 1) 
+  if (kin_mem->kin_printfl > 1) 
     KINPrintInfo(kin_mem, PRNT_FMAX, "KINSOL", "KINStop", INFO_FMAX, fmax);
 
-  if (fmax <= fnormtol) return(KIN_SUCCESS);
+  if (fmax <= kin_mem->kin_fnormtol) return(KIN_SUCCESS);
 
   /* Check if the scaled distance between the last two steps is too small */
   /* NOTE: pp used as work space to store this distance */
 
-  delta = pp;
-  N_VLinearSum(ONE, unew, -ONE, uu, delta);
-  rlength = KINScSNorm(kin_mem, delta, unew);
+  delta = kin_mem->kin_pp;
+  N_VLinearSum(ONE, kin_mem->kin_unew, -ONE, kin_mem->kin_uu, delta);
+  rlength = KINScSNorm(kin_mem, delta, kin_mem->kin_unew);
 
-  if (rlength <= scsteptol) {
+  if (rlength <= kin_mem->kin_scsteptol) {
 
-    if (setupNonNull && !jacCurrent) {
+    if ((kin_mem->kin_lsetup != NULL) && !(kin_mem->kin_jacCurrent)) {
       /* If the Jacobian is out of date, update it and retry */
-      sthrsh = TWO;
+      kin_mem->kin_sthrsh = TWO;
       return(CONTINUE_ITERATIONS);
     } else {
       /* give up */
@@ -1792,56 +1692,56 @@ static int KINStop(KINMem kin_mem, booleantype maxStepTaken, int sflag)
 
   /* Check if the maximum number of iterations is reached */
 
-  if (nni >= mxiter) return(KIN_MAXITER_REACHED);
+  if (kin_mem->kin_nni >= kin_mem->kin_mxiter) return(KIN_MAXITER_REACHED);
 
   /* Check for consecutive number of steps taken of size mxnewtstep
      and if not maxStepTaken, then set ncscmx to 0 */
  
-  if (maxStepTaken) ncscmx++;
-  else              ncscmx = 0;
+  if (maxStepTaken) kin_mem->kin_ncscmx++;
+  else              kin_mem->kin_ncscmx = 0;
  
-  if (ncscmx == 5) return(KIN_MXNEWT_5X_EXCEEDED);
+  if (kin_mem->kin_ncscmx == 5) return(KIN_MXNEWT_5X_EXCEEDED);
 
   /* Proceed according to the type of linear solver used */
 
-  if (inexact_ls) {
+  if (kin_mem->kin_inexact_ls) {
 
     /* We're doing inexact Newton.
        Load threshold for reevaluating the Jacobian. */
 
-    sthrsh = rlength;
+    kin_mem->kin_sthrsh = rlength;
 
-  } else if (!noResMon) {
+  } else if (!(kin_mem->kin_noResMon)) {
 
     /* We're doing modified Newton and the user did not disable residual monitoring.
        Check if it is time to monitor residual. */
 
-    if ((nni - nnilset_sub) >= msbset_sub) {
+    if ((kin_mem->kin_nni - kin_mem->kin_nnilset_sub) >= kin_mem->kin_msbset_sub) {
 
       /* Residual monitoring needed */
 
-      nnilset_sub = nni;
+      kin_mem->kin_nnilset_sub = kin_mem->kin_nni;
 
       /* If indicated, estimate new OMEGA value */
-      if (eval_omega) {
-        omexp = SUNMAX(ZERO,(fnorm/fnormtol)-ONE);
-        omega = (omexp > TWELVE)? omega_max : SUNMIN(omega_min*SUNRexp(omexp), omega_max);
+      if (kin_mem->kin_eval_omega) {
+        omexp = SUNMAX(ZERO,((kin_mem->kin_fnorm)/(kin_mem->kin_fnormtol))-ONE);
+        kin_mem->kin_omega = (omexp > TWELVE)? kin_mem->kin_omega_max : SUNMIN(kin_mem->kin_omega_min * SUNRexp(omexp), kin_mem->kin_omega_max);
       }   
       /* Check if making satisfactory progress */
 
-      if (fnorm > omega*fnorm_sub) {
+      if (kin_mem->kin_fnorm > kin_mem->kin_omega * kin_mem->kin_fnorm_sub) {
         /* Insufficient progress */
-	if (setupNonNull && !jacCurrent) {
+	if ((kin_mem->kin_lsetup != NULL) && !(kin_mem->kin_jacCurrent)) {
           /* If the Jacobian is out of date, update it and retry */
-	  sthrsh = TWO;
+	  kin_mem->kin_sthrsh = TWO;
           return(CONTINUE_ITERATIONS);
 	} else {
           /* Otherwise, we cannot do anything, so just return. */
         }
       } else {
         /* Sufficient progress */
-	fnorm_sub = fnorm;
-	sthrsh = ONE;
+	kin_mem->kin_fnorm_sub = kin_mem->kin_fnorm;
+	kin_mem->kin_sthrsh = ONE;
       }
 
     } else {
@@ -1849,9 +1749,9 @@ static int KINStop(KINMem kin_mem, booleantype maxStepTaken, int sflag)
       /* Residual monitoring not needed */
 
       /* Reset sthrsh */
-      if (retry_nni || update_fnorm_sub) fnorm_sub = fnorm;
-      if (update_fnorm_sub) update_fnorm_sub = FALSE;
-      sthrsh = ONE;
+      if (kin_mem->kin_retry_nni || kin_mem->kin_update_fnorm_sub) kin_mem->kin_fnorm_sub = kin_mem->kin_fnorm;
+      if (kin_mem->kin_update_fnorm_sub) kin_mem->kin_update_fnorm_sub = SUNFALSE;
+      kin_mem->kin_sthrsh = ONE;
 
     }
 
@@ -1891,31 +1791,31 @@ static void KINForcingTerm(KINMem kin_mem, realtype fnormp)
 
   /* choice #1 forcing term */
 
-  if (etaflag == KIN_ETACHOICE1) {
+  if (kin_mem->kin_etaflag == KIN_ETACHOICE1) {
 
     /* compute the norm of f + Jp , scaled L2 norm */
 
-    linmodel_norm = SUNRsqrt((fnorm * fnorm) + (TWO * sFdotJp) + (sJpnorm * sJpnorm));
+    linmodel_norm = SUNRsqrt((kin_mem->kin_fnorm * kin_mem->kin_fnorm) + (TWO * kin_mem->kin_sFdotJp) + (kin_mem->kin_sJpnorm * kin_mem->kin_sJpnorm));
 
     /* form the safeguarded for choice #1 */ 
 
-    eta_safe = SUNRpowerR(eta, ealpha); 
-    eta = SUNRabs(fnormp - linmodel_norm) / fnorm;
+    eta_safe = SUNRpowerR(kin_mem->kin_eta, kin_mem->kin_eta_alpha); 
+    kin_mem->kin_eta = SUNRabs(fnormp - linmodel_norm) / kin_mem->kin_fnorm;
   }
 
   /* choice #2 forcing term */
 
-  if (etaflag == KIN_ETACHOICE2) {
-    eta_safe = egamma * SUNRpowerR(eta, ealpha); 
-    eta = egamma * SUNRpowerR((fnormp / fnorm), ealpha); 
+  if (kin_mem->kin_etaflag == KIN_ETACHOICE2) {
+    eta_safe = kin_mem->kin_eta_gamma * SUNRpowerR(kin_mem->kin_eta, kin_mem->kin_eta_alpha); 
+    kin_mem->kin_eta = kin_mem->kin_eta_gamma * SUNRpowerR((fnormp / kin_mem->kin_fnorm), kin_mem->kin_eta_alpha); 
   }
 
   /* apply safeguards */
  
   if(eta_safe < POINT1) eta_safe = ZERO;
-  eta = SUNMAX(eta, eta_safe);
-  eta = SUNMAX(eta, eta_min);
-  eta = SUNMIN(eta, eta_max);
+  kin_mem->kin_eta = SUNMAX(kin_mem->kin_eta, eta_safe);
+  kin_mem->kin_eta = SUNMAX(kin_mem->kin_eta, eta_min);
+  kin_mem->kin_eta = SUNMIN(kin_mem->kin_eta, eta_max);
 
   return; 
 }
@@ -1939,8 +1839,8 @@ static void KINForcingTerm(KINMem kin_mem, realtype fnormp)
 
 static realtype KINScFNorm(KINMem kin_mem, N_Vector v, N_Vector scale)
 {
-  N_VProd(scale, v, vtemp1);
-  return(N_VMaxNorm(vtemp1));
+  N_VProd(scale, v, kin_mem->kin_vtemp1);
+  return(N_VMaxNorm(kin_mem->kin_vtemp1));
 }
 
 /*
@@ -1954,12 +1854,12 @@ static realtype KINScSNorm(KINMem kin_mem, N_Vector v, N_Vector u)
 {
   realtype length;
 
-  N_VInv(uscale, vtemp1);
-  N_VAbs(u, vtemp2);
-  N_VLinearSum(ONE, vtemp1, ONE, vtemp2, vtemp1);
-  N_VDiv(v, vtemp1, vtemp1);
+  N_VInv(kin_mem->kin_uscale, kin_mem->kin_vtemp1);
+  N_VAbs(u, kin_mem->kin_vtemp2);
+  N_VLinearSum(ONE, kin_mem->kin_vtemp1, ONE, kin_mem->kin_vtemp2, kin_mem->kin_vtemp1);
+  N_VDiv(v, kin_mem->kin_vtemp1, kin_mem->kin_vtemp1);
 
-  length = N_VMaxNorm(vtemp1);
+  length = N_VMaxNorm(kin_mem->kin_vtemp1);
 
   return(length);
 }
@@ -2144,8 +2044,6 @@ void KINProcessError(KINMem kin_mem,
  * It sends the error message to the stream pointed to by kin_errfp 
  */
 
-#define errfp    (kin_mem->kin_errfp)
-
 void KINErrHandler(int error_code, const char *module,
                    const char *function, char *msg, void *data)
 {
@@ -2162,9 +2060,9 @@ void KINErrHandler(int error_code, const char *module,
     sprintf(err_type,"ERROR");
 
 #ifndef NO_FPRINTF_OUTPUT
-  if (errfp != NULL) {
-    fprintf(errfp,"\n[%s %s]  %s\n",module,err_type,function);
-    fprintf(errfp,"  %s\n\n",msg);
+  if (kin_mem->kin_errfp != NULL) {
+    fprintf(kin_mem->kin_errfp,"\n[%s %s]  %s\n",module,err_type,function);
+    fprintf(kin_mem->kin_errfp,"  %s\n\n",msg);
   }
 #endif
 
@@ -2196,7 +2094,7 @@ static int KINPicardAA(KINMem kin_mem, long int *iterp, realtype *R,
   delta = kin_mem->kin_vtemp1;
   gval = kin_mem->kin_gval;
   ret = CONTINUE_ITERATIONS;
-  fmax = fnormtol + ONE;
+  fmax = kin_mem->kin_fnormtol + ONE;
   iter = 0;
   epsmin = ZERO;
   fnormp = -ONE;
@@ -2204,38 +2102,38 @@ static int KINPicardAA(KINMem kin_mem, long int *iterp, realtype *R,
   N_VConst(ZERO, gval);
 
   /* if eps is to be bounded from below, set the bound */
-  if (inexact_ls && !noMinEps) epsmin = POINT01 * fnormtol;
+  if (kin_mem->kin_inexact_ls && !(kin_mem->kin_noMinEps)) epsmin = POINT01 * kin_mem->kin_fnormtol;
 
   while (ret == CONTINUE_ITERATIONS) {
 
     iter++;
 
     /* Update the forcing term for the inexact linear solves */
-    if (inexact_ls) {
-      eps = (eta + uround) * fnorm;
-      if(!noMinEps) eps = SUNMAX(epsmin, eps);
+    if (kin_mem->kin_inexact_ls) {
+      kin_mem->kin_eps = (kin_mem->kin_eta + kin_mem->kin_uround) * kin_mem->kin_fnorm;
+      if(!(kin_mem->kin_noMinEps)) kin_mem->kin_eps = SUNMAX(epsmin, kin_mem->kin_eps);
     }
 
     /* evaluate g = uu - L^{-1}func(uu) and return if failed.  
        For Picard, assume that the fval vector has been filled 
        with an eval of the nonlinear residual prior to this call. */
-    retval = KINPicardFcnEval(kin_mem, gval, uu, fval);
+    retval = KINPicardFcnEval(kin_mem, gval, kin_mem->kin_uu, kin_mem->kin_fval);
 
     if (retval < 0) {
       ret = KIN_SYSFUNC_FAIL;
       break;
     }
 
-    if (maa == 0) { 
-      N_VScale(ONE, gval, unew);
+    if (kin_mem->kin_m_aa == 0) { 
+      N_VScale(ONE, gval, kin_mem->kin_unew);
     }
     else {  /* use Anderson, if desired */
-      N_VScale(ONE, uu, unew);
-      AndersonAcc(kin_mem, gval, delta, unew, uu, (int)(iter-1), R, gamma);
+      N_VScale(ONE, kin_mem->kin_uu, kin_mem->kin_unew);
+      AndersonAcc(kin_mem, gval, delta, kin_mem->kin_unew, kin_mem->kin_uu, (int)(iter-1), R, gamma);
     }
 
     /* Fill the Newton residual based on the new solution iterate */
-    retval = func(unew, fval, user_data); nfe++;
+    retval = kin_mem->kin_func(kin_mem->kin_unew, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
     
     if (retval < 0) {
       ret = KIN_SYSFUNC_FAIL;
@@ -2243,41 +2141,41 @@ static int KINPicardAA(KINMem kin_mem, long int *iterp, realtype *R,
     }
 
     /* Evaluate function norms */
-    fnormp = N_VWL2Norm(fval,fscale);
-    fmax = KINScFNorm(kin_mem, fval, fscale); /* measure  || F(x) ||_max */
-    fnorm = fmax;
+    fnormp = N_VWL2Norm(kin_mem->kin_fval, kin_mem->kin_fscale);
+    fmax = KINScFNorm(kin_mem, kin_mem->kin_fval, kin_mem->kin_fscale); /* measure  || F(x) ||_max */
+    kin_mem->kin_fnorm = fmax;
     *fmaxptr = fmax;
     
-    if (printfl > 1) 
+    if (kin_mem->kin_printfl > 1) 
       KINPrintInfo(kin_mem, PRNT_FMAX, "KINSOL", "KINPicardAA", INFO_FMAX, fmax);
 
     /* print the current iter, fnorm, and nfe values if printfl > 0 */
-    if (printfl>0)
-      KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINPicardAA", INFO_NNI, iter, nfe, fnorm);
+    if (kin_mem->kin_printfl > 0)
+      KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINPicardAA", INFO_NNI, iter, kin_mem->kin_nfe, kin_mem->kin_fnorm);
 
     /* Check if the maximum number of iterations is reached */
-    if (iter >= mxiter) {
+    if (iter >= kin_mem->kin_mxiter) {
       ret = KIN_MAXITER_REACHED;
     }
-    if (fmax <= fnormtol) { 
+    if (fmax <= kin_mem->kin_fnormtol) { 
       ret = KIN_SUCCESS;
     }
 
     /* Update with new iterate. */
-    N_VScale(ONE, unew, uu);
+    N_VScale(ONE, kin_mem->kin_unew, kin_mem->kin_uu);
 
     if (ret == CONTINUE_ITERATIONS) { 
       /* evaluate eta by calling the forcing term routine */
-      if (callForcingTerm) KINForcingTerm(kin_mem, fnormp);
+      if (kin_mem->kin_callForcingTerm) KINForcingTerm(kin_mem, fnormp);
     }
 
-    fflush(errfp);
+    fflush(kin_mem->kin_errfp);
     
   }  /* end of loop; return */
 
   *iterp = iter;
 
-  if (printfl > 0)
+  if (kin_mem->kin_printfl > 0)
     KINPrintInfo(kin_mem, PRNT_RETVAL, "KINSOL", "KINPicardAA", INFO_RETVAL, ret);
 
   return(ret); 
@@ -2301,27 +2199,27 @@ static int KINPicardFcnEval(KINMem kin_mem, N_Vector gval, N_Vector uval, N_Vect
 {
   int retval;
 
-  if ((nni - nnilset) >= msbset) {
-    sthrsh = TWO;
-    update_fnorm_sub = TRUE;
+  if ((kin_mem->kin_nni - kin_mem->kin_nnilset) >= kin_mem->kin_msbset) {
+    kin_mem->kin_sthrsh = TWO;
+    kin_mem->kin_update_fnorm_sub = SUNTRUE;
   }
 
-  loop{
+  for(;;){
 
-    jacCurrent = FALSE;
+    kin_mem->kin_jacCurrent = SUNFALSE;
 
-    if ((sthrsh > ONEPT5) && setupNonNull) {
-      retval = lsetup(kin_mem);
-      jacCurrent = TRUE;
-      nnilset = nni;
-      nnilset_sub = nni;
+    if ((kin_mem->kin_sthrsh > ONEPT5) && (kin_mem->kin_lsetup != NULL)) {
+      retval = kin_mem->kin_lsetup(kin_mem);
+      kin_mem->kin_jacCurrent = SUNTRUE;
+      kin_mem->kin_nnilset = kin_mem->kin_nni;
+      kin_mem->kin_nnilset_sub = kin_mem->kin_nni;
       if (retval != 0) return(KIN_LSETUP_FAIL);
     }
 
     /* call the generic 'lsolve' routine to solve the system Lx = -fval
        Note that we are using gval to hold x. */
     N_VScale(-ONE, fval1, fval1);
-    retval = lsolve(kin_mem, gval, fval1, &sJpnorm, &sFdotJp);
+    retval = kin_mem->kin_lsolve(kin_mem, gval, fval1, &(kin_mem->kin_sJpnorm), &(kin_mem->kin_sFdotJp));
 
     if (retval == 0) {
       /* Update gval = uval + gval since gval = -L^{-1}F(uu)  */
@@ -2329,12 +2227,12 @@ static int KINPicardFcnEval(KINMem kin_mem, N_Vector gval, N_Vector uval, N_Vect
       return(KIN_SUCCESS);
     }
     else if (retval < 0)                      return(KIN_LSOLVE_FAIL);
-    else if ((!setupNonNull) || (jacCurrent)) return(KIN_LINSOLV_NO_RECOVERY);
+    else if ((kin_mem->kin_lsetup == NULL) || (kin_mem->kin_jacCurrent)) return(KIN_LINSOLV_NO_RECOVERY);
 
     /* loop back only if the linear solver setup is in use
        and matrix information is not current */
 
-    sthrsh = TWO;
+    kin_mem->kin_sthrsh = TWO;
   }
 
 }
@@ -2358,7 +2256,7 @@ static int KINFP(KINMem kin_mem, long int *iterp,
   
   delta = kin_mem->kin_vtemp1;
   ret = CONTINUE_ITERATIONS;
-  fmax = fnormtol + ONE;
+  fmax = kin_mem->kin_fnormtol + ONE;
   iter = 0;
 
   while (ret == CONTINUE_ITERATIONS) {
@@ -2366,38 +2264,38 @@ static int KINFP(KINMem kin_mem, long int *iterp,
     iter++;
 
     /* evaluate func(uu) and return if failed */
-    retval = func(uu, fval, user_data); nfe++;
+    retval = kin_mem->kin_func(kin_mem->kin_uu, kin_mem->kin_fval, kin_mem->kin_user_data); kin_mem->kin_nfe++;
 
     if (retval < 0) {
       ret = KIN_SYSFUNC_FAIL;
       break;
     }
 
-    if (maa == 0) { 
-      N_VScale(ONE, fval, unew);
+    if (kin_mem->kin_m_aa == 0) { 
+      N_VScale(ONE, kin_mem->kin_fval, kin_mem->kin_unew);
     }
     else {  /* use Anderson, if desired */
-      AndersonAcc(kin_mem, fval, delta, unew, uu, (int)(iter-1), R, gamma);
+      AndersonAcc(kin_mem, kin_mem->kin_fval, delta, kin_mem->kin_unew, kin_mem->kin_uu, (int)(iter-1), R, gamma);
     }
 
-    N_VLinearSum(ONE, unew, -ONE, uu, delta);
-    fmax = KINScFNorm(kin_mem, delta, fscale); /* measure  || g(x)-x || */
+    N_VLinearSum(ONE, kin_mem->kin_unew, -ONE, kin_mem->kin_uu, delta);
+    fmax = KINScFNorm(kin_mem, delta, kin_mem->kin_fscale); /* measure  || g(x)-x || */
     
-    if (printfl > 1) 
+    if (kin_mem->kin_printfl > 1) 
       KINPrintInfo(kin_mem, PRNT_FMAX, "KINSOL", "KINFP", INFO_FMAX, fmax);
     
-    fnorm = fmax;
+    kin_mem->kin_fnorm = fmax;
     *fmaxptr = fmax;
 
     /* print the current iter, fnorm, and nfe values if printfl > 0 */
-    if (printfl>0)
-      KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINFP", INFO_NNI, iter, nfe, fnorm);
+    if (kin_mem->kin_printfl > 0)
+      KINPrintInfo(kin_mem, PRNT_NNI, "KINSOL", "KINFP", INFO_NNI, iter, kin_mem->kin_nfe, kin_mem->kin_fnorm);
 
     /* Check if the maximum number of iterations is reached */
-    if (iter >= mxiter) {
+    if (iter >= kin_mem->kin_mxiter) {
       ret = KIN_MAXITER_REACHED;
     }
-    if (fmax <= fnormtol) { 
+    if (fmax <= kin_mem->kin_fnormtol) { 
       ret = KIN_SUCCESS;
     }
     
@@ -2405,16 +2303,16 @@ static int KINFP(KINMem kin_mem, long int *iterp,
       /* Only update solution if taking a next iteration.  */
       /* CSW  Should put in a conditional to send back the newest iterate or
 	 the one consistent with the fval */
-      N_VScale(ONE, unew, uu);
+      N_VScale(ONE, kin_mem->kin_unew, kin_mem->kin_uu);
     }
 
-    fflush(errfp);
+    fflush(kin_mem->kin_errfp);
     
   }  /* end of loop; return */
 
   *iterp = iter;
 
-  if (printfl > 0)
+  if (kin_mem->kin_printfl > 0)
     KINPrintInfo(kin_mem, PRNT_RETVAL, "KINSOL", "KINFP", INFO_RETVAL, ret);
 
   return(ret); 
@@ -2443,83 +2341,83 @@ static int AndersonAcc(KINMem kin_mem, N_Vector gval, N_Vector fv,
   realtype a, b, temp, c, s;
 
   ipt_map = kin_mem->kin_ipt_map;
-  i_pt = iter-1 - ((iter-1)/maa)*maa;
+  i_pt = iter-1 - ((iter-1)/kin_mem->kin_m_aa)*kin_mem->kin_m_aa;
   N_VLinearSum(ONE, gval, -1.0, xold, fv);
   if (iter > 0) {
     /* compute dg_new = gval -gval_old*/
-    N_VLinearSum(ONE, gval, -1.0, gold, dg[i_pt]);
+    N_VLinearSum(ONE, gval, -1.0, kin_mem->kin_gold_aa, kin_mem->kin_dg_aa[i_pt]);
     /* compute df_new = fval - fval_old */
-    N_VLinearSum(ONE, fv, -1.0, fold, df[i_pt]);
+    N_VLinearSum(ONE, fv, -1.0, kin_mem->kin_fold_aa, kin_mem->kin_df_aa[i_pt]);
   }
 
-  N_VScale(ONE, gval, gold);
-  N_VScale(ONE, fv, fold);
+  N_VScale(ONE, gval, kin_mem->kin_gold_aa);
+  N_VScale(ONE, fv, kin_mem->kin_fold_aa);
 
   if (iter == 0) {
     N_VScale(ONE, gval, x);
   }
   else {
     if (iter == 1) {
-      R[0] = sqrt(N_VDotProd(df[i_pt],df[i_pt]));
+      R[0] = sqrt(N_VDotProd(kin_mem->kin_df_aa[i_pt], kin_mem->kin_df_aa[i_pt]));
       alfa = 1/R[0];
-      N_VScale(alfa,df[i_pt],Q[i_pt]);
+      N_VScale(alfa, kin_mem->kin_df_aa[i_pt], kin_mem->kin_q_aa[i_pt]);
       ipt_map[0] = 0;
     }
-    else if (iter <= maa) {
-      N_VScale(ONE,df[i_pt],vtemp2);
+    else if (iter <= kin_mem->kin_m_aa) {
+      N_VScale(ONE, kin_mem->kin_df_aa[i_pt], kin_mem->kin_vtemp2);
       for (j=0; j < (iter-1); j++) {
         ipt_map[j] = j;
-        R[(iter-1)*maa+j] = N_VDotProd(Q[j],vtemp2);
-        N_VLinearSum(ONE,vtemp2,-R[(iter-1)*maa+j],Q[j],vtemp2);
+        R[(iter-1)*kin_mem->kin_m_aa+j] = N_VDotProd(kin_mem->kin_q_aa[j], kin_mem->kin_vtemp2);
+        N_VLinearSum(ONE,kin_mem->kin_vtemp2, -R[(iter-1)*kin_mem->kin_m_aa+j], kin_mem->kin_q_aa[j], kin_mem->kin_vtemp2);
       }
-      R[(iter-1)*maa+iter-1] = sqrt(N_VDotProd(vtemp2,vtemp2));
-      N_VScale((1/R[(iter-1)*maa+iter-1]),vtemp2,Q[i_pt]);
+      R[(iter-1)*kin_mem->kin_m_aa+iter-1] = sqrt(N_VDotProd(kin_mem->kin_vtemp2, kin_mem->kin_vtemp2));
+      N_VScale((1/R[(iter-1)*kin_mem->kin_m_aa+iter-1]), kin_mem->kin_vtemp2, kin_mem->kin_q_aa[i_pt]);
       ipt_map[iter-1] = iter-1;
     }
     else {
       /* Delete left-most column vector from QR factorization */
-      for (i=0; i < maa-1; i++) {
-        a = R[(i+1)*maa + i];
-        b = R[(i+1)*maa + i+1];
+      for (i=0; i < kin_mem->kin_m_aa-1; i++) {
+        a = R[(i+1)*kin_mem->kin_m_aa + i];
+        b = R[(i+1)*kin_mem->kin_m_aa + i+1];
         temp = sqrt(a*a + b*b);
         c = a / temp;
         s = b / temp;
-        R[(i+1)*maa + i] = temp;
-        R[(i+1)*maa + i+1] = 0.0;
+        R[(i+1)*kin_mem->kin_m_aa + i] = temp;
+        R[(i+1)*kin_mem->kin_m_aa + i+1] = 0.0;
 	/* OK to re-use temp */
-        if (i < maa-1) {
-          for (j = i+2; j < maa; j++) {
-            a = R[j*maa + i];
-            b = R[j*maa + i+1];
+        if (i < kin_mem->kin_m_aa-1) {
+          for (j = i+2; j < kin_mem->kin_m_aa; j++) {
+            a = R[j*kin_mem->kin_m_aa + i];
+            b = R[j*kin_mem->kin_m_aa + i+1];
             temp = c * a + s * b;
-            R[j*maa + i+1] = -s*a + c*b;
-            R[j*maa + i] = temp;
+            R[j*kin_mem->kin_m_aa + i+1] = -s*a + c*b;
+            R[j*kin_mem->kin_m_aa + i] = temp;
 	  }
 	}
-        N_VLinearSum(c, Q[i], s, Q[i+1], vtemp2);
-        N_VLinearSum(-s, Q[i], c, Q[i+1], Q[i+1]);
-        N_VScale(ONE, vtemp2, Q[i]);
+        N_VLinearSum(c, kin_mem->kin_q_aa[i], s, kin_mem->kin_q_aa[i+1], kin_mem->kin_vtemp2);
+        N_VLinearSum(-s, kin_mem->kin_q_aa[i], c, kin_mem->kin_q_aa[i+1], kin_mem->kin_q_aa[i+1]);
+        N_VScale(ONE, kin_mem->kin_vtemp2, kin_mem->kin_q_aa[i]);
       }
 
       /* Shift R to the left by one. */
-      for (i = 1; i < maa; i++) {
-        for (j = 0; j < maa-1; j++) {
-          R[(i-1)*maa + j] = R[i*maa + j];
+      for (i = 1; i < kin_mem->kin_m_aa; i++) {
+        for (j = 0; j < kin_mem->kin_m_aa-1; j++) {
+          R[(i-1)*kin_mem->kin_m_aa + j] = R[i*kin_mem->kin_m_aa + j];
         }
       }
 
       /* Add the new df vector */
-      N_VScale(ONE,df[i_pt],vtemp2);
-      for (j=0; j < (maa-1); j++) {
-        R[(maa-1)*maa+j] = N_VDotProd(Q[j],vtemp2);
-        N_VLinearSum(ONE,vtemp2,-R[(maa-1)*maa+j],Q[j],vtemp2);
+      N_VScale(ONE, kin_mem->kin_df_aa[i_pt], kin_mem->kin_vtemp2);
+      for (j=0; j < (kin_mem->kin_m_aa-1); j++) {
+        R[(kin_mem->kin_m_aa-1)*kin_mem->kin_m_aa+j] = N_VDotProd(kin_mem->kin_q_aa[j], kin_mem->kin_vtemp2);
+        N_VLinearSum(ONE, kin_mem->kin_vtemp2, -R[(kin_mem->kin_m_aa-1)*kin_mem->kin_m_aa+j], kin_mem->kin_q_aa[j],kin_mem->kin_vtemp2);
       }
-      R[(maa-1)*maa+maa-1] = sqrt(N_VDotProd(vtemp2,vtemp2));
-      N_VScale((1/R[(maa-1)*maa+maa-1]),vtemp2,Q[maa-1]);
+      R[(kin_mem->kin_m_aa-1)*kin_mem->kin_m_aa+kin_mem->kin_m_aa-1] = sqrt(N_VDotProd(kin_mem->kin_vtemp2, kin_mem->kin_vtemp2));
+      N_VScale((1/R[(kin_mem->kin_m_aa-1)*kin_mem->kin_m_aa+kin_mem->kin_m_aa-1]), kin_mem->kin_vtemp2, kin_mem->kin_q_aa[kin_mem->kin_m_aa-1]);
 
       /* Update the iteration map */
       j = 0;
-      for (i=i_pt+1; i < maa; i++)
+      for (i=i_pt+1; i < kin_mem->kin_m_aa; i++)
         ipt_map[j++] = i;
       for (i=0; i < (i_pt+1); i++)
         ipt_map[j++] = i;
@@ -2527,16 +2425,16 @@ static int AndersonAcc(KINMem kin_mem, N_Vector gval, N_Vector fv,
 
     /* Solve least squares problem and update solution */
     lAA = iter;
-    if (maa < iter) lAA = maa;
+    if (kin_mem->kin_m_aa < iter) lAA = kin_mem->kin_m_aa;
     N_VScale(ONE, gval, x);
     for (i=0; i < lAA; i++)
-      gamma[i] = N_VDotProd(fv,Q[i]);
+      gamma[i] = N_VDotProd(fv, kin_mem->kin_q_aa[i]);
     for (i=lAA-1; i > -1; i--) {
       for (j=i+1; j < lAA; j++) {
-        gamma[i] = gamma[i]-R[j*maa+i]*gamma[j]; 
+        gamma[i] = gamma[i]-R[j*kin_mem->kin_m_aa+i]*gamma[j]; 
       }
-      gamma[i] = gamma[i]/R[i*maa+i];
-      N_VLinearSum(ONE,x,-gamma[i],dg[ipt_map[i]],x);
+      gamma[i] = gamma[i]/R[i*kin_mem->kin_m_aa+i];
+      N_VLinearSum(ONE, x, -gamma[i], kin_mem->kin_dg_aa[ipt_map[i]], x);
     }
   }
 
diff --git a/src/kinsol/kinsol_band.c b/src/kinsol/kinsol_band.c
deleted file mode 100644
index 79b7109..0000000
--- a/src/kinsol/kinsol_band.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINBAND linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <kinsol/kinsol_band.h>
-#include "kinsol_direct_impl.h"
-#include "kinsol_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/* KINBAND linit, lsetup, lsolve, and lfree routines */
-static int kinBandInit(KINMem kin_mem);
-static int kinBandSetup(KINMem kin_mem);
-static int kinBandsolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                        realtype *sJpnorm, realtype *sFdotJp);
-static int kinBandFree(KINMem kin_mem);
-
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define lrw1           (kin_mem->kin_lrw1)
-#define liw1           (kin_mem->kin_liw1)
-#define func           (kin_mem->kin_func)
-#define printfl        (kin_mem->kin_printfl)
-#define linit          (kin_mem->kin_linit)
-#define lsetup         (kin_mem->kin_lsetup)
-#define lsolve         (kin_mem->kin_lsolve)
-#define lfree          (kin_mem->kin_lfree)
-#define lmem           (kin_mem->kin_lmem)
-#define inexact_ls     (kin_mem->kin_inexact_ls)
-#define uu             (kin_mem->kin_uu)
-#define fval           (kin_mem->kin_fval)
-#define uscale         (kin_mem->kin_uscale)
-#define fscale         (kin_mem->kin_fscale)
-#define sqrt_relfunc   (kin_mem->kin_sqrt_relfunc)
-#define errfp          (kin_mem->kin_errfp)
-#define infofp         (kin_mem->kin_infofp)
-#define setupNonNull   (kin_mem->kin_setupNonNull)
-#define vtemp1         (kin_mem->kin_vtemp1)
-#define vec_tmpl       (kin_mem->kin_vtemp1)
-#define vtemp2         (kin_mem->kin_vtemp2)
-#define strategy       (kin_mem->kin_globalstrategy)
-
-#define mtype          (kindls_mem->d_type)
-#define n              (kindls_mem->d_n)
-#define ml             (kindls_mem->d_ml)
-#define mu             (kindls_mem->d_mu)
-#define smu            (kindls_mem->d_smu)
-#define jacDQ          (kindls_mem->d_jacDQ)
-#define bjac           (kindls_mem->d_bjac)
-#define J              (kindls_mem->d_J)
-#define lpivots        (kindls_mem->d_lpivots)
-#define nje            (kindls_mem->d_nje)
-#define nfeDQ          (kindls_mem->d_nfeDQ)
-#define J_data         (kindls_mem->d_J_data)
-#define last_flag      (kindls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * KINBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module.  KINBand first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * cv_linit, cv_lsetup, cv_lsolve, and cv_lfree fields in (*cvode_mem)
- * to be kinBandInit, kinBandSetup, kinBandsolve, and kinBandFree,
- * respectively.  It allocates memory for a structure of type
- * KINDlsMemRec and sets the cv_lmem field in (*cvode_mem) to the
- * address of this structure.  It sets setupNonNull in (*cvode_mem) to be
- * TRUE, b_mu to be mupper, b_ml to be mlower, and the bjac field to be 
- * kinDlsBandDQJac.
- * Finally, it allocates memory for M, savedJ, and pivot.
- *
- * NOTE: The band linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, KINBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-                  
-int KINBand(void *kinmem, long int N, long int mupper, long int mlower)
-{
-  KINMem kin_mem;
-  KINDlsMem kindls_mem;
-
-  /* Return immediately if kinmem is NULL */
-  if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINBAND", "KINBand", MSGD_KINMEM_NULL);
-    return(KINDLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL) {
-    KINProcessError(kin_mem, KINDLS_ILL_INPUT, "KINBAND", "KINBand", MSGD_BAD_NVECTOR);
-    return(KINDLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(kin_mem);
-
-  /* Set four main function fields in kin_mem */  
-  linit  = kinBandInit;
-  lsetup = kinBandSetup;
-  lsolve = kinBandsolve;
-  lfree  = kinBandFree;
-  
-  /* Get memory for KINDlsMemRec */
-  kindls_mem = NULL;
-  kindls_mem = (KINDlsMem) malloc(sizeof(struct KINDlsMemRec));
-  if (kindls_mem == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINBAND", "KINBand", MSGD_MEM_FAIL);
-    return(KINDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;  
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  bjac   = NULL;
-  J_data = NULL;
-  last_flag = KINDLS_SUCCESS;
-
-  kinDlsInitializeCounters(kindls_mem);
-
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = N;
-
-  /* Load half-bandwiths in kindls_mem */
-  ml = mlower;
-  mu = mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= N) || (mu >= N)) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINBAND", "KINBand", MSGD_MEM_FAIL);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = SUNMIN(N-1, mu + ml);
-
-  /* Allocate memory for J and pivot array */
-  J = NULL;
-  J = NewBandMat(N, mu, ml, smu);
-  if (J == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINBAND", "KINBand", MSGD_MEM_FAIL);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  lpivots = NULL;
-  lpivots = NewLintArray(N);
-  if (lpivots == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINBAND", "KINBand", MSGD_MEM_FAIL);
-    DestroyMat(J);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  /* This is a direct linear solver */
-  inexact_ls = FALSE;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = kindls_mem;
-
-  return(KINDLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * kinBandInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the band
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinBandInit(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  kinDlsInitializeCounters(kindls_mem);
-
-  if (jacDQ) {
-    bjac = kinDlsBandDQJac;
-    J_data = kin_mem;
-  } else {
-    J_data = kin_mem->kin_user_data;
-  }
-
-  /* Stop Picard solve if user fails to provide Jacobian */
-  if ( (strategy == KIN_PICARD) && jacDQ )
-    {
-      KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "kinBandInit", 
-		      MSG_NOL_FAIL);
-      return(KIN_ILL_INPUT);
-    }
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinBandSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the band linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy.  In any case, it constructs the Newton matrix J,
- * updates counters, and calls the band LU factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int kinBandSetup(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-  int retval;
-  long int ier;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  nje++;
-  SetToZero(J); 
-  retval = bjac(n, mu, ml, uu, fval, J, J_data, vtemp1, vtemp2);
-  if (retval != 0) {
-    last_flag = -1;
-    return(-1);
-  }
-  
-  /* Do LU factorization of J */
-  ier = BandGBTRF(J, lpivots);
-
-  /* Return 0 if the LU was complete; otherwise return -1 */
-  last_flag = ier;
-  if (ier > 0) return(-1);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinBandsolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the band linear solver
- * by calling the band backsolve routine.  The return value is 0.
- * The argument *sJpnorm is ignored.
- * -----------------------------------------------------------------
- */
-
-static int kinBandsolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                        realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINDlsMem kindls_mem;
-  realtype *xd;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  /* Copy the right-hand side into x */
-
-  N_VScale(ONE, b, x);
-  
-  xd = N_VGetArrayPointer(x);
-
-  /* Back-solve and get solution in x */
-
-  BandGBTRS(J, lpivots, xd);
-
-  /* Compute the term sFdotJp for use in the linesearch routine.
-     This term is subsequently corrected if the step is reduced by
-     constraints or the linesearch.
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  N_VProd(b, fscale, b);
-  N_VProd(b, fscale, b);
-  *sFdotJp = N_VDotProd(fval, b);
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinBandFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the band linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinBandFree(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  DestroyMat(J);
-  DestroyArray(lpivots);
-  free(kindls_mem); kindls_mem = NULL;
-
-  return(0);
-}
-
diff --git a/src/kinsol/kinsol_bbdpre.c b/src/kinsol/kinsol_bbdpre.c
index 05e880a..047540a 100644
--- a/src/kinsol/kinsol_bbdpre.c
+++ b/src/kinsol/kinsol_bbdpre.c
@@ -1,244 +1,313 @@
-/*
- *-----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- *-----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
- *-----------------------------------------------------------------
- * Copyright (c) 2002, The Regents of the University of California.
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
  * For details, see the LICENSE file.
- *-----------------------------------------------------------------
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
  * This file contains implementations of routines for a
  * band-block-diagonal preconditioner, i.e. a block-diagonal
- * matrix with banded blocks, for use with KINSol, KINSp*
- * and the parallel implementation of NVECTOR.
+ * matrix with banded blocks, for use with KINSol and the 
+ * KINSPILS linear solver interface.
  *
  * Note: With only one process, a banded matrix results
  * rather than a b-b-d matrix with banded blocks. Diagonal
  * blocking occurs at the process level.
- *-----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <kinsol/kinsol_sptfqmr.h>
-#include <kinsol/kinsol_spbcgs.h>
-#include <kinsol/kinsol_spgmr.h>
-
 #include "kinsol_impl.h"
 #include "kinsol_spils_impl.h"
 #include "kinsol_bbdpre_impl.h"
 
 #include <sundials/sundials_math.h>
-
-/*
- *-----------------------------------------------------------------
- * private constants
- *-----------------------------------------------------------------
- */
+#include <nvector/nvector_serial.h>
 
 #define ZERO RCONST(0.0)
 #define ONE  RCONST(1.0)
 
-/* Prototypes for functions KINBBDPrecSetup and KINBBDPrecSolve */
-
+/* Prototypes of functions KINBBDPrecSetup and KINBBDPrecSolve */
 static int KINBBDPrecSetup(N_Vector uu, N_Vector uscale,
                            N_Vector fval, N_Vector fscale, 
-                           void *p_data,
-                           N_Vector vtemp1, N_Vector vtemp2);
+                           void *pdata);
 
 static int KINBBDPrecSolve(N_Vector uu, N_Vector uscale,
                            N_Vector fval, N_Vector fscale, 
-                           N_Vector vv, void *p_data,
-                           N_Vector vtemp);
+                           N_Vector vv, void *pdata);
 
 /* Prototype for KINBBDPrecFree */
-
 static int KINBBDPrecFree(KINMem kin_mem);
 
 /* Prototype for difference quotient jacobian calculation routine */
-
 static int KBBDDQJac(KBBDPrecData pdata,
                      N_Vector uu, N_Vector uscale,
                      N_Vector gu, N_Vector gtemp, N_Vector utemp);
 
-/*
- *-----------------------------------------------------------------
- * redability replacements
- *-----------------------------------------------------------------
- */
-
-#define errfp    (kin_mem->kin_errfp)
-#define uround   (kin_mem->kin_uround)
-#define vec_tmpl (kin_mem->kin_vtemp1)
-
-/*
- *-----------------------------------------------------------------
- * user-callable functions
- *-----------------------------------------------------------------
- */
-
-/*
- *-----------------------------------------------------------------
- * Function : KINBBDPrecInit
- *-----------------------------------------------------------------
- */
-
-int KINBBDPrecInit(void *kinmem, long int Nlocal, 
-                   long int mudq, long int mldq,
-                   long int mukeep, long int mlkeep,
+/*------------------------------------------------------------------
+  user-callable functions
+  ------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------
+  KINBBDPrecInit
+  ------------------------------------------------------------------*/
+int KINBBDPrecInit(void *kinmem, sunindextype Nlocal, 
+                   sunindextype mudq, sunindextype mldq,
+                   sunindextype mukeep, sunindextype mlkeep,
                    realtype dq_rel_uu, 
-                   KINLocalFn gloc, KINCommFn gcomm)
+                   KINBBDLocalFn gloc, KINBBDCommFn gcomm)
 {
-  KBBDPrecData pdata;
-  KINSpilsMem kinspils_mem;
   KINMem kin_mem;
-  N_Vector vtemp3;
-  long int muk, mlk, storage_mu;
+  KINSpilsMem kinspils_mem;
+  KBBDPrecData pdata;
+  sunindextype muk, mlk, storage_mu, lrw1, liw1;
+  long int lrw, liw;
   int flag;
 
-  pdata = NULL;
-
   if (kinmem == NULL) {
-    KINProcessError(NULL, 0, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_MEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
 
-  /* Test if one of the SPILS linear solvers has been attached */
+  /* Test if the SPILS linear solver interface has been created */
   if (kin_mem->kin_lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_LMEM_NULL);
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
   kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
-  /* Test if the NVECTOR package is compatible with BLOCK BAND preconditioner.
-     Note: do NOT need to check for N_VScale since it is required by KINSOL and
-     so has already been checked for (see KINMalloc) */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL) {
-    KINProcessError(kin_mem, KINSPILS_ILL_INPUT, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_BAD_NVECTOR);
+  /* Test compatibility of NVECTOR package with the BBD preconditioner */
+  /* Note: Do NOT need to check for N_VScale since has already been checked for in KINSOL */
+  if (kin_mem->kin_vtemp1->ops->nvgetarraypointer == NULL) {
+    KINProcessError(kin_mem, KINSPILS_ILL_INPUT, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_BAD_NVECTOR);
     return(KINSPILS_ILL_INPUT);
   }
 
+  /* Allocate data memory */
   pdata = NULL;
-  pdata = (KBBDPrecData) malloc(sizeof *pdata);  /* allocate data memory */
+  pdata = (KBBDPrecData) malloc(sizeof *pdata);
   if (pdata == NULL) {
-    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL,
+                    "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_FAIL);
     return(KINSPILS_MEM_FAIL);
   }
 
-  /* set pointers to gloc and gcomm and load half-bandwiths */
-
+  /* Set pointers to gloc and gcomm; load half-bandwidths */
   pdata->kin_mem = kinmem;
   pdata->gloc = gloc;
   pdata->gcomm = gcomm;
   pdata->mudq = SUNMIN(Nlocal-1, SUNMAX(0, mudq));
   pdata->mldq = SUNMIN(Nlocal-1, SUNMAX(0, mldq));
-  muk = SUNMIN(Nlocal-1, SUNMAX(0,mukeep));
-  mlk = SUNMIN(Nlocal-1, SUNMAX(0,mlkeep));
+  muk = SUNMIN(Nlocal-1, SUNMAX(0, mukeep));
+  mlk = SUNMIN(Nlocal-1, SUNMAX(0, mlkeep));
   pdata->mukeep = muk;
   pdata->mlkeep = mlk;
 
-  /* allocate memory for preconditioner matrix */
-
+  /* Set extended upper half-bandwidth for PP (required for pivoting) */
   storage_mu = SUNMIN(Nlocal-1, muk+mlk);
+
+  /* Allocate memory for preconditioner matrix */
   pdata->PP = NULL;
-  pdata->PP = NewBandMat(Nlocal, muk, mlk, storage_mu);
+  pdata->PP = SUNBandMatrix(Nlocal, muk, mlk, storage_mu);
   if (pdata->PP == NULL) {
     free(pdata); pdata = NULL;
-    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_MEM_FAIL);
     return(KINSPILS_MEM_FAIL);
   }
 
-  /* allocate memory for lpivots */
+  /* Allocate memory for temporary N_Vectors */
+  pdata->zlocal = NULL;
+  pdata->zlocal = N_VNew_Serial(Nlocal);
+  if (pdata->zlocal == NULL) {
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE", 
+                    "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(KINSPILS_MEM_FAIL);
+  }
 
-  pdata->lpivots = NULL;
-  pdata->lpivots = NewLintArray(Nlocal);
-  if (pdata->lpivots == NULL) {
-    DestroyMat(pdata->PP);
+  pdata->rlocal = NULL;
+  pdata->rlocal = N_VNewEmpty_Serial(Nlocal); /* empty vector */
+  if (pdata->rlocal == NULL) {
+    N_VDestroy(pdata->zlocal);
+    SUNMatDestroy(pdata->PP);
     free(pdata); pdata = NULL;
-    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_MEM_FAIL);
     return(KINSPILS_MEM_FAIL);
   }
 
-  /* allocate vtemp3 for use by KBBDDQJac routine */
+  pdata->tempv1 = NULL;
+  pdata->tempv1 = N_VClone(kin_mem->kin_vtemp1);
+  if (pdata->tempv1 == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(KINSPILS_MEM_FAIL);
+  }
 
-  vtemp3 = NULL;
-  vtemp3 = N_VClone(kin_mem->kin_vtemp1);
-  if (vtemp3 == NULL) {
-    DestroyArray(pdata->lpivots);
-    DestroyMat(pdata->PP);
+  pdata->tempv2 = NULL;
+  pdata->tempv2 = N_VClone(kin_mem->kin_vtemp1);
+  if (pdata->tempv2 == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    SUNMatDestroy(pdata->PP);
     free(pdata); pdata = NULL;
-    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE", "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_MEM_FAIL);
     return(KINSPILS_MEM_FAIL);
   }
-  pdata->vtemp3 = vtemp3;
 
-  /* set rel_uu based on input value dq_rel_uu */
+  pdata->tempv3 = NULL;
+  pdata->tempv3 = N_VClone(kin_mem->kin_vtemp1);
+  if (pdata->tempv3 == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(KINSPILS_MEM_FAIL);
+  }
 
-  if (dq_rel_uu > ZERO) pdata->rel_uu = dq_rel_uu;
-  else pdata->rel_uu = SUNRsqrt(uround);  /* using dq_rel_uu = 0.0 means use default */
+  /* Allocate memory for banded linear solver */
+  pdata->LS = NULL;
+  pdata->LS = SUNBandLinearSolver(pdata->zlocal, pdata->PP);
+  if (pdata->LS == NULL) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    SUNMatDestroy(pdata->PP);
+    free(pdata); pdata = NULL;
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_MEM_FAIL);
+    return(KINSPILS_MEM_FAIL);
+  }
 
-  /* store Nlocal to be used by the preconditioner routines */
+  /* initialize band linear solver object */
+  flag = SUNLinSolInitialize(pdata->LS);
+  if (flag != SUNLS_SUCCESS) {
+    N_VDestroy(pdata->zlocal);
+    N_VDestroy(pdata->rlocal);
+    N_VDestroy(pdata->tempv1);
+    N_VDestroy(pdata->tempv2);
+    N_VDestroy(pdata->tempv3);
+    SUNMatDestroy(pdata->PP);
+    SUNLinSolFree(pdata->LS);
+    free(pdata); pdata = NULL;
+    KINProcessError(kin_mem, KINSPILS_SUNLS_FAIL, "KINBBDPRE",
+                    "KINBBDPrecInit", MSGBBD_SUNLS_FAIL);
+    return(KINSPILS_SUNLS_FAIL);
+  }
 
-  pdata->n_local = Nlocal;
+  /* Set rel_uu based on input value dq_rel_uu (0 implies default) */
+  pdata->rel_uu = (dq_rel_uu > ZERO) ? dq_rel_uu : SUNRsqrt(kin_mem->kin_uround);
 
-  /* set work space sizes and initialize nge */
+  /* Store Nlocal to be used in KINBBDPrecSetup */
+  pdata->n_local = Nlocal;
 
-  pdata->rpwsize = Nlocal * (storage_mu*mlk + 1) + 1;
-  pdata->ipwsize = Nlocal + 1;
+  /* Set work space sizes and initialize nge */
+  pdata->rpwsize = 0;
+  pdata->ipwsize = 0;
+  if (kin_mem->kin_vtemp1->ops->nvspace) {
+    N_VSpace(kin_mem->kin_vtemp1, &lrw1, &liw1);
+    pdata->rpwsize += 3*lrw1;
+    pdata->ipwsize += 3*liw1;
+  }
+  if (pdata->zlocal->ops->nvspace) {
+    N_VSpace(pdata->zlocal, &lrw1, &liw1);
+    pdata->rpwsize += lrw1;
+    pdata->ipwsize += liw1;
+  }
+  if (pdata->rlocal->ops->nvspace) {
+    N_VSpace(pdata->rlocal, &lrw1, &liw1);
+    pdata->rpwsize += lrw1;
+    pdata->ipwsize += liw1;
+  }
+  if (pdata->PP->ops->space) {
+    flag = SUNMatSpace(pdata->PP, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
+  if (pdata->LS->ops->space) {
+    flag = SUNLinSolSpace(pdata->LS, &lrw, &liw);
+    pdata->rpwsize += lrw;
+    pdata->ipwsize += liw;
+  }
   pdata->nge = 0;
 
-  /* make sure s_P_data is free from any previous allocations */
-  if (kinspils_mem->s_pfree != NULL) {
-    kinspils_mem->s_pfree(kin_mem);
-  }
+  /* make sure pdata is free from any previous allocations */
+  if (kinspils_mem->pfree != NULL)
+    kinspils_mem->pfree(kin_mem);
 
-  /* Point to the new P_data field in the SPILS memory */
-  kinspils_mem->s_P_data = pdata;
+  /* Point to the new pdata field in the SPILS memory */
+  kinspils_mem->pdata = pdata;
 
   /* Attach the pfree function */
-  kinspils_mem->s_pfree = KINBBDPrecFree;
+  kinspils_mem->pfree = KINBBDPrecFree;
 
   /* Attach preconditioner solve and setup functions */
-  flag = KINSpilsSetPreconditioner(kinmem, KINBBDPrecSetup, KINBBDPrecSolve);
+  flag = KINSpilsSetPreconditioner(kinmem,
+                                   KINBBDPrecSetup,
+                                   KINBBDPrecSolve);
 
   return(flag);
 }
 
-/*
- *-----------------------------------------------------------------
- * Function : KINBBDPrecGetWorkSpace
- *-----------------------------------------------------------------
- */
 
-int KINBBDPrecGetWorkSpace(void *kinmem, long int *lenrwBBDP, long int *leniwBBDP)
+/*------------------------------------------------------------------
+  KINBBDPrecGetWorkSpace
+  ------------------------------------------------------------------*/
+int KINBBDPrecGetWorkSpace(void *kinmem,
+                           long int *lenrwBBDP,
+                           long int *leniwBBDP)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
   KBBDPrecData pdata;
 
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINBBDPRE", "KINBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecGetWorkSpace", MSGBBD_MEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
 
   if (kin_mem->kin_lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINBBDPRE", "KINBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecGetWorkSpace", MSGBBD_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
   kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
-  if (kinspils_mem->s_P_data == NULL) {
-    KINProcessError(kin_mem, KINSPILS_PMEM_NULL, "KINBBDPRE", "KINBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
+  if (kinspils_mem->pdata == NULL) {
+    KINProcessError(kin_mem, KINSPILS_PMEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecGetWorkSpace", MSGBBD_PMEM_NULL);
     return(KINSPILS_PMEM_NULL);
   } 
-  pdata = (KBBDPrecData) kinspils_mem->s_P_data;
+  pdata = (KBBDPrecData) kinspils_mem->pdata;
 
   *lenrwBBDP = pdata->rpwsize;
   *leniwBBDP = pdata->ipwsize;
@@ -246,205 +315,186 @@ int KINBBDPrecGetWorkSpace(void *kinmem, long int *lenrwBBDP, long int *leniwBBD
   return(KINSPILS_SUCCESS);
 }
 
-/*
- *-----------------------------------------------------------------
- * Function : KINBBDPrecGetNumGfnEvals
- *-----------------------------------------------------------------
- */
-
-int KINBBDPrecGetNumGfnEvals(void *kinmem, long int *ngevalsBBDP)
+/*------------------------------------------------------------------
+ KINBBDPrecGetNumGfnEvals
+ -------------------------------------------------------------------*/
+int KINBBDPrecGetNumGfnEvals(void *kinmem,
+                             long int *ngevalsBBDP)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
   KBBDPrecData pdata;
 
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINBBDPRE", "KINBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecGetNumGfnEvals", MSGBBD_MEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
 
   if (kin_mem->kin_lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINBBDPRE", "KINBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecGetNumGfnEvals", MSGBBD_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
   kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
-  if (kinspils_mem->s_P_data == NULL) {
-    KINProcessError(kin_mem, KINSPILS_PMEM_NULL, "KINBBDPRE", "KINBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
+  if (kinspils_mem->pdata == NULL) {
+    KINProcessError(kin_mem, KINSPILS_PMEM_NULL, "KINBBDPRE",
+                    "KINBBDPrecGetNumGfnEvals", MSGBBD_PMEM_NULL);
     return(KINSPILS_PMEM_NULL);
   } 
-  pdata = (KBBDPrecData) kinspils_mem->s_P_data;
+  pdata = (KBBDPrecData) kinspils_mem->pdata;
 
   *ngevalsBBDP = pdata->nge;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- *-----------------------------------------------------------------
- * preconditioner setup and solve functions
- *-----------------------------------------------------------------
- */
- 
-/*
- *-----------------------------------------------------------------
- * readability replacements
- *-----------------------------------------------------------------
- */
-
-#define Nlocal  (pdata->n_local)
-#define mudq    (pdata->mudq)
-#define mldq    (pdata->mldq)
-#define mukeep  (pdata->mukeep)
-#define mlkeep  (pdata->mlkeep)
-#define gloc    (pdata->gloc)
-#define gcomm   (pdata->gcomm)
-#define lpivots (pdata->lpivots)
-#define PP      (pdata->PP)
-#define vtemp3  (pdata->vtemp3)
-#define nge     (pdata->nge)
-#define rel_uu  (pdata->rel_uu)
-
-/*
- *-----------------------------------------------------------------
- * Function : KINBBDPrecSetup
- *-----------------------------------------------------------------
- * KINBBDPrecSetup generates and factors a banded block of the
- * preconditioner matrix on each processor, via calls to the
- * user-supplied gloc and gcomm functions. It uses difference
- * quotient approximations to the Jacobian elements.
- *
- * KINBBDPrecSetup calculates a new Jacobian, stored in banded
- * matrix PP and does an LU factorization of P in place in PP.
- *
- * The parameters of KINBBDPrecSetup are as follows:
- *
- * uu      is the current value of the dependent variable vector,
- *         namely the solutin to func(uu)=0
- *
- * uscale  is the dependent variable scaling vector (i.e. uu)
- *
- * fval    is the vector f(u)
- *
- * fscale  is the function scaling vector
- *
- * bbd_data is the pointer to BBD data set by IDABBDInit.
- *
- * vtemp1, vtemp2 are pointers to memory allocated for vectors of
- *                length N which are be used by KINBBDPrecSetup
- *                as temporary storage or work space. A third
- *                vector (vtemp3) required for KINBBDPrecSetup
- *                was previously allocated as pdata->vtemp3.
- *
- * Note: The value to be returned by the KINBBDPrecSetup function
- * is a flag indicating whether it was successful. This value is:
- *   0 if successful,
- *   > 0 for a recoverable error - step will be retried.
- *-----------------------------------------------------------------
- */
 
+/*------------------------------------------------------------------
+  KINBBDPrecSetup
+
+  KINBBDPrecSetup generates and factors a banded block of the
+  preconditioner matrix on each processor, via calls to the
+  user-supplied gloc and gcomm functions. It uses difference
+  quotient approximations to the Jacobian elements.
+ 
+  KINBBDPrecSetup calculates a new Jacobian, stored in banded
+  matrix PP and does an LU factorization of P in place in PP.
+ 
+  The parameters of KINBBDPrecSetup are as follows:
+ 
+  uu      is the current value of the dependent variable vector,
+          namely the solutin to func(uu)=0
+ 
+  uscale  is the dependent variable scaling vector (i.e. uu)
+ 
+  fval    is the vector f(u)
+ 
+  fscale  is the function scaling vector
+ 
+  bbd_data is the pointer to BBD data set by KINBBDInit.
+  
+  Note: The value to be returned by the KINBBDPrecSetup function
+  is a flag indicating whether it was successful. This value is:
+    0 if successful,
+    > 0 for a recoverable error - step will be retried.
+  ------------------------------------------------------------------*/
 static int KINBBDPrecSetup(N_Vector uu, N_Vector uscale,
                            N_Vector fval, N_Vector fscale, 
-                           void *bbd_data,
-                           N_Vector vtemp1, N_Vector vtemp2)
+                           void *bbd_data)
 {
   KBBDPrecData pdata;
   KINMem kin_mem;
   int retval;
-  long int ier;
 
   pdata = (KBBDPrecData) bbd_data;
 
   kin_mem = (KINMem) pdata->kin_mem;
 
-  /* call KBBDDQJac for a new jacobian and store in PP */
-
-  SetToZero(PP);
-  retval = KBBDDQJac(pdata, uu, uscale, vtemp1, vtemp2, vtemp3);
+  /* Call KBBDDQJac for a new Jacobian calculation and store in PP */
+  retval = SUNMatZero(pdata->PP);
   if (retval != 0) {
-    KINProcessError(kin_mem, -1, "KINBBDPRE", "KINBBDPrecSetup", MSGBBD_FUNC_FAILED);
+    KINProcessError(kin_mem, -1, "KINBBDPRE", "KINBBDPrecSetup",
+                    MSGBBD_SUNMAT_FAIL);
     return(-1);
   }
 
-  nge += (1 + SUNMIN(mldq+mudq+1, Nlocal));
-
-  /* do LU factorization of P in place (in PP) */
+  retval = KBBDDQJac(pdata, uu, uscale,
+                     pdata->tempv1, pdata->tempv2, pdata->tempv3);
+  if (retval != 0) {
+    KINProcessError(kin_mem, -1, "KINBBDPRE", "KINBBDPrecSetup",
+                    MSGBBD_FUNC_FAILED);
+    return(-1);
+  }
 
-  ier = BandGBTRF(PP, lpivots);
+  /* Do LU factorization of P and return error flag */
+  retval = SUNLinSolSetup_Band(pdata->LS, pdata->PP);
+  return(retval);
+}
 
-  /* return 0 if the LU was complete, else return 1 */
+/*------------------------------------------------------------------
+  INBBDPrecSolve
 
-  if (ier > 0) return(1);
-  else return(0);
-}
+  KINBBDPrecSolve solves a linear system P z = r, with the
+  banded blocked preconditioner matrix P generated and factored
+  by KINBBDPrecSetup. Here, r comes in as vv and z is
+  returned in vv as well.
+ 
+  The parameters for KINBBDPrecSolve are as follows:
+ 
+  uu     an N_Vector giving the current iterate for the system
+ 
+  uscale an N_Vector giving the diagonal entries of the
+         uu scaling matrix
+ 
+  fval   an N_Vector giving the current function value
+ 
+  fscale an N_Vector giving the diagonal entries of the
+         function scaling matrix
 
-/*
- *-----------------------------------------------------------------
- * Function : KINBBDPrecSolve
- *-----------------------------------------------------------------
- * KINBBDPrecSolve solves a linear system Pz = r, with the
- * banded blocked preconditioner matrix P generated and factored
- * by KINBBDPrecSetup. Here, r comes in as vtemp and z is
- * returned in vtemp as well.
- *
- * The parameters for KINBBDPrecSolve are as follows:
- *
- * uu     an N_Vector giving the current iterate for the system
- *
- * uscale an N_Vector giving the diagonal entries of the
- *        uu scaling matrix
- *
- * fval   an N_Vector giving the current function value
- *
- * fscale an N_Vector giving the diagonal entries of the
- *        function scaling matrix
- *
- * bbd_data is the pointer to BBD data set by IDABBDInit.
- *
- * vtemp  an N_Vector (temporary storage), usually the scratch
- *        vector vtemp from SPGMR/SPBCG/SPTFQMR (typical calling
- *        routine)
- *
- * Note: The value returned by the KINBBDPrecSolve function is a
- * flag indicating whether it was successful. Here this value is
- * always 0 which indicates success.
- *-----------------------------------------------------------------
- */
+   vv  vector initially set to the right-hand side vector r, but
+       which upon return contains a solution of the linear system
+       P*z = r
+ 
+  bbd_data is the pointer to BBD data set by KINBBDInit.
+  
+  Note: The value returned by the KINBBDPrecSolve function is a
+  flag returned from the lienar solver object.
+  ------------------------------------------------------------------*/
 
 static int KINBBDPrecSolve(N_Vector uu, N_Vector uscale,
                            N_Vector fval, N_Vector fscale, 
-                           N_Vector vv, void *bbd_data,
-                           N_Vector vtemp)
+                           N_Vector vv, void *bbd_data)
 {
   KBBDPrecData pdata;
   realtype *vd;
+  realtype *zd;
+  int i, retval;
 
   pdata = (KBBDPrecData) bbd_data;
 
-  /* do the backsolve and return */
-
+  /* Get data pointers */
   vd = N_VGetArrayPointer(vv);
-  BandGBTRS(PP, lpivots, vd);
+  zd = N_VGetArrayPointer(pdata->zlocal);
 
-  return(0);
+  /* Attach local data array for vv to rlocal */
+  N_VSetArrayPointer(vd, pdata->rlocal);
+
+  /* Call banded solver object to do the work */
+  retval = SUNLinSolSolve(pdata->LS, pdata->PP, pdata->zlocal, 
+                          pdata->rlocal, ZERO);
+
+  /* Copy result into vv */
+  for (i=0; i<pdata->n_local; i++)
+    vd[i] = zd[i]; 
+
+  return(retval);
 }
 
 
+/*------------------------------------------------------------------
+  KINBBDPrecFree
+  ------------------------------------------------------------------*/
 static int KINBBDPrecFree(KINMem kin_mem)
 {
   KINSpilsMem kinspils_mem;
   KBBDPrecData pdata;
-
+  
   if (kin_mem->kin_lmem == NULL) return(0);
   kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
   
-  if (kinspils_mem->s_P_data == NULL) return(0);
-  pdata = (KBBDPrecData) kinspils_mem->s_P_data;
+  if (kinspils_mem->pdata == NULL) return(0);
+  pdata = (KBBDPrecData) kinspils_mem->pdata;
 
-  N_VDestroy(vtemp3);
-  DestroyMat(PP);
-  DestroyArray(lpivots);
+  SUNLinSolFree(pdata->LS);
+  N_VDestroy(pdata->zlocal);
+  N_VDestroy(pdata->rlocal);
+  N_VDestroy(pdata->tempv1);
+  N_VDestroy(pdata->tempv2);
+  N_VDestroy(pdata->tempv3);
+  SUNMatDestroy(pdata->PP);
 
   free(pdata);
   pdata = NULL;
@@ -453,91 +503,79 @@ static int KINBBDPrecFree(KINMem kin_mem)
 }
 
 
+/*------------------------------------------------------------------
+  KBBDDQJac
 
-/*
- *-----------------------------------------------------------------
- * Function : KBBDDQJac
- *-----------------------------------------------------------------
- * This routine generates a banded difference quotient
- * approximation to the Jacobian of f(u). It assumes that a band
- * matrix of type BandMat is stored column-wise, and that elements
- * within each column are contiguous. All matrix elements are
- * generated as difference quotients, by way of calls to the user
- * routine gloc. By virtue of the band structure, the number of
- * these calls is bandwidth + 1, where bandwidth = ml + mu + 1.
- * This routine also assumes that the local elements of a vector
- * are stored contiguously.
- *-----------------------------------------------------------------
- */
-
-#define user_data (kin_mem->kin_user_data)
-
+  This routine generates a banded difference quotient
+  approximation to the Jacobian of f(u). It assumes that a band
+  matrix of type SUNMatrix is stored column-wise, and that elements
+  within each column are contiguous. All matrix elements are
+  generated as difference quotients, by way of calls to the user
+  routine gloc. By virtue of the band structure, the number of
+  these calls is bandwidth + 1, where bandwidth = ml + mu + 1.
+  This routine also assumes that the local elements of a vector
+  are stored contiguously.
+  ------------------------------------------------------------------*/
 static int KBBDDQJac(KBBDPrecData pdata,
                      N_Vector uu, N_Vector uscale,
                      N_Vector gu, N_Vector gtemp, N_Vector utemp)
 {
-  realtype inc, inc_inv;
-  long int group, i, j, width, ngroups, i1, i2;
   KINMem kin_mem;
-  realtype *udata, *uscdata, *gudata, *gtempdata, *utempdata, *col_j;
+  realtype inc, inc_inv;
   int retval;
+  sunindextype group, i, j, width, ngroups, i1, i2;
+  realtype *udata, *uscdata, *gudata, *gtempdata, *utempdata, *col_j;
 
   kin_mem = (KINMem) pdata->kin_mem;
 
-  /* set pointers to the data for all vectors */
+  /* load utemp with uu = predicted solution vector */
+  N_VScale(ONE, uu, utemp);
 
+  /* set pointers to the data for all vectors */
   udata     = N_VGetArrayPointer(uu);
   uscdata   = N_VGetArrayPointer(uscale);
   gudata    = N_VGetArrayPointer(gu);
   gtempdata = N_VGetArrayPointer(gtemp);
   utempdata = N_VGetArrayPointer(utemp);
 
-  /* load utemp with uu = predicted solution vector */
-
-  N_VScale(ONE, uu, utemp);
-
-  /* call gcomm and gloc to get base value of g(uu) */
-
-  if (gcomm != NULL) {
-    retval = gcomm(Nlocal, uu, user_data);
+  /* Call gcomm and gloc to get base value of g(uu) */
+  if (pdata->gcomm != NULL) {
+    retval = pdata->gcomm(pdata->n_local, uu, kin_mem->kin_user_data);
     if (retval != 0) return(retval);
   }
 
-  retval = gloc(Nlocal, uu, gu, user_data);
+  retval = pdata->gloc(pdata->n_local, uu, gu, kin_mem->kin_user_data);
+  pdata->nge++;
   if (retval != 0) return(retval);
 
-  /* set bandwidth and number of column groups for band differencing */
+  /* Set bandwidth and number of column groups for band differencing */
+  width = pdata->mldq + pdata->mudq + 1;
+  ngroups = SUNMIN(width, pdata->n_local);
 
-  width = mldq + mudq + 1;
-  ngroups = SUNMIN(width, Nlocal);
+  /* Loop over groups */
+  for(group = 1; group <= ngroups; group++) {
 
-  /* loop over groups */
-  
-  for (group = 1; group <= ngroups; group++) {
-  
     /* increment all u_j in group */
-
-    for(j = group - 1; j < Nlocal; j += width) {
-      inc = rel_uu * SUNMAX(SUNRabs(udata[j]), (ONE / uscdata[j]));
+    for(j = group - 1; j < pdata->n_local; j += width) {
+      inc = pdata->rel_uu * SUNMAX(SUNRabs(udata[j]), (ONE / uscdata[j]));
       utempdata[j] += inc;
     }
-  
-    /* evaluate g with incremented u */
 
-    retval = gloc(Nlocal, utemp, gtemp, user_data);
+    /* Evaluate g with incremented u */
+    retval = pdata->gloc(pdata->n_local, utemp, gtemp, kin_mem->kin_user_data);
+    pdata->nge++;
     if (retval != 0) return(retval);
 
     /* restore utemp, then form and load difference quotients */
-
-    for (j = group - 1; j < Nlocal; j += width) {
+    for (j = group - 1; j < pdata->n_local; j += width) {
       utempdata[j] = udata[j];
-      col_j = BAND_COL(PP,j);
-      inc = rel_uu * SUNMAX(SUNRabs(udata[j]) , (ONE / uscdata[j]));
+      col_j = SUNBandMatrix_Column(pdata->PP,j);
+      inc = pdata->rel_uu * SUNMAX(SUNRabs(udata[j]) , (ONE / uscdata[j]));
       inc_inv = ONE / inc;
-      i1 = SUNMAX(0, (j - mukeep));
-      i2 = SUNMIN((j + mlkeep), (Nlocal - 1));
+      i1 = SUNMAX(0, (j - pdata->mukeep));
+      i2 = SUNMIN((j + pdata->mlkeep), (pdata->n_local - 1));
       for (i = i1; i <= i2; i++)
-	BAND_COL_ELEM(col_j, i, j) = inc_inv * (gtempdata[i] - gudata[i]);
+        SM_COLUMN_ELEMENT_B(col_j, i, j) = inc_inv * (gtempdata[i] - gudata[i]);
     }
   }
 
diff --git a/src/kinsol/kinsol_bbdpre_impl.h b/src/kinsol/kinsol_bbdpre_impl.h
index 1ff6de0..5978bb2 100644
--- a/src/kinsol/kinsol_bbdpre_impl.h
+++ b/src/kinsol/kinsol_bbdpre_impl.h
@@ -1,11 +1,8 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * -----------------------------------------------------------------
- * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
- *  -----------------------------------------------------------------
+ * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
  * This work was performed under the auspices of the U.S. Department 
@@ -17,59 +14,48 @@
  * LLNS Copyright End
  * -----------------------------------------------------------------
  * KINBBDPRE module header file (private version)
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _KINBBDPRE_IMPL_H
 #define _KINBBDPRE_IMPL_H
 
 #include <kinsol/kinsol_bbdpre.h>
-#include <sundials/sundials_band.h>
-#include "kinsol_impl.h"
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunlinsol/sunlinsol_band.h>
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-/*
- * -----------------------------------------------------------------
- * Definition of KBBDData
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Definition of KBBDData
+  ------------------------------------------------------------------*/
 
 typedef struct KBBDPrecDataRec {
 
   /* passed by user to KINBBDPrecAlloc, used by pset/psolve functions */
-
-  long int mudq, mldq, mukeep, mlkeep;
-  KINLocalFn gloc;
-  KINCommFn gcomm;
-
-  /* relative error for the Jacobian DQ routine */
-
-  realtype rel_uu;
-
-  /* allocated for use by KINBBDPrecSetup */
-
-  N_Vector vtemp3;
-
-  /* set by KINBBDPrecSetup and used by KINBBDPrecSolve */
-
-  DlsMat PP;
-  long int *lpivots;
-
-  /* set by KINBBDPrecAlloc and used by KINBBDPrecSetup */
-
-  long int n_local;
+  sunindextype mudq, mldq, mukeep, mlkeep;
+  realtype rel_uu;  /* relative error for the Jacobian DQ routine */
+  KINBBDLocalFn gloc;
+  KINBBDCommFn gcomm;
+
+  /* set by KINBBDPrecSetup and used by KINBBDPrecSetup and 
+     KINBBDPrecSolve functions */
+  sunindextype n_local;
+  SUNMatrix PP;
+  SUNLinearSolver LS;
+  N_Vector rlocal;
+  N_Vector zlocal;
+  N_Vector tempv1;
+  N_Vector tempv2;
+  N_Vector tempv3;
 
   /* available for optional output */
-
   long int rpwsize;
   long int ipwsize;
   long int nge;
 
   /* pointer to KINSol memory */
-
   void *kin_mem;
 
 } *KBBDPrecData;
@@ -84,8 +70,10 @@ typedef struct KBBDPrecDataRec {
 #define MSGBBD_LMEM_NULL   "Linear solver memory is NULL. One of the SPILS linear solvers must be attached."
 #define MSGBBD_MEM_FAIL    "A memory request failed."
 #define MSGBBD_BAD_NVECTOR "A required vector operation is not implemented."
-#define MSGBBD_FUNC_FAILED "The gloc or cfn routine failed in an unrecoverable manner."
+#define MSGBBD_SUNMAT_FAIL "An error arose from a SUNBandMatrix routine."
+#define MSGBBD_SUNLS_FAIL  "An error arose from a SUNBandLinearSolver routine."
 #define MSGBBD_PMEM_NULL   "BBD peconditioner memory is NULL. IDABBDPrecInit must be called."
+#define MSGBBD_FUNC_FAILED "The gloc or gcomm routine failed in an unrecoverable manner."
 
 #ifdef __cplusplus
 }
diff --git a/src/kinsol/kinsol_dense.c b/src/kinsol/kinsol_dense.c
deleted file mode 100644
index c55e317..0000000
--- a/src/kinsol/kinsol_dense.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINDENSE linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <kinsol/kinsol_dense.h>
-#include "kinsol_direct_impl.h"
-#include "kinsol_impl.h"
-
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/* KINDENSE linit, lsetup, lsolve, and lfree routines */ 
-static int kinDenseInit(KINMem kin_mem);
-static int kinDenseSetup(KINMem kin_mem);
-static int kinDenseSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                         realtype *sJpnorm, realtype *sFdotJp);
-static int kinDenseFree(KINMem kin_mem);
-
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define lrw1           (kin_mem->kin_lrw1)
-#define liw1           (kin_mem->kin_liw1)
-#define func           (kin_mem->kin_func)
-#define printfl        (kin_mem->kin_printfl)
-#define linit          (kin_mem->kin_linit)
-#define lsetup         (kin_mem->kin_lsetup)
-#define lsolve         (kin_mem->kin_lsolve)
-#define lfree          (kin_mem->kin_lfree)
-#define lmem           (kin_mem->kin_lmem)
-#define inexact_ls     (kin_mem->kin_inexact_ls)
-#define uu             (kin_mem->kin_uu)
-#define fval           (kin_mem->kin_fval)
-#define uscale         (kin_mem->kin_uscale)
-#define fscale         (kin_mem->kin_fscale)
-#define sqrt_relfunc   (kin_mem->kin_sqrt_relfunc)
-#define errfp          (kin_mem->kin_errfp)
-#define infofp         (kin_mem->kin_infofp)
-#define setupNonNull   (kin_mem->kin_setupNonNull)
-#define vtemp1         (kin_mem->kin_vtemp1)
-#define vec_tmpl       (kin_mem->kin_vtemp1)
-#define vtemp2         (kin_mem->kin_vtemp2)
-#define strategy       (kin_mem->kin_globalstrategy)
-
-#define mtype          (kindls_mem->d_type)
-#define n              (kindls_mem->d_n)
-#define ml             (kindls_mem->d_ml)
-#define mu             (kindls_mem->d_mu)
-#define smu            (kindls_mem->d_smu)
-#define jacDQ          (kindls_mem->d_jacDQ)
-#define djac           (kindls_mem->d_djac)
-#define J              (kindls_mem->d_J)
-#define lpivots        (kindls_mem->d_lpivots)
-#define nje            (kindls_mem->d_nje)
-#define nfeDQ          (kindls_mem->d_nfeDQ)
-#define J_data         (kindls_mem->d_J_data)
-#define last_flag      (kindls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS
- * =================================================================
- */
-             
-/*
- * -----------------------------------------------------------------
- * KINDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the dense linear solver module. 
- * KINDense sets the kin_linit, kin_lsetup, kin_lsolve, kin_lfree fields 
- * in *kinmem to be kinDenseInit, kinDenseSetup, kinDenseSolve, and 
- * kinDenseFree, respectively.  
- * It allocates memory for a structure of type KINDlsMemRec and sets 
- * the kin_lmem field in *kinmem to the address of this structure.  
- * It sets setupNonNull in *kinmem to TRUE, and the djac field to the 
- * default kinDlsDenseDQJac.
- * Finally, it allocates memory for J and lpivots.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, KINDense will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that N_VGetArrayPointer and
- *       N_VSetArrayPointer exist.
- * -----------------------------------------------------------------
- */
-
-int KINDense(void *kinmem, long int N)
-{
-  KINMem kin_mem;
-  KINDlsMem kindls_mem;
-
-  /* Return immediately if kinmem is NULL */
-  if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDENSE", "KINDense", MSGD_KINMEM_NULL);
-    return(KINDLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL ||
-      vec_tmpl->ops->nvsetarraypointer == NULL) {
-    KINProcessError(kin_mem, KINDLS_ILL_INPUT, "KINDENSE", "KINDense", MSGD_BAD_NVECTOR);
-    return(KINDLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(kin_mem);
-
-  /* Set four main function fields in kin_mem */
-  linit  = kinDenseInit;
-  lsetup = kinDenseSetup;
-  lsolve = kinDenseSolve;
-  lfree  = kinDenseFree;
-
-  /* Get memory for KINDlsMemRec */
-  kindls_mem = NULL;
-  kindls_mem = (KINDlsMem) malloc(sizeof(struct KINDlsMemRec));
-  if (kindls_mem == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINDENSE", "KINDense", MSGD_MEM_FAIL);
-    return(KINDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;  
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  djac   = NULL;
-  J_data = NULL;
-  last_flag = KINDLS_SUCCESS;
-
-  kinDlsInitializeCounters(kindls_mem);
-
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = N;
-
-  /* Allocate memory for J and pivot array */
-  
-  J = NULL;
-  J = NewDenseMat(N, N);
-  if (J == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINDENSE", "KINDense", MSGD_MEM_FAIL);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  lpivots = NULL;
-  lpivots = NewLintArray(N);
-  if (lpivots == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINDENSE", "KINDense", MSGD_MEM_FAIL);
-    DestroyMat(J);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  /* This is a direct linear solver */
-  inexact_ls = FALSE;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = kindls_mem;
-
-  return(KINDLS_SUCCESS);
-}
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * kinDenseInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the dense
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinDenseInit(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-  
-  kinDlsInitializeCounters(kindls_mem);
-  
-  if (jacDQ) {
-    djac = kinDlsDenseDQJac;
-    J_data = kin_mem;
-  } else {
-    J_data = kin_mem->kin_user_data;
-  }
-  
-  if ( (strategy == KIN_PICARD) && jacDQ ) {
-    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINDenseInit", 
-		    MSG_NOL_FAIL);
-    return(KIN_ILL_INPUT);
-  }
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinDenseSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the dense linear solver.
- * It calls the dense LU factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int kinDenseSetup(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-  int retval;
-  long int ier;
-
-  kindls_mem = (KINDlsMem) lmem;
- 
-  nje++;
-  SetToZero(J); 
-  retval = djac(n, uu, fval, J, J_data, vtemp1, vtemp2);
-  if (retval != 0) {
-    last_flag = -1;
-    return(-1);
-  }
-
-  /* Do LU factorization of J */
-  ier = DenseGETRF(J, lpivots); 
-
-  /* Return 0 if the LU was complete; otherwise return -1 */
-  last_flag = ier;
-  if (ier > 0) return(-1);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinDenseSolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.  The returned value is 0.
- * The argument *sJpnorm is ignored.
- * -----------------------------------------------------------------
- */
-
-static int kinDenseSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                         realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINDlsMem kindls_mem;
-  realtype *xd;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  /* Copy the right-hand side into x */
-
-  N_VScale(ONE, b, x);
-  
-  xd = N_VGetArrayPointer(x);
-
-  /* Back-solve and get solution in x */
-  
-  DenseGETRS(J, lpivots, xd);
-
-  /* Compute the term sFdotJp for use in the linesearch routine.
-     This term is subsequently corrected if the step is reduced by
-     constraints or the linesearch.
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  N_VProd(b, fscale, b);
-  N_VProd(b, fscale, b);
-  *sFdotJp = N_VDotProd(fval, b);
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinDenseFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the dense linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinDenseFree(KINMem kin_mem)
-{
-  KINDlsMem  kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-  
-  DestroyMat(J);
-  DestroyArray(lpivots);
-  free(kindls_mem); kindls_mem = NULL;
-
-  return(0);
-}
-
diff --git a/src/kinsol/kinsol_direct.c b/src/kinsol/kinsol_direct.c
index 3ef5d65..3fc6724 100644
--- a/src/kinsol/kinsol_direct.c
+++ b/src/kinsol/kinsol_direct.c
@@ -1,9 +1,6 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -15,15 +12,9 @@
  * For details, see the LICENSE file.
  * LLNS Copyright End
  * -----------------------------------------------------------------
- * This is the implementation file for the KINDLS linear solvers
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
+ * This is the implementation file for the KINDLS linear solver
+ * interface
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,12 +22,14 @@
 #include "kinsol_impl.h"
 #include "kinsol_direct_impl.h"
 #include <sundials/sundials_math.h>
+#include <sunmatrix/sunmatrix_band.h>
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sunmatrix/sunmatrix_sparse.h>
+
 
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
+/*==================================================================
+  FUNCTION SPECIFIC CONSTANTS
+  ==================================================================*/
 
 /* Constant for DQ Jacobian approximation */
 #define MIN_INC_MULT RCONST(1000.0)
@@ -45,249 +38,256 @@
 #define ONE          RCONST(1.0)
 #define TWO          RCONST(2.0)
 
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define lrw1           (kin_mem->kin_lrw1)
-#define liw1           (kin_mem->kin_liw1)
-#define uround         (kin_mem->kin_uround)
-#define func           (kin_mem->kin_func)
-#define user_data      (kin_mem->kin_user_data)
-#define printfl        (kin_mem->kin_printfl)
-#define linit          (kin_mem->kin_linit)
-#define lsetup         (kin_mem->kin_lsetup)
-#define lsolve         (kin_mem->kin_lsolve)
-#define lfree          (kin_mem->kin_lfree)
-#define lmem           (kin_mem->kin_lmem)
-#define inexact_ls     (kin_mem->kin_inexact_ls)
-#define uu             (kin_mem->kin_uu)
-#define fval           (kin_mem->kin_fval)
-#define uscale         (kin_mem->kin_uscale)
-#define fscale         (kin_mem->kin_fscale)
-#define sqrt_relfunc   (kin_mem->kin_sqrt_relfunc)
-#define sJpnorm        (kin_mem->kin_sJpnorm)
-#define sfdotJp        (kin_mem->kin_sfdotJp)
-#define errfp          (kin_mem->kin_errfp)
-#define infofp         (kin_mem->kin_infofp)
-#define setupNonNull   (kin_mem->kin_setupNonNull)
-#define vtemp1         (kin_mem->kin_vtemp1)
-#define vec_tmpl       (kin_mem->kin_vtemp1)
-#define vtemp2         (kin_mem->kin_vtemp2)
-
-#define mtype          (kindls_mem->d_type)
-#define n              (kindls_mem->d_n)
-#define ml             (kindls_mem->d_ml)
-#define mu             (kindls_mem->d_mu)
-#define smu            (kindls_mem->d_smu)
-#define jacDQ          (kindls_mem->d_jacDQ)
-#define djac           (kindls_mem->d_djac)
-#define bjac           (kindls_mem->d_bjac)
-#define J              (kindls_mem->d_J)
-#define pivots         (kindls_mem->d_pivots)
-#define nje            (kindls_mem->d_nje)
-#define nfeDQ          (kindls_mem->d_nfeDQ)
-#define J_data         (kindls_mem->d_J_data)
-#define last_flag      (kindls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS
- * =================================================================
- */
-              
-/*
- * -----------------------------------------------------------------
- * KINDlsSetJacFn
- * -----------------------------------------------------------------
- */
+/*==================================================================
+  KINDLS Exported fuctions -- Required
+  ==================================================================*/
 
-int KINDlsSetDenseJacFn(void *kinmem, KINDlsDenseJacFn jac)
+/*------------------------------------------------------------------
+  KINDlsSetLinearSolver speficies the direct linear solver
+  ------------------------------------------------------------------*/
+int KINDlsSetLinearSolver(void *kinmem, SUNLinearSolver LS,
+                          SUNMatrix A)
 {
   KINMem kin_mem;
   KINDlsMem kindls_mem;
 
-  /* Return immediately if kinmem is NULL */
+  /* Return immediately if any input is NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINDlsSetDenseJacFn", MSGD_KINMEM_NULL);
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS",
+                    "KINDlsSetLinearSolver", MSGD_KINMEM_NULL);
     return(KINDLS_MEM_NULL);
   }
+  if ( (LS == NULL) || (A == NULL) ) {
+    KINProcessError(NULL, KINDLS_ILL_INPUT, "KINDLS", 
+                    "KINDlsSetLinearSolver",
+                    "Both LS and A must be non-NULL");
+    return(KINDLS_ILL_INPUT);
+  }
   kin_mem = (KINMem) kinmem;
 
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", "KINDlsSetDenseJacFn", MSGD_LMEM_NULL);
-    return(KINDLS_LMEM_NULL);
+  /* Test if solver and vector are compatible with DLS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_DIRECT) {
+    KINProcessError(kin_mem, KINDLS_ILL_INPUT, "KINDLS", 
+                    "KINDlsSetLinearSolver", 
+                    "Non-direct LS supplied to KINDls interface");
+    return(KINDLS_ILL_INPUT);
+  }
+  if (kin_mem->kin_vtemp1->ops->nvgetarraypointer == NULL ||
+      kin_mem->kin_vtemp1->ops->nvsetarraypointer == NULL) {
+    KINProcessError(kin_mem, KINDLS_ILL_INPUT, "KINDLS", 
+                    "KINDlsSetLinearSolver", MSGD_BAD_NVECTOR);
+    return(KINDLS_ILL_INPUT);
   }
-  kindls_mem = (KINDlsMem) lmem;
 
-  if (jac != NULL) {
-    jacDQ = FALSE;
-    djac = jac;
-  } else {
-    jacDQ = TRUE;
+  /* free any existing system solver attached to KINSOL */
+  if (kin_mem->kin_lfree)  kin_mem->kin_lfree(kin_mem);
+
+  /* Set four main system linear solver function fields in kin_mem */
+  kin_mem->kin_linit  = kinDlsInitialize;
+  kin_mem->kin_lsetup = kinDlsSetup;
+  kin_mem->kin_lsolve = kinDlsSolve;
+  kin_mem->kin_lfree  = kinDlsFree;
+
+  /* Get memory for KINDlsMemRec */
+  kindls_mem = NULL;
+  kindls_mem = (KINDlsMem) malloc(sizeof(struct KINDlsMemRec));
+  if (kindls_mem == NULL) {
+    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINDLS",
+                    "KINDlsSetLinearSolver", MSGD_MEM_FAIL);
+    return(KINDLS_MEM_FAIL);
   }
 
+  /* set SUNLinearSolver pointer */
+  kindls_mem->LS = LS;
+
+  /* set SUNMatrix pointer */
+  kindls_mem->J = A;
+
+  /* Initialize Jacobian-related data */
+  kindls_mem->jacDQ     = SUNTRUE;
+  kindls_mem->jac       = kinDlsDQJac;
+  kindls_mem->J_data    = kin_mem;
+  kindls_mem->last_flag = KINDLS_SUCCESS;
+
+  /* Initialize counters */
+  kinDlsInitializeCounters(kindls_mem);
+
+  /* Attach linear solver memory to integrator memory */
+  kin_mem->kin_lmem = kindls_mem;
+
   return(KINDLS_SUCCESS);
 }
 
-int KINDlsSetBandJacFn(void *kinmem, KINDlsBandJacFn jac)
+
+/*==================================================================
+  KINDLS Exported fuctions -- Optional input/output
+  ==================================================================*/
+
+/*------------------------------------------------------------------
+  KINDlsSetJacFn specifies the Jacobian function
+  ------------------------------------------------------------------*/
+int KINDlsSetJacFn(void *kinmem, KINDlsJacFn jac)
 {
   KINMem kin_mem;
   KINDlsMem kindls_mem;
 
-  /* Return immediately if kinmem is NULL */
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINDlsSetBandJacFn", MSGD_KINMEM_NULL);
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS",
+                    "KINDlsSetJacFn", MSGD_KINMEM_NULL);
     return(KINDLS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", "KINDlsSetBandJacFn", MSGD_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS",
+                    "KINDlsSetJacFn", MSGD_LMEM_NULL);
     return(KINDLS_LMEM_NULL);
   }
-  kindls_mem = (KINDlsMem) lmem;
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
 
   if (jac != NULL) {
-    jacDQ = FALSE;
-    bjac = jac;
+    kindls_mem->jacDQ  = SUNFALSE;
+    kindls_mem->jac    = jac;
+    kindls_mem->J_data = kin_mem->kin_user_data;
   } else {
-    jacDQ = TRUE;
+    kindls_mem->jacDQ  = SUNTRUE;
+    kindls_mem->jac    = kinDlsDQJac;
+    kindls_mem->J_data = kin_mem;
   }
 
   return(KINDLS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * KINDlsGetWorkSpace
- * -----------------------------------------------------------------
- */
 
-int KINDlsGetWorkSpace(void *kinmem, long int *lenrwLS, long int *leniwLS)
+/*------------------------------------------------------------------
+  KINDlsGetWorkSpace returns the lenght of workspace allocated for
+  the KINDls linear solver interface
+  ------------------------------------------------------------------*/
+int KINDlsGetWorkSpace(void *kinmem, long int *lenrwLS,
+                       long int *leniwLS)
 {
   KINMem kin_mem;
   KINDlsMem kindls_mem;
+  long int lrw, liw;
+  int flag;
 
-  /* Return immediately if kinmem is NULL */
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINBandGetWorkSpace", MSGD_KINMEM_NULL);
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", 
+                    "KINDlsGetWorkSpace", MSGD_KINMEM_NULL);
     return(KINDLS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", "KINBandGetWorkSpace", MSGD_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS",
+                    "KINGetWorkSpace", MSGD_LMEM_NULL);
     return(KINDLS_LMEM_NULL);
   }
-  kindls_mem = (KINDlsMem) lmem;
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
 
-  if (mtype == SUNDIALS_DENSE) {
-    *lenrwLS = n*n;
-    *leniwLS = n;
-  } else if (mtype == SUNDIALS_BAND) {
-    *lenrwLS = n*(smu + mu + 2*ml + 2);
-    *leniwLS = n;
+  /* initialize outputs with requirements from KINDlsMem structure */
+  *lenrwLS = 0;
+  *leniwLS = 3;
+
+  /* add LS sizes */
+  if (kindls_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(kindls_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
   }
 
   return(KINDLS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * KINDlsGetNumJacEvals
- * -----------------------------------------------------------------
- */
 
+/*------------------------------------------------------------------
+  KINDlsGetNumJacEvals returns the number of Jacobian evaluations
+  ------------------------------------------------------------------*/
 int KINDlsGetNumJacEvals(void *kinmem, long int *njevals)
 {
   KINMem kin_mem;
   KINDlsMem kindls_mem;
 
-  /* Return immediately if kinmem is NULL */
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINDlsGetNumJacEvals", MSGD_KINMEM_NULL);
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS",
+                    "KINDlsGetNumJacEvals", MSGD_KINMEM_NULL);
     return(KINDLS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", "KINDlsGetNumJacEvals", MSGD_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS",
+                    "KINDlsGetNumJacEvals", MSGD_LMEM_NULL);
     return(KINDLS_LMEM_NULL);
   }
-  kindls_mem = (KINDlsMem) lmem;
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
 
-  *njevals = nje;
+  *njevals = kindls_mem->nje;
 
   return(KINDLS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * KINDlsGetNumFuncEvals
- * -----------------------------------------------------------------
- */
 
-int KINDlsGetNumFuncEvals(void *kinmem, long int *nfevalsLS)
+/*------------------------------------------------------------------
+  KINDlsGetNumFuncEvals returns the number of calls to the user's
+  F routine needed for the DQ Jacobian approximation
+  ------------------------------------------------------------------*/
+int KINDlsGetNumFuncEvals(void *kinmem, long int *nfevals)
 {
   KINMem kin_mem;
   KINDlsMem kindls_mem;
 
-  /* Return immediately if kinmem is NULL */
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINDlsGetNumFuncEvals", MSGD_KINMEM_NULL);
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS",
+                    "KINDlsGetNumFuncEvals", MSGD_KINMEM_NULL);
     return(KINDLS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", "KINDlsGetNumGuncEvals", MSGD_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL,
+                    "KINDLS", "KINDlsGetNumGuncEvals", MSGD_LMEM_NULL);
     return(KINDLS_LMEM_NULL);
   }
-  kindls_mem = (KINDlsMem) lmem;
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
 
-  *nfevalsLS = nfeDQ;
+  *nfevals = kindls_mem->nfeDQ;
 
   return(KINDLS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * KINDlsGetLastFlag
- * -----------------------------------------------------------------
- */
 
+/*------------------------------------------------------------------
+  KINDlsGetLastFlag returns the last flag set in the KINDLS function
+  ------------------------------------------------------------------*/
 int KINDlsGetLastFlag(void *kinmem, long int *flag)
 {
   KINMem kin_mem;
   KINDlsMem kindls_mem;
 
-  /* Return immediately if kinmem is NULL */
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", "KINDlsGetLastFlag", MSGD_KINMEM_NULL);
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS",
+                    "KINDlsGetLastFlag", MSGD_KINMEM_NULL);
     return(KINDLS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", "KINDlsGetLastFlag", MSGD_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS",
+                    "KINDlsGetLastFlag", MSGD_LMEM_NULL);
     return(KINDLS_LMEM_NULL);
   }
-  kindls_mem = (KINDlsMem) lmem;
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
 
-  *flag = last_flag;
+  *flag = kindls_mem->last_flag;
 
   return(KINDLS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * KINDlsGetReturnFlagName
- * -----------------------------------------------------------------
- */
 
+/*------------------------------------------------------------------
+  KINDlsGetReturnFlagName
+  ------------------------------------------------------------------*/
 char *KINDlsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -310,6 +310,12 @@ char *KINDlsGetReturnFlagName(long int flag)
   case KINDLS_MEM_FAIL:
     sprintf(name, "KINDLS_MEM_FAIL");
     break;
+  case KINDLS_JACFUNC_ERR:
+    sprintf(name,"KINDLS_JACFUNC_ERR");
+    break;
+  case KINDLS_SUNMAT_FAIL:
+    sprintf(name,"KINDLS_SUNMAT_FAIL");
+    break;
   default:
     sprintf(name, "NONE");
   }
@@ -317,92 +323,128 @@ char *KINDlsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/* 
- * =================================================================
- * DQ JACOBIAN APPROXIMATIONS
- * =================================================================
- */
 
+/*==================================================================
+  KINDLS Private function 
+  ==================================================================*/
 
+/*------------------------------------------------------------------
+  kinDlsDenseDQJac 
 
-/*
- * -----------------------------------------------------------------
- * kinDlsDenseDQJac 
- * -----------------------------------------------------------------
- * This routine generates a dense difference quotient approximation to
- * the Jacobian of F(u). It assumes that a dense matrix of type
- * DlsMat is stored column-wise, and that elements within each column
- * are contiguous. The address of the jth column of J is obtained via
- * the macro DENSE_COL and this pointer is associated with an N_Vector
- * using the N_VGetArrayPointer/N_VSetArrayPointer functions. 
- * Finally, the actual computation of the jth column of the Jacobian is 
- * done with a call to N_VLinearSum.
- *
- * The increment used in the finite-difference approximation
- *   J_ij = ( F_i(u+sigma_j * e_j) - F_i(u)  ) / sigma_j
- * is
- *  sigma_j = max{|u_j|, |1/uscale_j|} * sqrt(uround)
- *
- * Note: uscale_j = 1/typ(u_j)
- *
- * NOTE: Any type of failure of the system function her leads to an
- *       unrecoverable failure of the Jacobian function and thus
- *       of the linear solver setup function, stopping KINSOL.
- * -----------------------------------------------------------------
- */
+  This routine is a wrapper for the Dense and Band implementations
+  of the difference quotient Jacobian approximation routines. 
+  ------------------------------------------------------------------*/
+int kinDlsDQJac(N_Vector u, N_Vector fu, SUNMatrix Jac, 
+                void *kinmem, N_Vector tmp1, N_Vector tmp2)
+{
+  int retval;
+  KINMem kin_mem;
+  kin_mem = (KINMem) kinmem;
+
+  /* verify that Jac is non-NULL */
+  if (Jac == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", 
+		    "kinDlsDQJac", MSGD_LMEM_NULL);
+    return(KINDLS_LMEM_NULL);
+  }
 
-int kinDlsDenseDQJac(long int N,
-                     N_Vector u, N_Vector fu,
-                     DlsMat Jac, void *data,
-                     N_Vector tmp1, N_Vector tmp2)
+  if (SUNMatGetID(Jac) == SUNMATRIX_DENSE) {
+    retval = kinDlsDenseDQJac(u, fu, Jac, kin_mem, tmp1, tmp2);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_BAND) {
+    retval = kinDlsBandDQJac(u, fu, Jac, kin_mem, tmp1, tmp2);
+  } else if (SUNMatGetID(Jac) == SUNMATRIX_SPARSE) {
+    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINDLS",
+		    "kinDlsDQJac",
+                    "kinDlsDQJac not implemented for SUNMATRIX_SPARSE");
+    retval = KIN_ILL_INPUT;
+  } else {
+    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINDLS",
+		    "kinDlsDQJac",
+                    "unrecognized matrix type for kinDlsDQJac");
+    retval = KIN_ILL_INPUT;
+  }
+  return(retval);
+}
+
+
+/*------------------------------------------------------------------
+  kinDlsDenseDQJac
+
+  This routine generates a dense difference quotient approximation
+  to the Jacobian of F(u). It assumes a dense SUNMatrix input
+  stored column-wise, and that elements within each column are 
+  contiguous. The address of the jth column of J is obtained via
+  the function SUNDenseMatrix_Column() and this pointer is
+  associated with an N_Vector using the N_VGetArrayPointer and
+  N_VSetArrayPointer functions. Finally, the actual computation of
+  the jth column of the Jacobian is done with a call to N_VLinearSum.
+ 
+  The increment used in the finite-difference approximation
+    J_ij = ( F_i(u+sigma_j * e_j) - F_i(u)  ) / sigma_j
+  is
+   sigma_j = max{|u_j|, |1/uscale_j|} * sqrt(uround)
+ 
+  Note: uscale_j = 1/typ(u_j)
+ 
+  NOTE: Any type of failure of the system function here leads to an
+        unrecoverable failure of the Jacobian function and thus of 
+        the linear solver setup function, stopping KINSOL.
+  ------------------------------------------------------------------*/
+int kinDlsDenseDQJac(N_Vector u, N_Vector fu, SUNMatrix Jac, 
+                     KINMem kin_mem, N_Vector tmp1, N_Vector tmp2)
 {
   realtype inc, inc_inv, ujsaved, ujscale, sign;
   realtype *tmp2_data, *u_data, *uscale_data;
   N_Vector ftemp, jthCol;
+  sunindextype j, N;
   int retval = 0;
-  long int j;
+  KINDlsMem kindls_mem;
 
-  KINMem kin_mem;
-  KINDlsMem  kindls_mem;
+  /* access DlsMem interface structure */
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
 
-  /* data points to kin_mem */
-  kin_mem = (KINMem) data;
-  kindls_mem = (KINDlsMem) lmem;
+  /* access matrix dimension */
+  N = SUNDenseMatrix_Rows(Jac);
 
   /* Save pointer to the array in tmp2 */
   tmp2_data = N_VGetArrayPointer(tmp2);
 
   /* Rename work vectors for readibility */
-  ftemp = tmp1; 
+  ftemp  = tmp1; 
   jthCol = tmp2;
 
   /* Obtain pointers to the data for u and uscale */
-  u_data   = N_VGetArrayPointer(u);
-  uscale_data = N_VGetArrayPointer(uscale);
+  u_data      = N_VGetArrayPointer(u);
+  uscale_data = N_VGetArrayPointer(kin_mem->kin_uscale);
 
   /* This is the only for loop for 0..N-1 in KINSOL */
 
   for (j = 0; j < N; j++) {
 
-    /* Generate the jth col of Jac(u) */
-
-    N_VSetArrayPointer(DENSE_COL(Jac,j), jthCol);
+    /* Generate the jth col of J(u) */
 
+    /* Set data address of jthCol, and save u_j values and scaling */
+    N_VSetArrayPointer(SUNDenseMatrix_Column(Jac,j), jthCol);
     ujsaved = u_data[j];
     ujscale = ONE/uscale_data[j];
+
+    /* Compute increment */
     sign = (ujsaved >= ZERO) ? ONE : -ONE;
-    inc = sqrt_relfunc*SUNMAX(SUNRabs(ujsaved), ujscale)*sign;
+    inc = kin_mem->kin_sqrt_relfunc*SUNMAX(SUNRabs(ujsaved), ujscale)*sign;
+
+    /* Increment u_j, call F(u), and return if error occurs */
     u_data[j] += inc;
 
-    retval = func(u, ftemp, user_data);
-    nfeDQ++;
-    if (retval != 0) break; 
+    retval = kin_mem->kin_func(u, ftemp, kin_mem->kin_user_data);
+    kindls_mem->nfeDQ++;
+    if (retval != 0) break;
 
+    /* reset u_j */
     u_data[j] = ujsaved;
 
+    /* Construct difference quotient in jthCol */
     inc_inv = ONE/inc;
     N_VLinearSum(inc_inv, ftemp, -inc_inv, fu, jthCol);
-
   }
 
   /* Restore original array pointer in tmp2 */
@@ -411,95 +453,271 @@ int kinDlsDenseDQJac(long int N,
   return(retval);
 }
 
-/*
- * -----------------------------------------------------------------
- * kinDlsBandDQJac
- * -----------------------------------------------------------------
- * This routine generates a banded difference quotient approximation to
- * the Jacobian of F(u).  It assumes that a band matrix of type
- * BandMat is stored column-wise, and that elements within each column
- * are contiguous. This makes it possible to get the address of a column
- * of J via the macro BAND_COL and to write a simple for loop to set
- * each of the elements of a column in succession.
- *
- * NOTE: Any type of failure of the system function her leads to an
- *       unrecoverable failure of the Jacobian function and thus
- *       of the linear solver setup function, stopping KINSOL.
- * -----------------------------------------------------------------
- */
 
-int kinDlsBandDQJac(long int N, long int mupper, long int mlower,
-                    N_Vector u, N_Vector fu,
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2)
+/*------------------------------------------------------------------
+  kinDlsBandDQJac
+
+  This routine generates a banded difference quotient approximation
+  to the Jacobian of F(u).  It assumes a SUNBandMatrix input stored
+  column-wise, and that elements within each column are contiguous.
+  This makes it possible to get the address of a column of J via the
+  function SUNBandMatrix_Column() and to write a simple for loop to
+  set each of the elements of a column in succession.
+ 
+  NOTE: Any type of failure of the system function her leads to an
+        unrecoverable failure of the Jacobian function and thus of
+        the linear solver setup function, stopping KINSOL.
+  ------------------------------------------------------------------*/
+int kinDlsBandDQJac(N_Vector u, N_Vector fu, SUNMatrix Jac,
+                    KINMem kin_mem, N_Vector tmp1, N_Vector tmp2)
 {
   realtype inc, inc_inv;
   N_Vector futemp, utemp;
-  int retval;
-  long int group, i, j, width, ngroups, i1, i2;
+  sunindextype group, i, j, width, ngroups, i1, i2;
+  sunindextype N, mupper, mlower;
   realtype *col_j, *fu_data, *futemp_data, *u_data, *utemp_data, *uscale_data;
-
-  KINMem kin_mem;
+  int retval = 0;
   KINDlsMem kindls_mem;
 
-  /* data points to kinmem */
-  kin_mem = (KINMem) data;
-  kindls_mem = (KINDlsMem) lmem;
+  /* access DlsMem interface structure */
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
+
+  /* access matrix dimensions */
+  N = SUNBandMatrix_Columns(Jac);
+  mupper = SUNBandMatrix_UpperBandwidth(Jac);
+  mlower = SUNBandMatrix_LowerBandwidth(Jac);
 
   /* Rename work vectors for use as temporary values of u and fu */
   futemp = tmp1;
-  utemp = tmp2;
+  utemp  = tmp2;
 
   /* Obtain pointers to the data for ewt, fy, futemp, y, ytemp */
-  fu_data    = N_VGetArrayPointer(fu);
+  fu_data     = N_VGetArrayPointer(fu);
   futemp_data = N_VGetArrayPointer(futemp);
-  u_data     = N_VGetArrayPointer(u);
-  uscale_data = N_VGetArrayPointer(uscale);
-  utemp_data = N_VGetArrayPointer(utemp);
+  u_data      = N_VGetArrayPointer(u);
+  uscale_data = N_VGetArrayPointer(kin_mem->kin_uscale);
+  utemp_data  = N_VGetArrayPointer(utemp);
 
   /* Load utemp with u */
   N_VScale(ONE, u, utemp);
 
   /* Set bandwidth and number of column groups for band differencing */
-  width = mlower + mupper + 1;
+  width   = mlower + mupper + 1;
   ngroups = SUNMIN(width, N);
   
   for (group=1; group <= ngroups; group++) {
     
     /* Increment all utemp components in group */
     for(j=group-1; j < N; j+=width) {
-      inc = sqrt_relfunc*SUNMAX(SUNRabs(u_data[j]), ONE/SUNRabs(uscale_data[j]));
+      inc = kin_mem->kin_sqrt_relfunc*SUNMAX(SUNRabs(u_data[j]),
+                                             ONE/SUNRabs(uscale_data[j]));
       utemp_data[j] += inc;
     }
 
     /* Evaluate f with incremented u */
-    retval = func(utemp, futemp, user_data);
-    if (retval != 0) return(-1); 
+    retval = kin_mem->kin_func(utemp, futemp, kin_mem->kin_user_data);
+    if (retval != 0) return(retval); 
 
     /* Restore utemp components, then form and load difference quotients */
     for (j=group-1; j < N; j+=width) {
       utemp_data[j] = u_data[j];
-      col_j = BAND_COL(Jac,j);
-      inc = sqrt_relfunc*SUNMAX(SUNRabs(u_data[j]), ONE/SUNRabs(uscale_data[j]));
+      col_j = SUNBandMatrix_Column(Jac, j);
+      inc = kin_mem->kin_sqrt_relfunc*SUNMAX(SUNRabs(u_data[j]),
+                                             ONE/SUNRabs(uscale_data[j]));
       inc_inv = ONE/inc;
       i1 = SUNMAX(0, j-mupper);
       i2 = SUNMIN(j+mlower, N-1);
       for (i=i1; i <= i2; i++)
-        BAND_COL_ELEM(col_j,i,j) = inc_inv * (futemp_data[i] - fu_data[i]);
+        SM_COLUMN_ELEMENT_B(col_j,i,j) = inc_inv * (futemp_data[i] - fu_data[i]);
     }
   }
   
   /* Increment counter nfeDQ */
-  nfeDQ += ngroups;
+  kindls_mem->nfeDQ += ngroups;
 
   return(0);
 }
 
 
+/*------------------------------------------------------------------
+  kinDlsInitialize performs remaining initializations specific to 
+  the direct linear solver interface (and solver itself)
+  ------------------------------------------------------------------*/
+int kinDlsInitialize(KINMem kin_mem)
+{
+  KINDlsMem kindls_mem;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) {
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", 
+                    "kinDlsInitialize", MSGD_KINMEM_NULL);
+    return(KINDLS_MEM_NULL);
+  }
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", 
+                    "kinDlsInitialize", MSGD_LMEM_NULL);
+    return(KINDLS_LMEM_NULL);
+  }
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
+  
+  kinDlsInitializeCounters(kindls_mem);
+
+  /* Set Jacobian function and data, depending on jacDQ (in case 
+     it has changed based on user input) */
+  if (kindls_mem->jacDQ) {
+    kindls_mem->jac    = kinDlsDQJac;
+    kindls_mem->J_data = kin_mem;
+  } else {
+    kindls_mem->J_data = kin_mem->kin_user_data;
+  }
+
+  if ( (kin_mem->kin_globalstrategy == KIN_PICARD) && kindls_mem->jacDQ ) {
+    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL",
+                    "kinDlsInitialize", MSG_NOL_FAIL);
+    return(KIN_ILL_INPUT);
+  }
+
+  /* Call LS initialize routine */
+  kindls_mem->last_flag = SUNLinSolInitialize(kindls_mem->LS);
+  return(kindls_mem->last_flag);
+}
+
+
+/*------------------------------------------------------------------
+  kinDlsSetup does the setup operations for the KINDLS linear solver
+  interface. It calls the Jacobian evaluation routine, updates 
+  counters, and calls the LS 'setup' routine to prepare for 
+  subsequent calls to the LS 'solve' routine.
+
+  The return value is either
+     KINLS_SUCCESS = 0  if successful,
+      1  if the LS 'setup' routine failed recoverably, or
+     -1  if the jac or LS 'setup' routines failed unrecoverably.
+  ------------------------------------------------------------------*/
+int kinDlsSetup(KINMem kin_mem)
+{
+  KINDlsMem kindls_mem;
+  int retval;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) {
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", 
+                    "kinDlsSetup", MSGD_KINMEM_NULL);
+    return(KINDLS_MEM_NULL);
+  }
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", 
+                    "kinDlsSetup", MSGD_LMEM_NULL);
+    return(KINDLS_LMEM_NULL);
+  }
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
+
+  /* Increment nje counter. */
+  kindls_mem->nje++;
+
+  /* Zero out J; call Jacobian routine jac; return if it failed. */
+  retval = SUNMatZero(kindls_mem->J);
+  if (retval != 0) {
+    KINProcessError(kin_mem, KINDLS_SUNMAT_FAIL, "KINDLS",
+                    "kinDlsSetup", MSGD_MATZERO_FAILED);
+    kindls_mem->last_flag = KINDLS_SUNMAT_FAIL;
+    return(-1);
+  }
+
+  retval = kindls_mem->jac(kin_mem->kin_uu, kin_mem->kin_fval, kindls_mem->J,
+                           kindls_mem->J_data, kin_mem->kin_vtemp1, kin_mem->kin_vtemp2);
+  if (retval != 0) {
+    KINProcessError(kin_mem, KINDLS_JACFUNC_ERR, "KINDLS",
+                    "kinDlsSetup", MSGD_JACFUNC_FAILED);
+    kindls_mem->last_flag = KINDLS_JACFUNC_ERR;
+    return(-1);
+  }
+
+  /* Call generic linear solver 'setup' with this system matrix, and
+     return success/failure flag */
+  kindls_mem->last_flag = SUNLinSolSetup(kindls_mem->LS, kindls_mem->J);
+  return(kindls_mem->last_flag);
+}
+
+
+/*------------------------------------------------------------------
+  kinDlsSolve interfaces between KINSOL and the generic 
+  SUNLinearSolver object LS, by calling the LS 'solve' routine
+
+  The return value is KINLS_SUCCESS = 0 if successful. The argument
+  *sJpnorm is ignored.
+  ------------------------------------------------------------------*/
+int kinDlsSolve(KINMem kin_mem, N_Vector x, N_Vector b,
+                realtype *sJpnorm, realtype *sFdotJp)
+{
+  KINDlsMem kindls_mem;
+  int retval;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) {
+    KINProcessError(NULL, KINDLS_MEM_NULL, "KINDLS", 
+		    "kinDlsSolve", MSGD_KINMEM_NULL);
+    return(KINDLS_MEM_NULL);
+  }
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINDLS_LMEM_NULL, "KINDLS", 
+		    "kinDlsSolve", MSGD_LMEM_NULL);
+    return(KINDLS_LMEM_NULL);
+  }
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
+
+  /* call the generic linear system solver */
+  retval = SUNLinSolSolve(kindls_mem->LS, kindls_mem->J, x, b, ZERO);
+
+  /*
+    Compute the term sFdotJp for use in the linesearch routine.
+    This term is subsequently corrected if the step is reduced by
+    constraints or the linesearch.
+    
+    sFdotJp is the dot product of the scaled f vector and the scaled
+    vector J*p, where the scaling uses fscale.
+  */
+  N_VProd(b, kin_mem->kin_fscale, b);
+  N_VProd(b, kin_mem->kin_fscale, b);
+  *sFdotJp = N_VDotProd(kin_mem->kin_fval, b);
+  
+  /* store solver return value and return */
+  kindls_mem->last_flag = retval;
+  return(retval);
+}
+
+
+/*------------------------------------------------------------------
+  kinDlsFree frees memory associates with the KINDls system solver
+  interface.
+  ------------------------------------------------------------------*/
+int kinDlsFree(KINMem kin_mem)
+{
+  KINDlsMem kindls_mem;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) return(KINDLS_SUCCESS);
+  if (kin_mem->kin_lmem == NULL) return(KINDLS_SUCCESS);
+  kindls_mem = (KINDlsMem) kin_mem->kin_lmem;
+
+  /* Nullify SUNMatrix pointer */
+  kindls_mem->J = NULL;
+
+  /* free KINDls interface structure */
+  free(kin_mem->kin_lmem);
+  kindls_mem = NULL;
+  
+  return(KINDLS_SUCCESS);
+}
+
+
+/*------------------------------------------------------------------
+  kinDlsInitializeCounters resets counters for the DLS interface
+  ------------------------------------------------------------------*/
 int kinDlsInitializeCounters(KINDlsMem kindls_mem)
 {
-  kindls_mem->d_nje   = 0;
-  kindls_mem->d_nfeDQ = 0;
+  kindls_mem->nje   = 0;
+  kindls_mem->nfeDQ = 0;
   
   return(0);
 }
diff --git a/src/kinsol/kinsol_direct_impl.h b/src/kinsol/kinsol_direct_impl.h
index db1e2f0..9c6de9a 100644
--- a/src/kinsol/kinsol_direct_impl.h
+++ b/src/kinsol/kinsol_direct_impl.h
@@ -1,9 +1,6 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
@@ -16,81 +13,74 @@
  * LLNS Copyright End
  * -----------------------------------------------------------------
  * Common implementation header file for the KINDLS linear solvers.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _KINDLS_IMPL_H
 #define _KINDLS_IMPL_H
 
 #include <kinsol/kinsol_direct.h>
+#include "kinsol_impl.h"
 
 #ifdef __cplusplus  /* wrapper to enable C++ usage */
 extern "C" {
 #endif
 
-
-/*
- * -----------------------------------------------------------------
- * Types: KINDlsMemRec, KINDlsMem                             
- * -----------------------------------------------------------------
- * The type KINDlsMem is pointer to a KINDlsMemRec.
- * This structure contains KINDLS solver-specific data. 
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Types: KINDlsMemRec, KINDlsMem                             
+  ------------------------------------------------------------------
+  The type KINDlsMem is pointer to a KINDlsMemRec.
+  This structure contains KINDLS solver-specific data. 
+  ------------------------------------------------------------------*/
 
 typedef struct KINDlsMemRec {
 
-  int d_type;              /* SUNDIALS_DENSE or SUNDIALS_BAND              */
-
-  long int d_n;            /* problem dimension                            */
+  booleantype jacDQ;   /* SUNTRUE if using internal DQ Jacobian approx. */
+  KINDlsJacFn jac;     /* Jacobian routine to be called                 */
+  void *J_data;        /* J_data is passed to jac                       */
+  
+  SUNLinearSolver LS;  /* generic direct linear solver object           */
 
-  long int d_ml;           /* lower bandwidth of Jacobian                  */
-  long int d_mu;           /* upper bandwidth of Jacobian                  */ 
-  long int d_smu;          /* upper bandwith of M = MIN(N-1,d_mu+d_ml)     */
+  SUNMatrix J;         /* problem Jacobian                              */
 
-  booleantype d_jacDQ;     /* TRUE if using internal DQ Jacobian approx.   */
-  KINDlsDenseJacFn d_djac; /* dense Jacobian routine to be called          */
-  KINDlsBandJacFn d_bjac;  /* band Jacobian routine to be called           */
-  void *d_J_data;          /* J_data is passed to djac or bjac             */
-    
-  DlsMat d_J;              /* problem Jacobian                             */
-    
-  int *d_pivots;           /* int pivot array for PM = LU                  */
-  long int *d_lpivots;     /* long int pivot array for PM = LU             */
+  long int nje  ;      /* no. of calls to jac                           */
     
-  long int d_nje;          /* no. of calls to jac                          */
+  long int nfeDQ;      /* no. of calls to F due to DQ Jacobian approx.  */
     
-  long int d_nfeDQ;        /* no. of calls to F due to DQ Jacobian approx. */
-    
-  long int d_last_flag;    /* last error return flag                       */
+  long int last_flag;  /* last error return flag                        */
     
 } *KINDlsMem;
 
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Prototypes of internal functions
+  ------------------------------------------------------------------*/
+
+/* difference-quotient Jacobian approximation routines */
+int kinDlsDQJac(N_Vector u, N_Vector fu, SUNMatrix Jac,
+                void *data, N_Vector tmp1, N_Vector tmp2);
+
+int kinDlsDenseDQJac(N_Vector u, N_Vector fu, SUNMatrix Jac,
+                     KINMem kin_mem, N_Vector tmp1, N_Vector tmp2);
 
-int kinDlsDenseDQJac(long int N,
-                     N_Vector u, N_Vector fu,
-                     DlsMat Jac, void *data,
-                     N_Vector tmp1, N_Vector tmp2);
+int kinDlsBandDQJac(N_Vector u, N_Vector fu, SUNMatrix Jac,
+                    KINMem kin_mem, N_Vector tmp1, N_Vector tmp2);
 
-int kinDlsBandDQJac(long int N, long int mupper, long int mlower,
-                    N_Vector u, N_Vector fu,
-                    DlsMat Jac, void *data,
-                    N_Vector tmp1, N_Vector tmp2);
+/* generic linit/lsetup/lsolve/lfree interface routines for KINSOL to call */
+int kinDlsInitialize(KINMem kin_mem);
+
+int kinDlsSetup(KINMem kin_mem);
+
+int kinDlsSolve(KINMem kin_mem, N_Vector x, N_Vector b,
+                realtype *sJpnorm, realtype *sFdotJp);
+                  
+int kinDlsFree(KINMem kin_mem);
 
 /* Auxilliary functions */
 int kinDlsInitializeCounters(KINDlsMem kindls_mem);
 
-/*
- * -----------------------------------------------------------------
- * Error Messages
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Error Messages
+  ------------------------------------------------------------------*/
 
 #define MSGD_KINMEM_NULL "KINSOL memory is NULL."
 #define MSGD_BAD_NVECTOR "A required vector operation is not implemented."
@@ -98,6 +88,7 @@ int kinDlsInitializeCounters(KINDlsMem kindls_mem);
 #define MSGD_LMEM_NULL   "Linear solver memory is NULL."
 #define MSGD_BAD_SIZES   "Illegal bandwidth parameter(s). Must have 0 <=  ml, mu <= N-1."
 #define MSGD_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
+#define MSGD_MATZERO_FAILED "The SUNMatZero routine failed in an unrecoverable manner."
 
 #ifdef __cplusplus
 }
diff --git a/src/kinsol/kinsol_impl.h b/src/kinsol/kinsol_impl.h
index 7994b5d..77dc8eb 100644
--- a/src/kinsol/kinsol_impl.h
+++ b/src/kinsol/kinsol_impl.h
@@ -1,8 +1,5 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -84,8 +81,6 @@ typedef struct KINMemRec {
 				  and KIN_ETACHOICE2                           */
   booleantype kin_noMinEps;    /* flag controlling whether or not the value
 				  of eps is bounded below                      */
-  booleantype kin_setupNonNull;   /* flag indicating if linear solver setup
-				     routine is non-null and if setup is used  */
   booleantype kin_constraintsSet; /* flag indicating if constraints are being
 				     used                                      */
   booleantype kin_jacCurrent;     /* flag indicating if the Jacobian info. 
@@ -164,15 +159,15 @@ typedef struct KINMemRec {
   realtype *kin_gamma_aa;   /* array of size maa used in AA */
   realtype *kin_R_aa;       /* array of size maa*maa used in AA */
   int      *kin_ipt_map;    /* array of size maa used in AA */
-  long int kin_m_aa;	    /* parameter for AA, Broyden or NLEN */
+  sunindextype kin_m_aa;    /* parameter for AA, Broyden or NLEN */
   booleantype kin_aamem_aa; /* sets additional memory needed for Anderson Acc */
   booleantype kin_setstop_aa; /* determines whether user will set stopping criterion */
 
   /* space requirements for vector storage */ 
 
-  long int kin_lrw1;        /* number of realtype-sized memory blocks needed
+  sunindextype kin_lrw1;    /* number of realtype-sized memory blocks needed
 			       for a single N_Vector                           */ 
-  long int kin_liw1;        /* number of int-sized memory blocks needed for
+  sunindextype kin_liw1;    /* number of int-sized memory blocks needed for
 			       a single N_Vecotr                               */ 
   long int kin_lrw;         /* total number of realtype-sized memory blocks
 			       needed for all KINSOL work vectors              */
@@ -194,8 +189,8 @@ typedef struct KINMemRec {
 
   booleantype kin_inexact_ls; /* flag set by the linear solver module
 				 (in linit) indicating whether this is an
-				 iterative linear solver (TRUE), or a direct
-				 linear solver (FALSE)                         */
+				 iterative linear solver (SUNTRUE), or a direct
+				 linear solver (SUNFALSE)                       */
 
   void *kin_lmem;         /* pointer to linear solver memory block             */
 
@@ -266,7 +261,7 @@ typedef struct KINMemRec {
  * but system memory allocation should be done by the subroutine
  * that actually initializes the environment for liner solver
  * package. If the linear system is to be preconditioned, then the
- * variable setupNonNull (type booleantype) should be set to TRUE
+ * variable setupNonNull (type booleantype) should be set to SUNTRUE
  * (predefined constant) and the kin_lsetup routine should be
  * appropriately defined.
  *
diff --git a/src/kinsol/kinsol_io.c b/src/kinsol/kinsol_io.c
index 08d67b3..fd85611 100644
--- a/src/kinsol/kinsol_io.c
+++ b/src/kinsol/kinsol_io.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4368 $
- * $Date: 2015-02-12 12:25:15 -0800 (Thu, 12 Feb 2015) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
  *                Aaron Collier @ LLNL
@@ -214,7 +214,7 @@ int KINSetMAA(void *kinmem, long int maa)
 
   kin_mem = (KINMem) kinmem;
   kin_mem->kin_m_aa = maa;
-  kin_mem->kin_aamem_aa = (maa == 0) ? FALSE : TRUE;
+  kin_mem->kin_aamem_aa = (maa == 0) ? SUNFALSE : SUNTRUE;
 
   return(KIN_SUCCESS);
 }
@@ -768,7 +768,7 @@ int KINSetConstraints(void *kinmem, N_Vector constraints)
       lrw -= lrw1;
       liw -= liw1;
     }
-    kin_mem->kin_constraintsSet = FALSE;
+    kin_mem->kin_constraintsSet = SUNFALSE;
     return(KIN_SUCCESS);
   }
 
@@ -784,7 +784,7 @@ int KINSetConstraints(void *kinmem, N_Vector constraints)
     kin_mem->kin_constraints = N_VClone(constraints);
     lrw += lrw1;
     liw += liw1;
-    kin_mem->kin_constraintsSet = TRUE;
+    kin_mem->kin_constraintsSet = SUNTRUE;
   }
 
   /* Load the constraint vector */
diff --git a/src/kinsol/kinsol_klu.c b/src/kinsol/kinsol_klu.c
deleted file mode 100644
index 646684e..0000000
--- a/src/kinsol/kinsol_klu.c
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINKLU linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <sundials/sundials_math.h>
-
-#include "kinsol/kinsol_klu.h"
-#include "kinsol_impl.h"
-#include "kinsol_sparse_impl.h"
-#include "sundials/sundials_klu_impl.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-#define TWOTHIRDS    RCONST(0.6666666666666667)
-
-/* KINKLU linit, lsetup, lsolve, and lfree routines */
- 
-static int kinKLUInit(KINMem kin_mem);
-static int kinKLUSetup(KINMem kin_mem);
-static int kinKLUSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-		       realtype *sJpnorm, realtype *sFdotJp);		       
-static int kinKLUFree(KINMem kin_mem);
-
-/*
- * -----------------------------------------------------------------
- * KINKLU
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the KINSOL / KLU linear solver module.  
- * KINKLU first calls the existing lfree routine if this is not NULL.
- * Then it sets the kin_linit, kin_lsetup, kin_lsolve, kin_lperf, and
- * kin_lfree fields in (*kin_mem) to be kinKLUInit, kinKLUSetup,
- * kinKLUSolve, NULL, and kinKLUFree, respectively.
- * It allocates memory for a structure of type kinkluMemRec and sets
- * the kin_lmem field in (*kin_mem) to the address of this structure.
- * It sets setupNonNull in (*kin_mem) to TRUE.
- * Finally, it allocates memory for KLU.
- * The return value is KINSLS_SUCCESS = 0, KINSLS_LMEM_FAIL = -1,
- * or KINSLS_ILL_INPUT = -2.
- *
- * NOTE: The KLU linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, KINKLU will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int KINKLU(void *kin_mem_v, int n, int nnz, int sparsetype)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-  KLUData klu_data;
-  int flag;
-
-  /* Return immediately if kin_mem is NULL. */
-  if (kin_mem_v == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINKLU", 
-                    MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kin_mem_v;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (kin_mem->kin_vtemp1->ops->nvgetarraypointer == NULL) {
-    KINProcessError(kin_mem, KINSLS_ILL_INPUT, "KINSLS", "KINKLU", 
-                    MSGSP_BAD_NVECTOR);
-    return(KINSLS_ILL_INPUT);
-  }
-
-  if (kin_mem->kin_lfree != NULL) kin_mem->kin_lfree(kin_mem);
-
-  /* Set five main function fields in kin_mem. */
-  kin_mem->kin_linit  = kinKLUInit;
-  kin_mem->kin_lsetup = kinKLUSetup;
-  kin_mem->kin_lsolve = kinKLUSolve;
-  kin_mem->kin_lfree  = kinKLUFree;
-
-  /* Get memory for kinSlsMemRec. */
-  kinsls_mem = (KINSlsMem) malloc(sizeof(struct KINSlsMemRec));
-  if (kinsls_mem == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "KINKLU", 
-                    MSGSP_MEM_FAIL);
-    return(KINSLS_MEM_FAIL);
-  }
-
-  /* Get memory for KLUData. */
-  klu_data = (KLUData)malloc(sizeof(struct KLUDataRec));
-  if (klu_data == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "KINKLU", 
-                    MSGSP_MEM_FAIL);
-    return(KINSLS_MEM_FAIL);
-  }
-
-  kin_mem->kin_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  kinsls_mem->s_jaceval = NULL;
-  kinsls_mem->s_jacdata = NULL;
-
-  /* Allocate memory for the sparse Jacobian */
-  kinsls_mem->s_JacMat = SparseNewMat(n, n, nnz, sparsetype);
-  if (kinsls_mem->s_JacMat == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "KINKLU", 
-                    MSGSP_MEM_FAIL);
-    return(KINSLS_MEM_FAIL);
-  }
-
-  /* Initialize KLU structures */
-  switch (sparsetype) {
-    case CSC_MAT:
-      klu_data->sun_klu_solve = &klu_solve;
-      break;
-    case CSR_MAT:
-      klu_data->sun_klu_solve = &klu_tsolve;
-      break;
-    default:
-      SparseDestroyMat(kinsls_mem->s_JacMat);
-      free(klu_data);
-      free(kinsls_mem);
-      return(KINSLS_ILL_INPUT);
-  }
-  klu_data->s_Symbolic = NULL;
-  klu_data->s_Numeric = NULL;
-
-  /* Set default parameters for KLU */
-  flag = klu_defaults(&klu_data->s_Common);
-  if (flag == 0) {
-    KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", "KINKLU", 
-                    MSGSP_PACKAGE_FAIL);
-    return(KINSLS_PACKAGE_FAIL);
-  }
-  /* Set ordering to COLAMD as the kinsol default use.
-     Users can set a different value with KINKLUSetOrdering,
-     and the user-set value is loaded before any call to klu_analyze in
-     kinKLUSetup.  */
-  klu_data->s_ordering = 1;
-  klu_data->s_Common.ordering = klu_data->s_ordering;
-
-  /* This is a direct linear solver */
-  kin_mem->kin_inexact_ls = FALSE;
-
-  /* Attach linear solver memory to the nonlinear solver memory */
-  kinsls_mem->s_solver_data = (void *) klu_data;
-  kin_mem->kin_lmem = kinsls_mem;
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-
-  return(KINSLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * KINKLUReInit
- * -----------------------------------------------------------------
- * This routine reinitializes memory and flags for a new factorization 
- * (symbolic and numeric) to be conducted at the next solver setup
- * call.  This routine is useful in the cases where the number of nonzeroes 
- * has changed or if the structure of the linear system has changed
- * which would require a new symbolic (and numeric factorization).
- *
- * The reinit_type argumenmt governs the level of reinitialization:
- *
- * reinit_type = 1: The Jacobian matrix will be destroyed and 
- *                  a new one will be allocated based on the nnz
- *                  value passed to this call. New symbolic and
- *                  numeric factorizations will be completed at the next
- *                  solver setup.
- *
- * reinit_type = 2: Only symbolic and numeric factorizations will be 
- *                  completed.  It is assumed that the Jacobian size
- *                  has not exceeded the size of nnz given in the prior
- *                  call to KINKLU.
- *
- * This routine assumes no other changes to solver use are necessary.
- *
- * The return value is KINSLS_SUCCESS = 0, KINSLS_MEM_NULL = -1, 
- * KINSLS_LMEM_NULL = -2, KINSLS_ILL_INPUT = -3, or KINSLS_MEM_FAIL = -4.
- *
- * -----------------------------------------------------------------
- */
-
-int KINKLUReInit(void *kin_mem_v, int n, int nnz, int reinit_type)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-  KLUData klu_data;
-
-  /* Return immediately if kin_mem is NULL. */
-  if (kin_mem_v == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINKLUReInit", 
-                    MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kin_mem_v;
-
-  /* Return immediately if kin_lmem is NULL. */
-  if (kin_mem->kin_lmem == NULL) {
-    KINProcessError(NULL, KINSLS_LMEM_NULL, "KINSLS", "KINKLUReInit", 
-                    MSGSP_LMEM_NULL);
-    return(KINSLS_LMEM_NULL);
-  }
-  kinsls_mem = (KINSlsMem) (kin_mem->kin_lmem);
-  klu_data = (KLUData) kinsls_mem->s_solver_data;
-
-  /* Return if reinit_type is not valid */
-  if ((reinit_type != 1) && (reinit_type != 2)) {
-    KINProcessError(NULL, KINSLS_ILL_INPUT, "KINSLS", "KINKLUReInit", 
-                    MSGSP_ILL_INPUT);
-    return(KINSLS_ILL_INPUT);
-  }
-
-  if (reinit_type == 1) {
-
-    /* Destroy previous Jacobian information */
-    if (kinsls_mem->s_JacMat) {
-      SparseDestroyMat(kinsls_mem->s_JacMat);
-    }
-
-    /* Allocate memory for the sparse Jacobian */
-    kinsls_mem->s_JacMat = SparseNewMat(n, n, nnz, kinsls_mem->sparsetype);
-    if (kinsls_mem->s_JacMat == NULL) {
-      KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "KINKLU", 
-                      MSGSP_MEM_FAIL);
-      return(KINSLS_MEM_FAIL);
-    }
-  }
-
-  /* Free the prior factorazation and reset for first factorization */
-  if( klu_data->s_Symbolic != NULL)
-    klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  if( klu_data->s_Numeric != NULL)
-    klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  kinsls_mem->s_first_factorize = 1;
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * KINKLU interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the KINKLU
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int kinKLUInit(KINMem kin_mem)
-{
-  KINSlsMem kinsls_mem;
-
-  kinsls_mem = (KINSlsMem)kin_mem->kin_lmem;
-
-  kinsls_mem->s_jacdata = kin_mem->kin_user_data;
-
-  kinsls_mem->s_nje = 0;
-  /* This forces factorization for every call to KINSol */
-  kinsls_mem->s_first_factorize = 1;
-
-  kinsls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the KINKLU linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     KINSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int kinKLUSetup(KINMem kin_mem)
-{
-  int retval;
-  KINSlsMem kinsls_mem;
-  KINSlsSparseJacFn jaceval;
-  KLUData klu_data;
-  SlsMat JacMat;
-  void *jacdata;
-  realtype uround_twothirds;
-
-  uround_twothirds = SUNRpowerR(kin_mem->kin_uround,TWOTHIRDS);
-
-  kinsls_mem = (KINSlsMem) (kin_mem->kin_lmem);
-
-  klu_data = (KLUData) kinsls_mem->s_solver_data;
-
-  jaceval = kinsls_mem->s_jaceval;
-  jacdata = kinsls_mem->s_jacdata;
-  JacMat = kinsls_mem->s_JacMat;
-
-  /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    KINProcessError(kin_mem, KINSLS_JAC_NOSET, "KINSLS", "kinKLUSetup", 
-		    MSGSP_JAC_NOSET);
-    free(kinsls_mem); kinsls_mem = NULL;
-    return(KINSLS_JAC_NOSET);
-  }
-
-  /* Increment nje counter and call Jacobian eval routine. */
-  kinsls_mem->s_nje++;
-  retval = jaceval(kin_mem->kin_uu, kin_mem->kin_fval, JacMat, jacdata, 
-		   kin_mem->kin_vtemp1, kin_mem->kin_vtemp2);
-
-  if (retval < 0) {
-    KINProcessError(kin_mem, KINSLS_JACFUNC_UNRECVR, "KINSLS", 
-		    "kinKLUSetup", MSGSP_JACFUNC_FAILED);
-    kinsls_mem->s_last_flag = KINSLS_JACFUNC_UNRECVR;
-    return(KINSLS_JACFUNC_UNRECVR);
-  }
-  if (retval == 1) {
-    kinsls_mem->s_first_factorize = 1;
-  }
-  if (retval > 1) {
-    kinsls_mem->s_last_flag = KINSLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  if (kinsls_mem->s_first_factorize) {
-    /* ------------------------------------------------------------
-       Get the symbolic factorization
-       ------------------------------------------------------------*/ 
-    /* Update the ordering option with any user-updated values from 
-       calls to KINKLUSetOrdering */
-    klu_data->s_Common.ordering = klu_data->s_ordering;
-
-    if (klu_data->s_Symbolic != NULL) {
-       klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-    }
-    klu_data->s_Symbolic = klu_analyze(JacMat->NP, JacMat->indexptrs, 
-				       JacMat->indexvals, &(klu_data->s_Common));
-    if (klu_data->s_Symbolic == NULL) {
-      KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", "kinKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(KINSLS_PACKAGE_FAIL);
-    }
-
-    /* ------------------------------------------------------------
-       Compute the LU factorization of the Jacobian.
-       ------------------------------------------------------------*/
-    /* If klu_factor previously called, free data */
-    if( klu_data->s_Numeric != NULL) {
-       klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-    }
-    klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-				     JacMat->data, klu_data->s_Symbolic, 
-				     &(klu_data->s_Common));
-
-    if (klu_data->s_Numeric == NULL) {
-      KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", "kinKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(KINSLS_PACKAGE_FAIL);
-    }
-
-    kinsls_mem->s_first_factorize = 0;
-
-  }
-  else {
-    
-    retval = klu_refactor(JacMat->indexptrs, JacMat->indexvals, JacMat->data, 
-			klu_data->s_Symbolic, klu_data->s_Numeric,
-			&(klu_data->s_Common));
-    if (retval == 0) {
-      KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", "kinKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(KINSLS_PACKAGE_FAIL);
-    }
-
-    /*-----------------------------------------------------------
-      Check if a cheap estimate of the reciprocal of the condition 
-      number is getting too small.  If so, delete
-      the prior numeric factorization and recompute it.
-      -----------------------------------------------------------*/
-    
-    retval = klu_rcond(klu_data->s_Symbolic, klu_data->s_Numeric,
-		       &(klu_data->s_Common));
-    if (retval == 0) {
-      KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", "kinKLUSetup", 
-		      MSGSP_PACKAGE_FAIL);
-      return(KINSLS_PACKAGE_FAIL);
-    }
-
-# if 1
-    if ( (klu_data->s_Common.rcond)  < uround_twothirds ) {
-      
-      /* Condition number may be getting large.  
-	 Compute more accurate estimate */
-      retval = klu_condest(JacMat->indexptrs, JacMat->data, 
-			   klu_data->s_Symbolic, klu_data->s_Numeric,
-			   &(klu_data->s_Common));
-      if (retval == 0) {
-	KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", "kinKLUSetup", 
-			MSGSP_PACKAGE_FAIL);
-	return(KINSLS_PACKAGE_FAIL);
-      }
-      
-      if ( (klu_data->s_Common.condest) > 
-	   (1.0/uround_twothirds) ) {
-
-	/* More accurate estimate also says condition number is 
-	   large, so recompute the numeric factorization */
-
-	klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-	
-	klu_data->s_Numeric = klu_factor(JacMat->indexptrs, JacMat->indexvals, 
-					 JacMat->data, klu_data->s_Symbolic, 
-					 &(klu_data->s_Common));
-
-	if (klu_data->s_Numeric == NULL) {
-	  KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", 
-			  "kinKLUSetup", MSGSP_PACKAGE_FAIL);
-	  return(KINSLS_PACKAGE_FAIL);
-	}
-      }
-    }
-#endif 
-
-  }
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the KINKLU linear
-  solver module.  It calls the KLU solve routine, 
-  then returns KINSLS_SUCCESS = 0.
-*/
-
-static int kinKLUSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-		       realtype *sJpnorm, realtype *sFdotJp)		       
-{
-  int flag;
-  KINSlsMem kinsls_mem;
-  KLUData klu_data;
-  SlsMat JacMat;
-  realtype *xd;
-  
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-  JacMat = kinsls_mem->s_JacMat;
-
-  klu_data = (KLUData) kinsls_mem->s_solver_data;
-
-  /* Copy the right-hand side into x */
-  N_VScale(ONE, b, x);
-  xd = N_VGetArrayPointer(x);
-
-  /* Call KLU to solve the linear system */
-  flag = klu_data->sun_klu_solve(klu_data->s_Symbolic, klu_data->s_Numeric, JacMat->NP, 1, xd, 
-                                 &(klu_data->s_Common));
-  if (flag == 0) {
-    KINProcessError(kin_mem, KINSLS_PACKAGE_FAIL, "KINSLS", "kinKLUSolve", 
-		    MSGSP_PACKAGE_FAIL);
-    return(KINSLS_PACKAGE_FAIL);
-  }
-
-  /* Compute the term sFdotJp for use in the linesearch routine.
-     This term is subsequently corrected if the step is reduced by
-     constraints or the linesearch.
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  N_VProd(b, kin_mem->kin_fscale, b);
-  N_VProd(b, kin_mem->kin_fscale, b);
-  *sFdotJp = N_VDotProd(kin_mem->kin_fval, b);
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-  return(KINSLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the KINKLU linear solver.
-*/
-
-static int kinKLUFree(KINMem kin_mem)
-{
-  KINSlsMem kinsls_mem;
-  KLUData klu_data;
-  
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-  klu_data = (KLUData) kinsls_mem->s_solver_data;
-
-  if( klu_data->s_Numeric != NULL)
-  {
-     klu_free_numeric(&(klu_data->s_Numeric), &(klu_data->s_Common));
-  }
-  if( klu_data->s_Symbolic != NULL)
-  {
-     klu_free_symbolic(&(klu_data->s_Symbolic), &(klu_data->s_Common));
-  }
-
-  if (kinsls_mem->s_JacMat) {
-    SparseDestroyMat(kinsls_mem->s_JacMat);
-    kinsls_mem->s_JacMat = NULL;
-  }
-
-  free(klu_data); 
-  free(kin_mem->kin_lmem); 
-
-  return(0);
-}
-
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * KINKLUSetOrdering sets the ordering used by KLU for reducing fill.
- * Options are: 0 for AMD, 1 for COLAMD, and 2 for the natural ordering.
- * The default used in KINSOL is 1 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int KINKLUSetOrdering(void *kin_mem_v, int ordering_choice)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-  KLUData klu_data;
-
- /* Return immediately if kin_mem is NULL */
-  if (kin_mem_v == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINKLUSetOrdering",
-		    MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kin_mem_v;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) ) {
-    KINProcessError(NULL, KINSLS_ILL_INPUT, "KINSLS", "KINKLUSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(KINSLS_ILL_INPUT);
-  }
-
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-  klu_data = (KLUData) kinsls_mem->s_solver_data;
-
-  klu_data->s_ordering = ordering_choice;
-
-  return(KINSLS_SUCCESS);
-}
-
diff --git a/src/kinsol/kinsol_lapack.c b/src/kinsol/kinsol_lapack.c
deleted file mode 100644
index ceb6026..0000000
--- a/src/kinsol/kinsol_lapack.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer: Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for a KINSOL dense linear solver
- * using BLAS and LAPACK functions.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <kinsol/kinsol_lapack.h>
-#include "kinsol_direct_impl.h"
-#include "kinsol_impl.h"
-#include <sundials/sundials_math.h>
-
-/* Constants */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * PROTOTYPES FOR PRIVATE FUNCTIONS
- * =================================================================
- */
-
-/* KINLAPACK DENSE linit, lsetup, lsolve, and lfree routines */ 
-static int kinLapackDenseInit(KINMem kin_mem);
-static int kinLapackDenseSetup(KINMem kin_mem);
-static int kinLapackDenseSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                               realtype *sJpnorm, realtype *sFdotJp);
-static int kinLapackDenseFree(KINMem kin_mem);
-
-/* KINLAPACK BAND linit, lsetup, lsolve, and lfree routines */ 
-static int kinLapackBandInit(KINMem kin_mem);
-static int kinLapackBandSetup(KINMem kin_mem);
-static int kinLapackBandSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                              realtype *sJpnorm, realtype *sFdotJp);
-static int kinLapackBandFree(KINMem kin_mem);
-
-/*
- * =================================================================
- * READIBILITY REPLACEMENTS
- * =================================================================
- */
-
-#define lrw1           (kin_mem->kin_lrw1)
-#define liw1           (kin_mem->kin_liw1)
-#define func           (kin_mem->kin_func)
-#define printfl        (kin_mem->kin_printfl)
-#define linit          (kin_mem->kin_linit)
-#define lsetup         (kin_mem->kin_lsetup)
-#define lsolve         (kin_mem->kin_lsolve)
-#define lfree          (kin_mem->kin_lfree)
-#define lmem           (kin_mem->kin_lmem)
-#define inexact_ls     (kin_mem->kin_inexact_ls)
-#define uu             (kin_mem->kin_uu)
-#define fval           (kin_mem->kin_fval)
-#define uscale         (kin_mem->kin_uscale)
-#define fscale         (kin_mem->kin_fscale)
-#define sqrt_relfunc   (kin_mem->kin_sqrt_relfunc)
-#define errfp          (kin_mem->kin_errfp)
-#define infofp         (kin_mem->kin_infofp)
-#define setupNonNull   (kin_mem->kin_setupNonNull)
-#define vtemp1         (kin_mem->kin_vtemp1)
-#define vec_tmpl       (kin_mem->kin_vtemp1)
-#define vtemp2         (kin_mem->kin_vtemp2)
-
-#define mtype          (kindls_mem->d_type)
-#define n              (kindls_mem->d_n)
-#define ml             (kindls_mem->d_ml)
-#define mu             (kindls_mem->d_mu)
-#define smu            (kindls_mem->d_smu)
-#define jacDQ          (kindls_mem->d_jacDQ)
-#define djac           (kindls_mem->d_djac)
-#define bjac           (kindls_mem->d_bjac)
-#define J              (kindls_mem->d_J)
-#define pivots         (kindls_mem->d_pivots)
-#define nje            (kindls_mem->d_nje)
-#define nfeDQ          (kindls_mem->d_nfeDQ)
-#define J_data         (kindls_mem->d_J_data)
-#define last_flag      (kindls_mem->d_last_flag)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS
- * =================================================================
- */
-              
-/*
- * -----------------------------------------------------------------
- * KINLapackDense
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the linear solver module.  KINLapackDense first
- * calls the existing lfree routine if this is not NULL.  Then it sets
- * the kin_linit, kin_lsetup, kin_lsolve, kin_lfree fields in (*kinmem)
- * to be kinLapackDenseInit, kinLapackDenseSetup, kinLapackDenseSolve, 
- * and kinLapackDenseFree, respectively.  It allocates memory for a 
- * structure of type KINDlsMemRec and sets the kin_lmem field in 
- * (*kinmem) to the address of this structure.  It sets lsetup_exists 
- * in (*kinmem) to TRUE, and the djac field to the default 
- * kinLapackDenseDQJac. Finally, it allocates memory for M, pivots, and 
- * (if needed) savedJ.
- *
- * NOTE: The dense linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, KINLapackDense will first 
- *       test for a compatible N_Vector internal representation 
- *       by checking that N_VGetArrayPointer and N_VSetArrayPointer 
- *       exist.
- * -----------------------------------------------------------------
- */
-int KINLapackDense(void *kinmem, int N)
-{
-  KINMem kin_mem;
-  KINDlsMem kindls_mem;
-
-  /* Return immediately if kinmem is NULL */
-  if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINLAPACK", "KINLapackDense", MSGD_KINMEM_NULL);
-    return(KINDLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* Test if the NVECTOR package is compatible with the DENSE solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL ||
-      vec_tmpl->ops->nvsetarraypointer == NULL) {
-    KINProcessError(kin_mem, KINDLS_ILL_INPUT, "KINLAPACK", "KINLapackDense", MSGD_BAD_NVECTOR);
-    return(KINDLS_ILL_INPUT);
-  }
-
-  if (lfree !=NULL) lfree(kin_mem);
-
-  /* Set four main function fields in kin_mem */
-  linit  = kinLapackDenseInit;
-  lsetup = kinLapackDenseSetup;
-  lsolve = kinLapackDenseSolve;
-  lfree  = kinLapackDenseFree;
-
-  /* Get memory for KINDlsMemRec */
-  kindls_mem = NULL;
-  kindls_mem = (KINDlsMem) malloc(sizeof(struct KINDlsMemRec));
-  if (kindls_mem == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINLAPACK", "KINLapackDense", MSGD_MEM_FAIL);
-    return(KINDLS_MEM_FAIL);
-  }
-
-  /* Set matrix type */
-  mtype = SUNDIALS_DENSE;  
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  djac   = NULL;
-  J_data = NULL;
-
-  last_flag = KINDLS_SUCCESS;
-
-  kinDlsInitializeCounters(kindls_mem);
-
-  setupNonNull = TRUE;
-
-  /* Set problem dimension */
-  n = (long int) N;
-
-  /* Allocate memory for J and pivot array */
-  
-  J = NULL;
-  J = NewDenseMat(n, n);
-  if (J == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINLAPACK", "KINLapackDense", MSGD_MEM_FAIL);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  pivots = NULL;
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINLAPACK", "KINLapackDense", MSGD_MEM_FAIL);
-    DestroyMat(J);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  /* This is a direct linear solver */
-  inexact_ls = FALSE;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = kindls_mem;
-
-  return(KINDLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * KINLapackBand
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the band linear solver module. It first calls
- * the existing lfree routine if this is not NULL.  It then sets the
- * kin_linit, kin_lsetup, kin_lsolve, and kin_lfree fields in (*kinmem)
- * to be kinLapackBandInit, kinLapackBandSetup, kinLapackBandSolve, 
- * and kinLapackBandFree, respectively.  It allocates memory for a 
- * structure of type KINLapackBandMemRec and sets the kin_lmem field in 
- * (*kinmem) to the address of this structure.  It sets lsetup_exists 
- * in (*kinmem) to be TRUE, mu to be mupper, ml to be mlower, and 
- * the bjac field to kinDlsBandDQJac
- * Finally, it allocates memory for M, pivots, and (if needed) savedJ.  
- * The KINLapackBand return value is KINDLS_SUCCESS = 0, 
- * KINDLS_MEM_FAIL = -1, or KINDLS_ILL_INPUT = -2.
- *
- * NOTE: The KINLAPACK linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, KINLapackBand will first 
- *       test for compatible a compatible N_Vector internal
- *       representation by checking that the function 
- *       N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */                  
-int KINLapackBand(void *kinmem, int N, int mupper, int mlower)
-{
-  KINMem kin_mem;
-  KINDlsMem kindls_mem;
-
-  /* Return immediately if kinmem is NULL */
-  if (kinmem == NULL) {
-    KINProcessError(NULL, KINDLS_MEM_NULL, "KINLAPACK", "KINLapackBand", MSGD_KINMEM_NULL);
-    return(KINDLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* Test if the NVECTOR package is compatible with the BAND solver */
-  if (vec_tmpl->ops->nvgetarraypointer == NULL) {
-    KINProcessError(kin_mem, KINDLS_ILL_INPUT, "KINLAPACK", "KINLapackBand", MSGD_BAD_NVECTOR);
-    return(KINDLS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(kin_mem);
-
-  /* Set four main function fields in kin_mem */  
-  linit  = kinLapackBandInit;
-  lsetup = kinLapackBandSetup;
-  lsolve = kinLapackBandSolve;
-  lfree  = kinLapackBandFree;
-  
-  /* Get memory for KINDlsMemRec */
-  kindls_mem = NULL;
-  kindls_mem = (KINDlsMem) malloc(sizeof(struct KINDlsMemRec));
-  if (kindls_mem == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINLAPACK", "KINLapackBand", MSGD_MEM_FAIL);
-    return(KINDLS_MEM_FAIL);
-  }
-  
-  /* Set matrix type */
-  mtype = SUNDIALS_BAND;  
-
-  /* Set default Jacobian routine and Jacobian data */
-  jacDQ  = TRUE;
-  bjac   = NULL;
-  J_data = NULL;
-
-  last_flag = KINDLS_SUCCESS;
-
-  kinDlsInitializeCounters(kindls_mem);
-
-  setupNonNull = TRUE;
-  
-  /* Load problem dimension */
-  n = (long int) N;
-
-  /* Load half-bandwidths in kindls_mem */
-  ml = (long int) mlower;
-  mu = (long int) mupper;
-
-  /* Test ml and mu for legality */
-  if ((ml < 0) || (mu < 0) || (ml >= n) || (mu >= n)) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINLAPACK", "KINLapackBand", MSGD_MEM_FAIL);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_ILL_INPUT);
-  }
-
-  /* Set extended upper half-bandwith for M (required for pivoting) */
-  smu = mu + ml;
-
-  /* Allocate memory for J and pivot array */
-  J = NULL;
-  J = NewBandMat(n, mu, ml, smu);
-  if (J == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINLAPACK", "KINLapackBand", MSGD_MEM_FAIL);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  pivots = NULL;
-  pivots = NewIntArray(N);
-  if (pivots == NULL) {
-    KINProcessError(kin_mem, KINDLS_MEM_FAIL, "KINLAPACK", "KINLapackBand", MSGD_MEM_FAIL);
-    DestroyMat(J);
-    free(kindls_mem); kindls_mem = NULL;
-    return(KINDLS_MEM_FAIL);
-  }
-
-  /* This is a direct linear solver */
-  inexact_ls = FALSE;
-
-  /* Attach linear solver memory to integrator memory */
-  lmem = kindls_mem;
-
-  return(KINDLS_SUCCESS);
-}
-
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR SOLUTION WITH DENSE JACOBIANS
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * kinLapackDenseInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the dense
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackDenseInit(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-  
-  kinDlsInitializeCounters(kindls_mem);
-  
-  if (jacDQ) {
-    djac = kinDlsDenseDQJac;
-    J_data = kin_mem;
-  } else {
-    J_data = kin_mem->kin_user_data;
-  }
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinLapackDenseSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the dense linear solver.
- * It calls the dense LU factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackDenseSetup(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-  int ier, retval;
-  int intn;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  intn = (int) n;
-
-  nje++;
-  SetToZero(J); 
-  retval = djac(n, uu, fval, J, J_data, vtemp1, vtemp2);
-  if (retval != 0) {
-    last_flag = -1;
-    return(-1);
-  }
-
-  /* Do LU factorization of J */
-  dgetrf_f77(&intn, &intn, J->data, &intn, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return -1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(-1);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinLapackDenseSolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the dense linear solver
- * by calling the dense backsolve routine.  The returned value is 0.
- * The argument *sJpnorm is ignored.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackDenseSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                               realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINDlsMem kindls_mem;
-  realtype *xd;
-  int ier, one = 1;
-  int intn;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  intn = (int) n;
-
-  /* Copy the right-hand side into x */
-  N_VScale(ONE, b, x);
-  xd = N_VGetArrayPointer(x);
-
-  /* Back-solve and get solution in x */
-  dgetrs_f77("N", &intn, &one, J->data, &intn, pivots, xd, &intn, &ier, 1); 
-  if (ier > 0) return(-1);
-
-  /* Compute the term sFdotJp for use in the linesearch routine.
-     This term is subsequently corrected if the step is reduced by
-     constraints or the linesearch.
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  N_VProd(b, fscale, b);
-  N_VProd(b, fscale, b);
-  *sFdotJp = N_VDotProd(fval, b);
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinLapackDenseFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the dense linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackDenseFree(KINMem kin_mem)
-{
-  KINDlsMem  kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-  
-  DestroyMat(J);
-  DestroyArray(pivots);
-  free(kindls_mem); kindls_mem = NULL;
-
-  return(0);
-}
-
-
-/* 
- * =================================================================
- *  PRIVATE FUNCTIONS FOR SOLUTION WITH BANDED JACOBIANS
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * kinLapackBandInit
- * -----------------------------------------------------------------
- * This routine does remaining initializations specific to the band
- * linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackBandInit(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  kinDlsInitializeCounters(kindls_mem);
-
-  if (jacDQ) {
-    bjac = kinDlsBandDQJac;
-    J_data = kin_mem;
-  } else {
-    J_data = kin_mem->kin_user_data;
-  }
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinLapackBandSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the band linear solver.
- * It makes a decision whether or not to call the Jacobian evaluation
- * routine based on various state variables, and if not it uses the 
- * saved copy.  In any case, it constructs the Newton matrix 
- * M = I - gamma*J, updates counters, and calls the band LU 
- * factorization routine.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackBandSetup(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-  int ier, retval;
-  int intn, iml, imu, ldmat;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = J->ldim;
-
-  nje++;
-  SetToZero(J); 
-  retval = bjac(n, mu, ml, uu, fval, J, J_data, vtemp1, vtemp2);
-  if (retval != 0) {
-    last_flag = -1;
-    return(-1);
-  }
-  
-  /* Do LU factorization of J */
-  dgbtrf_f77(&intn, &intn, &iml, &imu, J->data, &ldmat, pivots, &ier);
-
-  /* Return 0 if the LU was complete; otherwise return -1 */
-  last_flag = (long int) ier;
-  if (ier > 0) return(-1);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinLapackBandSolve
- * -----------------------------------------------------------------
- * This routine handles the solve operation for the band linear solver
- * by calling the band backsolve routine.  The return value is 0.
- * The argument *sJpnorm is ignored.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackBandSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-                              realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINDlsMem kindls_mem;
-  realtype *xd;
-  int ier, one = 1;
-  int intn, iml, imu, ldmat;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  intn = (int) n;
-  iml = (int) ml;
-  imu = (int) mu;
-  ldmat = J->ldim;
-
-  /* Copy the right-hand side into x */
-  N_VScale(ONE, b, x);
-  xd = N_VGetArrayPointer(x);
-
-  /* Back-solve and get solution in x */
-  dgbtrs_f77("N", &intn, &iml, &imu, &one, J->data, &ldmat, pivots, xd, &intn, &ier, 1);
-  if (ier > 0) return(-1);
-
-  /* Compute the term sFdotJp for use in the linesearch routine.
-     This term is subsequently corrected if the step is reduced by
-     constraints or the linesearch.
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  N_VProd(b, fscale, b);
-  N_VProd(b, fscale, b);
-  *sFdotJp = N_VDotProd(fval, b);
-
-  last_flag = KINDLS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * kinLapackBandFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the band linear solver.
- * -----------------------------------------------------------------
- */
-
-static int kinLapackBandFree(KINMem kin_mem)
-{
-  KINDlsMem kindls_mem;
-
-  kindls_mem = (KINDlsMem) lmem;
-
-  DestroyMat(J);
-  DestroyArray(pivots);
-  free(kindls_mem); kindls_mem = NULL;
-
-  return(0);
-}
diff --git a/src/kinsol/kinsol_sparse.c b/src/kinsol/kinsol_sparse.c
deleted file mode 100644
index 17b05ec..0000000
--- a/src/kinsol/kinsol_sparse.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for an KINSLS linear solver.
- * -----------------------------------------------------------------
- */
-
-/* 
- * =================================================================
- * IMPORTED HEADER FILES
- * =================================================================
- */
-
-#include "kinsol_impl.h"
-#include "kinsol_sparse_impl.h"
-#include "sundials/sundials_math.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/* 
- * =================================================================
- * FUNCTION SPECIFIC CONSTANTS
- * =================================================================
- */
-
-#define ZERO         RCONST(0.0)
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* 
- * =================================================================
- * EXPORTED FUNCTIONS 
- * =================================================================
- */
-              
-/*
- * KINSlsSetSparseJacFn specifies the sparse Jacobian function.
- */
-int KINSlsSetSparseJacFn(void *kin_mem_v, KINSlsSparseJacFn jac)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-
-  kin_mem = (KINMem) kin_mem_v;
-
-  /* Return immediately if kin_mem is NULL */
-  if (kin_mem == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINSlsSetSparseJacFn", 
-		    MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-
-  if (kin_mem->kin_lmem == NULL) {
-    KINProcessError(kin_mem, KINSLS_LMEM_NULL, "KINSLS", 
-		    "KINSlsSetSparseJacFn", MSGSP_LMEM_NULL);
-    return(KINSLS_LMEM_NULL);
-  }
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-
-  kinsls_mem->s_jaceval = jac;
-
-  return(KINSLS_SUCCESS);
-}
-
-/*
- * KINSlsGetNumJacEvals returns the number of Jacobian evaluations.
- */
-int KINSlsGetNumJacEvals(void *kin_mem_v, long int *njevals)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-
-  kin_mem = (KINMem) kin_mem_v;
-
-  /* Return immediately if kin_mem is NULL */
-  if (kin_mem == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINSlsGetNumJacEvals", MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-
-  if (kin_mem->kin_lmem == NULL) {
-    KINProcessError(kin_mem, KINSLS_LMEM_NULL, "KINSLS", 
-		    "KINSlsGetNumJacEvals", MSGSP_LMEM_NULL);
-    return(KINSLS_LMEM_NULL);
-  }
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-
-  *njevals = kinsls_mem->s_nje;
-
-  return(KINSLS_SUCCESS);
-}
-
-/*
- * KINSlsGetReturnFlagName returns the name associated with a KINSLS
- * return value.
- */
-char *KINSlsGetReturnFlagName(long int flag)
-{
-  char *name;
-
-  name = (char *)malloc(30*sizeof(char));
-
-  switch(flag) {
-  case KINSLS_SUCCESS:
-    sprintf(name,"KINSLS_SUCCESS");
-    break;   
-  case KINSLS_MEM_NULL:
-    sprintf(name,"KINSLS_MEM_NULL");
-    break;
-  case KINSLS_LMEM_NULL:
-    sprintf(name,"KINSLS_LMEM_NULL");
-    break;
-  case KINSLS_ILL_INPUT:
-    sprintf(name,"KINSLS_ILL_INPUT");
-    break;
-  case KINSLS_MEM_FAIL:
-    sprintf(name,"KINSLS_MEM_FAIL");
-    break;
-  case KINSLS_JAC_NOSET:
-    sprintf(name,"KINSLS_JAC_NOSET");
-    break;
-  case KINSLS_JACFUNC_UNRECVR:
-    sprintf(name,"KINSLS_JACFUNC_UNRECVR");
-    break;
-  case KINSLS_JACFUNC_RECVR:
-    sprintf(name,"KINSLS_JACFUNC_RECVR");
-    break;
-  default:
-    sprintf(name,"NONE");
-  }
-
-  return(name);
-}
-
-/*
- * KINSlsGetLastFlag returns the last flag set in a KINSLS function.
- */
-int KINSlsGetLastFlag(void *kin_mem_v, long int *flag)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-
-  kin_mem= (KINMem) kin_mem_v;
-
-  /* Return immediately if kin_mem is NULL */
-  if (kin_mem == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINSlsGetLastFlag", 
-		    MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-
-  if (kin_mem->kin_lmem == NULL) {
-    KINProcessError(kin_mem, KINSLS_LMEM_NULL, "KINSLS", 
-		    "KINSlsGetLastFlag", MSGSP_LMEM_NULL);
-    return(KINSLS_LMEM_NULL);
-  }
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-
-  *flag = kinsls_mem->s_last_flag;
-
-  return(KINSLS_SUCCESS);
-}
-
diff --git a/src/kinsol/kinsol_sparse_impl.h b/src/kinsol/kinsol_sparse_impl.h
deleted file mode 100644
index ed98bd9..0000000
--- a/src/kinsol/kinsol_sparse_impl.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4558 $
- * $Date: 2015-10-05 09:04:16 -0700 (Mon, 05 Oct 2015) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * Implementation header file for the KINSLS linear solvers.
- * -----------------------------------------------------------------
- */
-
-#ifndef _KINSPARSE_IMPL_H
-#define _KINSPARSE_IMPL_H
-
-#include "kinsol/kinsol_sparse.h"
-
-#ifdef __cplusplus  /* wrapper to enable C++ usage */
-extern "C" {
-#endif
-
-/*
- * =================================================================
- * K I N S P A R S E    I N T E R N A L    C O N S T A N T S
- * =================================================================
- */
-
-/*
- * -----------------------------------------------------------------
- * Types : KINSlsMemRec, KINSlsMem                             
- * -----------------------------------------------------------------
- * KINSlsMem is pointer to a KINSlsMemRec structure.
- * -----------------------------------------------------------------
- */
-
-typedef struct KINSlsMemRec {
-
-  KINSlsSparseJacFn s_jaceval; /* user Jacobian evaluation routine 
-				  to be called */
-  void *s_jacdata;           /* J_data is passed to eval. routine */
-
-  long int s_nje;           /* nje = no. of calls to jac */
-
-  long int s_last_flag;     /* last error return flag */
-
-  int s_first_factorize;    /* flag telling whether the first 
-			       factorization needs to happen */
-  SlsMat s_JacMat;          /* J = dF/du */
-
-  int sparsetype;           /* matrix type: compressed sparse column or row */
-
-  void *s_solver_data;      /* structure for solver-specific data */
-  
-
-} *KINSlsMem;
-
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-  
-
-/*
- * =================================================================
- * E R R O R   M E S S A G E S
- * =================================================================
- */
-
-#define MSGSP_KINMEM_NULL "Solver memory is NULL."
-#define MSGSP_BAD_NVECTOR "A required vector operation is not implemented."
-#define MSGSP_MEM_FAIL "A memory request failed."
-#define MSGSP_LMEM_NULL "Linear solver memory is NULL."
-#define MSGSP_JAC_NOSET "Jacobian evaluation function has not been set."
-#define MSGSP_ILL_INPUT "Invalid input detected."
-#define MSGSP_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
-#define MSGSP_PACKAGE_FAIL "A call to an external package failed."
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/kinsol/kinsol_spbcgs.c b/src/kinsol/kinsol_spbcgs.c
deleted file mode 100644
index 979fa2c..0000000
--- a/src/kinsol/kinsol_spbcgs.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINSOL interface to the
- * scaled, preconditioned Bi-CGSTAB (SPBCG) iterative linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "kinsol_impl.h"
-#include <kinsol/kinsol_spbcgs.h>
-#include "kinsol_spils_impl.h"
-
-#include <sundials/sundials_spbcgs.h>
-#include <sundials/sundials_math.h>
-
-/*
- * -----------------------------------------------------------------
- * private constants
- * -----------------------------------------------------------------
- */
-
-#define ZERO RCONST(0.0)
-
-/*
- * -----------------------------------------------------------------
- * function prototypes
- * -----------------------------------------------------------------
- */
-
-/* KINSpbcg linit, lsetup, lsolve, and lfree routines */
-
-static int KINSpbcgInit(KINMem kin_mem);
-static int KINSpbcgSetup(KINMem kin_mem);
-static int KINSpbcgSolve(KINMem kin_mem, N_Vector xx,
-			 N_Vector bb, realtype *sJpnorm, realtype *sFdotJp);
-static int KINSpbcgFree(KINMem kin_mem);
-
-/*
- * -----------------------------------------------------------------
- * readability replacements
- * -----------------------------------------------------------------
- */
-
-#define nni          (kin_mem->kin_nni)
-#define nnilset      (kin_mem->kin_nnilset)
-#define func         (kin_mem->kin_func)
-#define user_data    (kin_mem->kin_user_data)
-#define printfl      (kin_mem->kin_printfl)
-#define linit        (kin_mem->kin_linit)
-#define lsetup       (kin_mem->kin_lsetup)
-#define lsolve       (kin_mem->kin_lsolve)
-#define lfree        (kin_mem->kin_lfree)
-#define lmem         (kin_mem->kin_lmem)
-#define inexact_ls   (kin_mem->kin_inexact_ls)
-#define uu           (kin_mem->kin_uu)
-#define fval         (kin_mem->kin_fval)
-#define uscale       (kin_mem->kin_uscale)
-#define fscale       (kin_mem->kin_fscale)
-#define sqrt_relfunc (kin_mem->kin_sqrt_relfunc)
-#define eps          (kin_mem->kin_eps)
-#define errfp        (kin_mem->kin_errfp)
-#define infofp       (kin_mem->kin_infofp)
-#define setupNonNull (kin_mem->kin_setupNonNull)
-#define vtemp1       (kin_mem->kin_vtemp1)
-#define vec_tmpl     (kin_mem->kin_vtemp1)
-#define vtemp2       (kin_mem->kin_vtemp2)
-#define strategy     (kin_mem->kin_globalstrategy)
-
-#define pretype   (kinspils_mem->s_pretype)
-#define nli       (kinspils_mem->s_nli)
-#define npe       (kinspils_mem->s_npe)
-#define nps       (kinspils_mem->s_nps)
-#define ncfl      (kinspils_mem->s_ncfl)
-#define njtimes   (kinspils_mem->s_njtimes)
-#define nfes      (kinspils_mem->s_nfes)
-#define new_uu    (kinspils_mem->s_new_uu)
-#define spils_mem (kinspils_mem->s_spils_mem)
-
-#define jtimesDQ  (kinspils_mem->s_jtimesDQ)
-#define jtimes    (kinspils_mem->s_jtimes)
-#define J_data    (kinspils_mem->s_J_data)
-
-#define last_flag (kinspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpbcg
- * -----------------------------------------------------------------
- * This routine allocates and initializes the memory record and
- * sets function fields specific to the SPBCG linear solver module.
- * KINSpbcg sets the kin_linit, kin_lsetup, kin_lsolve, and
- * kin_lfree fields in *kinmem to be KINSpbcgInit, KINSpbcgSetup,
- * KINSpbcgSolve, and KINSpbcgFree, respectively. It allocates
- * memory for a structure of type KINSpilsMemRec and sets the
- * kin_lmem field in *kinmem to the address of this structure. It
- * also calls SpbcgMalloc to allocate memory for the module
- * SPBCG. It sets setupNonNull in (*kin_mem) and sets various
- * fields in the KINSpilsMemRec structure.
- * Finally, KINSpbcg allocates memory for local vectors, and calls
- * SpbcgMalloc to allocate memory for the Spbcg solver.
- * -----------------------------------------------------------------
- */
-
-int KINSpbcg(void *kinmem, int maxl)
-{
-  KINMem kin_mem;
-  KINSpilsMem kinspils_mem;
-  SpbcgMem spbcg_mem;
-  int maxl1;
-
-  if (kinmem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpbcg", MSGS_KINMEM_NULL);
-    return(KINSPILS_MEM_NULL);  
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* check for required vector operations */
-
-  /* Note: do NOT need to check for N_VLinearSum, N_VProd, N_VScale, N_VDiv, 
-     or N_VWL2Norm because they are required by KINSOL */
-
-  if ((vec_tmpl->ops->nvconst == NULL) ||
-      (vec_tmpl->ops->nvdotprod == NULL) ||
-      (vec_tmpl->ops->nvl1norm == NULL)) {
-    KINProcessError(NULL, KINSPILS_ILL_INPUT, "KINSPILS", "KINSpbcg", MSGS_BAD_NVECTOR);
-    return(KINSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(kin_mem);
-
-  /* set four main function fields in kin_mem */
-
-  linit  = KINSpbcgInit; 
-  lsetup = KINSpbcgSetup;
-  lsolve = KINSpbcgSolve;
-  lfree  = KINSpbcgFree;
-
-  /* get memory for KINSpilsMemRec */
-  kinspils_mem = NULL;
-  kinspils_mem = (KINSpilsMem) malloc(sizeof(struct KINSpilsMemRec));
-  if (kinspils_mem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSpbcg", MSGS_MEM_FAIL);
-    return(KINSPILS_MEM_FAIL);  
-  }
-
-  /* Set ILS type */
-  kinspils_mem->s_type = SPILS_SPBCG;
-
-  /* set SPBCG parameters that were passed in call sequence */
-
-  maxl1 = (maxl <= 0) ? KINSPILS_MAXL : maxl;
-  kinspils_mem->s_maxl = maxl1;  
-
-  /* Set defaults for Jacobian-related fileds */
-
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  J_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-
-  kinspils_mem->s_pset   = NULL;
-  kinspils_mem->s_psolve = NULL;
-  kinspils_mem->s_pfree  = NULL;
-  kinspils_mem->s_P_data = kin_mem->kin_user_data;
-
-  /* Set default values for the rest of the SPBCG parameters */
-
-  kinspils_mem->s_pretype   = PREC_NONE;
-  kinspils_mem->s_last_flag = KINSPILS_SUCCESS;
-
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* Call SpbcgMalloc to allocate workspace for SPBCG */
-
-  /* vec_tmpl passed as template vector */
-  spbcg_mem = NULL;
-  spbcg_mem = SpbcgMalloc(maxl1, vec_tmpl);
-  if (spbcg_mem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSpbcg", MSGS_MEM_FAIL);
-    free(kinspils_mem); kinspils_mem = NULL;
-    return(KINSPILS_MEM_FAIL);
-  }
-
-  /* This is an iterative linear solver */
-
-  inexact_ls = TRUE;
-
-  /* Attach SPBCG memory to spils memory structure */
-  spils_mem = (void *) spbcg_mem;
-
-  /* attach linear solver memory to KINSOL memory */
-  lmem = kinspils_mem;
-
-  return(KINSPILS_SUCCESS);
-}
-
-
-/*
- * -----------------------------------------------------------------
- * additional readability replacements
- * -----------------------------------------------------------------
- */
-
-#define maxl   (kinspils_mem->s_maxl)
-#define pset   (kinspils_mem->s_pset)
-#define psolve (kinspils_mem->s_psolve)
-#define P_data (kinspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpbcgInit
- * -----------------------------------------------------------------
- * This routine initializes variables associated with the SPBCG
- * iterative linear solver. Mmemory allocation was done previously
- * in KINSpbcg.
- * -----------------------------------------------------------------
- */
-
-static int KINSpbcgInit(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  SpbcgMem spbcg_mem;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-  /* initialize counters */
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* set preconditioner type */
-
-  if (psolve != NULL) {
-    pretype = PREC_RIGHT;
-  } else {
-    pretype = PREC_NONE;
-  }
-  
-  /* set setupNonNull to TRUE iff there is preconditioning with setup */
-
-  setupNonNull = ((psolve != NULL) && (pset != NULL));
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-
-  if (jtimesDQ) {
-    jtimes = KINSpilsDQJtimes;
-    J_data = kin_mem;
-  } else {
-    J_data = user_data;
-  }
-
-  if ( (strategy == KIN_PICARD) && jtimesDQ ) {
-    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSpbcgInit", 
-		    MSG_NOL_FAIL);
-    return(KIN_ILL_INPUT);
-  }
-
- /*  Set maxl in the SPBCG memory in case it was changed by the user */
-  spbcg_mem->l_max  = maxl;
-
-  last_flag = KINSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpbcgSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the SPBCG linear
- * solver, that is, it is an interface to the user-supplied
- * routine pset.
- * -----------------------------------------------------------------
- */
-
-static int KINSpbcgSetup(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  int ret;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  /* call pset routine */
-
-  ret = pset(uu, uscale, fval, fscale, P_data, vtemp1, vtemp2);
-
-  last_flag = ret;
-
-  npe++;
-  nnilset = nni; 
-
-  /* return the same value ret that pset returned */
-
-  return(ret);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpbcgSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic SPBCG solver routine
- * called SpbcgSolve for the solution of the linear system Ax = b.
- *
- * Appropriate variables are passed to SpbcgSolve and the counters
- * nli, nps, and ncfl are incremented, and the return value is set
- * according to the success of SpbcgSolve. The success flag is
- * returned if SpbcgSolve converged, or if the residual was reduced.
- * Of the other error conditions, only preconditioner solver
- * failure is specifically returned. Otherwise a generic flag is
- * returned to denote failure of this routine.
- * -----------------------------------------------------------------
- */
-
-static int KINSpbcgSolve(KINMem kin_mem, N_Vector xx, N_Vector bb, 
-                         realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINSpilsMem kinspils_mem;
-  SpbcgMem spbcg_mem;
-  int ret, nli_inc, nps_inc;
-  realtype res_norm;
-  
-  kinspils_mem = (KINSpilsMem) lmem;
-  spbcg_mem = (SpbcgMem) spils_mem;
-
-  /* Set initial guess to xx = 0. bb is set, by the routine
-     calling KINSpbcgSolve, to the RHS vector for the system
-     to be solved. */ 
- 
-  N_VConst(ZERO, xx);
-
-  new_uu = TRUE;  /* set flag required for user Jacobian routine */
-
-  /* call SpbcgSolve */
-
-  ret = SpbcgSolve(spbcg_mem, kin_mem, xx, bb, pretype, eps,
-                   kin_mem, fscale, fscale, KINSpilsAtimes,
-                   KINSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  /* increment counters nli, nps, and ncfl 
-     (nni is updated in the KINSol main iteration loop) */
-
-  nli = nli + (long int) nli_inc;
-  nps = nps + (long int) nps_inc;
-
-  if (printfl > 2) 
-    KINPrintInfo(kin_mem, PRNT_NLI, "KINSPBCG", "KINSpbcgSolve", INFO_NLI, nli_inc);
-
-  if (ret != 0) ncfl++;
-  last_flag = ret;
-
-  if ( (ret != 0) && (ret != SPBCG_RES_REDUCED) ) {
-
-    /* Handle all failure returns from SpbcgSolve */
-
-    switch(ret) {
-    case SPBCG_PSOLVE_FAIL_REC:
-    case SPBCG_ATIMES_FAIL_REC:
-      return(1);
-      break;
-    case SPBCG_CONV_FAIL:
-    case SPBCG_MEM_NULL:
-    case SPBCG_ATIMES_FAIL_UNREC:
-    case SPBCG_PSOLVE_FAIL_UNREC:
-      return(-1);
-      break;
-    }
-  }
-
-  /*  SpbcgSolve returned either SPBCG_SUCCESS or SPBCG_RES_REDUCED.
-
-     Compute the terms sJpnorm and sFdotJp for use in the linesearch
-     routine and in KINForcingTerm.  Both of these terms are subsequently
-     corrected if the step is reduced by constraints or the linesearch.
-
-     sJpnorm is the norm of the scaled product (scaled by fscale) of the
-     current Jacobian matrix J and the step vector p (= solution vector xx).
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  ret = KINSpilsAtimes(kin_mem, xx, bb);
-  if (ret > 0) {
-    last_flag = SPBCG_ATIMES_FAIL_REC;
-    return(1);
-  }      
-  else if (ret < 0) {
-    last_flag = SPBCG_ATIMES_FAIL_UNREC;
-    return(-1);
-  }
-
-  *sJpnorm = N_VWL2Norm(bb, fscale);
-  N_VProd(bb, fscale, bb);
-  N_VProd(bb, fscale, bb);
-  *sFdotJp = N_VDotProd(fval, bb);
-
-  if (printfl > 2) KINPrintInfo(kin_mem, PRNT_EPS, "KINSPBCG",
-                     "KINSpbcgSolve", INFO_EPS, res_norm, eps);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpbcgFree
- * -----------------------------------------------------------------
- * Frees memory specific to the SPBCG linear solver module.
- * -----------------------------------------------------------------
- */
-
-static int KINSpbcgFree(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  SpbcgMem spbcg_mem;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  spbcg_mem = (SpbcgMem) spils_mem;
-  SpbcgFree(spbcg_mem);
-
-  if (kinspils_mem->s_pfree != NULL) (kinspils_mem->s_pfree)(kin_mem);
-
-  free(kinspils_mem); kinspils_mem = NULL;
-
-  return(0);
-}
diff --git a/src/kinsol/kinsol_spfgmr.c b/src/kinsol/kinsol_spfgmr.c
deleted file mode 100644
index 9186c28..0000000
--- a/src/kinsol/kinsol_spfgmr.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Carol S. Woodward @ LLNL
- *    Based on kinsol_spgmr.c
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINSOL scaled,
- * preconditioned Flexible GMRES linear solver, KINSpfgmr.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "kinsol_impl.h"
-#include <kinsol/kinsol_spfgmr.h>
-#include "kinsol_spils_impl.h"
-
-#include <sundials/sundials_spfgmr.h>
-#include <sundials/sundials_math.h>
-
-/*
- * -----------------------------------------------------------------
- * private constants
- * -----------------------------------------------------------------
- */
-
-#define ZERO RCONST(0.0)
-
-/*
- * -----------------------------------------------------------------
- * function prototypes
- * -----------------------------------------------------------------
- */
-
-/* KINSpfgmr linit, lsetup, lsolve, and lfree routines */
-
-static int KINSpfgmrInit(KINMem kin_mem);
-static int KINSpfgmrSetup(KINMem kin_mem);
-static int KINSpfgmrSolve(KINMem kin_mem, N_Vector xx, 
-                          N_Vector bb, realtype *sJpnorm, realtype *sFdotJp);
-static int KINSpfgmrFree(KINMem kin_mem);
-
-/*
- * -----------------------------------------------------------------
- * readability replacements
- * -----------------------------------------------------------------
- */
-/*
-#define nni            (kin_mem->kin_nni)
-#define nnilset        (kin_mem->kin_nnilset)
-#define func           (kin_mem->kin_func)
-#define user_data      (kin_mem->kin_user_data)
-#define printfl        (kin_mem->kin_printfl)
-#define linit          (kin_mem->kin_linit)
-#define lsetup         (kin_mem->kin_lsetup)
-#define lsolve         (kin_mem->kin_lsolve)
-#define lfree          (kin_mem->kin_lfree)
-#define lmem           (kin_mem->kin_lmem)
-#define inexact_ls     (kin_mem->kin_inexact_ls)
-#define uu             (kin_mem->kin_uu)
-#define fval           (kin_mem->kin_fval)
-#define uscale         (kin_mem->kin_uscale)
-#define fscale         (kin_mem->kin_fscale)
-#define sqrt_relfunc   (kin_mem->kin_sqrt_relfunc)
-#define jacCurrent     (kin_mem->kin_jacCurrent)
-#define eps            (kin_mem->kin_eps)
-#define errfp          (kin_mem->kin_errfp)
-#define infofp         (kin_mem->kin_infofp)
-#define setupNonNull   (kin_mem->kin_setupNonNull)
-#define vtemp1         (kin_mem->kin_vtemp1)
-#define vec_tmpl       (kin_mem->kin_vtemp1)
-#define vtemp2         (kin_mem->kin_vtemp2)
-#define strategy       (kin_mem->kin_globalstrategy)
-
-#define pretype   (kinspils_mem->s_pretype)
-#define gstype    (kinspils_mem->s_gstype)
-#define nli       (kinspils_mem->s_nli)
-#define npe       (kinspils_mem->s_npe)
-#define nps       (kinspils_mem->s_nps)
-#define ncfl      (kinspils_mem->s_ncfl)
-#define njtimes   (kinspils_mem->s_njtimes)
-#define nfes      (kinspils_mem->s_nfes)
-#define new_uu    (kinspils_mem->s_new_uu)
-#define spils_mem (kinspils_mem->s_spils_mem)
-
-#define jtimesDQ  (kinspils_mem->s_jtimesDQ)
-#define jtimes    (kinspils_mem->s_jtimes)
-#define J_data    (kinspils_mem->s_J_data)
-
-#define last_flag (kinspils_mem->s_last_flag)
-*/
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpfgmr
- * -----------------------------------------------------------------
- * This routine allocates and initializes the memory record and
- * sets function fields specific to the SPFGMR linear solver module.
- * KINSpfgmr sets the kin_linit, kin_lsetup, kin_lsolve, and
- * kin_lfree fields in *kinmem to be KINSpfgmrInit, KINSpfgmrSetup,
- * KINSpfgmrSolve, and KINSpfgmrFree, respectively. It allocates
- * memory for a structure of type KINSpilsMemRec and sets the
- * kin_lmem field in *kinmem to the address of this structure. It
- * also calls SpfgmrMalloc to allocate memory for the module
- * SPFGMR. In summary, KINSpfgmr sets various fields in the
- * KINSpilsMemRec structure.
- * -----------------------------------------------------------------
- */
-
-int KINSpfgmr(void *kinmem, int maxl)
-{
-  KINMem kin_mem;
-  KINSpilsMem kinspils_mem;
-  SpfgmrMem spfgmr_mem;
-  int maxl1;
-
-  if (kinmem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpfgmr", MSGS_KINMEM_NULL);
-    return(KINSPILS_MEM_NULL);  
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* check for required vector operations */
-
-  /* Note: do NOT need to check for N_VLinearSum, N_VProd, N_VScale, N_VDiv, 
-     or N_VWL2Norm because they are required by KINSOL */
-
-  if ((kin_mem->kin_vtemp1->ops->nvconst == NULL) ||
-      (kin_mem->kin_vtemp1->ops->nvdotprod == NULL) ||
-      (kin_mem->kin_vtemp1->ops->nvl1norm == NULL)) {
-    KINProcessError(NULL, KINSPILS_ILL_INPUT, "KINSPILS", "KINSpfgmr", MSGS_BAD_NVECTOR);
-    return(KINSPILS_ILL_INPUT);
-  }
-
-  if (kin_mem->kin_lfree != NULL) kin_mem->kin_lfree(kin_mem);
-
-  /* set four main function fields in kin_mem */
-
-  kin_mem->kin_linit  = KINSpfgmrInit; 
-  kin_mem->kin_lsetup = KINSpfgmrSetup;
-  kin_mem->kin_lsolve = KINSpfgmrSolve;
-  kin_mem->kin_lfree  = KINSpfgmrFree;
-
-  /* get memory for KINSpilsMemRec */
-  kinspils_mem = NULL;
-  kinspils_mem = (KINSpilsMem) malloc(sizeof(struct KINSpilsMemRec));
-  if (kinspils_mem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSpfgmr", MSGS_MEM_FAIL);
-    return(KINSPILS_MEM_FAIL);  
-  }
-
-  /* Set ILS type */
-  kinspils_mem->s_type = SPILS_SPFGMR;
-
-  /* set SPFGMR parameters that were passed in call sequence */
-
-  maxl1 = (maxl <= 0) ? KINSPILS_MAXL : maxl;
-  kinspils_mem->s_maxl = maxl1;  
-
-  /* Set defaults for Jacobian-related fields */
-
-  kinspils_mem->s_jtimesDQ = TRUE;
-  kinspils_mem->s_jtimes   = NULL;
-  kinspils_mem->s_J_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-
-  kinspils_mem->s_pset   = NULL;
-  kinspils_mem->s_psolve = NULL;
-  kinspils_mem->s_pfree  = NULL;
-  kinspils_mem->s_P_data = kin_mem->kin_user_data;
-
-  /* Set default values for the rest of the SPFGMR parameters */
-
-  kinspils_mem->s_pretype   = PREC_NONE;
-  kinspils_mem->s_gstype    = MODIFIED_GS;
-  kinspils_mem->s_maxlrst   = 0;
-  kinspils_mem->s_last_flag = KINSPILS_SUCCESS;
-
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* Call SpfgmrMalloc to allocate workspace for SPFGMR */
-
-  /* vtemp1 passed as template vector */
-  spfgmr_mem = NULL;
-  spfgmr_mem = SpfgmrMalloc(maxl1, kin_mem->kin_vtemp1);
-  if (spfgmr_mem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSpfgmr", MSGS_MEM_FAIL);
-    free(kinspils_mem); kinspils_mem = NULL;
-    return(KINSPILS_MEM_FAIL);
-  }
-
-  /* This is an iterative linear solver */
-
-  kin_mem->kin_inexact_ls = TRUE;
-
-  /* Attach SPFGMR memory to spils memory structure */
-  kinspils_mem->s_spils_mem = (void *) spfgmr_mem;
-
-  /* attach linear solver memory to KINSOL memory */
-  kin_mem->kin_lmem = kinspils_mem;
-
-  return(KINSPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * additional readability replacements
- * -----------------------------------------------------------------
- */
-
-/*
-#define maxl    (kinspils_mem->s_maxl)
-#define maxlrst (kinspils_mem->s_maxlrst)
-#define pset    (kinspils_mem->s_pset)
-#define psolve  (kinspils_mem->s_psolve)
-#define P_data  (kinspils_mem->s_P_data)
-*/
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpfgmrInit
- * -----------------------------------------------------------------
- * This routine initializes variables associated with the FGMRES
- * linear solver. Memory allocation was done previously in
- * KINSpfgmr.
- * -----------------------------------------------------------------
- */
-
-static int KINSpfgmrInit(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-
-  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
-
-  /* initialize counters */
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* set preconditioner type */
-
-  if (kinspils_mem->s_psolve != NULL) {
-    kinspils_mem->s_pretype = PREC_RIGHT;
-  } else {
-    kinspils_mem->s_pretype = PREC_NONE;
-  }
-  
-  /* set setupNonNull to TRUE iff there is preconditioning with setup */
-
-  kin_mem->kin_setupNonNull = 
-    (kinspils_mem->s_psolve != NULL) && (kinspils_mem->s_pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-  if (kinspils_mem->s_jtimesDQ) {
-    kinspils_mem->s_jtimes = KINSpilsDQJtimes;
-    kinspils_mem->s_J_data = kin_mem;
-  } else {
-    kinspils_mem->s_J_data = kin_mem->kin_user_data;
-  }
-
-  if ( (kin_mem->kin_globalstrategy == KIN_PICARD) 
-       && (kinspils_mem->s_jtimesDQ) ) {
-    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSpfgmrInit", 
-		    MSG_NOL_FAIL);
-    return(KIN_ILL_INPUT);
-  }
-
-  kinspils_mem->s_last_flag = KINSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpfgmrSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the SPFGMR linear
- * solver, that is, it is an interface to the user-supplied
- * routine pset.
- * -----------------------------------------------------------------
- */
-
-static int KINSpfgmrSetup(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  int ret;
-
-  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
-
-  /* call pset routine */
-
-  ret = kinspils_mem->s_pset(kin_mem->kin_uu, kin_mem->kin_uscale, 
-                             kin_mem->kin_fval, kin_mem->kin_fscale, 
-                             kinspils_mem->s_P_data, 
-                             kin_mem->kin_vtemp1, kin_mem->kin_vtemp2); 
-
-  kinspils_mem->s_last_flag = ret;
-
-  (kinspils_mem->s_npe)++;
-  kin_mem->kin_nnilset = kin_mem->kin_nni; 
-
-  /* return the same value ret that pset returned */
-  return(ret);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpfgmrSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic SPFGMR solver
- * SpfgmrSolve for the solution of the linear system Ax = b.
- *
- * Appropriate variables are passed to SpfgmrSolve and the counters
- * nli, nps, and ncfl are incremented, and the return value is set
- * according to the success of SpfgmrSolve. The success flag is
- * returned if SpfgmrSolve converged, or if the residual was reduced.
- * Of the other error conditions, only preconditioner solver
- * failure is specifically returned. Otherwise a generic flag is
- * returned to denote failure of this routine.
- * -----------------------------------------------------------------
- */
-
-static int KINSpfgmrSolve(KINMem kin_mem, N_Vector xx, N_Vector bb, 
-                         realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINSpilsMem kinspils_mem;
-  SpfgmrMem spfgmr_mem;
-  int ret, nli_inc, nps_inc;
-  realtype res_norm;
-  
-  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
-
-  spfgmr_mem = (SpfgmrMem) kinspils_mem->s_spils_mem;
-
-  /* Set initial guess to xx = 0. bb is set, by the routine
-     calling KINSpfgmrSolve, to the RHS vector for the system
-     to be solved. */ 
-  N_VConst(ZERO, xx);
-
-  kinspils_mem->s_new_uu = TRUE; /* set flag required for user Jacobian routine */
-
-  /* call SpfgmrSolve */
-  ret = SpfgmrSolve(spfgmr_mem, kin_mem, xx, bb, kinspils_mem->s_pretype, 
-		    kinspils_mem->s_gstype, kin_mem->kin_eps, 
-		    kinspils_mem->s_maxlrst, kinspils_mem->s_maxl, 
-		    kin_mem, kin_mem->kin_fscale, kin_mem->kin_fscale, 
-		    KINSpilsAtimes, KINSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  /* increment counters nli, nps, and ncfl 
-     (nni is updated in the KINSol main iteration loop) */
-
-  kinspils_mem->s_nli = kinspils_mem->s_nli + (long int) nli_inc;
-  kinspils_mem->s_nps = kinspils_mem->s_nps + (long int) nps_inc;
-
-  if (kin_mem->kin_printfl > 2) 
-    KINPrintInfo(kin_mem, PRNT_NLI, "KINSPFGMR", "KINSpfgmrSolve", INFO_NLI, nli_inc);
-
-  if (ret != 0) (kinspils_mem->s_ncfl)++;
-  kinspils_mem->s_last_flag = ret;
-
-  if ( (ret != 0) && (ret != SPFGMR_RES_REDUCED) ) {
-
-    /* Handle all failure returns from SpfgmrSolve */
-
-    switch(ret) {
-    case SPFGMR_PSOLVE_FAIL_REC:
-    case SPFGMR_ATIMES_FAIL_REC:
-      return(1);
-      break;
-    case SPFGMR_CONV_FAIL:
-    case SPFGMR_QRFACT_FAIL:
-    case SPFGMR_MEM_NULL:
-    case SPFGMR_GS_FAIL:
-    case SPFGMR_QRSOL_FAIL:
-    case SPFGMR_ATIMES_FAIL_UNREC:
-    case SPFGMR_PSOLVE_FAIL_UNREC:
-      return(-1);
-      break;
-    }
-  }
-
-  /*  SpfgmrSolve returned either SPFGMR_SUCCESS or SPFGMR_RES_REDUCED.
-
-     Compute the terms sJpnorm and sFdotJp for use in the linesearch
-     routine and in KINForcingTerm.  Both of these terms are subsequently
-     corrected if the step is reduced by constraints or the linesearch.
-
-     sJpnorm is the norm of the scaled product (scaled by fscale) of the
-     current Jacobian matrix J and the step vector p (= solution vector xx).
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  ret = KINSpilsAtimes(kin_mem, xx, bb);
-  if (ret > 0) {
-    kinspils_mem->s_last_flag = SPFGMR_ATIMES_FAIL_REC;
-    return(1);
-  }      
-  else if (ret < 0) {
-    kinspils_mem->s_last_flag = SPFGMR_ATIMES_FAIL_UNREC;
-    return(-1);
-  }
-
-  *sJpnorm = N_VWL2Norm(bb, kin_mem->kin_fscale);
-  N_VProd(bb, kin_mem->kin_fscale, bb);
-  N_VProd(bb, kin_mem->kin_fscale, bb);
-  *sFdotJp = N_VDotProd(kin_mem->kin_fval, bb);
-
-  if (kin_mem->kin_printfl > 2) KINPrintInfo(kin_mem, PRNT_EPS, "KINSPFGMR",
-					     "KINSpfgmrSolve", INFO_EPS, 
-					     res_norm, kin_mem->kin_eps);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpfgmrFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the SPFGMR linear solver.
- * -----------------------------------------------------------------
- */
-
-static int KINSpfgmrFree(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  SpfgmrMem spfgmr_mem;
-
-  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
-
-  spfgmr_mem = (SpfgmrMem) kinspils_mem->s_spils_mem;
-  SpfgmrFree(spfgmr_mem);
-
-  if (kinspils_mem->s_pfree != NULL) (kinspils_mem->s_pfree)(kin_mem);
-
-  free(kinspils_mem); kinspils_mem = NULL;
-
-  return(0);
-}
diff --git a/src/kinsol/kinsol_spgmr.c b/src/kinsol/kinsol_spgmr.c
deleted file mode 100644
index 1341ca9..0000000
--- a/src/kinsol/kinsol_spgmr.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Radu Serban and Aaron Collier @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINSOL scaled,
- * preconditioned GMRES linear solver, KINSpgmr.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "kinsol_impl.h"
-#include <kinsol/kinsol_spgmr.h>
-#include "kinsol_spils_impl.h"
-
-#include <sundials/sundials_spgmr.h>
-#include <sundials/sundials_math.h>
-
-/*
- * -----------------------------------------------------------------
- * private constants
- * -----------------------------------------------------------------
- */
-
-#define ZERO RCONST(0.0)
-
-/*
- * -----------------------------------------------------------------
- * function prototypes
- * -----------------------------------------------------------------
- */
-
-/* KINSpgmr linit, lsetup, lsolve, and lfree routines */
-
-static int KINSpgmrInit(KINMem kin_mem);
-static int KINSpgmrSetup(KINMem kin_mem);
-static int KINSpgmrSolve(KINMem kin_mem, N_Vector xx, 
-                         N_Vector bb, realtype *sJpnorm, realtype *sFdotJp);
-static int KINSpgmrFree(KINMem kin_mem);
-
-/*
- * -----------------------------------------------------------------
- * readability replacements
- * -----------------------------------------------------------------
- */
-
-#define nni            (kin_mem->kin_nni)
-#define nnilset        (kin_mem->kin_nnilset)
-#define func           (kin_mem->kin_func)
-#define user_data      (kin_mem->kin_user_data)
-#define printfl        (kin_mem->kin_printfl)
-#define linit          (kin_mem->kin_linit)
-#define lsetup         (kin_mem->kin_lsetup)
-#define lsolve         (kin_mem->kin_lsolve)
-#define lfree          (kin_mem->kin_lfree)
-#define lmem           (kin_mem->kin_lmem)
-#define inexact_ls     (kin_mem->kin_inexact_ls)
-#define uu             (kin_mem->kin_uu)
-#define fval           (kin_mem->kin_fval)
-#define uscale         (kin_mem->kin_uscale)
-#define fscale         (kin_mem->kin_fscale)
-#define sqrt_relfunc   (kin_mem->kin_sqrt_relfunc)
-#define jacCurrent     (kin_mem->kin_jacCurrent)
-#define eps            (kin_mem->kin_eps)
-#define errfp          (kin_mem->kin_errfp)
-#define infofp         (kin_mem->kin_infofp)
-#define setupNonNull   (kin_mem->kin_setupNonNull)
-#define vtemp1         (kin_mem->kin_vtemp1)
-#define vec_tmpl       (kin_mem->kin_vtemp1)
-#define vtemp2         (kin_mem->kin_vtemp2)
-#define strategy       (kin_mem->kin_globalstrategy)
-
-#define pretype   (kinspils_mem->s_pretype)
-#define gstype    (kinspils_mem->s_gstype)
-#define nli       (kinspils_mem->s_nli)
-#define npe       (kinspils_mem->s_npe)
-#define nps       (kinspils_mem->s_nps)
-#define ncfl      (kinspils_mem->s_ncfl)
-#define njtimes   (kinspils_mem->s_njtimes)
-#define nfes      (kinspils_mem->s_nfes)
-#define new_uu    (kinspils_mem->s_new_uu)
-#define spils_mem (kinspils_mem->s_spils_mem)
-
-#define jtimesDQ  (kinspils_mem->s_jtimesDQ)
-#define jtimes    (kinspils_mem->s_jtimes)
-#define J_data    (kinspils_mem->s_J_data)
-
-#define last_flag (kinspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpgmr
- * -----------------------------------------------------------------
- * This routine allocates and initializes the memory record and
- * sets function fields specific to the SPGMR linear solver module.
- * KINSpgmr sets the kin_linit, kin_lsetup, kin_lsolve, and
- * kin_lfree fields in *kinmem to be KINSpgmrInit, KINSpgmrSetup,
- * KINSpgmrSolve, and KINSpgmrFree, respectively. It allocates
- * memory for a structure of type KINSpilsMemRec and sets the
- * kin_lmem field in *kinmem to the address of this structure. It
- * also calls SpgmrMalloc to allocate memory for the module
- * SPGMR. In summary, KINSpgmr sets various fields in the
- * KINSpilsMemRec structure.
- * -----------------------------------------------------------------
- */
-
-int KINSpgmr(void *kinmem, int maxl)
-{
-  KINMem kin_mem;
-  KINSpilsMem kinspils_mem;
-  SpgmrMem spgmr_mem;
-  int maxl1;
-
-  if (kinmem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpgmr", MSGS_KINMEM_NULL);
-    return(KINSPILS_MEM_NULL);  
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* check for required vector operations */
-
-  /* Note: do NOT need to check for N_VLinearSum, N_VProd, N_VScale, N_VDiv, 
-     or N_VWL2Norm because they are required by KINSOL */
-
-  if ((vec_tmpl->ops->nvconst == NULL) ||
-      (vec_tmpl->ops->nvdotprod == NULL) ||
-      (vec_tmpl->ops->nvl1norm == NULL)) {
-    KINProcessError(NULL, KINSPILS_ILL_INPUT, "KINSPILS", "KINSpgmr", MSGS_BAD_NVECTOR);
-    return(KINSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(kin_mem);
-
-  /* set four main function fields in kin_mem */
-
-  linit  = KINSpgmrInit; 
-  lsetup = KINSpgmrSetup;
-  lsolve = KINSpgmrSolve;
-  lfree  = KINSpgmrFree;
-
-  /* get memory for KINSpilsMemRec */
-  kinspils_mem = NULL;
-  kinspils_mem = (KINSpilsMem) malloc(sizeof(struct KINSpilsMemRec));
-  if (kinspils_mem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSpgmr", MSGS_MEM_FAIL);
-    return(KINSPILS_MEM_FAIL);  
-  }
-
-  /* Set ILS type */
-  kinspils_mem->s_type = SPILS_SPGMR;
-
-  /* set SPGMR parameters that were passed in call sequence */
-
-  maxl1 = (maxl <= 0) ? KINSPILS_MAXL : maxl;
-  kinspils_mem->s_maxl = maxl1;  
-
-  /* Set defaults for Jacobian-related fileds */
-
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  J_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-
-  kinspils_mem->s_pset   = NULL;
-  kinspils_mem->s_psolve = NULL;
-  kinspils_mem->s_pfree  = NULL;
-  kinspils_mem->s_P_data = kin_mem->kin_user_data;
-
-  /* Set default values for the rest of the SPGMR parameters */
-
-  kinspils_mem->s_pretype   = PREC_NONE;
-  kinspils_mem->s_gstype    = MODIFIED_GS;
-  kinspils_mem->s_maxlrst   = 0;
-  kinspils_mem->s_last_flag = KINSPILS_SUCCESS;
-
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* Call SpgmrMalloc to allocate workspace for SPGMR */
-
-  /* vec_tmpl passed as template vector */
-  spgmr_mem = NULL;
-  spgmr_mem = SpgmrMalloc(maxl1, vec_tmpl);
-  if (spgmr_mem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSpgmr", MSGS_MEM_FAIL);
-    free(kinspils_mem); kinspils_mem = NULL;
-    return(KINSPILS_MEM_FAIL);
-  }
-
-  /* This is an iterative linear solver */
-
-  inexact_ls = TRUE;
-
-  /* Attach SPGMR memory to spils memory structure */
-  spils_mem = (void *) spgmr_mem;
-
-  /* attach linear solver memory to KINSOL memory */
-  lmem = kinspils_mem;
-
-  return(KINSPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * additional readability replacements
- * -----------------------------------------------------------------
- */
-
-#define maxl    (kinspils_mem->s_maxl)
-#define maxlrst (kinspils_mem->s_maxlrst)
-#define pset    (kinspils_mem->s_pset)
-#define psolve  (kinspils_mem->s_psolve)
-#define P_data  (kinspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpgmrInit
- * -----------------------------------------------------------------
- * This routine initializes variables associated with the GMRES
- * linear solver. Memory allocation was done previously in
- * KINSpgmr.
- * -----------------------------------------------------------------
- */
-
-static int KINSpgmrInit(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  /* initialize counters */
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* set preconditioner type */
-
-  if (psolve != NULL) {
-    pretype = PREC_RIGHT;
-  } else {
-    pretype = PREC_NONE;
-  }
-  
-  /* set setupNonNull to TRUE iff there is preconditioning with setup */
-
-  setupNonNull = (psolve != NULL) && (pset != NULL);
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-
-  if (jtimesDQ) {
-    jtimes = KINSpilsDQJtimes;
-    J_data = kin_mem;
-  } else {
-    J_data = user_data;
-  }
-
-  if ( (strategy == KIN_PICARD) && jtimesDQ ) {
-    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSpgmrInit", 
-		    MSG_NOL_FAIL);
-    return(KIN_ILL_INPUT);
-  }
-
-  last_flag = KINSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpgmrSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the SPGMR linear
- * solver, that is, it is an interface to the user-supplied
- * routine pset.
- * -----------------------------------------------------------------
- */
-
-static int KINSpgmrSetup(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  int ret;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  /* call pset routine */
-
-  ret = pset(uu, uscale, fval, fscale, P_data, vtemp1, vtemp2); 
-
-  last_flag = ret;
-
-  npe++;
-  nnilset = nni; 
-
-  /* return the same value ret that pset returned */
-
-  return(ret);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpgmrSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic SPGMR solver
- * SpgmrSolve for the solution of the linear system Ax = b.
- *
- * Appropriate variables are passed to SpgmrSolve and the counters
- * nli, nps, and ncfl are incremented, and the return value is set
- * according to the success of SpgmrSolve. The success flag is
- * returned if SpgmrSolve converged, or if the residual was reduced.
- * Of the other error conditions, only preconditioner solver
- * failure is specifically returned. Otherwise a generic flag is
- * returned to denote failure of this routine.
- * -----------------------------------------------------------------
- */
-
-static int KINSpgmrSolve(KINMem kin_mem, N_Vector xx, N_Vector bb, 
-                         realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINSpilsMem kinspils_mem;
-  SpgmrMem spgmr_mem;
-  int ret, nli_inc, nps_inc;
-  realtype res_norm;
-  
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-
-  /* Set initial guess to xx = 0. bb is set, by the routine
-     calling KINSpgmrSolve, to the RHS vector for the system
-     to be solved. */ 
- 
-  N_VConst(ZERO, xx);
-
-  new_uu = TRUE;  /* set flag required for user Jacobian routine */
-
-  /* call SpgmrSolve */
-
-  ret = SpgmrSolve(spgmr_mem, kin_mem, xx, bb, pretype, gstype, eps, 
-                   maxlrst, kin_mem, fscale, fscale, KINSpilsAtimes,
-                   KINSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  /* increment counters nli, nps, and ncfl 
-     (nni is updated in the KINSol main iteration loop) */
-
-  nli = nli + (long int) nli_inc;
-  nps = nps + (long int) nps_inc;
-
-  if (printfl > 2) 
-    KINPrintInfo(kin_mem, PRNT_NLI, "KINSPGMR", "KINSpgmrSolve", INFO_NLI, nli_inc);
-
-  if (ret != 0) ncfl++;
-  last_flag = ret;
-
-  if ( (ret != 0) && (ret != SPGMR_RES_REDUCED) ) {
-
-    /* Handle all failure returns from SpgmrSolve */
-
-    switch(ret) {
-    case SPGMR_PSOLVE_FAIL_REC:
-    case SPGMR_ATIMES_FAIL_REC:
-      return(1);
-      break;
-    case SPGMR_CONV_FAIL:
-    case SPGMR_QRFACT_FAIL:
-    case SPGMR_MEM_NULL:
-    case SPGMR_GS_FAIL:
-    case SPGMR_QRSOL_FAIL:
-    case SPGMR_ATIMES_FAIL_UNREC:
-    case SPGMR_PSOLVE_FAIL_UNREC:
-      return(-1);
-      break;
-    }
-  }
-
-  /*  SpgmrSolve returned either SPGMR_SUCCESS or SPGMR_RES_REDUCED.
-
-     Compute the terms sJpnorm and sFdotJp for use in the linesearch
-     routine and in KINForcingTerm.  Both of these terms are subsequently
-     corrected if the step is reduced by constraints or the linesearch.
-
-     sJpnorm is the norm of the scaled product (scaled by fscale) of the
-     current Jacobian matrix J and the step vector p (= solution vector xx).
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  ret = KINSpilsAtimes(kin_mem, xx, bb);
-  if (ret > 0) {
-    last_flag = SPGMR_ATIMES_FAIL_REC;
-    return(1);
-  }      
-  else if (ret < 0) {
-    last_flag = SPGMR_ATIMES_FAIL_UNREC;
-    return(-1);
-  }
-
-  *sJpnorm = N_VWL2Norm(bb, fscale);
-  N_VProd(bb, fscale, bb);
-  N_VProd(bb, fscale, bb);
-  *sFdotJp = N_VDotProd(fval, bb);
-
-  if (printfl > 2) KINPrintInfo(kin_mem, PRNT_EPS, "KINSPGMR",
-                     "KINSpgmrSolve", INFO_EPS, res_norm, eps);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpgmrFree
- * -----------------------------------------------------------------
- * This routine frees memory specific to the SPGMR linear solver.
- * -----------------------------------------------------------------
- */
-
-static int KINSpgmrFree(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  SpgmrMem spgmr_mem;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  spgmr_mem = (SpgmrMem) spils_mem;
-  SpgmrFree(spgmr_mem);
-
-  if (kinspils_mem->s_pfree != NULL) (kinspils_mem->s_pfree)(kin_mem);
-
-  free(kinspils_mem); kinspils_mem = NULL;
-
-  return(0);
-}
diff --git a/src/kinsol/kinsol_spils.c b/src/kinsol/kinsol_spils.c
index 262c738..104b3a7 100644
--- a/src/kinsol/kinsol_spils.c
+++ b/src/kinsol/kinsol_spils.c
@@ -1,14 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4749 $
- * $Date: 2016-04-23 18:42:38 -0700 (Sat, 23 Apr 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -16,8 +13,7 @@
  * LLNS Copyright End
  * -----------------------------------------------------------------
  * This is the implementation file for the KINSPILS linear solvers.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -28,420 +24,470 @@
 
 #include <sundials/sundials_math.h>
 
-/*
- * -----------------------------------------------------------------
- * private constants
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  private constants
+  ------------------------------------------------------------------*/
 
 #define ZERO RCONST(0.0)
 #define ONE  RCONST(1.0)
 #define TWO  RCONST(2.0)
 
 
-/*
- * -----------------------------------------------------------------
- * readability replacements
- * -----------------------------------------------------------------
- */
-
-#define lrw1           (kin_mem->kin_lrw1)
-#define liw1           (kin_mem->kin_liw1)
-#define func           (kin_mem->kin_func)
-#define user_data      (kin_mem->kin_user_data)
-#define printfl        (kin_mem->kin_printfl)
-#define lmem           (kin_mem->kin_lmem)
-#define uu             (kin_mem->kin_uu)
-#define fval           (kin_mem->kin_fval)
-#define uscale         (kin_mem->kin_uscale)
-#define fscale         (kin_mem->kin_fscale)
-#define sqrt_relfunc   (kin_mem->kin_sqrt_relfunc)
-#define eps            (kin_mem->kin_eps)
-#define errfp          (kin_mem->kin_errfp)
-#define infofp         (kin_mem->kin_infofp)
-#define vtemp1         (kin_mem->kin_vtemp1)
-#define vec_tmpl       (kin_mem->kin_vtemp1)
-#define vtemp2         (kin_mem->kin_vtemp2)
-
-#define ils_type       (kinspils_mem->s_type)
-#define pretype        (kinspils_mem->s_pretype)
-#define gstype         (kinspils_mem->s_gstype)
-#define nli            (kinspils_mem->s_nli)
-#define npe            (kinspils_mem->s_npe)
-#define nps            (kinspils_mem->s_nps)
-#define ncfl           (kinspils_mem->s_ncfl)
-#define njtimes        (kinspils_mem->s_njtimes)
-#define nfes           (kinspils_mem->s_nfes)
-#define new_uu         (kinspils_mem->s_new_uu)
-
-#define jtimesDQ       (kinspils_mem->s_jtimesDQ)
-#define jtimes         (kinspils_mem->s_jtimes)
-#define J_data         (kinspils_mem->s_J_data)
-
-#define last_flag      (kinspils_mem->s_last_flag)
-
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsSetMaxRestarts
- * -----------------------------------------------------------------
- */
+/*==================================================================
+  KINSPILS Exported functions -- Required
+  ==================================================================*/
 
-int KINSpilsSetMaxRestarts(void *kinmem, int maxrs)
+/*---------------------------------------------------------------
+  KINSpilsSetLinearSolver specifies the iterative linear solver
+  ---------------------------------------------------------------*/
+int KINSpilsSetLinearSolver(void *kinmem, SUNLinearSolver LS)
 {
+  int retval;
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if any input is NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsSetMaxRestarts", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+		    "KINSpilsSetLinearSolver", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
+  if (LS == NULL) {
+    KINProcessError(NULL, KINSPILS_ILL_INPUT, "KINSPILS",
+		    "KINSpilsSetLinearSolver",
+                    "LS must be non-NULL");
+    return(KINSPILS_ILL_INPUT);
+  }
   kin_mem = (KINMem) kinmem;
 
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsSetMaxRestarts", MSGS_LMEM_NULL);
-    return(KINSPILS_LMEM_NULL);
+  /* Test if solver and vector are compatible with SPILS */
+  if (SUNLinSolGetType(LS) != SUNLINEARSOLVER_ITERATIVE) {
+    KINProcessError(kin_mem, KINSPILS_ILL_INPUT, "KINSPILS",
+                    "KINSpilsSetLinearSolver",
+                    "Non-iterative LS supplied to KINSpils interface");
+    return(KINSPILS_ILL_INPUT);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  /* check for legal maxrs */
 
-  if (maxrs < 0) {
-    KINProcessError(kin_mem, KINSPILS_ILL_INPUT, "KINSPILS", "KINSpilsSetMaxRestarts", MSGS_NEG_MAXRS);
+  /*
+    check for required vector operations
+
+    Note: do NOT need to check for N_VLinearSum, N_VProd, N_VScale,
+    N_VDiv, or N_VWL2Norm because they are required by KINSOL.
+  */
+  if ( (kin_mem->kin_vtemp1->ops->nvconst == NULL) ||
+       (kin_mem->kin_vtemp1->ops->nvdotprod == NULL) ||
+       (kin_mem->kin_vtemp1->ops->nvl1norm == NULL) ) {
+    KINProcessError(kin_mem, KINSPILS_ILL_INPUT, "KINSPILS",
+                    "KINSpilsSetLinearSolver", MSGS_BAD_NVECTOR);
     return(KINSPILS_ILL_INPUT);
   }
-  kinspils_mem->s_maxlrst = maxrs;
+
+  /* free any existing system solver attached to KIN */
+  if (kin_mem->kin_lfree) kin_mem->kin_lfree(kin_mem);
+
+  /* This is an iterative linear solver */
+  kin_mem->kin_inexact_ls = SUNTRUE;
+
+  /* Set four main system linear solver function fields in kin_mem */
+  kin_mem->kin_linit  = kinSpilsInitialize;
+  kin_mem->kin_lsetup = kinSpilsSetup;
+  kin_mem->kin_lsolve = kinSpilsSolve;
+  kin_mem->kin_lfree  = kinSpilsFree;
+  
+  /* Get memory for KINSpilsMemRec */
+  kinspils_mem = NULL;
+  kinspils_mem = (KINSpilsMem) malloc(sizeof(struct KINSpilsMemRec));
+  if (kinspils_mem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_MEM_FAIL, "KINSPILS",
+                    "KINSpilsSetLinearSolver", MSGS_MEM_FAIL);
+    return(KINSPILS_MEM_FAIL);
+  }
+
+  /* set SUNLinearSolver pointer */
+  kinspils_mem->LS = LS;
+
+  /* Set defaults for Jacobian-related fields */
+  kinspils_mem->jtimesDQ = SUNTRUE;
+  kinspils_mem->jtimes   = KINSpilsDQJtimes;
+  kinspils_mem->jdata    = kin_mem;
+
+  /* Set defaults for preconditioner-related fields */
+  kinspils_mem->pset   = NULL;
+  kinspils_mem->psolve = NULL;
+  kinspils_mem->pfree  = NULL;
+  kinspils_mem->pdata  = kin_mem->kin_user_data;
+
+  /* Initialize counters */
+  kinSpilsInitializeCounters(kinspils_mem);
+
+  /* Set default values for the rest of the SPILS parameters */
+  kinspils_mem->last_flag = KINSPILS_SUCCESS;
+
+  /* Attach default KINSpils interface routines to iterative LS */
+  retval = SUNLinSolSetATimes(LS, kin_mem, KINSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    KINProcessError(kin_mem, KINSPILS_SUNLS_FAIL, "KINSPILS",
+                    "KINSpilsSetLinearSolver",
+                    "Error in calling SUNLinSolSetATimes");
+    free(kinspils_mem); kinspils_mem = NULL;
+    return(KINSPILS_SUNLS_FAIL);
+  }
+  retval = SUNLinSolSetPreconditioner(LS, kin_mem, NULL, NULL);
+  if (retval != SUNLS_SUCCESS) {
+    KINProcessError(kin_mem, KINSPILS_SUNLS_FAIL, "KINSPILS",
+                    "KINSpilsSetLinearSolver",
+                    "Error in calling SUNLinSolSetPreconditioner");
+    free(kinspils_mem); kinspils_mem = NULL;
+    return(KINSPILS_SUNLS_FAIL);
+  }
+
+  /* Attach linear solver memory to integrator memory */
+  kin_mem->kin_lmem = kinspils_mem;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsSetPreconditioner
- * -----------------------------------------------------------------
- */
 
+/*==================================================================
+  KINSPILS Exported functions -- Optional input/output
+  ==================================================================*/
+
+/*------------------------------------------------------------------
+  KINSpilsSetPreconditioner sets the preconditioner setup and solve
+  functions
+  ------------------------------------------------------------------*/
 int KINSpilsSetPreconditioner(void *kinmem,
-			      KINSpilsPrecSetupFn pset, KINSpilsPrecSolveFn psolve)
+			      KINSpilsPrecSetupFn psetup,
+                              KINSpilsPrecSolveFn psolve)
 {
+  int retval;
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
+  PSetupFn kinspils_psetup;
+  PSolveFn kinspils_psolve;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsSetPreconditioner", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsSetPreconditioner", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsSetPreconditioner", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsSetPreconditioner", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  kinspils_mem->s_pset   = pset;
-  kinspils_mem->s_psolve = psolve;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  kinspils_mem->pset   = psetup;
+  kinspils_mem->psolve = psolve;
+
+  /* notify iterative linear solver to call KINSpils interface routines */
+  kinspils_psetup = (psetup == NULL) ? NULL : KINSpilsPSetup;
+  kinspils_psolve = (psolve == NULL) ? NULL : KINSpilsPSolve;
+  retval = SUNLinSolSetPreconditioner(kinspils_mem->LS, kin_mem,
+                                      kinspils_psetup, kinspils_psolve);
+  if (retval != SUNLS_SUCCESS) {
+    KINProcessError(kin_mem, KINSPILS_SUNLS_FAIL, "KINSPILS", 
+                    "KINSpilsSetPreconditioner", 
+                    "Error in calling SUNLinSolSetPreconditioner");
+    return(KINSPILS_SUNLS_FAIL);
+  }
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsSetJacTimesVecFn
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsSetJacTimesVecFn sets the matrix-vector product function
+  ------------------------------------------------------------------*/
 int KINSpilsSetJacTimesVecFn(void *kinmem, KINSpilsJacTimesVecFn jtv)
-
 {
+  int retval;
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsSetJacTimesVecFn", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsSetJacTimesVecFn", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsSetJacTimesVecFn", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
+  /* store function pointers for user-supplied routine in KINSpils 
+     interface (NULL jtimes implies use of DQ default) */
   if (jtv != NULL) {
-    jtimesDQ = FALSE;
-    jtimes = jtv;
+    kinspils_mem->jtimesDQ = SUNFALSE;
+    kinspils_mem->jtimes   = jtv;
   } else {
-    jtimesDQ = TRUE;
+    kinspils_mem->jtimesDQ = SUNTRUE;
+  }
+
+  /* notify iterative linear solver to call KINSpils interface routines */
+  retval = SUNLinSolSetATimes(kinspils_mem->LS, kin_mem, KINSpilsATimes);
+  if (retval != SUNLS_SUCCESS) {
+    KINProcessError(kin_mem, KINSPILS_SUNLS_FAIL, "KINSPILS", 
+                    "KINSpilsSetJacTimes", 
+                    "Error in calling SUNLinSolSetATimes");
+    return(KINSPILS_SUNLS_FAIL);
   }
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetWorkSpace
- * -----------------------------------------------------------------
- */
-
-int KINSpilsGetWorkSpace(void *kinmem, long int *lenrwSG, long int *leniwSG)
+/*------------------------------------------------------------------
+  KINSpilsGetWorkSpace returns the integer and real workspace size
+  ------------------------------------------------------------------*/
+int KINSpilsGetWorkSpace(void *kinmem, long int *lenrwLS,
+                         long int *leniwLS)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
-  int maxl;
-
-  /* return immediately if kinmem is NULL */
+  sunindextype lrw1, liw1;
+  long int lrw, liw;
+  int flag;
 
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetWorkSpace", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetWorkSpace", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetWorkSpace", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL,
+                    "KINSPILS", "KINSpilsGetWorkSpace", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
-  maxl = kinspils_mem->s_maxl;
+  /* start with fixed sizes */
+  *lenrwLS = 0;
+  *leniwLS = 9;
 
-  switch(ils_type) {
-  case SPILS_SPGMR:
-    *lenrwSG = lrw1 * (maxl + 3) + (maxl * (maxl + 4)) + 1;
-    *leniwSG = liw1 * (maxl + 3);
-    break;
-  case SPILS_SPBCG:
-    *lenrwSG = lrw1 * 7;
-    *leniwSG = liw1 * 7;
-    break;
-  case SPILS_SPTFQMR:
-    *lenrwSG = lrw1 * 11;
-    *leniwSG = liw1 * 11;
-    break;
+  /* add N_Vector sizes */
+  if (kin_mem->kin_vtemp1->ops->nvspace) {
+    N_VSpace(kin_mem->kin_vtemp1, &lrw1, &liw1);
+    *lenrwLS += lrw1;
+    *leniwLS += liw1;
   }
 
+  /* add LS sizes */
+  if (kinspils_mem->LS->ops->space) {
+    flag = SUNLinSolSpace(kinspils_mem->LS, &lrw, &liw);
+    *lenrwLS += lrw;
+    *leniwLS += liw;
+  }
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetNumPrecEvals
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsGetNumPrecEvals returns the total number of preconditioner
+  evaluations
+  ------------------------------------------------------------------*/
 int KINSpilsGetNumPrecEvals(void *kinmem, long int *npevals)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetNumPrecEvals", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumPrecEvals", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumPrecEvals", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-  *npevals = npe;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  *npevals = kinspils_mem->npe;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetNumPrecSolves
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsGetNumPrecSolves returns the total number of times the
+  preconditioner was applied
+  ------------------------------------------------------------------*/
 int KINSpilsGetNumPrecSolves(void *kinmem, long int *npsolves)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetNumPrecSolves", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumPrecSolves", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumPrecSolves", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-  *npsolves = nps;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  *npsolves = kinspils_mem->nps;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetNumLinIters
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsGetNumLinIters returns the total number of linear 
+  iterations
+  ------------------------------------------------------------------*/
 int KINSpilsGetNumLinIters(void *kinmem, long int *nliters)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetNumLinIters", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumLinIters", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetNumLinIters", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumLinIters", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-  *nliters = nli;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  *nliters = kinspils_mem->nli;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetNumConvFails
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsGetNumConvFails returns the total numbe of convergence 
+  failures
+  ------------------------------------------------------------------*/
 int KINSpilsGetNumConvFails(void *kinmem, long int *nlcfails)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetNumConvFails", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumConvFails", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetNumConvFails", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumConvFails", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-  *nlcfails = ncfl;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  *nlcfails = kinspils_mem->ncfl;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetNumJtimesEvals
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsGetNumJtimesEvals returns the number of times the matrix
+  vector product was computed
+  ------------------------------------------------------------------*/
 int KINSpilsGetNumJtimesEvals(void *kinmem, long int *njvevals)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetNumJtimesEvals", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumJtimesEvals", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumJtimesEvals", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-  *njvevals = njtimes;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  *njvevals = kinspils_mem->njtimes;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetNumFuncEvals
- * -----------------------------------------------------------------
- */
-
-int KINSpilsGetNumFuncEvals(void *kinmem, long int *nfevalsS)
+/*------------------------------------------------------------------
+  KINSpilsGetNumFuncEvals returns the number of calls to the user's
+  F routine by the linear solver module
+  ------------------------------------------------------------------*/
+int KINSpilsGetNumFuncEvals(void *kinmem, long int *nfevals)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetNumFuncEvals", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumFuncEvals", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetNumFuncEvals", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsGetNumFuncEvals", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
-  *nfevalsS = nfes;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  *nfevals = kinspils_mem->nfes;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetLastFlag
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsGetLastFlag returns the last flag set in the KINSPILS 
+  function
+  ------------------------------------------------------------------*/
 int KINSpilsGetLastFlag(void *kinmem, long int *flag)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
 
-  /* return immediately if kinmem is NULL */
-
+  /* Return immediately if kinmem or kin_mem->kin_lmem are NULL */
   if (kinmem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSpilsGetLastFlag", MSGS_KINMEM_NULL);
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+                    "KINSpilsGetLastFlag", MSGS_KINMEM_NULL);
     return(KINSPILS_MEM_NULL);
   }
   kin_mem = (KINMem) kinmem;
-
-  if (lmem == NULL) {
-    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", "KINSpilsGetLastFlag", MSGS_LMEM_NULL);
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+                    "KINSpilsGetLastFlag", MSGS_LMEM_NULL);
     return(KINSPILS_LMEM_NULL);
   }
-  kinspils_mem = (KINSpilsMem) lmem;
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
-  *flag = last_flag;
+  *flag = kinspils_mem->last_flag;
 
   return(KINSPILS_SUCCESS);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsGetReturnFlagName
- * -----------------------------------------------------------------
- */
-
+/*------------------------------------------------------------------
+  KINSpilsGetReturnFlagName
+  ------------------------------------------------------------------*/
 char *KINSpilsGetReturnFlagName(long int flag)
 {
   char *name;
@@ -467,6 +513,9 @@ char *KINSpilsGetReturnFlagName(long int flag)
   case KINSPILS_PMEM_NULL:
     sprintf(name, "KINSPILS_PMEM_NULL");
     break;
+  case KINSPILS_SUNLS_FAIL:
+    sprintf(name,"KINSPILS_SUNLS_FAIL");
+    break;
   default:
     sprintf(name, "NONE");
   }
@@ -474,166 +523,466 @@ char *KINSpilsGetReturnFlagName(long int flag)
   return(name);
 }
 
-/*
- * -----------------------------------------------------------------
- * additional readability replacements
- * -----------------------------------------------------------------
- */
-
-#define maxl    (kinspils_mem->s_maxl)
-#define maxlrst (kinspils_mem->s_maxlrst)
-#define pset    (kinspils_mem->s_pset)
-#define psolve  (kinspils_mem->s_psolve)
-#define P_data  (kinspils_mem->s_P_data)
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsAtimes
- * -----------------------------------------------------------------
- * This routine coordinates the generation of the matrix-vector
- * product z = J*v by calling either KINSpilsDQJtimes, which uses
- * a difference quotient approximation for J*v, or by calling the
- * user-supplied routine KINSpilsJacTimesVecFn if it is non-null.
- * -----------------------------------------------------------------
- */
+/*==================================================================
+  KINSPILS Private functions
+  ==================================================================*/
 
-int KINSpilsAtimes(void *kinsol_mem, N_Vector v, N_Vector z)
+/*------------------------------------------------------------------
+  KINSpilsATimes
+  
+  This routine coordinates the generation of the matrix-vector
+  product z = J*v by calling either KINSpilsDQJtimes, which uses
+  a difference quotient approximation for J*v, or by calling the
+  user-supplied routine KINSpilsJacTimesVecFn if it is non-null.
+  ------------------------------------------------------------------*/
+int KINSpilsATimes(void *kinmem, N_Vector v, N_Vector z)
 {
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
-  int ret;
+  int retval;
 
-  kin_mem = (KINMem) kinsol_mem;
-  kinspils_mem = (KINSpilsMem) lmem;
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kinmem == NULL) {
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", 
+                    "KINSpilsATimes", MSGS_KINMEM_NULL);
+    return(KINSPILS_MEM_NULL);
+  }
+  kin_mem = (KINMem) kinmem;
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", 
+                    "KINSpilsATimes", MSGS_LMEM_NULL);
+    return(KINSPILS_LMEM_NULL);
+  }
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
-  ret = jtimes(v, z, uu, &new_uu, J_data);
-  njtimes++;
+  retval = kinspils_mem->jtimes(v, z, kin_mem->kin_uu,
+                                &(kinspils_mem->new_uu),
+                                kinspils_mem->jdata);
+  kinspils_mem->njtimes++;
 
-  return(ret);
+  return(retval);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsPSolve
- * -----------------------------------------------------------------
- * This routine interfaces between the generic Sp***Solve routine
- * (within the SPGMR, SPBCG, or SPTFQMR solver) and the
- * user's psolve routine.  It passes to psolve all required state 
- * information from kinsol_mem.  Its return value is the same as that
- * returned by psolve. Note that the generic SP*** solver guarantees
- * that KINSpilsPSolve will not be called in the case in which
- * preconditioning is not done. This is the only case in which the
- * user's psolve routine is allowed to be NULL.
- * -----------------------------------------------------------------
- */
 
-int KINSpilsPSolve(void *kinsol_mem, N_Vector r, N_Vector z, int lrdummy)
+/*---------------------------------------------------------------
+  KINSpilsPSetup:
+
+  This routine interfaces between the generic iterative linear 
+  solvers and the user's psetup routine. It passes to psetup all 
+  required state information from kin_mem. Its return value 
+  is the same as that returned by psetup. Note that the generic
+  iterative linear solvers guarantee that KINSpilsPSetup will only
+  be called in the case that the user's psetup routine is non-NULL.
+  ---------------------------------------------------------------*/
+int KINSpilsPSetup(void *kinmem)
 {
-  KINMem kin_mem;
+  KINMem      kin_mem;
   KINSpilsMem kinspils_mem;
-  int ret;
+  int         retval;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kinmem == NULL) {
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", 
+		    "KINSpilsPSetup", MSGS_KINMEM_NULL);
+    return(KINSPILS_MEM_NULL);
+  }
+  kin_mem = (KINMem) kinmem;
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", 
+		    "KINSpilsPSetup", MSGS_LMEM_NULL);
+    return(KINSPILS_LMEM_NULL);
+  }
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  /* Call user pset routine to update preconditioner */
+  retval = kinspils_mem->pset(kin_mem->kin_uu, kin_mem->kin_uscale,
+                              kin_mem->kin_fval, kin_mem->kin_fscale, 
+                              kinspils_mem->pdata);
+  kinspils_mem->npe++;
+  return(retval);
+}
 
-  kin_mem = (KINMem) kinsol_mem;
-  kinspils_mem = (KINSpilsMem) lmem;
 
+/*------------------------------------------------------------------
+  KINSpilsPSolve
+
+  This routine interfaces between the generic iterative linear
+  solvers and the user's psolve routine. It passes to psolve all
+  required state information from kinsol_mem. Its return value is
+  the same as that returned by psolve. Note that the generic
+  SUNLinSol solver guarantees that KINSpilsPSolve will not be called
+  in the case in which preconditioning is not done. This is the only
+  case in which the user's psolve routine is allowed to be NULL.
+  ------------------------------------------------------------------*/
+int KINSpilsPSolve(void *kinmem, N_Vector r, N_Vector z,
+                   realtype toldummy, int lrdummy)
+{
+  KINMem kin_mem;
+  KINSpilsMem kinspils_mem;
+  int retval;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kinmem == NULL) {
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", 
+		    "KINSpilsPSolve", MSGS_KINMEM_NULL);
+    return(KINSPILS_MEM_NULL);
+  }
+  kin_mem = (KINMem) kinmem;
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", 
+		    "KINSpilsPSolve", MSGS_LMEM_NULL);
+    return(KINSPILS_LMEM_NULL);
+  }
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+  
   /* copy the rhs into z before the psolve call */   
   /* Note: z returns with the solution */
-
   N_VScale(ONE, r, z);
 
-  /* this call is counted in nps within the KINSpilsSolve routine */
+  retval = kinspils_mem->psolve(kin_mem->kin_uu, kin_mem->kin_uscale,
+                                kin_mem->kin_fval, kin_mem->kin_fscale,
+                                z, kinspils_mem->pdata);
 
-  ret = psolve(uu, uscale, fval, fscale, z, P_data, vtemp1);
-
-  return(ret);     
+  kinspils_mem->nps++;
+  return(retval);
 }
 
-/*
- * -----------------------------------------------------------------
- * Function : KINSpilsDQJtimes
- * -----------------------------------------------------------------
- * This routine generates the matrix-vector product z = J*v using a
- * difference quotient approximation. The approximation is 
- * J*v = [func(uu + sigma*v) - func(uu)]/sigma. Here sigma is based
- * on the dot products (uscale*uu, uscale*v) and
- * (uscale*v, uscale*v), the L1Norm(uscale*v), and on sqrt_relfunc
- * (the square root of the relative error in the function). Note
- * that v in the argument list has already been both preconditioned
- * and unscaled.
- *
- * NOTE: Unlike the DQ Jacobian functions for direct linear solvers
- *       (which are called from within the lsetup function), this
- *       function is called from within the lsolve function and thus
- *       a recovery may still be possible even if the system function
- *       fails (recoverably).
- * -----------------------------------------------------------------
- */
 
-int KINSpilsDQJtimes(N_Vector v, N_Vector Jv,
-                     N_Vector u, booleantype *new_u, 
-                     void *data)
+/*------------------------------------------------------------------
+  KINSpilsDQJtimes
+
+  This routine generates the matrix-vector product z = J*v using a
+  difference quotient approximation. The approximation is 
+  J*v = [func(uu + sigma*v) - func(uu)]/sigma. Here sigma is based
+  on the dot products (uscale*uu, uscale*v) and
+  (uscale*v, uscale*v), the L1Norm(uscale*v), and on sqrt_relfunc
+  (the square root of the relative error in the function). Note
+  that v in the argument list has already been both preconditioned
+  and unscaled.
+ 
+  NOTE: Unlike the DQ Jacobian functions for direct linear solvers
+        (which are called from within the lsetup function), this
+        function is called from within the lsolve function and thus
+        a recovery may still be possible even if the system function
+        fails (recoverably).
+  ------------------------------------------------------------------*/
+int KINSpilsDQJtimes(N_Vector v, N_Vector Jv, N_Vector u, 
+                     booleantype *new_u, void *kinmem)
 {
   realtype sigma, sigma_inv, sutsv, sq1norm, sign, vtv;
   KINMem kin_mem;
   KINSpilsMem kinspils_mem;
   int retval;
 
-  /* data is kin_mem */
-
-  kin_mem = (KINMem) data;
-  kinspils_mem = (KINSpilsMem) lmem;
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kinmem == NULL) {
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", 
+		    "KINSpilsDQJtimes", MSGS_KINMEM_NULL);
+    return(KINSPILS_MEM_NULL);
+  }
+  kin_mem = (KINMem) kinmem;
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS", 
+		    "KINSpilsDQJtimes", MSGS_LMEM_NULL);
+    return(KINSPILS_LMEM_NULL);
+  }
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
 
   /* scale the vector v and put Du*v into vtemp1 */
-
-  N_VProd(v, uscale, vtemp1);
+  N_VProd(v, kin_mem->kin_uscale, kin_mem->kin_vtemp1);
 
   /* scale u and put into Jv (used as a temporary storage) */
-
-  N_VProd(u, uscale, Jv);
+  N_VProd(u, kin_mem->kin_uscale, Jv);
 
   /* compute dot product (Du*u).(Du*v) */
-
-  sutsv = N_VDotProd(Jv, vtemp1);
+  sutsv = N_VDotProd(Jv, kin_mem->kin_vtemp1);
 
   /* compute dot product (Du*v).(Du*v) */
+  vtv = N_VDotProd(kin_mem->kin_vtemp1, kin_mem->kin_vtemp1);
 
-  vtv = N_VDotProd(vtemp1, vtemp1);
-
-  sq1norm = N_VL1Norm(vtemp1);
+  sq1norm = N_VL1Norm(kin_mem->kin_vtemp1);
 
   sign = (sutsv >= ZERO) ? ONE : -ONE ;
  
-  /*  this expression for sigma is from p. 469, Brown and Saad paper */
-
-  sigma = sign*sqrt_relfunc*SUNMAX(SUNRabs(sutsv),sq1norm)/vtv;
+  /* this expression for sigma is from p. 469, Brown and Saad paper */
+  sigma = sign*(kin_mem->kin_sqrt_relfunc)*SUNMAX(SUNRabs(sutsv),sq1norm)/vtv;
 
   sigma_inv = ONE/sigma;
 
   /* compute the u-prime at which to evaluate the function func */
-
-  N_VLinearSum(ONE, u, sigma, v, vtemp1);
+  N_VLinearSum(ONE, u, sigma, v, kin_mem->kin_vtemp1);
  
   /* call the system function to calculate func(u+sigma*v) */
-
-  retval = func(vtemp1, vtemp2, user_data);    
-  nfes++;
+  retval = kin_mem->kin_func(kin_mem->kin_vtemp1, kin_mem->kin_vtemp2,
+                             kin_mem->kin_user_data);    
+  kinspils_mem->nfes++;
   if (retval != 0) return(retval);
 
   /* finish the computation of the difference quotient */
+  N_VLinearSum(sigma_inv, kin_mem->kin_vtemp2, -sigma_inv, kin_mem->kin_fval, Jv);
+
+  return(0);
+}
+
 
-  N_VLinearSum(sigma_inv, vtemp2, -sigma_inv, fval, Jv);
+/*------------------------------------------------------------------
+  kinSpilsInitialize performs remaining initializations specific
+  to the iterative linear solver interface (and solver itself)
+  ------------------------------------------------------------------*/
+int kinSpilsInitialize(KINMem kin_mem)
+{
+  int retval;
+  KINSpilsMem kinspils_mem;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) {
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+		    "kinSpilsInitialize", MSGS_KINMEM_NULL);
+    return(KINSPILS_MEM_NULL);
+  }
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+		    "kinSpilsInitialize", MSGS_LMEM_NULL);
+    return(KINSPILS_LMEM_NULL);
+  }
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+  
+  /* initialize counters */
+  kinSpilsInitializeCounters(kinspils_mem);
+
+  /* Set Jacobian-related fields, based on jtimesDQ */
+  if (kinspils_mem->jtimesDQ) {
+    kinspils_mem->jtimes  = KINSpilsDQJtimes;
+    kinspils_mem->jdata   = kin_mem;
+  } else {
+    kinspils_mem->jdata   = kin_mem->kin_user_data;
+  }
+
+  /* the Picard iteration is incompatible with a difference-quotient J*v */
+  if ( (kin_mem->kin_globalstrategy == KIN_PICARD) && kinspils_mem->jtimesDQ ) {
+    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL",
+                    "kinSpilsInitialize", MSG_NOL_FAIL);
+    return(KIN_ILL_INPUT);
+  }
+
+  /* if NOT preconditioning or do NOT need to setup the
+     preconditioner, then set the lsetup function to NULL */
+  if ((kinspils_mem->psolve == NULL) || 
+      (kinspils_mem->pset == NULL)) {
+    kin_mem->kin_lsetup = NULL;
+  }
+
+  /* Set scaling vectors assuming RIGHT preconditioning */
+  /* NOTE: retval is non-zero only if LS == NULL        */
+  retval = SUNLinSolSetScalingVectors(kinspils_mem->LS,
+                                      kin_mem->kin_fscale,
+                                      kin_mem->kin_fscale);
+  if (retval != SUNLS_SUCCESS) {
+    KINProcessError(kin_mem, KINSPILS_SUNLS_FAIL, "KINSPILS", "kinSpilsInitialize", 
+		    "Error in calling SUNLinSolSetScalingVectors");
+    return(KINSPILS_SUNLS_FAIL);
+  }
+
+  /* Call LS initialize routine */
+  kinspils_mem->last_flag = SUNLinSolInitialize(kinspils_mem->LS);
+  return(kinspils_mem->last_flag);
+}
+
+
+/*------------------------------------------------------------------
+  kinSpilsSetup call the LS setup routine
+  ------------------------------------------------------------------*/
+int kinSpilsSetup(KINMem kin_mem)
+{
+  KINSpilsMem kinspils_mem;
+  int retval;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) {
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+		    "kinSpilsSetup", MSGS_KINMEM_NULL);
+    return(KINSPILS_MEM_NULL);
+  }
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+		    "kinSpilsSetup", MSGS_LMEM_NULL);
+    return(KINSPILS_LMEM_NULL);
+  }
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  /* Call LS setup routine -- the LS will call KINSpilsPSetup
+     if applicable */
+  retval = SUNLinSolSetup(kinspils_mem->LS, NULL);
+
+  /* save nni value from most recent lsetup call */
+  kin_mem->kin_nnilset = kin_mem->kin_nni;
+
+  return(retval);
+}
+
+
+/*------------------------------------------------------------------
+  kinSpilsSolve interfaces between KINSOL and the generic
+  SUNLinearSolver object
+  ------------------------------------------------------------------*/
+int kinSpilsSolve(KINMem kin_mem, N_Vector xx, N_Vector bb,
+                  realtype *sJpnorm, realtype *sFdotJp)
+{
+  KINSpilsMem kinspils_mem;
+  int nli_inc, retval;
+  realtype res_norm;
+  
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) {
+    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS",
+		    "kinSpilsSolve", MSGS_KINMEM_NULL);
+    return(KINSPILS_MEM_NULL);
+  }
+  if (kin_mem->kin_lmem == NULL) {
+    KINProcessError(kin_mem, KINSPILS_LMEM_NULL, "KINSPILS",
+		    "kinSpilsSolve", MSGS_LMEM_NULL);
+    return(KINSPILS_LMEM_NULL);
+  }
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  /* Set initial guess x = 0 to LS */  
+  N_VConst(ZERO, xx);
+  
+  /* set flag required for user Jacobian routine */
+  kinspils_mem->new_uu = SUNTRUE;
+
+  /* Call solver */
+  retval = SUNLinSolSolve(kinspils_mem->LS, NULL, xx, bb, kin_mem->kin_eps);
+
+  /* Retrieve solver statistics */
+  res_norm = SUNLinSolResNorm(kinspils_mem->LS);
+  nli_inc  = SUNLinSolNumIters(kinspils_mem->LS);
+
+  if (kin_mem->kin_printfl > 2) 
+    KINPrintInfo(kin_mem, PRNT_NLI, "KINSPILS", "kinSpilsSolve",
+                 INFO_NLI, nli_inc);
+
+  /* Increment counters nli and ncfl */
+  kinspils_mem->nli += nli_inc;
+  if (retval != SUNLS_SUCCESS) kinspils_mem->ncfl++;
+
+  /* Interpret solver return value */
+  kinspils_mem->last_flag = retval;
+
+  if ( (retval != 0) && (retval != SUNLS_RES_REDUCED) ) {
+    
+    switch(retval) {
+    case SUNLS_ATIMES_FAIL_REC:
+    case SUNLS_PSOLVE_FAIL_REC:
+      return(1);
+      break;
+    case SUNLS_MEM_NULL:
+    case SUNLS_ILL_INPUT:
+    case SUNLS_MEM_FAIL:
+    case SUNLS_GS_FAIL:
+    case SUNLS_CONV_FAIL:
+    case SUNLS_QRFACT_FAIL:
+    case SUNLS_LUFACT_FAIL:
+    case SUNLS_QRSOL_FAIL:
+      return(-1);
+      break;
+    case SUNLS_PACKAGE_FAIL_REC:
+      KINProcessError(kin_mem, SUNLS_PACKAGE_FAIL_REC, "KINSPILS",
+                      "kinSpilsSolve",
+                      "Failure in SUNLinSol external package");
+      return(-1);
+      break;
+    case SUNLS_PACKAGE_FAIL_UNREC:
+      KINProcessError(kin_mem, SUNLS_PACKAGE_FAIL_UNREC, "KINSPILS", 
+                      "kinSpilsSolve",
+                      "Failure in SUNLinSol external package");
+      return(-1);
+      break;
+    case SUNLS_ATIMES_FAIL_UNREC:
+      KINProcessError(kin_mem, SUNLS_ATIMES_FAIL_UNREC, "KINSPILS", 
+                      "kinSpilsSolve", MSGS_JTIMES_FAILED);    
+      return(-1);
+      break;
+    case SUNLS_PSOLVE_FAIL_UNREC:
+      KINProcessError(kin_mem, SUNLS_PSOLVE_FAIL_UNREC, "KINSPILS", 
+                      "kinSpilsSolve", MSGS_PSOLVE_FAILED);
+      return(-1);
+      break;
+    }
+  }
+
+  /*
+    SUNLinSolSolve returned SUNLS_SUCCESS or SUNLS_RES_REDUCED
+ 
+    Compute the terms sJpnorm and sFdotJp for use in the linesearch
+    routine and in KINForcingTerm.  Both of these terms are subsequently
+    corrected if the step is reduced by constraints or the linesearch.
+
+    sJpnorm is the norm of the scaled product (scaled by fscale) of the
+    current Jacobian matrix J and the step vector p (= solution vector xx).
+
+    sFdotJp is the dot product of the scaled f vector and the scaled
+    vector J*p, where the scaling uses fscale.
+  */
+
+  retval = KINSpilsATimes(kin_mem, xx, bb);
+  if (retval > 0) {
+    kinspils_mem->last_flag = SUNLS_ATIMES_FAIL_REC;
+    return(1);
+  }      
+  else if (retval < 0) {
+    kinspils_mem->last_flag = SUNLS_ATIMES_FAIL_UNREC;
+    return(-1);
+  }
+
+  *sJpnorm = N_VWL2Norm(bb, kin_mem->kin_fscale);
+  N_VProd(bb, kin_mem->kin_fscale, bb);
+  N_VProd(bb, kin_mem->kin_fscale, bb);
+  *sFdotJp = N_VDotProd(kin_mem->kin_fval, bb);
+
+  if (kin_mem->kin_printfl > 2)
+    KINPrintInfo(kin_mem, PRNT_EPS, "KINSPILS", "kinSpilsSolve",
+                 INFO_EPS, res_norm, kin_mem->kin_eps);
 
   return(0);
 }
 
+
+/*------------------------------------------------------------------
+  kinSpilsFree frees memory associated with the KINSpils system
+  solver interface
+  ------------------------------------------------------------------*/
+int kinSpilsFree(KINMem kin_mem)
+{
+  KINSpilsMem kinspils_mem;
+
+  /* Return immediately if kin_mem or kin_mem->kin_lmem are NULL */
+  if (kin_mem == NULL) return (KINSPILS_SUCCESS);
+  if (kin_mem->kin_lmem == NULL) return(KINSPILS_SUCCESS);
+  kinspils_mem = (KINSpilsMem) kin_mem->kin_lmem;
+
+  /* Free preconditioner memory (if applicable) */
+  if (kinspils_mem->pfree) kinspils_mem->pfree(kin_mem);
+
+  /* free KINSpils interface structure */
+  free(kin_mem->kin_lmem);
+
+  return(KINSPILS_SUCCESS);
+}
+
+
+/*------------------------------------------------------------------
+  kinSpilsInitializeCounters resets counters for the SPILS interface 
+  ------------------------------------------------------------------*/
 int kinSpilsInitializeCounters(KINSpilsMem kinspils_mem)
 {
-  kinspils_mem->s_npe     = 0;
-  kinspils_mem->s_nli     = 0;
-  kinspils_mem->s_nps     = 0;
-  kinspils_mem->s_ncfl    = 0;
-  kinspils_mem->s_njtimes = 0;
-  kinspils_mem->s_nfes    = 0;
+  kinspils_mem->npe     = 0;
+  kinspils_mem->nli     = 0;
+  kinspils_mem->nps     = 0;
+  kinspils_mem->ncfl    = 0;
+  kinspils_mem->njtimes = 0;
+  kinspils_mem->nfes    = 0;
   
   return(0);
 }
diff --git a/src/kinsol/kinsol_spils_impl.h b/src/kinsol/kinsol_spils_impl.h
index e7b5b3a..99b859e 100644
--- a/src/kinsol/kinsol_spils_impl.h
+++ b/src/kinsol/kinsol_spils_impl.h
@@ -1,14 +1,11 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Radu Serban and Aaron Collier @ LLNL
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL
+ *                Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -17,8 +14,7 @@
  * -----------------------------------------------------------------
  * Common implementation header file for the scaled, preconditioned
  * linear solver modules.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #ifndef _KINSPILS_IMPL_H
 #define _KINSPILS_IMPL_H
@@ -30,128 +26,100 @@
 extern "C" {
 #endif
 
-/* Types of iterative linear solvers */
-
-#define SPILS_SPGMR   1
-#define SPILS_SPBCG   2
-#define SPILS_SPTFQMR 3
-#define SPILS_SPFGMR  5
 
-/*
- * -----------------------------------------------------------------
- * keys for KINPrintInfo (do not use 1 -> conflict with PRNT_RETVAL)
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  keys for KINPrintInfo (do not use 1 -> conflict with PRNT_RETVAL)
+  ------------------------------------------------------------------*/
 
 #define PRNT_NLI   101
 #define PRNT_EPS   102
 
-/*
- * -----------------------------------------------------------------
- * Types : struct KINSpilsMemRec and struct *KINSpilsMem
- * -----------------------------------------------------------------
- * A variable declaration of type struct *KINSpilsMem denotes a
- * pointer to a data structure of type struct KINSpilsMemRec. The
- * KINSpilsMemRec structure contains fields that must be accessible
- * by KINSPILS/SPGMR solver module routines.
- * -----------------------------------------------------------------
- */
-
-typedef struct KINSpilsMemRec {
-
-  int s_type;           /* type of scaled preconditioned iterative LS          */
 
-  /* problem specification data */
+/*------------------------------------------------------------------
+  Types : struct KINSpilsMemRec, struct *KINSpilsMem
+  ------------------------------------------------------------------
+  A variable declaration of type struct *KINSpilsMem denotes a
+  pointer to a data structure of type struct KINSpilsMemRec. The
+  KINSpilsMemRec structure contains fields that must be accessible
+  by SPILS module routines.
+  ------------------------------------------------------------------*/
 
-  int  s_maxl;          /* maximum allowable dimension of Krylov subspace      */     
-  int  s_pretype;       /* preconditioning type: PREC_NONE, PREC_RIGHT,
-                           PREC_LEFT or PREC_BOTH (used by SPGMR module and
-                           defined in sundials_iterative.h)                    */
-  int  s_gstype;        /* Gram-Schmidt orthogonalization procedure:
-                           CLASSICAL_GS or MODIFIED_GS (used by SPGMR module
-                           and defined in sundials_iterative.h)                */
-  booleantype s_new_uu; /* flag indicating if the iterate has been updated -
-                           Jacobian must be updated/reevaluated (meant to be
-                           used by user-supplied jtimes function)              */
-  int s_maxlrst;        /* maximum number of times the SPGMR linear solver
-                           can be restarted                                    */
-
-  /* counters */
-
-  long int s_nli;     /* number of linear iterations performed                 */
-  long int s_npe;     /* number of preconditioner evaluations                  */
-  long int s_nps;     /* number of calls to preconditioner solve fun.          */
-  long int s_ncfl;    /* number of linear convergence failures                 */
-  long int s_nfes;    /* number of evaluations of the system function F(u) or
-                         number of calls made to func routine                  */    
-  long int s_njtimes; /* number of times the matrix-vector product J(u)*v
-                         was computed or number of calls made to jtimes
-                         routine                                               */
+typedef struct KINSpilsMemRec {
 
-  /* miscellaneous */
+  long int npe;       /* npe = total number of precond calls          */
+  long int nli;       /* nli = total number of linear iterations      */
+  long int nps;       /* nps = total number of psolve calls           */
+  long int ncfl;      /* ncfl = total number of convergence failures  */
+  long int nfes;      /* nres = total number of calls to F(u)         */
+  long int njtimes;   /* njtimes = total number of calls to jtimes    */
 
-  void *s_spils_mem;    /* pointer to generic linear solver memory block       */
+  booleantype new_uu; /* flag indicating if the iterate has been 
+                         updated - the Jacobian must be updated or 
+                         reevaluated (meant to be used by a
+                         user-supplied jtimes function                */
 
-  long int s_last_flag; /* last flag returned                                  */
+  SUNLinearSolver LS; /* generic iterative linear solver object       */
 
+  long int last_flag; /* last error return flag                       */
 
   /* Preconditioner computation
-   * (a) user-provided:
-   *     - P_data == user_data
-   *     - pfree == NULL (the user dealocates memory for user_data)
-   * (b) internal preconditioner module
-   *     - P_data == kinsol_mem
-   *     - pfree == set by the prec. module and called in KINSpilsFree
-   */
- 
-  KINSpilsPrecSetupFn s_pset;     
-  KINSpilsPrecSolveFn s_psolve; 
-  int (*s_pfree)(KINMem kin_mem);
-  void *s_P_data;
+     (a) user-provided:
+         - pdata == user_data
+         - pfree == NULL (the user dealocates memory)
+     (b) internal preconditioner module
+         - pdata == kin_mem
+         - pfree == set by the prec. module and called in kinSpilsFree */
+  KINSpilsPrecSetupFn pset;
+  KINSpilsPrecSolveFn psolve;
+  int (*pfree)(KINMem kin_mem);
+  void *pdata;
 
   /* Jacobian times vector compuation
-   * (a) jtimes function provided by the user:
-   *     - J_data == user_data
-   *     - jtimesDQ == FALSE
-   * (b) internal jtimes
-   *     - J_data == kinsol_mem
-   *     - jtimesDQ == TRUE
-   */
-
-  booleantype s_jtimesDQ;
-  KINSpilsJacTimesVecFn s_jtimes;
-  void *s_J_data;
+     (a) jtimes function provided by the user:
+         - jdata == user_data
+         - jtimesDQ == SUNFALSE
+     (b) internal jtimes
+         - jdata == kin_mem
+         - jtimesDQ == SUNTRUE */
+  booleantype jtimesDQ;
+  KINSpilsJacTimesVecFn jtimes;
+  void *jdata;
 
 } *KINSpilsMem;
 
 
-/*
- * -----------------------------------------------------------------
- * Prototypes of internal functions
- * -----------------------------------------------------------------
- */
-
-/* KINSpgmr Atimes and PSolve routines called by generic solver */
-
-int KINSpilsAtimes(void *kinsol_mem, N_Vector v, N_Vector z);
-int KINSpilsPSolve(void *kinsol_mem, N_Vector r, N_Vector z, int lr);
+/*------------------------------------------------------------------
+  Prototypes of internal functions
+  ------------------------------------------------------------------*/
 
-/* difference quotient approximation for jacobian times vector */
+/* Interface routines called by system SUNLinearSolvers */
+int KINSpilsATimes(void *kin_mem, N_Vector v, N_Vector z);
+int KINSpilsPSetup(void *kin_mem);
+int KINSpilsPSolve(void *kin_mem, N_Vector r, N_Vector z,
+                   realtype tol, int lr);
 
+/* Difference quotient approximation for Jacobian times vector */
 int KINSpilsDQJtimes(N_Vector v, N_Vector Jv,
-                     N_Vector u, booleantype *new_u, 
+                     N_Vector u, booleantype *new_u,
                      void *data);
 
-/* Auxilliary functions */
+/* Generic linit/lsetup/lsolve/lfree interface routines for KINSOL to call */
+int kinSpilsInitialize(KINMem kin_mem);
+
+int kinSpilsSetup(KINMem kin_mem);
+
+int kinSpilsSolve(KINMem kin_mem, N_Vector x, N_Vector b,
+                  realtype *sJpnorm, realtype *sFdotJp);
+
+int kinSpilsFree(KINMem kin_mem);
 
+/* Auxilliary functions */
 int kinSpilsInitializeCounters(KINSpilsMem kinspils_mem);
 
 
-/*
- * -----------------------------------------------------------------
- * KINSPILS error messages
- * -----------------------------------------------------------------
- */
+/*------------------------------------------------------------------
+  Error messages
+  ------------------------------------------------------------------*/
 
 #define MSGS_KINMEM_NULL "KINSOL memory is NULL."
 #define MSGS_MEM_FAIL    "A memory request failed."
@@ -159,12 +127,14 @@ int kinSpilsInitializeCounters(KINSpilsMem kinspils_mem);
 #define MSGS_LMEM_NULL   "Linear solver memory is NULL."
 #define MSGS_NEG_MAXRS   "maxrs < 0 illegal."
 
+#define MSGS_PSET_FAILED "The preconditioner setup routine failed in an unrecoverable manner."
+#define MSGS_PSOLVE_FAILED "The preconditioner solve routine failed in an unrecoverable manner."
+#define MSGS_JTIMES_FAILED "The Jacobian x vector routine failed in an unrecoverable manner."
 
-/*
- * -----------------------------------------------------------------
- * KINSPILS info messages
- * -----------------------------------------------------------------
- */
+
+/*------------------------------------------------------------------
+  Info messages
+  ------------------------------------------------------------------*/
 
 #define INFO_NLI  "nli_inc = %d"
 
@@ -183,7 +153,6 @@ int kinSpilsInitializeCounters(KINSpilsMem kinspils_mem);
 #endif
 
 
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/kinsol/kinsol_sptfqmr.c b/src/kinsol/kinsol_sptfqmr.c
deleted file mode 100644
index 57ec6a1..0000000
--- a/src/kinsol/kinsol_sptfqmr.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * -----------------------------------------------------------------
- * Programmer(s): Aaron Collier and Radu Serban @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINSOL interface to the
- * scaled, preconditioned TFQMR (SPTFQMR) iterative linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "kinsol_impl.h"
-#include <kinsol/kinsol_sptfqmr.h>
-#include "kinsol_spils_impl.h"
-
-#include <sundials/sundials_sptfqmr.h>
-#include <sundials/sundials_math.h>
-
-/*
- * -----------------------------------------------------------------
- * private constants
- * -----------------------------------------------------------------
- */
-
-#define ZERO RCONST(0.0)
-
-/*
- * -----------------------------------------------------------------
- * function prototypes
- * -----------------------------------------------------------------
- */
-
-/* KINSptfqmr linit, lsetup, lsolve, and lfree routines */
-
-static int KINSptfqmrInit(KINMem kin_mem);
-static int KINSptfqmrSetup(KINMem kin_mem);
-static int KINSptfqmrSolve(KINMem kin_mem, N_Vector xx,
-			   N_Vector bb, realtype *sJpnorm, realtype *sFdotJp);
-static int KINSptfqmrFree(KINMem kin_mem);
-
-/*
- * -----------------------------------------------------------------
- * readability replacements
- * -----------------------------------------------------------------
- */
-
-#define nni          (kin_mem->kin_nni)
-#define nnilset      (kin_mem->kin_nnilset)
-#define func         (kin_mem->kin_func)
-#define user_data    (kin_mem->kin_user_data)
-#define printfl      (kin_mem->kin_printfl)
-#define linit        (kin_mem->kin_linit)
-#define lsetup       (kin_mem->kin_lsetup)
-#define lsolve       (kin_mem->kin_lsolve)
-#define lfree        (kin_mem->kin_lfree)
-#define lmem         (kin_mem->kin_lmem)
-#define inexact_ls   (kin_mem->kin_inexact_ls)
-#define uu           (kin_mem->kin_uu)
-#define fval         (kin_mem->kin_fval)
-#define uscale       (kin_mem->kin_uscale)
-#define fscale       (kin_mem->kin_fscale)
-#define sqrt_relfunc (kin_mem->kin_sqrt_relfunc)
-#define eps          (kin_mem->kin_eps)
-#define errfp        (kin_mem->kin_errfp)
-#define infofp       (kin_mem->kin_infofp)
-#define setupNonNull (kin_mem->kin_setupNonNull)
-#define vtemp1       (kin_mem->kin_vtemp1)
-#define vec_tmpl     (kin_mem->kin_vtemp1)
-#define vtemp2       (kin_mem->kin_vtemp2)
-#define strategy     (kin_mem->kin_globalstrategy)
-
-#define pretype     (kinspils_mem->s_pretype)
-#define nli         (kinspils_mem->s_nli)
-#define npe         (kinspils_mem->s_npe)
-#define nps         (kinspils_mem->s_nps)
-#define ncfl        (kinspils_mem->s_ncfl)
-#define njtimes     (kinspils_mem->s_njtimes)
-#define nfes        (kinspils_mem->s_nfes)
-#define new_uu      (kinspils_mem->s_new_uu)
-#define spils_mem   (kinspils_mem->s_spils_mem)
-
-#define jtimesDQ    (kinspils_mem->s_jtimesDQ)
-#define jtimes      (kinspils_mem->s_jtimes)
-#define J_data      (kinspils_mem->s_J_data)
-
-#define last_flag   (kinspils_mem->s_last_flag)
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSptfqmr
- * -----------------------------------------------------------------
- * This routine allocates and initializes the memory record and
- * sets function fields specific to the SPTFQMR linear solver module.
- * KINSptfqmr sets the kin_linit, kin_lsetup, kin_lsolve, and
- * kin_lfree fields in *kinmem to be KINSptfqmrInit, KINSptfqmrSetup,
- * KINSptfqmrSolve, and KINSptfqmrFree, respectively. It allocates
- * memory for a structure of type KINSpilsMemRec and sets the
- * kin_lmem field in *kinmem to the address of this structure. It
- * also calls SptfqmrMalloc to allocate memory for the module
- * SPTFQMR. It sets setupNonNull in (*kin_mem),
- * and sets various fields in the KINSpilsMemRec structure.
- * Finally, KINSptfqmr allocates memory for local vectors, and calls
- * SptfqmrMalloc to allocate memory for the Sptfqmr solver.
- * -----------------------------------------------------------------
- */
-
-int KINSptfqmr(void *kinmem, int maxl)
-{
-  KINMem kin_mem;
-  KINSpilsMem kinspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int maxl1;
-
-  if (kinmem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_NULL, "KINSPILS", "KINSptfqmr", MSGS_KINMEM_NULL);
-    return(KINSPILS_MEM_NULL);  
-  }
-  kin_mem = (KINMem) kinmem;
-
-  /* check for required vector operations */
-
-  /* Note: do NOT need to check for N_VLinearSum, N_VProd, N_VScale, N_VDiv, 
-     or N_VWL2Norm because they are required by KINSOL */
-
-  if ((vec_tmpl->ops->nvconst == NULL) ||
-      (vec_tmpl->ops->nvdotprod == NULL) ||
-      (vec_tmpl->ops->nvl1norm == NULL)) {
-    KINProcessError(NULL, KINSPILS_ILL_INPUT, "KINSPILS", "KINSptfqmr", MSGS_BAD_NVECTOR);
-    return(KINSPILS_ILL_INPUT);
-  }
-
-  if (lfree != NULL) lfree(kin_mem);
-
-  /* set four main function fields in kin_mem */
-
-  linit  = KINSptfqmrInit; 
-  lsetup = KINSptfqmrSetup;
-  lsolve = KINSptfqmrSolve;
-  lfree  = KINSptfqmrFree;
-
-  /* get memory for KINSpilsMemRec */
-  kinspils_mem = NULL;
-  kinspils_mem = (KINSpilsMem) malloc(sizeof(struct KINSpilsMemRec));
-  if (kinspils_mem == NULL){
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSptfqmr", MSGS_MEM_FAIL);
-    return(KINSPILS_MEM_FAIL);  
-  }
-
-  /* Set ILS type */
-  kinspils_mem->s_type = SPILS_SPTFQMR;
-
-  /* set SPTFQMR parameters that were passed in call sequence */
-
-  maxl1 = (maxl <= 0) ? KINSPILS_MAXL : maxl;
-  kinspils_mem->s_maxl = maxl1;  
-
-  /* Set defaults for Jacobian-related fileds */
-
-  jtimesDQ = TRUE;
-  jtimes   = NULL;
-  J_data   = NULL;
-
-  /* Set defaults for preconditioner-related fields */
-
-  kinspils_mem->s_pset   = NULL;
-  kinspils_mem->s_psolve = NULL;
-  kinspils_mem->s_pfree  = NULL;
-  kinspils_mem->s_P_data = kin_mem->kin_user_data;
-
-  /* Set default values for the rest of the SPTFQMR parameters */
-
-  kinspils_mem->s_pretype   = PREC_NONE;
-  kinspils_mem->s_last_flag = KINSPILS_SUCCESS;
-
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* Call SptfqmrMalloc to allocate workspace for SPTFQMR */
-
-  /* vec_tmpl passed as template vector */
-
-  sptfqmr_mem = NULL;
-  sptfqmr_mem = SptfqmrMalloc(maxl1, vec_tmpl);
-  if (sptfqmr_mem == NULL) {
-    KINProcessError(NULL, KINSPILS_MEM_FAIL, "KINSPILS", "KINSptfqmr", MSGS_MEM_FAIL);
-    free(kinspils_mem); kinspils_mem = NULL;
-    return(KINSPILS_MEM_FAIL);
-  }
-
-  /* this is an iterative linear solver */
-
-  inexact_ls = TRUE;
-
-  /* Attach SPTFQMR memory to spils memory structure */
-  spils_mem = (void *) sptfqmr_mem;
-
-  /* attach linear solver memory to KINSOL memory */
-  lmem = kinspils_mem;
-
-  return(KINSPILS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * additional readability replacements
- * -----------------------------------------------------------------
- */
-
-#define maxl   (kinspils_mem->s_maxl)
-#define pset   (kinspils_mem->s_pset)
-#define psolve (kinspils_mem->s_psolve)
-#define P_data (kinspils_mem->s_P_data)
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSptfqmrInit
- * -----------------------------------------------------------------
- * This routine initializes variables associated with the SPTFQMR
- * iterative linear solver. Memory allocation was done previously
- * in KINSptfqmr.
- * -----------------------------------------------------------------
- */
-
-static int KINSptfqmrInit(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  /* initialize counters */
-  kinSpilsInitializeCounters(kinspils_mem);
-
-  /* set preconditioner type */
-
-  if (psolve != NULL) {
-    pretype = PREC_RIGHT;
-  } else {
-    pretype = PREC_NONE;
-  }
-  
-  /* set setupNonNull to TRUE iff there is preconditioning with setup */
-
-  setupNonNull = ((psolve != NULL) && (pset != NULL));
-
-  /* Set Jacobian-related fields, based on jtimesDQ */
-
-  if (jtimesDQ) {
-    jtimes = KINSpilsDQJtimes;
-    J_data = kin_mem;
-  } else {
-    J_data = user_data;
-  }
-
-  if ( (strategy == KIN_PICARD) && jtimesDQ ) {
-    KINProcessError(kin_mem, KIN_ILL_INPUT, "KINSOL", "KINSptfqmrInit", 
-		    MSG_NOL_FAIL);
-    return(KIN_ILL_INPUT);
-  }
-
-  last_flag = KINSPILS_SUCCESS;
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSptfqmrSetup
- * -----------------------------------------------------------------
- * This routine does the setup operations for the SPTFQMR linear
- * solver, that is, it is an interface to the user-supplied
- * routine pset.
- * -----------------------------------------------------------------
- */
-
-static int KINSptfqmrSetup(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  int ret;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  /* call pset routine */
-
-  ret = pset(uu, uscale, fval, fscale, P_data, vtemp1, vtemp2);
-
-  last_flag = ret;
-
-  npe++;
-  nnilset = nni;
-
-  /* return the same value ret that pset returned */
-
-  return(ret);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSptfqmrSolve
- * -----------------------------------------------------------------
- * This routine handles the call to the generic SPTFQMR solver routine
- * called SptfqmrSolve for the solution of the linear system Ax = b.
- *
- * Appropriate variables are passed to SptfqmrSolve and the counters
- * nli, nps, and ncfl are incremented, and the return value is set
- * according to the success of SptfqmrSolve. The success flag is
- * returned if SptfqmrSolve converged, or if the residual was reduced.
- * Of the other error conditions, only preconditioner solver
- * failure is specifically returned. Otherwise a generic flag is
- * returned to denote failure of this routine.
- * -----------------------------------------------------------------
- */
-
-static int KINSptfqmrSolve(KINMem kin_mem, N_Vector xx, N_Vector bb, 
-			   realtype *sJpnorm, realtype *sFdotJp)
-{
-  KINSpilsMem kinspils_mem;
-  SptfqmrMem sptfqmr_mem;
-  int ret, nli_inc, nps_inc;
-  realtype res_norm;
-  
-  kinspils_mem = (KINSpilsMem) lmem;
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-
-  /* Set initial guess to xx = 0. bb is set, by the routine
-     calling KINSptfqmrSolve, to the RHS vector for the system
-     to be solved. */ 
- 
-  N_VConst(ZERO, xx);
-
-  new_uu = TRUE;  /* set flag required for user Jacobian routine */
-
-  /* call SptfqmrSolve */
-
-  ret = SptfqmrSolve(sptfqmr_mem, kin_mem, xx, bb, pretype, eps,
-		     kin_mem, fscale, fscale, KINSpilsAtimes,
-		     KINSpilsPSolve, &res_norm, &nli_inc, &nps_inc);
-
-  /* increment counters nli, nps, and ncfl 
-     (nni is updated in the KINSol main iteration loop) */
-
-  nli = nli + (long int) nli_inc;
-  nps = nps + (long int) nps_inc;
-
-  if (printfl > 2) 
-    KINPrintInfo(kin_mem, PRNT_NLI, "KINSPTFQMR", "KINSptfqmrSolve", INFO_NLI, nli_inc);
-
-  if (ret != 0) ncfl++;
-  last_flag = ret;
-
-  if ( (ret != 0) && (ret != SPTFQMR_RES_REDUCED) ) {
-
-    /* Handle all failure returns from SptfqmrSolve */
-
-    switch(ret) {
-    case SPTFQMR_PSOLVE_FAIL_REC:
-    case SPTFQMR_ATIMES_FAIL_REC:
-      return(1);
-      break;
-    case SPTFQMR_CONV_FAIL:
-    case SPTFQMR_MEM_NULL:
-    case SPTFQMR_ATIMES_FAIL_UNREC:
-    case SPTFQMR_PSOLVE_FAIL_UNREC:
-      return(-1);
-      break;
-    }
-  }
-
-  /*  SptfqmrSolve returned either SPTFQMR_SUCCESS or SPTFQMR_RES_REDUCED.
-
-     Compute the terms sJpnorm and sFdotJp for use in the linesearch
-     routine and in KINForcingTerm.  Both of these terms are subsequently
-     corrected if the step is reduced by constraints or the linesearch.
-
-     sJpnorm is the norm of the scaled product (scaled by fscale) of the
-     current Jacobian matrix J and the step vector p (= solution vector xx).
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  ret = KINSpilsAtimes(kin_mem, xx, bb);
-  if (ret > 0) {
-    last_flag = SPTFQMR_ATIMES_FAIL_REC;
-    return(1);
-  }      
-  else if (ret < 0) {
-    last_flag = SPTFQMR_ATIMES_FAIL_UNREC;
-    return(-1);
-  }
-
-  *sJpnorm = N_VWL2Norm(bb, fscale);
-  N_VProd(bb, fscale, bb);
-  N_VProd(bb, fscale, bb);
-  *sFdotJp = N_VDotProd(fval, bb);
-
-  if (printfl > 2) KINPrintInfo(kin_mem, PRNT_EPS, "KINSPTFQMR",
-                     "KINSptfqmrSolve", INFO_EPS, res_norm, eps);
-
-  return(0);
-}
-
-/*
- * -----------------------------------------------------------------
- * Function : KINSptfqmrFree
- * -----------------------------------------------------------------
- * Frees memory specific to the SPTFQMR linear solver module.
- * -----------------------------------------------------------------
- */
-
-static int KINSptfqmrFree(KINMem kin_mem)
-{
-  KINSpilsMem kinspils_mem;
-  SptfqmrMem sptfqmr_mem;
-
-  kinspils_mem = (KINSpilsMem) lmem;
-
-  sptfqmr_mem = (SptfqmrMem) spils_mem;
-  SptfqmrFree(sptfqmr_mem);
-
-  if (kinspils_mem->s_pfree != NULL) (kinspils_mem->s_pfree)(kin_mem);
-
-  free(kinspils_mem); kinspils_mem = NULL;
-
-  return(0);
-}
diff --git a/src/kinsol/kinsol_superlumt.c b/src/kinsol/kinsol_superlumt.c
deleted file mode 100644
index 851ad1c..0000000
--- a/src/kinsol/kinsol_superlumt.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4924 $
- * $Date: 2016-09-19 14:36:05 -0700 (Mon, 19 Sep 2016) $
- * ----------------------------------------------------------------- 
- * Programmer(s): Carol S. Woodward @ LLNL
- * -----------------------------------------------------------------
- * LLNS Copyright Start
- * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
- * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
- * Produced at the Lawrence Livermore National Laboratory.
- * All rights reserved.
- * For details, see the LICENSE file.
- * LLNS Copyright End
- * -----------------------------------------------------------------
- * This is the implementation file for the KINSuperLUMT linear solver.
- * -----------------------------------------------------------------
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "sundials/sundials_math.h"
-#include "sundials/sundials_superlumt_impl.h"
-
-#include "kinsol/kinsol_superlumt.h"
-#include "kinsol_impl.h"
-#include "kinsol_sparse_impl.h"
-
-/* Constants */
-
-#define ONE          RCONST(1.0)
-#define TWO          RCONST(2.0)
-
-/* KINSuperLUMT linit, lsetup, lsolve, and lfree routines */
- 
-static int kinSuperLUMTInit(KINMem kin_mem);
-static int kinSuperLUMTSetup(KINMem kin_mem);
-static int kinSuperLUMTSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-		       realtype *sJpnorm, realtype *sFdotJp);		       
-static int kinSuperLUMTFree(KINMem kin_mem);
-
-/*
- * -----------------------------------------------------------------
- * KINSuperLUMT
- * -----------------------------------------------------------------
- * This routine initializes the memory record and sets various function
- * fields specific to the KINSOL / SuperLUMT linear solver module.  
- * KINSuperLUMT first calls the existing lfree routine if this is not NULL.
- * Then it sets the kin_linit, kin_lsetup, kin_lsolve, and
- * kin_lfree fields in (*kin_mem) to be kinSuperLUMTInit, kinSuperLUMTSetup,
- * kinSuperLUMTSolve, NULL, and kinSuperLUMTFree, respectively.
- * It allocates memory for a structure of type kinsluMemRec and sets
- * the kin_lmem field in (*kin_mem) to the address of this structure.
- * It sets setupNonNull in (*kin_mem) to TRUE.
- * Finally, it allocates memory for SuperLUMT.
- * The return value is KINSLS_SUCCESS = 0, KINSLS_LMEM_FAIL = -1,
- * or KINSLS_ILL_INPUT = -2.
- *
- * NOTE: The SuperLUMT linear solver assumes a serial implementation
- *       of the NVECTOR package. Therefore, KINSuperLUMT will first 
- *       test for a compatible N_Vector internal representation
- *       by checking that the function N_VGetArrayPointer exists.
- * -----------------------------------------------------------------
- */
-
-int KINSuperLUMT(void *kin_mem_v, int num_threads, int n, int nnz)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-  SLUMTData slumt_data;
-  int *perm_c, *perm_r;
-  int nrhs, panel_size, relax;
-  double *bd;
-  SuperMatrix *B;
-
-  /* Return immediately if kin_mem is NULL. */
-  if (kin_mem_v == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINSuperLUMT", 
-		    MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kin_mem_v;
-
-  /* Test if the NVECTOR package is compatible with the Direct solver */
-  if (kin_mem->kin_vtemp1->ops->nvgetarraypointer == NULL) {
-    KINProcessError(kin_mem, KINSLS_ILL_INPUT, "KINSLS", "KINSuperLUMT", 
-		    MSGSP_BAD_NVECTOR);
-    return(KINSLS_ILL_INPUT);
-  }
-
-  if (kin_mem->kin_lfree != NULL) kin_mem->kin_lfree(kin_mem);
-
-  /* Set five main function fields in kin_mem. */
-  kin_mem->kin_linit  = kinSuperLUMTInit;
-  kin_mem->kin_lsetup = kinSuperLUMTSetup;
-  kin_mem->kin_lsolve = kinSuperLUMTSolve;
-  kin_mem->kin_lfree  = kinSuperLUMTFree;
-
-  /* Get memory for kinSlsMemRec. */
-  kinsls_mem = (KINSlsMem) malloc(sizeof(struct KINSlsMemRec));
-  if (kinsls_mem == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "KINSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(KINSLS_MEM_FAIL);
-  }
-
-  /* Get memory for SLUMTData. */
-  slumt_data = (SLUMTData)malloc(sizeof(struct SLUMTDataRec));
-  if (slumt_data == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "KINSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(KINSLS_MEM_FAIL);
-  }
-
-  kin_mem->kin_setupNonNull = TRUE;
-
-  /* Set default Jacobian routine and Jacobian data */
-  kinsls_mem->s_jaceval = NULL;
-  kinsls_mem->s_jacdata = kin_mem->kin_user_data;
-
-  /* Allocate memory for the sparse Jacobian */
-  kinsls_mem->s_JacMat = SparseNewMat(n, n, nnz, CSC_MAT);
-  if (kinsls_mem->s_JacMat == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "KINSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(KINSLS_MEM_FAIL);
-  }
-
-   /* Set up memory for the permutations */
-  perm_r = (int *)malloc(n*sizeof(int));
-  if (perm_r == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "kinSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    return(KINSLS_MEM_FAIL);
-  }
-  perm_c = (int *)malloc(n*sizeof(int));
-  if (perm_c == NULL) {
-    KINProcessError(kin_mem, KINSLS_MEM_FAIL, "KINSLS", "kinSuperLUMT", 
-		    MSGSP_MEM_FAIL);
-    free(perm_r);
-    return(KINSLS_MEM_FAIL);
-  }
-  slumt_data->perm_r = perm_r;
-  slumt_data->perm_c = perm_c;
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-
-  /* Set default parameters for SuperLU */
-  slumt_data->num_threads = num_threads;
-  slumt_data->diag_pivot_thresh = 1.0;
-
-  /* Allocate structures for SuperLU */
-  slumt_data->Gstat = (Gstat_t *)malloc(sizeof(Gstat_t));
-  slumt_data->s_A = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_AC = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_L = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_U = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  slumt_data->s_A->Store  = NULL;
-  slumt_data->s_AC->Store = NULL;
-  slumt_data->s_L->Store  = NULL;
-  slumt_data->s_U->Store  = NULL;
-  slumt_data->superlumt_options = (superlumt_options_t *)malloc(sizeof(superlumt_options_t));
-
-  dCreate_CompCol_Matrix(slumt_data->s_A, kinsls_mem->s_JacMat->M, kinsls_mem->s_JacMat->N, 
-			 kinsls_mem->s_JacMat->NNZ, kinsls_mem->s_JacMat->data, 
-			 kinsls_mem->s_JacMat->indexvals, kinsls_mem->s_JacMat->indexptrs, 
-			 SLU_NC, SLU_D, SLU_GE);
-
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  StatAlloc(kinsls_mem->s_JacMat->N, num_threads, panel_size, relax, slumt_data->Gstat);
-  
-  /* Create RHS matrix */
-  nrhs = 1;
-  bd = NULL;
-  B = (SuperMatrix *)malloc(sizeof(SuperMatrix));
-  B->Store = NULL;
-  dCreate_Dense_Matrix(B, n, nrhs, bd, n, 
-		       SLU_DN, SLU_D, SLU_GE);
-  slumt_data->s_B = B;
-
-  /* Set ordering to COLAMD as the kinsol default use.
-     Users can set a different value with KINSuperLUMTSetOrdering,
-     and the user-set value is loaded before any call to factorize the
-     matrix in kinSuperLUMTSetup.  */
-  slumt_data->s_ordering = 3;
-
-  /* This is a direct linear solver */
-  kin_mem->kin_inexact_ls = FALSE;
-
-  /* Attach linear solver memory to the nonlinear solver memory */
-  kinsls_mem->s_solver_data = (void *) slumt_data;
-  kin_mem->kin_lmem = kinsls_mem;
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-
-  return(KINSLS_SUCCESS);
-}
-
-/*
- * -----------------------------------------------------------------
- * KINSuperLUMT interface functions
- * -----------------------------------------------------------------
- */
-
-/*
-  This routine does remaining initializations specific to the KINSuperLUMT
-  linear solver module.  
-  It returns 0 if successful.
-*/
-
-static int kinSuperLUMTInit(KINMem kin_mem)
-{
-  int num_threads, n;
-  KINSlsMem kinsls_mem;
-  SLUMTData slumt_data;
-
-  kinsls_mem = (KINSlsMem)kin_mem->kin_lmem;
-  slumt_data = (SLUMTData) kinsls_mem->s_solver_data;
-
-  kinsls_mem->s_nje = 0;
-  kinsls_mem->s_first_factorize = 1;
-
-  /* ------------------------------------------------------------
-     Allocate storage and initialize statistics variables. 
-     ------------------------------------------------------------*/
-  n = kinsls_mem->s_JacMat->N;
-  num_threads = slumt_data->num_threads;
-
-  StatInit(n, num_threads, slumt_data->Gstat);
-
-  kinsls_mem->s_last_flag = 0;
-  return(0);
-}
-
-/*
-  This routine does the setup operations for the KINSuperLUMT linear 
-  solver module.  It calls the Jacobian evaluation routine,
-  updates counters, and calls the LU factorization routine.
-  The return value is either
-     KINSLS_SUCCESS = 0  if successful,
-     +1  if the jac routine failed recoverably or the
-         LU factorization failed, or
-     -1  if the jac routine failed unrecoverably.
-*/
-
-static int kinSuperLUMTSetup(KINMem kin_mem)
-{
-  int retval, info;
-  int nprocs, panel_size, relax, permc_spec, lwork;
-  int *perm_r, *perm_c;
-  double diag_pivot_thresh, drop_tol;
-  fact_t fact;
-  trans_t trans;
-  yes_no_t refact, usepr;
-  KINSlsMem kinsls_mem;
-  KINSlsSparseJacFn jaceval;
-  SuperMatrix *A, *AC, *L, *U;
-  Gstat_t *Gstat;
-  superlumt_options_t *superlumt_options;
-  SLUMTData slumt_data;
-  SlsMat JacMat;
-  void *jacdata;
-  void *work;
-
-  kinsls_mem = (KINSlsMem) (kin_mem->kin_lmem);
-
-  slumt_data = (SLUMTData) kinsls_mem->s_solver_data;
-
-  jaceval = kinsls_mem->s_jaceval;
-  jacdata = kinsls_mem->s_jacdata;
-  JacMat = kinsls_mem->s_JacMat;
-
-  superlumt_options = slumt_data->superlumt_options;
-  A = slumt_data->s_A;
-  AC = slumt_data->s_AC;
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  Gstat = slumt_data->Gstat;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  nprocs = slumt_data->num_threads;
-  diag_pivot_thresh = slumt_data->diag_pivot_thresh;
-
-  /* Set option values for SuperL_MT */
-  panel_size = sp_ienv(1);
-  relax = sp_ienv(2);
-  fact = EQUILIBRATE;
-  trans = NOTRANS;
-  usepr = NO;
-  drop_tol = 0.0;
-  lwork = 0;
-  work = NULL;
-
- /* Check that Jacobian eval routine is set */
-  if (jaceval == NULL) {
-    KINProcessError(kin_mem, KINSLS_JAC_NOSET, "KINSLS", "kinSuperLUMTSetup", 
-		    MSGSP_JAC_NOSET);
-    free(kinsls_mem); kinsls_mem = NULL;
-    return(KINSLS_JAC_NOSET);
-  }
-
-  /* Increment nje counter and call Jacobian eval routine. */
-  kinsls_mem->s_nje++;
-  retval = jaceval(kin_mem->kin_uu, kin_mem->kin_fval, JacMat, jacdata, 
-		   kin_mem->kin_vtemp1, kin_mem->kin_vtemp2);
-
-  if (retval < 0) {
-    KINProcessError(kin_mem, KINSLS_JACFUNC_UNRECVR, "KINSLS", 
-		    "kinSuperLUMTSetup", MSGSP_JACFUNC_FAILED);
-    kinsls_mem->s_last_flag = KINSLS_JACFUNC_UNRECVR;
-    return(KINSLS_JACFUNC_UNRECVR);
-  }
-  if (retval > 0) {
-    kinsls_mem->s_last_flag = KINSLS_JACFUNC_RECVR;
-    return(+1);
-  }
-
-  if (kinsls_mem->s_first_factorize) {
-    /* Update the ordering option with any user-updated values from 
-       calls to KINSuperLUMTSetOrdering */
-    permc_spec = slumt_data->s_ordering;
-    get_perm_c(permc_spec, A, perm_c);
- 
-    refact= NO;
-    kinsls_mem->s_first_factorize = 0;
-  }
-  else {
-    /* ------------------------------------------------------------
-       Re-initialize statistics variables 
-       ------------------------------------------------------------*/
-    StatInit(JacMat->N, nprocs, Gstat);
-    Destroy_CompCol_Permuted(AC);
-    refact= YES;
-  }
-
-  /* ------------------------------------------------------------
-     Initialize the option structure superlumt_options using the
-     user-input parameters;  Subsequent calls will re-initialize
-     options.
-     Apply perm_c to the columns of original A to form AC.
-     ------------------------------------------------------------*/
-  pdgstrf_init(nprocs, fact, trans, refact, panel_size, relax,
-	       diag_pivot_thresh, usepr, drop_tol, perm_c, perm_r,
-	       work, lwork, A, AC, superlumt_options, Gstat);
-  /* ------------------------------------------------------------
-     Compute the LU factorization of A.
-     The following routine will create nprocs threads.
-     ------------------------------------------------------------*/
-  pdgstrf(superlumt_options, AC, perm_r, L, U, Gstat, &info);
-    
-  if (info != 0) {
-    kinsls_mem->s_last_flag = info;
-    return(+1);
-  }
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-
-  return(0);
-}
-
-/*
-  This routine handles the solve operation for the KINSuperLUMT linear
-  solver module.  It calls the SuperLUMT solve routine, 
-  then returns KINSLS_SUCCESS = 0.
-*/
-
-static int kinSuperLUMTSolve(KINMem kin_mem, N_Vector x, N_Vector b,
-			     realtype *sJpnorm, realtype *sFdotJp)		       
-{
-  int info, trans;
-  int *perm_r, *perm_c;
-  KINSlsMem kinsls_mem;
-  SuperMatrix *L, *U, *B;
-  Gstat_t *Gstat;
-  DNformat *Bstore;
-  SLUMTData slumt_data;
-  realtype *xd;
-  
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-  slumt_data = (SLUMTData) kinsls_mem->s_solver_data;
-
-  L = slumt_data->s_L;
-  U = slumt_data->s_U;
-  perm_r = slumt_data->perm_r;
-  perm_c = slumt_data->perm_c;
-  Gstat = slumt_data->Gstat;
-  B = slumt_data->s_B;
-   
-  /* Copy the right-hand side into x */
-  N_VScale(ONE, b, x);
-  xd = N_VGetArrayPointer(x);
-  Bstore = (DNformat *) (B->Store);
-  Bstore->nzval = xd;
-
-  /* Call SuperLUMT to solve the linear system using L and U */
-  trans = NOTRANS;
-  dgstrs(trans, L, U, perm_r, perm_c, B, Gstat, &info);
-
-  Bstore->nzval = NULL;
-
-  /* Compute the term sFdotJp for use in the linesearch routine.
-     This term is subsequently corrected if the step is reduced by
-     constraints or the linesearch.
-
-     sFdotJp is the dot product of the scaled f vector and the scaled
-     vector J*p, where the scaling uses fscale.                            */
-
-  N_VProd(b, kin_mem->kin_fscale, b);
-  N_VProd(b, kin_mem->kin_fscale, b);
-  *sFdotJp = N_VDotProd(kin_mem->kin_fval, b);
-
-  kinsls_mem->s_last_flag = KINSLS_SUCCESS;
-  return(KINSLS_SUCCESS);
-}
-
-/*
-  This routine frees memory specific to the KINSuperLUMT linear solver.
-*/
-
-static int kinSuperLUMTFree(KINMem kin_mem)
-{
-  KINSlsMem kinsls_mem;
-  SLUMTData slumt_data;
-  
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-  slumt_data = (SLUMTData) kinsls_mem->s_solver_data;
-
-  pxgstrf_finalize(slumt_data->superlumt_options, slumt_data->s_AC);
-
-  free(slumt_data->perm_r);
-  free(slumt_data->perm_c);
-  free(slumt_data->superlumt_options);
-  Destroy_SuperNode_SCP( (slumt_data->s_L) );
-  Destroy_CompCol_NCP( (slumt_data->s_U) );
-  StatFree( (slumt_data->Gstat) );
-  free(slumt_data->Gstat);
-  
-  Destroy_SuperMatrix_Store(slumt_data->s_B);
-  SUPERLU_FREE(slumt_data->s_A->Store);
-  if (kinsls_mem->s_JacMat) {
-    SparseDestroyMat(kinsls_mem->s_JacMat);
-    kinsls_mem->s_JacMat = NULL;
-  }
-
-  free(slumt_data->s_B);
-  free(slumt_data->s_A);
-  free(slumt_data->s_AC);
-  free(slumt_data->s_L);
-  free(slumt_data->s_U);
-
-  free(slumt_data); 
-  free(kin_mem->kin_lmem); 
-
-  return(0);
-}
-
-
-/* 
- * -----------------------------------------------------------------
- * Optional Input Specification Functions
- * -----------------------------------------------------------------
- *
- * KINSuperLUMTSetOrdering sets the ordering used by SuperLUMT for reducing fill.
- * Options are: 
- * 0 for natural ordering
- * 1 for minimal degree ordering on A'*A
- * 2 for minimal degree ordering on A'+A
- * 3 for approximate minimal degree ordering for unsymmetric matrices
- * The default used in SUNDIALS is 3 for COLAMD.
- * -----------------------------------------------------------------
- */
-
-int KINSuperLUMTSetOrdering(void *kin_mem_v, int ordering_choice)
-{
-  KINMem kin_mem;
-  KINSlsMem kinsls_mem;
-  SLUMTData slumt_data;
-
- /* Return immediately if kin_mem is NULL */
-  if (kin_mem_v == NULL) {
-    KINProcessError(NULL, KINSLS_MEM_NULL, "KINSLS", "KINSuperLUMTSetOrdering",
-		    MSGSP_KINMEM_NULL);
-    return(KINSLS_MEM_NULL);
-  }
-  kin_mem = (KINMem) kin_mem_v;
-  kinsls_mem = (KINSlsMem) kin_mem->kin_lmem;
-
- /* Return if ordering choice argument is not valid */
-  if ( (ordering_choice != 0) && (ordering_choice != 1) && 
-       (ordering_choice != 2) && (ordering_choice != 3) ) {
-    KINProcessError(NULL, KINSLS_ILL_INPUT, "KINSLS", "KINSuperLUMTSetOrdering",
-		    MSGSP_ILL_INPUT);
-    return(KINSLS_ILL_INPUT);
-  }
-
-  slumt_data = (SLUMTData) kinsls_mem->s_solver_data;
-
-  slumt_data->s_ordering = ordering_choice;
-
-  return(KINSLS_SUCCESS);
-}
-
diff --git a/src/nvec_cuda/CMakeLists.txt b/src/nvec_cuda/CMakeLists.txt
new file mode 100644
index 0000000..5eab18e
--- /dev/null
+++ b/src/nvec_cuda/CMakeLists.txt
@@ -0,0 +1,75 @@
+# ---------------------------------------------------------------
+# Programmer:  Slaven Peles @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the cuda NVECTOR library
+
+INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_CUDA\n\")")
+
+# Add variable nveccuda_SOURCES with the sources for the NVECSERIAL lib
+SET(nveccuda_SOURCES nvector_cuda.cu)
+
+# Tell compiler it is a CUDA source
+set_source_files_properties(${nvecraja_SOURCES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the NVECCUDA library
+SET(shared_SOURCES 
+  sundials_math.c
+)
+ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+
+# Add variable nveccuda_HEADERS with the exported NVECSERIAL header files
+SET(nveccuda_HEADERS 
+  nvector_cuda.h
+)
+ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nveccuda_HEADERS)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the NVECCUDA library
+#  - Set the library name and make sure it is not deleted
+#  - Install the NVECSERIAL library
+IF(BUILD_STATIC_LIBS)
+  CUDA_ADD_LIBRARY(sundials_nveccuda_static STATIC ${nveccuda_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_nveccuda_static
+    PROPERTIES OUTPUT_NAME sundials_nveccuda CLEAN_DIRECT_OUTPUT 1
+  )
+  INSTALL(TARGETS sundials_nveccuda_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the NVECSERIAL library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the NVECSERIAL library
+IF(BUILD_SHARED_LIBS)
+  CUDA_ADD_LIBRARY(sundials_nveccuda_shared SHARED ${nveccuda_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_nveccuda_shared
+    PROPERTIES OUTPUT_NAME sundials_nveccuda CLEAN_DIRECT_OUTPUT 1
+  )
+  SET_TARGET_PROPERTIES(sundials_nveccuda_shared
+    PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}
+  )
+  INSTALL(TARGETS sundials_nveccuda_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the NVECSERIAL header files
+INSTALL(FILES ${nveccuda_HEADERS} DESTINATION include/nvector)
+INSTALL(DIRECTORY ${sundials_SOURCE_DIR}/include/nvector/cuda DESTINATION include/nvector)
+
+MESSAGE(STATUS "Added NVECTOR_CUDA module")
diff --git a/src/nvec_cuda/nvector_cuda.cu b/src/nvec_cuda/nvector_cuda.cu
new file mode 100644
index 0000000..5a0f2a6
--- /dev/null
+++ b/src/nvec_cuda/nvector_cuda.cu
@@ -0,0 +1,459 @@
+/* -----------------------------------------------------------------
+ * Programmer(s): Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for a serial implementation
+ * of the NVECTOR package.
+ * -----------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nvector/cuda/Vector.hpp>
+#include <nvector/cuda/VectorKernels.cuh>
+
+extern "C" {
+
+using namespace suncudavec;
+
+/* ----------------------------------------------------------------
+ * Returns vector type ID. Used to identify vector implementation
+ * from abstract N_Vector interface.
+ */
+N_Vector_ID N_VGetVectorID_Cuda(N_Vector v)
+{
+  return SUNDIALS_NVEC_CUDA;
+}
+
+N_Vector N_VNewEmpty_Cuda(sunindextype length)
+{
+  N_Vector v;
+  N_Vector_Ops ops;
+  N_VectorContent_Cuda content;
+
+  /* Create vector */
+  v = NULL;
+  v = (N_Vector) malloc(sizeof *v);
+  if (v == NULL) return(NULL);
+
+  /* Create vector operation structure */
+  ops = NULL;
+  ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops));
+  if (ops == NULL) { free(v); return(NULL); }
+
+  ops->nvgetvectorid     = N_VGetVectorID_Cuda;
+  ops->nvclone           = N_VClone_Cuda;
+  ops->nvcloneempty      = N_VCloneEmpty_Cuda;
+  ops->nvdestroy         = N_VDestroy_Cuda;
+  ops->nvspace           = N_VSpace_Cuda;
+  ops->nvgetarraypointer = NULL;
+  ops->nvsetarraypointer = NULL;
+  ops->nvlinearsum       = N_VLinearSum_Cuda;
+  ops->nvconst           = N_VConst_Cuda;
+  ops->nvprod            = N_VProd_Cuda;
+  ops->nvdiv             = N_VDiv_Cuda;
+  ops->nvscale           = N_VScale_Cuda;
+  ops->nvabs             = N_VAbs_Cuda;
+  ops->nvinv             = N_VInv_Cuda;
+  ops->nvaddconst        = N_VAddConst_Cuda;
+  ops->nvdotprod         = N_VDotProd_Cuda;
+  ops->nvmaxnorm         = N_VMaxNorm_Cuda;
+  ops->nvwrmsnormmask    = N_VWrmsNormMask_Cuda;
+  ops->nvwrmsnorm        = N_VWrmsNorm_Cuda;
+  ops->nvmin             = N_VMin_Cuda;
+  ops->nvwl2norm         = N_VWL2Norm_Cuda;
+  ops->nvl1norm          = N_VL1Norm_Cuda;
+  ops->nvcompare         = N_VCompare_Cuda;
+  ops->nvinvtest         = N_VInvTest_Cuda;
+  ops->nvconstrmask      = N_VConstrMask_Cuda;
+  ops->nvminquotient     = N_VMinQuotient_Cuda;
+
+  /* Create content */
+  content = NULL;
+
+  /* Attach content and ops */
+  v->content = content;
+  v->ops     = ops;
+
+  return(v);
+}
+
+
+N_Vector N_VNew_Cuda(sunindextype length)
+{
+  N_Vector v;
+
+  v = NULL;
+  v = N_VNewEmpty_Cuda(length);
+  if (v == NULL)
+    return(NULL);
+
+  v->content = new Vector<realtype, sunindextype>(length);
+
+  return(v);
+}
+
+
+N_Vector N_VMake_Cuda(N_VectorContent_Cuda c)
+{
+  N_Vector v;
+  Vector<realtype, sunindextype>* x = static_cast<Vector<realtype, sunindextype>*>(c);
+  sunindextype length = x->size();
+
+  v = NULL;
+  v = N_VNewEmpty_Cuda(length);
+  if (v == NULL) return(NULL);
+
+  v->content = c;
+
+  return(v);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to create an array of new CUDA-based vectors.
+ */
+
+N_Vector *N_VCloneVectorArray_Cuda(int count, N_Vector w)
+{
+  N_Vector *vs;
+  int j;
+
+  if (count <= 0) return(NULL);
+
+  vs = NULL;
+  vs = (N_Vector *) malloc(count * sizeof(N_Vector));
+  if(vs == NULL) return(NULL);
+
+  for (j = 0; j < count; j++) {
+    vs[j] = NULL;
+    vs[j] = N_VClone_Cuda(w);
+    if (vs[j] == NULL) {
+      N_VDestroyVectorArray_Cuda(vs, j-1);
+      return(NULL);
+    }
+  }
+
+  return(vs);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to create an array of new serial vectors with NULL data array.
+ */
+
+N_Vector *N_VCloneVectorArrayEmpty_Cuda(int count, N_Vector w)
+{
+  N_Vector *vs;
+  int j;
+
+  if (count <= 0) return(NULL);
+
+  vs = NULL;
+  vs = (N_Vector *) malloc(count * sizeof(N_Vector));
+  if(vs == NULL) return(NULL);
+
+  for (j = 0; j < count; j++) {
+    vs[j] = NULL;
+    vs[j] = N_VCloneEmpty_Cuda(w);
+    if (vs[j] == NULL) {
+      N_VDestroyVectorArray_Cuda(vs, j-1);
+      return(NULL);
+    }
+  }
+
+  return(vs);
+}
+
+/* -----------------------------------------------------------------
+ * Function to return the length of the vector.
+ */
+sunindextype N_VGetLength_Cuda(N_Vector v)
+{
+  Vector<realtype, sunindextype>* xd = static_cast<Vector<realtype, sunindextype>*>(v->content);
+  return xd->size();
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to free an array created with N_VCloneVectorArray_Cuda
+ */
+
+void N_VDestroyVectorArray_Cuda(N_Vector *vs, int count)
+{
+  int j;
+
+  for (j = 0; j < count; j++) N_VDestroy_Cuda(vs[j]);
+
+  free(vs); vs = NULL;
+
+  return;
+}
+
+/* ----------------------------------------------------------------------------
+ * Return pointer to the raw host data
+ */
+
+realtype *N_VGetHostArrayPointer_Cuda(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  return (xv->host());
+}
+
+/* ----------------------------------------------------------------------------
+ * Return pointer to the raw device data
+ */
+
+realtype *N_VGetDeviceArrayPointer_Cuda(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  return (xv->device());
+}
+
+/* ----------------------------------------------------------------------------
+ * Copy vector data to the device
+ */
+
+void N_VCopyToDevice_Cuda(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  xv->copyToDev();
+}
+
+/* ----------------------------------------------------------------------------
+ * Copy vector data from the device to the host
+ */
+
+void N_VCopyFromDevice_Cuda(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  xv->copyFromDev();
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to print the a CUDA-based vector to stdout
+ */
+
+void N_VPrint_Cuda(N_Vector x)
+{
+  N_VPrintFile_Cuda(x, stdout);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to print the a CUDA-based vector to outfile
+ */
+
+void N_VPrintFile_Cuda(N_Vector x, FILE *outfile)
+{
+  sunindextype i;
+  Vector<realtype, sunindextype>* xd = static_cast<Vector<realtype, sunindextype>*>(x->content);
+
+  for (i = 0; i < xd->size(); i++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    fprintf(outfile, "%35.32Lg\n", xd->host()[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+    fprintf(outfile, "%19.16g\n", xd->host()[i]);
+#else
+    fprintf(outfile, "%11.8g\n", xd->host()[i]);
+#endif
+  }
+  fprintf(outfile, "\n");
+
+  return;
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of vector operations
+ * -----------------------------------------------------------------
+ */
+
+N_Vector N_VCloneEmpty_Cuda(N_Vector w)
+{
+  N_Vector v;
+  N_Vector_Ops ops;
+
+  if (w == NULL) return(NULL);
+
+  /* Create vector */
+  v = NULL;
+  v = (N_Vector) malloc(sizeof *v);
+  if (v == NULL) return(NULL);
+
+  /* Create vector operation structure */
+  ops = NULL;
+  ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops));
+  if (ops == NULL) { free(v); return(NULL); }
+
+  ops->nvgetvectorid     = w->ops->nvgetvectorid;
+  ops->nvclone           = w->ops->nvclone;
+  ops->nvcloneempty      = w->ops->nvcloneempty;
+  ops->nvdestroy         = w->ops->nvdestroy;
+  ops->nvspace           = w->ops->nvspace;
+  ops->nvgetarraypointer = w->ops->nvgetarraypointer;
+  ops->nvsetarraypointer = w->ops->nvsetarraypointer;
+  ops->nvlinearsum       = w->ops->nvlinearsum;
+  ops->nvconst           = w->ops->nvconst;
+  ops->nvprod            = w->ops->nvprod;
+  ops->nvdiv             = w->ops->nvdiv;
+  ops->nvscale           = w->ops->nvscale;
+  ops->nvabs             = w->ops->nvabs;
+  ops->nvinv             = w->ops->nvinv;
+  ops->nvaddconst        = w->ops->nvaddconst;
+  ops->nvdotprod         = w->ops->nvdotprod;
+  ops->nvmaxnorm         = w->ops->nvmaxnorm;
+  ops->nvwrmsnormmask    = w->ops->nvwrmsnormmask;
+  ops->nvwrmsnorm        = w->ops->nvwrmsnorm;
+  ops->nvmin             = w->ops->nvmin;
+  ops->nvwl2norm         = w->ops->nvwl2norm;
+  ops->nvl1norm          = w->ops->nvl1norm;
+  ops->nvcompare         = w->ops->nvcompare;
+  ops->nvinvtest         = w->ops->nvinvtest;
+  ops->nvconstrmask      = w->ops->nvconstrmask;
+  ops->nvminquotient     = w->ops->nvminquotient;
+
+  /* Create content */
+  v->content = NULL;
+  v->ops  = ops;
+
+  return(v);
+}
+
+N_Vector N_VClone_Cuda(N_Vector w)
+{
+  N_Vector v;
+  Vector<realtype, sunindextype>* wdat = static_cast<Vector<realtype, sunindextype>*>(w->content);
+  Vector<realtype, sunindextype>* vdat = new Vector<realtype, sunindextype>(*wdat);
+  v = NULL;
+  v = N_VCloneEmpty_Cuda(w);
+  if (v == NULL) return(NULL);
+
+  v->content = vdat;
+
+  return(v);
+}
+
+
+void N_VDestroy_Cuda(N_Vector v)
+{
+  Vector<realtype, sunindextype>* x = static_cast<Vector<realtype, sunindextype>*>(v->content);
+  if (x != NULL) {
+    delete x;
+    v->content = NULL;
+  }
+  
+  free(v->ops); v->ops = NULL;
+  free(v); v = NULL;
+
+  return;
+}
+
+void N_VSpace_Cuda(N_Vector X, sunindextype *lrw, sunindextype *liw)
+{
+  *lrw = (extract<realtype, sunindextype>(X))->size();
+  *liw = 1;
+}
+
+void N_VConst_Cuda(realtype a, N_Vector X)
+{
+  setConst(a, *extract<realtype, sunindextype>(X));
+}
+
+void N_VLinearSum_Cuda(realtype a, N_Vector X, realtype b, N_Vector Y, N_Vector Z)
+{
+  linearSum(a, *extract<realtype, sunindextype>(X), b, *extract<realtype, sunindextype>(Y), *extract<realtype, sunindextype>(Z));
+}
+
+void N_VProd_Cuda(N_Vector X, N_Vector Y, N_Vector Z)
+{
+  prod(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Y), *extract<realtype, sunindextype>(Z));
+}
+
+void N_VDiv_Cuda(N_Vector X, N_Vector Y, N_Vector Z)
+{
+  div(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Y), *extract<realtype, sunindextype>(Z));
+}
+
+void N_VScale_Cuda(realtype a, N_Vector X, N_Vector Z)
+{
+  scale(a, *extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Z));
+}
+
+void N_VAbs_Cuda(N_Vector X, N_Vector Z)
+{
+  absVal(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Z));
+}
+
+void N_VInv_Cuda(N_Vector X, N_Vector Z)
+{
+  inv(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Z));
+}
+
+void N_VAddConst_Cuda(N_Vector X, realtype b, N_Vector Z)
+{
+  addConst(b, *extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Z));
+}
+
+realtype N_VDotProd_Cuda(N_Vector X, N_Vector Y)
+{
+  return (dotProd(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Y)));
+}
+
+realtype N_VMaxNorm_Cuda(N_Vector X)
+{
+  return (maxNorm(*extract<realtype, sunindextype>(X)));
+}
+
+realtype N_VWrmsNorm_Cuda(N_Vector X, N_Vector W)
+{
+  return (wrmsNorm(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(W)));
+}
+
+realtype N_VWrmsNormMask_Cuda(N_Vector X, N_Vector W, N_Vector Id)
+{
+  return (wrmsNormMask(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(W), *extract<realtype, sunindextype>(Id)));
+}
+
+realtype N_VMin_Cuda(N_Vector X)
+{
+  return (findMin(*extract<realtype, sunindextype>(X)));
+}
+
+realtype N_VWL2Norm_Cuda(N_Vector X, N_Vector W)
+{
+  return (wL2Norm(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(W)));
+}
+
+realtype N_VL1Norm_Cuda(N_Vector X)
+{
+  return (L1Norm(*extract<realtype, sunindextype>(X)));
+}
+
+void N_VCompare_Cuda(realtype c, N_Vector X, N_Vector Z)
+{
+  compare(c, *extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Z));
+}
+
+booleantype N_VInvTest_Cuda(N_Vector X, N_Vector Z)
+{
+  return (booleantype) (invTest(*extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(Z)));
+}
+
+booleantype N_VConstrMask_Cuda(N_Vector C, N_Vector X, N_Vector M)
+{
+  return (booleantype) (constrMask(*extract<realtype, sunindextype>(C), *extract<realtype, sunindextype>(X), *extract<realtype, sunindextype>(M)));
+}
+
+realtype N_VMinQuotient_Cuda(N_Vector num, N_Vector denom)
+{
+  return (minQuotient(*extract<realtype, sunindextype>(num), *extract<realtype, sunindextype>(denom)));
+}
+
+} // extern "C"
diff --git a/src/nvec_openmp/CMakeLists.txt b/src/nvec_openmp/CMakeLists.txt
index eab8451..aed871a 100644
--- a/src/nvec_openmp/CMakeLists.txt
+++ b/src/nvec_openmp/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4075 $
-# $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Steve Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -23,12 +20,14 @@ SET(nvecopenmp_SOURCES nvector_openmp.c)
 
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the NVECOPENMP library
-SET(shared_SOURCES sundials_math.c)
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+SET(shared_SOURCES 
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
 
 # Add variable nvecopenmp_HEADERS with the exported NVECOPENMP header files
-SET(nvecopenmp_HEADERS nvector_openmp.h)
-ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecopenmp_HEADERS)
+SET(nvecopenmp_HEADERS 
+  ${sundials_SOURCE_DIR}/include/nvector/nvector_openmp.h
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(.)
@@ -61,6 +60,11 @@ ENDIF(BUILD_STATIC_LIBS)
 #  - Install the NVECOPENMP library
 IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(sundials_nvecopenmp_shared SHARED ${nvecopenmp_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_nvecopenmp_shared m)
+  ENDIF()
+
   SET_TARGET_PROPERTIES(sundials_nvecopenmp_shared
     PROPERTIES OUTPUT_NAME sundials_nvecopenmp CLEAN_DIRECT_OUTPUT 1)
   SET_TARGET_PROPERTIES(sundials_nvecopenmp_shared
@@ -74,20 +78,27 @@ INSTALL(FILES ${nvecopenmp_HEADERS} DESTINATION include/nvector)
 # If FCMIX is enabled, build and install the FNVECOPENMP library
 IF(FCMIX_ENABLE AND F77_FOUND)
   SET(fnvecopenmp_SOURCES fnvector_openmp.c)
+
   IF(BUILD_STATIC_LIBS)
     ADD_LIBRARY(sundials_fnvecopenmp_static STATIC ${fnvecopenmp_SOURCES})
     SET_TARGET_PROPERTIES(sundials_fnvecopenmp_static
       PROPERTIES OUTPUT_NAME sundials_fnvecopenmp CLEAN_DIRECT_OUTPUT 1)
     INSTALL(TARGETS sundials_fnvecopenmp_static DESTINATION lib)
   ENDIF(BUILD_STATIC_LIBS)
+
   IF(BUILD_SHARED_LIBS)
     ADD_LIBRARY(sundials_fnvecopenmp_shared ${fnvecopenmp_SOURCES})
+    
+    # fnvecopenmp depends on nvecopenmp
+    TARGET_LINK_LIBRARIES(sundials_fnvecopenmp_shared sundials_nvecopenmp_shared)
+
     SET_TARGET_PROPERTIES(sundials_fnvecopenmp_shared
       PROPERTIES OUTPUT_NAME sundials_fnvecopenmp CLEAN_DIRECT_OUTPUT 1)
     SET_TARGET_PROPERTIES(sundials_fnvecopenmp_shared 
       PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION})
     INSTALL(TARGETS sundials_fnvecopenmp_shared DESTINATION lib)
   ENDIF(BUILD_SHARED_LIBS)
+
 ENDIF(FCMIX_ENABLE AND F77_FOUND)
 
 #
diff --git a/src/nvec_openmp/README b/src/nvec_openmp/README
index d7faa43..4b77a19 100644
--- a/src/nvec_openmp/README
+++ b/src/nvec_openmp/README
@@ -1,7 +1,7 @@
                      NVECTOR_OPENMP
                  released as part of SUNDIALS
     SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
-                   Release 2.7.0, September 2016
+                   Release 3.1.0, November 2017
 
 
 OpenMP implementation of the NVECTOR module for SUNDIALS. 
@@ -39,7 +39,9 @@ For complete installation instructions see any of the user guides.
 C. Releases
 -----------
 
-v. 2.7.0 - Sep. 2015
+v. 3.1.0 - Nov. 2017
+v. 3.0.0 - Sep. 2017
+v. 2.7.0 - Sep. 2016
 v. 2.6.2 - Aug. 2015
 v. 2.6.1 - Mar. 2015
 v. 2.6.0 - Mar. 2015
diff --git a/src/nvec_openmp/fnvector_openmp.c b/src/nvec_openmp/fnvector_openmp.c
index 6108cf7..f82bd61 100644
--- a/src/nvec_openmp/fnvector_openmp.c
+++ b/src/nvec_openmp/fnvector_openmp.c
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4388 $
- * $Date: 2015-02-25 15:50:00 -0800 (Wed, 25 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Steven Smith @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -155,5 +152,3 @@ void FNV_INITOMP_S(int *code, int *Ns, int *ier)
     *ier = -1;
   }
 }
-
-
diff --git a/src/nvec_openmp/fnvector_openmp.h b/src/nvec_openmp/fnvector_openmp.h
index 4451b4b..1e83a3b 100644
--- a/src/nvec_openmp/fnvector_openmp.h
+++ b/src/nvec_openmp/fnvector_openmp.h
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4388 $
- * $Date: 2015-02-25 15:50:00 -0800 (Wed, 25 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Steven Smith @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -71,8 +68,8 @@ extern N_Vector F2C_KINSOL_vec;
 
 extern N_Vector F2C_ARKODE_vec;
 
-/* 
- * Prototypes of exported functions 
+/*
+ * Prototypes of exported functions
  *
  * FNV_INITOMP    - initializes openmp vector operations for main problem
  * FNV_INITOMP_Q  - initializes openmp vector operations for quadratures
diff --git a/src/nvec_openmp/nvector_openmp.c b/src/nvec_openmp/nvector_openmp.c
index aa23004..a303dc4 100644
--- a/src/nvec_openmp/nvector_openmp.c
+++ b/src/nvec_openmp/nvector_openmp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4869 $
- * $Date: 2016-08-19 10:34:20 -0700 (Fri, 19 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner and Carol S. Woodward @ LLNL
  * -----------------------------------------------------------------
  * Acknowledgements: This NVECTOR module is based on the NVECTOR 
@@ -22,8 +18,7 @@
  * -----------------------------------------------------------------
  * This is the implementation file for an OpenMP implementation
  * of the NVECTOR module.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <omp.h>
 
@@ -79,7 +74,7 @@ N_Vector_ID N_VGetVectorID_OpenMP(N_Vector v)
  * Function to create a new empty vector 
  */
 
-N_Vector N_VNewEmpty_OpenMP(long int length, int num_threads)
+N_Vector N_VNewEmpty_OpenMP(sunindextype length, int num_threads)
 {
   N_Vector v;
   N_Vector_Ops ops;
@@ -129,7 +124,7 @@ N_Vector N_VNewEmpty_OpenMP(long int length, int num_threads)
 
   content->length   = length;
   content->num_threads = num_threads;
-  content->own_data = FALSE;
+  content->own_data = SUNFALSE;
   content->data     = NULL;
 
   /* Attach content and ops */
@@ -143,7 +138,7 @@ N_Vector N_VNewEmpty_OpenMP(long int length, int num_threads)
  * Function to create a new vector 
  */
 
-N_Vector N_VNew_OpenMP(long int length, int num_threads)
+N_Vector N_VNew_OpenMP(sunindextype length, int num_threads)
 {
   N_Vector v;
   realtype *data;
@@ -161,7 +156,7 @@ N_Vector N_VNew_OpenMP(long int length, int num_threads)
     if(data == NULL) { N_VDestroy_OpenMP(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_OMP(v) = TRUE;
+    NV_OWN_DATA_OMP(v) = SUNTRUE;
     NV_DATA_OMP(v)     = data;
 
   }
@@ -173,7 +168,7 @@ N_Vector N_VNew_OpenMP(long int length, int num_threads)
  * Function to create a vector with user data component 
  */
 
-N_Vector N_VMake_OpenMP(long int length, realtype *v_data, int num_threads)
+N_Vector N_VMake_OpenMP(sunindextype length, realtype *v_data, int num_threads)
 {
   N_Vector v;
 
@@ -183,7 +178,7 @@ N_Vector N_VMake_OpenMP(long int length, realtype *v_data, int num_threads)
 
   if (length > 0) {
     /* Attach data */
-    NV_OWN_DATA_OMP(v) = FALSE;
+    NV_OWN_DATA_OMP(v) = SUNFALSE;
     NV_DATA_OMP(v)     = v_data;
   }
 
@@ -262,19 +257,27 @@ void N_VDestroyVectorArray_OpenMP(N_Vector *vs, int count)
 /* ----------------------------------------------------------------------------
  * Function to return number of vector elements
  */
-long int N_VGetLength_OpenMP(N_Vector v)
+sunindextype N_VGetLength_OpenMP(N_Vector v)
 {
   return NV_LENGTH_OMP(v);
 }
 
- 
 /* ----------------------------------------------------------------------------
- * Function to print a vector 
+ * Function to print a vector to stdout
  */
  
 void N_VPrint_OpenMP(N_Vector x)
 {
-  long int i, N;
+  N_VPrintFile_OpenMP(x, stdout);
+}
+ 
+/* ----------------------------------------------------------------------------
+ * Function to print a vector to outfile
+ */
+ 
+void N_VPrintFile_OpenMP(N_Vector x, FILE *outfile)
+{
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
@@ -284,14 +287,14 @@ void N_VPrint_OpenMP(N_Vector x)
 
   for (i = 0; i < N; i++) {
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-    printf("%11.8Lg\n", xd[i]);
+    fprintf(outfile, "%11.8Lg\n", xd[i]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-    printf("%11.8g\n", xd[i]);
+    fprintf(outfile, "%11.8g\n", xd[i]);
 #else
-    printf("%11.8g\n", xd[i]);
+    fprintf(outfile, "%11.8g\n", xd[i]);
 #endif
   }
-  printf("\n");
+  fprintf(outfile, "\n");
 
   return;
 }
@@ -358,7 +361,7 @@ N_Vector N_VCloneEmpty_OpenMP(N_Vector w)
 
   content->length   = NV_LENGTH_OMP(w);
   content->num_threads   = NV_NUM_THREADS_OMP(w);
-  content->own_data = FALSE;
+  content->own_data = SUNFALSE;
   content->data     = NULL;
 
   /* Attach content and ops */
@@ -377,7 +380,7 @@ N_Vector N_VClone_OpenMP(N_Vector w)
 {
   N_Vector v;
   realtype *data;
-  long int length;
+  sunindextype length;
 
   v = NULL;
   v = N_VCloneEmpty_OpenMP(w);
@@ -394,7 +397,7 @@ N_Vector N_VClone_OpenMP(N_Vector w)
     if(data == NULL) { N_VDestroy_OpenMP(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_OMP(v) = TRUE;
+    NV_OWN_DATA_OMP(v) = SUNTRUE;
     NV_DATA_OMP(v)     = data;
 
   }
@@ -409,7 +412,7 @@ N_Vector N_VClone_OpenMP(N_Vector w)
 
 void N_VDestroy_OpenMP(N_Vector v)
 {
-  if (NV_OWN_DATA_OMP(v) == TRUE) {
+  if (NV_OWN_DATA_OMP(v) == SUNTRUE) {
     free(NV_DATA_OMP(v));
     NV_DATA_OMP(v) = NULL;
   }
@@ -425,7 +428,7 @@ void N_VDestroy_OpenMP(N_Vector v)
  * Get storage requirement for N_Vector
  */
 
-void N_VSpace_OpenMP(N_Vector v, long int *lrw, long int *liw)
+void N_VSpace_OpenMP(N_Vector v, sunindextype *lrw, sunindextype *liw)
 {
   *lrw = NV_LENGTH_OMP(v);
   *liw = 1;
@@ -462,7 +465,7 @@ void N_VSetArrayPointer_OpenMP(realtype *v_data, N_Vector v)
 
 void N_VLinearSum_OpenMP(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype c, *xd, *yd, *zd;
   N_Vector v1, v2;
   booleantype test;
@@ -556,7 +559,7 @@ void N_VLinearSum_OpenMP(realtype a, N_Vector x, realtype b, N_Vector y, N_Vecto
 
 void N_VConst_OpenMP(realtype c, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *zd;
 
   zd = NULL;
@@ -578,7 +581,7 @@ void N_VConst_OpenMP(realtype c, N_Vector z)
 
 void N_VProd_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -603,7 +606,7 @@ void N_VProd_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 
 void N_VDiv_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -628,7 +631,7 @@ void N_VDiv_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 
 void N_VScale_OpenMP(realtype c, N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -663,7 +666,7 @@ void N_VScale_OpenMP(realtype c, N_Vector x, N_Vector z)
 
 void N_VAbs_OpenMP(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -686,7 +689,7 @@ void N_VAbs_OpenMP(N_Vector x, N_Vector z)
 
 void N_VInv_OpenMP(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -710,7 +713,7 @@ void N_VInv_OpenMP(N_Vector x, N_Vector z)
 
 void N_VAddConst_OpenMP(N_Vector x, realtype b, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -734,7 +737,7 @@ void N_VAddConst_OpenMP(N_Vector x, realtype b, N_Vector z)
 
 realtype N_VDotProd_OpenMP(N_Vector x, N_Vector y)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd, *yd;
 
   sum = ZERO;
@@ -760,7 +763,7 @@ realtype N_VDotProd_OpenMP(N_Vector x, N_Vector y)
 
 realtype N_VMaxNorm_OpenMP(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype tmax, max, *xd;
 
   max = ZERO;
@@ -793,7 +796,7 @@ realtype N_VMaxNorm_OpenMP(N_Vector x)
 
 realtype N_VWrmsNorm_OpenMP(N_Vector x, N_Vector w)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd, *wd;
 
   sum = ZERO;
@@ -819,7 +822,7 @@ realtype N_VWrmsNorm_OpenMP(N_Vector x, N_Vector w)
 
 realtype N_VWrmsNormMask_OpenMP(N_Vector x, N_Vector w, N_Vector id)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd, *wd, *idd;
 
   sum = ZERO;
@@ -848,7 +851,7 @@ realtype N_VWrmsNormMask_OpenMP(N_Vector x, N_Vector w, N_Vector id)
 
 realtype N_VMin_OpenMP(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype min, *xd;
   realtype tmin;
 
@@ -885,7 +888,7 @@ realtype N_VMin_OpenMP(N_Vector x)
 
 realtype N_VWL2Norm_OpenMP(N_Vector x, N_Vector w)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd, *wd;
 
   sum = ZERO;
@@ -911,7 +914,7 @@ realtype N_VWL2Norm_OpenMP(N_Vector x, N_Vector w)
 
 realtype N_VL1Norm_OpenMP(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd;
 
   sum = ZERO;
@@ -935,7 +938,7 @@ realtype N_VL1Norm_OpenMP(N_Vector x)
 
 void N_VCompare_OpenMP(realtype c, N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -960,7 +963,7 @@ void N_VCompare_OpenMP(realtype c, N_Vector x, N_Vector z)
 
 booleantype N_VInvTest_OpenMP(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd, val;
 
   xd = zd = NULL;
@@ -981,9 +984,9 @@ booleantype N_VInvTest_OpenMP(N_Vector x, N_Vector z)
   }
 
   if (val > ZERO)
-    return (FALSE);
+    return (SUNFALSE);
   else
-    return (TRUE);
+    return (SUNTRUE);
 }
 
 
@@ -993,7 +996,7 @@ booleantype N_VInvTest_OpenMP(N_Vector x, N_Vector z)
 
 booleantype N_VConstrMask_OpenMP(N_Vector c, N_Vector x, N_Vector m)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype temp;
   realtype *cd, *xd, *md;
 
@@ -1020,8 +1023,8 @@ booleantype N_VConstrMask_OpenMP(N_Vector c, N_Vector x, N_Vector m)
     }
   }
 
-  if (temp == ONE) return (TRUE);
-  else return(FALSE);
+  if (temp == ONE) return (SUNTRUE);
+  else return(SUNFALSE);
 }
 
 
@@ -1031,7 +1034,7 @@ booleantype N_VConstrMask_OpenMP(N_Vector c, N_Vector x, N_Vector m)
 
 realtype N_VMinQuotient_OpenMP(N_Vector num, N_Vector denom)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *nd, *dd, min, tmin, val;
 
   nd = dd = NULL;
@@ -1077,7 +1080,7 @@ realtype N_VMinQuotient_OpenMP(N_Vector num, N_Vector denom)
 
 static void VCopy_OpenMP(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -1101,7 +1104,7 @@ static void VCopy_OpenMP(N_Vector x, N_Vector z)
 
 static void VSum_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1126,7 +1129,7 @@ static void VSum_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 
 static void VDiff_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1151,7 +1154,7 @@ static void VDiff_OpenMP(N_Vector x, N_Vector y, N_Vector z)
 
 static void VNeg_OpenMP(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -1175,7 +1178,7 @@ static void VNeg_OpenMP(N_Vector x, N_Vector z)
 
 static void VScaleSum_OpenMP(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1200,7 +1203,7 @@ static void VScaleSum_OpenMP(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VScaleDiff_OpenMP(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1225,7 +1228,7 @@ static void VScaleDiff_OpenMP(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin1_OpenMP(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1250,7 +1253,7 @@ static void VLin1_OpenMP(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin2_OpenMP(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1275,7 +1278,7 @@ static void VLin2_OpenMP(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void Vaxpy_OpenMP(realtype a, N_Vector x, N_Vector y)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd;
 
   xd = yd = NULL;
@@ -1315,7 +1318,7 @@ static void Vaxpy_OpenMP(realtype a, N_Vector x, N_Vector y)
 
 static void VScaleBy_OpenMP(realtype a, N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
diff --git a/src/nvec_par/CMakeLists.txt b/src/nvec_par/CMakeLists.txt
index 8477fb4..58ea05a 100644
--- a/src/nvec_par/CMakeLists.txt
+++ b/src/nvec_par/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4625 $
-# $Date: 2016-01-13 16:05:42 -0800 (Wed, 13 Jan 2016) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -31,12 +28,14 @@ SET(nvecparallel_SOURCES nvector_parallel.c)
 
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the NVECPARALLEL library
-SET(shared_SOURCES sundials_math.c)
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+SET(shared_SOURCES 
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
 
 # Add variable nvecparallel_HEADERS with the exported NVECPARALLEL header files
-SET(nvecparallel_HEADERS nvector_parallel.h)
-ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecparallel_HEADERS)
+SET(nvecparallel_HEADERS 
+  ${sundials_SOURCE_DIR}/include/nvector/nvector_parallel.h
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(.)
@@ -62,6 +61,11 @@ ENDIF(BUILD_STATIC_LIBS)
 #  - Install the NVECPARALLEL library
 IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(sundials_nvecparallel_shared SHARED ${nvecparallel_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_nvecparallel_shared m)
+  ENDIF()
+
   SET_TARGET_PROPERTIES(sundials_nvecparallel_shared
     PROPERTIES OUTPUT_NAME sundials_nvecparallel CLEAN_DIRECT_OUTPUT 1)
   SET_TARGET_PROPERTIES(sundials_nvecparallel_shared 
@@ -75,20 +79,27 @@ INSTALL(FILES ${nvecparallel_HEADERS} DESTINATION include/nvector)
 # If FCMIX is enabled and MPI-F77 works, build and install the FNVECPARALLEL library
 IF(FCMIX_ENABLE AND MPIF_FOUND)
   SET(fnvecparallel_SOURCES fnvector_parallel.c)
+
   IF(BUILD_STATIC_LIBS)
     ADD_LIBRARY(sundials_fnvecparallel_static STATIC ${fnvecparallel_SOURCES})
     SET_TARGET_PROPERTIES(sundials_fnvecparallel_static
       PROPERTIES OUTPUT_NAME sundials_fnvecparallel CLEAN_DIRECT_OUTPUT 1)
     INSTALL(TARGETS sundials_fnvecparallel_static DESTINATION lib)
   ENDIF(BUILD_STATIC_LIBS)
+
   IF(BUILD_SHARED_LIBS)
     ADD_LIBRARY(sundials_fnvecparallel_shared SHARED ${fnvecparallel_SOURCES})
+
+    # fnvecparallel depends on nvecparallel
+    TARGET_LINK_LIBRARIES(sundials_fnvecparallel_shared sundials_nvecparallel_shared)
+
     SET_TARGET_PROPERTIES(sundials_fnvecparallel_shared
       PROPERTIES OUTPUT_NAME sundials_fnvecparallel CLEAN_DIRECT_OUTPUT 1)
     SET_TARGET_PROPERTIES(sundials_fnvecparallel_shared
       PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION})
     INSTALL(TARGETS sundials_fnvecparallel_shared DESTINATION lib)
   ENDIF(BUILD_SHARED_LIBS)
+
 ENDIF(FCMIX_ENABLE AND MPIF_FOUND)
 #
 MESSAGE(STATUS "Added NVECTOR_PARALLEL module")
diff --git a/src/nvec_par/README b/src/nvec_par/README
index 246c346..94757f3 100644
--- a/src/nvec_par/README
+++ b/src/nvec_par/README
@@ -1,7 +1,7 @@
                      NVECTOR_PARALLEL
                  released as part of SUNDIALS
     SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
-                   Release 2.7.0, September 2016
+                   Release 3.1.0, November 2017
 
 
 MPI parallel implementation of the NVECTOR module for SUNDIALS. 
@@ -39,6 +39,8 @@ For complete installation instructions see any of the user guides.
 C. Releases
 -----------
 
+v. 3.1.0 - Nov. 2017
+v. 3.0.0 - Sep. 2017
 v. 2.7.0 - Sep. 2016
 v. 2.6.2 - Aug. 2015
 v. 2.6.1 - Mar. 2015
diff --git a/src/nvec_par/fnvector_parallel.c b/src/nvec_par/fnvector_parallel.c
index 42492a7..1427519 100644
--- a/src/nvec_par/fnvector_parallel.c
+++ b/src/nvec_par/fnvector_parallel.c
@@ -1,22 +1,19 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
  * For details, see the LICENSE file.
  * LLNS Copyright End
  * -----------------------------------------------------------------
- * This file (companion of nvector_parallel.h) contains the 
- * implementation needed for the Fortran initialization of parallel 
+ * This file (companion of nvector_parallel.h) contains the
+ * implementation needed for the Fortran initialization of parallel
  * vector operations.
  * -----------------------------------------------------------------
  */
diff --git a/src/nvec_par/fnvector_parallel.h b/src/nvec_par/fnvector_parallel.h
index c9fcbac..c180ee5 100644
--- a/src/nvec_par/fnvector_parallel.h
+++ b/src/nvec_par/fnvector_parallel.h
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -71,8 +68,8 @@ extern N_Vector F2C_KINSOL_vec;
 
 extern N_Vector F2C_ARKODE_vec;
 
-/* 
- * Prototypes of exported functions 
+/*
+ * Prototypes of exported functions
  *
  * FNV_INITP    - initializes parallel vector operations for main problem
  * FNV_INITP_Q  - initializes parallel vector operations for quadratures
diff --git a/src/nvec_par/nvector_parallel.c b/src/nvec_par/nvector_parallel.c
index f9797c8..ca09df5 100644
--- a/src/nvec_par/nvector_parallel.c
+++ b/src/nvec_par/nvector_parallel.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4867 $
- * $Date: 2016-08-19 10:05:14 -0700 (Fri, 19 Aug 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
  *                and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -18,8 +14,7 @@
  * -----------------------------------------------------------------
  * This is the implementation file for a parallel MPI implementation
  * of the NVECTOR package.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -84,19 +79,19 @@ N_Vector_ID N_VGetVectorID_Parallel(N_Vector v)
  */
 
 N_Vector N_VNewEmpty_Parallel(MPI_Comm comm, 
-                              long int local_length,
-                              long int global_length)
+                              sunindextype local_length,
+                              sunindextype global_length)
 {
   N_Vector v;
   N_Vector_Ops ops;
   N_VectorContent_Parallel content;
-  long int n, Nsum;
+  sunindextype n, Nsum;
 
   /* Compute global length as sum of local lengths */
   n = local_length;
   MPI_Allreduce(&n, &Nsum, 1, PVEC_INTEGER_MPI_TYPE, MPI_SUM, comm);
   if (Nsum != global_length) {
-    printf(BAD_N);
+    fprintf(stderr, BAD_N);
     return(NULL);
   } 
 
@@ -146,7 +141,7 @@ N_Vector N_VNewEmpty_Parallel(MPI_Comm comm,
   content->local_length  = local_length;
   content->global_length = global_length;
   content->comm          = comm;
-  content->own_data      = FALSE;
+  content->own_data      = SUNFALSE;
   content->data          = NULL;
 
   /* Attach content and ops */
@@ -161,8 +156,8 @@ N_Vector N_VNewEmpty_Parallel(MPI_Comm comm,
  */
 
 N_Vector N_VNew_Parallel(MPI_Comm comm, 
-                         long int local_length,
-                         long int global_length)
+                         sunindextype local_length,
+                         sunindextype global_length)
 {
   N_Vector v;
   realtype *data;
@@ -180,7 +175,7 @@ N_Vector N_VNew_Parallel(MPI_Comm comm,
     if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_P(v) = TRUE;
+    NV_OWN_DATA_P(v) = SUNTRUE;
     NV_DATA_P(v)     = data; 
 
   }
@@ -193,8 +188,8 @@ N_Vector N_VNew_Parallel(MPI_Comm comm,
  */
 
 N_Vector N_VMake_Parallel(MPI_Comm comm, 
-                          long int local_length,
-                          long int global_length,
+                          sunindextype local_length,
+                          sunindextype global_length,
                           realtype *v_data)
 {
   N_Vector v;
@@ -205,7 +200,7 @@ N_Vector N_VMake_Parallel(MPI_Comm comm,
 
   if (local_length > 0) {
     /* Attach data */
-    NV_OWN_DATA_P(v) = FALSE;
+    NV_OWN_DATA_P(v) = SUNFALSE;
     NV_DATA_P(v)     = v_data;
   }
 
@@ -286,7 +281,7 @@ void N_VDestroyVectorArray_Parallel(N_Vector *vs, int count)
  * Function to return global vector length 
  */
 
-long int N_VGetLength_Parallel(N_Vector v)
+sunindextype N_VGetLength_Parallel(N_Vector v)
 {
   return NV_GLOBLENGTH_P(v);
 }
@@ -295,18 +290,27 @@ long int N_VGetLength_Parallel(N_Vector v)
  * Function to return local vector length 
  */
 
-long int N_VGetLocalLength_Parallel(N_Vector v)
+sunindextype N_VGetLocalLength_Parallel(N_Vector v)
 {
   return NV_LOCLENGTH_P(v);
 }
 
 /* ---------------------------------------------------------------- 
- * Function to print a parallel vector 
+ * Function to print the local data in a parallel vector to stdout
  */
 
 void N_VPrint_Parallel(N_Vector x)
 {
-  long int i, N;
+  N_VPrintFile_Parallel(x, stdout);
+}
+
+/* ---------------------------------------------------------------- 
+ * Function to print the local data in a parallel vector to outfile
+ */
+
+void N_VPrintFile_Parallel(N_Vector x, FILE* outfile)
+{
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
@@ -316,14 +320,14 @@ void N_VPrint_Parallel(N_Vector x)
 
   for (i = 0; i < N; i++) {
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-    printf("%Lg\n", xd[i]);
+    fprintf(outfile, "%Lg\n", xd[i]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-    printf("%g\n", xd[i]);
+    fprintf(outfile, "%g\n", xd[i]);
 #else
-    printf("%g\n", xd[i]);
+    fprintf(outfile, "%g\n", xd[i]);
 #endif
   }
-  printf("\n");
+  fprintf(outfile, "\n");
 
   return;
 }
@@ -388,7 +392,7 @@ N_Vector N_VCloneEmpty_Parallel(N_Vector w)
   content->local_length  = NV_LOCLENGTH_P(w);
   content->global_length = NV_GLOBLENGTH_P(w);
   content->comm          = NV_COMM_P(w);
-  content->own_data      = FALSE;
+  content->own_data      = SUNFALSE;
   content->data          = NULL;
 
   /* Attach content and ops */
@@ -402,7 +406,7 @@ N_Vector N_VClone_Parallel(N_Vector w)
 {
   N_Vector v;
   realtype *data;
-  long int local_length;
+  sunindextype local_length;
 
   v = NULL;
   v = N_VCloneEmpty_Parallel(w);
@@ -419,7 +423,7 @@ N_Vector N_VClone_Parallel(N_Vector w)
     if(data == NULL) { N_VDestroy_Parallel(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_P(v) = TRUE;
+    NV_OWN_DATA_P(v) = SUNTRUE;
     NV_DATA_P(v)     = data;
   }
 
@@ -428,7 +432,7 @@ N_Vector N_VClone_Parallel(N_Vector w)
 
 void N_VDestroy_Parallel(N_Vector v)
 {
-  if ((NV_OWN_DATA_P(v) == TRUE) && (NV_DATA_P(v) != NULL)) {
+  if ((NV_OWN_DATA_P(v) == SUNTRUE) && (NV_DATA_P(v) != NULL)) {
     free(NV_DATA_P(v));
     NV_DATA_P(v) = NULL;
   }
@@ -439,7 +443,7 @@ void N_VDestroy_Parallel(N_Vector v)
   return;
 }
 
-void N_VSpace_Parallel(N_Vector v, long int *lrw, long int *liw)
+void N_VSpace_Parallel(N_Vector v, sunindextype *lrw, sunindextype *liw)
 {
   MPI_Comm comm;
   int npes;
@@ -467,7 +471,7 @@ void N_VSetArrayPointer_Parallel(realtype *v_data, N_Vector v)
 
 void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype c, *xd, *yd, *zd;
   N_Vector v1, v2;
   booleantype test;
@@ -554,7 +558,7 @@ void N_VLinearSum_Parallel(realtype a, N_Vector x, realtype b, N_Vector y, N_Vec
 
 void N_VConst_Parallel(realtype c, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *zd;
 
   zd = NULL;
@@ -569,7 +573,7 @@ void N_VConst_Parallel(realtype c, N_Vector z)
 
 void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -587,7 +591,7 @@ void N_VProd_Parallel(N_Vector x, N_Vector y, N_Vector z)
 
 void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -605,7 +609,7 @@ void N_VDiv_Parallel(N_Vector x, N_Vector y, N_Vector z)
 
 void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -632,7 +636,7 @@ void N_VScale_Parallel(realtype c, N_Vector x, N_Vector z)
 
 void N_VAbs_Parallel(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -649,7 +653,7 @@ void N_VAbs_Parallel(N_Vector x, N_Vector z)
 
 void N_VInv_Parallel(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -666,7 +670,7 @@ void N_VInv_Parallel(N_Vector x, N_Vector z)
 
 void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -682,7 +686,7 @@ void N_VAddConst_Parallel(N_Vector x, realtype b, N_Vector z)
 
 realtype N_VDotProd_Parallel(N_Vector x, N_Vector y)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd, *yd, gsum;
   MPI_Comm comm;
 
@@ -703,7 +707,7 @@ realtype N_VDotProd_Parallel(N_Vector x, N_Vector y)
 
 realtype N_VMaxNorm_Parallel(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype max, *xd, gmax;
   MPI_Comm comm;
 
@@ -726,7 +730,7 @@ realtype N_VMaxNorm_Parallel(N_Vector x)
 
 realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w)
 {
-  long int i, N, N_global;
+  sunindextype i, N, N_global;
   realtype sum, prodi, *xd, *wd, gsum;
   MPI_Comm comm;
 
@@ -751,7 +755,7 @@ realtype N_VWrmsNorm_Parallel(N_Vector x, N_Vector w)
 
 realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id)
 {
-  long int i, N, N_global;
+  sunindextype i, N, N_global;
   realtype sum, prodi, *xd, *wd, *idd, gsum;
   MPI_Comm comm;
 
@@ -779,7 +783,7 @@ realtype N_VWrmsNormMask_Parallel(N_Vector x, N_Vector w, N_Vector id)
 
 realtype N_VMin_Parallel(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype min, *xd, gmin;
   MPI_Comm comm;
 
@@ -809,7 +813,7 @@ realtype N_VMin_Parallel(N_Vector x)
 
 realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, prodi, *xd, *wd, gsum;
   MPI_Comm comm;
 
@@ -833,7 +837,7 @@ realtype N_VWL2Norm_Parallel(N_Vector x, N_Vector w)
 
 realtype N_VL1Norm_Parallel(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, gsum, *xd;
   MPI_Comm comm;
 
@@ -854,7 +858,7 @@ realtype N_VL1Norm_Parallel(N_Vector x)
 
 void N_VCompare_Parallel(realtype c, N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -872,7 +876,7 @@ void N_VCompare_Parallel(realtype c, N_Vector x, N_Vector z)
 
 booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd, val, gval;
   MPI_Comm comm;
 
@@ -894,14 +898,14 @@ booleantype N_VInvTest_Parallel(N_Vector x, N_Vector z)
   gval = VAllReduce_Parallel(val, 3, comm);
 
   if (gval == ZERO)
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype temp;
   realtype *cd, *xd, *md;
   MPI_Comm comm;
@@ -930,14 +934,14 @@ booleantype N_VConstrMask_Parallel(N_Vector c, N_Vector x, N_Vector m)
 
   temp = VAllReduce_Parallel(temp, 3, comm);
 
-  if (temp == ONE) return(TRUE);
-  else return(FALSE);
+  if (temp == ONE) return(SUNTRUE);
+  else return(SUNFALSE);
 }
 
 realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom)
 {
   booleantype notEvenOnce;
-  long int i, N;
+  sunindextype i, N;
   realtype *nd, *dd, min;
   MPI_Comm comm;
 
@@ -948,7 +952,7 @@ realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom)
   dd = NV_DATA_P(denom);
   comm = NV_COMM_P(num);
 
-  notEvenOnce = TRUE;
+  notEvenOnce = SUNTRUE;
   min = BIG_REAL;
 
   for (i = 0; i < N; i++) {
@@ -957,7 +961,7 @@ realtype N_VMinQuotient_Parallel(N_Vector num, N_Vector denom)
       if (!notEvenOnce) min = SUNMIN(min, nd[i]/dd[i]);
       else {
         min = nd[i]/dd[i];
-        notEvenOnce = FALSE;
+        notEvenOnce = SUNFALSE;
       }
     }
   }
@@ -1001,7 +1005,7 @@ static realtype VAllReduce_Parallel(realtype d, int op, MPI_Comm comm)
 
 static void VCopy_Parallel(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -1018,7 +1022,7 @@ static void VCopy_Parallel(N_Vector x, N_Vector z)
 
 static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1036,7 +1040,7 @@ static void VSum_Parallel(N_Vector x, N_Vector y, N_Vector z)
 
 static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1054,7 +1058,7 @@ static void VDiff_Parallel(N_Vector x, N_Vector y, N_Vector z)
 
 static void VNeg_Parallel(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -1071,7 +1075,7 @@ static void VNeg_Parallel(N_Vector x, N_Vector z)
 
 static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1089,7 +1093,7 @@ static void VScaleSum_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1107,7 +1111,7 @@ static void VScaleDiff_Parallel(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1125,7 +1129,7 @@ static void VLin1_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1143,7 +1147,7 @@ static void VLin2_Parallel(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd;
 
   xd = yd = NULL;
@@ -1172,7 +1176,7 @@ static void Vaxpy_Parallel(realtype a, N_Vector x, N_Vector y)
 
 static void VScaleBy_Parallel(realtype a, N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
diff --git a/src/nvec_parhyp/CMakeLists.txt b/src/nvec_parhyp/CMakeLists.txt
index 9255489..c8c45b9 100644
--- a/src/nvec_parhyp/CMakeLists.txt
+++ b/src/nvec_parhyp/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4075 $
-# $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -15,6 +12,7 @@
 # LLNS Copyright End
 # ---------------------------------------------------------------
 # CMakeLists.txt file for the parhyp NVECTOR library
+# ---------------------------------------------------------------
 
 INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_PARHYP\n\")")
 
@@ -63,6 +61,14 @@ ENDIF(BUILD_STATIC_LIBS)
 #  - Install the NVECPARHYP library
 IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(sundials_nvecparhyp_shared SHARED ${nvecparhyp_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_nvecparhyp_shared m)
+  ENDIF()
+
+  # nvecparhyp depends on hypre
+  TARGET_LINK_LIBRARIES(sundials_nvecparhyp_shared ${HYPRE_LIBRARIES})
+
   SET_TARGET_PROPERTIES(sundials_nvecparhyp_shared
     PROPERTIES OUTPUT_NAME sundials_nvecparhyp CLEAN_DIRECT_OUTPUT 1)
   SET_TARGET_PROPERTIES(sundials_nvecparhyp_shared 
diff --git a/src/nvec_parhyp/README b/src/nvec_parhyp/README
index 4469e2f..7381360 100644
--- a/src/nvec_parhyp/README
+++ b/src/nvec_parhyp/README
@@ -1,7 +1,7 @@
                      NVECTOR_PARHYPE
                  released as part of SUNDIALS
     SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
-                   Release 2.7.0, September 2016
+                   Release 3.1.0, November 2017
 
 
 The NVECTOR_PARHYP implementation of the nvector module provided with
@@ -41,6 +41,8 @@ For complete installation instructions see any of the user guides.
 C. Releases
 -----------
 
+v. 3.1.0 - Nov. 2017
+v. 3.0.0 - Sep. 2017
 v. 2.7.0 - Sep. 2016
 
 
diff --git a/src/nvec_parhyp/nvector_parhyp.c b/src/nvec_parhyp/nvector_parhyp.c
index fc56996..123200a 100644
--- a/src/nvec_parhyp/nvector_parhyp.c
+++ b/src/nvec_parhyp/nvector_parhyp.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4396 $
- * $Date: 2015-02-26 16:59:39 -0800 (Thu, 26 Feb 2015) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Jean M. Sexton @ SMU
  *                Slaven Peles @ LLNL
  * -----------------------------------------------------------------
@@ -21,8 +17,7 @@
  * -----------------------------------------------------------------
  * This is the implementation file for a parhyp MPI implementation
  * of the NVECTOR package.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -50,7 +45,7 @@
  * are assumed:
  *
  * N_Vector v;
- * long int v_len, s_len, i;
+ * sunindextype v_len, s_len, i;
  *
  * (1) NV_CONTENT_PH
  *
@@ -165,8 +160,8 @@ N_Vector_ID N_VGetVectorID_ParHyp(N_Vector v)
  * HYPRE vector.
  */
 N_Vector N_VNewEmpty_ParHyp(MPI_Comm comm, 
-                            long int local_length,
-                            long int global_length)
+                            sunindextype local_length,
+                            sunindextype global_length)
 {
   N_Vector v;
   N_Vector_Ops ops;
@@ -218,7 +213,7 @@ N_Vector N_VNewEmpty_ParHyp(MPI_Comm comm,
   content->local_length  = local_length;
   content->global_length = global_length;
   content->comm          = comm;
-  content->own_parvector = FALSE;
+  content->own_parvector = SUNFALSE;
   content->x             = NULL;
   
   /* Attach content and ops */
@@ -248,7 +243,7 @@ N_Vector N_VMake_ParHyp(hypre_ParVector *x)
   if (v == NULL) 
     return(NULL);
 
-  NV_OWN_PARVEC_PH(v)   = FALSE;
+  NV_OWN_PARVEC_PH(v)   = SUNFALSE;
   NV_HYPRE_PARVEC_PH(v) = x;
 
   return(v);
@@ -344,7 +339,17 @@ hypre_ParVector* N_VGetVector_ParHyp(N_Vector v)
 
 void N_VPrint_ParHyp(N_Vector x)
 {
-  long int i, N;
+  N_VPrintFile_ParHyp(x, stdout);
+}
+
+/* ---------------------------------------------------------------- 
+ * Function to print a parhyp vector.
+ * TODO: Consider using a HYPRE function for this.
+ */
+
+void N_VPrintFile_ParHyp(N_Vector x, FILE *outfile)
+{
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
@@ -354,14 +359,14 @@ void N_VPrint_ParHyp(N_Vector x)
 
   for (i = 0; i < N; i++) {
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-    printf("%Lg\n", xd[i]);
+    fprintf(outfile, "%Lg\n", xd[i]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-    printf("%g\n", xd[i]);
+    fprintf(outfile, "%g\n", xd[i]);
 #else
-    printf("%g\n", xd[i]);
+    fprintf(outfile, "%g\n", xd[i]);
 #endif
   }
-  printf("\n");
+  fprintf(outfile, "\n");
 
   return;
 }
@@ -431,7 +436,7 @@ N_Vector N_VCloneEmpty_ParHyp(N_Vector w)
   content->local_length  = NV_LOCLENGTH_PH(w);
   content->global_length = NV_GLOBLENGTH_PH(w);
   content->comm          = NV_COMM_PH(w);
-  content->own_parvector = FALSE;
+  content->own_parvector = SUNFALSE;
   content->x             = NULL;
   
   /* Attach content and ops */
@@ -464,14 +469,14 @@ N_Vector N_VClone_ParHyp(N_Vector w)
   hypre_SeqVectorSetDataOwner(hypre_ParVectorLocalVector(vx), 1);
   
   NV_HYPRE_PARVEC_PH(v) = vx;
-  NV_OWN_PARVEC_PH(v) = TRUE;
+  NV_OWN_PARVEC_PH(v) = SUNTRUE;
   
   return(v);
 }
 
 void N_VDestroy_ParHyp(N_Vector v)
 {
-  if ((NV_OWN_PARVEC_PH(v) == TRUE)) {
+  if ((NV_OWN_PARVEC_PH(v) == SUNTRUE)) {
     hypre_ParVectorDestroy(NV_HYPRE_PARVEC_PH(v));
   }
   
@@ -483,7 +488,7 @@ void N_VDestroy_ParHyp(N_Vector v)
 }
 
 
-void N_VSpace_ParHyp(N_Vector v, long int *lrw, long int *liw)
+void N_VSpace_ParHyp(N_Vector v, sunindextype *lrw, sunindextype *liw)
 {
   MPI_Comm comm;
   int npes;
@@ -525,7 +530,7 @@ void N_VSetArrayPointer_ParHyp(realtype *v_data, N_Vector v)
  */
 void N_VLinearSum_ParHyp(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype c, *xd, *yd, *zd;
   N_Vector v1, v2;
   booleantype test;
@@ -627,7 +632,7 @@ void N_VConst_ParHyp(realtype c, N_Vector z)
 
 void N_VProd_ParHyp(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -650,7 +655,7 @@ void N_VProd_ParHyp(N_Vector x, N_Vector y, N_Vector z)
 
 void N_VDiv_ParHyp(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -682,7 +687,7 @@ void N_VScale_ParHyp(realtype c, N_Vector x, N_Vector z)
 
 void N_VAbs_ParHyp(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -699,7 +704,7 @@ void N_VAbs_ParHyp(N_Vector x, N_Vector z)
 
 void N_VInv_ParHyp(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -716,7 +721,7 @@ void N_VInv_ParHyp(N_Vector x, N_Vector z)
 
 void N_VAddConst_ParHyp(N_Vector x, realtype b, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -743,7 +748,7 @@ realtype N_VDotProd_ParHyp(N_Vector x, N_Vector y)
 
 realtype N_VMaxNorm_ParHyp(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype max, *xd, gmax;
   MPI_Comm comm;
 
@@ -766,7 +771,7 @@ realtype N_VMaxNorm_ParHyp(N_Vector x)
 
 realtype N_VWrmsNorm_ParHyp(N_Vector x, N_Vector w)
 {
-  long int i, N, N_global;
+  sunindextype i, N, N_global;
   realtype sum, prodi, *xd, *wd, gsum;
   MPI_Comm comm;
 
@@ -791,7 +796,7 @@ realtype N_VWrmsNorm_ParHyp(N_Vector x, N_Vector w)
 
 realtype N_VWrmsNormMask_ParHyp(N_Vector x, N_Vector w, N_Vector id)
 {
-  long int i, N, N_global;
+  sunindextype i, N, N_global;
   realtype sum, prodi, *xd, *wd, *idd, gsum;
   MPI_Comm comm;
 
@@ -819,7 +824,7 @@ realtype N_VWrmsNormMask_ParHyp(N_Vector x, N_Vector w, N_Vector id)
 
 realtype N_VMin_ParHyp(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype min, *xd, gmin;
   MPI_Comm comm;
 
@@ -850,7 +855,7 @@ realtype N_VMin_ParHyp(N_Vector x)
 
 realtype N_VWL2Norm_ParHyp(N_Vector x, N_Vector w)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, prodi, *xd, *wd, gsum;
   MPI_Comm comm;
 
@@ -874,7 +879,7 @@ realtype N_VWL2Norm_ParHyp(N_Vector x, N_Vector w)
 
 realtype N_VL1Norm_ParHyp(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, gsum, *xd;
   MPI_Comm comm;
 
@@ -895,7 +900,7 @@ realtype N_VL1Norm_ParHyp(N_Vector x)
 
 void N_VCompare_ParHyp(realtype c, N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -913,7 +918,7 @@ void N_VCompare_ParHyp(realtype c, N_Vector x, N_Vector z)
 
 booleantype N_VInvTest_ParHyp(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd, val, gval;
   MPI_Comm comm;
 
@@ -935,14 +940,14 @@ booleantype N_VInvTest_ParHyp(N_Vector x, N_Vector z)
   gval = VAllReduce_ParHyp(val, 3, comm);
 
   if (gval == ZERO)
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 booleantype N_VConstrMask_ParHyp(N_Vector c, N_Vector x, N_Vector m)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype temp;
   realtype *cd, *xd, *md;
   MPI_Comm comm;
@@ -978,15 +983,15 @@ booleantype N_VConstrMask_ParHyp(N_Vector c, N_Vector x, N_Vector m)
   temp = VAllReduce_ParHyp(temp, 3, comm);
 
   if (temp == ONE) 
-    return(TRUE);
+    return(SUNTRUE);
   else 
-    return(FALSE);
+    return(SUNFALSE);
 }
 
 realtype N_VMinQuotient_ParHyp(N_Vector num, N_Vector denom)
 {
   booleantype notEvenOnce;
-  long int i, N;
+  sunindextype i, N;
   realtype *nd, *dd, min;
   MPI_Comm comm;
 
@@ -997,7 +1002,7 @@ realtype N_VMinQuotient_ParHyp(N_Vector num, N_Vector denom)
   dd = NV_DATA_PH(denom);
   comm = NV_COMM_PH(num);
 
-  notEvenOnce = TRUE;
+  notEvenOnce = SUNTRUE;
   min = BIG_REAL;
 
   for (i = 0; i < N; i++) {
@@ -1006,7 +1011,7 @@ realtype N_VMinQuotient_ParHyp(N_Vector num, N_Vector denom)
       if (!notEvenOnce) min = SUNMIN(min, nd[i]/dd[i]);
       else {
         min = nd[i]/dd[i];
-        notEvenOnce = FALSE;
+        notEvenOnce = SUNFALSE;
       }
     }
   }
@@ -1051,7 +1056,7 @@ static realtype VAllReduce_ParHyp(realtype d, int op, MPI_Comm comm)
 
 static void VSum_ParHyp(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1069,7 +1074,7 @@ static void VSum_ParHyp(N_Vector x, N_Vector y, N_Vector z)
 
 static void VDiff_ParHyp(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1088,7 +1093,7 @@ static void VDiff_ParHyp(N_Vector x, N_Vector y, N_Vector z)
 
 static void VScaleSum_ParHyp(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1106,7 +1111,7 @@ static void VScaleSum_ParHyp(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VScaleDiff_ParHyp(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1124,7 +1129,7 @@ static void VScaleDiff_ParHyp(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin1_ParHyp(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1142,7 +1147,7 @@ static void VLin1_ParHyp(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin2_ParHyp(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
diff --git a/src/nvec_petsc/CMakeLists.txt b/src/nvec_petsc/CMakeLists.txt
index a98867c..76b7dbd 100644
--- a/src/nvec_petsc/CMakeLists.txt
+++ b/src/nvec_petsc/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision:  $
-# $Date:  $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -31,12 +28,14 @@ SET(nvecpetsc_SOURCES nvector_petsc.c)
 
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the NVECPARHYP library
-SET(shared_SOURCES sundials_math.c)
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+SET(shared_SOURCES 
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
 
 # Add variable nvecpetsc_HEADERS with the exported NVECPARHYP header files
-SET(nvecpetsc_HEADERS nvector_petsc.h)
-ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecpetsc_HEADERS)
+SET(nvecpetsc_HEADERS
+  ${sundials_SOURCE_DIR}/include/nvector/nvector_petsc.h
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(.)
@@ -63,6 +62,14 @@ ENDIF(BUILD_STATIC_LIBS)
 #  - Install the NVECPARHYP library
 IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(sundials_nvecpetsc_shared SHARED ${nvecpetsc_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_nvecpetsc_shared m)
+  ENDIF()
+
+  # nvecpetsc depends on PETSc
+  TARGET_LINK_LIBRARIES(sundials_nvecpetsc_shared ${PETSC_LIBRARIES})
+
   SET_TARGET_PROPERTIES(sundials_nvecpetsc_shared
     PROPERTIES OUTPUT_NAME sundials_nvecpetsc CLEAN_DIRECT_OUTPUT 1)
   SET_TARGET_PROPERTIES(sundials_nvecpetsc_shared 
diff --git a/src/nvec_petsc/README b/src/nvec_petsc/README
index 36f5f8a..6751030 100644
--- a/src/nvec_petsc/README
+++ b/src/nvec_petsc/README
@@ -1,7 +1,7 @@
                      NVECTOR_PARALLEL
                  released as part of SUNDIALS
     SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
-                   Release 2.7.0, September 2016
+                   Release 3.1.0, November 2017
 
 
 NVECTOR_PETSC is an NVECTOR wrapper around the PETSC vector.  
@@ -40,6 +40,8 @@ For complete installation instructions see any of the user guides.
 C. Releases
 -----------
 
+v. 3.1.0 - Nov. 2017
+v. 3.0.0 - Sep. 2017
 v. 2.7.0 - Sep. 2016
 
 
diff --git a/src/nvec_petsc/nvector_petsc.c b/src/nvec_petsc/nvector_petsc.c
index 1ab06da..153a9c1 100644
--- a/src/nvec_petsc/nvector_petsc.c
+++ b/src/nvec_petsc/nvector_petsc.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4918 $
- * $Date: 2016-09-19 09:07:29 -0700 (Mon, 19 Sep 2016) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer(s): Slaven Peles @ LLNL
  * 
  * Based on N_Vector_Parallel by Scott D. Cohen, Alan C. Hindmarsh, 
@@ -20,8 +16,7 @@
  * -----------------------------------------------------------------
  * This is the implementation file for a PETSc implementation
  * of the NVECTOR package.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -53,7 +48,7 @@
  * are assumed:
  *
  * N_Vector v;
- * long int v_len, s_len, i;
+ * sunindextype v_len, s_len, i;
  *
  * (1) NV_CONTENT_PTC
  *
@@ -128,13 +123,13 @@ N_Vector_ID N_VGetVectorID_Petsc(N_Vector v)
  */
 
 N_Vector N_VNewEmpty_Petsc(MPI_Comm comm, 
-                           long int local_length,
-                           long int global_length)
+                           sunindextype local_length,
+                           sunindextype global_length)
 {
   N_Vector v;
   N_Vector_Ops ops;
   N_VectorContent_Petsc content;
-  long int n, Nsum;
+  sunindextype n, Nsum;
   PetscErrorCode ierr;
 
   /* Compute global length as sum of local lengths */
@@ -142,7 +137,7 @@ N_Vector N_VNewEmpty_Petsc(MPI_Comm comm,
   ierr = MPI_Allreduce(&n, &Nsum, 1, PVEC_INTEGER_MPI_TYPE, MPI_SUM, comm);
   CHKERRABORT(comm,ierr);
   if (Nsum != global_length) {
-    printf(BAD_N);
+    fprintf(stderr, BAD_N);
     return(NULL);
   } 
 
@@ -196,7 +191,7 @@ N_Vector N_VNewEmpty_Petsc(MPI_Comm comm,
   content->local_length  = local_length;
   content->global_length = global_length;
   content->comm          = comm;
-  content->own_data      = FALSE;
+  content->own_data      = SUNFALSE;
   content->pvec          = NULL;
 
   /* Attach content and ops */
@@ -229,7 +224,7 @@ N_Vector N_VMake_Petsc(Vec *pvec)
      return(NULL);
 
   /* Attach data */
-  NV_OWN_DATA_PTC(v) = FALSE;
+  NV_OWN_DATA_PTC(v) = SUNFALSE;
   NV_PVEC_PTC(v)     = pvec;
 
   return(v);
@@ -316,7 +311,8 @@ Vec *N_VGetVector_Petsc(N_Vector v)
 }
 
 /* ---------------------------------------------------------------- 
- * Function to print a parallel vector 
+ * Function to print the global data in a PETSc parallel vector to
+ * stdout
  */
 
 void N_VPrint_Petsc(N_Vector x)
@@ -329,6 +325,58 @@ void N_VPrint_Petsc(N_Vector x)
   return;
 }
 
+/* ---------------------------------------------------------------- 
+ * Function to print the global data in a PETSc parallel vector to
+ * fname
+ */
+
+void N_VPrintFile_Petsc(N_Vector x, const char fname[])
+{
+  Vec *xv = NV_PVEC_PTC(x);
+  MPI_Comm comm = NV_COMM_PTC(x);
+  PetscViewer viewer;
+
+  PetscViewerASCIIOpen(comm, fname, &viewer);
+
+  VecView(*xv, viewer);
+
+  PetscViewerDestroy(&viewer);
+
+  return;
+}
+
+/* ---------------------------------------------------------------- 
+ * Function to print the local data in a PETSc parallel vector to
+ * outfile
+ */
+
+/*
+void N_VPrintFileLocal_Petsc(N_Vector x, FILE *outfile)
+{
+  sunindextype i;
+  sunindextype N = NV_LOCLENGTH_PTC(x);
+  Vec *xv = NV_PVEC_PTC(x);
+  PetscScalar *xd;
+
+  VecGetArray(*xv, &xd);
+
+  for (i = 0; i < N; i++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    fprintf(outfile, "%Lg\n", xd[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+    fprintf(outfile, "%g\n", xd[i]);
+#else
+    fprintf(outfile, "%g\n", xd[i]);
+#endif
+  }
+  fprintf(outfile, "\n");
+
+  VecRestoreArray(*xv, &xd);
+
+  return;
+}
+*/
+
 /*
  * -----------------------------------------------------------------
  * implementation of vector operations
@@ -396,7 +444,7 @@ N_Vector N_VCloneEmpty_Petsc(N_Vector w)
   content->local_length  = NV_LOCLENGTH_PTC(w);
   content->global_length = NV_GLOBLENGTH_PTC(w);
   content->comm          = NV_COMM_PTC(w);
-  content->own_data      = FALSE;
+  content->own_data      = SUNFALSE;
   content->pvec          = NULL;
 
   /* Attach content and ops */
@@ -435,7 +483,7 @@ N_Vector N_VClone_Petsc(N_Vector w)
   }
     
   /* Attach data */
-  NV_OWN_DATA_PTC(v) = TRUE;
+  NV_OWN_DATA_PTC(v) = SUNTRUE;
   NV_PVEC_PTC(v)     = pvec;
 
   return(v);
@@ -443,7 +491,7 @@ N_Vector N_VClone_Petsc(N_Vector w)
 
 void N_VDestroy_Petsc(N_Vector v)
 {
-  if (NV_OWN_DATA_PTC(v) == TRUE) {
+  if (NV_OWN_DATA_PTC(v) == SUNTRUE) {
     VecDestroy((NV_PVEC_PTC(v)));
     NV_PVEC_PTC(v) = NULL;
   }
@@ -458,7 +506,7 @@ void N_VDestroy_Petsc(N_Vector v)
   return;
 }
 
-void N_VSpace_Petsc(N_Vector v, long int *lrw, long int *liw)
+void N_VSpace_Petsc(N_Vector v, sunindextype *lrw, sunindextype *liw)
 {
   MPI_Comm comm;
   int npes;
@@ -633,9 +681,9 @@ realtype N_VMaxNorm_Petsc(N_Vector x)
 
 realtype N_VWrmsNorm_Petsc(N_Vector x, N_Vector w)
 {
-  long int i;
-  long int N        = NV_LOCLENGTH_PTC(x);
-  long int N_global = NV_GLOBLENGTH_PTC(x);
+  sunindextype i;
+  sunindextype N        = NV_LOCLENGTH_PTC(x);
+  sunindextype N_global = NV_GLOBLENGTH_PTC(x);
   MPI_Comm comm     = NV_COMM_PTC(x);
   Vec *xv = NV_PVEC_PTC(x);
   Vec *wv = NV_PVEC_PTC(w);
@@ -658,9 +706,9 @@ realtype N_VWrmsNorm_Petsc(N_Vector x, N_Vector w)
 
 realtype N_VWrmsNormMask_Petsc(N_Vector x, N_Vector w, N_Vector id)
 {
-  long int i;
-  long int N        = NV_LOCLENGTH_PTC(x);
-  long int N_global = NV_GLOBLENGTH_PTC(x);
+  sunindextype i;
+  sunindextype N        = NV_LOCLENGTH_PTC(x);
+  sunindextype N_global = NV_GLOBLENGTH_PTC(x);
   MPI_Comm comm     = NV_COMM_PTC(x);
   
   Vec *xv = NV_PVEC_PTC(x);
@@ -702,8 +750,8 @@ realtype N_VMin_Petsc(N_Vector x)
 
 realtype N_VWL2Norm_Petsc(N_Vector x, N_Vector w)
 {
-  long int i;
-  long int N        = NV_LOCLENGTH_PTC(x);
+  sunindextype i;
+  sunindextype N        = NV_LOCLENGTH_PTC(x);
   MPI_Comm comm     = NV_COMM_PTC(x);
 
   Vec *xv = NV_PVEC_PTC(x);
@@ -737,8 +785,8 @@ realtype N_VL1Norm_Petsc(N_Vector x)
 
 void N_VCompare_Petsc(realtype c, N_Vector x, N_Vector z)
 {
-  long int i;
-  long int N = NV_LOCLENGTH_PTC(x);
+  sunindextype i;
+  sunindextype N = NV_LOCLENGTH_PTC(x);
   Vec *xv = NV_PVEC_PTC(x);
   Vec *zv = NV_PVEC_PTC(z);
   PetscReal cpet = c; // <~ realtype should typedef to PETScReal
@@ -758,8 +806,8 @@ void N_VCompare_Petsc(realtype c, N_Vector x, N_Vector z)
 
 booleantype N_VInvTest_Petsc(N_Vector x, N_Vector z)
 {
-  long int i;
-  long int N = NV_LOCLENGTH_PTC(x);
+  sunindextype i;
+  sunindextype N = NV_LOCLENGTH_PTC(x);
   MPI_Comm comm = NV_COMM_PTC(x);
   Vec *xv = NV_PVEC_PTC(x);
   Vec *zv = NV_PVEC_PTC(z);
@@ -781,15 +829,15 @@ booleantype N_VInvTest_Petsc(N_Vector x, N_Vector z)
   val = VAllReduce_Petsc(val, 3, comm);
 
   if (val == ZERO)
-    return(FALSE);
+    return(SUNFALSE);
   else
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 booleantype N_VConstrMask_Petsc(N_Vector c, N_Vector x, N_Vector m)
 {
-  long int i;
-  long int N = NV_LOCLENGTH_PTC(x);
+  sunindextype i;
+  sunindextype N = NV_LOCLENGTH_PTC(x);
   MPI_Comm comm = NV_COMM_PTC(x);
   realtype minval = ONE;
   Vec *xv = NV_PVEC_PTC(x);
@@ -822,16 +870,16 @@ booleantype N_VConstrMask_Petsc(N_Vector c, N_Vector x, N_Vector m)
   minval = VAllReduce_Petsc(minval, 3, comm);
 
   if (minval == ONE) 
-    return(TRUE);
+    return(SUNTRUE);
   else
-    return(FALSE);
+    return(SUNFALSE);
 }
 
 realtype N_VMinQuotient_Petsc(N_Vector num, N_Vector denom)
 {
-  booleantype notEvenOnce = TRUE;
-  long int i; 
-  long int N    = NV_LOCLENGTH_PTC(num);
+  booleantype notEvenOnce = SUNTRUE;
+  sunindextype i; 
+  sunindextype N    = NV_LOCLENGTH_PTC(num);
   MPI_Comm comm = NV_COMM_PTC(num);
 
   Vec *nv = NV_PVEC_PTC(num);
@@ -852,7 +900,7 @@ realtype N_VMinQuotient_Petsc(N_Vector num, N_Vector denom)
         minval = SUNMIN(minval, nr/dr);
       else {
         minval = nr/dr;
-        notEvenOnce = FALSE;
+        notEvenOnce = SUNFALSE;
       }
     }
   }
diff --git a/src/nvec_pthreads/CMakeLists.txt b/src/nvec_pthreads/CMakeLists.txt
index b711d3a..fe58e7d 100644
--- a/src/nvec_pthreads/CMakeLists.txt
+++ b/src/nvec_pthreads/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4075 $
-# $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Steve Smith @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -23,12 +20,14 @@ SET(nvecpthreads_SOURCES nvector_pthreads.c)
 
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the NVECPTHREADS library
-SET(shared_SOURCES sundials_math.c)
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
 
 # Add variable nvecpthreads_HEADERS with the exported NVECPTHREADS header files
-SET(nvecpthreads_HEADERS nvector_pthreads.h)
-ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecpthreads_HEADERS)
+SET(nvecpthreads_HEADERS
+  ${sundials_SOURCE_DIR}/include/nvector/nvector_pthreads.h
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(.)
@@ -54,6 +53,13 @@ ENDIF(BUILD_STATIC_LIBS)
 #  - Install the NVECPTHREADS library
 IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(sundials_nvecpthreads_shared SHARED ${nvecpthreads_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_nvecpthreads_shared m)
+  ENDIF()
+
+  TARGET_LINK_LIBRARIES(sundials_nvecpthreads_shared pthread)
+
   SET_TARGET_PROPERTIES(sundials_nvecpthreads_shared
     PROPERTIES OUTPUT_NAME sundials_nvecpthreads CLEAN_DIRECT_OUTPUT 1)
   SET_TARGET_PROPERTIES(sundials_nvecpthreads_shared
@@ -67,14 +73,20 @@ INSTALL(FILES ${nvecpthreads_HEADERS} DESTINATION include/nvector)
 # If FCMIX is enabled, build and install the FNVECPTHREADS library
 IF(FCMIX_ENABLE AND F77_FOUND)
   SET(fnvecpthreads_SOURCES fnvector_pthreads.c)
+
   IF(BUILD_STATIC_LIBS)
     ADD_LIBRARY(sundials_fnvecpthreads_static STATIC ${fnvecpthreads_SOURCES})
     SET_TARGET_PROPERTIES(sundials_fnvecpthreads_static
       PROPERTIES OUTPUT_NAME sundials_fnvecpthreads CLEAN_DIRECT_OUTPUT 1)
     INSTALL(TARGETS sundials_fnvecpthreads_static DESTINATION lib)
   ENDIF(BUILD_STATIC_LIBS)
+
   IF(BUILD_SHARED_LIBS)
     ADD_LIBRARY(sundials_fnvecpthreads_shared ${fnvecpthreads_SOURCES})
+
+    # fnvecpthreads depends on nvecpthreads
+    TARGET_LINK_LIBRARIES(sundials_fnvecpthreads_shared sundials_nvecpthreads_shared)
+
     SET_TARGET_PROPERTIES(sundials_fnvecpthreads_shared
       PROPERTIES OUTPUT_NAME sundials_fnvecpthreads CLEAN_DIRECT_OUTPUT 1)
     SET_TARGET_PROPERTIES(sundials_fnvecpthreads_shared 
diff --git a/src/nvec_pthreads/README b/src/nvec_pthreads/README
index 23e8ca1..89d3791 100644
--- a/src/nvec_pthreads/README
+++ b/src/nvec_pthreads/README
@@ -1,7 +1,7 @@
                      NVECTOR_PTHREADS
                  released as part of SUNDIALS
     SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
-                   Release 2.7.0, September 2016
+                   Release 3.1.0, November 2017
 
 
 Pthreads implementation of the NVECTOR module for SUNDIALS. 
@@ -39,7 +39,9 @@ For complete installation instructions see any of the user guides.
 C. Releases
 -----------
 
-v. 2.7.0 - Sep. 2015
+v. 3.1.0 - Nov. 2017
+v. 3.0.0 - Sep. 2017
+v. 2.7.0 - Sep. 2016
 v. 2.6.2 - Aug. 2015
 v. 2.6.1 - Mar. 2015
 v. 2.6.0 - Mar. 2015
diff --git a/src/nvec_pthreads/fnvector_pthreads.c b/src/nvec_pthreads/fnvector_pthreads.c
index cfdf938..a4ec6a7 100644
--- a/src/nvec_pthreads/fnvector_pthreads.c
+++ b/src/nvec_pthreads/fnvector_pthreads.c
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4388 $
- * $Date: 2015-02-25 15:50:00 -0800 (Wed, 25 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Steven Smith @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -155,5 +152,3 @@ void FNV_INITPTS_S(int *code, int *Ns, int *ier)
     *ier = -1;
   }
 }
-
-
diff --git a/src/nvec_pthreads/fnvector_pthreads.h b/src/nvec_pthreads/fnvector_pthreads.h
index 52bf706..8c81077 100644
--- a/src/nvec_pthreads/fnvector_pthreads.h
+++ b/src/nvec_pthreads/fnvector_pthreads.h
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4388 $
- * $Date: 2015-02-25 15:50:00 -0800 (Wed, 25 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Steven Smith @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -71,8 +68,8 @@ extern N_Vector F2C_KINSOL_vec;
 
 extern N_Vector F2C_ARKODE_vec;
 
-/* 
- * Prototypes of exported functions 
+/*
+ * Prototypes of exported functions
  *
  * FNV_INITPTS    - initializes pthreads vector operations for main problem
  * FNV_INITPTS_Q  - initializes pthreads vector operations for quadratures
diff --git a/src/nvec_pthreads/nvector_pthreads.c b/src/nvec_pthreads/nvector_pthreads.c
index a2f6898..06551cf 100644
--- a/src/nvec_pthreads/nvector_pthreads.c
+++ b/src/nvec_pthreads/nvector_pthreads.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4869 $
- * $Date: 2016-08-19 10:34:20 -0700 (Fri, 19 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): David J. Gardner @ LLNL
  * ----------------------------------------------------------------- 
  * Acknowledgements: This NVECTOR module is based on the NVECTOR 
@@ -23,8 +19,7 @@
  * This is the implementation file for a POSIX Threads (Pthreads)
  * implementation of the NVECTOR package using a LOCAL array of 
  * structures to pass data to threads.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -92,8 +87,8 @@ static void *N_VConstrMask_PT(void *thread_data);
 static void *N_VMinQuotient_PT(void *thread_data);
 
 /* Function to determine loop values for threads */
-static void N_VSplitLoop(int myid, int *nthreads, long int *N, 
-			 long int *start, long int *end);
+static void N_VSplitLoop(int myid, int *nthreads, sunindextype *N, 
+			 sunindextype *start, sunindextype *end);
 
 /* Function to initialize thread data */
 static void N_VInitThreadData(Pthreads_Data *thread_data);
@@ -117,7 +112,7 @@ N_Vector_ID N_VGetVectorID_Pthreads(N_Vector v)
  * Function to create a new empty vector 
  */
 
-N_Vector N_VNewEmpty_Pthreads(long int length, int num_threads)
+N_Vector N_VNewEmpty_Pthreads(sunindextype length, int num_threads)
 {
   N_Vector v;
   N_Vector_Ops ops;
@@ -167,7 +162,7 @@ N_Vector N_VNewEmpty_Pthreads(long int length, int num_threads)
 
   content->length      = length;
   content->num_threads = num_threads;
-  content->own_data    = FALSE;
+  content->own_data    = SUNFALSE;
   content->data        = NULL;
 
   /* Attach content and ops */
@@ -181,7 +176,7 @@ N_Vector N_VNewEmpty_Pthreads(long int length, int num_threads)
  * Function to create a new vector 
  */
 
-N_Vector N_VNew_Pthreads(long int length, int num_threads)
+N_Vector N_VNew_Pthreads(sunindextype length, int num_threads)
 {
   N_Vector v;
   realtype *data;
@@ -199,7 +194,7 @@ N_Vector N_VNew_Pthreads(long int length, int num_threads)
     if(data == NULL) { N_VDestroy_Pthreads(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_PT(v) = TRUE;
+    NV_OWN_DATA_PT(v) = SUNTRUE;
     NV_DATA_PT(v)     = data;
 
   }
@@ -211,7 +206,7 @@ N_Vector N_VNew_Pthreads(long int length, int num_threads)
  * Function to create a vector with user data component 
  */
 
-N_Vector N_VMake_Pthreads(long int length, int num_threads, realtype *v_data)
+N_Vector N_VMake_Pthreads(sunindextype length, int num_threads, realtype *v_data)
 {
   N_Vector v;
 
@@ -221,7 +216,7 @@ N_Vector N_VMake_Pthreads(long int length, int num_threads, realtype *v_data)
 
   if (length > 0) {
     /* Attach data */
-    NV_OWN_DATA_PT(v) = FALSE;
+    NV_OWN_DATA_PT(v) = SUNFALSE;
     NV_DATA_PT(v)     = v_data;
   }
 
@@ -300,19 +295,27 @@ void N_VDestroyVectorArray_Pthreads(N_Vector *vs, int count)
 /* ----------------------------------------------------------------------------
  * Function to return number of vector elements
  */
-long int N_VGetLength_Pthreads(N_Vector v)
+sunindextype N_VGetLength_Pthreads(N_Vector v)
 {
   return NV_LENGTH_PT(v);
 }
 
- 
 /* ----------------------------------------------------------------------------
- * Function to print a vector 
+ * Function to print a vector to stdout
  */
  
 void N_VPrint_Pthreads(N_Vector x)
 {
-  long int i, N;
+  N_VPrintFile_Pthreads(x, stdout);
+}
+ 
+/* ----------------------------------------------------------------------------
+ * Function to print a vector to outfile
+ */
+ 
+void N_VPrintFile_Pthreads(N_Vector x, FILE *outfile)
+{
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
@@ -322,14 +325,14 @@ void N_VPrint_Pthreads(N_Vector x)
 
   for (i = 0; i < N; i++) {
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-    printf("%11.8Lg\n", xd[i]);
+    fprintf(outfile, "%11.8Lg\n", xd[i]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-    printf("%11.8g\n", xd[i]);
+    fprintf(outfile, "%11.8g\n", xd[i]);
 #else
-    printf("%11.8g\n", xd[i]);
+    fprintf(outfile, "%11.8g\n", xd[i]);
 #endif
   }
-  printf("\n");
+  fprintf(outfile, "\n");
 
   return;
 }
@@ -396,7 +399,7 @@ N_Vector N_VCloneEmpty_Pthreads(N_Vector w)
 
   content->length      = NV_LENGTH_PT(w);
   content->num_threads = NV_NUM_THREADS_PT(w);
-  content->own_data    = FALSE;
+  content->own_data    = SUNFALSE;
   content->data        = NULL;
 
   /* Attach content and ops */
@@ -415,7 +418,7 @@ N_Vector N_VClone_Pthreads(N_Vector w)
 {
   N_Vector v;
   realtype *data;
-  long int length;
+  sunindextype length;
 
   v = NULL;
   v = N_VCloneEmpty_Pthreads(w);
@@ -432,7 +435,7 @@ N_Vector N_VClone_Pthreads(N_Vector w)
     if(data == NULL) { N_VDestroy_Pthreads(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_PT(v) = TRUE;
+    NV_OWN_DATA_PT(v) = SUNTRUE;
     NV_DATA_PT(v)     = data;
 
   }
@@ -446,7 +449,7 @@ N_Vector N_VClone_Pthreads(N_Vector w)
 
 void N_VDestroy_Pthreads(N_Vector v)
 {
-  if (NV_OWN_DATA_PT(v) == TRUE) {
+  if (NV_OWN_DATA_PT(v) == SUNTRUE) {
     free(NV_DATA_PT(v));
     NV_DATA_PT(v) = NULL;
   }
@@ -461,7 +464,7 @@ void N_VDestroy_Pthreads(N_Vector v)
  * Get storage requirement for vector
  */
 
-void N_VSpace_Pthreads(N_Vector v, long int *lrw, long int *liw)
+void N_VSpace_Pthreads(N_Vector v, sunindextype *lrw, sunindextype *liw)
 {
   *lrw = NV_LENGTH_PT(v);
   *liw = 1;
@@ -502,7 +505,7 @@ void N_VLinearSum_Pthreads(realtype a, N_Vector x, realtype b, N_Vector y, N_Vec
   N_Vector v1, v2;
   booleantype test;
 
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -623,7 +626,7 @@ void N_VLinearSum_Pthreads(realtype a, N_Vector x, realtype b, N_Vector y, N_Vec
 
 static void *N_VLinearSum_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype a, b;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
@@ -656,7 +659,7 @@ static void *N_VLinearSum_PT(void *thread_data)
 
 void N_VConst_Pthreads(realtype c, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -707,7 +710,7 @@ void N_VConst_Pthreads(realtype c, N_Vector z)
 
 static void *N_VConst_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype c;
   realtype *zd;
   Pthreads_Data *my_data;
@@ -736,7 +739,7 @@ static void *N_VConst_PT(void *thread_data)
 
 void N_VProd_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -787,7 +790,7 @@ void N_VProd_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 
 static void *N_VProd_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
 
@@ -816,7 +819,7 @@ static void *N_VProd_PT(void *thread_data)
 
 void N_VDiv_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -868,7 +871,7 @@ void N_VDiv_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 
 static void *N_VDiv_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
 
@@ -909,7 +912,7 @@ void N_VScale_Pthreads(realtype c, N_Vector x, N_Vector z)
     VNeg_Pthreads(x, z);
   } 
   else {      
-      long int      N;
+      sunindextype      N;
       int           i, nthreads;
       pthread_t     *threads;
       Pthreads_Data *thread_data;
@@ -962,7 +965,7 @@ void N_VScale_Pthreads(realtype c, N_Vector x, N_Vector z)
 
 static void *N_VScale_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype c;
   realtype *xd, *zd;
   Pthreads_Data *my_data;
@@ -992,7 +995,7 @@ static void *N_VScale_PT(void *thread_data)
 
 void N_VAbs_Pthreads(N_Vector x, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1043,7 +1046,7 @@ void N_VAbs_Pthreads(N_Vector x, N_Vector z)
 
 static void *N_VAbs_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *zd;
   Pthreads_Data *my_data;
 
@@ -1071,7 +1074,7 @@ static void *N_VAbs_PT(void *thread_data)
 
 void N_VInv_Pthreads(N_Vector x, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1122,7 +1125,7 @@ void N_VInv_Pthreads(N_Vector x, N_Vector z)
 
 static void *N_VInv_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *zd;
   Pthreads_Data *my_data;
 
@@ -1150,7 +1153,7 @@ static void *N_VInv_PT(void *thread_data)
 
 void N_VAddConst_Pthreads(N_Vector x, realtype b, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1202,7 +1205,7 @@ void N_VAddConst_Pthreads(N_Vector x, realtype b, N_Vector z)
 
 static void *N_VAddConst_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype b;
   realtype *xd, *zd;
   Pthreads_Data *my_data;
@@ -1232,7 +1235,7 @@ static void *N_VAddConst_PT(void *thread_data)
 
 realtype N_VDotProd_Pthreads(N_Vector x, N_Vector y)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1291,7 +1294,7 @@ realtype N_VDotProd_Pthreads(N_Vector x, N_Vector y)
 
 static void *N_VDotProd_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *yd;
   realtype local_sum, *global_sum;
   Pthreads_Data *my_data;
@@ -1330,7 +1333,7 @@ static void *N_VDotProd_PT(void *thread_data)
 
 realtype N_VMaxNorm_Pthreads(N_Vector x)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1388,7 +1391,7 @@ realtype N_VMaxNorm_Pthreads(N_Vector x)
 
 static void *N_VMaxNorm_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd;
   realtype local_max, *global_max;
   Pthreads_Data *my_data;
@@ -1428,7 +1431,7 @@ static void *N_VMaxNorm_PT(void *thread_data)
 
 realtype N_VWrmsNorm_Pthreads(N_Vector x, N_Vector w)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1487,7 +1490,7 @@ realtype N_VWrmsNorm_Pthreads(N_Vector x, N_Vector w)
 
 static void *N_VWrmsNorm_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *wd;
   realtype local_sum, *global_sum;
   Pthreads_Data *my_data;
@@ -1526,7 +1529,7 @@ static void *N_VWrmsNorm_PT(void *thread_data)
 
 realtype N_VWrmsNormMask_Pthreads(N_Vector x, N_Vector w, N_Vector id)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1586,7 +1589,7 @@ realtype N_VWrmsNormMask_Pthreads(N_Vector x, N_Vector w, N_Vector id)
 
 static void *N_VWrmsNormMask_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *wd, *idd;
   realtype local_sum, *global_sum;
   Pthreads_Data *my_data;
@@ -1628,7 +1631,7 @@ static void *N_VWrmsNormMask_PT(void *thread_data)
 
 realtype N_VMin_Pthreads(N_Vector x)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1689,7 +1692,7 @@ realtype N_VMin_Pthreads(N_Vector x)
 
 static void *N_VMin_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd;
   realtype local_min, *global_min;
   Pthreads_Data *my_data;
@@ -1730,7 +1733,7 @@ static void *N_VMin_PT(void *thread_data)
 
 realtype N_VWL2Norm_Pthreads(N_Vector x, N_Vector w)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1789,7 +1792,7 @@ realtype N_VWL2Norm_Pthreads(N_Vector x, N_Vector w)
 
 static void *N_VWL2Norm_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *wd;
   realtype local_sum, *global_sum;
   Pthreads_Data *my_data;
@@ -1828,7 +1831,7 @@ static void *N_VWL2Norm_PT(void *thread_data)
 
 realtype N_VL1Norm_Pthreads(N_Vector x)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1886,7 +1889,7 @@ realtype N_VL1Norm_Pthreads(N_Vector x)
 
 static void *N_VL1Norm_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd;
   realtype local_sum, *global_sum;
   Pthreads_Data *my_data;
@@ -1924,7 +1927,7 @@ static void *N_VL1Norm_PT(void *thread_data)
 
 void N_VCompare_Pthreads(realtype c, N_Vector x, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -1975,7 +1978,7 @@ void N_VCompare_Pthreads(realtype c, N_Vector x, N_Vector z)
 
 static void *N_VCompare_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype c;
   realtype *xd, *zd;
   Pthreads_Data *my_data;
@@ -2005,7 +2008,7 @@ static void *N_VCompare_PT(void *thread_data)
 
 booleantype N_VInvTest_Pthreads(N_Vector x, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2049,9 +2052,9 @@ booleantype N_VInvTest_Pthreads(N_Vector x, N_Vector z)
   free(thread_data);
 
   if (val > ZERO)
-    return (FALSE);
+    return (SUNFALSE);
   else
-    return (TRUE);
+    return (SUNTRUE);
 }
 
 
@@ -2061,7 +2064,7 @@ booleantype N_VInvTest_Pthreads(N_Vector x, N_Vector z)
 
 static void *N_VInvTest_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *zd;
   realtype local_val, *global_val;
   Pthreads_Data *my_data;
@@ -2102,7 +2105,7 @@ static void *N_VInvTest_PT(void *thread_data)
 
 booleantype N_VConstrMask_Pthreads(N_Vector c, N_Vector x, N_Vector m)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2147,9 +2150,9 @@ booleantype N_VConstrMask_Pthreads(N_Vector c, N_Vector x, N_Vector m)
   free(thread_data);
 
   if (val > ZERO)
-    return(FALSE);
+    return(SUNFALSE);
   else 
-    return(TRUE);
+    return(SUNTRUE);
 }
 
 
@@ -2159,7 +2162,7 @@ booleantype N_VConstrMask_Pthreads(N_Vector c, N_Vector x, N_Vector m)
 
 static void *N_VConstrMask_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *cd, *xd, *md;
   realtype local_val, *global_val;
   Pthreads_Data *my_data;
@@ -2219,7 +2222,7 @@ static void *N_VConstrMask_PT(void *thread_data)
 
 realtype N_VMinQuotient_Pthreads(N_Vector num, N_Vector denom)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2278,7 +2281,7 @@ realtype N_VMinQuotient_Pthreads(N_Vector num, N_Vector denom)
 
 static void *N_VMinQuotient_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *nd, *dd;
   realtype local_min, *global_min;
   Pthreads_Data *my_data;
@@ -2328,7 +2331,7 @@ static void *N_VMinQuotient_PT(void *thread_data)
 
 static void VCopy_Pthreads(N_Vector x, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2379,7 +2382,7 @@ static void VCopy_Pthreads(N_Vector x, N_Vector z)
 
 static void *VCopy_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *zd;
   Pthreads_Data *my_data;
 
@@ -2407,7 +2410,7 @@ static void *VCopy_PT(void *thread_data)
 
 static void VSum_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2459,7 +2462,7 @@ static void VSum_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 
 static void *VSum_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
 
@@ -2488,7 +2491,7 @@ static void *VSum_PT(void *thread_data)
 
 static void VDiff_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2540,7 +2543,7 @@ static void VDiff_Pthreads(N_Vector x, N_Vector y, N_Vector z)
 
 static void *VDiff_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
 
@@ -2569,7 +2572,7 @@ static void *VDiff_PT(void *thread_data)
 
 static void VNeg_Pthreads(N_Vector x, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2620,7 +2623,7 @@ static void VNeg_Pthreads(N_Vector x, N_Vector z)
 
 static void *VNeg_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype *xd, *zd;
   Pthreads_Data *my_data;
 
@@ -2648,7 +2651,7 @@ static void *VNeg_PT(void *thread_data)
 
 static void VScaleSum_Pthreads(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2701,7 +2704,7 @@ static void VScaleSum_Pthreads(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void *VScaleSum_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype c;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
@@ -2732,7 +2735,7 @@ static void *VScaleSum_PT(void *thread_data)
 
 static void VScaleDiff_Pthreads(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2785,7 +2788,7 @@ static void VScaleDiff_Pthreads(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void *VScaleDiff_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype c;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
@@ -2816,7 +2819,7 @@ static void *VScaleDiff_PT(void *thread_data)
 
 static void VLin1_Pthreads(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2869,7 +2872,7 @@ static void VLin1_Pthreads(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void *VLin1_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype a;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
@@ -2900,7 +2903,7 @@ static void *VLin1_PT(void *thread_data)
 
 static void VLin2_Pthreads(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -2952,7 +2955,7 @@ static void VLin2_Pthreads(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void *VLin2_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype a;
   realtype *xd, *yd, *zd;
   Pthreads_Data *my_data;
@@ -2983,7 +2986,7 @@ static void *VLin2_PT(void *thread_data)
 
 static void Vaxpy_Pthreads(realtype a, N_Vector x, N_Vector y)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -3034,7 +3037,7 @@ static void Vaxpy_Pthreads(realtype a, N_Vector x, N_Vector y)
 
 static void *Vaxpy_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype a;
   realtype *xd, *yd;
   Pthreads_Data *my_data;
@@ -3080,7 +3083,7 @@ static void *Vaxpy_PT(void *thread_data)
 
 static void VScaleBy_Pthreads(realtype a, N_Vector x)
 {
-  long int      N;
+  sunindextype      N;
   int           i, nthreads;
   pthread_t     *threads;
   Pthreads_Data *thread_data;
@@ -3131,7 +3134,7 @@ static void VScaleBy_Pthreads(realtype a, N_Vector x)
 
 static void *VScaleBy_PT(void *thread_data)
 {
-  long int i, start, end;
+  sunindextype i, start, end;
   realtype a;
   realtype *xd;
   Pthreads_Data *my_data;
@@ -3158,10 +3161,10 @@ static void *VScaleBy_PT(void *thread_data)
  * Determine loop indices for a thread
  */
 
-static void N_VSplitLoop(int myid, int *nthreads, long int *N, 
-			 long int *start, long int *end)
+static void N_VSplitLoop(int myid, int *nthreads, sunindextype *N, 
+			 sunindextype *start, sunindextype *end)
 {
-  long int q, r; /* quotient and remainder */
+  sunindextype q, r; /* quotient and remainder */
 
   /* work per thread and leftover work */
   q = *N / *nthreads;
diff --git a/src/nvec_raja/CMakeLists.txt b/src/nvec_raja/CMakeLists.txt
new file mode 100644
index 0000000..7e4c57e
--- /dev/null
+++ b/src/nvec_raja/CMakeLists.txt
@@ -0,0 +1,83 @@
+# ---------------------------------------------------------------
+# Programmer:  Slaven Peles @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Lawrence Livermore National Laboratory in part under 
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the cuda NVECTOR library
+
+INSTALL(CODE "MESSAGE(\"\nInstall NVECTOR_RAJA\n\")")
+
+# Add variable nveccuda_SOURCES with the sources for the NVECRAJA lib
+SET(nvecraja_SOURCES 
+  nvector_raja.cu
+)
+
+# Tell compiler it is a CUDA source
+set_source_files_properties(${nvecraja_SOURCES} PROPERTIES CUDA_SOURCE_PROPERTY_FORMAT OBJ)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the NVECRAJA library
+SET(shared_SOURCES 
+  sundials_math.c
+)
+ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+
+# Add variable nveccuda_HEADERS with the exported NVECRAJA header files
+SET(nvecraja_HEADERS
+  nvector_raja.h 
+#  raja/Vector.hpp 
+#  raja/VectorKernels.cuh
+)
+ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecraja_HEADERS)
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the NVECRAJA library
+#  - Set the library name and make sure it is not deleted
+#  - Install the NVECRAJA library
+IF(BUILD_STATIC_LIBS)
+  CUDA_ADD_LIBRARY(sundials_nvecraja_static STATIC ${nvecraja_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_nvecraja_static
+    PROPERTIES OUTPUT_NAME sundials_nvecraja CLEAN_DIRECT_OUTPUT 1
+  )
+  INSTALL(TARGETS sundials_nvecraja_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the NVECRAJA library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the NVECRAJA library
+IF(BUILD_SHARED_LIBS)
+  CUDA_ADD_LIBRARY(sundials_nvecraja_shared SHARED ${nvecraja_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_nvecraja_shared
+    PROPERTIES OUTPUT_NAME sundials_nvecraja CLEAN_DIRECT_OUTPUT 1
+  )
+  SET_TARGET_PROPERTIES(sundials_nvecraja_shared
+    PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION}
+  )
+#  SET_TARGET_PROPERTIES(sundials_nvecraja_shared 
+#    PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE
+#  )
+  INSTALL(TARGETS sundials_nvecraja_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the NVECRAJA header files
+INSTALL(FILES ${nvecraja_HEADERS} DESTINATION include/nvector)
+INSTALL(DIRECTORY ${sundials_SOURCE_DIR}/include/nvector/raja DESTINATION include/nvector)
+
+
+MESSAGE(STATUS "Added NVECTOR_RAJA module")
diff --git a/src/nvec_raja/nvector_raja.cu b/src/nvec_raja/nvector_raja.cu
new file mode 100644
index 0000000..c56c491
--- /dev/null
+++ b/src/nvec_raja/nvector_raja.cu
@@ -0,0 +1,617 @@
+/* ----------------------------------------------------------------- 
+ * Programmer(s): Slaven Peles @ LLNL                               
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Lawrence Livermore National Laboratory in part under 
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nvector/raja/Vector.hpp>
+#include <RAJA/RAJA.hpp>
+
+#define ZERO   RCONST(0.0)
+#define HALF   RCONST(0.5)
+#define ONE    RCONST(1.0)
+#define ONEPT5 RCONST(1.5)
+
+extern "C" {
+
+using namespace sunrajavec;
+
+static constexpr sunindextype zeroIdx = 0;
+
+/* ----------------------------------------------------------------
+ * Returns vector type ID. Used to identify vector implementation
+ * from abstract N_Vector interface.
+ */
+N_Vector_ID N_VGetVectorID_Raja(N_Vector v)
+{
+  return SUNDIALS_NVEC_RAJA;
+}
+
+N_Vector N_VNewEmpty_Raja(sunindextype length)
+{
+  N_Vector v;
+  N_Vector_Ops ops;
+  N_VectorContent_Raja content;
+
+  /* Create vector */
+  v = NULL;
+  v = (N_Vector) malloc(sizeof *v);
+  if (v == NULL) return(NULL);
+  
+  /* Create vector operation structure */
+  ops = NULL;
+  ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops));
+  if (ops == NULL) { free(v); return(NULL); }
+
+  ops->nvgetvectorid     = N_VGetVectorID_Raja;
+  ops->nvclone           = N_VClone_Raja;
+  ops->nvcloneempty      = N_VCloneEmpty_Raja;
+  ops->nvdestroy         = N_VDestroy_Raja;
+  ops->nvspace           = N_VSpace_Raja;
+  ops->nvgetarraypointer = NULL; //N_VGetArrayPointer_Raja;
+  ops->nvsetarraypointer = NULL; //N_VSetArrayPointer_Raja;
+  ops->nvlinearsum       = N_VLinearSum_Raja;
+  ops->nvconst           = N_VConst_Raja;
+  ops->nvprod            = N_VProd_Raja;
+  ops->nvdiv             = N_VDiv_Raja;
+  ops->nvscale           = N_VScale_Raja;
+  ops->nvabs             = N_VAbs_Raja;
+  ops->nvinv             = N_VInv_Raja;
+  ops->nvaddconst        = N_VAddConst_Raja;
+  ops->nvdotprod         = N_VDotProd_Raja;
+  ops->nvmaxnorm         = N_VMaxNorm_Raja;
+  ops->nvwrmsnormmask    = N_VWrmsNormMask_Raja;
+  ops->nvwrmsnorm        = N_VWrmsNorm_Raja;
+  ops->nvmin             = N_VMin_Raja;
+  ops->nvwl2norm         = N_VWL2Norm_Raja;
+  ops->nvl1norm          = N_VL1Norm_Raja;
+  ops->nvcompare         = N_VCompare_Raja;
+  ops->nvinvtest         = N_VInvTest_Raja;
+  ops->nvconstrmask      = N_VConstrMask_Raja;
+  ops->nvminquotient     = N_VMinQuotient_Raja;
+
+  /* Create content */
+  content = NULL;
+
+  /* Attach content and ops */
+  v->content = content;
+  v->ops     = ops;
+
+  return(v);
+}
+
+    
+N_Vector N_VNew_Raja(sunindextype length)
+{
+  N_Vector v;
+
+  v = NULL;
+  v = N_VNewEmpty_Raja(length);
+  if (v == NULL) return(NULL);
+
+  v->content = new Vector<realtype, sunindextype>(length);
+
+  return(v);
+}
+
+
+N_Vector N_VMake_Raja(N_VectorContent_Raja c)
+{
+  N_Vector v;
+  Vector<realtype, sunindextype>* x = static_cast<Vector<realtype, sunindextype>*>(c);
+  sunindextype length = x->size();
+
+  v = NULL;
+  v = N_VNewEmpty_Raja(length);
+  if (v == NULL) return(NULL);
+
+  v->content = c;
+
+  return(v);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to create an array of new RAJA-based vectors.
+ */
+
+N_Vector *N_VCloneVectorArray_Raja(int count, N_Vector w)
+{
+  N_Vector *vs;
+  int j;
+
+  if (count <= 0) return(NULL);
+
+  vs = NULL;
+  vs = (N_Vector *) malloc(count * sizeof(N_Vector));
+  if(vs == NULL) return(NULL);
+
+  for (j = 0; j < count; j++) {
+    vs[j] = NULL;
+    vs[j] = N_VClone_Raja(w);
+    if (vs[j] == NULL) {
+      N_VDestroyVectorArray_Raja(vs, j-1);
+      return(NULL);
+    }
+  }
+
+  return(vs);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to create an array of new RAJA-based vectors with NULL data array.
+ */
+
+N_Vector *N_VCloneVectorArrayEmpty_Raja(int count, N_Vector w)
+{
+  N_Vector *vs;
+  int j;
+
+  if (count <= 0) return(NULL);
+
+  vs = NULL;
+  vs = (N_Vector *) malloc(count * sizeof(N_Vector));
+  if(vs == NULL) return(NULL);
+
+  for (j = 0; j < count; j++) {
+    vs[j] = NULL;
+    vs[j] = N_VCloneEmpty_Raja(w);
+    if (vs[j] == NULL) {
+      N_VDestroyVectorArray_Raja(vs, j-1);
+      return(NULL);
+    }
+  }
+
+  return(vs);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to free an array created with N_VCloneVectorArray_Raja
+ */
+
+void N_VDestroyVectorArray_Raja(N_Vector *vs, int count)
+{
+  int j;
+
+  for (j = 0; j < count; j++) N_VDestroy_Raja(vs[j]);
+
+  free(vs); vs = NULL;
+
+  return;
+}
+
+/* -----------------------------------------------------------------
+ * Function to return the length of the vector.
+ */
+sunindextype N_VGetLength_Raja(N_Vector v)
+{
+  Vector<realtype, sunindextype>* xd = static_cast<Vector<realtype, sunindextype>*>(v->content);
+  return xd->size();
+}
+
+/* ----------------------------------------------------------------------------
+ * Return pointer to the raw host data
+ */
+
+realtype *N_VGetHostArrayPointer_Raja(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  return (xv->host());
+}
+
+/* ----------------------------------------------------------------------------
+ * Return pointer to the raw device data
+ */
+
+realtype *N_VGetDeviceArrayPointer_Raja(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  return (xv->device());
+}
+
+/* ----------------------------------------------------------------------------
+ * Copy vector data to the device
+ */
+
+void N_VCopyToDevice_Raja(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  xv->copyToDev();
+}
+
+/* ----------------------------------------------------------------------------
+ * Copy vector data from the device to the host
+ */
+
+void N_VCopyFromDevice_Raja(N_Vector x)
+{
+  Vector<realtype, sunindextype>* xv = static_cast<Vector<realtype, sunindextype>*>(x->content);
+  xv->copyFromDev();
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to print the a serial vector to stdout
+ */
+
+void N_VPrint_Raja(N_Vector X)
+{
+  N_VPrintFile_Raja(X, stdout);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to print the a serial vector to outfile
+ */
+
+void N_VPrintFile_Raja(N_Vector X, FILE *outfile)
+{
+  const realtype *xd = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  sunindextype i;
+
+  for (i = 0; i < N; ++i) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+    fprintf(outfile, "%35.32Lg\n", xd[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+    fprintf(outfile, "%19.16g\n", xd[i]);
+#else
+    fprintf(outfile, "%11.8g\n", xd[i]);
+#endif
+  }
+  fprintf(outfile, "\n");
+
+  return;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of vector operations
+ * -----------------------------------------------------------------
+ */
+
+N_Vector N_VCloneEmpty_Raja(N_Vector w)
+{
+  N_Vector v;
+  N_Vector_Ops ops;
+
+  if (w == NULL) return(NULL);
+
+  /* Create vector */
+  v = NULL;
+  v = (N_Vector) malloc(sizeof *v);
+  if (v == NULL) return(NULL);
+
+  /* Create vector operation structure */
+  ops = NULL;
+  ops = (N_Vector_Ops) malloc(sizeof(struct _generic_N_Vector_Ops));
+  if (ops == NULL) { free(v); return(NULL); }
+
+  ops->nvgetvectorid     = w->ops->nvgetvectorid;
+  ops->nvclone           = w->ops->nvclone;
+  ops->nvcloneempty      = w->ops->nvcloneempty;
+  ops->nvdestroy         = w->ops->nvdestroy;
+  ops->nvspace           = w->ops->nvspace;
+  ops->nvgetarraypointer = w->ops->nvgetarraypointer;
+  ops->nvsetarraypointer = w->ops->nvsetarraypointer;
+  ops->nvlinearsum       = w->ops->nvlinearsum;
+  ops->nvconst           = w->ops->nvconst;
+  ops->nvprod            = w->ops->nvprod;
+  ops->nvdiv             = w->ops->nvdiv;
+  ops->nvscale           = w->ops->nvscale;
+  ops->nvabs             = w->ops->nvabs;
+  ops->nvinv             = w->ops->nvinv;
+  ops->nvaddconst        = w->ops->nvaddconst;
+  ops->nvdotprod         = w->ops->nvdotprod;
+  ops->nvmaxnorm         = w->ops->nvmaxnorm;
+  ops->nvwrmsnormmask    = w->ops->nvwrmsnormmask;
+  ops->nvwrmsnorm        = w->ops->nvwrmsnorm;
+  ops->nvmin             = w->ops->nvmin;
+  ops->nvwl2norm         = w->ops->nvwl2norm;
+  ops->nvl1norm          = w->ops->nvl1norm;
+  ops->nvcompare         = w->ops->nvcompare;
+  ops->nvinvtest         = w->ops->nvinvtest;
+  ops->nvconstrmask      = w->ops->nvconstrmask;
+  ops->nvminquotient     = w->ops->nvminquotient;
+
+  /* Create content */
+  v->content = NULL;
+  v->ops  = ops;
+
+  return(v);
+}
+
+N_Vector N_VClone_Raja(N_Vector w)
+{
+  N_Vector v;
+  Vector<realtype, sunindextype>* wdat = static_cast<Vector<realtype, sunindextype>*>(w->content);
+  Vector<realtype, sunindextype>* vdat = new Vector<realtype, sunindextype>(*wdat);
+  v = NULL;
+  v = N_VCloneEmpty_Raja(w);
+  if (v == NULL) return(NULL);
+
+  v->content = vdat;
+
+  return(v);
+}
+
+
+void N_VDestroy_Raja(N_Vector v)
+{
+  Vector<realtype, sunindextype>* x = static_cast<Vector<realtype, sunindextype>*>(v->content);
+  if (x != NULL) {
+    delete x;
+    v->content = NULL;
+  }
+
+  free(v->ops); v->ops = NULL;
+  free(v); v = NULL;
+
+  return;
+}
+
+void N_VSpace_Raja(N_Vector X, sunindextype *lrw, sunindextype *liw)
+{
+    *lrw = getSize<realtype, sunindextype>(X);
+    *liw = 1;
+}
+
+void N_VConst_Raja(realtype c, N_Vector Z)
+{
+  const sunindextype N = getSize<realtype, sunindextype>(Z);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = c;
+  });
+}
+
+void N_VLinearSum_Raja(realtype a, N_Vector X, realtype b, N_Vector Y, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const realtype *ydata = getDevData<realtype, sunindextype>(Y);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = a*xdata[i] + b*ydata[i];
+  });
+}
+
+void N_VProd_Raja(N_Vector X, N_Vector Y, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const realtype *ydata = getDevData<realtype, sunindextype>(Y);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = xdata[i] * ydata[i];
+  });
+}
+
+void N_VDiv_Raja(N_Vector X, N_Vector Y, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const realtype *ydata = getDevData<realtype, sunindextype>(Y);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = xdata[i] / ydata[i];
+  });
+}
+
+void N_VScale_Raja(realtype c, N_Vector X, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = c * xdata[i];
+  });
+}
+
+void N_VAbs_Raja(N_Vector X, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = abs(xdata[i]);
+  });
+}
+
+void N_VInv_Raja(N_Vector X, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = RCONST(1.0) / xdata[i];
+  });
+}
+
+void N_VAddConst_Raja(N_Vector X, realtype b, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = xdata[i] + b;
+  });
+}
+
+realtype N_VDotProd_Raja(N_Vector X, N_Vector Y)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const realtype *ydata = getDevData<realtype, sunindextype>(Y);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+
+  RAJA::ReduceSum<RAJA::cuda_reduce<128>, realtype> gpu_result(0.0);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    gpu_result += xdata[i] * ydata[i] ;
+  });
+
+  return static_cast<realtype>(gpu_result);
+}
+
+realtype N_VMaxNorm_Raja(N_Vector X)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+
+  RAJA::ReduceMax<RAJA::cuda_reduce<128>, realtype> gpu_result(0.0);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    gpu_result.max(abs(xdata[i]));
+  });
+
+  return static_cast<realtype>(gpu_result);
+}
+
+realtype N_VWrmsNorm_Raja(N_Vector X, N_Vector W)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const realtype *wdata = getDevData<realtype, sunindextype>(W);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+
+  RAJA::ReduceSum<RAJA::cuda_reduce<128>, realtype> gpu_result(0.0);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    gpu_result += (xdata[i] * wdata[i] * xdata[i] * wdata[i]);
+  });
+
+  return std::sqrt(static_cast<realtype>(gpu_result)/N);
+}
+
+realtype N_VWrmsNormMask_Raja(N_Vector X, N_Vector W, N_Vector ID)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const realtype *wdata = getDevData<realtype, sunindextype>(W);
+  const realtype *iddata = getDevData<realtype, sunindextype>(ID);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+
+  RAJA::ReduceSum<RAJA::cuda_reduce<128>, realtype> gpu_result(0.0);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    gpu_result += (xdata[i] * wdata[i] * xdata[i] * wdata[i] * iddata[i]);
+  });
+
+  return std::sqrt(static_cast<realtype>(gpu_result)/N);
+}
+
+realtype N_VMin_Raja(N_Vector X)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+
+  RAJA::ReduceMin<RAJA::cuda_reduce<128>, realtype> gpu_result(std::numeric_limits<realtype>::max());
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    gpu_result.min(xdata[i]);
+  });
+
+  return static_cast<realtype>(gpu_result);
+}
+
+realtype N_VWL2Norm_Raja(N_Vector X, N_Vector W)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const realtype *wdata = getDevData<realtype, sunindextype>(W);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+
+  RAJA::ReduceSum<RAJA::cuda_reduce<128>, realtype> gpu_result(0.0);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    gpu_result += (xdata[i] * wdata[i] * xdata[i] * wdata[i]);
+  });
+
+  return std::sqrt(static_cast<realtype>(gpu_result));
+}
+
+realtype N_VL1Norm_Raja(N_Vector X)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+
+  RAJA::ReduceSum<RAJA::cuda_reduce<128>, realtype> gpu_result(0.0);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    gpu_result += (abs(xdata[i]));
+  });
+
+  return static_cast<realtype>(gpu_result);
+}
+
+void N_VCompare_Raja(realtype c, N_Vector X, N_Vector Z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(X);
+  const sunindextype N = getSize<realtype, sunindextype>(X);
+  realtype *zdata = getDevData<realtype, sunindextype>(Z);
+
+  RAJA::forall<RAJA::cuda_exec<256> >(zeroIdx, N, [=] __device__(sunindextype i) {
+     zdata[i] = abs(xdata[i]) >= c ? ONE : ZERO;
+  });
+}
+
+booleantype N_VInvTest_Raja(N_Vector x, N_Vector z)
+{
+  const realtype *xdata = getDevData<realtype, sunindextype>(x);
+  const sunindextype N = getSize<realtype, sunindextype>(x);
+  realtype *zdata = getDevData<realtype, sunindextype>(z);
+
+  RAJA::ReduceSum<RAJA::cuda_reduce<128>, realtype> gpu_result(ZERO);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    if (xdata[i] == ZERO) {
+      gpu_result += ONE;
+    } else {
+      zdata[i] = ONE/xdata[i];
+    }
+  });
+
+  return (static_cast<realtype>(gpu_result) < HALF);
+}
+
+booleantype N_VConstrMask_Raja(N_Vector c, N_Vector x, N_Vector m)
+{
+  const realtype *cdata = getDevData<realtype, sunindextype>(c);
+  const realtype *xdata = getDevData<realtype, sunindextype>(x);
+  const sunindextype N = getSize<realtype, sunindextype>(x);
+  realtype *mdata = getDevData<realtype, sunindextype>(m);
+
+  RAJA::ReduceSum<RAJA::cuda_reduce<128>, realtype> gpu_result(ZERO);
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    bool test = (abs(cdata[i]) > ONEPT5 && cdata[i]*xdata[i] <= ZERO) ||
+                (abs(cdata[i]) > HALF   && cdata[i]*xdata[i] <  ZERO);
+    mdata[i] = test ? ONE : ZERO;
+    gpu_result += mdata[i];
+  });
+
+  return (static_cast<realtype>(gpu_result) < HALF);
+}
+
+realtype N_VMinQuotient_Raja(N_Vector num, N_Vector denom)
+{
+  const realtype *ndata = getDevData<realtype, sunindextype>(num);
+  const realtype *ddata = getDevData<realtype, sunindextype>(denom);
+  const sunindextype N = getSize<realtype, sunindextype>(num);
+
+  RAJA::ReduceMin<RAJA::cuda_reduce<128>, realtype> gpu_result(std::numeric_limits<realtype>::max());
+  RAJA::forall<RAJA::cuda_exec<128> >(zeroIdx, N, [=] __device__(sunindextype i) {
+    if (ddata[i] != ZERO)
+      gpu_result.min(ndata[i]/ddata[i]);
+  });
+
+  return (static_cast<realtype>(gpu_result));
+}
+
+
+} // extern "C"
diff --git a/src/nvec_ser/CMakeLists.txt b/src/nvec_ser/CMakeLists.txt
index de9fb12..a41974f 100644
--- a/src/nvec_ser/CMakeLists.txt
+++ b/src/nvec_ser/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4075 $
-# $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -23,12 +20,14 @@ SET(nvecserial_SOURCES nvector_serial.c)
 
 # Add variable shared_SOURCES with the common SUNDIALS sources which will
 # also be included in the NVECSERIAL library
-SET(shared_SOURCES sundials_math.c)
-ADD_PREFIX(${sundials_SOURCE_DIR}/src/sundials/ shared_SOURCES)
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
 
 # Add variable nvecserial_HEADERS with the exported NVECSERIAL header files
-SET(nvecserial_HEADERS nvector_serial.h)
-ADD_PREFIX(${sundials_SOURCE_DIR}/include/nvector/ nvecserial_HEADERS)
+SET(nvecserial_HEADERS
+  ${sundials_SOURCE_DIR}/include/nvector/nvector_serial.h
+  )
 
 # Add source directory to include directories
 INCLUDE_DIRECTORIES(.)
@@ -54,6 +53,11 @@ ENDIF(BUILD_STATIC_LIBS)
 #  - Install the NVECSERIAL library
 IF(BUILD_SHARED_LIBS)
   ADD_LIBRARY(sundials_nvecserial_shared SHARED ${nvecserial_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_nvecserial_shared m)
+  ENDIF()
+
   SET_TARGET_PROPERTIES(sundials_nvecserial_shared
     PROPERTIES OUTPUT_NAME sundials_nvecserial CLEAN_DIRECT_OUTPUT 1)
   SET_TARGET_PROPERTIES(sundials_nvecserial_shared
@@ -67,20 +71,27 @@ INSTALL(FILES ${nvecserial_HEADERS} DESTINATION include/nvector)
 # If FCMIX is enabled, build and install the FNVECSERIAL library
 IF(FCMIX_ENABLE AND F77_FOUND)
   SET(fnvecserial_SOURCES fnvector_serial.c)
+
   IF(BUILD_STATIC_LIBS)
     ADD_LIBRARY(sundials_fnvecserial_static STATIC ${fnvecserial_SOURCES})
     SET_TARGET_PROPERTIES(sundials_fnvecserial_static
       PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1)
     INSTALL(TARGETS sundials_fnvecserial_static DESTINATION lib)
   ENDIF(BUILD_STATIC_LIBS)
+
   IF(BUILD_SHARED_LIBS)
     ADD_LIBRARY(sundials_fnvecserial_shared ${fnvecserial_SOURCES})
+
+    # fnvecserial depends on nvecserial
+    TARGET_LINK_LIBRARIES(sundials_fnvecserial_shared sundials_nvecserial_shared)
+
     SET_TARGET_PROPERTIES(sundials_fnvecserial_shared
       PROPERTIES OUTPUT_NAME sundials_fnvecserial CLEAN_DIRECT_OUTPUT 1)
     SET_TARGET_PROPERTIES(sundials_fnvecserial_shared 
       PROPERTIES VERSION ${nveclib_VERSION} SOVERSION ${nveclib_SOVERSION})
     INSTALL(TARGETS sundials_fnvecserial_shared DESTINATION lib)
   ENDIF(BUILD_SHARED_LIBS)
+
 ENDIF(FCMIX_ENABLE AND F77_FOUND)
 
 #
diff --git a/src/nvec_ser/README b/src/nvec_ser/README
index 433ccfa..84b5c92 100644
--- a/src/nvec_ser/README
+++ b/src/nvec_ser/README
@@ -1,7 +1,7 @@
                      NVECTOR_SERIAL
                  released as part of SUNDIALS
     SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
-                   Release 2.7.0, September 2016
+                   Release 3.1.0, November 2017
 
 
 Serial implementation of the NVECTOR module for SUNDIALS. 
@@ -37,6 +37,9 @@ For complete installation instructions see any of the user guides.
 
 D. Releases
 -----------
+
+v. 3.1.0 - Nov. 2017
+v. 3.0.0 - Sep. 2017
 v. 2.7.0 - Sep. 2016
 v. 2.6.2 - Aug. 2015
 v. 2.6.1 - Mar. 2015
diff --git a/src/nvec_ser/fnvector_serial.c b/src/nvec_ser/fnvector_serial.c
index bc6d949..5a517ed 100644
--- a/src/nvec_ser/fnvector_serial.c
+++ b/src/nvec_ser/fnvector_serial.c
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4075 $
- * $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -155,5 +152,3 @@ void FNV_INITS_S(int *code, int *Ns, int *ier)
     *ier = -1;
   }
 }
-
-
diff --git a/src/nvec_ser/fnvector_serial.h b/src/nvec_ser/fnvector_serial.h
index 98e883e..e21435d 100644
--- a/src/nvec_ser/fnvector_serial.h
+++ b/src/nvec_ser/fnvector_serial.h
@@ -1,14 +1,11 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4378 $
- * $Date: 2015-02-19 10:55:14 -0800 (Thu, 19 Feb 2015) $
- * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
  * Copyright (c) 2014, Lawrence Livermore National Security
- * This work was performed under the auspices of the U.S. Department 
- * of Energy by Lawrence Livermore National Laboratory in part under 
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
  * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
  * Produced at the Lawrence Livermore National Laboratory.
  * All rights reserved.
@@ -71,8 +68,8 @@ extern N_Vector F2C_KINSOL_vec;
 
 extern N_Vector F2C_ARKODE_vec;
 
-/* 
- * Prototypes of exported functions 
+/*
+ * Prototypes of exported functions
  *
  * FNV_INITS    - initializes serial vector operations for main problem
  * FNV_INITS_Q  - initializes serial vector operations for quadratures
diff --git a/src/nvec_ser/nvector_serial.c b/src/nvec_ser/nvector_serial.c
index 8992480..1e8cdd3 100644
--- a/src/nvec_ser/nvector_serial.c
+++ b/src/nvec_ser/nvector_serial.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4867 $
- * $Date: 2016-08-19 10:05:14 -0700 (Fri, 19 Aug 2016) $
- * ----------------------------------------------------------------- 
+/* ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
  *                and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -18,8 +14,7 @@
  * -----------------------------------------------------------------
  * This is the implementation file for a serial implementation
  * of the NVECTOR package.
- * -----------------------------------------------------------------
- */
+ * -----------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -73,7 +68,7 @@ N_Vector_ID N_VGetVectorID_Serial(N_Vector v)
  * Function to create a new empty serial vector 
  */
 
-N_Vector N_VNewEmpty_Serial(long int length)
+N_Vector N_VNewEmpty_Serial(sunindextype length)
 {
   N_Vector v;
   N_Vector_Ops ops;
@@ -122,7 +117,7 @@ N_Vector N_VNewEmpty_Serial(long int length)
   if (content == NULL) { free(ops); free(v); return(NULL); }
 
   content->length   = length;
-  content->own_data = FALSE;
+  content->own_data = SUNFALSE;
   content->data     = NULL;
 
   /* Attach content and ops */
@@ -136,7 +131,7 @@ N_Vector N_VNewEmpty_Serial(long int length)
  * Function to create a new serial vector 
  */
 
-N_Vector N_VNew_Serial(long int length)
+N_Vector N_VNew_Serial(sunindextype length)
 {
   N_Vector v;
   realtype *data;
@@ -154,7 +149,7 @@ N_Vector N_VNew_Serial(long int length)
     if(data == NULL) { N_VDestroy_Serial(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_S(v) = TRUE;
+    NV_OWN_DATA_S(v) = SUNTRUE;
     NV_DATA_S(v)     = data;
 
   }
@@ -166,7 +161,7 @@ N_Vector N_VNew_Serial(long int length)
  * Function to create a serial N_Vector with user data component 
  */
 
-N_Vector N_VMake_Serial(long int length, realtype *v_data)
+N_Vector N_VMake_Serial(sunindextype length, realtype *v_data)
 {
   N_Vector v;
 
@@ -176,7 +171,7 @@ N_Vector N_VMake_Serial(long int length, realtype *v_data)
 
   if (length > 0) {
     /* Attach data */
-    NV_OWN_DATA_S(v) = FALSE;
+    NV_OWN_DATA_S(v) = SUNFALSE;
     NV_DATA_S(v)     = v_data;
   }
 
@@ -255,19 +250,27 @@ void N_VDestroyVectorArray_Serial(N_Vector *vs, int count)
 /* ----------------------------------------------------------------------------
  * Function to return number of vector elements
  */
-long int N_VGetLength_Serial(N_Vector v)
+sunindextype N_VGetLength_Serial(N_Vector v)
 {
   return NV_LENGTH_S(v);
 }
 
- 
 /* ----------------------------------------------------------------------------
- * Function to print the a serial vector 
+ * Function to print the a serial vector to stdout
  */
  
 void N_VPrint_Serial(N_Vector x)
 {
-  long int i, N;
+  N_VPrintFile_Serial(x, stdout);
+}
+ 
+/* ----------------------------------------------------------------------------
+ * Function to print the a serial vector to outfile
+ */
+ 
+void N_VPrintFile_Serial(N_Vector x, FILE* outfile)
+{
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
@@ -277,14 +280,14 @@ void N_VPrint_Serial(N_Vector x)
 
   for (i = 0; i < N; i++) {
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-    printf("%35.32Lg\n", xd[i]);
+    fprintf(outfile, "%35.32Lg\n", xd[i]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-    printf("%19.16g\n", xd[i]);
+    fprintf(outfile, "%19.16g\n", xd[i]);
 #else
-    printf("%11.8g\n", xd[i]);
+    fprintf(outfile, "%11.8g\n", xd[i]);
 #endif
   }
-  printf("\n");
+  fprintf(outfile, "\n");
 
   return;
 }
@@ -346,7 +349,7 @@ N_Vector N_VCloneEmpty_Serial(N_Vector w)
   if (content == NULL) { free(ops); free(v); return(NULL); }
 
   content->length   = NV_LENGTH_S(w);
-  content->own_data = FALSE;
+  content->own_data = SUNFALSE;
   content->data     = NULL;
 
   /* Attach content and ops */
@@ -360,7 +363,7 @@ N_Vector N_VClone_Serial(N_Vector w)
 {
   N_Vector v;
   realtype *data;
-  long int length;
+  sunindextype length;
 
   v = NULL;
   v = N_VCloneEmpty_Serial(w);
@@ -377,7 +380,7 @@ N_Vector N_VClone_Serial(N_Vector w)
     if(data == NULL) { N_VDestroy_Serial(v); return(NULL); }
 
     /* Attach data */
-    NV_OWN_DATA_S(v) = TRUE;
+    NV_OWN_DATA_S(v) = SUNTRUE;
     NV_DATA_S(v)     = data;
 
   }
@@ -387,7 +390,7 @@ N_Vector N_VClone_Serial(N_Vector w)
 
 void N_VDestroy_Serial(N_Vector v)
 {
-  if (NV_OWN_DATA_S(v) == TRUE) {
+  if (NV_OWN_DATA_S(v) == SUNTRUE) {
     free(NV_DATA_S(v));
     NV_DATA_S(v) = NULL;
   }
@@ -398,7 +401,7 @@ void N_VDestroy_Serial(N_Vector v)
   return;
 }
 
-void N_VSpace_Serial(N_Vector v, long int *lrw, long int *liw)
+void N_VSpace_Serial(N_Vector v, sunindextype *lrw, sunindextype *liw)
 {
   *lrw = NV_LENGTH_S(v);
   *liw = 1;
@@ -420,7 +423,7 @@ void N_VSetArrayPointer_Serial(realtype *v_data, N_Vector v)
 
 void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype c, *xd, *yd, *zd;
   N_Vector v1, v2;
   booleantype test;
@@ -507,7 +510,7 @@ void N_VLinearSum_Serial(realtype a, N_Vector x, realtype b, N_Vector y, N_Vecto
 
 void N_VConst_Serial(realtype c, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *zd;
 
   zd = NULL;
@@ -522,7 +525,7 @@ void N_VConst_Serial(realtype c, N_Vector z)
 
 void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -540,7 +543,7 @@ void N_VProd_Serial(N_Vector x, N_Vector y, N_Vector z)
 
 void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -558,7 +561,7 @@ void N_VDiv_Serial(N_Vector x, N_Vector y, N_Vector z)
 
 void N_VScale_Serial(realtype c, N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -585,7 +588,7 @@ void N_VScale_Serial(realtype c, N_Vector x, N_Vector z)
 
 void N_VAbs_Serial(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -602,7 +605,7 @@ void N_VAbs_Serial(N_Vector x, N_Vector z)
 
 void N_VInv_Serial(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -619,7 +622,7 @@ void N_VInv_Serial(N_Vector x, N_Vector z)
 
 void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -636,7 +639,7 @@ void N_VAddConst_Serial(N_Vector x, realtype b, N_Vector z)
 
 realtype N_VDotProd_Serial(N_Vector x, N_Vector y)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd, *yd;
 
   sum = ZERO;
@@ -654,7 +657,7 @@ realtype N_VDotProd_Serial(N_Vector x, N_Vector y)
 
 realtype N_VMaxNorm_Serial(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype max, *xd;
 
   max = ZERO;
@@ -672,7 +675,7 @@ realtype N_VMaxNorm_Serial(N_Vector x)
 
 realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, prodi, *xd, *wd;
 
   sum = ZERO;
@@ -692,7 +695,7 @@ realtype N_VWrmsNorm_Serial(N_Vector x, N_Vector w)
 
 realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, prodi, *xd, *wd, *idd;
 
   sum = ZERO;
@@ -715,7 +718,7 @@ realtype N_VWrmsNormMask_Serial(N_Vector x, N_Vector w, N_Vector id)
 
 realtype N_VMin_Serial(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype min, *xd;
 
   xd = NULL;
@@ -734,7 +737,7 @@ realtype N_VMin_Serial(N_Vector x)
 
 realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, prodi, *xd, *wd;
 
   sum = ZERO;
@@ -754,7 +757,7 @@ realtype N_VWL2Norm_Serial(N_Vector x, N_Vector w)
 
 realtype N_VL1Norm_Serial(N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype sum, *xd;
 
   sum = ZERO;
@@ -771,7 +774,7 @@ realtype N_VL1Norm_Serial(N_Vector x)
 
 void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -789,7 +792,7 @@ void N_VCompare_Serial(realtype c, N_Vector x, N_Vector z)
 
 booleantype N_VInvTest_Serial(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
   booleantype no_zero_found;
 
@@ -799,10 +802,10 @@ booleantype N_VInvTest_Serial(N_Vector x, N_Vector z)
   xd = NV_DATA_S(x);
   zd = NV_DATA_S(z);
 
-  no_zero_found = TRUE;
+  no_zero_found = SUNTRUE;
   for (i = 0; i < N; i++) {
     if (xd[i] == ZERO) 
-      no_zero_found = FALSE;
+      no_zero_found = SUNFALSE;
     else
       zd[i] = ONE/xd[i];
   }
@@ -812,7 +815,7 @@ booleantype N_VInvTest_Serial(N_Vector x, N_Vector z)
 
 booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m)
 {
-  long int i, N;
+  sunindextype i, N;
   booleantype test;
   realtype *cd, *xd, *md;
 
@@ -823,17 +826,17 @@ booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m)
   cd = NV_DATA_S(c);
   md = NV_DATA_S(m);
 
-  test = TRUE;
+  test = SUNTRUE;
 
   for (i = 0; i < N; i++) {
     md[i] = ZERO;
     if (cd[i] == ZERO) continue;
     if (cd[i] > ONEPT5 || cd[i] < -ONEPT5) {
-      if ( xd[i]*cd[i] <= ZERO) { test = FALSE; md[i] = ONE; }
+      if ( xd[i]*cd[i] <= ZERO) { test = SUNFALSE; md[i] = ONE; }
       continue;
     }
     if ( cd[i] > HALF || cd[i] < -HALF) {
-      if (xd[i]*cd[i] < ZERO ) { test = FALSE; md[i] = ONE; }
+      if (xd[i]*cd[i] < ZERO ) { test = SUNFALSE; md[i] = ONE; }
     }
   }
 
@@ -843,7 +846,7 @@ booleantype N_VConstrMask_Serial(N_Vector c, N_Vector x, N_Vector m)
 realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom)
 {
   booleantype notEvenOnce;
-  long int i, N;
+  sunindextype i, N;
   realtype *nd, *dd, min;
 
   nd = dd = NULL;
@@ -852,7 +855,7 @@ realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom)
   nd = NV_DATA_S(num);
   dd = NV_DATA_S(denom);
 
-  notEvenOnce = TRUE;
+  notEvenOnce = SUNTRUE;
   min = BIG_REAL;
 
   for (i = 0; i < N; i++) {
@@ -861,7 +864,7 @@ realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom)
       if (!notEvenOnce) min = SUNMIN(min, nd[i]/dd[i]);
       else {
 	min = nd[i]/dd[i];
-        notEvenOnce = FALSE;
+        notEvenOnce = SUNFALSE;
       }
     }
   }
@@ -877,7 +880,7 @@ realtype N_VMinQuotient_Serial(N_Vector num, N_Vector denom)
 
 static void VCopy_Serial(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -894,7 +897,7 @@ static void VCopy_Serial(N_Vector x, N_Vector z)
 
 static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -912,7 +915,7 @@ static void VSum_Serial(N_Vector x, N_Vector y, N_Vector z)
 
 static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -930,7 +933,7 @@ static void VDiff_Serial(N_Vector x, N_Vector y, N_Vector z)
 
 static void VNeg_Serial(N_Vector x, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *zd;
 
   xd = zd = NULL;
@@ -947,7 +950,7 @@ static void VNeg_Serial(N_Vector x, N_Vector z)
 
 static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -965,7 +968,7 @@ static void VScaleSum_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -983,7 +986,7 @@ static void VScaleDiff_Serial(realtype c, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1001,7 +1004,7 @@ static void VLin1_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd, *zd;
 
   xd = yd = zd = NULL;
@@ -1019,7 +1022,7 @@ static void VLin2_Serial(realtype a, N_Vector x, N_Vector y, N_Vector z)
 
 static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd, *yd;
 
   xd = yd = NULL;
@@ -1048,7 +1051,7 @@ static void Vaxpy_Serial(realtype a, N_Vector x, N_Vector y)
 
 static void VScaleBy_Serial(realtype a, N_Vector x)
 {
-  long int i, N;
+  sunindextype i, N;
   realtype *xd;
 
   xd = NULL;
diff --git a/src/sundials/CMakeLists.txt b/src/sundials/CMakeLists.txt
index b01b65f..07d340d 100644
--- a/src/sundials/CMakeLists.txt
+++ b/src/sundials/CMakeLists.txt
@@ -1,7 +1,4 @@
 # ---------------------------------------------------------------
-# $Revision: 4075 $
-# $Date: 2014-04-24 10:46:58 -0700 (Thu, 24 Apr 2014) $
-# ---------------------------------------------------------------
 # Programmer:  Radu Serban @ LLNL
 # ---------------------------------------------------------------
 # LLNS Copyright Start
@@ -26,10 +23,12 @@ SET(sundials_HEADERS
   sundials_band.h
   sundials_dense.h
   sundials_direct.h
+  sundials_fnvector.h
   sundials_iterative.h
+  sundials_linearsolver.h
   sundials_math.h
+  sundials_matrix.h
   sundials_nvector.h
-  sundials_fnvector.h
   sundials_pcg.h
   sundials_sparse.h
   sundials_spbcgs.h
@@ -37,8 +36,14 @@ SET(sundials_HEADERS
   sundials_spgmr.h
   sundials_sptfqmr.h
   sundials_types.h
+  sundials_version.h
   )
 
+# append header file with sundials MPI type macros if using MPI
+IF(MPIC_FOUND)
+  LIST(APPEND sundials_HEADERS sundials_mpi_types.h)
+ENDIF()
+
 # Add prefix with complete path to the SUNDIALS header files
 ADD_PREFIX(${sundials_SOURCE_DIR}/include/sundials/ sundials_HEADERS)
 
diff --git a/src/sundials/README b/src/sundials/README
index 6fcb40a..d44bffc 100644
--- a/src/sundials/README
+++ b/src/sundials/README
@@ -1,6 +1,6 @@
                           SUNDIALS 
                         Shared Module
-                 Release 2.7.0, Sep 2016
+                 Release 3.0.0, Sep 2017
 
 
 The family of solvers referred to as SUNDIALS consists of solvers 
@@ -11,6 +11,8 @@ capabilities), and KINSOL (for nonlinear algebraic systems).
 The various solvers of this family share many subordinate modules contained
 in this module:
 - generic NVECTOR module
+- generic SUNMatrix module
+- generic SUNLinearSolver module
 - generic linear solver modules (band, dense, lapack, sparse, pcg, spfgmr, spgmr, spbcg, sptfqmr)
 - definitions of SUNDIALS types (realtype, booleantype)
 - common math functions (RpowerI, SUNRpowerR, SUNRsqrt, SUNRabs,...)
@@ -56,6 +58,7 @@ C. References
 D. Releases
 -----------
 
+v. 3.0.0 - Sep. 2017
 v. 2.7.0 - Sep. 2016
 v. 2.6.2 - Aug. 2015
 v. 2.6.1 - Mar. 2015
diff --git a/src/sundials/sundials_band.c b/src/sundials/sundials_band.c
index 7349eb7..c359eda 100644
--- a/src/sundials/sundials_band.c
+++ b/src/sundials/sundials_band.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4272 $
- * $Date: 2014-12-02 11:19:41 -0800 (Tue, 02 Dec 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Alan C. Hindmarsh and Radu Serban @ LLNL
  * -----------------------------------------------------------------
@@ -37,17 +37,17 @@
  * -----------------------------------------------------
  */
 
-long int BandGBTRF(DlsMat A, long int *p)
+sunindextype BandGBTRF(DlsMat A, sunindextype *p)
 {
   return(bandGBTRF(A->cols, A->M, A->mu, A->ml, A->s_mu, p));
 }
 
-void BandGBTRS(DlsMat A, long int *p, realtype *b)
+void BandGBTRS(DlsMat A, sunindextype *p, realtype *b)
 {
   bandGBTRS(A->cols, A->M, A->s_mu, A->ml, p, b);
 }
 
-void BandCopy(DlsMat A, DlsMat B, long int copymu, long int copyml)
+void BandCopy(DlsMat A, DlsMat B, sunindextype copymu, sunindextype copyml)
 {
   bandCopy(A->cols, B->cols, A->M, A->s_mu, B->s_mu, copymu, copyml);
 }
@@ -68,10 +68,10 @@ void BandMatvec(DlsMat A, realtype *x, realtype *y)
  * -----------------------------------------------------
  */
 
-long int bandGBTRF(realtype **a, long int n, long int mu, long int ml, long int smu, long int *p)
+sunindextype bandGBTRF(realtype **a, sunindextype n, sunindextype mu, sunindextype ml, sunindextype smu, sunindextype *p)
 {
-  long int c, r, num_rows;
-  long int i, j, k, l, storage_l, storage_k, last_col_k, last_row_k;
+  sunindextype c, r, num_rows;
+  sunindextype i, j, k, l, storage_l, storage_k, last_col_k, last_row_k;
   realtype *a_c, *col_k, *diag_k, *sub_diag_k, *col_j, *kptr, *jptr;
   realtype max, temp, mult, a_kj;
   booleantype swap;
@@ -174,9 +174,9 @@ long int bandGBTRF(realtype **a, long int n, long int mu, long int ml, long int
   return(0);
 }
 
-void bandGBTRS(realtype **a, long int n, long int smu, long int ml, long int *p, realtype *b)
+void bandGBTRS(realtype **a, sunindextype n, sunindextype smu, sunindextype ml, sunindextype *p, realtype *b)
 {
-  long int k, l, i, first_row_k, last_row_k;
+  sunindextype k, l, i, first_row_k, last_row_k;
   realtype mult, *diag_k;
   
   /* Solve Ly = Pb, store solution y in b */
@@ -206,10 +206,10 @@ void bandGBTRS(realtype **a, long int n, long int smu, long int ml, long int *p,
   }
 }
 
-void bandCopy(realtype **a, realtype **b, long int n, long int a_smu, long int b_smu, 
-              long int copymu, long int copyml)
+void bandCopy(realtype **a, realtype **b, sunindextype n, sunindextype a_smu, sunindextype b_smu, 
+              sunindextype copymu, sunindextype copyml)
 {
-  long int i, j, copySize;
+  sunindextype i, j, copySize;
   realtype *a_col_j, *b_col_j;
 
   copySize = copymu + copyml + 1;
@@ -222,9 +222,9 @@ void bandCopy(realtype **a, realtype **b, long int n, long int a_smu, long int b
   }
 }
 
-void bandScale(realtype c, realtype **a, long int n, long int mu, long int ml, long int smu)
+void bandScale(realtype c, realtype **a, sunindextype n, sunindextype mu, sunindextype ml, sunindextype smu)
 {
-  long int i, j, colSize;
+  sunindextype i, j, colSize;
   realtype *col_j;
 
   colSize = mu + ml + 1;
@@ -236,18 +236,18 @@ void bandScale(realtype c, realtype **a, long int n, long int mu, long int ml, l
   }
 }
 
-void bandAddIdentity(realtype **a, long int n, long int smu)
+void bandAddIdentity(realtype **a, sunindextype n, sunindextype smu)
 {
-  long int j;
+  sunindextype j;
  
   for(j=0; j < n; j++)
     a[j][smu] += ONE;
 }
 
-void bandMatvec(realtype **a, realtype *x, realtype *y, long int n, 
-		long int mu, long int ml, long int smu)
+void bandMatvec(realtype **a, realtype *x, realtype *y, sunindextype n, 
+		sunindextype mu, sunindextype ml, sunindextype smu)
 {
-  long int i, j, is, ie;
+  sunindextype i, j, is, ie;
   realtype *col_j;
 
   for (i=0; i<n; i++)
diff --git a/src/sundials/sundials_dense.c b/src/sundials/sundials_dense.c
index 1a15a46..25e07ec 100644
--- a/src/sundials/sundials_dense.c
+++ b/src/sundials/sundials_dense.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4272 $
- * $Date: 2014-12-02 11:19:41 -0800 (Tue, 02 Dec 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
@@ -37,17 +37,17 @@
  * -----------------------------------------------------
  */
 
-long int DenseGETRF(DlsMat A, long int *p)
+sunindextype DenseGETRF(DlsMat A, sunindextype *p)
 {
   return(denseGETRF(A->cols, A->M, A->N, p));
 }
 
-void DenseGETRS(DlsMat A, long int *p, realtype *b)
+void DenseGETRS(DlsMat A, sunindextype *p, realtype *b)
 {
   denseGETRS(A->cols, A->N, p, b);
 }
 
-long int DensePOTRF(DlsMat A)
+sunindextype DensePOTRF(DlsMat A)
 {
   return(densePOTRF(A->cols, A->M));
 }
@@ -82,9 +82,9 @@ void DenseMatvec(DlsMat A, realtype *x, realtype *y)
   denseMatvec(A->cols, x, y, A->M, A->N);
 }
 
-long int denseGETRF(realtype **a, long int m, long int n, long int *p)
+sunindextype denseGETRF(realtype **a, sunindextype m, sunindextype n, sunindextype *p)
 {
-  long int i, j, k, l;
+  sunindextype i, j, k, l;
   realtype *col_j, *col_k;
   realtype temp, mult, a_kj;
 
@@ -145,9 +145,9 @@ long int denseGETRF(realtype **a, long int m, long int n, long int *p)
   return(0);
 }
 
-void denseGETRS(realtype **a, long int n, long int *p, realtype *b)
+void denseGETRS(realtype **a, sunindextype n, sunindextype *p, realtype *b)
 {
-  long int i, k, pk;
+  sunindextype i, k, pk;
   realtype *col_k, tmp;
 
   /* Permute b, based on pivot information in p */
@@ -182,11 +182,11 @@ void denseGETRS(realtype **a, long int n, long int *p, realtype *b)
  * Only the lower triangle of A is accessed and it is overwritten with
  * the lower triangle of C.
  */
-long int densePOTRF(realtype **a, long int m)
+sunindextype densePOTRF(realtype **a, sunindextype m)
 {
   realtype *a_col_j, *a_col_k;
   realtype a_diag;
-  long int i, j, k;
+  sunindextype i, j, k;
 
   for (j=0; j<m; j++) {
 
@@ -217,10 +217,10 @@ long int densePOTRF(realtype **a, long int m)
  * obtained with denPOTRF.; A = C*C^T, C lower triangular
  *
  */
-void densePOTRS(realtype **a, long int m, realtype *b)
+void densePOTRS(realtype **a, sunindextype m, realtype *b)
 {
   realtype *col_j, *col_i;
-  long int i, j;
+  sunindextype i, j;
 
   /* Solve C y = b, forward substitution - column version.
      Store solution y in b */
@@ -258,11 +258,11 @@ void densePOTRS(realtype **a, long int m, realtype *b)
  *
  */
 
-int denseGEQRF(realtype **a, long int m, long int n, realtype *beta, realtype *v)
+int denseGEQRF(realtype **a, sunindextype m, sunindextype n, realtype *beta, realtype *v)
 {
   realtype ajj, s, mu, v1, v1_2;
   realtype *col_j, *col_k;
-  long int i, j, k;
+  sunindextype i, j, k;
 
   /* For each column...*/
   for(j=0; j<n; j++) {
@@ -319,11 +319,11 @@ int denseGEQRF(realtype **a, long int m, long int n, realtype *beta, realtype *v
  *
  * v (of length m) must be provided as workspace.
  */
-int denseORMQR(realtype **a, long int m, long int n, realtype *beta,
+int denseORMQR(realtype **a, sunindextype m, sunindextype n, realtype *beta,
                realtype *vn, realtype *vm, realtype *v)
 {
   realtype *col_j, s;
-  long int i, j;
+  sunindextype i, j;
 
   /* Initialize vm */
   for(i=0; i<n; i++) vm[i] = vn[i];
@@ -349,9 +349,9 @@ int denseORMQR(realtype **a, long int m, long int n, realtype *beta,
   return(0);
 }
 
-void denseCopy(realtype **a, realtype **b, long int m, long int n)
+void denseCopy(realtype **a, realtype **b, sunindextype m, sunindextype n)
 {
-  long int i, j;
+  sunindextype i, j;
   realtype *a_col_j, *b_col_j;
 
   for (j=0; j < n; j++) {
@@ -363,9 +363,9 @@ void denseCopy(realtype **a, realtype **b, long int m, long int n)
 
 }
 
-void denseScale(realtype c, realtype **a, long int m, long int n)
+void denseScale(realtype c, realtype **a, sunindextype m, sunindextype n)
 {
-  long int i, j;
+  sunindextype i, j;
   realtype *col_j;
 
   for (j=0; j < n; j++) {
@@ -375,16 +375,16 @@ void denseScale(realtype c, realtype **a, long int m, long int n)
   }
 }
 
-void denseAddIdentity(realtype **a, long int n)
+void denseAddIdentity(realtype **a, sunindextype n)
 {
-  long int i;
+  sunindextype i;
   
   for (i=0; i < n; i++) a[i][i] += ONE;
 }
 
-void denseMatvec(realtype **a, realtype *x, realtype *y, long int m, long int n)
+void denseMatvec(realtype **a, realtype *x, realtype *y, sunindextype m, sunindextype n)
 {
-  long int i, j;
+  sunindextype i, j;
   realtype *col_j;
 
   for (i=0; i<m; i++) {
diff --git a/src/sundials/sundials_direct.c b/src/sundials/sundials_direct.c
index 0fabca6..3cc7216 100644
--- a/src/sundials/sundials_direct.c
+++ b/src/sundials/sundials_direct.c
@@ -1,8 +1,4 @@
-/*
- * -----------------------------------------------------------------
- * $Revision: 4272 $
- * $Date: 2014-12-02 11:19:41 -0800 (Tue, 02 Dec 2014) $
- * -----------------------------------------------------------------
+/* -----------------------------------------------------------------
  * Programmer: Radu Serban @ LLNL
  * -----------------------------------------------------------------
  * LLNS Copyright Start
@@ -17,8 +13,7 @@
  * -----------------------------------------------------------------
  * This is the implementation file for operations to be used by a
  * generic direct linear solver.
- * -----------------------------------------------------------------
- */ 
+ * -----------------------------------------------------------------*/ 
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -29,10 +24,10 @@
 #define ZERO RCONST(0.0)
 #define ONE  RCONST(1.0)
 
-DlsMat NewDenseMat(long int M, long int N)
+DlsMat NewDenseMat(sunindextype M, sunindextype N)
 {
   DlsMat A;
-  long int j;
+  sunindextype j;
 
   if ( (M <= 0) || (N <= 0) ) return(NULL);
 
@@ -64,9 +59,9 @@ DlsMat NewDenseMat(long int M, long int N)
   return(A);
 }
 
-realtype **newDenseMat(long int m, long int n)
+realtype **newDenseMat(sunindextype m, sunindextype n)
 {
-  long int j;
+  sunindextype j;
   realtype **a;
 
   if ( (n <= 0) || (m <= 0) ) return(NULL);
@@ -88,10 +83,10 @@ realtype **newDenseMat(long int m, long int n)
 }
 
 
-DlsMat NewBandMat(long int N, long int mu, long int ml, long int smu)
+DlsMat NewBandMat(sunindextype N, sunindextype mu, sunindextype ml, sunindextype smu)
 {
   DlsMat A;
-  long int j, colSize;
+  sunindextype j, colSize;
 
   if (N <= 0) return(NULL);
   
@@ -130,10 +125,10 @@ DlsMat NewBandMat(long int N, long int mu, long int ml, long int smu)
   return(A);
 }
 
-realtype **newBandMat(long int n, long int smu, long int ml)
+realtype **newBandMat(sunindextype n, sunindextype smu, sunindextype ml)
 {
   realtype **a;
-  long int j, colSize;
+  sunindextype j, colSize;
 
   if (n <= 0) return(NULL);
 
@@ -191,31 +186,31 @@ int *newIntArray(int n)
   return(v);
 }
 
-long int *NewLintArray(long int N)
+sunindextype *NewIndexArray(sunindextype N)
 {
-  long int *vec;
+  sunindextype *vec;
 
   if (N <= 0) return(NULL);
 
   vec = NULL;
-  vec = (long int *) malloc(N * sizeof(long int));
+  vec = (sunindextype *) malloc(N * sizeof(sunindextype));
 
   return(vec);
 }
 
-long int *newLintArray(long int n)
+sunindextype *newIndexArray(sunindextype n)
 {
-  long int *v;
+  sunindextype *v;
 
   if (n <= 0) return(NULL);
 
   v = NULL;
-  v = (long int *) malloc(n * sizeof(long int));
+  v = (sunindextype *) malloc(n * sizeof(sunindextype));
 
   return(v);
 }
 
-realtype *NewRealArray(long int N)
+realtype *NewRealArray(sunindextype N)
 {
   realtype *vec;
 
@@ -227,7 +222,7 @@ realtype *NewRealArray(long int N)
   return(vec);
 }
 
-realtype *newRealArray(long int m)
+realtype *newRealArray(sunindextype m)
 {
   realtype *v;
 
@@ -254,7 +249,7 @@ void destroyArray(void *v)
 
 void AddIdentity(DlsMat A)
 {
-  long int i;
+  sunindextype i;
 
   switch (A->type) {
 
@@ -273,7 +268,7 @@ void AddIdentity(DlsMat A)
 
 void SetToZero(DlsMat A)
 {
-  long int i, j, colSize;
+  sunindextype i, j, colSize;
   realtype *col_j;
 
   switch (A->type) {
@@ -304,52 +299,52 @@ void SetToZero(DlsMat A)
 }
 
 
-void PrintMat(DlsMat A)
+void PrintMat(DlsMat A, FILE *outfile)
 {
-  long int i, j, start, finish;
+  sunindextype i, j, start, finish;
   realtype **a;
 
   switch (A->type) {
 
   case SUNDIALS_DENSE:
 
-    printf("\n");
+    fprintf(outfile, "\n");
     for (i=0; i < A->M; i++) {
       for (j=0; j < A->N; j++) {
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-        printf("%12Lg  ", DENSE_ELEM(A,i,j));
+        fprintf(outfile, "%12Lg  ", DENSE_ELEM(A,i,j));
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-        printf("%12g  ", DENSE_ELEM(A,i,j));
+        fprintf(outfile, "%12g  ", DENSE_ELEM(A,i,j));
 #else
-        printf("%12g  ", DENSE_ELEM(A,i,j));
+        fprintf(outfile, "%12g  ", DENSE_ELEM(A,i,j));
 #endif
       }
-      printf("\n");
+      fprintf(outfile, "\n");
     }
-    printf("\n");
+    fprintf(outfile, "\n");
     
     break;
 
   case SUNDIALS_BAND:
 
     a = A->cols;
-    printf("\n");
+    fprintf(outfile, "\n");
     for (i=0; i < A->N; i++) {
       start = SUNMAX(0,i-A->ml);
       finish = SUNMIN(A->N-1,i+A->mu);
-      for (j=0; j < start; j++) printf("%12s  ","");
+      for (j=0; j < start; j++) fprintf(outfile, "%12s  ","");
       for (j=start; j <= finish; j++) {
 #if defined(SUNDIALS_EXTENDED_PRECISION)
-        printf("%12Lg  ", a[j][i-j+A->s_mu]);
+        fprintf(outfile, "%12Lg  ", a[j][i-j+A->s_mu]);
 #elif defined(SUNDIALS_DOUBLE_PRECISION)
-        printf("%12g  ", a[j][i-j+A->s_mu]);
+        fprintf(outfile, "%12g  ", a[j][i-j+A->s_mu]);
 #else
-        printf("%12g  ", a[j][i-j+A->s_mu]);
+        fprintf(outfile, "%12g  ", a[j][i-j+A->s_mu]);
 #endif
       }
-      printf("\n");
+      fprintf(outfile, "\n");
     }
-    printf("\n");
+    fprintf(outfile, "\n");
     
     break;
 
diff --git a/src/sundials/sundials_iterative.c b/src/sundials/sundials_iterative.c
index 3d36106..b74d43a 100644
--- a/src/sundials/sundials_iterative.c
+++ b/src/sundials/sundials_iterative.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4272 $
- * $Date: 2014-12-02 11:19:41 -0800 (Tue, 02 Dec 2014) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
diff --git a/src/sundials/sundials_linearsolver.c b/src/sundials/sundials_linearsolver.c
new file mode 100644
index 0000000..ac8a3cb
--- /dev/null
+++ b/src/sundials/sundials_linearsolver.c
@@ -0,0 +1,136 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner, Carol Woodward, Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for a generic SUNLINEARSOLVER 
+ * package.  It contains the implementation of the SUNLinearSolver
+ * operations listed in sundials_linearsolver.h
+ * -----------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+#include <sundials/sundials_linearsolver.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Functions in the 'ops' structure
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType(SUNLinearSolver S)
+{
+  SUNLinearSolver_Type type;
+  type = S->ops->gettype(S);
+  return(type);
+}
+
+int SUNLinSolSetATimes(SUNLinearSolver S, void* A_data,
+                       ATimesFn ATimes)
+{
+  if (S->ops->setatimes)
+    return ((int) S->ops->setatimes(S, A_data, ATimes));
+  else
+    return SUNLS_SUCCESS;
+}
+
+  
+int SUNLinSolSetPreconditioner(SUNLinearSolver S, void* P_data,
+                               PSetupFn Pset, PSolveFn Psol)
+{
+  if (S->ops->setpreconditioner)
+    return ((int) S->ops->setpreconditioner(S, P_data, Pset, Psol));
+  else
+    return SUNLS_SUCCESS;
+}
+  
+int SUNLinSolSetScalingVectors(SUNLinearSolver S,
+                               N_Vector s1, N_Vector s2)
+{
+  if (S->ops->setscalingvectors)
+    return ((int) S->ops->setscalingvectors(S, s1, s2));
+  else
+    return SUNLS_SUCCESS;
+}
+  
+int SUNLinSolInitialize(SUNLinearSolver S)
+{
+  return ((int) S->ops->initialize(S));
+}
+  
+int SUNLinSolSetup(SUNLinearSolver S, SUNMatrix A)
+{
+  return ((int) S->ops->setup(S, A));
+}
+
+int SUNLinSolSolve(SUNLinearSolver S, SUNMatrix A, N_Vector x,
+                   N_Vector b, realtype tol)
+{
+  return ((int) S->ops->solve(S, A, x, b, tol));
+}
+  
+int SUNLinSolNumIters(SUNLinearSolver S)
+{
+  if (S->ops->numiters)
+    return ((int) S->ops->numiters(S));
+  else
+    return 0;
+}
+
+realtype SUNLinSolResNorm(SUNLinearSolver S)
+{
+  if (S->ops->resnorm)
+    return ((realtype) S->ops->resnorm(S));
+  else
+    return RCONST(0.0);
+}
+
+N_Vector SUNLinSolResid(SUNLinearSolver S)
+{
+  if (S->ops->resid)
+    return ((N_Vector) S->ops->resid(S));
+  else
+    return NULL;
+}
+
+long int SUNLinSolLastFlag(SUNLinearSolver S)
+{
+  if (S->ops->lastflag)
+    return ((long int) S->ops->lastflag(S));
+  else
+    return SUNLS_SUCCESS;
+}
+
+int SUNLinSolSpace(SUNLinearSolver S, long int *lenrwLS,
+                   long int *leniwLS)
+{
+  if (S->ops->space)
+    return ((int) S->ops->space(S, lenrwLS, leniwLS));
+  else {
+    *lenrwLS = 0;
+    *leniwLS = 0;
+    return SUNLS_SUCCESS;
+  }
+}
+
+int SUNLinSolFree(SUNLinearSolver S)
+{
+  if (S==NULL) return 0;
+  S->ops->free(S);
+  return 0;
+}
+
diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c
index 0e9a1de..7a63880 100644
--- a/src/sundials/sundials_math.c
+++ b/src/sundials/sundials_math.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4272 $
- * $Date: 2014-12-02 11:19:41 -0800 (Tue, 02 Dec 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Aaron Collier @ LLNL
diff --git a/src/sundials/sundials_matrix.c b/src/sundials/sundials_matrix.c
new file mode 100644
index 0000000..64c75f1
--- /dev/null
+++ b/src/sundials/sundials_matrix.c
@@ -0,0 +1,86 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner, Carol Woodward, Slaven Peles @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for a generic SUNMATRIX package.
+ * It contains the implementation of the SUNMatrix operations listed
+ * in sundials_matrix.h
+ * -----------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+#include <sundials/sundials_matrix.h>
+#include <sundials/sundials_nvector.h>
+
+/*
+ * -----------------------------------------------------------------
+ * Functions in the 'ops' structure
+ * -----------------------------------------------------------------
+ */
+
+SUNMatrix_ID SUNMatGetID(SUNMatrix A)
+{
+  SUNMatrix_ID id;
+  id = A->ops->getid(A);
+  return(id);
+}
+
+SUNMatrix SUNMatClone(SUNMatrix A)
+{
+  SUNMatrix B = NULL;
+  B = A->ops->clone(A);
+  return(B);
+}
+
+void SUNMatDestroy(SUNMatrix A)
+{
+  if (A==NULL) return;
+  A->ops->destroy(A);
+  return;
+}
+
+int SUNMatZero(SUNMatrix A)
+{
+  return((int) A->ops->zero(A));
+}
+
+int SUNMatCopy(SUNMatrix A, SUNMatrix B)
+{
+  return((int) A->ops->copy(A, B));
+}
+
+int SUNMatScaleAdd(realtype c, SUNMatrix A, SUNMatrix B)
+{
+  return((int) A->ops->scaleadd(c, A, B));
+}
+
+int SUNMatScaleAddI(realtype c, SUNMatrix A)
+{
+  return((int) A->ops->scaleaddi(c, A));
+}
+
+int SUNMatMatvec(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  return((int) A->ops->matvec(A, x, y));
+}
+
+int SUNMatSpace(SUNMatrix A, long int *lenrw, long int *leniw)
+{
+  return((int) A->ops->space(A, lenrw, leniw));
+}
+
diff --git a/src/sundials/sundials_nvector.c b/src/sundials/sundials_nvector.c
index 75208d5..c68fb50 100644
--- a/src/sundials/sundials_nvector.c
+++ b/src/sundials/sundials_nvector.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4790 $
- * $Date: 2016-06-29 14:47:05 -0700 (Wed, 29 Jun 2016) $
+ * $Revision$
+ * $Date$
  * ----------------------------------------------------------------- 
  * Programmer(s): Radu Serban and Aaron Collier @ LLNL                               
  * -----------------------------------------------------------------
@@ -59,7 +59,7 @@ void N_VDestroy(N_Vector v)
   return;
 }
 
-void N_VSpace(N_Vector v, long int *lrw, long int *liw)
+void N_VSpace(N_Vector v, sunindextype *lrw, sunindextype *liw)
 {
   v->ops->nvspace(v, lrw, liw);
   return;
diff --git a/src/sundials/sundials_pcg.c b/src/sundials/sundials_pcg.c
index 1840c14..ae37ecf 100644
--- a/src/sundials/sundials_pcg.c
+++ b/src/sundials/sundials_pcg.c
@@ -106,7 +106,7 @@ int PcgSolve(PcgMem mem, void *A_data, N_Vector x, N_Vector b,
 
   /* Initialize counters and converged flag */
   *nli = *nps = 0;
-  converged = FALSE;
+  converged = SUNFALSE;
 
   /* Set preconditioning flag */
   UsePrec = ((pretype == PREC_BOTH) || (pretype == PREC_LEFT) || (pretype == PREC_RIGHT));
@@ -126,7 +126,7 @@ int PcgSolve(PcgMem mem, void *A_data, N_Vector x, N_Vector b,
 
   /* Apply preconditioner and b-scaling to r = r_0 */
   if (UsePrec) {
-    ier = psolve(P_data, r, z, PREC_LEFT);   /* z = P^{-1}r */
+    ier = psolve(P_data, r, z, delta, PREC_LEFT);   /* z = P^{-1}r */
     (*nps)++;
     if (ier != 0) return((ier < 0) ? PCG_PSOLVE_FAIL_UNREC : PCG_PSOLVE_FAIL_REC);
   }
@@ -161,13 +161,13 @@ int PcgSolve(PcgMem mem, void *A_data, N_Vector x, N_Vector b,
     /* Set rho and check convergence */
     *res_norm = rho = N_VWrmsNorm(r, w);
     if (rho <= delta) {
-      converged = TRUE;
+      converged = SUNTRUE;
       break;
     }
 
     /* Apply preconditioner:  z = P^{-1}*r */
     if (UsePrec) {
-      ier = psolve(P_data, r, z, PREC_LEFT);
+      ier = psolve(P_data, r, z, delta, PREC_LEFT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? PCG_PSOLVE_FAIL_UNREC : PCG_PSOLVE_FAIL_REC);
     }
@@ -186,7 +186,7 @@ int PcgSolve(PcgMem mem, void *A_data, N_Vector x, N_Vector b,
   }
 
   /* Main loop finished, return with result */
-  if (converged == TRUE)  return(PCG_SUCCESS);
+  if (converged == SUNTRUE)  return(PCG_SUCCESS);
   if (rho < r0_norm)      return(PCG_RES_REDUCED);
   return(PCG_CONV_FAIL);
 }
diff --git a/src/sundials/sundials_sparse.c b/src/sundials/sundials_sparse.c
index a63f505..f1935dc 100644
--- a/src/sundials/sundials_sparse.c
+++ b/src/sundials/sundials_sparse.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4761 $
- * $Date: 2016-05-18 20:00:35 -0700 (Wed, 18 May 2016) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmers: Carol Woodward, Slaven Peles @ LLNL
  *              Daniel R. Reynolds @ SMU
diff --git a/src/sundials/sundials_spbcgs.c b/src/sundials/sundials_spbcgs.c
index bbec881..ab1f25f 100644
--- a/src/sundials/sundials_spbcgs.c
+++ b/src/sundials/sundials_spbcgs.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4507 $
- * $Date: 2015-06-24 08:47:04 -0700 (Wed, 24 Jun 2015) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Peter Brown and Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -169,7 +169,7 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
   vtemp  = mem->vtemp;
 
   *nli = *nps = 0;    /* Initialize counters */
-  converged = FALSE;  /* Initialize converged flag */
+  converged = SUNFALSE;  /* Initialize converged flag */
 
   if ((pretype != PREC_LEFT) && (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) pretype = PREC_NONE;
 
@@ -192,7 +192,7 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
   /* Apply left preconditioner and b-scaling to r_star = r_0 */
 
   if (preOnLeft) {
-    ier = psolve(P_data, r_star, r, PREC_LEFT);
+    ier = psolve(P_data, r_star, r, delta, PREC_LEFT);
     (*nps)++;
     if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
   }
@@ -233,7 +233,7 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
 
     if (preOnRight) {
       N_VScale(ONE, vtemp, Ap);
-      ier = psolve(P_data, Ap, vtemp, PREC_RIGHT);
+      ier = psolve(P_data, Ap, vtemp, delta, PREC_RIGHT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
     }
@@ -247,7 +247,7 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
     /*   Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */
 
     if (preOnLeft) {
-      ier = psolve(P_data, Ap, vtemp, PREC_LEFT);
+      ier = psolve(P_data, Ap, vtemp, delta, PREC_LEFT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
     }
@@ -278,7 +278,7 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
 
     if (preOnRight) {
       N_VScale(ONE, vtemp, u);
-      ier = psolve(P_data, u, vtemp, PREC_RIGHT);
+      ier = psolve(P_data, u, vtemp, delta, PREC_RIGHT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
     }
@@ -292,7 +292,7 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
     /*   Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */
 
     if (preOnLeft) {
-      ier = psolve(P_data, u, vtemp, PREC_LEFT);
+      ier = psolve(P_data, u, vtemp, delta, PREC_LEFT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
     }
@@ -323,7 +323,7 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
 
     *res_norm = rho = SUNRsqrt(N_VDotProd(r, r));
     if (rho <= delta) {
-      converged = TRUE;
+      converged = SUNTRUE;
       break;
     }
 
@@ -343,19 +343,19 @@ int SpbcgSolve(SpbcgMem mem, void *A_data, N_Vector x, N_Vector b,
 
   /* Main loop finished */
 
-  if ((converged == TRUE) || (rho < r_norm)) {
+  if ((converged == SUNTRUE) || (rho < r_norm)) {
 
     /* Apply the x-scaling and right preconditioner: x = P2_inv sx_inv x */
 
     if (scale_x) N_VDiv(x, sx, x);
     if (preOnRight) {
-      ier = psolve(P_data, x, vtemp, PREC_RIGHT);
+      ier = psolve(P_data, x, vtemp, delta, PREC_RIGHT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPBCG_PSOLVE_FAIL_UNREC : SPBCG_PSOLVE_FAIL_REC);
       N_VScale(ONE, vtemp, x);
     }
 
-    if (converged == TRUE) return(SPBCG_SUCCESS);
+    if (converged == SUNTRUE) return(SPBCG_SUCCESS);
     else return(SPBCG_RES_REDUCED);
   }
   else return(SPBCG_CONV_FAIL);
diff --git a/src/sundials/sundials_spfgmr.c b/src/sundials/sundials_spfgmr.c
index 3edf7fd..28ac91a 100644
--- a/src/sundials/sundials_spfgmr.c
+++ b/src/sundials/sundials_spfgmr.c
@@ -171,7 +171,7 @@ int SpfgmrSolve(SpfgmrMem mem, void *A_data, N_Vector x,
   vtemp  = mem->vtemp;
 
   *nli = *nps = 0;    /* Initialize counters */
-  converged = FALSE;  /* Initialize converged flag */
+  converged = SUNFALSE;  /* Initialize converged flag */
 
   /* If maxit is greater than l_max, then set maxit=l_max */
   if (maxit > l_max)  maxit = l_max;
@@ -242,7 +242,7 @@ int SpfgmrSolve(SpfgmrMem mem, void *A_data, N_Vector x,
       /*   Apply right preconditioner: vtemp = Z[l] = P_inv s2_inv V[l]. */ 
       if (preOnRight) {
         N_VScale(ONE, vtemp, V[l+1]);
-        ier = psolve(P_data, V[l+1], vtemp, PREC_RIGHT);
+        ier = psolve(P_data, V[l+1], vtemp, delta, PREC_RIGHT);
         (*nps)++;
         if (ier != 0)
           return((ier < 0) ? SPFGMR_PSOLVE_FAIL_UNREC : SPFGMR_PSOLVE_FAIL_REC);
@@ -274,7 +274,7 @@ int SpfgmrSolve(SpfgmrMem mem, void *A_data, N_Vector x,
       /* Update residual norm estimate; break if convergence test passes. */
       rotation_product *= givens[2*l+1];
       *res_norm = rho = SUNRabs(rotation_product*r_norm);
-      if (rho <= delta) { converged = TRUE; break; }
+      if (rho <= delta) { converged = SUNTRUE; break; }
       
       /* Normalize V[l+1] with norm value from the Gram-Schmidt routine. */
       N_VScale(ONE/Hes[l+1][l], V[l+1], V[l+1]);
diff --git a/src/sundials/sundials_spgmr.c b/src/sundials/sundials_spgmr.c
index d32718b..f515459 100644
--- a/src/sundials/sundials_spgmr.c
+++ b/src/sundials/sundials_spgmr.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4294 $
- * $Date: 2014-12-15 13:18:40 -0800 (Mon, 15 Dec 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
  *                Radu Serban @ LLNL
@@ -191,7 +191,7 @@ int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
   vtemp  = mem->vtemp;
 
   *nli = *nps = 0;    /* Initialize counters */
-  converged = FALSE;  /* Initialize converged flag */
+  converged = SUNFALSE;  /* Initialize converged flag */
 
   if (max_restarts < 0) max_restarts = 0;
 
@@ -218,7 +218,7 @@ int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
   /* Apply left preconditioner and left scaling to V[0] = r_0. */
   
   if (preOnLeft) {
-    ier = psolve(P_data, V[0], vtemp, PREC_LEFT);
+    ier = psolve(P_data, V[0], vtemp, delta, PREC_LEFT);
     (*nps)++;
     if (ier != 0)
       return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
@@ -282,7 +282,7 @@ int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
 
       if (preOnRight) {
         N_VScale(ONE, vtemp, V[l_plus_1]);
-        ier = psolve(P_data, V[l_plus_1], vtemp, PREC_RIGHT);
+        ier = psolve(P_data, V[l_plus_1], vtemp, delta, PREC_RIGHT);
         (*nps)++;
         if (ier != 0)
           return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
@@ -297,7 +297,7 @@ int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
       /* Apply left preconditioning: vtemp = P1_inv A P2_inv s2_inv V[l]. */
 
       if (preOnLeft) {
-        ier = psolve(P_data, V[l_plus_1], vtemp, PREC_LEFT);
+        ier = psolve(P_data, V[l_plus_1], vtemp, delta, PREC_LEFT);
         (*nps)++;
         if (ier != 0)
           return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
@@ -334,7 +334,7 @@ int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
       rotation_product *= givens[2*l+1];
       *res_norm = rho = SUNRabs(rotation_product*r_norm);
       
-      if (rho <= delta) { converged = TRUE; break; }
+      if (rho <= delta) { converged = SUNTRUE; break; }
       
       /* Normalize V[l+1] with norm value from the Gram-Schmidt routine. */
 
@@ -363,7 +363,7 @@ int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
       
       if (scale2) N_VDiv(xcor, s2, xcor);
       if (preOnRight) {
-        ier = psolve(P_data, xcor, vtemp, PREC_RIGHT);
+        ier = psolve(P_data, xcor, vtemp, delta, PREC_RIGHT);
         (*nps)++;
         if (ier != 0)
           return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
@@ -414,7 +414,7 @@ int SpgmrSolve(SpgmrMem mem, void *A_data, N_Vector x, N_Vector b,
     
     if (scale2) N_VDiv(xcor, s2, xcor);
     if (preOnRight) {
-      ier = psolve(P_data, xcor, vtemp, PREC_RIGHT);
+      ier = psolve(P_data, xcor, vtemp, delta, PREC_RIGHT);
       (*nps)++;
       if (ier != 0)
         return((ier < 0) ? SPGMR_PSOLVE_FAIL_UNREC : SPGMR_PSOLVE_FAIL_REC);
diff --git a/src/sundials/sundials_sptfqmr.c b/src/sundials/sundials_sptfqmr.c
index 2aa360f..5968fe1 100644
--- a/src/sundials/sundials_sptfqmr.c
+++ b/src/sundials/sundials_sptfqmr.c
@@ -1,7 +1,7 @@
 /*
  * -----------------------------------------------------------------
- * $Revision: 4272 $
- * $Date: 2014-12-02 11:19:41 -0800 (Tue, 02 Dec 2014) $
+ * $Revision$
+ * $Date$
  * -----------------------------------------------------------------
  * Programmer(s): Aaron Collier @ LLNL
  * -----------------------------------------------------------------
@@ -217,8 +217,8 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
   temp_val = r_curr_norm = -ONE;  /* Initialize to avoid compiler warnings */
 
   *nli = *nps = 0;    /* Initialize counters */
-  converged = FALSE;  /* Initialize convergence flag */
-  b_ok = FALSE;
+  converged = SUNFALSE;  /* Initialize convergence flag */
+  b_ok = SUNFALSE;
 
   if ((pretype != PREC_LEFT)  &&
       (pretype != PREC_RIGHT) &&
@@ -242,7 +242,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
 
   /* Apply left preconditioner and b-scaling to r_star (or really just r_0) */
   if (preOnLeft) {
-    ier = psolve(P_data, r_star, vtemp1, PREC_LEFT);
+    ier = psolve(P_data, r_star, vtemp1, delta, PREC_LEFT);
     (*nps)++;
     if (ier != 0)
       return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
@@ -267,7 +267,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
   else N_VScale(ONE, r_star, vtemp1);
   if (preOnRight) {
     N_VScale(ONE, vtemp1, v_);
-    ier = psolve(P_data, v_, vtemp1, PREC_RIGHT);
+    ier = psolve(P_data, v_, vtemp1, delta, PREC_RIGHT);
     (*nps)++;
     if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
   }
@@ -275,7 +275,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
   if (ier != 0)
     return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
   if (preOnLeft) {
-    ier = psolve(P_data, v_, vtemp1, PREC_LEFT);
+    ier = psolve(P_data, v_, vtemp1, delta, PREC_LEFT);
     (*nps)++;
     if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
   }
@@ -312,7 +312,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
     if (scale_x) N_VDiv(r_[1], sx, r_[1]);
     if (preOnRight) {
       N_VScale(ONE, r_[1], vtemp1);
-      ier = psolve(P_data, vtemp1, r_[1], PREC_RIGHT);
+      ier = psolve(P_data, vtemp1, r_[1], delta, PREC_RIGHT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
     }
@@ -320,7 +320,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
     if (ier != 0)
       return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
     if (preOnLeft) {
-      ier = psolve(P_data, vtemp1, r_[1], PREC_LEFT);
+      ier = psolve(P_data, vtemp1, r_[1], delta, PREC_LEFT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
     }
@@ -370,7 +370,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
       /* Exit inner loop if iteration has converged based upon approximation
 	 to norm of current residual */
       if (r_curr_norm <= delta) {
-	converged = TRUE;
+	converged = SUNTRUE;
 	break;
       }
 
@@ -393,7 +393,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
 	if (scale_x) N_VDiv(x, sx, vtemp1);
 	else N_VScale(ONE, x, vtemp1);
 	if (preOnRight) {
-	  ier = psolve(P_data, vtemp1, vtemp2, PREC_RIGHT);
+	  ier = psolve(P_data, vtemp1, vtemp2, delta, PREC_RIGHT);
 	  (*nps)++;
 	  if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC);
 	  N_VScale(ONE, vtemp2, vtemp1);
@@ -402,7 +402,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
         if (ier != 0)
           return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
 	if (preOnLeft) {
-	  ier = psolve(P_data, vtemp2, vtemp1, PREC_LEFT);
+	  ier = psolve(P_data, vtemp2, vtemp1, delta, PREC_LEFT);
 	  (*nps)++;
 	  if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
 	}
@@ -411,9 +411,9 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
 	else N_VScale(ONE, vtemp1, vtemp2);
 	/* Only precondition and scale b once (result saved for reuse) */
 	if (!b_ok) {
-	  b_ok = TRUE;
+	  b_ok = SUNTRUE;
 	  if (preOnLeft) {
-	    ier = psolve(P_data, b, vtemp3, PREC_LEFT);
+	    ier = psolve(P_data, b, vtemp3, delta, PREC_LEFT);
 	    (*nps)++;
 	    if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
 	  }
@@ -426,7 +426,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
 	/* Exit inner loop if inequality condition is satisfied 
 	   (meaning exit if we have converged) */
 	if (r_curr_norm <= delta) {
-	  converged = TRUE;
+	  converged = SUNTRUE;
 	  break;
 	}
 
@@ -435,7 +435,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
     }  /* END inner loop */
 
     /* If converged, then exit outer loop as well */
-    if (converged == TRUE) break;
+    if (converged == SUNTRUE) break;
 
     /* rho[1] = r_star^T*r_[1] */
     rho[1] = N_VDotProd(r_star, r_[1]);
@@ -455,7 +455,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
     else N_VScale(ONE, p_, vtemp1);
     if (preOnRight) {
       N_VScale(ONE, vtemp1, v_);
-      ier = psolve(P_data, v_, vtemp1, PREC_RIGHT);
+      ier = psolve(P_data, v_, vtemp1, delta, PREC_RIGHT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
     }
@@ -463,7 +463,7 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
     if (ier != 0)
       return((ier < 0) ? SPTFQMR_ATIMES_FAIL_UNREC : SPTFQMR_ATIMES_FAIL_REC);
     if (preOnLeft) {
-      ier = psolve(P_data, v_, vtemp1, PREC_LEFT);
+      ier = psolve(P_data, v_, vtemp1, delta, PREC_LEFT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_REC);
     }
@@ -480,15 +480,15 @@ int SptfqmrSolve(SptfqmrMem mem, void *A_data, N_Vector x, N_Vector b,
 
   /* Determine return value */
   /* If iteration converged or residual was reduced, then return current iterate (x) */
-  if ((converged == TRUE) || (r_curr_norm < r_init_norm)) {
+  if ((converged == SUNTRUE) || (r_curr_norm < r_init_norm)) {
     if (scale_x) N_VDiv(x, sx, x);
     if (preOnRight) {
-      ier = psolve(P_data, x, vtemp1, PREC_RIGHT);
+      ier = psolve(P_data, x, vtemp1, delta, PREC_RIGHT);
       (*nps)++;
       if (ier != 0) return((ier < 0) ? SPTFQMR_PSOLVE_FAIL_UNREC : SPTFQMR_PSOLVE_FAIL_UNREC);
       N_VScale(ONE, vtemp1, x);
     }
-    if (converged == TRUE) return(SPTFQMR_SUCCESS);
+    if (converged == SUNTRUE) return(SPTFQMR_SUCCESS);
     else return(SPTFQMR_RES_REDUCED);
   }
   /* Otherwise, return error code */
diff --git a/src/sundials/sundials_version.c b/src/sundials/sundials_version.c
new file mode 100644
index 0000000..7c563f2
--- /dev/null
+++ b/src/sundials/sundials_version.c
@@ -0,0 +1,48 @@
+/* -----------------------------------------------------------------
+ * Programmer(s): David J. Gardner @ LLNL                               
+ * -----------------------------------------------------------------
+ * LLNS Copyright Start
+ * Copyright (c) 2014, Lawrence Livermore National Security
+ * This work was performed under the auspices of the U.S. Department
+ * of Energy by Lawrence Livermore National Laboratory in part under
+ * Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+ * Produced at the Lawrence Livermore National Laboratory.
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS Copyright End
+ * -----------------------------------------------------------------
+ * This file implements functions for getting SUNDIALS version
+ * information.
+ * -----------------------------------------------------------------*/
+
+#include <string.h>
+
+#include <sundials/sundials_version.h>
+
+/* fill string with SUNDIALS version information */
+int SUNDIALSGetVersion(char *version, int len)
+{
+  if (strlen(SUNDIALS_VERSION) > len) {
+    return(-1);
+  }
+  
+  strncpy(version, SUNDIALS_VERSION, len);
+  return(0);
+}
+
+/* fill integers with SUNDIALS major, minor, and patch release 
+   numbers and fill a string with the release label */
+int SUNDIALSGetVersionNumber(int *major, int *minor, int *patch, 
+                             char *label, int len)
+{
+  if (strlen(SUNDIALS_VERSION_LABEL) > len) {
+    return(-1);
+  }
+  
+  *major = SUNDIALS_VERSION_MAJOR;
+  *minor = SUNDIALS_VERSION_MINOR;
+  *patch = SUNDIALS_VERSION_PATCH;
+  strncpy(label, SUNDIALS_VERSION_LABEL, len);
+
+  return(0);
+}
diff --git a/src/sunlinsol_band/CMakeLists.txt b/src/sunlinsol_band/CMakeLists.txt
new file mode 100644
index 0000000..b4fdbf1
--- /dev/null
+++ b/src/sunlinsol_band/CMakeLists.txt
@@ -0,0 +1,105 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the band SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_BAND\n\")")
+
+# Add variable sunlinsolband_SOURCES with the sources for the SUNLINSOLBAND lib
+SET(sunlinsolband_SOURCES sunlinsol_band.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLBAND library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_band.c
+  )
+
+# Add variable sunlinsolband_HEADERS with the exported SUNLINSOLBAND header files
+SET(sunlinsolband_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_band.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLBAND library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLBAND library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolband_static STATIC ${sunlinsolband_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolband_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolband CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolband_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLBAND library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLBAND library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolband_shared SHARED ${sunlinsolband_SOURCES} ${shared_SOURCES})
+
+  # sunlinsolband depends on sunmatrixband
+  TARGET_LINK_LIBRARIES(sundials_sunlinsolband_shared sundials_sunmatrixband_shared)
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolband_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolband CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolband_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolband_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLBAND header files
+INSTALL(FILES ${sunlinsolband_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLBAND library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsolband_SOURCES fsunlinsol_band.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolband_static STATIC ${fsunlinsolband_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolband_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolband CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsolband_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolband_shared ${fsunlinsolband_SOURCES})
+
+    # fsunlinsolband depends on fnvecserial, fsunmatrixband, sunlinsolband
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsolband_shared
+      sundials_fnvecserial_shared
+      sundials_fsunmatrixband_shared
+      sundials_sunlinsolband_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolband_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolband CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolband_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsolband_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_BAND module")
diff --git a/src/sunlinsol_band/README b/src/sunlinsol_band/README
new file mode 100644
index 0000000..e668905
--- /dev/null
+++ b/src/sunlinsol_band/README
@@ -0,0 +1,41 @@
+                     SUNLINSOL_BAND
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Band implementation of the SUNLINSOL module for SUNDIALS. 
+
+SUNLINSOL_BAND defines the content field of SUNMatrix to be a structure 
+containing a pivot array for performing LU factorization with row
+pivoting, along with a long integer for any error flag that arises in
+the factorization process.
+
+SUNLINSOL_BAND defines three macros to provide access to the content of 
+a band SUNLinearSolver, and constructor for the banded
+SUNLinearSolver, in addition to implementation of all linear
+solver operations defined by the generic SUNLINSOL module in the table
+of operations.
+
+
+A. Documentation
+----------------
+
+The band SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_band/fsunlinsol_band.c b/src/sunlinsol_band/fsunlinsol_band.c
new file mode 100644
index 0000000..258818e
--- /dev/null
+++ b/src/sunlinsol_band/fsunlinsol_band.c
@@ -0,0 +1,100 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_band.h) contains the
+ * implementation needed for the Fortran initialization of band
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_band.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNBANDLINSOL_INIT(int *code, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNBandLinearSolver(F2C_CVODE_vec,
+                                           F2C_CVODE_matrix);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNBandLinearSolver(F2C_IDA_vec,
+                                         F2C_IDA_matrix);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNBandLinearSolver(F2C_KINSOL_vec,
+                                            F2C_KINSOL_matrix);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNBandLinearSolver(F2C_ARKODE_vec,
+                                            F2C_ARKODE_matrix);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSBANDLINSOL_INIT(int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNBandLinearSolver(F2C_ARKODE_vec,
+                                            F2C_ARKODE_mass_matrix);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
diff --git a/src/sunlinsol_band/fsunlinsol_band.h b/src/sunlinsol_band/fsunlinsol_band.h
new file mode 100644
index 0000000..2a02a71
--- /dev/null
+++ b/src/sunlinsol_band/fsunlinsol_band.h
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_band.c) contains the
+ * definitions needed for the initialization of band
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_BAND_H
+#define _FSUNLINSOL_BAND_H
+
+#include <sunlinsol/sunlinsol_band.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNBANDLINSOL_INIT     SUNDIALS_F77_FUNC(fsunbandlinsolinit, FSUNBANDLINSOLINIT)
+#define FSUNMASSBANDLINSOL_INIT SUNDIALS_F77_FUNC(fsunmassbandlinsolinit, FSUNMASSBANDLINSOLINIT)
+#else
+#define FSUNBANDLINSOL_INIT     fsunbandlinsolinit_
+#define FSUNMASSBANDLINSOL_INIT fsunmassbandlinsolinit_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNBANDLINSOL_INIT - initializes band linear solver for main problem
+ * FSUNMASSBANDLINSOL_INIT - initializes band linear solver for mass matrix solve
+ */
+
+void FSUNBANDLINSOL_INIT(int *code, int *ier);
+void FSUNMASSBANDLINSOL_INIT(int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_band/sunlinsol_band.c b/src/sunlinsol_band/sunlinsol_band.c
new file mode 100644
index 0000000..ac8b3a6
--- /dev/null
+++ b/src/sunlinsol_band/sunlinsol_band.c
@@ -0,0 +1,281 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the band implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_band.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO  RCONST(0.0)
+#define ONE   RCONST(1.0)
+#define ROW(i,j,smu) (i-j+smu)
+
+
+/* Private function prototypes */
+sunindextype GlobalVectorLength_BandLS(N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * Band solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define BAND_CONTENT(S)   ( (SUNLinearSolverContent_Band)(S->content) )
+#define PIVOTS(S)         ( BAND_CONTENT(S)->pivots )
+#define LASTFLAG(S)       ( BAND_CONTENT(S)->last_flag )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new band linear solver
+ */
+
+SUNLinearSolver SUNBandLinearSolver(N_Vector y, SUNMatrix A)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_Band content;
+  sunindextype MatrixRows, VecLength;
+  
+  /* Check compatibility with supplied SUNMatrix and N_Vector */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND)
+    return(NULL);
+  if (SUNBandMatrix_Rows(A) != SUNBandMatrix_Columns(A))
+    return(NULL);
+  MatrixRows = SUNBandMatrix_Rows(A);
+  if ( (N_VGetVectorID(y) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_PTHREADS) )
+    return(NULL);
+
+  /* Check that A has appropriate storage upper bandwidth for factorization */
+  if (SUNBandMatrix_StoredUpperBandwidth(A) <
+      SUNMIN(MatrixRows-1, SUNBandMatrix_LowerBandwidth(A)+SUNBandMatrix_UpperBandwidth(A)))
+    return(NULL);
+
+  /* optimally this function would be replaced with a generic N_Vector routine */
+  VecLength = GlobalVectorLength_BandLS(y);
+  if (MatrixRows != VecLength)
+    return(NULL);
+  
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_Band;
+  ops->initialize        = SUNLinSolInitialize_Band;
+  ops->setup             = SUNLinSolSetup_Band;
+  ops->solve             = SUNLinSolSolve_Band;
+  ops->lastflag          = SUNLinSolLastFlag_Band;
+  ops->space             = SUNLinSolSpace_Band;
+  ops->free              = SUNLinSolFree_Band;
+  ops->setatimes         = NULL;
+  ops->setpreconditioner = NULL;
+  ops->setscalingvectors = NULL;
+  ops->numiters          = NULL;
+  ops->resnorm           = NULL;
+  ops->resid             = NULL;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_Band) malloc(sizeof(struct _SUNLinearSolverContent_Band));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->N = MatrixRows;
+  content->last_flag = 0;
+  content->pivots = NULL;
+  content->pivots = (sunindextype *) malloc(MatrixRows * sizeof(sunindextype));
+  if (content->pivots == NULL) {
+    free(content); free(ops); free(S); return(NULL);
+  }
+  
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_Band(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_DIRECT);
+}
+
+int SUNLinSolInitialize_Band(SUNLinearSolver S)
+{
+  /* all solver-specific memory has already been allocated */
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+int SUNLinSolSetup_Band(SUNLinearSolver S, SUNMatrix A)
+{
+  realtype **A_cols;
+  sunindextype *pivots;
+
+  /* check for valid inputs */
+  if ( (A == NULL) || (S == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* Ensure that A is a band matrix */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND) {
+    LASTFLAG(S) = SUNLS_ILL_INPUT;
+    return(LASTFLAG(S));
+  }
+  
+  /* access data pointers (return with failure on NULL) */
+  A_cols = NULL;
+  pivots = NULL;
+  A_cols = SM_COLS_B(A);
+  pivots = PIVOTS(S);
+  if ( (A_cols == NULL) || (pivots == NULL) ) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+
+  /* ensure that storage upper bandwidth is sufficient for fill-in */
+  if (SM_SUBAND_B(A) < SUNMIN(SM_COLUMNS_B(A)-1, SM_UBAND_B(A) + SM_LBAND_B(A))) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+  
+  /* perform LU factorization of input matrix */
+  LASTFLAG(S) = bandGBTRF(A_cols, SM_COLUMNS_B(A), SM_UBAND_B(A),
+			  SM_LBAND_B(A), SM_SUBAND_B(A), pivots);
+  
+  /* store error flag (if nonzero, that row encountered zero-valued pivod) */
+  if (LASTFLAG(S) > 0)
+    return(SUNLS_LUFACT_FAIL);
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolSolve_Band(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                        N_Vector b, realtype tol)
+{
+  realtype **A_cols, *xdata;
+  sunindextype *pivots;
+  
+  /* check for valid inputs */
+  if ( (A == NULL) || (S == NULL) || (x == NULL) || (b == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* copy b into x */
+  N_VScale(ONE, b, x);
+
+  /* access data pointers (return with failure on NULL) */
+  A_cols = NULL;
+  xdata = NULL;
+  pivots = NULL;
+  A_cols = SUNBandMatrix_Cols(A);
+  xdata = N_VGetArrayPointer(x);
+  pivots = PIVOTS(S);
+  if ( (A_cols == NULL) || (xdata == NULL)  || (pivots == NULL) ) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+
+  /* solve using LU factors */
+  bandGBTRS(A_cols, SM_COLUMNS_B(A), SM_SUBAND_B(A), 
+            SM_LBAND_B(A), pivots, xdata);
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+long int SUNLinSolLastFlag_Band(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  return(LASTFLAG(S));
+}
+
+int SUNLinSolSpace_Band(SUNLinearSolver S, 
+                        long int *lenrwLS, 
+                        long int *leniwLS)
+{
+  *leniwLS = 2 + BAND_CONTENT(S)->N;
+  *lenrwLS = 0;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_Band(SUNLinearSolver S)
+{
+  /* return if S is already free */
+  if (S == NULL)
+    return(SUNLS_SUCCESS);
+
+  /* delete items from contents, then delete generic structure */
+  if (S->content) {
+    if (PIVOTS(S)) {
+      free(PIVOTS(S));
+      PIVOTS(S) = NULL;
+    }
+    free(S->content);  
+    S->content = NULL;
+  }
+  if (S->ops) {
+    free(S->ops);  
+    S->ops = NULL;
+  }
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+/* Inefficient kludge for determining the number of entries in a N_Vector 
+   object (replace if such a routine is ever added to the N_Vector API).
+
+   Returns "-1" on an error. */
+sunindextype GlobalVectorLength_BandLS(N_Vector y)
+{
+  realtype len;
+  N_Vector tmp = NULL;
+  tmp = N_VClone(y);
+  if (tmp == NULL)  return(-1);
+  N_VConst(ONE, tmp);
+  len = N_VDotProd(tmp, tmp);
+  N_VDestroy(tmp);
+  return( (sunindextype) len );
+}
diff --git a/src/sunlinsol_dense/CMakeLists.txt b/src/sunlinsol_dense/CMakeLists.txt
new file mode 100644
index 0000000..131de1e
--- /dev/null
+++ b/src/sunlinsol_dense/CMakeLists.txt
@@ -0,0 +1,104 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds, Ashley Crawford @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the dense SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_DENSE\n\")")
+
+# Add variable sunlinsoldense_SOURCES with the sources for the SUNLINSOLDENSE lib
+SET(sunlinsoldense_SOURCES sunlinsol_dense.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLDENSE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_dense.c
+  )
+
+# Add variable sunlinsoldense_HEADERS with the exported SUNLINSOLDENSE header files
+SET(sunlinsoldense_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_dense.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLDENSE library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLDENSE library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsoldense_static STATIC ${sunlinsoldense_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsoldense_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsoldense CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsoldense_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLDENSE library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLDENSE library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsoldense_shared SHARED ${sunlinsoldense_SOURCES} ${shared_SOURCES})
+
+  TARGET_LINK_LIBRARIES(sundials_sunlinsoldense_shared sundials_sunmatrixdense_shared)
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsoldense_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsoldense CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsoldense_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsoldense_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLDENSE header files
+INSTALL(FILES ${sunlinsoldense_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLDENSE library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsoldense_SOURCES fsunlinsol_dense.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsoldense_static STATIC ${fsunlinsoldense_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsoldense_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsoldense CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsoldense_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsoldense_shared ${fsunlinsoldense_SOURCES})
+
+    # fsunlinsoldense depends on fnvecserial, fsunmatrixdense, sunlinsoldense
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsoldense_shared
+      sundials_fnvecserial_shared
+      sundials_fsunmatrixdense_shared
+      sundials_sunlinsoldense_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsoldense_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsoldense CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsoldense_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsoldense_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_DENSE module")
diff --git a/src/sunlinsol_dense/README b/src/sunlinsol_dense/README
new file mode 100644
index 0000000..337df2e
--- /dev/null
+++ b/src/sunlinsol_dense/README
@@ -0,0 +1,41 @@
+                     SUNLINSOL_DENSE
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Dense implementation of the SUNLINSOL module for SUNDIALS. 
+
+SUNLINSOL_DENSE defines the content field of SUNMatrix to be a structure 
+containing a pivot array for performing LU factorization with row
+pivoting, along with a long integer for any error flag that arises in
+the factorization process.
+
+SUNLINSOL_DENSE defines macros to provide access to the content of 
+a dense SUNLinearSolver, and constructor for the dense
+SUNLinearSolver, in addition to implementation of all linear
+solver operations defined by the generic SUNLINSOL module in the table
+of operations.
+
+
+A. Documentation
+----------------
+
+The dense SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_dense/fsunlinsol_dense.c b/src/sunlinsol_dense/fsunlinsol_dense.c
new file mode 100644
index 0000000..f29fa2e
--- /dev/null
+++ b/src/sunlinsol_dense/fsunlinsol_dense.c
@@ -0,0 +1,100 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_dense.h) contains the
+ * implementation needed for the Fortran initialization of dense
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_dense.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNDENSELINSOL_INIT(int *code, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNDenseLinearSolver(F2C_CVODE_vec,
+                                            F2C_CVODE_matrix);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNDenseLinearSolver(F2C_IDA_vec,
+                                          F2C_IDA_matrix);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNDenseLinearSolver(F2C_KINSOL_vec,
+                                             F2C_KINSOL_matrix);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNDenseLinearSolver(F2C_ARKODE_vec,
+                                             F2C_ARKODE_matrix);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSDENSELINSOL_INIT(int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNDenseLinearSolver(F2C_ARKODE_vec,
+                                             F2C_ARKODE_mass_matrix);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
diff --git a/src/sunlinsol_dense/fsunlinsol_dense.h b/src/sunlinsol_dense/fsunlinsol_dense.h
new file mode 100644
index 0000000..545f156
--- /dev/null
+++ b/src/sunlinsol_dense/fsunlinsol_dense.h
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_dense.c) contains the
+ * definitions needed for the initialization of dense
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_DENSE_H
+#define _FSUNLINSOL_DENSE_H
+
+#include <sunlinsol/sunlinsol_dense.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNDENSELINSOL_INIT     SUNDIALS_F77_FUNC(fsundenselinsolinit, FSUNDENSELINSOLINIT)
+#define FSUNMASSDENSELINSOL_INIT SUNDIALS_F77_FUNC(fsunmassdenselinsolinit, FSUNMASSDENSELINSOLINIT)
+#else
+#define FSUNDENSELINSOL_INIT     fsundenselinsolinit_
+#define FSUNMASSDENSELINSOL_INIT fsunmassdenselinsolinit_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNDENSELINSOL_INIT - initializes dense linear solver for main problem
+ * FSUNMASSDENSELINSOL_INIT - initializes dense linear solver for mass matrix solve
+ */
+
+void FSUNDENSELINSOL_INIT(int *code, int *ier);
+void FSUNMASSDENSELINSOL_INIT(int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_dense/sunlinsol_dense.c b/src/sunlinsol_dense/sunlinsol_dense.c
new file mode 100644
index 0000000..f940651
--- /dev/null
+++ b/src/sunlinsol_dense/sunlinsol_dense.c
@@ -0,0 +1,267 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the dense implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_dense.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(1.0)
+#define ONE  RCONST(1.0)
+
+/* Private function prototypes */
+sunindextype GlobalVectorLength_DenseLS(N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * Dense solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define DENSE_CONTENT(S)  ( (SUNLinearSolverContent_Dense)(S->content) )
+#define PIVOTS(S)         ( DENSE_CONTENT(S)->pivots )
+#define LASTFLAG(S)       ( DENSE_CONTENT(S)->last_flag )
+
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new dense linear solver
+ */
+
+SUNLinearSolver SUNDenseLinearSolver(N_Vector y, SUNMatrix A)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_Dense content;
+  sunindextype MatrixRows, VecLength;
+  
+  /* Check compatibility with supplied SUNMatrix and N_Vector */
+  if (SUNMatGetID(A) != SUNMATRIX_DENSE)
+    return(NULL);
+  if (SUNDenseMatrix_Rows(A) != SUNDenseMatrix_Columns(A))
+    return(NULL);
+  MatrixRows = SUNDenseMatrix_Rows(A);
+  if ( (N_VGetVectorID(y) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_PTHREADS) )
+    return(NULL);
+
+  /* optimally this function would be replaced with a generic N_Vector routine */
+  VecLength = GlobalVectorLength_DenseLS(y);
+  if (MatrixRows != VecLength)
+    return(NULL);
+  
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_Dense;
+  ops->initialize        = SUNLinSolInitialize_Dense;
+  ops->setup             = SUNLinSolSetup_Dense;
+  ops->solve             = SUNLinSolSolve_Dense;
+  ops->lastflag          = SUNLinSolLastFlag_Dense;
+  ops->space             = SUNLinSolSpace_Dense;
+  ops->free              = SUNLinSolFree_Dense;
+  ops->setatimes         = NULL;
+  ops->setpreconditioner = NULL;
+  ops->setscalingvectors = NULL;
+  ops->numiters          = NULL;
+  ops->resnorm           = NULL;
+  ops->resid             = NULL;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_Dense) malloc(sizeof(struct _SUNLinearSolverContent_Dense));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->N = MatrixRows;
+  content->last_flag = 0;
+  content->pivots = NULL;
+  content->pivots = (sunindextype *) malloc(MatrixRows * sizeof(sunindextype));
+  if (content->pivots == NULL) {
+    free(content); free(ops); free(S); return(NULL);
+  }
+  
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_Dense(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_DIRECT);
+}
+
+int SUNLinSolInitialize_Dense(SUNLinearSolver S)
+{
+  /* all solver-specific memory has already been allocated */
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+int SUNLinSolSetup_Dense(SUNLinearSolver S, SUNMatrix A)
+{
+  realtype **A_cols;
+  sunindextype *pivots;
+  
+  /* check for valid inputs */
+  if ( (A == NULL) || (S == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* Ensure that A is a dense matrix */
+  if (SUNMatGetID(A) != SUNMATRIX_DENSE) {
+    LASTFLAG(S) = SUNLS_ILL_INPUT;
+    return(LASTFLAG(S));
+  }
+  
+  /* access data pointers (return with failure on NULL) */
+  A_cols = NULL;
+  pivots = NULL;
+  A_cols = SUNDenseMatrix_Cols(A);
+  pivots = PIVOTS(S);
+  if ( (A_cols == NULL) || (pivots == NULL) ) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+  
+  /* perform LU factorization of input matrix */
+  LASTFLAG(S) = denseGETRF(A_cols, SUNDenseMatrix_Rows(A),
+                           SUNDenseMatrix_Columns(A), pivots);
+
+  /* store error flag (if nonzero, this row encountered zero-valued pivod) */
+  if (LASTFLAG(S) > 0)
+    return(SUNLS_LUFACT_FAIL);
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolSolve_Dense(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                        N_Vector b, realtype tol)
+{
+  realtype **A_cols, *xdata;
+  sunindextype *pivots;
+  
+  if ( (A == NULL) || (S == NULL) || (x == NULL) || (b == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* copy b into x */
+  N_VScale(ONE, b, x);
+
+  /* access data pointers (return with failure on NULL) */
+  A_cols = NULL;
+  xdata = NULL;
+  pivots = NULL;
+  A_cols = SUNDenseMatrix_Cols(A);
+  xdata = N_VGetArrayPointer(x);
+  pivots = PIVOTS(S);
+  if ( (A_cols == NULL) || (xdata == NULL)  || (pivots == NULL) ) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+  
+  /* solve using LU factors */
+  denseGETRS(A_cols, SUNDenseMatrix_Rows(A), pivots, xdata);
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+long int SUNLinSolLastFlag_Dense(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  return(LASTFLAG(S));
+}
+
+int SUNLinSolSpace_Dense(SUNLinearSolver S, 
+                         long int *lenrwLS, 
+                         long int *leniwLS)
+{
+  *leniwLS = 2 + DENSE_CONTENT(S)->N;
+  *lenrwLS = 0;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_Dense(SUNLinearSolver S)
+{
+  /* return if S is already free */
+  if (S == NULL)
+    return(SUNLS_SUCCESS);
+
+  /* delete items from contents, then delete generic structure */
+  if (S->content) {
+    if (PIVOTS(S)) {
+      free(PIVOTS(S));
+      PIVOTS(S) = NULL;
+    }
+    free(S->content);  
+    S->content = NULL;
+  }
+  if (S->ops) {
+    free(S->ops);  
+    S->ops = NULL;
+  }
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+/* Inefficient kludge for determining the number of entries in a N_Vector 
+   object (replace if such a routine is ever added to the N_Vector API).
+
+   Returns "-1" on an error. */
+sunindextype GlobalVectorLength_DenseLS(N_Vector y)
+{
+  realtype len;
+  N_Vector tmp = NULL;
+  tmp = N_VClone(y);
+  if (tmp == NULL)  return(-1);
+  N_VConst(ONE, tmp);
+  len = N_VDotProd(tmp, tmp);
+  N_VDestroy(tmp);
+  return( (sunindextype) len );
+}
diff --git a/src/sunlinsol_klu/CMakeLists.txt b/src/sunlinsol_klu/CMakeLists.txt
new file mode 100644
index 0000000..5a43d68
--- /dev/null
+++ b/src/sunlinsol_klu/CMakeLists.txt
@@ -0,0 +1,116 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the klu SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_KLU\n\")")
+
+# Add variable sunlinsolklu_SOURCES with the sources for the SUNLINSOLKLU lib
+SET(sunlinsolklu_SOURCES sunlinsol_klu.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLKLU library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  )
+
+# Add variable sunlinsolklu_HEADERS with the exported SUNLINSOLKLU header files
+SET(sunlinsolklu_HEADERS
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_klu.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLKLU library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLKLU library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolklu_static STATIC ${sunlinsolklu_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolklu_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolklu CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolklu_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLKLU library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLKLU library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolklu_shared SHARED ${sunlinsolklu_SOURCES} ${shared_SOURCES})
+
+  # sunlinsolklu depends on sunmatrixsparse and KLU
+  TARGET_LINK_LIBRARIES(sundials_sunlinsolklu_shared
+    sundials_sunmatrixsparse_shared
+    ${KLU_LIBRARIES})
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolklu_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolklu CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolklu_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolklu_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLKLU header files
+INSTALL(FILES ${sunlinsolklu_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled and building with 64-bit indices, then build and install 
+# the FSUNLINSOLKLU library
+IF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+  PRINT_WARNING("The Fortran interface to KLU is not compatible with ${SUNDIALS_INDEX_TYPE} integers"
+                "Fortran interfaces to KLU will not be built")
+
+ELSE(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+  IF(FCMIX_ENABLE AND F77_FOUND)
+    SET(fsunlinsolklu_SOURCES fsunlinsol_klu.c)
+
+    IF(BUILD_STATIC_LIBS)
+      ADD_LIBRARY(sundials_fsunlinsolklu_static STATIC ${fsunlinsolklu_SOURCES})
+      SET_TARGET_PROPERTIES(sundials_fsunlinsolklu_static
+        PROPERTIES OUTPUT_NAME sundials_fsunlinsolklu CLEAN_DIRECT_OUTPUT 1)
+      INSTALL(TARGETS sundials_fsunlinsolklu_static DESTINATION lib)
+    ENDIF(BUILD_STATIC_LIBS)
+
+    IF(BUILD_SHARED_LIBS)
+      ADD_LIBRARY(sundials_fsunlinsolklu_shared ${fsunlinsolklu_SOURCES})
+
+      # fsunlinsolklu depends on fnvecserial, fsunmatrixsparse, sunlinsolklu
+      TARGET_LINK_LIBRARIES(sundials_fsunlinsolklu_shared
+        sundials_fnvecserial_shared
+        sundials_fsunmatrixsparse_shared
+        sundials_sunlinsolklu_shared)
+
+      SET_TARGET_PROPERTIES(sundials_fsunlinsolklu_shared
+        PROPERTIES OUTPUT_NAME sundials_fsunlinsolklu CLEAN_DIRECT_OUTPUT 1)
+      SET_TARGET_PROPERTIES(sundials_fsunlinsolklu_shared 
+        PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+      INSTALL(TARGETS sundials_fsunlinsolklu_shared DESTINATION lib)
+    ENDIF(BUILD_SHARED_LIBS)
+
+  ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+ENDIF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_KLU module")
diff --git a/src/sunlinsol_klu/README b/src/sunlinsol_klu/README
new file mode 100644
index 0000000..087363b
--- /dev/null
+++ b/src/sunlinsol_klu/README
@@ -0,0 +1,40 @@
+                     SUNLINSOL_KLU
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+KLU implementation of the SUNLINSOL module for SUNDIALS. 
+
+SUNLINSOL_KLU defines the content field of SUNMatrix to be a structure 
+containing X, along with a long integer for any error flag that arises in
+the factorization process.
+
+SUNLINSOL_KLU defines N macros to provide access to the content of 
+a KLU SUNLinearSolver, and constructor for the KLU SUNLinearSolver
+interface, in addition to implementation of all linear solver
+operations defined by the generic SUNLINSOL module in the table 
+of operations.
+
+
+A. Documentation
+----------------
+
+The KLU SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_klu/fsunlinsol_klu.c b/src/sunlinsol_klu/fsunlinsol_klu.c
new file mode 100644
index 0000000..2a193a1
--- /dev/null
+++ b/src/sunlinsol_klu/fsunlinsol_klu.c
@@ -0,0 +1,161 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_klu.h) contains the
+ * implementation needed for the Fortran initialization of klu
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_klu.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNKLU_INIT(int *code, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNKLU(F2C_CVODE_vec, F2C_CVODE_matrix);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNKLU(F2C_IDA_vec, F2C_IDA_matrix);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNKLU(F2C_KINSOL_vec, F2C_KINSOL_matrix);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNKLU(F2C_ARKODE_vec, F2C_ARKODE_matrix);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNKLU_REINIT(int *code, long int *NNZ, int *reinit_type, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    *ier = SUNKLUReInit(F2C_CVODE_linsol, F2C_CVODE_matrix,
+                        *NNZ, *reinit_type);
+    break;
+  case FCMIX_IDA:
+    *ier = SUNKLUReInit(F2C_IDA_linsol, F2C_IDA_matrix,
+                        *NNZ, *reinit_type);
+    break;
+  case FCMIX_KINSOL:
+    *ier = SUNKLUReInit(F2C_KINSOL_linsol, F2C_KINSOL_matrix,
+                        *NNZ, *reinit_type);
+    break;
+  case FCMIX_ARKODE:
+    *ier = SUNKLUReInit(F2C_ARKODE_linsol, F2C_ARKODE_matrix,
+                        *NNZ, *reinit_type);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNKLU_SETORDERING(int *code, int *ordering_choice, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    *ier = SUNKLUSetOrdering(F2C_CVODE_linsol, *ordering_choice);
+    break;
+  case FCMIX_IDA:
+    *ier = SUNKLUSetOrdering(F2C_IDA_linsol, *ordering_choice);
+    break;
+  case FCMIX_KINSOL:
+    *ier = SUNKLUSetOrdering(F2C_KINSOL_linsol, *ordering_choice);
+    break;
+  case FCMIX_ARKODE:
+    *ier = SUNKLUSetOrdering(F2C_ARKODE_linsol, *ordering_choice);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSKLU_INIT(int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNKLU(F2C_ARKODE_vec, 
+                               F2C_ARKODE_mass_matrix);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
+void FSUNMASSKLU_REINIT(long int *NNZ, int *reinit_type, int *ier)
+{
+  *ier = 0;
+  *ier = SUNKLUReInit(F2C_ARKODE_mass_sol, F2C_ARKODE_mass_matrix,
+                      *NNZ, *reinit_type);
+}
+
+
+void FSUNMASSKLU_SETORDERING(int *ordering_choice, int *ier)
+{
+  *ier = 0;
+  *ier = SUNKLUSetOrdering(F2C_ARKODE_mass_sol, *ordering_choice);
+}
diff --git a/src/sunlinsol_klu/fsunlinsol_klu.h b/src/sunlinsol_klu/fsunlinsol_klu.h
new file mode 100644
index 0000000..c5647d8
--- /dev/null
+++ b/src/sunlinsol_klu/fsunlinsol_klu.h
@@ -0,0 +1,85 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_klu.c) contains the
+ * definitions needed for the initialization of klu
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_KLU_H
+#define _FSUNLINSOL_KLU_H
+
+#include <sunlinsol/sunlinsol_klu.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNKLU_INIT            SUNDIALS_F77_FUNC(fsunkluinit,        FSUNKLUINIT)
+#define FSUNKLU_REINIT          SUNDIALS_F77_FUNC(fsunklureinit,      FSUNKLUREINIT)
+#define FSUNKLU_SETORDERING     SUNDIALS_F77_FUNC(fsunklusetordering, FSUNKLUSETORDERING)
+#define FSUNMASSKLU_INIT        SUNDIALS_F77_FUNC(fsunmasskluinit,        FSUNMASSKLUINIT)
+#define FSUNMASSKLU_REINIT      SUNDIALS_F77_FUNC(fsunmassklureinit,      FSUNMASSKLUREINIT)
+#define FSUNMASSKLU_SETORDERING SUNDIALS_F77_FUNC(fsunmassklusetordering, FSUNMASSKLUSETORDERING)
+#else
+#define FSUNKLU_INIT            fsunkluinit_
+#define FSUNKLU_REINIT          fsunklureinit_
+#define FSUNKLU_SETORDERING     fsunklusetordering_
+#define FSUNMASSKLU_INIT        fsunmasskluinit_
+#define FSUNMASSKLU_REINIT      fsunmassklureinit_
+#define FSUNMASSKLU_SETORDERING fsunmassklusetordering_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNKLU_INIT - initializes klu linear solver for main problem
+ * FSUNKLU_REINIT - reinitializes klu linear solver for main problem
+ * FSUNKLU_SETORDERING - sets the ordering choice used by KLU for main problem
+ * FSUNMASSKLU_INIT - initializes klu linear solver for mass matrix solve
+ * FSUNMASSKLU_REINIT - reinitializes klu linear solver for mass matrix solve
+ * FSUNMASSKLU_SETORDERING - sets the ordering choice used by KLU for mass matrix solve
+ */
+
+void FSUNKLU_INIT(int *code, int *ier);
+void FSUNKLU_REINIT(int *code, long int *NNZ, 
+                    int *reinit_type, int *ier);
+void FSUNKLU_SETORDERING(int *code, int *ordering,
+                         int *ier);
+void FSUNMASSKLU_INIT(int *ier);
+void FSUNMASSKLU_REINIT(long int *NNZ, 
+                        int *reinit_type, int *ier);
+void FSUNMASSKLU_SETORDERING(int *ordering, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_klu/sunlinsol_klu.c b/src/sunlinsol_klu/sunlinsol_klu.c
new file mode 100644
index 0000000..eb3ed5c
--- /dev/null
+++ b/src/sunlinsol_klu/sunlinsol_klu.c
@@ -0,0 +1,445 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on codes <solver>_klu.c, written by Carol Woodward @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the KLU implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_klu.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO      RCONST(0.0)
+#define ONE       RCONST(1.0)
+#define TWO       RCONST(2.0)
+#define TWOTHIRDS RCONST(0.666666666666666666666666666666667)
+
+/* Private function prototypes */
+sunindextype GlobalVectorLength_KLU(N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * KLU solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define KLU_CONTENT(S)     ( (SUNLinearSolverContent_KLU)(S->content) )
+#define LASTFLAG(S)        ( KLU_CONTENT(S)->last_flag )
+#define FIRSTFACTORIZE(S)  ( KLU_CONTENT(S)->first_factorize )
+#define SYMBOLIC(S)        ( KLU_CONTENT(S)->symbolic )
+#define NUMERIC(S)         ( KLU_CONTENT(S)->numeric )
+#define COMMON(S)          ( KLU_CONTENT(S)->common )
+#define SOLVE(S)           ( KLU_CONTENT(S)->klu_solver )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new KLU linear solver
+ */
+
+SUNLinearSolver SUNKLU(N_Vector y, SUNMatrix A)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_KLU content;
+  sunindextype MatrixRows, VecLength;
+  int flag;
+  
+  /* Check compatibility with supplied SUNMatrix and N_Vector */
+  if (SUNMatGetID(A) != SUNMATRIX_SPARSE)
+    return(NULL);
+  if (SUNSparseMatrix_Rows(A) != SUNSparseMatrix_Columns(A))
+    return(NULL);
+  MatrixRows = SUNSparseMatrix_Rows(A);
+  if ( (N_VGetVectorID(y) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_PTHREADS) )
+    return(NULL);
+
+  /* optimally this function would be replaced with a generic N_Vector routine */
+  VecLength = GlobalVectorLength_KLU(y);
+  if (MatrixRows != VecLength)
+    return(NULL);
+  
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_KLU;
+  ops->initialize        = SUNLinSolInitialize_KLU;
+  ops->setup             = SUNLinSolSetup_KLU;
+  ops->solve             = SUNLinSolSolve_KLU;
+  ops->lastflag          = SUNLinSolLastFlag_KLU;
+  ops->space             = SUNLinSolSpace_KLU;
+  ops->free              = SUNLinSolFree_KLU;
+  ops->setatimes         = NULL;
+  ops->setpreconditioner = NULL;
+  ops->setscalingvectors = NULL;
+  ops->numiters          = NULL;
+  ops->resnorm           = NULL;
+  ops->resid             = NULL;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_KLU) malloc(sizeof(struct _SUNLinearSolverContent_KLU));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->last_flag = 0;
+  content->first_factorize = 1;
+#if defined(SUNDIALS_INT64_T)
+  if (SUNSparseMatrix_SparseType(A) == CSC_MAT) {
+    content->klu_solver = &klu_l_solve;
+  } else {
+    content->klu_solver = &klu_l_tsolve;
+  }
+#elif defined(SUNDIALS_INT32_T)
+  if (SUNSparseMatrix_SparseType(A) == CSC_MAT) {
+    content->klu_solver = &klu_solve;
+  } else {
+    content->klu_solver = &klu_tsolve;
+  }
+#else  /* incompatible sunindextype for KLU */
+#error  Incompatible sunindextype for KLU
+#endif
+  content->symbolic = NULL;
+  content->numeric = NULL;
+  flag = sun_klu_defaults(&(content->common));
+  if (flag == 0) { free(content); free(ops); free(S); return(NULL); }
+  (content->common).ordering = SUNKLU_ORDERING_DEFAULT;
+  
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to reinitialize a KLU linear solver
+ */
+
+int SUNKLUReInit(SUNLinearSolver S, SUNMatrix A,
+                 sunindextype nnz, int reinit_type)
+{
+  sunindextype n;
+  int type;
+  
+  /* Check for non-NULL SUNLinearSolver */
+  if ((S == NULL) || (A == NULL)) 
+    return(SUNLS_MEM_NULL);
+
+  /* Check for valid SUNMatrix */
+  if (SUNMatGetID(A) != SUNMATRIX_SPARSE)
+    return(SUNLS_ILL_INPUT);
+
+  /* Check for valid reinit_type */
+  if ((reinit_type != 1) && (reinit_type != 2))
+    return(SUNLS_ILL_INPUT);
+
+  /* Perform re-initialization */ 
+  if (reinit_type == 1) {
+
+    /* Get size/type of current matrix */
+    n = SUNSparseMatrix_Rows(A);
+    type = SUNSparseMatrix_SparseType(A);
+    
+    /* Destroy previous matrix */
+    SUNMatDestroy(A);
+
+    /* Create new sparse matrix */
+    A = SUNSparseMatrix(n, n, nnz, type);
+    if (A == NULL) return(SUNLS_MEM_FAIL);
+    
+  }
+
+  /* Free the prior factorazation and reset for first factorization */
+  if( SYMBOLIC(S) != NULL)
+    sun_klu_free_symbolic(&SYMBOLIC(S), &COMMON(S));
+  if( NUMERIC(S) != NULL)
+    sun_klu_free_numeric(&NUMERIC(S), &COMMON(S));
+  FIRSTFACTORIZE(S) = 1;
+
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to set the ordering type for a KLU linear solver
+ */
+
+int SUNKLUSetOrdering(SUNLinearSolver S, int ordering_choice)
+{
+  /* Check for legal ordering_choice */ 
+  if ((ordering_choice < 0) || (ordering_choice > 2))
+    return(SUNLS_ILL_INPUT);
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set ordering_choice */
+  COMMON(S).ordering = ordering_choice;
+
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_KLU(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_DIRECT);
+}
+
+
+int SUNLinSolInitialize_KLU(SUNLinearSolver S)
+{
+  /* Force factorization */
+  FIRSTFACTORIZE(S) = 1;
+ 
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_KLU(SUNLinearSolver S, SUNMatrix A)
+{
+  int retval;
+  realtype uround_twothirds;
+  
+  uround_twothirds = SUNRpowerR(UNIT_ROUNDOFF,TWOTHIRDS);
+
+  /* Ensure that A is a sparse matrix */
+  if (SUNMatGetID(A) != SUNMATRIX_SPARSE) {
+    LASTFLAG(S) = SUNLS_ILL_INPUT;
+    return(LASTFLAG(S));
+  }
+  
+  /* On first decomposition, get the symbolic factorization */ 
+  if (FIRSTFACTORIZE(S)) {
+
+    /* Perform symbolic analysis of sparsity structure */
+    if (SYMBOLIC(S)) 
+      sun_klu_free_symbolic(&SYMBOLIC(S), &COMMON(S));
+    SYMBOLIC(S) = sun_klu_analyze(SUNSparseMatrix_NP(A), 
+                                  SUNSparseMatrix_IndexPointers(A), 
+                                  SUNSparseMatrix_IndexValues(A), 
+                                  &COMMON(S));
+    if (SYMBOLIC(S) == NULL) {
+      LASTFLAG(S) = SUNLS_PACKAGE_FAIL_UNREC;
+      return(LASTFLAG(S));
+    }
+
+    /* ------------------------------------------------------------
+       Compute the LU factorization of the matrix
+       ------------------------------------------------------------*/
+    if(NUMERIC(S)) 
+      sun_klu_free_numeric(&NUMERIC(S), &COMMON(S));
+    NUMERIC(S) = sun_klu_factor(SUNSparseMatrix_IndexPointers(A), 
+                                SUNSparseMatrix_IndexValues(A), 
+                                SUNSparseMatrix_Data(A), 
+                                SYMBOLIC(S), 
+                                &COMMON(S));
+    if (NUMERIC(S) == NULL) {
+      LASTFLAG(S) = SUNLS_PACKAGE_FAIL_UNREC;
+      return(LASTFLAG(S));
+    }
+
+    FIRSTFACTORIZE(S) = 0;
+
+  } else {   /* not the first decomposition, so just refactor */
+
+    retval = sun_klu_refactor(SUNSparseMatrix_IndexPointers(A), 
+                              SUNSparseMatrix_IndexValues(A), 
+                              SUNSparseMatrix_Data(A), 
+                              SYMBOLIC(S),
+                              NUMERIC(S),
+                              &COMMON(S));
+    if (retval == 0) {
+      LASTFLAG(S) = SUNLS_PACKAGE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    
+    /*-----------------------------------------------------------
+      Check if a cheap estimate of the reciprocal of the condition 
+      number is getting too small.  If so, delete
+      the prior numeric factorization and recompute it.
+      -----------------------------------------------------------*/
+    
+    retval = sun_klu_rcond(SYMBOLIC(S), NUMERIC(S), &COMMON(S));
+    if (retval == 0) {
+      LASTFLAG(S) = SUNLS_PACKAGE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+
+    if ( COMMON(S).rcond < uround_twothirds ) {
+      
+      /* Condition number may be getting large.  
+	 Compute more accurate estimate */
+      retval = sun_klu_condest(SUNSparseMatrix_IndexPointers(A), 
+                               SUNSparseMatrix_Data(A), 
+                               SYMBOLIC(S),
+                               NUMERIC(S),
+                               &COMMON(S));
+      if (retval == 0) {
+	LASTFLAG(S) = SUNLS_PACKAGE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+      
+      if ( COMMON(S).condest > (ONE/uround_twothirds) ) {
+
+	/* More accurate estimate also says condition number is 
+	   large, so recompute the numeric factorization */
+	sun_klu_free_numeric(&NUMERIC(S), &COMMON(S));
+	NUMERIC(S) = sun_klu_factor(SUNSparseMatrix_IndexPointers(A), 
+                                    SUNSparseMatrix_IndexValues(A), 
+                                    SUNSparseMatrix_Data(A), 
+                                    SYMBOLIC(S), 
+                                    &COMMON(S));
+	if (NUMERIC(S) == NULL) {
+	  LASTFLAG(S) = SUNLS_PACKAGE_FAIL_UNREC;
+          return(LASTFLAG(S));
+	}
+      }
+      
+    }
+  }
+
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSolve_KLU(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                       N_Vector b, realtype tol)
+{
+  int flag;
+  realtype *xdata;
+  
+  /* check for valid inputs */
+  if ( (A == NULL) || (S == NULL) || (x == NULL) || (b == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* copy b into x */
+  N_VScale(ONE, b, x);
+
+  /* access x data array */
+  xdata = N_VGetArrayPointer(x);
+  if (xdata == NULL) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+  
+  /* Call KLU to solve the linear system */
+  flag = SOLVE(S)(SYMBOLIC(S), NUMERIC(S), 
+                  SUNSparseMatrix_NP(A), 1, xdata, 
+                  &COMMON(S));
+  if (flag == 0) {
+    LASTFLAG(S) = SUNLS_PACKAGE_FAIL_REC;
+    return(LASTFLAG(S));
+  }
+
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+long int SUNLinSolLastFlag_KLU(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_KLU(SUNLinearSolver S, 
+                       long int *lenrwLS, 
+                       long int *leniwLS)
+{
+  /* since the klu structures are opaque objects, we 
+     omit those from these results */
+  *leniwLS = 2;
+  *lenrwLS = 0;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_KLU(SUNLinearSolver S)
+{
+  /* return with success if already freed */
+  if (S == NULL)
+    return(SUNLS_SUCCESS);
+  
+  /* delete items from the contents structure (if it exists) */
+  if (S->content) {
+    if (NUMERIC(S))
+      sun_klu_free_numeric(&NUMERIC(S), &COMMON(S));
+    if (SYMBOLIC(S))
+      sun_klu_free_symbolic(&SYMBOLIC(S), &COMMON(S));
+    free(S->content);  
+    S->content = NULL;
+  }
+  
+  /* delete generic structures */
+  if (S->ops) {
+    free(S->ops);  
+    S->ops = NULL;
+  }
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+/* Inefficient kludge for determining the number of entries in a N_Vector 
+   object (replace if such a routine is ever added to the N_Vector API).
+
+   Returns "-1" on an error. */
+sunindextype GlobalVectorLength_KLU(N_Vector y)
+{
+  realtype len;
+  N_Vector tmp = NULL;
+  tmp = N_VClone(y);
+  if (tmp == NULL)  return(-1);
+  N_VConst(ONE, tmp);
+  len = N_VDotProd(tmp, tmp);
+  N_VDestroy(tmp);
+  return( (sunindextype) len );
+}
diff --git a/src/sunlinsol_lapackband/CMakeLists.txt b/src/sunlinsol_lapackband/CMakeLists.txt
new file mode 100644
index 0000000..f1ce8e2
--- /dev/null
+++ b/src/sunlinsol_lapackband/CMakeLists.txt
@@ -0,0 +1,107 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the LapackBand SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_LAPACKBAND\n\")")
+
+# Add variable sunlinsollapackband_SOURCES with the sources for the SUNLINSOLLAPACKBAND lib
+SET(sunlinsollapackband_SOURCES sunlinsol_lapackband.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLLAPACKBAND library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  )
+
+# Add variable sunlinsollapackband_HEADERS with the
+# exported SUNLINSOLLAPACKBAND header files
+SET(sunlinsollapackband_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_lapackband.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLLAPACKBAND library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLLAPACKBAND library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsollapackband_static STATIC ${sunlinsollapackband_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsollapackband_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsollapackband CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsollapackband_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLLAPACKBAND library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLLAPACKBAND library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsollapackband_shared SHARED ${sunlinsollapackband_SOURCES} ${shared_SOURCES})
+
+  # sunlinsollapackband depends on sunmatrixband and LAPACK
+  TARGET_LINK_LIBRARIES(sundials_sunlinsollapackband_shared
+    sundials_sunmatrixband_shared
+    ${LAPACK_LIBRARIES})
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsollapackband_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsollapackband CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsollapackband_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsollapackband_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLLAPACKBAND header files
+INSTALL(FILES ${sunlinsollapackband_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLLAPACKBAND library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsollapackband_SOURCES fsunlinsol_lapackband.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsollapackband_static STATIC ${fsunlinsollapackband_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsollapackband_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsollapackband CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsollapackband_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsollapackband_shared ${fsunlinsollapackband_SOURCES})
+
+    # fsunlinsollapackband depends on fnvecserial, fsunmatrixband, sunlinsollapackband
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsollapackband_shared
+      sundials_fnvecserial_shared
+      sundials_fsunmatrixband_shared
+      sundials_sunlinsollapackband_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsollapackband_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsollapackband CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsollapackband_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsollapackband_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_LAPACKBAND module")
diff --git a/src/sunlinsol_lapackband/README b/src/sunlinsol_lapackband/README
new file mode 100644
index 0000000..071b5d9
--- /dev/null
+++ b/src/sunlinsol_lapackband/README
@@ -0,0 +1,37 @@
+                     SUNLINSOL_LAPACKBAND
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+LAPACK band implementation of the SUNLINSOL module for SUNDIALS. 
+
+SUNLINSOL_LAPACKBAND defines the content field of SUNMatrix to be a structure 
+containing an integer 'pivots' array, along with a long integer for
+any error flag that arises in the factorization process.
+
+SUNLINSOL_LAPACKBAND implements all linear solver operations defined
+by the generic SUNLINSOL module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The LAPACK band SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_lapackband/fsunlinsol_lapackband.c b/src/sunlinsol_lapackband/fsunlinsol_lapackband.c
new file mode 100644
index 0000000..1d49ac7
--- /dev/null
+++ b/src/sunlinsol_lapackband/fsunlinsol_lapackband.c
@@ -0,0 +1,98 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_lapackband.h) contains the
+ * implementation needed for the Fortran initialization of LAPACK 
+ * band linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_lapackband.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNLAPACKBAND_INIT(int *code, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNLapackBand(F2C_CVODE_vec, F2C_CVODE_matrix);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNLapackBand(F2C_IDA_vec, F2C_IDA_matrix);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNLapackBand(F2C_KINSOL_vec, F2C_KINSOL_matrix);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNLapackBand(F2C_ARKODE_vec, F2C_ARKODE_matrix);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSLAPACKBAND_INIT(int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNLapackBand(F2C_ARKODE_vec, 
+                                      F2C_ARKODE_mass_matrix);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
diff --git a/src/sunlinsol_lapackband/fsunlinsol_lapackband.h b/src/sunlinsol_lapackband/fsunlinsol_lapackband.h
new file mode 100644
index 0000000..ea11865
--- /dev/null
+++ b/src/sunlinsol_lapackband/fsunlinsol_lapackband.h
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_lapackband.c) contains the
+ * definitions needed for the initialization of LAPACK band
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_LAPBAND_H
+#define _FSUNLINSOL_LAPBAND_H
+
+#include <sunlinsol/sunlinsol_lapackband.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNLAPACKBAND_INIT     SUNDIALS_F77_FUNC(fsunlapackbandinit, FSUNLAPACKBANDINIT)
+#define FSUNMASSLAPACKBAND_INIT SUNDIALS_F77_FUNC(fsunmasslapackbandinit, FSUNMASSLAPACKBANDINIT)
+#else
+#define FSUNLAPACKBAND_INIT     fsunlapackbandinit_
+#define FSUNMASSLAPACKBAND_INIT fsunmasslapackbandinit_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNLAPACKBAND_INIT - initializes LAPACK band linear solver for main problem
+ * FSUNMASSLAPACKBAND_INIT - initializes LAPACK band linear solver for mass matrix solve
+ */
+
+void FSUNLAPACKBAND_INIT(int *code, int *ier);
+void FSUNMASSLAPACKBAND_INIT(int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_lapackband/sunlinsol_lapackband.c b/src/sunlinsol_lapackband/sunlinsol_lapackband.c
new file mode 100644
index 0000000..ecc6bbf
--- /dev/null
+++ b/src/sunlinsol_lapackband/sunlinsol_lapackband.c
@@ -0,0 +1,275 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on codes <solver>_lapack.c by: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the LAPACK band 
+ * implementation of the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_lapackband.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO  RCONST(0.0)
+#define ONE   RCONST(1.0)
+
+/* Private function prototypes */
+sunindextype GlobalVectorLength_LapBand(N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * Band solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define LAPACKBAND_CONTENT(S) ( (SUNLinearSolverContent_LapackBand)(S->content) )
+#define PIVOTS(S)             ( LAPACKBAND_CONTENT(S)->pivots )
+#define LASTFLAG(S)           ( LAPACKBAND_CONTENT(S)->last_flag )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new LAPACK band linear solver
+ */
+
+SUNLinearSolver SUNLapackBand(N_Vector y, SUNMatrix A)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_LapackBand content;
+  sunindextype MatrixRows, VecLength;
+  
+  /* Check compatibility with supplied SUNMatrix and N_Vector */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND)
+    return(NULL);
+  if (SUNBandMatrix_Rows(A) != SUNBandMatrix_Columns(A))
+    return(NULL);
+  MatrixRows = SUNBandMatrix_Rows(A);
+  if ( (N_VGetVectorID(y) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_PTHREADS) )
+    return(NULL);
+
+  /* optimally this function would be replaced with a generic N_Vector routine */
+  VecLength = GlobalVectorLength_LapBand(y);
+  if (MatrixRows != VecLength)
+    return(NULL);
+  
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_LapackBand;
+  ops->initialize        = SUNLinSolInitialize_LapackBand;
+  ops->setup             = SUNLinSolSetup_LapackBand;
+  ops->solve             = SUNLinSolSolve_LapackBand;
+  ops->lastflag          = SUNLinSolLastFlag_LapackBand;
+  ops->space             = SUNLinSolSpace_LapackBand;
+  ops->free              = SUNLinSolFree_LapackBand;
+  ops->setatimes         = NULL;
+  ops->setpreconditioner = NULL;
+  ops->setscalingvectors = NULL;
+  ops->numiters          = NULL;
+  ops->resnorm           = NULL;
+  ops->resid             = NULL;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_LapackBand) malloc(sizeof(struct _SUNLinearSolverContent_LapackBand));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->N = MatrixRows;
+  content->last_flag = 0;
+  content->pivots = NULL;
+  content->pivots = (sunindextype *) malloc(MatrixRows * sizeof(sunindextype));
+  if (content->pivots == NULL) {
+    free(content); free(ops); free(S); return(NULL);
+  }
+  
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_LapackBand(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_DIRECT);
+}
+
+
+int SUNLinSolInitialize_LapackBand(SUNLinearSolver S)
+{
+  /* all solver-specific memory has already been allocated */
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_LapackBand(SUNLinearSolver S, SUNMatrix A)
+{
+  int n, ml, mu, ldim, ier;
+
+  /* check for valid inputs */
+  if ( (A == NULL) || (S == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* Ensure that A is a band matrix */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND) {
+    LASTFLAG(S) = SUNLS_ILL_INPUT;
+    return(LASTFLAG(S));
+  }
+  
+  /* Call LAPACK to do LU factorization of A */
+  n = SUNBandMatrix_Rows(A);
+  ml = SUNBandMatrix_LowerBandwidth(A);
+  mu = SUNBandMatrix_UpperBandwidth(A);
+  ldim = SUNBandMatrix_LDim(A);
+  xgbtrf_f77(&n, &n, &ml, &mu, SUNBandMatrix_Data(A), 
+	     &ldim, PIVOTS(S), &ier);
+  
+  LASTFLAG(S) = (long int) ier;
+  if (ier > 0) 
+    return(SUNLS_LUFACT_FAIL);
+  if (ier < 0) 
+    return(SUNLS_PACKAGE_FAIL_UNREC);
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSolve_LapackBand(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                              N_Vector b, realtype tol)
+{
+  int n, ml, mu, ldim, one, ier;
+  realtype *xdata;
+  
+  /* check for valid inputs */
+  if ( (A == NULL) || (S == NULL) || (x == NULL) || (b == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* copy b into x */
+  N_VScale(ONE, b, x);
+
+  /* access x data array */
+  xdata = N_VGetArrayPointer(x);
+  if (xdata == NULL) {
+    LASTFLAG(S) = 1;
+    return(LASTFLAG(S));
+  }
+  
+  /* Call LAPACK to solve the linear system */
+  n = SUNBandMatrix_Rows(A);
+  ml = SUNBandMatrix_LowerBandwidth(A);
+  mu = SUNBandMatrix_UpperBandwidth(A);
+  ldim = SUNBandMatrix_LDim(A);
+  one = 1;
+  xgbtrs_f77("N", &n, &ml, &mu, &one, SUNBandMatrix_Data(A), 
+	     &ldim, PIVOTS(S), xdata, &n, &ier, 1);
+  LASTFLAG(S) = (long int) ier;
+  if (ier < 0) 
+    return(SUNLS_PACKAGE_FAIL_UNREC);
+
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+long int SUNLinSolLastFlag_LapackBand(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_LapackBand(SUNLinearSolver S, 
+                              long int *lenrwLS, 
+                              long int *leniwLS)
+{
+  *lenrwLS = 0;
+  *leniwLS = 2 + LAPACKBAND_CONTENT(S)->N;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_LapackBand(SUNLinearSolver S)
+{
+  /* return with success if already freed */
+  if (S == NULL)
+    return(SUNLS_SUCCESS);
+  
+  /* delete items from contents, then delete generic structure */
+  if (S->content) {
+    if (PIVOTS(S)) {
+      free(PIVOTS(S));
+      PIVOTS(S) = NULL;
+    }
+    free(S->content);  
+    S->content = NULL;
+  }
+ 
+  if (S->ops) {
+    free(S->ops);  
+    S->ops = NULL;
+  }
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+/* Inefficient kludge for determining the number of entries in a N_Vector 
+   object (replace if such a routine is ever added to the N_Vector API).
+
+   Returns "-1" on an error. */
+sunindextype GlobalVectorLength_LapBand(N_Vector y)
+{
+  realtype len;
+  N_Vector tmp = NULL;
+  tmp = N_VClone(y);
+  if (tmp == NULL)  return(-1);
+  N_VConst(ONE, tmp);
+  len = N_VDotProd(tmp, tmp);
+  N_VDestroy(tmp);
+  return( (sunindextype) len );
+}
diff --git a/src/sunlinsol_lapackdense/CMakeLists.txt b/src/sunlinsol_lapackdense/CMakeLists.txt
new file mode 100644
index 0000000..809392a
--- /dev/null
+++ b/src/sunlinsol_lapackdense/CMakeLists.txt
@@ -0,0 +1,113 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the LapackDense SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_LAPACKDENSE\n\")")
+
+# Add variable sunlinsollapackdense_SOURCES with the sources for
+# the SUNLINSOLLAPACKDENSE lib
+SET(sunlinsollapackdense_SOURCES sunlinsol_lapackdense.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLLAPACKDENSE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  )
+
+# Add variable sunlinsollapackdense_HEADERS with the
+# exported SUNLINSOLLAPACKDENSE header files
+SET(sunlinsollapackdense_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_lapackdense.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLLAPACKDENSE library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLLAPACKDENSE library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsollapackdense_static STATIC ${sunlinsollapackdense_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsollapackdense_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsollapackdense CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsollapackdense_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLLAPACKDENSE library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLLAPACKDENSE library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsollapackdense_shared SHARED ${sunlinsollapackdense_SOURCES} ${shared_SOURCES})
+
+  # sunlinsollapackdense depends on sunmatrixdense and LAPACK
+  TARGET_LINK_LIBRARIES(sundials_sunlinsollapackdense_shared
+    sundials_sunmatrixdense_shared
+    ${LAPACK_LIBRARIES})
+  
+  #	if a blas library was provided, assume LAPACK depends on it
+  IF(BLAS_FOUND)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsollapackdense_shared ${BLAS_LIBRARIES})
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsollapackdense_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsollapackdense CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsollapackdense_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsollapackdense_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLLAPACKDENSE header files
+INSTALL(FILES ${sunlinsollapackdense_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLLAPACKDENSE library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsollapackdense_SOURCES fsunlinsol_lapackdense.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsollapackdense_static STATIC ${fsunlinsollapackdense_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsollapackdense_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsollapackdense CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsollapackdense_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsollapackdense_shared ${fsunlinsollapackdense_SOURCES})
+
+    # fsunlinsollapack depends on fnvecserial, fsunmatrixdense, sunlinsollapackdense
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsollapackdense_shared
+      sundials_fnvecserial_shared
+      sundials_fsunmatrixdense_shared
+      sundials_sunlinsollapackdense_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsollapackdense_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsollapackdense CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsollapackdense_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsollapackdense_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_LAPACKDENSE module")
diff --git a/src/sunlinsol_lapackdense/README b/src/sunlinsol_lapackdense/README
new file mode 100644
index 0000000..afb3b03
--- /dev/null
+++ b/src/sunlinsol_lapackdense/README
@@ -0,0 +1,37 @@
+                     SUNLINSOL_LAPACKDENSE
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+LAPACK dense implementation of the SUNLINSOL module for SUNDIALS. 
+
+SUNLINSOL_LAPACKDENSE defines the content field of SUNMatrix to be a structure 
+containing an integer 'pivots' array, along with a long integer for
+any error flag that arises in the factorization process.
+
+SUNLINSOL_LAPACKDENSE implements all linear solver operations defined
+by the generic SUNLINSOL module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The LAPACK dense SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c b/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c
new file mode 100644
index 0000000..6f367dd
--- /dev/null
+++ b/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.c
@@ -0,0 +1,96 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_lapackdense.h) contains the
+ * implementation needed for the Fortran initialization of LAPACK 
+ * dense linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_lapackdense.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNLAPACKDENSE_INIT(int *code, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNLapackDense(F2C_CVODE_vec, F2C_CVODE_matrix);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNLapackDense(F2C_IDA_vec, F2C_IDA_matrix);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNLapackDense(F2C_KINSOL_vec, F2C_KINSOL_matrix);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNLapackDense(F2C_ARKODE_vec, F2C_ARKODE_matrix);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSLAPACKDENSE_INIT(int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNLapackDense(F2C_ARKODE_vec, 
+                                       F2C_ARKODE_mass_matrix);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
diff --git a/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.h b/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.h
new file mode 100644
index 0000000..40c95c1
--- /dev/null
+++ b/src/sunlinsol_lapackdense/fsunlinsol_lapackdense.h
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_lapackdense.c) contains the
+ * definitions needed for the initialization of LAPACK dense
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_LAPDENSE_H
+#define _FSUNLINSOL_LAPDENSE_H
+
+#include <sunlinsol/sunlinsol_lapackdense.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNLAPACKDENSE_INIT     SUNDIALS_F77_FUNC(fsunlapackdenseinit, FSUNLAPACKDENSEINIT)
+#define FSUNMASSLAPACKDENSE_INIT SUNDIALS_F77_FUNC(fsunmasslapackdenseinit, FSUNMASSLAPACKDENSEINIT)
+#else
+#define FSUNLAPACKDENSE_INIT     fsunlapackdenseinit_
+#define FSUNMASSLAPACKDENSE_INIT fsunmasslapackdenseinit_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNLAPACKDENSE_INIT - initializes LAPACK dense linear solver for main problem
+ * FSUNMASSLAPACKDENSE_INIT - initializes LAPACK dense linear solver for mass matrix solve
+ */
+
+void FSUNLAPACKDENSE_INIT(int *code, int *ier);
+void FSUNMASSLAPACKDENSE_INIT(int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_lapackdense/sunlinsol_lapackdense.c b/src/sunlinsol_lapackdense/sunlinsol_lapackdense.c
new file mode 100644
index 0000000..59e244d
--- /dev/null
+++ b/src/sunlinsol_lapackdense/sunlinsol_lapackdense.c
@@ -0,0 +1,266 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on codes <solver>_lapack.c by: Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the LAPACK dense 
+ * implementation of the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_lapackdense.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO  RCONST(0.0)
+#define ONE   RCONST(1.0)
+
+/* Private function prototypes */
+sunindextype GlobalVectorLength_LapDense(N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * LapackDense solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define LAPACKDENSE_CONTENT(S) ( (SUNLinearSolverContent_LapackDense)(S->content) )
+#define PIVOTS(S)              ( LAPACKDENSE_CONTENT(S)->pivots )
+#define LASTFLAG(S)            ( LAPACKDENSE_CONTENT(S)->last_flag )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new LAPACK dense linear solver
+ */
+
+SUNLinearSolver SUNLapackDense(N_Vector y, SUNMatrix A)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_LapackDense content;
+  sunindextype MatrixRows, VecLength;
+  
+  /* Check compatibility with supplied SUNMatrix and N_Vector */
+  if (SUNMatGetID(A) != SUNMATRIX_DENSE)
+    return(NULL);
+  if (SUNDenseMatrix_Rows(A) != SUNDenseMatrix_Columns(A))
+    return(NULL);
+  MatrixRows = SUNDenseMatrix_Rows(A);
+  if ( (N_VGetVectorID(y) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_PTHREADS) )
+    return(NULL);
+
+  /* optimally this function would be replaced with a generic N_Vector routine */
+  VecLength = GlobalVectorLength_LapDense(y);
+  if (MatrixRows != VecLength)
+    return(NULL);
+  
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_LapackDense;
+  ops->initialize        = SUNLinSolInitialize_LapackDense;
+  ops->setup             = SUNLinSolSetup_LapackDense;
+  ops->solve             = SUNLinSolSolve_LapackDense;
+  ops->lastflag          = SUNLinSolLastFlag_LapackDense;
+  ops->space             = SUNLinSolSpace_LapackDense;
+  ops->free              = SUNLinSolFree_LapackDense;
+  ops->setatimes         = NULL;
+  ops->setpreconditioner = NULL;
+  ops->setscalingvectors = NULL;
+  ops->numiters          = NULL;
+  ops->resnorm           = NULL;
+  ops->resid             = NULL;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_LapackDense)
+    malloc(sizeof(struct _SUNLinearSolverContent_LapackDense));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->N = MatrixRows;
+  content->last_flag = 0;
+  content->pivots = NULL;
+  content->pivots = (sunindextype *) malloc(MatrixRows * sizeof(sunindextype));
+  if (content->pivots == NULL) {
+    free(content); free(ops); free(S); return(NULL);
+  }
+  
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_LapackDense(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_DIRECT);
+}
+
+
+int SUNLinSolInitialize_LapackDense(SUNLinearSolver S)
+{
+  /* all solver-specific memory has already been allocated */
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_LapackDense(SUNLinearSolver S, SUNMatrix A)
+{
+  int n, ier;
+
+  /* check for valid inputs */
+  if ( (A == NULL) || (S == NULL) ) 
+    return(SUNLS_MEM_NULL);
+  
+  /* Ensure that A is a dense matrix */
+  if (SUNMatGetID(A) != SUNMATRIX_DENSE) {
+    LASTFLAG(S) = SUNLS_ILL_INPUT;
+    return(LASTFLAG(S));
+  }
+  
+  /* Call LAPACK to do LU factorization of A */
+  n = SUNDenseMatrix_Rows(A);
+  xgetrf_f77(&n, &n, SUNDenseMatrix_Data(A), &n, PIVOTS(S), &ier);
+  LASTFLAG(S) = (long int) ier;
+  if (ier > 0) 
+    return(SUNLS_LUFACT_FAIL);
+  if (ier < 0) 
+    return(SUNLS_PACKAGE_FAIL_UNREC);
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSolve_LapackDense(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                              N_Vector b, realtype tol)
+{
+  int n, one, ier;
+  realtype *xdata;
+  
+  if ( (A == NULL) || (S == NULL) || (x == NULL) || (b == NULL) ) 
+    return(SUNLS_MEM_NULL);
+
+  /* copy b into x */
+  N_VScale(ONE, b, x);
+
+  /* access x data array */
+  xdata = N_VGetArrayPointer(x);
+  if (xdata == NULL) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+  
+  /* Call LAPACK to solve the linear system */
+  n = SUNDenseMatrix_Rows(A);
+  one = 1;
+  xgetrs_f77("N", &n, &one, SUNDenseMatrix_Data(A), 
+	     &n, PIVOTS(S), xdata, &n, &ier, 1);
+  LASTFLAG(S) = (long int) ier;
+  if (ier < 0) 
+    return(SUNLS_PACKAGE_FAIL_UNREC);
+
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+long int SUNLinSolLastFlag_LapackDense(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_LapackDense(SUNLinearSolver S, 
+                               long int *lenrwLS, 
+                               long int *leniwLS)
+{
+  *lenrwLS = 0;
+  *leniwLS = 2 + LAPACKDENSE_CONTENT(S)->N;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_LapackDense(SUNLinearSolver S)
+{
+  /* return if S is already free */
+  if (S == NULL)
+    return(SUNLS_SUCCESS);
+
+  /* delete items from contents, then delete generic structure */
+  if (S->content) {
+    if (PIVOTS(S)) {
+      free(PIVOTS(S));
+      PIVOTS(S) = NULL;
+    }
+    free(S->content);  
+    S->content = NULL;
+  }
+  if (S->ops) {
+    free(S->ops);  
+    S->ops = NULL;
+  }
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+/* Inefficient kludge for determining the number of entries in a N_Vector 
+   object (replace if such a routine is ever added to the N_Vector API).
+
+   Returns "-1" on an error. */
+sunindextype GlobalVectorLength_LapDense(N_Vector y)
+{
+  realtype len;
+  N_Vector tmp = NULL;
+  tmp = N_VClone(y);
+  if (tmp == NULL)  return(-1);
+  N_VConst(ONE, tmp);
+  len = N_VDotProd(tmp, tmp);
+  N_VDestroy(tmp);
+  return( (sunindextype) len );
+}
diff --git a/src/sunlinsol_pcg/CMakeLists.txt b/src/sunlinsol_pcg/CMakeLists.txt
new file mode 100644
index 0000000..f1ec24a
--- /dev/null
+++ b/src/sunlinsol_pcg/CMakeLists.txt
@@ -0,0 +1,107 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the PCG SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_PCG\n\")")
+
+# Add variable sunlinsolpcg_SOURCES with the sources for the SUNLINSOLPCG lib
+SET(sunlinsolpcg_SOURCES sunlinsol_pcg.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLPCG library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  )
+
+# Add variable sunlinsolpcg_HEADERS with the exported SUNLINSOLPCG header files
+SET(sunlinsolpcg_HEADERS
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_pcg.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLPCG library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLPCG library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolpcg_static STATIC ${sunlinsolpcg_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolpcg_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolpcg CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolpcg_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLPCG library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLPCG library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolpcg_shared SHARED ${sunlinsolpcg_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsolpcg_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolpcg_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolpcg CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolpcg_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolpcg_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLPCG header files
+INSTALL(FILES ${sunlinsolpcg_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLPCG library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsolpcg_SOURCES fsunlinsol_pcg.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolpcg_static STATIC ${fsunlinsolpcg_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolpcg_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolpcg CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsolpcg_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolpcg_shared ${fsunlinsolpcg_SOURCES})
+
+    # fsunlinsolpcg dependes on fnvecserial and sunlinsolpcg_shared
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsolpcg_shared
+      sundials_fnvecserial_shared
+      sundials_sunlinsolpcg_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolpcg_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolpcg CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolpcg_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsolpcg_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_PCG module")
diff --git a/src/sunlinsol_pcg/README b/src/sunlinsol_pcg/README
new file mode 100644
index 0000000..675347c
--- /dev/null
+++ b/src/sunlinsol_pcg/README
@@ -0,0 +1,40 @@
+                     SUNLINSOL_PCG
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Preconditioned conjugate gradient implementation of the SUNLINSOL 
+module for SUNDIALS.  
+
+SUNLINSOL_PCG defines the content field of SUNMatrix to be a structure 
+containing X, along with a long integer for any error flag that arises
+in the linear solver routines.
+
+SUNLINSOL_PCG defines a constructor for the PCG SUNLinearSolver and a 
+routine to enable/disable preconditioning, in addition to
+implementation of all linear solver operations defined by the generic
+SUNLINSOL module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The PCG SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_pcg/fsunlinsol_pcg.c b/src/sunlinsol_pcg/fsunlinsol_pcg.c
new file mode 100644
index 0000000..a4a6902
--- /dev/null
+++ b/src/sunlinsol_pcg/fsunlinsol_pcg.c
@@ -0,0 +1,195 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_pcg.h) contains the
+ * implementation needed for the Fortran initialization of PCG
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_pcg.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNPCG_INIT(int *code, int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNPCG(F2C_CVODE_vec, *pretype, *maxl);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNPCG(F2C_IDA_vec, *pretype, *maxl);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNPCG(F2C_KINSOL_vec, *pretype, *maxl);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNPCG(F2C_ARKODE_vec, *pretype, *maxl);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNPCG_SETPRECTYPE(int *code, int *pretype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetPrecType(F2C_CVODE_linsol, *pretype);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetPrecType(F2C_IDA_linsol, *pretype);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetPrecType(F2C_KINSOL_linsol, *pretype);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetPrecType(F2C_ARKODE_linsol, *pretype);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNPCG_SETMAXL(int *code, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetMaxl(F2C_CVODE_linsol, *maxl);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetMaxl(F2C_IDA_linsol, *maxl);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetMaxl(F2C_KINSOL_linsol, *maxl);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNPCGSetMaxl(F2C_ARKODE_linsol, *maxl);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSPCG_INIT(int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNPCG(F2C_ARKODE_vec, *pretype, *maxl);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
+void FSUNMASSPCG_SETPRECTYPE(int *pretype, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNPCGSetPrecType(F2C_ARKODE_mass_sol, *pretype);
+}
+
+
+void FSUNMASSPCG_SETMAXL(int *maxl, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNPCGSetMaxl(F2C_ARKODE_mass_sol, *maxl);
+}
diff --git a/src/sunlinsol_pcg/fsunlinsol_pcg.h b/src/sunlinsol_pcg/fsunlinsol_pcg.h
new file mode 100644
index 0000000..441d8bb
--- /dev/null
+++ b/src/sunlinsol_pcg/fsunlinsol_pcg.h
@@ -0,0 +1,84 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_pcg.c) contains the
+ * definitions needed for the initialization of PCG
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_PCG_H
+#define _FSUNLINSOL_PCG_H
+
+#include <sunlinsol/sunlinsol_pcg.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNPCG_INIT            SUNDIALS_F77_FUNC(fsunpcginit,            FSUNPCGINIT)
+#define FSUNPCG_SETPRECTYPE     SUNDIALS_F77_FUNC(fsunpcgsetprectype,     FSUNPCGSETPRECTYPE)
+#define FSUNPCG_SETMAXL         SUNDIALS_F77_FUNC(fsunpcgsetmaxl,         FSUNPCGSETMAXL)
+#define FSUNMASSPCG_INIT        SUNDIALS_F77_FUNC(fsunmasspcginit,        FSUNMASSPCGINIT)
+#define FSUNMASSPCG_SETPRECTYPE SUNDIALS_F77_FUNC(fsunmasspcgsetprectype, FSUNMASSPCGSETPRECTYPE)
+#define FSUNMASSPCG_SETMAXL     SUNDIALS_F77_FUNC(fsunmasspcgsetmaxl,     FSUNMASSPCGSETMAXL)
+#else
+#define FSUNPCG_INIT            fsunpcginit_
+#define FSUNPCG_SETPRECTYPE     fsunpcgsetprectype_
+#define FSUNPCG_SETMAXL         fsunpcgsetmaxl_
+#define FSUNMASSPCG_INIT        fsunmasspcginit_
+#define FSUNMASSPCG_SETPRECTYPE fsunmasspcgsetprectype_
+#define FSUNMASSPCG_SETMAXL     fsunmasspcgsetmaxl_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNPCG_INIT - initializes PCG linear solver for main problem
+ * FSUNPCG_SETPRECTYPE - sets preconditioning type for main problem
+ * FSUNPCG_SETMAXL - sets the max number of iterations for main problem
+ *
+ * FSUNMASSPCG_INIT - initializes PCG linear solver for mass matrix solve
+ * FSUNMASSPCG_SETPRECTYPE - sets preconditioning type for mass matrix solve
+ * FSUNMASSPCG_SETMAXL - sets the max number of iterations for mass matrix solve
+ */
+
+void FSUNPCG_INIT(int *code, int *pretype, int *maxl, int *ier);
+void FSUNPCG_SETPRECTYPE(int *code, int *pretype, int *ier);
+void FSUNPCG_SETMAXL(int *code, int *maxl, int *ier);
+
+void FSUNMASSPCG_INIT(int *pretype, int *maxl, int *ier);
+void FSUNMASSPCG_SETPRECTYPE(int *pretype, int *ier);
+void FSUNMASSPCG_SETMAXL(int *maxl, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_pcg/sunlinsol_pcg.c b/src/sunlinsol_pcg/sunlinsol_pcg.c
new file mode 100644
index 0000000..9b2ea31
--- /dev/null
+++ b/src/sunlinsol_pcg/sunlinsol_pcg.c
@@ -0,0 +1,470 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds, Ashley Crawford @ SMU
+ * Based on sundials_pcg.c code, written by Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the PCG implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_pcg.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * PCG solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define PCG_CONTENT(S)  ( (SUNLinearSolverContent_PCG)(S->content) )
+#define PRETYPE(S)      ( PCG_CONTENT(S)->pretype )
+#define LASTFLAG(S)     ( PCG_CONTENT(S)->last_flag )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new PCG linear solver
+ */
+
+SUNLinearSolver SUNPCG(N_Vector y, int pretype, int maxl)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_PCG content;
+  
+  /* check for legal pretype and maxl values; if illegal use defaults */
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH))
+    pretype = PREC_NONE;
+  if (maxl <= 0)
+    maxl = SUNPCG_MAXL_DEFAULT;
+
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_PCG;
+  ops->setatimes         = SUNLinSolSetATimes_PCG;
+  ops->setpreconditioner = SUNLinSolSetPreconditioner_PCG;
+  ops->setscalingvectors = SUNLinSolSetScalingVectors_PCG;
+  ops->initialize        = SUNLinSolInitialize_PCG;
+  ops->setup             = SUNLinSolSetup_PCG;
+  ops->solve             = SUNLinSolSolve_PCG;
+  ops->numiters          = SUNLinSolNumIters_PCG;
+  ops->resnorm           = SUNLinSolResNorm_PCG;
+  ops->resid             = SUNLinSolResid_PCG;
+  ops->lastflag          = SUNLinSolLastFlag_PCG;  
+  ops->space             = SUNLinSolSpace_PCG;  
+  ops->free              = SUNLinSolFree_PCG;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_PCG) malloc(sizeof(struct _SUNLinearSolverContent_PCG));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->last_flag = 0;
+  content->maxl = maxl;
+  content->pretype = pretype;
+  content->numiters = 0;
+  content->resnorm = ZERO;
+  content->r = N_VClone(y);
+  if (content->r == NULL)  return NULL;
+  content->p = N_VClone(y);
+  if (content->p == NULL)  return NULL;
+  content->z = N_VClone(y);
+  if (content->z == NULL)  return NULL;
+  content->Ap = N_VClone(y);
+  if (content->Ap == NULL)  return NULL;
+  content->s = NULL;
+  content->ATimes = NULL;
+  content->ATData = NULL;
+  content->Psetup = NULL;
+  content->Psolve = NULL;
+  content->PData = NULL;
+
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the type of preconditioning for PCG to use 
+ */
+
+SUNDIALS_EXPORT int SUNPCGSetPrecType(SUNLinearSolver S, int pretype) 
+{
+  /* Check for legal pretype */ 
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
+    return(SUNLS_ILL_INPUT);
+  }
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set pretype */
+  PRETYPE(S) = pretype;
+  return(SUNLS_SUCCESS);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the maximum number of iterations for PCG to use 
+ */
+
+SUNDIALS_EXPORT int SUNPCGSetMaxl(SUNLinearSolver S, int maxl) 
+{
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Check for legal pretype */ 
+  if (maxl <= 0)
+    maxl = SUNPCG_MAXL_DEFAULT;
+
+  /* Set pretype */
+  PCG_CONTENT(S)->maxl = maxl;
+  return(SUNLS_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_PCG(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_ITERATIVE);
+}
+
+int SUNLinSolInitialize_PCG(SUNLinearSolver S)
+{
+  /* ensure valid options */
+  if (S == NULL) return(SUNLS_MEM_NULL);  
+  if ( (PRETYPE(S) != PREC_LEFT) && 
+       (PRETYPE(S) != PREC_RIGHT) && 
+       (PRETYPE(S) != PREC_BOTH) )
+    PRETYPE(S) = PREC_NONE;
+  if (PCG_CONTENT(S)->maxl <= 0) 
+    PCG_CONTENT(S)->maxl = SUNPCG_MAXL_DEFAULT;
+
+  /* no additional memory to allocate */
+
+  /* return with success */
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetATimes_PCG(SUNLinearSolver S, void* ATData, 
+                           ATimesFn ATimes)
+{
+  /* set function pointers to integrator-supplied ATimes routine
+     and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  PCG_CONTENT(S)->ATimes = ATimes;
+  PCG_CONTENT(S)->ATData = ATData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetPreconditioner_PCG(SUNLinearSolver S, void* PData,
+                                   PSetupFn Psetup, PSolveFn Psolve)
+{
+  /* set function pointers to integrator-supplied Psetup and PSolve
+     routines and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  PCG_CONTENT(S)->Psetup = Psetup;
+  PCG_CONTENT(S)->Psolve = Psolve;
+  PCG_CONTENT(S)->PData = PData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetScalingVectors_PCG(SUNLinearSolver S, N_Vector s,
+                                   N_Vector nul)
+{
+  /* set N_Vector pointer to integrator-supplied scaling vector
+     (only use the first one), and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  PCG_CONTENT(S)->s = s;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_PCG(SUNLinearSolver S, SUNMatrix nul)
+{
+  int ier;
+  PSetupFn Psetup;
+  void* PData;
+
+  /* Set shortcuts to PCG memory structures */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  Psetup = PCG_CONTENT(S)->Psetup;
+  PData = PCG_CONTENT(S)->PData;
+  
+  /* no solver-specific setup is required, but if user-supplied 
+     Psetup routine exists, call that here */
+  if (Psetup != NULL) {
+    ier = Psetup(PData);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+	SUNLS_PSET_FAIL_UNREC : SUNLS_PSET_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  
+  /* return with success */ 
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSolve_PCG(SUNLinearSolver S, SUNMatrix nul, N_Vector x, 
+                       N_Vector b, realtype delta)
+{
+  /* local data and shortcut variables */
+  realtype alpha, beta, r0_norm, rho, rz, rz_old;
+  N_Vector r, p, z, Ap, w;
+  booleantype UsePrec, UseScaling, converged;
+  int l, l_max, pretype, ier;
+  void *A_data, *P_data;
+  ATimesFn atimes;
+  PSolveFn psolve;
+  realtype *res_norm;
+  int *nli;
+
+   /* Make local shorcuts to solver variables. */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  l_max        = PCG_CONTENT(S)->maxl;
+  r            = PCG_CONTENT(S)->r;
+  p            = PCG_CONTENT(S)->p;
+  z            = PCG_CONTENT(S)->z;
+  Ap           = PCG_CONTENT(S)->Ap;
+  w            = PCG_CONTENT(S)->s;
+  A_data       = PCG_CONTENT(S)->ATData;
+  P_data       = PCG_CONTENT(S)->PData;
+  atimes       = PCG_CONTENT(S)->ATimes;
+  psolve       = PCG_CONTENT(S)->Psolve;
+  pretype      = PCG_CONTENT(S)->pretype;
+  nli          = &(PCG_CONTENT(S)->numiters);
+  res_norm     = &(PCG_CONTENT(S)->resnorm);
+
+  /* Initialize counters and convergence flag */
+  *nli = 0;
+  converged = SUNFALSE;
+
+  /* set booleantype flags for internal solver options */
+  UsePrec = ( (pretype == PREC_BOTH) || 
+              (pretype == PREC_LEFT) || 
+              (pretype == PREC_RIGHT) );
+  UseScaling = (w != NULL);
+
+  /* Set r to initial residual r_0 = b - A*x_0 */
+  if (N_VDotProd(x, x) == ZERO)  N_VScale(ONE, b, r);
+  else {
+    ier = atimes(A_data, x, r);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    N_VLinearSum(ONE, b, -ONE, r, r);
+  }
+
+  /* Set rho to scaled L2 norm of r, and return if small */
+  if (UseScaling)  N_VProd(r, w, Ap);
+  else N_VScale(ONE, r, Ap);
+  *res_norm = r0_norm = rho = SUNRsqrt(N_VDotProd(Ap, Ap));
+  if (rho <= delta) {
+    LASTFLAG(S) = SUNLS_SUCCESS;
+    return(LASTFLAG(S));
+  }
+
+  /* Apply preconditioner and b-scaling to r = r_0 */
+  if (UsePrec) {
+    ier = psolve(P_data, r, z, delta, PREC_LEFT);   /* z = P^{-1}r */
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+        SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  else N_VScale(ONE, r, z);
+
+  /* Initialize rz to <r,z> */
+  rz = N_VDotProd(r, z);
+
+  /* Copy z to p */
+  N_VScale(ONE, z, p);
+
+  /* Begin main iteration loop */
+  for(l=0; l<l_max; l++) {
+
+    /* increment counter */
+    (*nli)++;
+
+    /* Generate Ap = A*p */
+    ier = atimes(A_data, p, Ap);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+
+    /* Calculate alpha = <r,z> / <Ap,p> */
+    alpha = rz / N_VDotProd(Ap, p);
+
+    /* Update x = x + alpha*p */
+    N_VLinearSum(ONE, x, alpha, p, x);
+
+    /* Update r = r - alpha*Ap */
+    N_VLinearSum(ONE, r, -alpha, Ap, r);
+
+    /* Set rho and check convergence */
+    if (UseScaling)  N_VProd(r, w, Ap);
+    else N_VScale(ONE, r, Ap);
+    *res_norm = rho = SUNRsqrt(N_VDotProd(Ap, Ap));
+    if (rho <= delta) {
+      converged = SUNTRUE;
+      break;
+    }
+
+    /* Apply preconditioner:  z = P^{-1}*r */
+    if (UsePrec) {
+      ier = psolve(P_data, r, z, delta, PREC_LEFT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ? 
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+    else N_VScale(ONE, r, z);
+
+    /* update rz */
+    rz_old = rz;
+    rz = N_VDotProd(r, z);
+    
+    /* Calculate beta = <r,z> / <r_old,z_old> */
+    beta = rz / rz_old;
+
+    /* Update p = z + beta*p */
+    N_VLinearSum(ONE, z, beta, p, p);
+  }
+
+  /* Main loop finished, return with result */
+  if (converged == SUNTRUE) {
+    LASTFLAG(S) = SUNLS_SUCCESS;
+  } else if (rho < r0_norm) {
+    LASTFLAG(S) = SUNLS_RES_REDUCED;
+  } else {
+    LASTFLAG(S) = SUNLS_CONV_FAIL;
+  }
+  return(LASTFLAG(S));
+}
+
+
+
+
+int SUNLinSolNumIters_PCG(SUNLinearSolver S)
+{
+  /* return the stored 'numiters' value */
+  if (S == NULL) return(-1);
+  return (PCG_CONTENT(S)->numiters);
+}
+
+
+realtype SUNLinSolResNorm_PCG(SUNLinearSolver S)
+{
+  /* return the stored 'resnorm' value */
+  if (S == NULL) return(-ONE);
+  return (PCG_CONTENT(S)->resnorm);
+}
+
+
+N_Vector SUNLinSolResid_PCG(SUNLinearSolver S)
+{
+  /* return the stored 'r' vector */
+  return (PCG_CONTENT(S)->r);
+}
+
+
+long int SUNLinSolLastFlag_PCG(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  if (S == NULL) return(-1);
+  return (LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_PCG(SUNLinearSolver S, 
+                       long int *lenrwLS, 
+                       long int *leniwLS)
+{
+  sunindextype liw1, lrw1;
+  N_VSpace(PCG_CONTENT(S)->r, &lrw1, &liw1);
+  *lenrwLS = 1 + lrw1*4;
+  *leniwLS = 4 + liw1*4;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_PCG(SUNLinearSolver S)
+{
+  if (S == NULL) return(SUNLS_SUCCESS);
+
+  /* delete items from within the content structure */
+  if (PCG_CONTENT(S)->r)
+    N_VDestroy(PCG_CONTENT(S)->r);
+  if (PCG_CONTENT(S)->p)
+    N_VDestroy(PCG_CONTENT(S)->p);
+  if (PCG_CONTENT(S)->z)
+    N_VDestroy(PCG_CONTENT(S)->z);
+  if (PCG_CONTENT(S)->Ap)
+    N_VDestroy(PCG_CONTENT(S)->Ap);
+
+  /* delete generic structures */
+  free(S->content);  S->content = NULL;
+  free(S->ops);  S->ops = NULL;
+  free(S); S = NULL;
+  return 0;
+}
diff --git a/src/sunlinsol_spbcgs/CMakeLists.txt b/src/sunlinsol_spbcgs/CMakeLists.txt
new file mode 100644
index 0000000..84a8b98
--- /dev/null
+++ b/src/sunlinsol_spbcgs/CMakeLists.txt
@@ -0,0 +1,107 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the SPBCGS SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_SPBCGS\n\")")
+
+# Add variable sunlinsolspbcgs_SOURCES with the sources for the SUNLINSOLSPBCGS lib
+SET(sunlinsolspbcgs_SOURCES sunlinsol_spbcgs.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLSPBCGS library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  )
+
+# Add variable sunlinsolspbcgs_HEADERS with the exported SUNLINSOLSPBCGS header files
+SET(sunlinsolspbcgs_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_spbcgs.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLSPBCGS library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLSPBCGS library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolspbcgs_static STATIC ${sunlinsolspbcgs_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspbcgs_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolspbcgs CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolspbcgs_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLSPBCGS library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLSPBCGS library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolspbcgs_shared SHARED ${sunlinsolspbcgs_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsolspbcgs_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspbcgs_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolspbcgs CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspbcgs_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolspbcgs_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLSPBCGS header files
+INSTALL(FILES ${sunlinsolspbcgs_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLSPBCGS library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsolspbcgs_SOURCES fsunlinsol_spbcgs.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolspbcgs_static STATIC ${fsunlinsolspbcgs_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspbcgs_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolspbcgs CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsolspbcgs_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolspbcgs_shared ${fsunlinsolspbcgs_SOURCES})
+
+    # fsunlinsolspbcgs depdens on fnvecserial and sunlinsolspbcgs
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsolspbcgs_shared
+      sundials_fnvecserial_shared
+      sundials_sunlinsolspbcgs_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspbcgs_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolspbcgs CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspbcgs_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsolspbcgs_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_SPBCGS module")
diff --git a/src/sunlinsol_spbcgs/README b/src/sunlinsol_spbcgs/README
new file mode 100644
index 0000000..9b26cad
--- /dev/null
+++ b/src/sunlinsol_spbcgs/README
@@ -0,0 +1,41 @@
+                     SUNLINSOL_SPBCGS
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Scaled, preconditioned, Bi-CG-stabilized implementation of the SUNLINSOL 
+module for SUNDIALS.  
+
+SUNLINSOL_SPBCGS defines the content field of SUNMatrix to be a structure 
+containing a X, along with a long integer for any error flag that arises in
+the linear solver routines.
+
+SUNLINSOL_SPBCGS defines N macros to provide access to the content of 
+a SPBCGS SUNLinearSolver, and constructor for the SPBCGS
+SUNLinearSolver, in addition to implementation of all linear
+solver operations defined by the generic SUNLINSOL module in the table
+of operations.
+
+
+A. Documentation
+----------------
+
+The SPBCGS SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c b/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c
new file mode 100644
index 0000000..81893a1
--- /dev/null
+++ b/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.c
@@ -0,0 +1,195 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_spbcgs.h) contains the
+ * implementation needed for the Fortran initialization of SPBCGS
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_spbcgs.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNSPBCGS_INIT(int *code, int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNSPBCGS(F2C_CVODE_vec, *pretype, *maxl);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNSPBCGS(F2C_IDA_vec, *pretype, *maxl);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNSPBCGS(F2C_KINSOL_vec, *pretype, *maxl);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNSPBCGS(F2C_ARKODE_vec, *pretype, *maxl);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPBCGS_SETPRECTYPE(int *code, int *pretype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetPrecType(F2C_CVODE_linsol, *pretype);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetPrecType(F2C_IDA_linsol, *pretype);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetPrecType(F2C_KINSOL_linsol, *pretype);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetPrecType(F2C_ARKODE_linsol, *pretype);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPBCGS_SETMAXL(int *code, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetMaxl(F2C_CVODE_linsol, *maxl);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetMaxl(F2C_IDA_linsol, *maxl);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetMaxl(F2C_KINSOL_linsol, *maxl);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPBCGSSetMaxl(F2C_ARKODE_linsol, *maxl);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSSPBCGS_INIT(int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNSPBCGS(F2C_ARKODE_vec, *pretype, *maxl);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
+void FSUNMASSSPBCGS_SETPRECTYPE(int *pretype, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPBCGSSetPrecType(F2C_ARKODE_mass_sol, *pretype);
+}
+
+
+void FSUNMASSSPBCGS_SETMAXL(int *maxl, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPBCGSSetMaxl(F2C_ARKODE_mass_sol, *maxl);
+}
diff --git a/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.h b/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.h
new file mode 100644
index 0000000..a56bb08
--- /dev/null
+++ b/src/sunlinsol_spbcgs/fsunlinsol_spbcgs.h
@@ -0,0 +1,84 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_spbcgs.c) contains the
+ * definitions needed for the initialization of SPBCGS
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_SPBCGS_H
+#define _FSUNLINSOL_SPBCGS_H
+
+#include <sunlinsol/sunlinsol_spbcgs.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNSPBCGS_INIT            SUNDIALS_F77_FUNC(fsunspbcgsinit,            FSUNSPBCGSINIT)
+#define FSUNSPBCGS_SETPRECTYPE     SUNDIALS_F77_FUNC(fsunspbcgssetprectype,     FSUNSPBCGSSETPRECTYPE)
+#define FSUNSPBCGS_SETMAXL         SUNDIALS_F77_FUNC(fsunspbcgssetmaxl,         FSUNSPBCGSSETMAXL)
+#define FSUNMASSSPBCGS_INIT        SUNDIALS_F77_FUNC(fsunmassspbcgsinit,        FSUNMASSSPBCGSINIT)
+#define FSUNMASSSPBCGS_SETPRECTYPE SUNDIALS_F77_FUNC(fsunmassspbcgssetprectype, FSUNMASSSPBCGSSETPRECTYPE)
+#define FSUNMASSSPBCGS_SETMAXL     SUNDIALS_F77_FUNC(fsunmassspbcgssetmaxl,     FSUNMASSSPBCGSSETMAXL)
+#else
+#define FSUNSPBCGS_INIT            fsunspbcgsinit_
+#define FSUNSPBCGS_SETPRECTYPE     fsunspbcgssetprectype_
+#define FSUNSPBCGS_SETMAXL         fsunspbcgssetmaxl_
+#define FSUNMASSSPBCGS_INIT        fsunmassspbcgsinit_
+#define FSUNMASSSPBCGS_SETPRECTYPE fsunmassspbcgssetprectype_
+#define FSUNMASSSPBCGS_SETMAXL     fsunmassspbcgssetmaxl_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNSPBCGS_INIT - initializes SPBCGS linear solver for main problem
+ * FSUNSPBCGS_SETPRECTYPE - sets the preconditioning type for main problem
+ * FSUNSPBCGS_SETMAXL - sets the max number of iterations for main problem
+ *
+ * FSUNMASSSPBCGS_INIT - initializes SPBCGS linear solver for mass matrix solve
+ * FSUNMASSSPBCGS_SETPRECTYPE - sets the preconditioning type for mass matrix solve
+ * FSUNMASSSPBCGS_SETMAXL - sets the max number of iterations for mass matrix solve
+ */
+
+void FSUNSPBCGS_INIT(int *code, int *pretype, int *maxl, int *ier);
+void FSUNSPBCGS_SETPRECTYPE(int *code, int *pretype, int *ier);
+void FSUNSPBCGS_SETMAXL(int *code, int *maxl, int *ier);
+
+void FSUNMASSSPBCGS_INIT(int *pretype, int *maxl, int *ier);
+void FSUNMASSSPBCGS_SETPRECTYPE(int *pretype, int *ier);
+void FSUNMASSSPBCGS_SETMAXL(int *maxl, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c b/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
new file mode 100644
index 0000000..9b348b6
--- /dev/null
+++ b/src/sunlinsol_spbcgs/sunlinsol_spbcgs.c
@@ -0,0 +1,617 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on sundials_spbcgs.c code, written by Peter Brown and 
+ *                Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the SPBCGS implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_spbcgs.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * SPBCGS solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define SPBCGS_CONTENT(S)  ( (SUNLinearSolverContent_SPBCGS)(S->content) )
+#define PRETYPE(S)         ( SPBCGS_CONTENT(S)->pretype )
+#define LASTFLAG(S)        ( SPBCGS_CONTENT(S)->last_flag )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new SPBCGS linear solver
+ */
+
+SUNLinearSolver SUNSPBCGS(N_Vector y, int pretype, int maxl)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_SPBCGS content;
+  
+  /* check for legal pretype and maxl values; if illegal use defaults */
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH))
+    pretype = PREC_NONE;
+  if (maxl <= 0)
+    maxl = SUNSPBCGS_MAXL_DEFAULT;
+
+  /* check that the supplied N_Vector supports all requisite operations */
+  if ( (y->ops->nvclone == NULL) || (y->ops->nvdestroy == NULL) ||
+       (y->ops->nvlinearsum == NULL) || (y->ops->nvprod == NULL) ||
+       (y->ops->nvdiv == NULL) || (y->ops->nvscale == NULL) ||
+       (y->ops->nvdotprod == NULL) )
+    return(NULL);
+
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_SPBCGS;
+  ops->setatimes         = SUNLinSolSetATimes_SPBCGS;
+  ops->setpreconditioner = SUNLinSolSetPreconditioner_SPBCGS;
+  ops->setscalingvectors = SUNLinSolSetScalingVectors_SPBCGS;
+  ops->initialize        = SUNLinSolInitialize_SPBCGS;
+  ops->setup             = SUNLinSolSetup_SPBCGS;
+  ops->solve             = SUNLinSolSolve_SPBCGS;
+  ops->numiters          = SUNLinSolNumIters_SPBCGS;
+  ops->resnorm           = SUNLinSolResNorm_SPBCGS;
+  ops->resid             = SUNLinSolResid_SPBCGS;
+  ops->lastflag          = SUNLinSolLastFlag_SPBCGS;  
+  ops->space             = SUNLinSolSpace_SPBCGS;  
+  ops->free              = SUNLinSolFree_SPBCGS;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_SPBCGS) malloc(sizeof(struct _SUNLinearSolverContent_SPBCGS));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->last_flag = 0;
+  content->maxl = maxl;
+  content->pretype = pretype;
+  content->numiters = 0;
+  content->resnorm = ZERO;
+  content->r_star = N_VClone(y);
+  if (content->r_star == NULL)  return(NULL);
+  content->r = N_VClone(y);
+  if (content->r == NULL)  return(NULL);
+  content->p = N_VClone(y);
+  if (content->p == NULL)  return(NULL);
+  content->q = N_VClone(y);
+  if (content->q == NULL)  return(NULL);
+  content->u = N_VClone(y);
+  if (content->u == NULL)  return(NULL);
+  content->Ap = N_VClone(y);
+  if (content->Ap == NULL)  return(NULL);
+  content->vtemp = N_VClone(y);
+  if (content->vtemp == NULL)  return(NULL);
+  content->s1 = NULL;
+  content->s2 = NULL;
+  content->ATimes = NULL;
+  content->ATData = NULL;
+  content->Psetup = NULL;
+  content->Psolve = NULL;
+  content->PData = NULL;
+
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the type of preconditioning for SPBCGS to use 
+ */
+
+SUNDIALS_EXPORT int SUNSPBCGSSetPrecType(SUNLinearSolver S, int pretype) 
+{
+  /* Check for legal pretype */ 
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
+    return(SUNLS_ILL_INPUT);
+  }
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set pretype */
+  PRETYPE(S) = pretype;
+  return(SUNLS_SUCCESS);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the maximum number of iterations for SPBCGS to use 
+ */
+
+SUNDIALS_EXPORT int SUNSPBCGSSetMaxl(SUNLinearSolver S, int maxl) 
+{
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Check for legal pretype */ 
+  if (maxl <= 0)
+    maxl = SUNSPBCGS_MAXL_DEFAULT;
+
+  /* Set pretype */
+  SPBCGS_CONTENT(S)->maxl = maxl;
+  return(SUNLS_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_SPBCGS(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_ITERATIVE);
+}
+
+
+int SUNLinSolInitialize_SPBCGS(SUNLinearSolver S)
+{
+  /* ensure valid options */
+  if (S == NULL) return(SUNLS_MEM_NULL);  
+  if ( (PRETYPE(S) != PREC_LEFT) && 
+       (PRETYPE(S) != PREC_RIGHT) && 
+       (PRETYPE(S) != PREC_BOTH) )
+    PRETYPE(S) = PREC_NONE;
+  if (SPBCGS_CONTENT(S)->maxl <= 0) 
+    SPBCGS_CONTENT(S)->maxl = SUNSPBCGS_MAXL_DEFAULT;
+
+  /* no additional memory to allocate */
+  
+  /* return with success */
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetATimes_SPBCGS(SUNLinearSolver S, void* ATData, 
+                              ATimesFn ATimes)
+{
+  /* set function pointers to integrator-supplied ATimes routine
+     and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPBCGS_CONTENT(S)->ATimes = ATimes;
+  SPBCGS_CONTENT(S)->ATData = ATData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetPreconditioner_SPBCGS(SUNLinearSolver S, void* PData,
+                                      PSetupFn Psetup, PSolveFn Psolve)
+{
+  /* set function pointers to integrator-supplied Psetup and PSolve
+     routines and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPBCGS_CONTENT(S)->Psetup = Psetup;
+  SPBCGS_CONTENT(S)->Psolve = Psolve;
+  SPBCGS_CONTENT(S)->PData = PData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetScalingVectors_SPBCGS(SUNLinearSolver S, N_Vector s1,
+                                      N_Vector s2)
+{
+  /* set N_Vector pointers to integrator-supplied scaling vectors, 
+     and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPBCGS_CONTENT(S)->s1 = s1;
+  SPBCGS_CONTENT(S)->s2 = s2;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_SPBCGS(SUNLinearSolver S, SUNMatrix A)
+{
+  int ier;
+  PSetupFn Psetup;
+  void* PData;
+
+  /* Set shortcuts to SPBCGS memory structures */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  Psetup = SPBCGS_CONTENT(S)->Psetup;
+  PData = SPBCGS_CONTENT(S)->PData;
+  
+  /* no solver-specific setup is required, but if user-supplied 
+     Psetup routine exists, call that here */
+  if (Psetup != NULL) {
+    ier = Psetup(PData);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+	SUNLS_PSET_FAIL_UNREC : SUNLS_PSET_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  
+  /* return with success */ 
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSolve_SPBCGS(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                          N_Vector b, realtype delta)
+{
+  /* local data and shortcut variables */
+  realtype alpha, beta, omega, omega_denom, beta_num, beta_denom, r_norm, rho;
+  N_Vector r_star, r, p, q, u, Ap, vtemp;
+  booleantype preOnLeft, preOnRight, scale_x, scale_b, converged;
+  int l, l_max, ier;
+  void *A_data, *P_data;
+  N_Vector sx, sb;
+  ATimesFn atimes;
+  PSolveFn psolve;
+  realtype *res_norm;
+  int *nli;
+  
+  /* Make local shorcuts to solver variables. */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  l_max        = SPBCGS_CONTENT(S)->maxl;
+  r_star       = SPBCGS_CONTENT(S)->r_star;
+  r            = SPBCGS_CONTENT(S)->r;
+  p            = SPBCGS_CONTENT(S)->p;
+  q            = SPBCGS_CONTENT(S)->q;
+  u            = SPBCGS_CONTENT(S)->u;
+  Ap           = SPBCGS_CONTENT(S)->Ap;
+  vtemp        = SPBCGS_CONTENT(S)->vtemp;
+  sb           = SPBCGS_CONTENT(S)->s1;
+  sx           = SPBCGS_CONTENT(S)->s2;
+  A_data       = SPBCGS_CONTENT(S)->ATData;
+  P_data       = SPBCGS_CONTENT(S)->PData;
+  atimes       = SPBCGS_CONTENT(S)->ATimes;
+  psolve       = SPBCGS_CONTENT(S)->Psolve;
+  nli          = &(SPBCGS_CONTENT(S)->numiters);
+  res_norm     = &(SPBCGS_CONTENT(S)->resnorm);
+
+  /* Initialize counters and convergence flag */
+  *nli = 0;
+  converged = SUNFALSE;
+
+  /* set booleantype flags for internal solver options */
+  preOnLeft  = ( (PRETYPE(S) == PREC_LEFT) || 
+                 (PRETYPE(S) == PREC_BOTH) );
+  preOnRight = ( (PRETYPE(S) == PREC_RIGHT) || 
+                 (PRETYPE(S) == PREC_BOTH) );
+  scale_x = (sx != NULL);
+  scale_b = (sb != NULL);
+
+  /* Set r_star to initial (unscaled) residual r_0 = b - A*x_0 */
+
+  if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star);
+  else {
+    ier = atimes(A_data, x, r_star);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    N_VLinearSum(ONE, b, -ONE, r_star, r_star);
+  }
+
+  /* Apply left preconditioner and b-scaling to r_star = r_0 */
+
+  if (preOnLeft) {
+    ier = psolve(P_data, r_star, r, delta, PREC_LEFT);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  else N_VScale(ONE, r_star, r);
+
+  if (scale_b) N_VProd(sb, r, r_star);
+  else N_VScale(ONE, r, r_star);
+
+  /* Initialize beta_denom to the dot product of r0 with r0 */
+
+  beta_denom = N_VDotProd(r_star, r_star);
+
+  /* Set r_norm to L2 norm of r_star = sb P1_inv r_0, and
+     return if small */
+
+  *res_norm = r_norm = rho = SUNRsqrt(beta_denom);
+  if (r_norm <= delta) {
+    LASTFLAG(S) = SUNLS_SUCCESS;
+    return(LASTFLAG(S));
+  }
+
+  /* Copy r_star to r and p */
+
+  N_VScale(ONE, r_star, r);
+  N_VScale(ONE, r_star, p);
+
+  /* Begin main iteration loop */
+
+  for(l = 0; l < l_max; l++) {
+
+    (*nli)++;
+
+    /* Generate Ap = A-tilde p, where A-tilde = sb P1_inv A P2_inv sx_inv */
+
+    /*   Apply x-scaling: vtemp = sx_inv p */
+
+    if (scale_x) N_VDiv(p, sx, vtemp);
+    else N_VScale(ONE, p, vtemp);
+
+    /*   Apply right preconditioner: vtemp = P2_inv sx_inv p */
+
+    if (preOnRight) {
+      N_VScale(ONE, vtemp, Ap);
+      ier = psolve(P_data, Ap, vtemp, delta, PREC_RIGHT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+
+    /*   Apply A: Ap = A P2_inv sx_inv p */
+
+    ier = atimes(A_data, vtemp, Ap );
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+
+    /*   Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */
+
+    if (preOnLeft) {
+      ier = psolve(P_data, Ap, vtemp, delta, PREC_LEFT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+    else N_VScale(ONE, Ap, vtemp);
+
+    /*   Apply b-scaling: Ap = sb P1_inv A P2_inv sx_inv p */
+
+    if (scale_b) N_VProd(sb, vtemp, Ap);
+    else N_VScale(ONE, vtemp, Ap);
+
+
+    /* Calculate alpha = <r,r_star>/<Ap,r_star> */
+
+    alpha = ((beta_denom / N_VDotProd(Ap, r_star)));
+
+    /* Update q = r - alpha*Ap = r - alpha*(sb P1_inv A P2_inv sx_inv p) */
+
+    N_VLinearSum(ONE, r, -alpha, Ap, q);
+
+    /* Generate u = A-tilde q */
+
+    /*   Apply x-scaling: vtemp = sx_inv q */
+
+    if (scale_x) N_VDiv(q, sx, vtemp);
+    else N_VScale(ONE, q, vtemp);
+
+    /*   Apply right preconditioner: vtemp = P2_inv sx_inv q */
+
+    if (preOnRight) {
+      N_VScale(ONE, vtemp, u);
+      ier = psolve(P_data, u, vtemp, delta, PREC_RIGHT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+
+    /*   Apply A: u = A P2_inv sx_inv u */
+
+    ier = atimes(A_data, vtemp, u );
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+
+    /*   Apply left preconditioner: vtemp = P1_inv A P2_inv sx_inv p */
+
+    if (preOnLeft) {
+      ier = psolve(P_data, u, vtemp, delta, PREC_LEFT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+    else N_VScale(ONE, u, vtemp);
+
+    /*   Apply b-scaling: u = sb P1_inv A P2_inv sx_inv u */
+
+    if (scale_b) N_VProd(sb, vtemp, u);
+    else N_VScale(ONE, vtemp, u);
+
+
+    /* Calculate omega = <u,q>/<u,u> */
+
+    omega_denom = N_VDotProd(u, u);
+    if (omega_denom == ZERO) omega_denom = ONE;
+    omega = (N_VDotProd(u, q) / omega_denom);
+
+    /* Update x = x + alpha*p + omega*q */
+
+    N_VLinearSum(alpha, p, omega, q, vtemp);
+    N_VLinearSum(ONE, x, ONE, vtemp, x);
+
+    /* Update the residual r = q - omega*u */
+
+    N_VLinearSum(ONE, q, -omega, u, r);
+
+    /* Set rho = norm(r) and check convergence */
+
+    *res_norm = rho = SUNRsqrt(N_VDotProd(r, r));
+    if (rho <= delta) {
+      converged = SUNTRUE;
+      break;
+    }
+
+    /* Not yet converged, continue iteration */
+    /* Update beta = <rnew,r_star> / <rold,r_start> * alpha / omega */
+
+    beta_num = N_VDotProd(r, r_star);
+    beta = ((beta_num / beta_denom) * (alpha / omega));
+    beta_denom = beta_num;
+
+    /* Update p = r + beta*(p - omega*Ap) */
+
+    N_VLinearSum(ONE, p, -omega, Ap, vtemp);
+    N_VLinearSum(ONE, r, beta, vtemp, p);
+
+  }
+
+  /* Main loop finished */
+
+  if ((converged == SUNTRUE) || (rho < r_norm)) {
+
+    /* Apply the x-scaling and right preconditioner: x = P2_inv sx_inv x */
+
+    if (scale_x) N_VDiv(x, sx, x);
+    if (preOnRight) {
+      ier = psolve(P_data, x, vtemp, delta, PREC_RIGHT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+      N_VScale(ONE, vtemp, x);
+    }
+
+    if (converged == SUNTRUE) 
+      LASTFLAG(S) = SUNLS_SUCCESS;
+    else 
+      LASTFLAG(S) = SUNLS_RES_REDUCED;
+    return(LASTFLAG(S));
+    
+  }
+  else {
+    LASTFLAG(S) = SUNLS_CONV_FAIL;
+    return(LASTFLAG(S));
+  }
+}
+
+
+int SUNLinSolNumIters_SPBCGS(SUNLinearSolver S)
+{
+  /* return the stored 'numiters' value */
+  if (S == NULL) return(-1);
+  return (SPBCGS_CONTENT(S)->numiters);
+}
+
+
+realtype SUNLinSolResNorm_SPBCGS(SUNLinearSolver S)
+{
+  /* return the stored 'resnorm' value */
+  if (S == NULL) return(-ONE);
+  return (SPBCGS_CONTENT(S)->resnorm);
+}
+
+
+N_Vector SUNLinSolResid_SPBCGS(SUNLinearSolver S)
+{
+  /* return the stored 'r' vector */
+  return (SPBCGS_CONTENT(S)->r);
+}
+
+
+long int SUNLinSolLastFlag_SPBCGS(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  if (S == NULL) return(-1);
+  return (LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_SPBCGS(SUNLinearSolver S, 
+                          long int *lenrwLS, 
+                          long int *leniwLS)
+{
+  sunindextype liw1, lrw1;
+  if (SPBCGS_CONTENT(S)->vtemp->ops->nvspace)
+    N_VSpace(SPBCGS_CONTENT(S)->vtemp, &lrw1, &liw1);
+  else
+    lrw1 = liw1 = 0;
+  *lenrwLS = lrw1*9;
+  *leniwLS = liw1*9;
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolFree_SPBCGS(SUNLinearSolver S)
+{
+  if (S == NULL) return(SUNLS_SUCCESS);
+
+  /* delete items from within the content structure */
+  if (SPBCGS_CONTENT(S)->r_star)
+    N_VDestroy(SPBCGS_CONTENT(S)->r_star);
+  if (SPBCGS_CONTENT(S)->r)
+    N_VDestroy(SPBCGS_CONTENT(S)->r);
+  if (SPBCGS_CONTENT(S)->p)
+    N_VDestroy(SPBCGS_CONTENT(S)->p);
+  if (SPBCGS_CONTENT(S)->q)
+    N_VDestroy(SPBCGS_CONTENT(S)->q);
+  if (SPBCGS_CONTENT(S)->u)
+    N_VDestroy(SPBCGS_CONTENT(S)->u);
+  if (SPBCGS_CONTENT(S)->Ap)
+    N_VDestroy(SPBCGS_CONTENT(S)->Ap);
+  if (SPBCGS_CONTENT(S)->vtemp)
+    N_VDestroy(SPBCGS_CONTENT(S)->vtemp);
+
+  /* delete generic structures */
+  free(S->content);  S->content = NULL;
+  free(S->ops);  S->ops = NULL;
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
diff --git a/src/sunlinsol_spfgmr/CMakeLists.txt b/src/sunlinsol_spfgmr/CMakeLists.txt
new file mode 100644
index 0000000..fd97c1c
--- /dev/null
+++ b/src/sunlinsol_spfgmr/CMakeLists.txt
@@ -0,0 +1,107 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the SPFGMR SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_SPFGMR\n\")")
+
+# Add variable sunlinsolspfgmr_SOURCES with the sources for the SUNLINSOLSPFGMR lib
+SET(sunlinsolspfgmr_SOURCES sunlinsol_spfgmr.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLSPFGMR library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  )
+
+# Add variable sunlinsolspfgmr_HEADERS with the exported SUNLINSOLSPFGMR header files
+SET(sunlinsolspfgmr_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_spfgmr.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLSPFGMR library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLSPFGMR library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolspfgmr_static STATIC ${sunlinsolspfgmr_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspfgmr_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolspfgmr CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolspfgmr_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLSPFGMR library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLSPFGMR library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolspfgmr_shared SHARED ${sunlinsolspfgmr_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsolspfgmr_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspfgmr_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolspfgmr CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspfgmr_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolspfgmr_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLSPFGMR header files
+INSTALL(FILES ${sunlinsolspfgmr_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLSPFGMR library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsolspfgmr_SOURCES fsunlinsol_spfgmr.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolspfgmr_static STATIC ${fsunlinsolspfgmr_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspfgmr_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolspfgmr CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsolspfgmr_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolspfgmr_shared ${fsunlinsolspfgmr_SOURCES})
+
+    # fsunlinsolspfgmr depends on fnvecserial and sunlinsolspfgmr
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsolspfgmr_shared
+      sundials_fnvecserial_shared
+      sundials_sunlinsolspfgmr_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspfgmr_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolspfgmr CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspfgmr_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsolspfgmr_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_SPFGMR module")
diff --git a/src/sunlinsol_spfgmr/README b/src/sunlinsol_spfgmr/README
new file mode 100644
index 0000000..8e95174
--- /dev/null
+++ b/src/sunlinsol_spfgmr/README
@@ -0,0 +1,41 @@
+                     SUNLINSOL_SPFGMR
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Scaled, preconditioned, FGMRES implementation of the SUNLINSOL module
+for SUNDIALS.  
+
+SUNLINSOL_SPFGMR defines the content field of SUNMatrix to be a structure 
+containing a X, along with a long integer for any error flag that arises in
+the linear solver routines.
+
+SUNLINSOL_SPFGMR defines N macros to provide access to the content of 
+a SPFGMR SUNLinearSolver, and constructor for the SPFGMR
+SUNLinearSolver, in addition to implementation of all linear
+solver operations defined by the generic SUNLINSOL module in the table
+of operations.
+
+
+A. Documentation
+----------------
+
+The SPFGMR SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c b/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c
new file mode 100644
index 0000000..82e960f
--- /dev/null
+++ b/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.c
@@ -0,0 +1,245 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_spfgmr.h) contains the
+ * implementation needed for the Fortran initialization of SPFGMR
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_spfgmr.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNSPFGMR_INIT(int *code, int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNSPFGMR(F2C_CVODE_vec, *pretype, *maxl);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNSPFGMR(F2C_IDA_vec, *pretype, *maxl);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNSPFGMR(F2C_KINSOL_vec, *pretype, *maxl);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNSPFGMR(F2C_ARKODE_vec, *pretype, *maxl);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPFGMR_SETGSTYPE(int *code, int *gstype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetGSType(F2C_CVODE_linsol, *gstype);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetGSType(F2C_IDA_linsol, *gstype);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetGSType(F2C_KINSOL_linsol, *gstype);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetGSType(F2C_ARKODE_linsol, *gstype);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPFGMR_SETPRECTYPE(int *code, int *pretype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetPrecType(F2C_CVODE_linsol, *pretype);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetPrecType(F2C_IDA_linsol, *pretype);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetPrecType(F2C_KINSOL_linsol, *pretype);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetPrecType(F2C_ARKODE_linsol, *pretype);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPFGMR_SETMAXRS(int *code, int *maxrs, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetMaxRestarts(F2C_CVODE_linsol, *maxrs);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetMaxRestarts(F2C_IDA_linsol, *maxrs);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetMaxRestarts(F2C_KINSOL_linsol, *maxrs);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPFGMRSetMaxRestarts(F2C_ARKODE_linsol, *maxrs);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSSPFGMR_INIT(int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNSPFGMR(F2C_ARKODE_vec, *pretype, *maxl);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
+void FSUNMASSSPFGMR_SETGSTYPE(int *gstype, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPFGMRSetGSType(F2C_ARKODE_mass_sol, *gstype);
+}
+
+
+void FSUNMASSSPFGMR_SETPRECTYPE(int *pretype, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPFGMRSetPrecType(F2C_ARKODE_mass_sol, *pretype);
+}
+
+
+void FSUNMASSSPFGMR_SETMAXRS(int *maxrs, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPFGMRSetMaxRestarts(F2C_ARKODE_mass_sol, *maxrs);
+}
diff --git a/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.h b/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.h
new file mode 100644
index 0000000..72cbe0a
--- /dev/null
+++ b/src/sunlinsol_spfgmr/fsunlinsol_spfgmr.h
@@ -0,0 +1,92 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_spfgmr.c) contains the
+ * definitions needed for the initialization of SPFGMR
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_SPFGMR_H
+#define _FSUNLINSOL_SPFGMR_H
+
+#include <sunlinsol/sunlinsol_spfgmr.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNSPFGMR_INIT            SUNDIALS_F77_FUNC(fsunspfgmrinit,            FSUNSPFGMRINIT)
+#define FSUNSPFGMR_SETGSTYPE       SUNDIALS_F77_FUNC(fsunspfgmrsetgstype,       FSUNSPFGMRSETGSTYPE)
+#define FSUNSPFGMR_SETPRECTYPE     SUNDIALS_F77_FUNC(fsunspfgmrsetprectype,     FSUNSPFGMRSETPRECTYPE)
+#define FSUNSPFGMR_SETMAXRS        SUNDIALS_F77_FUNC(fsunspfgmrsetmaxrs,        FSUNSPFGMRSETMAXRS)
+#define FSUNMASSSPFGMR_INIT        SUNDIALS_F77_FUNC(fsunmassspfgmrinit,        FSUNMASSSPFGMRINIT)
+#define FSUNMASSSPFGMR_SETGSTYPE   SUNDIALS_F77_FUNC(fsunmassspfgmrsetgstype,   FSUNMASSSPFGMRSETGSTYPE)
+#define FSUNMASSSPFGMR_SETPRECTYPE SUNDIALS_F77_FUNC(fsunmassspfgmrsetprectype, FSUNMASSSPFGMRSETPRECTYPE)
+#define FSUNMASSSPFGMR_SETMAXRS    SUNDIALS_F77_FUNC(fsunmassspfgmrsetmaxrs,    FSUNMASSSPFGMRSETMAXRS)
+#else
+#define FSUNSPFGMR_INIT            fsunspfgmrinit_
+#define FSUNSPFGMR_SETGSTYPE       fsunspfgmrsetgstype_
+#define FSUNSPFGMR_SETPRECTYPE     fsunspfgmrsetprectype_
+#define FSUNSPFGMR_SETMAXRS        fsunspfgmrsetmaxrs_
+#define FSUNMASSSPFGMR_INIT        fsunmassspfgmrinit_
+#define FSUNMASSSPFGMR_SETGSTYPE   fsunmassspfgmrsetgstype_
+#define FSUNMASSSPFGMR_SETPRECTYPE fsunmassspfgmrsetprectype_
+#define FSUNMASSSPFGMR_SETMAXRS    fsunmassspfgmrsetmaxrs_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNSPFGMR_INIT - initializes SPFGMR linear solver for main problem
+ * FSUNSPFGMR_SETGSTYPE - sets the Gram-Scmidt orthogonalization type for main problem
+ * FSUNSPFGMR_SETPRECTYPE - sets the preconditioning type for main problem
+ * FSUNSPFGMR_SETMAXRS - sets the maximum number of restarts to allow for main problem
+ *
+ * FSUNMASSSPFGMR_INIT - initializes SPFGMR linear solver for mass matrix solve
+ * FSUNMASSSPFGMR_SETGSTYPE - sets the Gram-Scmidt orthogonalization type for mass matrix solve
+ * FSUNMASSSPFGMR_SETPRECTYPE - sets the preconditioning type for mass matrix solve
+ * FSUNMASSSPFGMR_SETMAXRS - sets the maximum number of restarts to allow for mass matrix solve
+ */
+
+void FSUNSPFGMR_INIT(int *code, int *pretype, int *maxl, int *ier);
+void FSUNSPFGMR_SETGSTYPE(int *code, int *gstype, int *ier);
+void FSUNSPFGMR_SETPRECTYPE(int *code, int *pretype, int *ier);
+void FSUNSPFGMR_SETMAXRS(int *code, int *maxrs, int *ier);
+  
+void FSUNMASSSPFGMR_INIT(int *pretype, int *maxl, int *ier);
+void FSUNMASSSPFGMR_SETGSTYPE(int *gstype, int *ier);
+void FSUNMASSSPFGMR_SETPRECTYPE(int *pretype, int *ier);
+void FSUNMASSSPFGMR_SETMAXRS(int *maxrs, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c b/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
new file mode 100644
index 0000000..f5e567f
--- /dev/null
+++ b/src/sunlinsol_spfgmr/sunlinsol_spfgmr.c
@@ -0,0 +1,655 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on sundials_spfgmr.c code, written by Daniel R. Reynolds 
+ *                and Hilari C. Tiedeman @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the SPFGMR implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_spfgmr.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * SPFGMR solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define SPFGMR_CONTENT(S)  ( (SUNLinearSolverContent_SPFGMR)(S->content) )
+#define LASTFLAG(S)        ( SPFGMR_CONTENT(S)->last_flag )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new SPFGMR linear solver
+ */
+
+SUNLinearSolver SUNSPFGMR(N_Vector y, int pretype, int maxl)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_SPFGMR content;
+  
+  /* set preconditioning flag (enabling any preconditioner implies right 
+     preconditioning, since SPFGMR does not support left preconditioning) */
+  pretype = ( (pretype == PREC_LEFT)  ||
+              (pretype == PREC_RIGHT) ||
+              (pretype == PREC_BOTH) ) ? PREC_RIGHT : PREC_NONE;
+
+  /* if maxl input is illegal, set to default */
+  if (maxl <= 0)  maxl = SUNSPFGMR_MAXL_DEFAULT;
+
+  /* check that the supplied N_Vector supports all requisite operations */
+  if ( (y->ops->nvclone == NULL) || (y->ops->nvdestroy == NULL) ||
+       (y->ops->nvlinearsum == NULL) || (y->ops->nvconst == NULL) ||
+       (y->ops->nvprod == NULL) || (y->ops->nvdiv == NULL) ||
+       (y->ops->nvscale == NULL) || (y->ops->nvdotprod == NULL) )
+    return(NULL);
+
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_SPFGMR;
+  ops->setatimes         = SUNLinSolSetATimes_SPFGMR;
+  ops->setpreconditioner = SUNLinSolSetPreconditioner_SPFGMR;
+  ops->setscalingvectors = SUNLinSolSetScalingVectors_SPFGMR;
+  ops->initialize        = SUNLinSolInitialize_SPFGMR;
+  ops->setup             = SUNLinSolSetup_SPFGMR;
+  ops->solve             = SUNLinSolSolve_SPFGMR;
+  ops->numiters          = SUNLinSolNumIters_SPFGMR;
+  ops->resnorm           = SUNLinSolResNorm_SPFGMR;
+  ops->resid             = SUNLinSolResid_SPFGMR;
+  ops->lastflag          = SUNLinSolLastFlag_SPFGMR;  
+  ops->space             = SUNLinSolSpace_SPFGMR;  
+  ops->free              = SUNLinSolFree_SPFGMR;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_SPFGMR) malloc(sizeof(struct _SUNLinearSolverContent_SPFGMR));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->last_flag = 0;
+  content->maxl = maxl;
+  content->pretype = pretype;
+  content->gstype = SUNSPFGMR_GSTYPE_DEFAULT;
+  content->max_restarts = SUNSPFGMR_MAXRS_DEFAULT;
+  content->numiters = 0;
+  content->resnorm = ZERO;
+  content->xcor = N_VClone(y);
+  if (content->xcor == NULL)  return(NULL);
+  content->vtemp = N_VClone(y);
+  if (content->vtemp == NULL)  return(NULL);
+  content->s1 = NULL;
+  content->s2 = NULL;
+  content->ATimes = NULL;
+  content->ATData = NULL;
+  content->Psetup = NULL;
+  content->Psolve = NULL;
+  content->PData = NULL;
+  content->V = NULL;
+  content->Z = NULL;
+  content->Hes = NULL;
+  content->givens = NULL;
+  content->yg = NULL;
+
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to toggle preconditioning on/off -- turns on if pretype is any 
+ * one of PREC_LEFT, PREC_RIGHT or PREC_BOTH; otherwise turns off
+ */
+
+SUNDIALS_EXPORT int SUNSPFGMRSetPrecType(SUNLinearSolver S, int pretype) 
+{
+  /* Check for legal pretype */ 
+  pretype = ( (pretype == PREC_LEFT)  ||
+              (pretype == PREC_RIGHT) ||
+              (pretype == PREC_BOTH) ) ? PREC_RIGHT : PREC_NONE;
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set pretype */
+  SPFGMR_CONTENT(S)->pretype = pretype;
+  return(SUNLS_SUCCESS);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the type of Gram-Schmidt orthogonalization for SPFGMR to use
+ */
+
+SUNDIALS_EXPORT int SUNSPFGMRSetGSType(SUNLinearSolver S, int gstype)
+{
+  /* Check for legal gstype */ 
+  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
+    return(SUNLS_ILL_INPUT);
+  }
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set pretype */
+  SPFGMR_CONTENT(S)->gstype = gstype;
+  return(SUNLS_SUCCESS);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the maximum number of FGMRES restarts to allow
+ */
+
+SUNDIALS_EXPORT int SUNSPFGMRSetMaxRestarts(SUNLinearSolver S, int maxrs)
+{
+  /* Illegal maxrs implies use of default value */ 
+  if (maxrs < 0)
+    maxrs = SUNSPFGMR_MAXRS_DEFAULT;
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set max_restarts */
+  SPFGMR_CONTENT(S)->max_restarts = maxrs;
+  return(SUNLS_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_SPFGMR(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_ITERATIVE);
+}
+
+
+int SUNLinSolInitialize_SPFGMR(SUNLinearSolver S)
+{
+  int k;
+  SUNLinearSolverContent_SPFGMR content;
+
+  /* set shortcut to SPFGMR memory structure */
+  if (S == NULL) return(SUNLS_MEM_NULL);  
+  content = SPFGMR_CONTENT(S);
+
+  /* ensure valid options */
+  if (content->max_restarts < 0) 
+    content->max_restarts = SUNSPFGMR_MAXRS_DEFAULT;
+  if ( (content->pretype != PREC_LEFT) && 
+       (content->pretype != PREC_RIGHT) && 
+       (content->pretype != PREC_BOTH) )
+    content->pretype = PREC_NONE;
+
+
+  /* allocate solver-specific memory (where the size depends on the
+     choice of maxl) here */
+
+  /*   Krylov subspace vectors */
+  content->V = N_VCloneVectorArray(content->maxl+1, content->vtemp);
+  if (content->V == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  /*   Preconditioned basis vectors */
+  content->Z = N_VCloneVectorArray(content->maxl+1, content->vtemp);
+  if (content->Z == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  /*   Hessenberg matrix Hes */
+  content->Hes = (realtype **) malloc((content->maxl+1)*sizeof(realtype *)); 
+  if (content->Hes == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  for (k=0; k<=content->maxl; k++) {
+    content->Hes[k] = NULL;
+    content->Hes[k] = (realtype *) malloc(content->maxl*sizeof(realtype));
+    if (content->Hes[k] == NULL) {
+      SUNLinSolFree(S);
+      content->last_flag = SUNLS_MEM_FAIL;
+      return(SUNLS_MEM_FAIL);
+    }
+  }
+  
+  /*   Givens rotation components */
+  content->givens = NULL;
+  content->givens = (realtype *) malloc(2*content->maxl*sizeof(realtype));
+  if (content->givens == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  /*    y and g vectors */
+  content->yg = (realtype *) malloc((content->maxl+1)*sizeof(realtype));
+  if (content->yg == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  /* return with success */
+  content->last_flag = SUNLS_SUCCESS;
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSetATimes_SPFGMR(SUNLinearSolver S, void* ATData, 
+                              ATimesFn ATimes)
+{
+  /* set function pointers to integrator-supplied ATimes routine 
+     and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPFGMR_CONTENT(S)->ATimes = ATimes;
+  SPFGMR_CONTENT(S)->ATData = ATData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetPreconditioner_SPFGMR(SUNLinearSolver S, void* PData,
+                                    PSetupFn Psetup, PSolveFn Psolve)
+{
+  /* set function pointers to integrator-supplied Psetup and PSolve
+     routines and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPFGMR_CONTENT(S)->Psetup = Psetup;
+  SPFGMR_CONTENT(S)->Psolve = Psolve;
+  SPFGMR_CONTENT(S)->PData = PData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetScalingVectors_SPFGMR(SUNLinearSolver S, N_Vector s1,
+                                     N_Vector s2)
+{
+  /* set N_Vector pointers to integrator-supplied scaling vectors, 
+     and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPFGMR_CONTENT(S)->s1 = s1;
+  SPFGMR_CONTENT(S)->s2 = s2;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_SPFGMR(SUNLinearSolver S, SUNMatrix A)
+{
+  int ier;
+  PSetupFn Psetup;
+  void* PData;
+
+  /* Set shortcuts to SPFGMR memory structures */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  Psetup = SPFGMR_CONTENT(S)->Psetup;
+  PData = SPFGMR_CONTENT(S)->PData;
+  
+  /* no solver-specific setup is required, but if user-supplied 
+     Psetup routine exists, call that here */
+  if (Psetup != NULL) {
+    ier = Psetup(PData);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+	SUNLS_PSET_FAIL_UNREC : SUNLS_PSET_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  
+  /* return with success */ 
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSolve_SPFGMR(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                         N_Vector b, realtype delta)
+{
+  /* local data and shortcut variables */
+  N_Vector *V, *Z, xcor, vtemp, s1, s2;
+  realtype **Hes, *givens, *yg, *res_norm;
+  realtype beta, rotation_product, r_norm, s_product, rho;
+  booleantype preOnRight, scale1, scale2, converged;
+  int i, j, k, l, l_max, krydim, ier, ntries, max_restarts, gstype;
+  int *nli;
+  void *A_data, *P_data;
+  ATimesFn atimes;
+  PSolveFn psolve;
+
+  /* Initialize some variables */
+  krydim = 0;
+
+  /* Make local shorcuts to solver variables. */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  l_max        = SPFGMR_CONTENT(S)->maxl;
+  max_restarts = SPFGMR_CONTENT(S)->max_restarts;
+  gstype       = SPFGMR_CONTENT(S)->gstype;
+  V            = SPFGMR_CONTENT(S)->V;
+  Z            = SPFGMR_CONTENT(S)->Z;
+  Hes          = SPFGMR_CONTENT(S)->Hes;
+  givens       = SPFGMR_CONTENT(S)->givens;
+  xcor         = SPFGMR_CONTENT(S)->xcor;
+  yg           = SPFGMR_CONTENT(S)->yg;
+  vtemp        = SPFGMR_CONTENT(S)->vtemp;
+  s1           = SPFGMR_CONTENT(S)->s1;
+  s2           = SPFGMR_CONTENT(S)->s2;
+  A_data       = SPFGMR_CONTENT(S)->ATData;
+  P_data       = SPFGMR_CONTENT(S)->PData;
+  atimes       = SPFGMR_CONTENT(S)->ATimes;
+  psolve       = SPFGMR_CONTENT(S)->Psolve;
+  nli          = &(SPFGMR_CONTENT(S)->numiters);
+  res_norm     = &(SPFGMR_CONTENT(S)->resnorm);
+
+  /* Initialize counters and convergence flag */
+  *nli = 0;
+  converged = SUNFALSE;
+
+  /* set booleantype flags for internal solver options */
+  preOnRight = ( (SPFGMR_CONTENT(S)->pretype == PREC_LEFT) ||
+                 (SPFGMR_CONTENT(S)->pretype == PREC_RIGHT) || 
+                 (SPFGMR_CONTENT(S)->pretype == PREC_BOTH) );
+  scale1 = (s1 != NULL);
+  scale2 = (s2 != NULL);
+
+  /* Set vtemp and V[0] to initial (unscaled) residual r_0 = b - A*x_0 */
+  if (N_VDotProd(x, x) == ZERO) {
+    N_VScale(ONE, b, vtemp);
+  } else {
+    ier = atimes(A_data, x, vtemp);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+          SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    N_VLinearSum(ONE, b, -ONE, vtemp, vtemp);
+  }
+
+  /* Apply left scaling to vtemp = r_0 to fill V[0]. */
+  if (scale1) {
+    N_VProd(s1, vtemp, V[0]);   
+  } else {
+    N_VScale(ONE, vtemp, V[0]);
+  }
+
+  /* Set r_norm = beta to L2 norm of V[0] = s1 r_0, and return if small */
+  *res_norm = r_norm = beta = SUNRsqrt(N_VDotProd(V[0], V[0]));
+  if (r_norm <= delta) {
+    LASTFLAG(S) = SUNLS_SUCCESS;
+    return(LASTFLAG(S));
+  }
+
+  /* Initialize rho to avoid compiler warning message */
+  rho = beta;
+
+  /* Set xcor = 0. */
+  N_VConst(ZERO, xcor);
+
+  /* Begin outer iterations: up to (max_restarts + 1) attempts. */
+  for (ntries=0; ntries<=max_restarts; ntries++) {
+    
+    /* Initialize the Hessenberg matrix Hes and Givens rotation
+       product.  Normalize the initial vector V[0].             */
+    for (i=0; i<=l_max; i++)
+      for (j=0; j<l_max; j++)
+        Hes[i][j] = ZERO;
+    rotation_product = ONE;
+    N_VScale(ONE/r_norm, V[0], V[0]);
+    
+    /* Inner loop: generate Krylov sequence and Arnoldi basis. */
+    for (l=0; l<l_max; l++) {
+      
+      (*nli)++;
+      
+      krydim = l + 1;
+      
+      /* Generate A-tilde V[l], where A-tilde = s1 A P_inv s2_inv. */
+
+      /*   Apply right scaling: vtemp = s2_inv V[l]. */
+      if (scale2) N_VDiv(V[l], s2, vtemp);
+      else N_VScale(ONE, V[l], vtemp);
+      
+      /*   Apply right preconditioner: vtemp = Z[l] = P_inv s2_inv V[l]. */ 
+      if (preOnRight) {
+        N_VScale(ONE, vtemp, V[l+1]);
+        ier = psolve(P_data, V[l+1], vtemp, delta, PREC_RIGHT);
+        if (ier != 0) {
+          LASTFLAG(S) = (ier < 0) ?
+            SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+          return(LASTFLAG(S));
+        }
+      }
+      N_VScale(ONE, vtemp, Z[l]);
+      
+      /*   Apply A: V[l+1] = A P_inv s2_inv V[l]. */
+      ier = atimes(A_data, vtemp, V[l+1]);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+
+      /*   Apply left scaling: V[l+1] = s1 A P_inv s2_inv V[l]. */
+      if (scale1)  N_VProd(s1, V[l+1], V[l+1]);
+      
+      /* Orthogonalize V[l+1] against previous V[i]: V[l+1] = w_tilde. */
+      if (gstype == CLASSICAL_GS) {
+        if (ClassicalGS(V, Hes, l+1, l_max, &(Hes[l+1][l]),
+                        vtemp, yg) != 0) {
+          LASTFLAG(S) = SUNLS_GS_FAIL;
+          return(LASTFLAG(S));
+        }
+      } else {
+        if (ModifiedGS(V, Hes, l+1, l_max, &(Hes[l+1][l])) != 0) {
+          LASTFLAG(S) = SUNLS_GS_FAIL;
+          return(LASTFLAG(S));
+        }
+      }
+      
+      /* Update the QR factorization of Hes. */
+      if(QRfact(krydim, Hes, givens, l) != 0 ) {
+        LASTFLAG(S) = SUNLS_QRFACT_FAIL;
+        return(LASTFLAG(S));
+      }
+      
+      /* Update residual norm estimate; break if convergence test passes. */
+      rotation_product *= givens[2*l+1];
+      *res_norm = rho = SUNRabs(rotation_product*r_norm);
+      if (rho <= delta) { converged = SUNTRUE; break; }
+      
+      /* Normalize V[l+1] with norm value from the Gram-Schmidt routine. */
+      N_VScale(ONE/Hes[l+1][l], V[l+1], V[l+1]);
+    }
+    
+    /* Inner loop is done.  Compute the new correction vector xcor. */
+    
+    /*   Construct g, then solve for y. */
+    yg[0] = r_norm;
+    for (i=1; i<=krydim; i++)  yg[i]=ZERO;
+    if (QRsol(krydim, Hes, givens, yg) != 0) {
+      LASTFLAG(S) = SUNLS_QRSOL_FAIL;
+      return(LASTFLAG(S));
+    }
+    
+    /*   Add correction vector Z_l y to xcor. */
+    for (k=0; k<krydim; k++)
+      N_VLinearSum(yg[k], Z[k], ONE, xcor, xcor);
+    
+    /* If converged, construct the final solution vector x and return. */
+    if (converged) {
+      N_VLinearSum(ONE, x, ONE, xcor, x); {
+        LASTFLAG(S) = SUNLS_SUCCESS;
+        return(LASTFLAG(S));
+      }
+    }
+    
+    /* Not yet converged; if allowed, prepare for restart. */
+    if (ntries == max_restarts) break;
+    
+    /* Construct last column of Q in yg. */
+    s_product = ONE;
+    for (i=krydim; i>0; i--) {
+      yg[i] = s_product*givens[2*i-2];
+      s_product *= givens[2*i-1];
+    }
+    yg[0] = s_product;
+    
+    /* Scale r_norm and yg. */
+    r_norm *= s_product;
+    for (i=0; i<=krydim; i++)
+      yg[i] *= r_norm;
+    r_norm = SUNRabs(r_norm);
+    
+    /* Multiply yg by V_(krydim+1) to get last residual vector; restart. */
+    N_VScale(yg[0], V[0], V[0]);
+    for (k=1; k<=krydim; k++)
+      N_VLinearSum(yg[k], V[k], ONE, V[0], V[0]);
+    
+  }
+  
+  /* Failed to converge, even after allowed restarts.
+     If the residual norm was reduced below its initial value, compute
+     and return x anyway.  Otherwise return failure flag. */
+  if (rho < beta) {
+    N_VLinearSum(ONE, x, ONE, xcor, x); {
+      LASTFLAG(S) = SUNLS_RES_REDUCED;
+      return(LASTFLAG(S));
+    }
+  }
+
+  LASTFLAG(S) = SUNLS_CONV_FAIL;
+  return(LASTFLAG(S)); 
+}
+
+
+int SUNLinSolNumIters_SPFGMR(SUNLinearSolver S)
+{
+  /* return the stored 'numiters' value */
+  if (S == NULL) return(-1);
+  return (SPFGMR_CONTENT(S)->numiters);
+}
+
+
+realtype SUNLinSolResNorm_SPFGMR(SUNLinearSolver S)
+{
+  /* return the stored 'resnorm' value */
+  if (S == NULL) return(-ONE);
+  return (SPFGMR_CONTENT(S)->resnorm);
+}
+
+
+N_Vector SUNLinSolResid_SPFGMR(SUNLinearSolver S)
+{
+  /* return the stored 'vtemp' vector */
+  return (SPFGMR_CONTENT(S)->vtemp);
+}
+
+
+long int SUNLinSolLastFlag_SPFGMR(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  if (S == NULL) return(-1);
+  return (LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_SPFGMR(SUNLinearSolver S, 
+                          long int *lenrwLS, 
+                          long int *leniwLS)
+{
+  int maxl;
+  sunindextype liw1, lrw1;
+  maxl = SPFGMR_CONTENT(S)->maxl;
+  if (SPFGMR_CONTENT(S)->vtemp->ops->nvspace)
+    N_VSpace(SPFGMR_CONTENT(S)->vtemp, &lrw1, &liw1);
+  else
+    lrw1 = liw1 = 0;
+  *lenrwLS = lrw1*(2*maxl + 4) + maxl*(maxl + 4) + 1;
+  *leniwLS = liw1*(2*maxl + 4);
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_SPFGMR(SUNLinearSolver S)
+{
+  int k;
+
+  if (S == NULL) return(SUNLS_SUCCESS);
+
+  /* delete items from within the content structure */
+  if (SPFGMR_CONTENT(S)->xcor)
+    N_VDestroy(SPFGMR_CONTENT(S)->xcor);
+  if (SPFGMR_CONTENT(S)->vtemp)
+    N_VDestroy(SPFGMR_CONTENT(S)->vtemp);
+  if (SPFGMR_CONTENT(S)->V)
+    N_VDestroyVectorArray(SPFGMR_CONTENT(S)->V,
+                          SPFGMR_CONTENT(S)->maxl+1);
+  if (SPFGMR_CONTENT(S)->Z)
+    N_VDestroyVectorArray(SPFGMR_CONTENT(S)->Z,
+                          SPFGMR_CONTENT(S)->maxl+1);
+  if (SPFGMR_CONTENT(S)->Hes) {
+    for (k=0; k<=SPFGMR_CONTENT(S)->maxl; k++)
+      if (SPFGMR_CONTENT(S)->Hes[k])
+        free(SPFGMR_CONTENT(S)->Hes[k]);
+    free(SPFGMR_CONTENT(S)->Hes);
+  }
+  if (SPFGMR_CONTENT(S)->givens)
+    free(SPFGMR_CONTENT(S)->givens);
+  if (SPFGMR_CONTENT(S)->yg)
+    free(SPFGMR_CONTENT(S)->yg);
+
+  /* delete generic structures */
+  free(S->content);  S->content = NULL;
+  free(S->ops);  S->ops = NULL;
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
diff --git a/src/sunlinsol_spgmr/CMakeLists.txt b/src/sunlinsol_spgmr/CMakeLists.txt
new file mode 100644
index 0000000..8cfb369
--- /dev/null
+++ b/src/sunlinsol_spgmr/CMakeLists.txt
@@ -0,0 +1,107 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the SPGMR SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_SPGMR\n\")")
+
+# Add variable sunlinsolspgmr_SOURCES with the sources for the SUNLINSOLSPGMR lib
+SET(sunlinsolspgmr_SOURCES sunlinsol_spgmr.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLSPGMR library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  )
+
+# Add variable sunlinsolspgmr_HEADERS with the exported SUNLINSOLSPGMR header files
+SET(sunlinsolspgmr_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_spgmr.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLSPGMR library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLSPGMR library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolspgmr_static STATIC ${sunlinsolspgmr_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspgmr_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolspgmr CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolspgmr_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLSPGMR library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLSPGMR library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolspgmr_shared SHARED ${sunlinsolspgmr_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsolspgmr_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspgmr_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolspgmr CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolspgmr_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolspgmr_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLSPGMR header files
+INSTALL(FILES ${sunlinsolspgmr_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLSPGMR library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsolspgmr_SOURCES fsunlinsol_spgmr.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolspgmr_static STATIC ${fsunlinsolspgmr_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspgmr_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolspgmr CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsolspgmr_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolspgmr_shared ${fsunlinsolspgmr_SOURCES})
+
+    # fsunlinsolspgmr depends on fnvecserial and sunlinsolspgmr
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsolspgmr_shared
+      sundials_fnvecserial_shared
+      sundials_sunlinsolspgmr_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspgmr_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolspgmr CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolspgmr_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsolspgmr_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_SPGMR module")
diff --git a/src/sunlinsol_spgmr/README b/src/sunlinsol_spgmr/README
new file mode 100644
index 0000000..15e4b05
--- /dev/null
+++ b/src/sunlinsol_spgmr/README
@@ -0,0 +1,41 @@
+                     SUNLINSOL_SPGMR
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Scaled, preconditioned, GMRES implementation of the SUNLINSOL module
+for SUNDIALS.  
+
+SUNLINSOL_SPGMR defines the content field of SUNMatrix to be a structure 
+containing a X, along with a long integer for any error flag that arises in
+the linear solver routines.
+
+SUNLINSOL_SPGMR defines N macros to provide access to the content of 
+a SPGMR SUNLinearSolver, and constructor for the SPGMR
+SUNLinearSolver, in addition to implementation of all linear
+solver operations defined by the generic SUNLINSOL module in the table
+of operations.
+
+
+A. Documentation
+----------------
+
+The SPGMR SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_spgmr/fsunlinsol_spgmr.c b/src/sunlinsol_spgmr/fsunlinsol_spgmr.c
new file mode 100644
index 0000000..cdabfb8
--- /dev/null
+++ b/src/sunlinsol_spgmr/fsunlinsol_spgmr.c
@@ -0,0 +1,245 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_spgmr.h) contains the
+ * implementation needed for the Fortran initialization of SPGMR
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_spgmr.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNSPGMR_INIT(int *code, int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNSPGMR(F2C_CVODE_vec, *pretype, *maxl);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNSPGMR(F2C_IDA_vec, *pretype, *maxl);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNSPGMR(F2C_KINSOL_vec, *pretype, *maxl);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNSPGMR(F2C_ARKODE_vec, *pretype, *maxl);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPGMR_SETGSTYPE(int *code, int *gstype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetGSType(F2C_CVODE_linsol, *gstype);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetGSType(F2C_IDA_linsol, *gstype);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetGSType(F2C_KINSOL_linsol, *gstype);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetGSType(F2C_ARKODE_linsol, *gstype);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPGMR_SETPRECTYPE(int *code, int *pretype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetPrecType(F2C_CVODE_linsol, *pretype);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetPrecType(F2C_IDA_linsol, *pretype);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetPrecType(F2C_KINSOL_linsol, *pretype);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetPrecType(F2C_ARKODE_linsol, *pretype);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPGMR_SETMAXRS(int *code, int *maxrs, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetMaxRestarts(F2C_CVODE_linsol, *maxrs);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetMaxRestarts(F2C_IDA_linsol, *maxrs);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetMaxRestarts(F2C_KINSOL_linsol, *maxrs);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPGMRSetMaxRestarts(F2C_ARKODE_linsol, *maxrs);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSSPGMR_INIT(int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNSPGMR(F2C_ARKODE_vec, *pretype, *maxl);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
+void FSUNMASSSPGMR_SETGSTYPE(int *gstype, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPGMRSetGSType(F2C_ARKODE_mass_sol, *gstype);
+}
+
+
+void FSUNMASSSPGMR_SETPRECTYPE(int *pretype, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPGMRSetPrecType(F2C_ARKODE_mass_sol, *pretype);
+}
+
+
+void FSUNMASSSPGMR_SETMAXRS(int *maxrs, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPGMRSetMaxRestarts(F2C_ARKODE_mass_sol, *maxrs);
+}
diff --git a/src/sunlinsol_spgmr/fsunlinsol_spgmr.h b/src/sunlinsol_spgmr/fsunlinsol_spgmr.h
new file mode 100644
index 0000000..4623160
--- /dev/null
+++ b/src/sunlinsol_spgmr/fsunlinsol_spgmr.h
@@ -0,0 +1,92 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_spgmr.c) contains the
+ * definitions needed for the initialization of SPGMR
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_SPGMR_H
+#define _FSUNLINSOL_SPGMR_H
+
+#include <sunlinsol/sunlinsol_spgmr.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNSPGMR_INIT            SUNDIALS_F77_FUNC(fsunspgmrinit,            FSUNSPGMRINIT)
+#define FSUNSPGMR_SETGSTYPE       SUNDIALS_F77_FUNC(fsunspgmrsetgstype,       FSUNSPGMRSETGSTYPE)
+#define FSUNSPGMR_SETPRECTYPE     SUNDIALS_F77_FUNC(fsunspgmrsetprectype,     FSUNSPGMRSETPRECTYPE)
+#define FSUNSPGMR_SETMAXRS        SUNDIALS_F77_FUNC(fsunspgmrsetmaxrs,        FSUNSPGMRSETMAXRS)
+#define FSUNMASSSPGMR_INIT        SUNDIALS_F77_FUNC(fsunmassspgmrinit,        FSUNMASSSPGMRINIT)
+#define FSUNMASSSPGMR_SETGSTYPE   SUNDIALS_F77_FUNC(fsunmassspgmrsetgstype,   FSUNMASSSPGMRSETGSTYPE)
+#define FSUNMASSSPGMR_SETPRECTYPE SUNDIALS_F77_FUNC(fsunmassspgmrsetprectype, FSUNMASSSPGMRSETPRECTYPE)
+#define FSUNMASSSPGMR_SETMAXRS    SUNDIALS_F77_FUNC(fsunmassspgmrsetmaxrs,    FSUNMASSSPGMRSETMAXRS)
+#else
+#define FSUNSPGMR_INIT            fsunspgmrinit_
+#define FSUNSPGMR_SETGSTYPE       fsunspgmrsetgstype_
+#define FSUNSPGMR_SETPRECTYPE     fsunspgmrsetprectype_
+#define FSUNSPGMR_SETMAXRS        fsunspgmrsetmaxrs_
+#define FSUNMASSSPGMR_INIT        fsunmassspgmrinit_
+#define FSUNMASSSPGMR_SETGSTYPE   fsunmassspgmrsetgstype_
+#define FSUNMASSSPGMR_SETPRECTYPE fsunmassspgmrsetprectype_
+#define FSUNMASSSPGMR_SETMAXRS    fsunmassspgmrsetmaxrs_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNSPGMR_INIT - initializes SPGMR linear solver for main problem
+ * FSUNSPGMR_SETGSTYPE - sets the Gram-Scmidt orthogonalization type for main problem
+ * FSUNSPGMR_SETPRECTYPE - sets the preconditioning type for main problem
+ * FSUNSPGMR_SETMAXRS - sets the maximum number of restarts to allow for main problem
+ *
+ * FSUNMASSSPGMR_INIT - initializes SPGMR linear solver for mass matrix solve
+ * FSUNMASSSPGMR_SETGSTYPE - sets the Gram-Scmidt orthogonalization type for mass matrix solve
+ * FSUNMASSSPGMR_SETPRECTYPE - sets the preconditioning type for mass matrix solve
+ * FSUNMASSSPGMR_SETMAXRS - sets the maximum number of restarts to allow for mass matrix solve
+ */
+
+void FSUNSPGMR_INIT(int *code, int *pretype, int *maxl, int *ier);
+void FSUNSPGMR_SETGSTYPE(int *code, int *gstype, int *ier);
+void FSUNSPGMR_SETPRECTYPE(int *code, int *pretype, int *ier);
+void FSUNSPGMR_SETMAXRS(int *code, int *maxrs, int *ier);
+
+void FSUNMASSSPGMR_INIT(int *pretype, int *maxl, int *ier);
+void FSUNMASSSPGMR_SETGSTYPE(int *gstype, int *ier);
+void FSUNMASSSPGMR_SETPRECTYPE(int *pretype, int *ier);
+void FSUNMASSSPGMR_SETMAXRS(int *maxrs, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_spgmr/sunlinsol_spgmr.c b/src/sunlinsol_spgmr/sunlinsol_spgmr.c
new file mode 100644
index 0000000..dc6dad3
--- /dev/null
+++ b/src/sunlinsol_spgmr/sunlinsol_spgmr.c
@@ -0,0 +1,701 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on sundials_spgmr.c code, written by Scott D. Cohen, 
+ *                Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the SPGMR implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_spgmr.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * SPGMR solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+  
+#define SPGMR_CONTENT(S)  ( (SUNLinearSolverContent_SPGMR)(S->content) )
+#define LASTFLAG(S)       ( SPGMR_CONTENT(S)->last_flag )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new SPGMR linear solver
+ */
+
+SUNLinearSolver SUNSPGMR(N_Vector y, int pretype, int maxl)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_SPGMR content;
+  
+  /* check for legal pretype and maxl values; if illegal use defaults */
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH))
+    pretype = PREC_NONE;
+  if (maxl <= 0)
+    maxl = SUNSPGMR_MAXL_DEFAULT;
+
+  /* check that the supplied N_Vector supports all requisite operations */
+  if ( (y->ops->nvclone == NULL) || (y->ops->nvdestroy == NULL) ||
+       (y->ops->nvlinearsum == NULL) || (y->ops->nvconst == NULL) ||
+       (y->ops->nvprod == NULL) || (y->ops->nvdiv == NULL) ||
+       (y->ops->nvscale == NULL) || (y->ops->nvdotprod == NULL) )
+    return(NULL);
+
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_SPGMR;
+  ops->setatimes         = SUNLinSolSetATimes_SPGMR;
+  ops->setpreconditioner = SUNLinSolSetPreconditioner_SPGMR;
+  ops->setscalingvectors = SUNLinSolSetScalingVectors_SPGMR;
+  ops->initialize        = SUNLinSolInitialize_SPGMR;
+  ops->setup             = SUNLinSolSetup_SPGMR;
+  ops->solve             = SUNLinSolSolve_SPGMR;
+  ops->numiters          = SUNLinSolNumIters_SPGMR;
+  ops->resnorm           = SUNLinSolResNorm_SPGMR;
+  ops->resid             = SUNLinSolResid_SPGMR;
+  ops->lastflag          = SUNLinSolLastFlag_SPGMR;  
+  ops->space             = SUNLinSolSpace_SPGMR;  
+  ops->free              = SUNLinSolFree_SPGMR;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_SPGMR) malloc(sizeof(struct _SUNLinearSolverContent_SPGMR));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->last_flag = 0;
+  content->maxl = maxl;
+  content->pretype = pretype;
+  content->gstype = SUNSPGMR_GSTYPE_DEFAULT;
+  content->max_restarts = SUNSPGMR_MAXRS_DEFAULT;
+  content->numiters = 0;
+  content->resnorm = ZERO;
+  content->xcor = N_VClone(y);
+  if (content->xcor == NULL)  return(NULL);
+  content->vtemp = N_VClone(y);
+  if (content->vtemp == NULL)  return(NULL);
+  content->s1 = NULL;
+  content->s2 = NULL;
+  content->ATimes = NULL;
+  content->ATData = NULL;
+  content->Psetup = NULL;
+  content->Psolve = NULL;
+  content->PData = NULL;
+  content->V = NULL;
+  content->Hes = NULL;
+  content->givens = NULL;
+  content->yg = NULL;
+
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the type of preconditioning for SPGMR to use 
+ */
+
+SUNDIALS_EXPORT int SUNSPGMRSetPrecType(SUNLinearSolver S, int pretype) 
+{
+  /* Check for legal pretype */ 
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
+    return(SUNLS_ILL_INPUT);
+  }
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set pretype */
+  SPGMR_CONTENT(S)->pretype = pretype;
+  return(SUNLS_SUCCESS);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the type of Gram-Schmidt orthogonalization for SPGMR to use
+ */
+
+SUNDIALS_EXPORT int SUNSPGMRSetGSType(SUNLinearSolver S, int gstype)
+{
+  /* Check for legal gstype */ 
+  if ((gstype != MODIFIED_GS) && (gstype != CLASSICAL_GS)) {
+    return(SUNLS_ILL_INPUT);
+  }
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set pretype */
+  SPGMR_CONTENT(S)->gstype = gstype;
+  return(SUNLS_SUCCESS);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the maximum number of GMRES restarts to allow
+ */
+
+SUNDIALS_EXPORT int SUNSPGMRSetMaxRestarts(SUNLinearSolver S, int maxrs)
+{
+  /* Illegal maxrs implies use of default value */ 
+  if (maxrs < 0)
+    maxrs = SUNSPGMR_MAXRS_DEFAULT;
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set max_restarts */
+  SPGMR_CONTENT(S)->max_restarts = maxrs;
+  return(SUNLS_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_SPGMR(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_ITERATIVE);
+}
+
+
+int SUNLinSolInitialize_SPGMR(SUNLinearSolver S)
+{
+  int k;
+  SUNLinearSolverContent_SPGMR content;
+
+  /* set shortcut to SPGMR memory structure */
+  if (S == NULL) return(SUNLS_MEM_NULL);  
+  content = SPGMR_CONTENT(S);
+
+  /* ensure valid options */
+  if (content->max_restarts < 0) 
+    content->max_restarts = SUNSPGMR_MAXRS_DEFAULT;
+  if ( (content->pretype != PREC_LEFT) && 
+       (content->pretype != PREC_RIGHT) && 
+       (content->pretype != PREC_BOTH) )
+    content->pretype = PREC_NONE;
+
+
+  /* allocate solver-specific memory (where the size depends on the
+     choice of maxl) here */
+
+  /*   Krylov subspace vectors */
+  content->V = N_VCloneVectorArray(content->maxl+1, content->vtemp);
+  if (content->V == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  /*   Hessenberg matrix Hes */
+  content->Hes = (realtype **) malloc((content->maxl+1)*sizeof(realtype *)); 
+  if (content->Hes == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  for (k=0; k<=content->maxl; k++) {
+    content->Hes[k] = NULL;
+    content->Hes[k] = (realtype *) malloc(content->maxl*sizeof(realtype));
+    if (content->Hes[k] == NULL) {
+      SUNLinSolFree(S);
+      content->last_flag = SUNLS_MEM_FAIL;
+      return(SUNLS_MEM_FAIL);
+    }
+  }
+  
+  /*   Givens rotation components */
+  content->givens = NULL;
+  content->givens = (realtype *) malloc(2*content->maxl*sizeof(realtype));
+  if (content->givens == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  /*    y and g vectors */
+  content->yg = (realtype *) malloc((content->maxl+1)*sizeof(realtype));
+  if (content->yg == NULL) {
+    SUNLinSolFree(S);
+    content->last_flag = SUNLS_MEM_FAIL;
+    return(SUNLS_MEM_FAIL);
+  }
+
+  /* return with success */
+  content->last_flag = SUNLS_SUCCESS;
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSetATimes_SPGMR(SUNLinearSolver S, void* ATData, 
+                             ATimesFn ATimes)
+{
+  /* set function pointers to integrator-supplied ATimes routine 
+     and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPGMR_CONTENT(S)->ATimes = ATimes;
+  SPGMR_CONTENT(S)->ATData = ATData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetPreconditioner_SPGMR(SUNLinearSolver S, void* PData,
+                                    PSetupFn Psetup, PSolveFn Psolve)
+{
+  /* set function pointers to integrator-supplied Psetup and PSolve
+     routines and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPGMR_CONTENT(S)->Psetup = Psetup;
+  SPGMR_CONTENT(S)->Psolve = Psolve;
+  SPGMR_CONTENT(S)->PData = PData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetScalingVectors_SPGMR(SUNLinearSolver S, N_Vector s1,
+                                     N_Vector s2)
+{
+  /* set N_Vector pointers to integrator-supplied scaling vectors, 
+     and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPGMR_CONTENT(S)->s1 = s1;
+  SPGMR_CONTENT(S)->s2 = s2;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_SPGMR(SUNLinearSolver S, SUNMatrix A)
+{
+  int ier;
+  PSetupFn Psetup;
+  void* PData;
+
+  /* Set shortcuts to SPGMR memory structures */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  Psetup = SPGMR_CONTENT(S)->Psetup;
+  PData = SPGMR_CONTENT(S)->PData;
+  
+  /* no solver-specific setup is required, but if user-supplied 
+     Psetup routine exists, call that here */
+  if (Psetup != NULL) {
+    ier = Psetup(PData);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+	SUNLS_PSET_FAIL_UNREC : SUNLS_PSET_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  
+  /* return with success */ 
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSolve_SPGMR(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                         N_Vector b, realtype delta)
+{
+  /* local data and shortcut variables */
+  N_Vector *V, xcor, vtemp, s1, s2;
+  realtype **Hes, *givens, *yg, *res_norm;
+  realtype beta, rotation_product, r_norm, s_product, rho;
+  booleantype preOnLeft, preOnRight, scale2, scale1, converged;
+  int i, j, k, l, l_plus_1, l_max, krydim, ier, ntries, max_restarts, gstype;
+  int *nli;
+  void *A_data, *P_data;
+  ATimesFn atimes;
+  PSolveFn psolve;
+
+  /* Initialize some variables */
+  l_plus_1 = 0;
+  krydim = 0;
+
+  /* Make local shorcuts to solver variables. */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  l_max        = SPGMR_CONTENT(S)->maxl;
+  max_restarts = SPGMR_CONTENT(S)->max_restarts;
+  gstype       = SPGMR_CONTENT(S)->gstype;
+  V            = SPGMR_CONTENT(S)->V;
+  Hes          = SPGMR_CONTENT(S)->Hes;
+  givens       = SPGMR_CONTENT(S)->givens;
+  xcor         = SPGMR_CONTENT(S)->xcor;
+  yg           = SPGMR_CONTENT(S)->yg;
+  vtemp        = SPGMR_CONTENT(S)->vtemp;
+  s1           = SPGMR_CONTENT(S)->s1;
+  s2           = SPGMR_CONTENT(S)->s2;
+  A_data       = SPGMR_CONTENT(S)->ATData;
+  P_data       = SPGMR_CONTENT(S)->PData;
+  atimes       = SPGMR_CONTENT(S)->ATimes;
+  psolve       = SPGMR_CONTENT(S)->Psolve;
+  nli          = &(SPGMR_CONTENT(S)->numiters);
+  res_norm     = &(SPGMR_CONTENT(S)->resnorm);
+
+  /* Initialize counters and convergence flag */
+  *nli = 0;
+  converged = SUNFALSE;
+
+  /* set booleantype flags for internal solver options */
+  preOnLeft  = ( (SPGMR_CONTENT(S)->pretype == PREC_LEFT) || 
+                 (SPGMR_CONTENT(S)->pretype == PREC_BOTH) );
+  preOnRight = ( (SPGMR_CONTENT(S)->pretype == PREC_RIGHT) || 
+                 (SPGMR_CONTENT(S)->pretype == PREC_BOTH) );
+  scale1 = (s1 != NULL);
+  scale2 = (s2 != NULL);
+
+  /* Set vtemp and V[0] to initial (unscaled) residual r_0 = b - A*x_0 */
+  if (N_VDotProd(x, x) == ZERO) {
+    N_VScale(ONE, b, vtemp);
+  } else {
+    ier = atimes(A_data, x, vtemp);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+          SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    N_VLinearSum(ONE, b, -ONE, vtemp, vtemp);
+  }
+  N_VScale(ONE, vtemp, V[0]);
+
+  /* Apply left preconditioner and left scaling to V[0] = r_0 */
+  if (preOnLeft) {
+    ier = psolve(P_data, V[0], vtemp, delta, PREC_LEFT);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  } else {
+    N_VScale(ONE, V[0], vtemp);
+  }
+  
+  if (scale1) {
+    N_VProd(s1, vtemp, V[0]);   
+  } else {
+    N_VScale(ONE, vtemp, V[0]);
+  }
+
+  /* Set r_norm = beta to L2 norm of V[0] = s1 P1_inv r_0, and
+     return if small  */
+  *res_norm = r_norm = beta = SUNRsqrt(N_VDotProd(V[0], V[0])); 
+  if (r_norm <= delta) {
+    LASTFLAG(S) = SUNLS_SUCCESS;
+    return(LASTFLAG(S));
+  }
+
+  /* Initialize rho to avoid compiler warning message */
+  rho = beta;
+
+  /* Set xcor = 0 */
+  N_VConst(ZERO, xcor);
+
+  /* Begin outer iterations: up to (max_restarts + 1) attempts */  
+  for (ntries=0; ntries<=max_restarts; ntries++) {
+    
+    /* Initialize the Hessenberg matrix Hes and Givens rotation
+       product.  Normalize the initial vector V[0] */
+    for (i=0; i<=l_max; i++)
+      for (j=0; j<l_max; j++)
+        Hes[i][j] = ZERO;
+
+    rotation_product = ONE;    
+    N_VScale(ONE/r_norm, V[0], V[0]);
+    
+    /* Inner loop: generate Krylov sequence and Arnoldi basis */    
+    for (l=0; l<l_max; l++) {
+      (*nli)++;      
+      krydim = l_plus_1 = l + 1;
+      
+      /* Generate A-tilde V[l], where A-tilde = s1 P1_inv A P2_inv s2_inv */
+      
+      /*   Apply right scaling: vtemp = s2_inv V[l] */
+      if (scale2) N_VDiv(V[l], s2, vtemp);
+      else N_VScale(ONE, V[l], vtemp);
+      
+      /*   Apply right preconditioner: vtemp = P2_inv s2_inv V[l] */ 
+      if (preOnRight) {
+        N_VScale(ONE, vtemp, V[l_plus_1]);
+        ier = psolve(P_data, V[l_plus_1], vtemp, delta, PREC_RIGHT);
+        if (ier != 0) {
+          LASTFLAG(S) = (ier < 0) ? 
+              SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+          return(LASTFLAG(S));
+        }
+      }
+      
+      /* Apply A: V[l+1] = A P2_inv s2_inv V[l] */
+      ier = atimes( A_data, vtemp, V[l_plus_1] );
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ? 
+            SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+      
+      /* Apply left preconditioning: vtemp = P1_inv A P2_inv s2_inv V[l] */
+      if (preOnLeft) {
+        ier = psolve(P_data, V[l_plus_1], vtemp, delta, PREC_LEFT);
+        if (ier != 0) {
+          LASTFLAG(S) = (ier < 0) ? 
+              SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+          return(LASTFLAG(S));
+        }
+      } else {
+        N_VScale(ONE, V[l_plus_1], vtemp);
+      }
+      
+      /* Apply left scaling: V[l+1] = s1 P1_inv A P2_inv s2_inv V[l] */
+      if (scale1) {
+        N_VProd(s1, vtemp, V[l_plus_1]);
+      } else {
+        N_VScale(ONE, vtemp, V[l_plus_1]);
+      }
+      
+      /*  Orthogonalize V[l+1] against previous V[i]: V[l+1] = w_tilde */
+      if (gstype == CLASSICAL_GS) {
+        if (ClassicalGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l]),
+                        vtemp, yg) != 0) {
+          LASTFLAG(S) = SUNLS_GS_FAIL;
+          return(LASTFLAG(S));
+        }
+      } else {
+        if (ModifiedGS(V, Hes, l_plus_1, l_max, &(Hes[l_plus_1][l])) != 0) {
+          LASTFLAG(S) = SUNLS_GS_FAIL;
+          return(LASTFLAG(S));
+        }
+      }
+      
+      /*  Update the QR factorization of Hes */
+      if(QRfact(krydim, Hes, givens, l) != 0 ) {
+        LASTFLAG(S) = SUNLS_QRFACT_FAIL;
+        return(LASTFLAG(S));
+      }
+      
+      /*  Update residual norm estimate; break if convergence test passes */
+      rotation_product *= givens[2*l+1];
+      *res_norm = rho = SUNRabs(rotation_product*r_norm);
+      
+      if (rho <= delta) { converged = SUNTRUE; break; }
+      
+      /* Normalize V[l+1] with norm value from the Gram-Schmidt routine */
+      N_VScale(ONE/Hes[l_plus_1][l], V[l_plus_1], V[l_plus_1]);
+    }
+    
+    /* Inner loop is done.  Compute the new correction vector xcor */
+    
+    /*   Construct g, then solve for y */
+    yg[0] = r_norm;
+    for (i=1; i<=krydim; i++) yg[i]=ZERO;
+    if (QRsol(krydim, Hes, givens, yg) != 0) {
+      LASTFLAG(S) = SUNLS_QRSOL_FAIL;
+      return(LASTFLAG(S));
+    }
+    
+    /*   Add correction vector V_l y to xcor */
+    for (k=0; k<krydim; k++)
+      N_VLinearSum(yg[k], V[k], ONE, xcor, xcor);
+    
+    /* If converged, construct the final solution vector x and return */
+    if (converged) {
+      
+      /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor */
+      if (scale2) N_VDiv(xcor, s2, xcor);
+      if (preOnRight) {
+        ier = psolve(P_data, xcor, vtemp, delta, PREC_RIGHT);
+        if (ier != 0) {
+          LASTFLAG(S) = (ier < 0) ? 
+              SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+          return(LASTFLAG(S));
+        }
+      } else {
+        N_VScale(ONE, xcor, vtemp);
+      }
+      
+      /* Add vtemp to initial x to get final solution x, and return */
+      N_VLinearSum(ONE, x, ONE, vtemp, x);
+      
+      LASTFLAG(S) = SUNLS_SUCCESS;
+      return(LASTFLAG(S));
+    }
+    
+    /* Not yet converged; if allowed, prepare for restart */    
+    if (ntries == max_restarts) break;
+    
+    /* Construct last column of Q in yg */
+    s_product = ONE;
+    for (i=krydim; i>0; i--) {
+      yg[i] = s_product*givens[2*i-2];
+      s_product *= givens[2*i-1];
+    }
+    yg[0] = s_product;
+    
+    /* Scale r_norm and yg */
+    r_norm *= s_product;
+    for (i=0; i<=krydim; i++)
+      yg[i] *= r_norm;
+    r_norm = SUNRabs(r_norm);
+    
+    /* Multiply yg by V_(krydim+1) to get last residual vector; restart */
+    N_VScale(yg[0], V[0], V[0]);
+    for (k=1; k<=krydim; k++)
+      N_VLinearSum(yg[k], V[k], ONE, V[0], V[0]);
+    
+  }
+  
+  /* Failed to converge, even after allowed restarts.
+     If the residual norm was reduced below its initial value, compute
+     and return x anyway.  Otherwise return failure flag. */
+  if (rho < beta) {
+    
+    /* Apply right scaling and right precond.: vtemp = P2_inv s2_inv xcor */    
+    if (scale2) N_VDiv(xcor, s2, xcor);
+    if (preOnRight) {
+      ier = psolve(P_data, xcor, vtemp, delta, PREC_RIGHT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ? 
+            SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+      } else {
+      N_VScale(ONE, xcor, vtemp);
+    }
+
+    /* Add vtemp to initial x to get final solution x, and return */
+    N_VLinearSum(ONE, x, ONE, vtemp, x);
+    
+    LASTFLAG(S) = SUNLS_RES_REDUCED;
+    return(LASTFLAG(S));
+  }
+
+  LASTFLAG(S) = SUNLS_CONV_FAIL;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolNumIters_SPGMR(SUNLinearSolver S)
+{
+  /* return the stored 'numiters' value */
+  if (S == NULL) return(-1);
+  return (SPGMR_CONTENT(S)->numiters);
+}
+
+
+realtype SUNLinSolResNorm_SPGMR(SUNLinearSolver S)
+{
+  /* return the stored 'resnorm' value */
+  if (S == NULL) return(-ONE);
+  return (SPGMR_CONTENT(S)->resnorm);
+}
+
+
+N_Vector SUNLinSolResid_SPGMR(SUNLinearSolver S)
+{
+  /* return the stored 'vtemp' vector */
+  return (SPGMR_CONTENT(S)->vtemp);
+}
+
+
+long int SUNLinSolLastFlag_SPGMR(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  if (S == NULL) return(-1);
+  return (LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_SPGMR(SUNLinearSolver S, 
+                         long int *lenrwLS, 
+                         long int *leniwLS)
+{
+  int maxl;
+  sunindextype liw1, lrw1;
+  maxl = SPGMR_CONTENT(S)->maxl;
+  if (SPGMR_CONTENT(S)->vtemp->ops->nvspace)
+    N_VSpace(SPGMR_CONTENT(S)->vtemp, &lrw1, &liw1);
+  else
+    lrw1 = liw1 = 0;
+  *lenrwLS = lrw1*(maxl + 5) + maxl*(maxl + 4) + 1;
+  *leniwLS = liw1*(maxl + 5);
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolFree_SPGMR(SUNLinearSolver S)
+{
+  int k;
+
+  if (S == NULL) return(SUNLS_SUCCESS);
+
+  /* delete items from within the content structure */
+  if (SPGMR_CONTENT(S)->xcor)
+    N_VDestroy(SPGMR_CONTENT(S)->xcor);
+  if (SPGMR_CONTENT(S)->vtemp)
+    N_VDestroy(SPGMR_CONTENT(S)->vtemp);
+  if (SPGMR_CONTENT(S)->V)
+    N_VDestroyVectorArray(SPGMR_CONTENT(S)->V, 
+                          SPGMR_CONTENT(S)->maxl+1);
+  if (SPGMR_CONTENT(S)->Hes) {
+    for (k=0; k<=SPGMR_CONTENT(S)->maxl; k++)
+      if (SPGMR_CONTENT(S)->Hes[k])
+        free(SPGMR_CONTENT(S)->Hes[k]);
+    free(SPGMR_CONTENT(S)->Hes);
+  }
+  if (SPGMR_CONTENT(S)->givens)
+    free(SPGMR_CONTENT(S)->givens);
+  if (SPGMR_CONTENT(S)->yg)
+    free(SPGMR_CONTENT(S)->yg);
+
+  /* delete generic structures */
+  free(S->content);  S->content = NULL;
+  free(S->ops);  S->ops = NULL;
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
diff --git a/src/sunlinsol_sptfqmr/CMakeLists.txt b/src/sunlinsol_sptfqmr/CMakeLists.txt
new file mode 100644
index 0000000..99d079d
--- /dev/null
+++ b/src/sunlinsol_sptfqmr/CMakeLists.txt
@@ -0,0 +1,106 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the SPTFQMR SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_SPTFQMR\n\")")
+
+# Add variable sunlinsolsptfqmr_SOURCES with the sources for the SUNLINSOLSPTFQMR lib
+SET(sunlinsolsptfqmr_SOURCES sunlinsol_sptfqmr.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLSPTFQMR library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_iterative.c
+  )
+
+# Add variable sunlinsolsptfqmr_HEADERS with the exported SUNLINSOLSPTFQMR header files
+SET(sunlinsolsptfqmr_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_sptfqmr.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLSPTFQMR library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLSPTFQMR library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolsptfqmr_static STATIC ${sunlinsolsptfqmr_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolsptfqmr_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolsptfqmr CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolsptfqmr_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLSPTFQMR library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLSPTFQMR library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolsptfqmr_shared SHARED ${sunlinsolsptfqmr_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsolsptfqmr_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolsptfqmr_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolsptfqmr CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolsptfqmr_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolsptfqmr_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLSPTFQMR header files
+INSTALL(FILES ${sunlinsolsptfqmr_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled, build and install the FSUNLINSOLSPTFQMR library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunlinsolsptfqmr_SOURCES fsunlinsol_sptfqmr.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolsptfqmr_static STATIC ${fsunlinsolsptfqmr_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolsptfqmr_static
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolsptfqmr CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunlinsolsptfqmr_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunlinsolsptfqmr_shared ${fsunlinsolsptfqmr_SOURCES})
+
+    # fsunlinsolsptfqmr depends on fnvecserial and sunlinsolsptfqmr
+    TARGET_LINK_LIBRARIES(sundials_fsunlinsolsptfqmr_shared
+      sundials_fnvecserial_shared
+      sundials_sunlinsolsptfqmr_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolsptfqmr_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunlinsolsptfqmr CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunlinsolsptfqmr_shared 
+      PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunlinsolsptfqmr_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_SPTFQMR module")
diff --git a/src/sunlinsol_sptfqmr/README b/src/sunlinsol_sptfqmr/README
new file mode 100644
index 0000000..075ed98
--- /dev/null
+++ b/src/sunlinsol_sptfqmr/README
@@ -0,0 +1,41 @@
+                     SUNLINSOL_SPTFQMR
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Scaled, preconditioned, Transpose-Free Quasi-Minimum Residual method
+implementation of the SUNLINSOL module for SUNDIALS.  
+
+SUNLINSOL_SPTFQMR defines the content field of SUNMatrix to be a structure 
+containing a X, along with a long integer for any error flag that arises in
+the linear solver routines.
+
+SUNLINSOL_SPTFQMR defines N macros to provide access to the content of 
+a SPTFQMR SUNLinearSolver, and constructor for the SPTFQMR
+SUNLinearSolver, in addition to implementation of all linear
+solver operations defined by the generic SUNLINSOL module in the table
+of operations.
+
+
+A. Documentation
+----------------
+
+The SPTFQMR SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c b/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c
new file mode 100644
index 0000000..207f64b
--- /dev/null
+++ b/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.c
@@ -0,0 +1,195 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_sptfqmr.h) contains the
+ * implementation needed for the Fortran initialization of SPTFQMR
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_sptfqmr.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNSPTFQMR_INIT(int *code, int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNSPTFQMR(F2C_CVODE_vec, *pretype, *maxl);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNSPTFQMR(F2C_IDA_vec, *pretype, *maxl);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNSPTFQMR(F2C_KINSOL_vec, *pretype, *maxl);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNSPTFQMR(F2C_ARKODE_vec, *pretype, *maxl);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPTFQMR_SETPRECTYPE(int *code, int *pretype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetPrecType(F2C_CVODE_linsol, *pretype);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetPrecType(F2C_IDA_linsol, *pretype);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetPrecType(F2C_KINSOL_linsol, *pretype);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetPrecType(F2C_ARKODE_linsol, *pretype);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSPTFQMR_SETMAXL(int *code, int *maxl, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (!F2C_CVODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetMaxl(F2C_CVODE_linsol, *maxl);
+    break;
+  case FCMIX_IDA:
+    if (!F2C_IDA_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetMaxl(F2C_IDA_linsol, *maxl);
+    break;
+  case FCMIX_KINSOL:
+    if (!F2C_KINSOL_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetMaxl(F2C_KINSOL_linsol, *maxl);
+    break;
+  case FCMIX_ARKODE:
+    if (!F2C_ARKODE_linsol) {
+      *ier = -1;
+      return;
+    }
+    *ier = SUNSPTFQMRSetMaxl(F2C_ARKODE_linsol, *maxl);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSSPTFQMR_INIT(int *pretype, int *maxl, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNSPTFQMR(F2C_ARKODE_vec, *pretype, *maxl);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
+void FSUNMASSSPTFQMR_SETPRECTYPE(int *pretype, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPTFQMRSetPrecType(F2C_ARKODE_mass_sol, *pretype);
+}
+
+
+void FSUNMASSSPTFQMR_SETMAXL(int *maxl, int *ier)
+{
+  *ier = 0;
+  if (!F2C_ARKODE_mass_sol) {
+      *ier = -1;
+      return;
+  }
+  *ier = SUNSPTFQMRSetMaxl(F2C_ARKODE_mass_sol, *maxl);
+}
diff --git a/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.h b/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.h
new file mode 100644
index 0000000..0e874fd
--- /dev/null
+++ b/src/sunlinsol_sptfqmr/fsunlinsol_sptfqmr.h
@@ -0,0 +1,84 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_sptfqmr.c) contains the
+ * definitions needed for the initialization of SPTFQMR
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_SPTFQMR_H
+#define _FSUNLINSOL_SPTFQMR_H
+
+#include <sunlinsol/sunlinsol_sptfqmr.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNSPTFQMR_INIT            SUNDIALS_F77_FUNC(fsunsptfqmrinit,            FSUNSPTFQMRINIT)
+#define FSUNSPTFQMR_SETPRECTYPE     SUNDIALS_F77_FUNC(fsunsptfqmrsetprectype,     FSUNSPTFQMRSETPRECTYPE)
+#define FSUNSPTFQMR_SETMAXL         SUNDIALS_F77_FUNC(fsunsptfqmrsetmaxl,         FSUNSPTFQMRSETMAXL)
+#define FSUNMASSSPTFQMR_INIT        SUNDIALS_F77_FUNC(fsunmasssptfqmrinit,        FSUNMASSSPTFQMRINIT)
+#define FSUNMASSSPTFQMR_SETPRECTYPE SUNDIALS_F77_FUNC(fsunmasssptfqmrsetprectype, FSUNMASSSPTFQMRSETPRECTYPE)
+#define FSUNMASSSPTFQMR_SETMAXL     SUNDIALS_F77_FUNC(fsunmasssptfqmrsetmaxl,     FSUNMASSSPTFQMRSETMAXL)
+#else
+#define FSUNSPTFQMR_INIT            fsunsptfqmrinit_
+#define FSUNSPTFQMR_SETPRECTYPE     fsunsptfqmrsetprectype_
+#define FSUNSPTFQMR_SETMAXL         fsunsptfqmrsetmaxl_
+#define FSUNMASSSPTFQMR_INIT        fsunmasssptfqmrinit_
+#define FSUNMASSSPTFQMR_SETPRECTYPE fsunmasssptfqmrsetprectype_
+#define FSUNMASSSPTFQMR_SETMAXL     fsunmasssptfqmrsetmaxl_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNSPTFQMR_INIT - initializes SPTFQMR linear solver for main problem
+ * FSUNSPTFQMR_SETPRECTYPE - sets the preconditioning type for main problem
+ * FSUNSPTFQMR_SETMAXL - sets the max number of iterations for main problem
+ *
+ * FSUNMASSSPTFQMR_INIT - initializes SPTFQMR linear solver for mass matrix solve
+ * FSUNMASSSPTFQMR_SETPRECTYPE - sets the preconditioning type for mass matrix solve
+ * FSUNMASSSPTFQMR_SETMAXL - sets the max number of iterations for mass matrix solve
+ */
+
+void FSUNSPTFQMR_INIT(int *code, int *pretype, int *maxl, int *ier);
+void FSUNSPTFQMR_SETPRECTYPE(int *code, int *pretype, int *ier);
+void FSUNSPTFQMR_SETMAXL(int *code, int *maxl, int *ier);
+
+void FSUNMASSSPTFQMR_INIT(int *pretype, int *maxl, int *ier);
+void FSUNMASSSPTFQMR_SETPRECTYPE(int *pretype, int *ier);
+void FSUNMASSSPTFQMR_SETMAXL(int *maxl, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c b/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
new file mode 100644
index 0000000..1d3126e
--- /dev/null
+++ b/src/sunlinsol_sptfqmr/sunlinsol_sptfqmr.c
@@ -0,0 +1,743 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on sundials_sptfqmr.c code, written by Aaron Collier @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the SPTFQMR implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_sptfqmr.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+/*
+ * -----------------------------------------------------------------
+ * SPTFQMR solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+  
+#define SPTFQMR_CONTENT(S)  ( (SUNLinearSolverContent_SPTFQMR)(S->content) )
+#define LASTFLAG(S)         ( SPTFQMR_CONTENT(S)->last_flag )
+
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new SPTFQMR linear solver
+ */
+
+SUNLinearSolver SUNSPTFQMR(N_Vector y, int pretype, int maxl)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_SPTFQMR content;
+  
+  /* check for legal pretype and maxl values; if illegal use defaults */
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH))
+    pretype = PREC_NONE;
+  if (maxl <= 0)
+    maxl = SUNSPTFQMR_MAXL_DEFAULT;
+
+  /* check that the supplied N_Vector supports all requisite operations */
+  if ( (y->ops->nvclone == NULL) || (y->ops->nvdestroy == NULL) ||
+       (y->ops->nvlinearsum == NULL) || (y->ops->nvconst == NULL) ||
+       (y->ops->nvprod == NULL) || (y->ops->nvdiv == NULL) ||
+       (y->ops->nvscale == NULL) || (y->ops->nvdotprod == NULL) )
+    return(NULL);
+
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_SPTFQMR;
+  ops->setatimes         = SUNLinSolSetATimes_SPTFQMR;
+  ops->setpreconditioner = SUNLinSolSetPreconditioner_SPTFQMR;
+  ops->setscalingvectors = SUNLinSolSetScalingVectors_SPTFQMR;
+  ops->initialize        = SUNLinSolInitialize_SPTFQMR;
+  ops->setup             = SUNLinSolSetup_SPTFQMR;
+  ops->solve             = SUNLinSolSolve_SPTFQMR;
+  ops->numiters          = SUNLinSolNumIters_SPTFQMR;
+  ops->resnorm           = SUNLinSolResNorm_SPTFQMR;
+  ops->resid             = SUNLinSolResid_SPTFQMR;
+  ops->lastflag          = SUNLinSolLastFlag_SPTFQMR;  
+  ops->space             = SUNLinSolSpace_SPTFQMR;  
+  ops->free              = SUNLinSolFree_SPTFQMR;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_SPTFQMR) malloc(sizeof(struct _SUNLinearSolverContent_SPTFQMR));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->last_flag = 0;
+  content->maxl = maxl;
+  content->pretype = pretype;
+  content->numiters = 0;
+  content->resnorm = ZERO;
+  content->r_star = N_VClone(y);
+  if (content->r_star == NULL)  return(NULL);
+  content->q = N_VClone(y);
+  if (content->q == NULL)  return(NULL);
+  content->d = N_VClone(y);
+  if (content->d == NULL)  return(NULL);
+  content->v = N_VClone(y);
+  if (content->v == NULL)  return(NULL);
+  content->p = N_VClone(y);
+  if (content->p == NULL)  return(NULL);
+  content->r = N_VCloneVectorArray(2, y);
+  if (content->r == NULL)  return(NULL);
+  content->u = N_VClone(y);
+  if (content->u == NULL)  return(NULL);
+  content->vtemp1 = N_VClone(y);
+  if (content->vtemp1 == NULL)  return(NULL);
+  content->vtemp2 = N_VClone(y);
+  if (content->vtemp2 == NULL)  return(NULL);
+  content->vtemp3 = N_VClone(y);
+  if (content->vtemp3 == NULL)  return(NULL);
+  content->s1 = NULL;
+  content->s2 = NULL;
+  content->ATimes = NULL;
+  content->ATData = NULL;
+  content->Psetup = NULL;
+  content->Psolve = NULL;
+  content->PData = NULL;
+
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the type of preconditioning for SPTFQMR to use 
+ */
+
+SUNDIALS_EXPORT int SUNSPTFQMRSetPrecType(SUNLinearSolver S, int pretype) 
+{
+  /* Check for legal pretype */ 
+  if ((pretype != PREC_NONE)  && (pretype != PREC_LEFT) &&
+      (pretype != PREC_RIGHT) && (pretype != PREC_BOTH)) {
+    return(SUNLS_ILL_INPUT);
+  }
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set pretype */
+  SPTFQMR_CONTENT(S)->pretype = pretype;
+  return(SUNLS_SUCCESS);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the maximum number of iterations for SPTFQMR to use 
+ */
+
+SUNDIALS_EXPORT int SUNSPTFQMRSetMaxl(SUNLinearSolver S, int maxl) 
+{
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Check for legal pretype */ 
+  if (maxl <= 0)
+    maxl = SUNSPTFQMR_MAXL_DEFAULT;
+
+  /* Set pretype */
+  SPTFQMR_CONTENT(S)->maxl = maxl;
+  return(SUNLS_SUCCESS);
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_SPTFQMR(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_ITERATIVE);
+}
+
+
+int SUNLinSolInitialize_SPTFQMR(SUNLinearSolver S)
+{
+  SUNLinearSolverContent_SPTFQMR content;
+
+  /* set shortcut to SPTFQMR memory structure */
+  if (S == NULL) return(SUNLS_MEM_NULL);  
+  content = SPTFQMR_CONTENT(S);
+
+  /* ensure valid options */
+  if ( (content->pretype != PREC_LEFT) && 
+       (content->pretype != PREC_RIGHT) && 
+       (content->pretype != PREC_BOTH) )
+    content->pretype = PREC_NONE;
+  if (content->maxl <= 0) 
+    content->maxl = SUNSPTFQMR_MAXL_DEFAULT;
+
+  /* no additional memory to allocate */
+  
+  /* return with success */
+  content->last_flag = SUNLS_SUCCESS;
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSetATimes_SPTFQMR(SUNLinearSolver S, void* ATData, 
+                               ATimesFn ATimes)
+{
+  /* set function pointers to integrator-supplied ATimes routine
+     and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPTFQMR_CONTENT(S)->ATimes = ATimes;
+  SPTFQMR_CONTENT(S)->ATData = ATData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetPreconditioner_SPTFQMR(SUNLinearSolver S, void* PData,
+                                       PSetupFn Psetup, PSolveFn Psolve)
+{
+  /* set function pointers to integrator-supplied Psetup and PSolve
+     routines and data, and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPTFQMR_CONTENT(S)->Psetup = Psetup;
+  SPTFQMR_CONTENT(S)->Psolve = Psolve;
+  SPTFQMR_CONTENT(S)->PData = PData;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetScalingVectors_SPTFQMR(SUNLinearSolver S,
+                                       N_Vector s1,
+                                       N_Vector s2)
+{
+  /* set N_Vector pointers to integrator-supplied scaling vectors, 
+     and return with success */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  SPTFQMR_CONTENT(S)->s1 = s1;
+  SPTFQMR_CONTENT(S)->s2 = s2;
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_SPTFQMR(SUNLinearSolver S, SUNMatrix A)
+{
+  int ier;
+  PSetupFn Psetup;
+  void* PData;
+
+  /* Set shortcuts to SPTFQMR memory structures */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  Psetup = SPTFQMR_CONTENT(S)->Psetup;
+  PData = SPTFQMR_CONTENT(S)->PData;
+  
+  /* no solver-specific setup is required, but if user-supplied 
+     Psetup routine exists, call that here */
+  if (Psetup != NULL) {
+    ier = Psetup(PData);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ? 
+	SUNLS_PSET_FAIL_UNREC : SUNLS_PSET_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  
+  /* return with success */ 
+  return(SUNLS_SUCCESS);
+}
+
+
+int SUNLinSolSolve_SPTFQMR(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                           N_Vector b, realtype delta)
+{
+  /* local data and shortcut variables */
+  realtype alpha, tau, eta, beta, c, sigma, v_bar, omega;
+  realtype rho[2];
+  realtype r_init_norm, r_curr_norm;
+  realtype temp_val;
+  booleantype preOnLeft, preOnRight, scale_x, scale_b, converged;
+  booleantype b_ok;
+  int n, m, ier, l_max;
+  void *A_data, *P_data;
+  ATimesFn atimes;
+  PSolveFn psolve;
+  realtype *res_norm;
+  int *nli;
+  N_Vector sx, sb, r_star, q, d, v, p, *r, u, vtemp1, vtemp2, vtemp3;
+  
+  /* Make local shorcuts to solver variables. */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+  l_max        = SPTFQMR_CONTENT(S)->maxl;
+  r_star       = SPTFQMR_CONTENT(S)->r_star;
+  q            = SPTFQMR_CONTENT(S)->q;
+  d            = SPTFQMR_CONTENT(S)->d;
+  v            = SPTFQMR_CONTENT(S)->v;
+  p            = SPTFQMR_CONTENT(S)->p;
+  r            = SPTFQMR_CONTENT(S)->r;
+  u            = SPTFQMR_CONTENT(S)->u;
+  vtemp1       = SPTFQMR_CONTENT(S)->vtemp1;
+  vtemp2       = SPTFQMR_CONTENT(S)->vtemp2;
+  vtemp3       = SPTFQMR_CONTENT(S)->vtemp3;
+  sb           = SPTFQMR_CONTENT(S)->s1;
+  sx           = SPTFQMR_CONTENT(S)->s2;
+  A_data       = SPTFQMR_CONTENT(S)->ATData;
+  P_data       = SPTFQMR_CONTENT(S)->PData;
+  atimes       = SPTFQMR_CONTENT(S)->ATimes;
+  psolve       = SPTFQMR_CONTENT(S)->Psolve;
+  nli          = &(SPTFQMR_CONTENT(S)->numiters);
+  res_norm     = &(SPTFQMR_CONTENT(S)->resnorm);
+
+  /* Initialize counters and convergence flag */
+  temp_val = r_curr_norm = -ONE;
+  *nli = 0;
+  converged = SUNFALSE;
+  b_ok = SUNFALSE;
+
+  /* set booleantype flags for internal solver options */
+  preOnLeft  = ( (SPTFQMR_CONTENT(S)->pretype == PREC_LEFT) || 
+                 (SPTFQMR_CONTENT(S)->pretype == PREC_BOTH) );
+  preOnRight = ( (SPTFQMR_CONTENT(S)->pretype == PREC_RIGHT) || 
+                 (SPTFQMR_CONTENT(S)->pretype == PREC_BOTH) );
+  scale_x = (sx != NULL);
+  scale_b = (sb != NULL);
+
+  /* Set r_star to initial (unscaled) residual r_star = r_0 = b - A*x_0 */
+  /* NOTE: if x == 0 then just set residual to b and continue */
+  if (N_VDotProd(x, x) == ZERO) N_VScale(ONE, b, r_star);
+  else {
+    ier = atimes(A_data, x, r_star);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    N_VLinearSum(ONE, b, -ONE, r_star, r_star);
+  }
+
+  /* Apply left preconditioner and b-scaling to r_star (or really just r_0) */
+  if (preOnLeft) {
+    ier = psolve(P_data, r_star, vtemp1, delta, PREC_LEFT);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  else N_VScale(ONE, r_star, vtemp1);
+  if (scale_b) N_VProd(sb, vtemp1, r_star);
+  else N_VScale(ONE, vtemp1, r_star);
+
+  /* Initialize rho[0] */
+  /* NOTE: initialized here to reduce number of computations - avoid need
+           to compute r_star^T*r_star twice, and avoid needlessly squaring
+           values */
+  rho[0] = N_VDotProd(r_star, r_star);
+
+  /* Compute norm of initial residual (r_0) to see if we really need
+     to do anything */
+  *res_norm = r_init_norm = SUNRsqrt(rho[0]);
+  if (r_init_norm <= delta) {
+    LASTFLAG(S) = SUNLS_SUCCESS;
+    return(LASTFLAG(S));
+  }
+
+  /* Set v = A*r_0 (preconditioned and scaled) */
+  if (scale_x) N_VDiv(r_star, sx, vtemp1);
+  else N_VScale(ONE, r_star, vtemp1);
+  if (preOnRight) {
+    N_VScale(ONE, vtemp1, v);
+    ier = psolve(P_data, v, vtemp1, delta, PREC_RIGHT);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  ier = atimes(A_data, vtemp1, v);
+  if (ier != 0) {
+    LASTFLAG(S) = (ier < 0) ?
+      SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+    return(LASTFLAG(S));
+  }
+  if (preOnLeft) {
+    ier = psolve(P_data, v, vtemp1, delta, PREC_LEFT);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+  }
+  else N_VScale(ONE, v, vtemp1);
+  if (scale_b) N_VProd(sb, vtemp1, v);
+  else N_VScale(ONE, vtemp1, v);
+
+  /* Initialize remaining variables */
+  N_VScale(ONE, r_star, r[0]);
+  N_VScale(ONE, r_star, u);
+  N_VScale(ONE, r_star, p);
+  N_VConst(ZERO, d);
+
+  tau = r_init_norm;
+  v_bar = eta = ZERO;
+
+  /* START outer loop */
+  for (n = 0; n < l_max; ++n) {
+
+    /* Increment linear iteration counter */
+    (*nli)++;
+
+    /* sigma = r_star^T*v */
+    sigma = N_VDotProd(r_star, v);
+
+    /* alpha = rho[0]/sigma */
+    alpha = rho[0]/sigma;
+
+    /* q = u-alpha*v */
+    N_VLinearSum(ONE, u, -alpha, v, q);
+
+    /* r[1] = r[0]-alpha*A*(u+q) */
+    N_VLinearSum(ONE, u, ONE, q, r[1]);
+    if (scale_x) N_VDiv(r[1], sx, r[1]);
+    if (preOnRight) {
+      N_VScale(ONE, r[1], vtemp1);
+      ier = psolve(P_data, vtemp1, r[1], delta, PREC_RIGHT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+    ier = atimes(A_data, r[1], vtemp1);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    if (preOnLeft) {
+      ier = psolve(P_data, vtemp1, r[1], delta, PREC_LEFT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+    else N_VScale(ONE, vtemp1, r[1]);
+    if (scale_b) N_VProd(sb, r[1], vtemp1);
+    else N_VScale(ONE, r[1], vtemp1);
+    N_VLinearSum(ONE, r[0], -alpha, vtemp1, r[1]);
+
+    /* START inner loop */
+    for (m = 0; m < 2; ++m) {
+
+      /* d = [*]+(v_bar^2*eta/alpha)*d */
+      /* NOTES:
+       *   (1) [*] = u if m == 0, and q if m == 1
+       *   (2) using temp_val reduces the number of required computations
+       *       if the inner loop is executed twice
+       */
+      if (m == 0) {
+	temp_val = SUNRsqrt(N_VDotProd(r[1], r[1]));
+	omega = SUNRsqrt(SUNRsqrt(N_VDotProd(r[0], r[0]))*temp_val);
+	N_VLinearSum(ONE, u, SUNSQR(v_bar)*eta/alpha, d, d);
+      }
+      else {
+	omega = temp_val;
+	N_VLinearSum(ONE, q, SUNSQR(v_bar)*eta/alpha, d, d);
+      }
+
+      /* v_bar = omega/tau */
+      v_bar = omega/tau;
+
+      /* c = (1+v_bar^2)^(-1/2) */
+      c = ONE / SUNRsqrt(ONE+SUNSQR(v_bar));
+
+      /* tau = tau*v_bar*c */
+      tau = tau*v_bar*c;
+
+      /* eta = c^2*alpha */
+      eta = SUNSQR(c)*alpha;
+
+      /* x = x+eta*d */
+      N_VLinearSum(ONE, x, eta, d, x);
+
+      /* Check for convergence... */
+      /* NOTE: just use approximation to norm of residual, if possible */
+      *res_norm = r_curr_norm = tau*SUNRsqrt(m+1);
+
+      /* Exit inner loop if iteration has converged based upon approximation
+	 to norm of current residual */
+      if (r_curr_norm <= delta) {
+	converged = SUNTRUE;
+	break;
+      }
+
+      /* Decide if actual norm of residual vector should be computed */
+      /* NOTES:
+       *   (1) if r_curr_norm > delta, then check if actual residual norm
+       *       is OK (recall we first compute an approximation)
+       *   (2) if r_curr_norm >= r_init_norm and m == 1 and n == l_max, then
+       *       compute actual residual norm to see if the iteration can be
+       *       saved
+       *   (3) the scaled and preconditioned right-hand side of the given
+       *       linear system (denoted by b) is only computed once, and the
+       *       result is stored in vtemp3 so it can be reused - reduces the
+       *       number of psovles if using left preconditioning
+       */
+      if ((r_curr_norm > delta) ||
+	  (r_curr_norm >= r_init_norm && m == 1 && n == l_max)) {
+
+	/* Compute norm of residual ||b-A*x||_2 (preconditioned and scaled) */
+	if (scale_x) N_VDiv(x, sx, vtemp1);
+	else N_VScale(ONE, x, vtemp1);
+	if (preOnRight) {
+	  ier = psolve(P_data, vtemp1, vtemp2, delta, PREC_RIGHT);
+	  if (ier != 0) {
+            LASTFLAG(S) = (ier < 0) ?
+              SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_UNREC;
+            return(LASTFLAG(S));
+          }
+	  N_VScale(ONE, vtemp2, vtemp1);
+	}
+	ier = atimes(A_data, vtemp1, vtemp2);
+        if (ier != 0) {
+          LASTFLAG(S) = (ier < 0) ?
+            SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+          return(LASTFLAG(S));
+        }
+	if (preOnLeft) {
+	  ier = psolve(P_data, vtemp2, vtemp1, delta, PREC_LEFT);
+	  if (ier != 0) {
+            LASTFLAG(S) = (ier < 0) ?
+              SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+            return(LASTFLAG(S));
+          }
+	}
+	else N_VScale(ONE, vtemp2, vtemp1);
+	if (scale_b) N_VProd(sb, vtemp1, vtemp2);
+	else N_VScale(ONE, vtemp1, vtemp2);
+	/* Only precondition and scale b once (result saved for reuse) */
+	if (!b_ok) {
+	  b_ok = SUNTRUE;
+	  if (preOnLeft) {
+	    ier = psolve(P_data, b, vtemp3, delta, PREC_LEFT);
+	    if (ier != 0) {
+              LASTFLAG(S) = (ier < 0) ?
+                SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+              return(LASTFLAG(S));
+            }
+	  }
+	  else N_VScale(ONE, b, vtemp3);
+	  if (scale_b) N_VProd(sb, vtemp3, vtemp3);
+	}
+	N_VLinearSum(ONE, vtemp3, -ONE, vtemp2, vtemp1);
+	*res_norm = r_curr_norm = SUNRsqrt(N_VDotProd(vtemp1, vtemp1));
+
+	/* Exit inner loop if inequality condition is satisfied 
+	   (meaning exit if we have converged) */
+	if (r_curr_norm <= delta) {
+	  converged = SUNTRUE;
+	  break;
+	}
+
+      }
+
+    }  /* END inner loop */
+
+    /* If converged, then exit outer loop as well */
+    if (converged == SUNTRUE) break;
+
+    /* rho[1] = r_star^T*r_[1] */
+    rho[1] = N_VDotProd(r_star, r[1]);
+
+    /* beta = rho[1]/rho[0] */
+    beta = rho[1]/rho[0];
+
+    /* u = r[1]+beta*q */
+    N_VLinearSum(ONE, r[1], beta, q, u);
+
+    /* p = u+beta*(q+beta*p) */
+    N_VLinearSum(beta, q, SUNSQR(beta), p, p);
+    N_VLinearSum(ONE, u, ONE, p, p);
+
+    /* v = A*p */
+    if (scale_x) N_VDiv(p, sx, vtemp1);
+    else N_VScale(ONE, p, vtemp1);
+    if (preOnRight) {
+      N_VScale(ONE, vtemp1, v);
+      ier = psolve(P_data, v, vtemp1, delta, PREC_RIGHT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+    ier = atimes(A_data, vtemp1, v);
+    if (ier != 0) {
+      LASTFLAG(S) = (ier < 0) ?
+        SUNLS_ATIMES_FAIL_UNREC : SUNLS_ATIMES_FAIL_REC;
+      return(LASTFLAG(S));
+    }
+    if (preOnLeft) {
+      ier = psolve(P_data, v, vtemp1, delta, PREC_LEFT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_REC;
+        return(LASTFLAG(S));
+      }
+    }
+    else N_VScale(ONE, v, vtemp1);
+    if (scale_b) N_VProd(sb, vtemp1, v);
+    else N_VScale(ONE, vtemp1, v);
+
+    /* Shift variable values */
+    /* NOTE: reduces storage requirements */
+    N_VScale(ONE, r[1], r[0]);
+    rho[0] = rho[1];
+
+  }  /* END outer loop */
+
+  /* Determine return value */
+  /* If iteration converged or residual was reduced, then return current iterate (x) */
+  if ((converged == SUNTRUE) || (r_curr_norm < r_init_norm)) {
+    if (scale_x) N_VDiv(x, sx, x);
+    if (preOnRight) {
+      ier = psolve(P_data, x, vtemp1, delta, PREC_RIGHT);
+      if (ier != 0) {
+        LASTFLAG(S) = (ier < 0) ?
+          SUNLS_PSOLVE_FAIL_UNREC : SUNLS_PSOLVE_FAIL_UNREC;
+        return(LASTFLAG(S));
+      }
+      N_VScale(ONE, vtemp1, x);
+    }
+    if (converged == SUNTRUE) 
+      LASTFLAG(S) = SUNLS_SUCCESS;
+    else 
+      LASTFLAG(S) = SUNLS_RES_REDUCED;
+    return(LASTFLAG(S));
+  }
+  /* Otherwise, return error code */
+  else {
+    LASTFLAG(S) = SUNLS_CONV_FAIL;
+    return(LASTFLAG(S));
+  }
+}
+
+
+int SUNLinSolNumIters_SPTFQMR(SUNLinearSolver S)
+{
+  /* return the stored 'numiters' value */
+  if (S == NULL) return(-1);
+  return (SPTFQMR_CONTENT(S)->numiters);
+}
+
+
+realtype SUNLinSolResNorm_SPTFQMR(SUNLinearSolver S)
+{
+  /* return the stored 'resnorm' value */
+  if (S == NULL) return(-ONE);
+  return (SPTFQMR_CONTENT(S)->resnorm);
+}
+
+
+N_Vector SUNLinSolResid_SPTFQMR(SUNLinearSolver S)
+{
+  /* return the stored 'vtemp1' vector */
+  return (SPTFQMR_CONTENT(S)->vtemp1);
+}
+
+
+long int SUNLinSolLastFlag_SPTFQMR(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  if (S == NULL) return(-1);
+  return (LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_SPTFQMR(SUNLinearSolver S, 
+                           long int *lenrwLS, 
+                           long int *leniwLS)
+{
+  sunindextype liw1, lrw1;
+  if (SPTFQMR_CONTENT(S)->vtemp1->ops->nvspace)
+    N_VSpace(SPTFQMR_CONTENT(S)->vtemp1, &lrw1, &liw1);
+  else
+    lrw1 = liw1 = 0;
+  *lenrwLS = lrw1*11;
+  *leniwLS = liw1*11;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_SPTFQMR(SUNLinearSolver S)
+{
+  if (S == NULL) return(SUNLS_SUCCESS);
+
+  /* delete items from within the content structure */
+  if (SPTFQMR_CONTENT(S)->r_star)
+    N_VDestroy(SPTFQMR_CONTENT(S)->r_star);
+  if (SPTFQMR_CONTENT(S)->q)
+    N_VDestroy(SPTFQMR_CONTENT(S)->q);
+  if (SPTFQMR_CONTENT(S)->d)
+    N_VDestroy(SPTFQMR_CONTENT(S)->d);
+  if (SPTFQMR_CONTENT(S)->v)
+    N_VDestroy(SPTFQMR_CONTENT(S)->v);
+  if (SPTFQMR_CONTENT(S)->p)
+    N_VDestroy(SPTFQMR_CONTENT(S)->p);
+  if (SPTFQMR_CONTENT(S)->r)
+    N_VDestroyVectorArray(SPTFQMR_CONTENT(S)->r, 2);
+  if (SPTFQMR_CONTENT(S)->u)
+    N_VDestroy(SPTFQMR_CONTENT(S)->u);
+  if (SPTFQMR_CONTENT(S)->vtemp1)
+    N_VDestroy(SPTFQMR_CONTENT(S)->vtemp1);
+  if (SPTFQMR_CONTENT(S)->vtemp2)
+    N_VDestroy(SPTFQMR_CONTENT(S)->vtemp2);
+  if (SPTFQMR_CONTENT(S)->vtemp3)
+    N_VDestroy(SPTFQMR_CONTENT(S)->vtemp3);
+
+  /* delete generic structures */
+  free(S->content);  S->content = NULL;
+  free(S->ops);  S->ops = NULL;
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
diff --git a/src/sunlinsol_superlumt/CMakeLists.txt b/src/sunlinsol_superlumt/CMakeLists.txt
new file mode 100644
index 0000000..e62d1de
--- /dev/null
+++ b/src/sunlinsol_superlumt/CMakeLists.txt
@@ -0,0 +1,127 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the superlumt SUNLinearSolver library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNLINSOL_SUPERLUMT\n\")")
+
+# Add variable sunlinsolsuperlumt_SOURCES with the sources for the SUNLINSOLSUPERLUMT lib
+SET(sunlinsolsuperlumt_SOURCES sunlinsol_superlumt.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNLINSOLSUPERLUMT library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_linearsolver.c
+  )
+
+# Add variable sunlinsolsuperlumt_HEADERS with the exported SUNLINSOLSUPERLUMT header files
+SET(sunlinsolsuperlumt_HEADERS
+  ${sundials_SOURCE_DIR}/include/sunlinsol/sunlinsol_superlumt.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNLINSOLSUPERLUMT library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNLINSOLSUPERLUMT library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolsuperlumt_static STATIC ${sunlinsolsuperlumt_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunlinsolsuperlumt_static
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolsuperlumt CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunlinsolsuperlumt_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNLINSOLSUPERLUMT library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNLINSOLSUPERLUMT library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunlinsolsuperlumt_shared SHARED ${sunlinsolsuperlumt_SOURCES} ${shared_SOURCES})
+
+  # sunlinsolsuperlumt depends on sunmatrixsparse and SuperLU_MT
+  TARGET_LINK_LIBRARIES(sundials_sunlinsolsuperlumt_shared
+    sundials_sunmatrixsparse_shared
+    ${SUPERLUMT_LIBRARIES})
+  
+  # if a blas library is provided, assume SuperLU_MT depends on it
+  IF(BLAS_FOUND)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsolsuperlumt_shared ${BLAS_LIBRARIES})
+  ENDIF()
+
+  # if a blas library was not provided but a lapack library was set, assume 
+  # SuperLU_MT depends depends on a blas library provided in LAPACK_LIBRARIES
+  IF((NOT BLAS_FOUND) AND LAPACK_FOUND)
+    TARGET_LINK_LIBRARIES(sundials_sunlinsolsuperlumt_shared ${LAPACK_LIBRARIES})
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunlinsolsuperlumt_shared
+    PROPERTIES OUTPUT_NAME sundials_sunlinsolsuperlumt CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunlinsolsuperlumt_shared
+    PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+  INSTALL(TARGETS sundials_sunlinsolsuperlumt_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNLINSOLSUPERLUMT header files
+INSTALL(FILES ${sunlinsolsuperlumt_HEADERS} DESTINATION include/sunlinsol)
+
+# If FCMIX is enabled and building with 64-bit indices, then build and install 
+# the FSUNLINSOLSUPERLUMT library
+IF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+  PRINT_WARNING("The Fortran interface to SuperLU_MT is not compatible with ${SUNDIALS_INDEX_TYPE} integers"
+                "Fortran interfaces to SuperLU_MT will not be built")
+
+ELSE(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+  IF(FCMIX_ENABLE AND F77_FOUND)
+    SET(fsunlinsolsuperlumt_SOURCES fsunlinsol_superlumt.c)
+
+    IF(BUILD_STATIC_LIBS)
+      ADD_LIBRARY(sundials_fsunlinsolsuperlumt_static STATIC ${fsunlinsolsuperlumt_SOURCES})
+      SET_TARGET_PROPERTIES(sundials_fsunlinsolsuperlumt_static
+        PROPERTIES OUTPUT_NAME sundials_fsunlinsolsuperlumt CLEAN_DIRECT_OUTPUT 1)
+      INSTALL(TARGETS sundials_fsunlinsolsuperlumt_static DESTINATION lib)
+    ENDIF(BUILD_STATIC_LIBS)
+
+    IF(BUILD_SHARED_LIBS)
+      ADD_LIBRARY(sundials_fsunlinsolsuperlumt_shared ${fsunlinsolsuperlumt_SOURCES})
+
+      # fsunlinsolsuperlumt dependes on fnvecserial, fsunmatrixsparse, sunlinsolsuperlumt
+      TARGET_LINK_LIBRARIES(sundials_fsunlinsolsuperlumt_shared
+        sundials_fnvecserial_shared
+        sundials_fsunmatrixsparse_shared
+        sundials_sunlinsolsuperlumt_shared)
+
+      SET_TARGET_PROPERTIES(sundials_fsunlinsolsuperlumt_shared
+        PROPERTIES OUTPUT_NAME sundials_fsunlinsolsuperlumt CLEAN_DIRECT_OUTPUT 1)
+      SET_TARGET_PROPERTIES(sundials_fsunlinsolsuperlumt_shared 
+        PROPERTIES VERSION ${sunlinsollib_VERSION} SOVERSION ${sunlinsollib_SOVERSION})
+      INSTALL(TARGETS sundials_fsunlinsolsuperlumt_shared DESTINATION lib)
+    ENDIF(BUILD_SHARED_LIBS)
+
+  ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+ENDIF(SUNDIALS_INDEX_TYPE MATCHES "INT32_T")
+
+#
+MESSAGE(STATUS "Added SUNLINSOL_SUPERLUMT module")
diff --git a/src/sunlinsol_superlumt/README b/src/sunlinsol_superlumt/README
new file mode 100644
index 0000000..350df27
--- /dev/null
+++ b/src/sunlinsol_superlumt/README
@@ -0,0 +1,41 @@
+                     SUNLINSOL_SUPERLUMT
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+SuperLUMT implementation of the SUNLINSOL module for SUNDIALS. 
+
+SUNLINSOL_SUPERLUMT defines the content field of SUNMatrix to be a structure 
+containing a pivot array for performing LU factorization with row
+pivoting, along with a long integer for any error flag that arises in
+the factorization process.
+
+SUNLINSOL_SUPERLUMT defines three macros to provide access to the content of 
+a SuperLUMT SUNLinearSolver, and constructor for the SuperLUMT
+SUNLinearSolver, in addition to implementation of all linear 
+solver operations defined by the generic SUNLINSOL module in the table
+of operations.
+
+
+A. Documentation
+----------------
+
+The SuperLUMT SUNLINSOL implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunlinsol_superlumt/fsunlinsol_superlumt.c b/src/sunlinsol_superlumt/fsunlinsol_superlumt.c
new file mode 100644
index 0000000..f8cc84a
--- /dev/null
+++ b/src/sunlinsol_superlumt/fsunlinsol_superlumt.c
@@ -0,0 +1,136 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_superlumt.h) contains the
+ * implementation needed for the Fortran initialization of superlumt
+ * linear solver operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunlinsol_superlumt.h"
+
+/* Define global linsol variables */
+
+SUNLinearSolver F2C_CVODE_linsol;
+SUNLinearSolver F2C_IDA_linsol;
+SUNLinearSolver F2C_KINSOL_linsol;
+SUNLinearSolver F2C_ARKODE_linsol;
+SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* Declarations of external global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+extern N_Vector F2C_CVODE_vec;
+extern N_Vector F2C_IDA_vec;
+extern N_Vector F2C_KINSOL_vec;
+extern N_Vector F2C_ARKODE_vec;
+
+/* Fortran callable interfaces */
+
+void FSUNSUPERLUMT_INIT(int *code, int *num_threads, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_linsol)  SUNLinSolFree(F2C_CVODE_linsol);
+    F2C_CVODE_linsol = NULL;
+    F2C_CVODE_linsol = SUNSuperLUMT(F2C_CVODE_vec,
+                                    F2C_CVODE_matrix,
+                                    *num_threads);
+    if (F2C_CVODE_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_linsol)  SUNLinSolFree(F2C_IDA_linsol);
+    F2C_IDA_linsol = NULL;
+    F2C_IDA_linsol = SUNSuperLUMT(F2C_IDA_vec,
+                                  F2C_IDA_matrix,
+                                  *num_threads);
+    if (F2C_IDA_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_linsol)  SUNLinSolFree(F2C_KINSOL_linsol);
+    F2C_KINSOL_linsol = NULL;
+    F2C_KINSOL_linsol = SUNSuperLUMT(F2C_KINSOL_vec,
+                                     F2C_KINSOL_matrix,
+                                     *num_threads);
+    if (F2C_KINSOL_linsol == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_linsol)  SUNLinSolFree(F2C_ARKODE_linsol);
+    F2C_ARKODE_linsol = NULL;
+    F2C_ARKODE_linsol = SUNSuperLUMT(F2C_ARKODE_vec,
+                                     F2C_ARKODE_matrix,
+                                     *num_threads);
+    if (F2C_ARKODE_linsol == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNSUPERLUMT_SETORDERING(int *code, int *ordering_choice, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    *ier = SUNSuperLUMTSetOrdering(F2C_CVODE_linsol, *ordering_choice);
+    break;
+  case FCMIX_IDA:
+    *ier = SUNSuperLUMTSetOrdering(F2C_IDA_linsol, *ordering_choice);
+    break;
+  case FCMIX_KINSOL:
+    *ier = SUNSuperLUMTSetOrdering(F2C_KINSOL_linsol, *ordering_choice);
+    break;
+  case FCMIX_ARKODE:
+    *ier = SUNSuperLUMTSetOrdering(F2C_ARKODE_linsol, *ordering_choice);
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNMASSSUPERLUMT_INIT(int *num_threads, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_sol)  SUNLinSolFree(F2C_ARKODE_mass_sol);
+  F2C_ARKODE_mass_sol = NULL;
+  F2C_ARKODE_mass_sol = SUNSuperLUMT(F2C_ARKODE_vec,
+                                     F2C_ARKODE_mass_matrix,
+                                     *num_threads);
+  if (F2C_ARKODE_mass_sol == NULL) *ier = -1;
+}
+
+
+void FSUNMASSSUPERLUMT_SETORDERING(int *ordering_choice, int *ier)
+{
+  *ier = 0;
+  *ier = SUNSuperLUMTSetOrdering(F2C_ARKODE_mass_sol, 
+                                 *ordering_choice);
+}
diff --git a/src/sunlinsol_superlumt/fsunlinsol_superlumt.h b/src/sunlinsol_superlumt/fsunlinsol_superlumt.h
new file mode 100644
index 0000000..7258524
--- /dev/null
+++ b/src/sunlinsol_superlumt/fsunlinsol_superlumt.h
@@ -0,0 +1,74 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunlinsol_superlumt.c) contains the
+ * definitions needed for the initialization of superlumt
+ * linear solver operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNLINSOL_SUPERLUMT_H
+#define _FSUNLINSOL_SUPERLUMT_H
+
+#include <sunlinsol/sunlinsol_superlumt.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNSUPERLUMT_INIT            SUNDIALS_F77_FUNC(fsunsuperlumtinit,        FSUNSUPERLUMTINIT)
+#define FSUNSUPERLUMT_SETORDERING     SUNDIALS_F77_FUNC(fsunsuperlumtsetordering, FSUNSUPERLUMTSETORDERING)
+#define FSUNMASSSUPERLUMT_INIT        SUNDIALS_F77_FUNC(fsunmasssuperlumtinit,        FSUNMASSSUPERLUMTINIT)
+#define FSUNMASSSUPERLUMT_SETORDERING SUNDIALS_F77_FUNC(fsunmasssuperlumtsetordering, FSUNMASSSUPERLUMTSETORDERING)
+#else
+#define FSUNSUPERLUMT_INIT            fsunsuperlumtinit_
+#define FSUNSUPERLUMT_SETORDERING     fsunsuperlumtsetordering_
+#define FSUNMASSSUPERLUMT_INIT        fsunmasssuperlumtinit_
+#define FSUNMASSSUPERLUMT_SETORDERING fsunmasssuperlumtsetordering_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNLinearSolver F2C_CVODE_linsol;
+extern SUNLinearSolver F2C_IDA_linsol;
+extern SUNLinearSolver F2C_KINSOL_linsol;
+extern SUNLinearSolver F2C_ARKODE_linsol;
+extern SUNLinearSolver F2C_ARKODE_mass_sol;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNSUPERLUMT_INIT - initializes superlumt linear solver for main problem
+ * FSUNSUPERLUMT_SETORDERING - sets the ordering choice used by SUPERLUMT for main problem
+ * FSUNMASSSUPERLUMT_INIT - initializes superlumt linear solver for mass matrix
+ * FSUNMASSSUPERLUMT_SETORDERING - sets the ordering choice used by SUPERLUMT for mass matrix
+ */
+
+void FSUNSUPERLUMT_INIT(int *code, int *num_threads, int *ier);
+void FSUNSUPERLUMT_SETORDERING(int *code, int *ordering, int *ier);
+void FSUNMASSSUPERLUMT_INIT(int *num_threads, int *ier);
+void FSUNMASSSUPERLUMT_SETORDERING(int *ordering, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunlinsol_superlumt/sunlinsol_superlumt.c b/src/sunlinsol_superlumt/sunlinsol_superlumt.c
new file mode 100644
index 0000000..228ee78
--- /dev/null
+++ b/src/sunlinsol_superlumt/sunlinsol_superlumt.c
@@ -0,0 +1,422 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * Based on codes <solver>_superlumt.c, written by 
+ *     Carol S. Woodward @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the SuperLUMT implementation of 
+ * the SUNLINSOL package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunlinsol/sunlinsol_superlumt.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO      RCONST(0.0)
+#define ONE       RCONST(1.0)
+#define TWO       RCONST(2.0)
+
+/* Private function prototypes */
+sunindextype GlobalVectorLength_SuperLUMT(N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * SuperLUMT solver structure accessibility macros: 
+ * -----------------------------------------------------------------
+ */
+
+#define SLUMT_CONTENT(S)    ( (SUNLinearSolverContent_SuperLUMT)(S->content) )
+#define LASTFLAG(S)         ( SLUMT_CONTENT(S)->last_flag )
+#define FIRSTFACTORIZE(S)   ( SLUMT_CONTENT(S)->first_factorize )
+#define SM_A(S)             ( SLUMT_CONTENT(S)->A )
+#define SM_AC(S)            ( SLUMT_CONTENT(S)->AC )
+#define SM_L(S)             ( SLUMT_CONTENT(S)->L )
+#define SM_U(S)             ( SLUMT_CONTENT(S)->U )
+#define SM_B(S)             ( SLUMT_CONTENT(S)->B )
+#define GSTAT(S)            ( SLUMT_CONTENT(S)->Gstat )
+#define PERMR(S)            ( SLUMT_CONTENT(S)->perm_r )
+#define PERMC(S)            ( SLUMT_CONTENT(S)->perm_c )
+#define SIZE(S)             ( SLUMT_CONTENT(S)->N )
+#define NUMTHREADS(S)       ( SLUMT_CONTENT(S)->num_threads )
+#define DIAGPIVOTTHRESH(S)  ( SLUMT_CONTENT(S)->diag_pivot_thresh )
+#define ORDERING(S)         ( SLUMT_CONTENT(S)->ordering )
+#define OPTIONS(S)          ( SLUMT_CONTENT(S)->options )
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new SuperLUMT linear solver
+ */
+
+SUNLinearSolver SUNSuperLUMT(N_Vector y, SUNMatrix A, int num_threads)
+{
+  SUNLinearSolver S;
+  SUNLinearSolver_Ops ops;
+  SUNLinearSolverContent_SuperLUMT content;
+  sunindextype MatrixRows, VecLength;
+
+  /* Check compatibility with supplied SUNMatrix and N_Vector */
+  if (SUNMatGetID(A) != SUNMATRIX_SPARSE)
+    return(NULL);
+  if (SUNSparseMatrix_Rows(A) != SUNSparseMatrix_Columns(A))
+    return(NULL);
+  MatrixRows = SUNSparseMatrix_Rows(A);
+  if ( (N_VGetVectorID(y) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(y) != SUNDIALS_NVEC_PTHREADS) )
+    return(NULL);
+
+  /* optimally this function would be replaced with a generic N_Vector routine */
+  VecLength = GlobalVectorLength_SuperLUMT(y);
+  if (MatrixRows != VecLength)
+    return(NULL);
+  
+  /* Create linear solver */
+  S = NULL;
+  S = (SUNLinearSolver) malloc(sizeof *S);
+  if (S == NULL) return(NULL);
+  
+  /* Create linear solver operation structure */
+  ops = NULL;
+  ops = (SUNLinearSolver_Ops) malloc(sizeof(struct _generic_SUNLinearSolver_Ops));
+  if (ops == NULL) { free(S); return(NULL); }
+
+  /* Attach operations */
+  ops->gettype           = SUNLinSolGetType_SuperLUMT;
+  ops->initialize        = SUNLinSolInitialize_SuperLUMT;
+  ops->setup             = SUNLinSolSetup_SuperLUMT;
+  ops->solve             = SUNLinSolSolve_SuperLUMT;
+  ops->lastflag          = SUNLinSolLastFlag_SuperLUMT;
+  ops->space             = SUNLinSolSpace_SuperLUMT;
+  ops->free              = SUNLinSolFree_SuperLUMT;
+  ops->setatimes         = NULL;
+  ops->setpreconditioner = NULL;
+  ops->setscalingvectors = NULL;
+  ops->numiters          = NULL;
+  ops->resnorm           = NULL;
+  ops->resid             = NULL;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNLinearSolverContent_SuperLUMT)
+    malloc(sizeof(struct _SUNLinearSolverContent_SuperLUMT));
+  if (content == NULL) { free(ops); free(S); return(NULL); }
+
+  /* Fill content */
+  content->N = MatrixRows;
+  content->last_flag = 0;
+  content->num_threads = num_threads;
+  content->diag_pivot_thresh = ONE;
+  content->ordering = SUNSLUMT_ORDERING_DEFAULT;
+
+  content->perm_r = NULL;
+  content->perm_r = (sunindextype *) malloc(MatrixRows*sizeof(sunindextype));
+  if (content->perm_r == NULL) {
+    free(content); free(ops); free(S); return(NULL); }
+
+  content->perm_c = NULL;
+  content->perm_c = (sunindextype *) malloc(MatrixRows*sizeof(sunindextype));
+  if (content->perm_c == NULL) {
+    free(content->perm_r); free(content); free(ops); free(S); return(NULL); }
+
+  content->Gstat = (Gstat_t *) malloc(sizeof(Gstat_t));
+  if (content->Gstat == NULL) {
+    free(content->perm_c); free(content->perm_r); free(content); free(ops);
+    free(S); return(NULL); }
+
+  content->A = (SuperMatrix *) malloc(sizeof(SuperMatrix));
+  if (content->A == NULL) {
+    free(content->Gstat); free(content->perm_c); free(content->perm_r);
+    free(content); free(ops); free(S); return(NULL); }
+  content->A->Store = NULL;
+
+  content->AC = (SuperMatrix *) malloc(sizeof(SuperMatrix));
+  if (content->AC == NULL) {
+    free(content->A); free(content->Gstat); free(content->perm_c);
+    free(content->perm_r); free(content); free(ops); free(S); return(NULL); }
+  content->AC->Store = NULL;
+
+  content->L = (SuperMatrix *) malloc(sizeof(SuperMatrix));
+  if (content->L == NULL) {
+    free(content->AC); free(content->A); free(content->Gstat); free(content->perm_c);
+    free(content->perm_r); free(content); free(ops); free(S); return(NULL); }
+  content->L->Store = NULL;
+
+  content->U = (SuperMatrix *) malloc(sizeof(SuperMatrix));
+  if (content->U == NULL) {
+    free(content->L); free(content->AC); free(content->A); free(content->Gstat);
+    free(content->perm_c); free(content->perm_r); free(content); free(ops); free(S);
+    return(NULL); }
+  content->U->Store = NULL;
+
+  content->B = (SuperMatrix *) malloc(sizeof(SuperMatrix));
+  if (content->B == NULL) {
+    free(content->U); free(content->L); free(content->AC); free(content->A);
+    free(content->Gstat); free(content->perm_c); free(content->perm_r); free(content);
+    free(ops); free(S); return(NULL); }
+  content->B->Store = NULL;
+  xCreate_Dense_Matrix(content->B, MatrixRows, 1, NULL, MatrixRows, SLU_DN, SLU_D, SLU_GE);
+  
+  content->options = (superlumt_options_t *) malloc(sizeof(superlumt_options_t));
+  if (content->options == NULL) {
+    free(content->B); free(content->U); free(content->L); free(content->AC);
+    free(content->A); free(content->Gstat); free(content->perm_c); free(content->perm_r);
+    free(content); free(ops); free(S); return(NULL); }
+  StatAlloc(MatrixRows, num_threads, sp_ienv(1), sp_ienv(2), content->Gstat);
+
+  /* Attach content and ops */
+  S->content = content;
+  S->ops     = ops;
+
+  return(S);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to set the ordering type for a SuperLUMT linear solver
+ */
+
+int SUNSuperLUMTSetOrdering(SUNLinearSolver S, int ordering_choice)
+{
+  /* Check for legal ordering_choice */ 
+  if ((ordering_choice < 0) || (ordering_choice > 3))
+    return(SUNLS_ILL_INPUT);
+
+  /* Check for non-NULL SUNLinearSolver */
+  if (S == NULL) return(SUNLS_MEM_NULL);
+
+  /* Set ordering_choice */
+  ORDERING(S) = ordering_choice;
+
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of linear solver operations
+ * -----------------------------------------------------------------
+ */
+
+SUNLinearSolver_Type SUNLinSolGetType_SuperLUMT(SUNLinearSolver S)
+{
+  return(SUNLINEARSOLVER_DIRECT);
+}
+
+
+int SUNLinSolInitialize_SuperLUMT(SUNLinearSolver S)
+{
+  /* force a first factorization */
+  FIRSTFACTORIZE(S) = 1;
+
+  /* Initialize statistics variables */
+  StatInit(SIZE(S), NUMTHREADS(S), GSTAT(S));
+  
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSetup_SuperLUMT(SUNLinearSolver S, SUNMatrix A)
+{
+  int_t retval;
+  int panel_size, relax, lwork;
+  double drop_tol;
+  fact_t fact;
+  trans_t trans;
+  yes_no_t refact, usepr;
+  void *work;
+  
+  /* Set option values for SuperLU_MT */
+  panel_size = sp_ienv(1);
+  relax = sp_ienv(2);
+  fact = EQUILIBRATE;
+  trans = (SUNSparseMatrix_SparseType(A) == CSC_MAT) ? NOTRANS : TRANS;
+  usepr = NO;
+  drop_tol = ZERO;
+  lwork = 0;
+  work = NULL;
+
+  /* free and reallocate sparse matrix */
+  if (SM_A(S)->Store)
+    SUPERLU_FREE(SM_A(S)->Store);
+  xCreate_CompCol_Matrix(SM_A(S), SUNSparseMatrix_Rows(A), 
+			 SUNSparseMatrix_Columns(A),
+                         SUNSparseMatrix_NNZ(A), 
+                         SUNSparseMatrix_Data(A), 
+                         (int_t*) SUNSparseMatrix_IndexValues(A), 
+                         (int_t*) SUNSparseMatrix_IndexPointers(A), 
+			 SLU_NC, SLU_D, SLU_GE);
+
+  /* On first decomposition, set up reusable pieces */ 
+  if (FIRSTFACTORIZE(S)) {
+
+    /* Get column permutation vector perm_c[], according to ordering */
+    get_perm_c(ORDERING(S), SM_A(S), (int_t *) PERMC(S));
+    refact = NO;
+    FIRSTFACTORIZE(S) = 0;
+
+  } else {
+
+    /* Re-initialize statistics variables */
+    StatInit(SIZE(S), NUMTHREADS(S), GSTAT(S)); 
+    Destroy_CompCol_Permuted(SM_AC(S));
+    refact = YES;
+    
+  }
+
+  /* Initialize the option structure using the user-input parameters. 
+     Subsequent calls will re-initialize options.  Apply perm_c to 
+     columns of original A to form AC */
+  pxgstrf_init(NUMTHREADS(S), fact, trans, refact, panel_size, relax, 
+	       DIAGPIVOTTHRESH(S), usepr, drop_tol, (int_t *) PERMC(S), (int_t *) PERMR(S), 
+               work, lwork, SM_A(S), SM_AC(S), OPTIONS(S), GSTAT(S));
+
+  /* Compute the LU factorization of A.
+     The following routine will create num_threads threads. */
+  pxgstrf(OPTIONS(S), SM_AC(S), (int_t *) PERMR(S), SM_L(S), SM_U(S),
+          GSTAT(S), &retval);
+  if (retval != 0) {
+    LASTFLAG(S) = (retval < 0) ? 
+      SUNLS_PACKAGE_FAIL_UNREC : SUNLS_PACKAGE_FAIL_REC;
+    return(LASTFLAG(S));
+  }
+  
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSolve_SuperLUMT(SUNLinearSolver S, SUNMatrix A, N_Vector x, 
+                             N_Vector b, realtype tol)
+{
+  int_t retval;
+  realtype *xdata;
+  DNformat *Bstore;
+  trans_t trans;
+  
+  /* copy b into x */
+  N_VScale(ONE, b, x);
+
+  /* access x data array */
+  xdata = N_VGetArrayPointer(x);
+  if (xdata == NULL) {
+    LASTFLAG(S) = SUNLS_MEM_FAIL;
+    return(LASTFLAG(S));
+  }
+
+  Bstore = (DNformat *) (SM_B(S)->Store);
+  Bstore->nzval = xdata;
+  
+  /* Call SuperLUMT to solve the linear system using L and U */
+  trans = (SUNSparseMatrix_SparseType(A) == CSC_MAT) ? NOTRANS : TRANS;
+  xgstrs(trans, SM_L(S), SM_U(S), (int_t *) PERMR(S), (int_t *) PERMC(S), SM_B(S), GSTAT(S), &retval);
+  if (retval != 0) {
+    LASTFLAG(S) = SUNLS_PACKAGE_FAIL_UNREC;
+    return(LASTFLAG(S));
+  }
+  
+  LASTFLAG(S) = SUNLS_SUCCESS;
+  return(LASTFLAG(S));
+}
+
+
+long int SUNLinSolLastFlag_SuperLUMT(SUNLinearSolver S)
+{
+  /* return the stored 'last_flag' value */
+  return(LASTFLAG(S));
+}
+
+
+int SUNLinSolSpace_SuperLUMT(SUNLinearSolver S, 
+                             long int *lenrwLS, 
+                             long int *leniwLS)
+{
+  /* since the SuperLU_MT structures are opaque objects, we 
+     omit those from these results */
+  *leniwLS = 5 + 2*SIZE(S);
+  *lenrwLS = 1;
+  return(SUNLS_SUCCESS);
+}
+
+int SUNLinSolFree_SuperLUMT(SUNLinearSolver S)
+{
+  /* return with success if already freed */
+  if (S == NULL)
+    return(SUNLS_SUCCESS);
+  
+  /* delete items from the contents structure (if it exists) */
+  if (S->content) {
+    pxgstrf_finalize(OPTIONS(S), SM_AC(S));
+    free(PERMR(S));
+    free(PERMC(S));
+    free(OPTIONS(S));
+    Destroy_SuperNode_SCP(SM_L(S));
+    Destroy_CompCol_NCP(SM_U(S));
+    StatFree(GSTAT(S));
+    free(GSTAT(S));
+  
+    Destroy_SuperMatrix_Store(SM_B(S));
+    SUPERLU_FREE(SM_A(S)->Store);
+
+    free(SM_B(S));
+    free(SM_A(S));
+    free(SM_AC(S));
+    free(SM_L(S));
+    free(SM_U(S));
+
+    free(S->content);  
+    S->content = NULL;
+  }
+  
+  /* delete generic structures */
+  if (S->ops) {
+    free(S->ops);  
+    S->ops = NULL;
+  }
+  free(S); S = NULL;
+  return(SUNLS_SUCCESS);
+}
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+/* Inefficient kludge for determining the number of entries in a N_Vector 
+   object (replace if such a routine is ever added to the N_Vector API).
+
+   Returns "-1" on an error. */
+sunindextype GlobalVectorLength_SuperLUMT(N_Vector y)
+{
+  realtype len;
+  N_Vector tmp = NULL;
+  tmp = N_VClone(y);
+  if (tmp == NULL)  return(-1);
+  N_VConst(ONE, tmp);
+  len = N_VDotProd(tmp, tmp);
+  N_VDestroy(tmp);
+  return( (sunindextype) len );
+}
diff --git a/src/sunmat_band/CMakeLists.txt b/src/sunmat_band/CMakeLists.txt
new file mode 100644
index 0000000..98a29fb
--- /dev/null
+++ b/src/sunmat_band/CMakeLists.txt
@@ -0,0 +1,104 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the band SUNMatrix library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNMATRIX_BAND\n\")")
+
+# Add variable sunmatrixband_SOURCES with the sources for the SUNMATRIXBAND lib
+SET(sunmatrixband_SOURCES sunmatrix_band.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNMATRIXBAND library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
+
+# Add variable sunmatrixband_HEADERS with the exported SUNMATRIXBAND header files
+SET(sunmatrixband_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunmatrix/sunmatrix_band.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNMATRIXBAND library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNMATRIXBAND library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunmatrixband_static STATIC ${sunmatrixband_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunmatrixband_static
+    PROPERTIES OUTPUT_NAME sundials_sunmatrixband CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunmatrixband_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNMATRIXBAND library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNMATRIXBAND library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunmatrixband_shared SHARED ${sunmatrixband_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunmatrixband_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunmatrixband_shared
+    PROPERTIES OUTPUT_NAME sundials_sunmatrixband CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunmatrixband_shared
+    PROPERTIES VERSION ${sunmatrixlib_VERSION} SOVERSION ${sunmatrixlib_SOVERSION})
+  INSTALL(TARGETS sundials_sunmatrixband_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNMATRIXBAND header files
+INSTALL(FILES ${sunmatrixband_HEADERS} DESTINATION include/sunmatrix)
+
+# If FCMIX is enabled, build and install the FSUNMATRIXBAND library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunmatrixband_SOURCES fsunmatrix_band.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunmatrixband_static STATIC ${fsunmatrixband_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixband_static
+      PROPERTIES OUTPUT_NAME sundials_fsunmatrixband CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunmatrixband_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunmatrixband_shared ${fsunmatrixband_SOURCES})
+
+    # fsunmatrixband depends on sunmatrixband
+    TARGET_LINK_LIBRARIES(sundials_fsunmatrixband_shared sundials_sunmatrixband_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixband_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunmatrixband CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixband_shared 
+      PROPERTIES VERSION ${sunmatrixlib_VERSION} SOVERSION ${sunmatrixlib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunmatrixband_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNMATRIX_BAND module")
diff --git a/src/sunmat_band/README b/src/sunmat_band/README
new file mode 100644
index 0000000..91c1f8c
--- /dev/null
+++ b/src/sunmat_band/README
@@ -0,0 +1,48 @@
+                     SUNMATRIX_BAND
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Band implementation of the SUNMATRIX module for SUNDIALS. 
+
+SUNMATRIX_BAND defines the content field of SUNMatrix to be a structure 
+containing the number of rows and columns of the matrix, the total
+allocated size of the matrix, the lower and upper bandwidth of the
+matrix, the number of stored upper bands of the matrix (may be larger
+than the actual matrix bandwidth to allow fill-in during LU
+factorization), a pointer to the beginning of a contiguous data array,
+the leading dimension of the data array (if contained inside a larger
+data array), and an array of pointers to the first entry of each
+column of the matrix. 
+
+SUNMATRIX_BAND defines six macros to provide access to the content of 
+a band SUNMatrix, a constructor for variables of type SUNMatrix,
+destructors for SUNMatrix, and a utility function for printing a
+banded SUNMatrix to screen/file.
+
+SUNMATRIX_BAND provides implementations for all matrix operations defined
+by the generic SUNMATRIX module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The band SUNMATRIX implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunmat_band/fsunmatrix_band.c b/src/sunmat_band/fsunmatrix_band.c
new file mode 100644
index 0000000..09bde24
--- /dev/null
+++ b/src/sunmat_band/fsunmatrix_band.c
@@ -0,0 +1,84 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunmatrix_band.h) contains the
+ * implementation needed for the Fortran initialization of band
+ * vector operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunmatrix_band.h"
+
+/* Define global matrix variables */
+
+SUNMatrix F2C_CVODE_matrix;
+SUNMatrix F2C_IDA_matrix;
+SUNMatrix F2C_KINSOL_matrix;
+SUNMatrix F2C_ARKODE_matrix;
+SUNMatrix F2C_ARKODE_mass_matrix;
+
+/* Fortran callable interfaces */
+
+void FSUNBANDMAT_INIT(int *code, long int *N, long int *mu, 
+                      long int *ml, long int *smu, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_matrix)  SUNMatDestroy(F2C_CVODE_matrix);
+    F2C_CVODE_matrix = NULL;
+    F2C_CVODE_matrix = SUNBandMatrix(*N, *mu, *ml, *smu);
+    if (F2C_CVODE_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_matrix)  SUNMatDestroy(F2C_IDA_matrix);
+    F2C_IDA_matrix = NULL;
+    F2C_IDA_matrix = SUNBandMatrix(*N, *mu, *ml, *smu);
+    if (F2C_IDA_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_matrix)  SUNMatDestroy(F2C_KINSOL_matrix);
+    F2C_KINSOL_matrix = NULL;
+    F2C_KINSOL_matrix = SUNBandMatrix(*N, *mu, *ml, *smu);
+    if (F2C_KINSOL_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_matrix)  SUNMatDestroy(F2C_ARKODE_matrix);
+    F2C_ARKODE_matrix = NULL;
+    F2C_ARKODE_matrix = SUNBandMatrix(*N, *mu, *ml, *smu);
+    if (F2C_ARKODE_matrix == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNBANDMASSMAT_INIT(long int *N, long int *mu, 
+                          long int *ml, long int *smu, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_matrix)  SUNMatDestroy(F2C_ARKODE_mass_matrix);
+  F2C_ARKODE_mass_matrix = NULL;
+  F2C_ARKODE_mass_matrix = SUNBandMatrix(*N, *mu, *ml, *smu);
+  if (F2C_ARKODE_mass_matrix == NULL) *ier = -1;
+}
diff --git a/src/sunmat_band/fsunmatrix_band.h b/src/sunmat_band/fsunmatrix_band.h
new file mode 100644
index 0000000..8371e0b
--- /dev/null
+++ b/src/sunmat_band/fsunmatrix_band.h
@@ -0,0 +1,68 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunmatrix_band.c) contains the
+ * definitions needed for the initialization of band
+ * matrix operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNMATRIX_BAND_H
+#define _FSUNMATRIX_BAND_H
+
+#include <sunmatrix/sunmatrix_band.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNBANDMAT_INIT     SUNDIALS_F77_FUNC(fsunbandmatinit, FSUNBANDMATINIT)
+#define FSUNBANDMASSMAT_INIT SUNDIALS_F77_FUNC(fsunbandmassmatinit, FSUNBANDMASSMATINIT)
+#else
+#define FSUNBANDMAT_INIT     fsunbandmatinit_
+#define FSUNBANDMASSMAT_INIT fsunbandmassmatinit_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNBANDMAT_INIT - initializes band matrix operations for main problem
+ * FSUNBANDMASSMAT_INIT - initializes band matrix operations for mass matrix solve
+ */
+
+void FSUNBANDMAT_INIT(int *code, long int *N, long int *mu, long int *ml,
+                      long int *smu, int *ier);
+void FSUNBANDMASSMAT_INIT(long int *N, long int *mu, long int *ml,
+                          long int *smu, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunmat_band/sunmatrix_band.c b/src/sunmat_band/sunmatrix_band.c
new file mode 100644
index 0000000..19276f1
--- /dev/null
+++ b/src/sunmat_band/sunmatrix_band.c
@@ -0,0 +1,482 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * Based on code sundials_band.c by: Alan C. Hindmarsh and 
+ *    Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the band implementation of 
+ * the SUNMATRIX package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunmatrix/sunmatrix_band.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+
+/* Private function prototypes */
+static booleantype SMCompatible_Band(SUNMatrix A, SUNMatrix B);
+static booleantype SMCompatible2_Band(SUNMatrix A, N_Vector x, N_Vector y);
+static int SMScaleAddNew_Band(realtype c, SUNMatrix A, SUNMatrix B);
+
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new band matrix
+ */
+
+SUNMatrix SUNBandMatrix(sunindextype N, sunindextype mu,
+                        sunindextype ml, sunindextype smu)
+{
+  SUNMatrix A;
+  SUNMatrix_Ops ops;
+  SUNMatrixContent_Band content;
+  sunindextype j, colSize;
+
+  /* return with NULL matrix on illegal dimension input */
+  if ( (N <= 0) || (smu < 0) || (ml < 0) ) return(NULL);
+
+  /* Create matrix */
+  A = NULL;
+  A = (SUNMatrix) malloc(sizeof *A);
+  if (A == NULL) return(NULL);
+  
+  /* Create matrix operation structure */
+  ops = NULL;
+  ops = (SUNMatrix_Ops) malloc(sizeof(struct _generic_SUNMatrix_Ops));
+  if (ops == NULL) { free(A); return(NULL); }
+
+  /* Attach operations */
+  ops->getid       = SUNMatGetID_Band;
+  ops->clone       = SUNMatClone_Band;
+  ops->destroy     = SUNMatDestroy_Band;
+  ops->zero        = SUNMatZero_Band;
+  ops->copy        = SUNMatCopy_Band;
+  ops->scaleadd    = SUNMatScaleAdd_Band;
+  ops->scaleaddi   = SUNMatScaleAddI_Band;
+  ops->matvec      = SUNMatMatvec_Band;
+  ops->space       = SUNMatSpace_Band;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNMatrixContent_Band) malloc(sizeof(struct _SUNMatrixContent_Band));
+  if (content == NULL) { free(ops); free(A); return(NULL); }
+
+  /* Fill content */
+  colSize = smu + ml + 1;
+  content->M = N;
+  content->N = N;
+  content->mu = mu;
+  content->ml = ml;
+  content->s_mu = smu;
+  content->ldim = colSize;
+  content->ldata = N * colSize;
+  content->data = NULL;
+  content->data = (realtype *) calloc(N * colSize, sizeof(realtype));
+  if (content->data == NULL) {
+    free(content); free(ops); free(A); return(NULL);
+  }
+  content->cols = NULL;
+  content->cols = (realtype **) malloc(N * sizeof(realtype *));
+  if (content->cols == NULL) {
+    free(content->data); free(content); free(ops); free(A); return(NULL);
+  }
+  for (j=0; j<N; j++) content->cols[j] = content->data + j * colSize;
+
+  /* Attach content and ops */
+  A->content = content;
+  A->ops     = ops;
+
+  return(A);
+}
+
+/* ----------------------------------------------------------------------------
+ * Function to print the band matrix 
+ */
+ 
+void SUNBandMatrix_Print(SUNMatrix A, FILE* outfile)
+{
+  sunindextype i, j, start, finish;
+
+  /* should not be called unless A is a band matrix; 
+     otherwise return immediately */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND)
+    return;
+
+  /* perform operation */
+  fprintf(outfile,"\n");
+  for (i=0; i<SM_ROWS_B(A); i++) {
+    start = SUNMAX(0, i-SM_LBAND_B(A));
+    finish = SUNMIN(SM_COLUMNS_B(A)-1, i+SM_UBAND_B(A));
+    for (j=0; j<start; j++)
+      fprintf(outfile,"%12s  ","");
+    for (j=start; j<=finish; j++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      fprintf(outfile,"%12Lg  ", SM_ELEMENT_B(A,i,j));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+      fprintf(outfile,"%12g  ", SM_ELEMENT_B(A,i,j));
+#else
+      fprintf(outfile,"%12g  ", SM_ELEMENT_B(A,i,j));
+#endif
+    }
+    fprintf(outfile,"\n");
+  }
+  fprintf(outfile,"\n");
+  return;
+}
+
+/* ----------------------------------------------------------------------------
+ * Functions to access the contents of the band matrix structure
+ */
+
+sunindextype SUNBandMatrix_Rows(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_ROWS_B(A);
+  else
+    return -1;
+}
+
+sunindextype SUNBandMatrix_Columns(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_COLUMNS_B(A);
+  else
+    return -1;
+}
+
+sunindextype SUNBandMatrix_LowerBandwidth(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_LBAND_B(A);
+  else
+    return -1;
+}
+
+sunindextype SUNBandMatrix_UpperBandwidth(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_UBAND_B(A);
+  else
+    return -1;
+}
+
+sunindextype SUNBandMatrix_StoredUpperBandwidth(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_SUBAND_B(A);
+  else
+    return -1;
+}
+
+sunindextype SUNBandMatrix_LDim(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_LDIM_B(A);
+  else
+    return -1;
+}
+
+realtype* SUNBandMatrix_Data(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_DATA_B(A);
+  else
+    return NULL;
+}
+
+realtype** SUNBandMatrix_Cols(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_COLS_B(A);
+  else
+    return NULL;
+}
+
+realtype* SUNBandMatrix_Column(SUNMatrix A, sunindextype j)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_BAND)
+    return SM_COLUMN_B(A,j);
+  else
+    return NULL;
+}
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of matrix operations
+ * -----------------------------------------------------------------
+ */
+
+SUNMatrix_ID SUNMatGetID_Band(SUNMatrix A)
+{
+  return SUNMATRIX_BAND;
+}
+
+SUNMatrix SUNMatClone_Band(SUNMatrix A)
+{
+  SUNMatrix B = SUNBandMatrix(SM_COLUMNS_B(A), SM_UBAND_B(A),
+                              SM_LBAND_B(A), SM_SUBAND_B(A));
+  return(B);
+}
+
+void SUNMatDestroy_Band(SUNMatrix A)
+{
+  if (A == NULL)  return;
+  if (A->ops)  free(A->ops);
+  A->ops = NULL;
+  if (A->content == NULL) {
+    free(A); A = NULL;
+    return;
+  }
+  if (SM_DATA_B(A))  free(SM_DATA_B(A));
+  SM_DATA_B(A) = NULL;
+  if (SM_COLS_B(A))  free(SM_COLS_B(A));
+  SM_COLS_B(A) = NULL;
+  if (A->content)  free(A->content);
+  A->content = NULL;
+  free(A); A = NULL;
+  return;
+}
+
+int SUNMatZero_Band(SUNMatrix A)
+{
+  sunindextype i;
+  realtype *Adata;
+
+  /* Verify that A is a band matrix */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND)
+    return 1;
+
+  /* Perform operation */
+  Adata = SM_DATA_B(A);
+  for (i=0; i<SM_LDATA_B(A); i++)
+    Adata[i] = ZERO;
+  return 0;
+}
+
+int SUNMatCopy_Band(SUNMatrix A, SUNMatrix B)
+{
+  sunindextype i, j, colSize, ml, mu, smu;
+  realtype *A_colj, *B_colj;
+
+  /* Verify that A and B have compatible dimensions */
+  if (!SMCompatible_Band(A, B))
+    return 1;
+
+  /* Grow B if A's bandwidth is larger */
+  if ( (SM_UBAND_B(A) > SM_UBAND_B(B)) ||
+       (SM_LBAND_B(A) > SM_LBAND_B(B)) ) {
+    ml  = SUNMAX(SM_LBAND_B(B),SM_LBAND_B(A));
+    mu  = SUNMAX(SM_UBAND_B(B),SM_UBAND_B(A));
+    smu = SUNMAX(SM_SUBAND_B(B),SM_SUBAND_B(A));
+    colSize = smu + ml + 1;
+    SM_CONTENT_B(B)->mu = mu;
+    SM_CONTENT_B(B)->ml = ml;
+    SM_CONTENT_B(B)->s_mu = smu;
+    SM_CONTENT_B(B)->ldim = colSize;
+    SM_CONTENT_B(B)->ldata = SM_COLUMNS_B(B) * colSize;
+    SM_CONTENT_B(B)->data = realloc(SM_CONTENT_B(B)->data, SM_COLUMNS_B(B) * colSize*sizeof(realtype));
+    for (j=0; j<SM_COLUMNS_B(B); j++)
+      SM_CONTENT_B(B)->cols[j] = SM_CONTENT_B(B)->data + j * colSize;   
+  }
+  
+  /* Perform operation */
+  if (SUNMatZero_Band(B) != 0)
+    return 1;
+  for (j=0; j<SM_COLUMNS_B(B); j++) {
+    B_colj = SM_COLUMN_B(B,j);
+    A_colj = SM_COLUMN_B(A,j);
+    for (i=-SM_UBAND_B(A); i<=SM_LBAND_B(A); i++)
+      B_colj[i] = A_colj[i];
+  }
+  return 0;
+}
+
+int SUNMatScaleAddI_Band(realtype c, SUNMatrix A)
+{
+  sunindextype i, j;
+  realtype *A_colj;
+  
+  /* Verify that A is a band matrix */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND)
+    return 1;
+
+  /* Perform operation */
+  for (j=0; j<SM_COLUMNS_B(A); j++) {
+    A_colj = SM_COLUMN_B(A,j);
+    for (i=-SM_UBAND_B(A); i<=SM_LBAND_B(A); i++)
+      A_colj[i] *= c;
+    SM_ELEMENT_B(A,j,j) += ONE;
+  }
+  return 0;
+}
+
+int SUNMatScaleAdd_Band(realtype c, SUNMatrix A, SUNMatrix B)
+{
+  sunindextype i, j;
+  realtype *A_colj, *B_colj;
+
+  /* Verify that A and B are compatible */
+  if (!SMCompatible_Band(A, B))
+    return 1;
+
+  /* Call separate routine in B has larger bandwidth(s) than A */
+  if ( (SM_UBAND_B(B) > SM_UBAND_B(A)) ||
+       (SM_LBAND_B(B) > SM_LBAND_B(A)) ) {
+    return SMScaleAddNew_Band(c,A,B);
+  }
+  
+  /* Otherwise, perform operation in-place */
+  for (j=0; j<SM_COLUMNS_B(A); j++) {
+    A_colj = SM_COLUMN_B(A,j);
+    B_colj = SM_COLUMN_B(B,j);
+    for (i=-SM_UBAND_B(B); i<=SM_LBAND_B(B); i++)
+      A_colj[i] = c*A_colj[i] + B_colj[i];
+  }
+  return 0;
+}
+
+int SUNMatMatvec_Band(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  sunindextype i, j, is, ie;
+  realtype *col_j, *xd, *yd;
+  
+  /* Verify that A, x and y are compatible */
+  if (!SMCompatible2_Band(A, x, y))
+    return 1;
+
+  /* access vector data (return if failure) */
+  xd = N_VGetArrayPointer(x);
+  yd = N_VGetArrayPointer(y);
+  if ((xd == NULL) || (yd == NULL) || (xd == yd))
+    return 1;
+
+  /* Perform operation */
+  for (i=0; i<SM_ROWS_B(A); i++)
+    yd[i] = ZERO;
+  for(j=0; j<SM_COLUMNS_B(A); j++) {
+    col_j = SM_COLUMN_B(A,j);
+    is = SUNMAX(0, j-SM_UBAND_B(A));
+    ie = SUNMIN(SM_ROWS_B(A)-1, j+SM_LBAND_B(A));
+    for (i=is; i<=ie; i++)
+      yd[i] += col_j[i-j]*xd[j];
+  }
+  return 0;
+}
+
+int SUNMatSpace_Band(SUNMatrix A, long int *lenrw, long int *leniw)
+{
+  *lenrw = SM_COLUMNS_B(A) * (SM_SUBAND_B(A) + SM_LBAND_B(A) + 1);
+  *leniw = 7 + SM_COLUMNS_B(A);
+  return 0;
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+static booleantype SMCompatible_Band(SUNMatrix A, SUNMatrix B)
+{
+  /* both matrices must be SUNMATRIX_BAND */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND)
+    return SUNFALSE;
+  if (SUNMatGetID(B) != SUNMATRIX_BAND)
+    return SUNFALSE;
+
+  /* both matrices must have the same number of columns
+     (note that we do not check for identical bandwidth) */
+  if (SM_ROWS_B(A) != SM_ROWS_B(B))
+    return SUNFALSE;
+  if (SM_COLUMNS_B(A) != SM_COLUMNS_B(B))
+    return SUNFALSE;
+
+  return SUNTRUE;
+}
+
+
+static booleantype SMCompatible2_Band(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  /*   matrix must be SUNMATRIX_BAND */
+  if (SUNMatGetID(A) != SUNMATRIX_BAND)
+    return SUNFALSE;
+
+  /*   vectors must be one of {SERIAL, OPENMP, PTHREADS} */ 
+  if ( (N_VGetVectorID(x) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(x) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(x) != SUNDIALS_NVEC_PTHREADS) )
+    return SUNFALSE;
+
+  /* Optimally we would verify that the dimensions of A, x and y agree, 
+   but since there is no generic 'length' routine for N_Vectors we cannot */
+
+  return SUNTRUE;
+}
+
+
+int SMScaleAddNew_Band(realtype c, SUNMatrix A, SUNMatrix B)
+{
+  sunindextype i, j, ml, mu, smu;
+  realtype *A_colj, *B_colj, *C_colj;
+  SUNMatrix C;
+
+  /* create new matrix large enough to hold both A and B */
+  ml  = SUNMAX(SM_LBAND_B(A),SM_LBAND_B(B));
+  mu  = SUNMAX(SM_UBAND_B(A),SM_UBAND_B(B));
+  smu = SUNMIN(SM_COLUMNS_B(A)-1, mu + ml);
+  C = SUNBandMatrix(SM_COLUMNS_B(A), mu, ml, smu);
+
+  /* scale/add c*A into new matrix */
+  for (j=0; j<SM_COLUMNS_B(A); j++) {
+    A_colj = SM_COLUMN_B(A,j);
+    C_colj = SM_COLUMN_B(C,j);
+    for (i=-SM_UBAND_B(A); i<=SM_LBAND_B(A); i++)
+      C_colj[i] = c*A_colj[i];
+  }
+  
+  /* add B into new matrix */
+  for (j=0; j<SM_COLUMNS_B(B); j++) {
+    B_colj = SM_COLUMN_B(B,j);
+    C_colj = SM_COLUMN_B(C,j);
+    for (i=-SM_UBAND_B(B); i<=SM_LBAND_B(B); i++)
+      C_colj[i] += B_colj[i];
+  }
+  
+  /* replace A contents with C contents, nullify C content pointer, destroy C */
+  free(SM_DATA_B(A));  SM_DATA_B(A) = NULL;
+  free(SM_COLS_B(A));  SM_COLS_B(A) = NULL;
+  free(A->content);    A->content = NULL;
+  A->content = C->content;
+  C->content = NULL;
+  SUNMatDestroy_Band(C);
+  
+  return 0;
+}
+
diff --git a/src/sunmat_dense/CMakeLists.txt b/src/sunmat_dense/CMakeLists.txt
new file mode 100644
index 0000000..1591b4c
--- /dev/null
+++ b/src/sunmat_dense/CMakeLists.txt
@@ -0,0 +1,104 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the dense SUNMatrix library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNMATRIX_DENSE\n\")")
+
+# Add variable sunmatrixdense_SOURCES with the sources for the SUNMATRIXDENSE lib
+SET(sunmatrixdense_SOURCES sunmatrix_dense.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNMATRIXDENSE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
+
+# Add variable sunmatrixdense_HEADERS with the exported SUNMATRIXDENSE header files
+SET(sunmatrixdense_HEADERS 
+  ${sundials_SOURCE_DIR}/include/sunmatrix/sunmatrix_dense.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNMATRIXDENSE library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNMATRIXDENSE library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunmatrixdense_static STATIC ${sunmatrixdense_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunmatrixdense_static
+    PROPERTIES OUTPUT_NAME sundials_sunmatrixdense CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunmatrixdense_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNMATRIXDENSE library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNMATRIXDENSE library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunmatrixdense_shared SHARED ${sunmatrixdense_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunmatrixdense_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunmatrixdense_shared
+    PROPERTIES OUTPUT_NAME sundials_sunmatrixdense CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunmatrixdense_shared
+    PROPERTIES VERSION ${sunmatrixlib_VERSION} SOVERSION ${sunmatrixlib_SOVERSION})
+  INSTALL(TARGETS sundials_sunmatrixdense_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNMATRIXDENSE header files
+INSTALL(FILES ${sunmatrixdense_HEADERS} DESTINATION include/sunmatrix)
+
+# If FCMIX is enabled, build and install the FSUNMATRIXDENSE library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunmatrixdense_SOURCES fsunmatrix_dense.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunmatrixdense_static STATIC ${fsunmatrixdense_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixdense_static
+      PROPERTIES OUTPUT_NAME sundials_fsunmatrixdense CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunmatrixdense_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunmatrixdense_shared ${fsunmatrixdense_SOURCES})
+
+    # fsunmatrixdense depends on sunmatrixdense
+    TARGET_LINK_LIBRARIES(sundials_fsunmatrixdense_shared sundials_sunmatrixdense_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixdense_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunmatrixdense CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixdense_shared 
+      PROPERTIES VERSION ${sunmatrixlib_VERSION} SOVERSION ${sunmatrixlib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunmatrixdense_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNMATRIX_DENSE module")
diff --git a/src/sunmat_dense/README b/src/sunmat_dense/README
new file mode 100644
index 0000000..095540c
--- /dev/null
+++ b/src/sunmat_dense/README
@@ -0,0 +1,44 @@
+                     SUNMATRIX_DENSE
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Dense implementation of the SUNMATRIX module for SUNDIALS. 
+
+SUNMATRIX_DENSE defines the content field of SUNMatrix to be a structure 
+containing the number of rows and columns of the matrix, the total
+allocated size of the matrix, a pointer to the beginning of a
+contiguous data array, and an array of pointers to the first entry of
+each column of the matrix.
+
+SUNMATRIX_DENSE defines six macros to provide access to the content of 
+a dense SUNMatrix, a constructor for variables of type SUNMatrix,
+destructors for SUNMatrix, and a utility function for printing a
+dense SUNMatrix to screen/file.
+
+SUNMATRIX_DENSE provides implementations for all matrix operations defined
+by the generic SUNMATRIX module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The dense SUNMATRIX implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunmat_dense/fsunmatrix_dense.c b/src/sunmat_dense/fsunmatrix_dense.c
new file mode 100644
index 0000000..f56afef
--- /dev/null
+++ b/src/sunmat_dense/fsunmatrix_dense.c
@@ -0,0 +1,82 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunmatrix_dense.h) contains the
+ * implementation needed for the Fortran initialization of dense
+ * vector operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunmatrix_dense.h"
+
+/* Define global matrix variables */
+
+SUNMatrix F2C_CVODE_matrix;
+SUNMatrix F2C_IDA_matrix;
+SUNMatrix F2C_KINSOL_matrix;
+SUNMatrix F2C_ARKODE_matrix;
+SUNMatrix F2C_ARKODE_mass_matrix;
+
+/* Fortran callable interfaces */
+
+void FSUNDENSEMAT_INIT(int *code, long int *M, long int *N, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+  if (F2C_CVODE_matrix)  SUNMatDestroy(F2C_CVODE_matrix);
+    F2C_CVODE_matrix = NULL;
+    F2C_CVODE_matrix = SUNDenseMatrix(*M, *N);
+    if (F2C_CVODE_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+  if (F2C_IDA_matrix)  SUNMatDestroy(F2C_IDA_matrix);
+    F2C_IDA_matrix = NULL;
+    F2C_IDA_matrix = SUNDenseMatrix(*M, *N);
+    if (F2C_IDA_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+  if (F2C_KINSOL_matrix)  SUNMatDestroy(F2C_KINSOL_matrix);
+    F2C_KINSOL_matrix = NULL;
+    F2C_KINSOL_matrix = SUNDenseMatrix(*M, *N);
+    if (F2C_KINSOL_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+  if (F2C_ARKODE_matrix)  SUNMatDestroy(F2C_ARKODE_matrix);
+    F2C_ARKODE_matrix = NULL;
+    F2C_ARKODE_matrix = SUNDenseMatrix(*M, *N);
+    if (F2C_ARKODE_matrix == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+
+void FSUNDENSEMASSMAT_INIT(long int *M, long int *N, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_matrix)  SUNMatDestroy(F2C_ARKODE_mass_matrix);
+  F2C_ARKODE_mass_matrix = NULL;
+  F2C_ARKODE_mass_matrix = SUNDenseMatrix(*M, *N);
+  if (F2C_ARKODE_mass_matrix == NULL) *ier = -1;
+}
diff --git a/src/sunmat_dense/fsunmatrix_dense.h b/src/sunmat_dense/fsunmatrix_dense.h
new file mode 100644
index 0000000..cfc3dc2
--- /dev/null
+++ b/src/sunmat_dense/fsunmatrix_dense.h
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunmatrix_dense.c) contains the
+ * definitions needed for the initialization of dense
+ * matrix operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNMATRIX_DENSE_H
+#define _FSUNMATRIX_DENSE_H
+
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNDENSEMAT_INIT     SUNDIALS_F77_FUNC(fsundensematinit, FSUNDENSEMATINIT)
+#define FSUNDENSEMASSMAT_INIT SUNDIALS_F77_FUNC(fsundensemassmatinit, FSUNDENSEMASSMATINIT)
+#else
+#define FSUNDENSEMAT_INIT     fsundensematinit_
+#define FSUNDENSEMASSMAT_INIT fsundensemassmatinit_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNDENSEMAT_INIT - initializes dense matrix operations for main problem
+ * FSUNDENSEMASSMAT_INIT - initializes dense matrix operations for mass matrix solver
+ */
+
+void FSUNDENSEMAT_INIT(int *code, long int *M, long int *N, int *ier);
+void FSUNDENSEMASSMAT_INIT(long int *M, long int *N, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunmat_dense/sunmatrix_dense.c b/src/sunmat_dense/sunmatrix_dense.c
new file mode 100644
index 0000000..ab6cdcf
--- /dev/null
+++ b/src/sunmat_dense/sunmatrix_dense.c
@@ -0,0 +1,352 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * Based on code sundials_dense.c by: Scott D. Cohen, 
+ *     Alan C. Hindmarsh and Radu Serban @ LLNL
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the dense implementation of 
+ * the SUNMATRIX package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunmatrix/sunmatrix_dense.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+
+/* Private function prototypes */
+static booleantype SMCompatible_Dense(SUNMatrix A, SUNMatrix B);
+static booleantype SMCompatible2_Dense(SUNMatrix A, N_Vector x, N_Vector y);
+
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new dense matrix
+ */
+
+SUNMatrix SUNDenseMatrix(sunindextype M, sunindextype N)
+{
+  SUNMatrix A;
+  SUNMatrix_Ops ops;
+  SUNMatrixContent_Dense content;
+  sunindextype j;
+
+  /* return with NULL matrix on illegal dimension input */
+  if ( (M <= 0) || (N <= 0) ) return(NULL);
+
+  /* Create matrix */
+  A = NULL;
+  A = (SUNMatrix) malloc(sizeof *A);
+  if (A == NULL) return(NULL);
+  
+  /* Create matrix operation structure */
+  ops = NULL;
+  ops = (SUNMatrix_Ops) malloc(sizeof(struct _generic_SUNMatrix_Ops));
+  if (ops == NULL) { free(A); return(NULL); }
+
+  /* Attach operations */
+  ops->getid       = SUNMatGetID_Dense;
+  ops->clone       = SUNMatClone_Dense;
+  ops->destroy     = SUNMatDestroy_Dense;
+  ops->zero        = SUNMatZero_Dense;
+  ops->copy        = SUNMatCopy_Dense;
+  ops->scaleadd    = SUNMatScaleAdd_Dense;
+  ops->scaleaddi   = SUNMatScaleAddI_Dense;
+  ops->matvec      = SUNMatMatvec_Dense;
+  ops->space       = SUNMatSpace_Dense;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNMatrixContent_Dense) malloc(sizeof(struct _SUNMatrixContent_Dense));
+  if (content == NULL) { free(ops); free(A); return(NULL); }
+
+  /* Fill content */
+  content->M = M;
+  content->N = N;
+  content->ldata = M*N;
+  content->data = NULL;
+  content->data = (realtype *) calloc(M * N, sizeof(realtype));
+  if (content->data == NULL) {
+    free(content); free(ops); free(A); return(NULL);
+  }
+  content->cols = NULL;
+  content->cols = (realtype **) malloc(N * sizeof(realtype *));
+  if (content->cols == NULL) {
+    free(content->data); free(content); free(ops); free(A); return(NULL);
+  }
+  for (j=0; j<N; j++) content->cols[j] = content->data + j * M;
+  
+  /* Attach content and ops */
+  A->content = content;
+  A->ops     = ops;
+
+  return(A);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to print the dense matrix 
+ */
+ 
+void SUNDenseMatrix_Print(SUNMatrix A, FILE* outfile)
+{
+  sunindextype i, j;
+  
+  /* should not be called unless A is a dense matrix; 
+     otherwise return immediately */
+  if (SUNMatGetID(A) != SUNMATRIX_DENSE)
+    return;
+
+  /* perform operation */
+  fprintf(outfile,"\n");
+  for (i=0; i<SM_ROWS_D(A); i++) {
+    for (j=0; j<SM_COLUMNS_D(A); j++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      fprintf(outfile,"%12Lg  ", SM_ELEMENT_D(A,i,j));
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+      fprintf(outfile,"%12g  ", SM_ELEMENT_D(A,i,j));
+#else
+      fprintf(outfile,"%12g  ", SM_ELEMENT_D(A,i,j));
+#endif
+    }
+    fprintf(outfile,"\n");
+  }
+  fprintf(outfile,"\n");
+  return;
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Functions to access the contents of the dense matrix structure
+ */
+
+sunindextype SUNDenseMatrix_Rows(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_DENSE)
+    return SM_ROWS_D(A);
+  else
+    return -1;
+}
+
+sunindextype SUNDenseMatrix_Columns(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_DENSE)
+    return SM_COLUMNS_D(A);
+  else
+    return -1;
+}
+
+sunindextype SUNDenseMatrix_LData(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_DENSE)
+    return SM_LDATA_D(A);
+  else
+    return -1;
+}
+
+realtype* SUNDenseMatrix_Data(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_DENSE)
+    return SM_DATA_D(A);
+  else
+    return NULL;
+}
+
+realtype** SUNDenseMatrix_Cols(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_DENSE)
+    return SM_COLS_D(A);
+  else
+    return NULL;
+}
+
+realtype* SUNDenseMatrix_Column(SUNMatrix A, sunindextype j)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_DENSE)
+    return SM_COLUMN_D(A,j);
+  else
+    return NULL;
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of matrix operations
+ * -----------------------------------------------------------------
+ */
+
+SUNMatrix_ID SUNMatGetID_Dense(SUNMatrix A)
+{
+  return SUNMATRIX_DENSE;
+}
+
+SUNMatrix SUNMatClone_Dense(SUNMatrix A)
+{
+  SUNMatrix B = SUNDenseMatrix(SM_ROWS_D(A), SM_COLUMNS_D(A));
+  return(B);
+}
+
+void SUNMatDestroy_Dense(SUNMatrix A)
+{
+  /* perform operation */
+  free(SM_DATA_D(A));  SM_DATA_D(A) = NULL;
+  free(SM_CONTENT_D(A)->cols);  SM_CONTENT_D(A)->cols = NULL;
+  free(A->content);  A->content = NULL;
+  free(A->ops);  A->ops = NULL;
+  free(A); A = NULL;
+  return;
+}
+
+int SUNMatZero_Dense(SUNMatrix A)
+{
+  sunindextype i;
+  realtype *Adata;
+
+  /* Perform operation */
+  Adata = SM_DATA_D(A);
+  for (i=0; i<SM_LDATA_D(A); i++)
+    Adata[i] = ZERO;
+  return 0;
+}
+
+int SUNMatCopy_Dense(SUNMatrix A, SUNMatrix B)
+{
+  sunindextype i, j;
+
+  /* Verify that A and B are compatible */
+  if (!SMCompatible_Dense(A, B))
+    return 1;
+
+  /* Perform operation */
+  for (j=0; j<SM_COLUMNS_D(A); j++)
+    for (i=0; i<SM_ROWS_D(A); i++)
+      SM_ELEMENT_D(B,i,j) = SM_ELEMENT_D(A,i,j);
+  return 0;
+}
+
+int SUNMatScaleAddI_Dense(realtype c, SUNMatrix A)
+{
+  sunindextype i, j;
+
+  /* Perform operation */
+  for (j=0; j<SM_COLUMNS_D(A); j++)
+    for (i=0; i<SM_ROWS_D(A); i++) {
+      SM_ELEMENT_D(A,i,j) *= c;
+      if (i == j) 
+        SM_ELEMENT_D(A,i,j) += ONE;
+    }
+  return 0;
+}
+
+int SUNMatScaleAdd_Dense(realtype c, SUNMatrix A, SUNMatrix B)
+{
+  sunindextype i, j;
+
+  /* Verify that A and B are compatible */
+  if (!SMCompatible_Dense(A, B))
+    return 1;
+
+  /* Perform operation */
+  for (j=0; j<SM_COLUMNS_D(A); j++)
+    for (i=0; i<SM_ROWS_D(A); i++)
+      SM_ELEMENT_D(A,i,j) = c*SM_ELEMENT_D(A,i,j) + SM_ELEMENT_D(B,i,j);
+  return 0;
+}
+
+int SUNMatMatvec_Dense(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  sunindextype i, j;
+  realtype *col_j, *xd, *yd;
+  
+  /* Verify that A, x and y are compatible */
+  if (!SMCompatible2_Dense(A, x, y))
+    return 1;
+
+  /* access vector data (return if failure) */
+  xd = N_VGetArrayPointer(x);
+  yd = N_VGetArrayPointer(y);
+  if ((xd == NULL) || (yd == NULL) || (xd == yd))
+    return 1;
+
+  /* Perform operation */
+  for (i=0; i<SM_ROWS_D(A); i++)
+    yd[i] = ZERO;
+  for(j=0; j<SM_COLUMNS_D(A); j++) {
+    col_j = SM_COLUMN_D(A,j);
+    for (i=0; i<SM_ROWS_D(A); i++)
+      yd[i] += col_j[i]*xd[j];
+  }
+  return 0;
+}
+
+int SUNMatSpace_Dense(SUNMatrix A, long int *lenrw, long int *leniw)
+{
+  *lenrw = SM_LDATA_D(A);
+  *leniw = 3 + SM_COLUMNS_D(A);
+  return 0;
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * private functions
+ * -----------------------------------------------------------------
+ */
+
+static booleantype SMCompatible_Dense(SUNMatrix A, SUNMatrix B)
+{
+  /* both matrices must be SUNMATRIX_DENSE */
+  if (SUNMatGetID(A) != SUNMATRIX_DENSE)
+    return SUNFALSE;
+  if (SUNMatGetID(B) != SUNMATRIX_DENSE)
+    return SUNFALSE;
+
+  /* both matrices must have the same shape */
+  if (SM_ROWS_D(A) != SM_ROWS_D(B))
+    return SUNFALSE;
+  if (SM_COLUMNS_D(A) != SM_COLUMNS_D(B))
+    return SUNFALSE;
+
+  return SUNTRUE;
+}
+
+
+static booleantype SMCompatible2_Dense(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  /*   vectors must be one of {SERIAL, OPENMP, PTHREADS} */ 
+  if ( (N_VGetVectorID(x) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(x) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(x) != SUNDIALS_NVEC_PTHREADS) )
+    return SUNFALSE;
+
+  /* Optimally we would verify that the dimensions of A, x and y agree, 
+   but since there is no generic 'length' routine for N_Vectors we cannot */
+
+  return SUNTRUE;
+}
+
diff --git a/src/sunmat_sparse/CMakeLists.txt b/src/sunmat_sparse/CMakeLists.txt
new file mode 100644
index 0000000..fbcba7d
--- /dev/null
+++ b/src/sunmat_sparse/CMakeLists.txt
@@ -0,0 +1,104 @@
+# ---------------------------------------------------------------
+# Programmer:  Daniel R. Reynolds @ SMU
+# ---------------------------------------------------------------
+# LLNS/SMU Copyright Start
+# Copyright (c) 2017, Southern Methodist University and 
+# Lawrence Livermore National Security
+#
+# This work was performed under the auspices of the U.S. Department 
+# of Energy by Southern Methodist University and Lawrence Livermore 
+# National Laboratory under Contract DE-AC52-07NA27344.
+# Produced at Southern Methodist University and the Lawrence 
+# Livermore National Laboratory.
+#
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS/SMU Copyright End
+# ---------------------------------------------------------------
+# CMakeLists.txt file for the sparse SUNMatrix library
+
+INSTALL(CODE "MESSAGE(\"\nInstall SUNMATRIX_SPARSE\n\")")
+
+# Add variable sunmatrixsparse_SOURCES with the sources for the SUNMATRIXSPARSE lib
+SET(sunmatrixsparse_SOURCES sunmatrix_sparse.c)
+
+# Add variable shared_SOURCES with the common SUNDIALS sources which will
+# also be included in the SUNMATRIXSPARSE library
+SET(shared_SOURCES
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_nvector.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_matrix.c
+  ${sundials_SOURCE_DIR}/src/sundials/sundials_math.c
+  )
+
+# Add variable sunmatrixsparse_HEADERS with the exported SUNMATRIXSPARSE header files
+SET(sunmatrixsparse_HEADERS
+  ${sundials_SOURCE_DIR}/include/sunmatrix/sunmatrix_sparse.h
+  )
+
+# Add source directory to include directories
+INCLUDE_DIRECTORIES(.)
+
+# Define C preprocessor flag -DBUILD_SUNDIALS_LIBRARY 
+ADD_DEFINITIONS(-DBUILD_SUNDIALS_LIBRARY)
+
+# Rules for building and installing the static library:
+#  - Add the build target for the SUNMATRIXSPARSE library
+#  - Set the library name and make sure it is not deleted
+#  - Install the SUNMATRIXSPARSE library
+IF(BUILD_STATIC_LIBS)
+  ADD_LIBRARY(sundials_sunmatrixsparse_static STATIC ${sunmatrixsparse_SOURCES} ${shared_SOURCES})
+  SET_TARGET_PROPERTIES(sundials_sunmatrixsparse_static
+    PROPERTIES OUTPUT_NAME sundials_sunmatrixsparse CLEAN_DIRECT_OUTPUT 1)
+  INSTALL(TARGETS sundials_sunmatrixsparse_static DESTINATION lib)
+ENDIF(BUILD_STATIC_LIBS)
+
+# Rules for building and installing the shared library:
+#  - Add the build target for the SUNMATRIXSPARSE library
+#  - Set the library name and make sure it is not deleted
+#  - Set VERSION and SOVERSION for shared libraries
+#  - Install the SUNMATRIXSPARSE library
+IF(BUILD_SHARED_LIBS)
+  ADD_LIBRARY(sundials_sunmatrixsparse_shared SHARED ${sunmatrixsparse_SOURCES} ${shared_SOURCES})
+
+  IF(UNIX)
+    TARGET_LINK_LIBRARIES(sundials_sunmatrixsparse_shared m)
+  ENDIF()
+
+  SET_TARGET_PROPERTIES(sundials_sunmatrixsparse_shared
+    PROPERTIES OUTPUT_NAME sundials_sunmatrixsparse CLEAN_DIRECT_OUTPUT 1)
+  SET_TARGET_PROPERTIES(sundials_sunmatrixsparse_shared
+    PROPERTIES VERSION ${sunmatrixlib_VERSION} SOVERSION ${sunmatrixlib_SOVERSION})
+  INSTALL(TARGETS sundials_sunmatrixsparse_shared DESTINATION lib)
+ENDIF(BUILD_SHARED_LIBS)
+
+# Install the SUNMATRIXSPARSE header files
+INSTALL(FILES ${sunmatrixsparse_HEADERS} DESTINATION include/sunmatrix)
+
+# If FCMIX is enabled, build and install the FSUNMATRIXSPARSE library
+IF(FCMIX_ENABLE AND F77_FOUND)
+  SET(fsunmatrixsparse_SOURCES fsunmatrix_sparse.c)
+
+  IF(BUILD_STATIC_LIBS)
+    ADD_LIBRARY(sundials_fsunmatrixsparse_static STATIC ${fsunmatrixsparse_SOURCES})
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixsparse_static
+      PROPERTIES OUTPUT_NAME sundials_fsunmatrixsparse CLEAN_DIRECT_OUTPUT 1)
+    INSTALL(TARGETS sundials_fsunmatrixsparse_static DESTINATION lib)
+  ENDIF(BUILD_STATIC_LIBS)
+
+  IF(BUILD_SHARED_LIBS)
+    ADD_LIBRARY(sundials_fsunmatrixsparse_shared ${fsunmatrixsparse_SOURCES})
+
+    # fsunmatrixdense depends on sunmatrixsparse
+    TARGET_LINK_LIBRARIES(sundials_fsunmatrixsparse_shared sundials_sunmatrixsparse_shared)
+
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixsparse_shared
+      PROPERTIES OUTPUT_NAME sundials_fsunmatrixsparse CLEAN_DIRECT_OUTPUT 1)
+    SET_TARGET_PROPERTIES(sundials_fsunmatrixsparse_shared 
+      PROPERTIES VERSION ${sunmatrixlib_VERSION} SOVERSION ${sunmatrixlib_SOVERSION})
+    INSTALL(TARGETS sundials_fsunmatrixsparse_shared DESTINATION lib)
+  ENDIF(BUILD_SHARED_LIBS)
+
+ENDIF(FCMIX_ENABLE AND F77_FOUND)
+
+#
+MESSAGE(STATUS "Added SUNMATRIX_SPARSE module")
diff --git a/src/sunmat_sparse/README b/src/sunmat_sparse/README
new file mode 100644
index 0000000..c783cb6
--- /dev/null
+++ b/src/sunmat_sparse/README
@@ -0,0 +1,48 @@
+                     SUNMATRIX_SPARSE
+                 released as part of SUNDIALS
+    SUite of Nonlinear and DIfferential/ALgebraic equation Solvers
+                   Release 3.0.0, September 2017
+
+
+Sparse implementation of the SUNMATRIX module for SUNDIALS. 
+
+SUNMATRIX_SPARSE defines the content field of SUNMatrix to be a structure 
+containing the type of sparse matrix (CSC_MAT vs CSR_MAT), the number
+of rows and columns of the matrix, the number of nonzeros in the
+matrix, a pointer to the beginning of a contiguous data array for the
+matrix values, a pointer to the beginning of a contiguous index array
+for the row/column indices of those values, a pointer to the beginning
+of a contiguous data array for the starting indices of each column/row 
+in the value/index arrays, and auxiliary pointers to simplify
+routines for handling CSC and CSR interfaces.
+
+SUNMATRIX_SPARSE defines nine macros to provide access to the content of 
+a sparse SUNMatrix, constructors for objects of type SUNMatrix,
+destructors for SUNMatrix, and a utility function for printing a
+sparse SUNMatrix to screen/file.
+
+SUNMATRIX_SPARSE provides implementations for all matrix operations defined
+by the generic SUNMATRIX module in the table of operations.
+
+
+A. Documentation
+----------------
+
+The sparse SUNMATRIX implementation is fully described in the user
+documentation for any of the SUNDIALS solvers. A PDF file for the user
+guide for a particular solver is available in the solver's
+subdirectory under doc/. 
+
+
+B. Installation
+---------------
+
+For basic installation instructions see /sundials/INSTALL_GUIDE.pdf. 
+For complete installation instructions see any of the user guides.
+
+
+D. Releases
+-----------
+v. 1.0   - date?
+
+
diff --git a/src/sunmat_sparse/fsunmatrix_sparse.c b/src/sunmat_sparse/fsunmatrix_sparse.c
new file mode 100644
index 0000000..9e0a36f
--- /dev/null
+++ b/src/sunmat_sparse/fsunmatrix_sparse.c
@@ -0,0 +1,83 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunmatrix_sparse.h) contains the
+ * implementation needed for the Fortran initialization of sparse
+ * vector operations.
+ * -----------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fsunmatrix_sparse.h"
+
+/* Define global matrix variables */
+
+SUNMatrix F2C_CVODE_matrix;
+SUNMatrix F2C_IDA_matrix;
+SUNMatrix F2C_KINSOL_matrix;
+SUNMatrix F2C_ARKODE_matrix;
+SUNMatrix F2C_ARKODE_mass_matrix;
+
+/* Fortran callable interfaces */
+
+void FSUNSPARSEMAT_INIT(int *code, long int *M, long int *N,
+                        long int *NNZ, int *sparsetype, int *ier)
+{
+  *ier = 0;
+
+  switch(*code) {
+  case FCMIX_CVODE:
+    if (F2C_CVODE_matrix)  SUNMatDestroy(F2C_CVODE_matrix);
+    F2C_CVODE_matrix = NULL;
+    F2C_CVODE_matrix = SUNSparseMatrix(*M, *N, *NNZ, *sparsetype);
+    if (F2C_CVODE_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_IDA:
+    if (F2C_IDA_matrix)  SUNMatDestroy(F2C_IDA_matrix);
+    F2C_IDA_matrix = NULL;
+    F2C_IDA_matrix = SUNSparseMatrix(*M, *N, *NNZ, *sparsetype);
+    if (F2C_IDA_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_KINSOL:
+    if (F2C_KINSOL_matrix)  SUNMatDestroy(F2C_KINSOL_matrix);
+    F2C_KINSOL_matrix = NULL;
+    F2C_KINSOL_matrix = SUNSparseMatrix(*M, *N, *NNZ, *sparsetype);
+    if (F2C_KINSOL_matrix == NULL) *ier = -1;
+    break;
+  case FCMIX_ARKODE:
+    if (F2C_ARKODE_matrix)  SUNMatDestroy(F2C_ARKODE_matrix);
+    F2C_ARKODE_matrix = NULL;
+    F2C_ARKODE_matrix = SUNSparseMatrix(*M, *N, *NNZ, *sparsetype);
+    if (F2C_ARKODE_matrix == NULL) *ier = -1;
+    break;
+  default:
+    *ier = -1;
+  }
+}
+
+void FSUNSPARSEMASSMAT_INIT(long int *M, long int *N, long int *NNZ, 
+                            int *sparsetype, int *ier)
+{
+  *ier = 0;
+  if (F2C_ARKODE_mass_matrix)  SUNMatDestroy(F2C_ARKODE_mass_matrix);
+  F2C_ARKODE_mass_matrix = NULL;
+  F2C_ARKODE_mass_matrix = SUNSparseMatrix(*M, *N, *NNZ, *sparsetype);
+  if (F2C_ARKODE_mass_matrix == NULL) *ier = -1;
+}
diff --git a/src/sunmat_sparse/fsunmatrix_sparse.h b/src/sunmat_sparse/fsunmatrix_sparse.h
new file mode 100644
index 0000000..5d23c1d
--- /dev/null
+++ b/src/sunmat_sparse/fsunmatrix_sparse.h
@@ -0,0 +1,69 @@
+/*
+ * ----------------------------------------------------------------- 
+ * Programmer(s): Daniel Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This file (companion of fsunmatrix_sparse.c) contains the
+ * definitions needed for the initialization of sparse
+ * matrix operations in Fortran.
+ * -----------------------------------------------------------------
+ */
+
+#ifndef _FSUNMATRIX_SPARSE_H
+#define _FSUNMATRIX_SPARSE_H
+
+#include <sunmatrix/sunmatrix_sparse.h>
+#include <sundials/sundials_fnvector.h>
+
+#ifdef __cplusplus  /* wrapper to enable C++ usage */
+extern "C" {
+#endif
+
+#if defined(SUNDIALS_F77_FUNC)
+#define FSUNSPARSEMAT_INIT     SUNDIALS_F77_FUNC(fsunsparsematinit, FSUNSPARSEMATINIT)
+#define FSUNSPARSEMASSMAT_INIT SUNDIALS_F77_FUNC(fsunsparsemassmatinit, FSUNSPARSEMASSMATINIT)
+#else
+#define FSUNSPARSEMAT_INIT     fsunsparsematinit_
+#define FSUNSPARSEMASSMAT_INIT fsunsparsemassmatinit_
+#endif
+
+
+/* Declarations of global variables */
+
+extern SUNMatrix F2C_CVODE_matrix;
+extern SUNMatrix F2C_IDA_matrix;
+extern SUNMatrix F2C_KINSOL_matrix;
+extern SUNMatrix F2C_ARKODE_matrix;
+extern SUNMatrix F2C_ARKODE_mass_matrix;
+
+/* 
+ * Prototypes of exported functions 
+ *
+ * FSUNSPARSEMAT_INIT - initializes sparse matrix operations for main problem
+ * FSUNSPARSEMASSMAT_INIT - initializes sparse matrix operations for mass matrix solve
+ */
+
+void FSUNSPARSEMAT_INIT(int *code, long int *M, long int *N,
+                        long int *NNZ, int *sparsetype, int *ier);
+
+void FSUNSPARSEMASSMAT_INIT(long int *M, long int *N,
+                            long int *NNZ, int *sparsetype, int *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/sunmat_sparse/sunmatrix_sparse.c b/src/sunmat_sparse/sunmatrix_sparse.c
new file mode 100644
index 0000000..61c2c3e
--- /dev/null
+++ b/src/sunmat_sparse/sunmatrix_sparse.c
@@ -0,0 +1,1004 @@
+/*
+ * -----------------------------------------------------------------
+ * Programmer(s): Daniel Reynolds @ SMU
+ *                David Gardner @ LLNL
+ * Based on code sundials_sparse.c by: Carol Woodward and 
+ *     Slaven Peles @ LLNL, and Daniel R. Reynolds @ SMU
+ * -----------------------------------------------------------------
+ * LLNS/SMU Copyright Start
+ * Copyright (c) 2017, Southern Methodist University and 
+ * Lawrence Livermore National Security
+ *
+ * This work was performed under the auspices of the U.S. Department 
+ * of Energy by Southern Methodist University and Lawrence Livermore 
+ * National Laboratory under Contract DE-AC52-07NA27344.
+ * Produced at Southern Methodist University and the Lawrence 
+ * Livermore National Laboratory.
+ *
+ * All rights reserved.
+ * For details, see the LICENSE file.
+ * LLNS/SMU Copyright End
+ * -----------------------------------------------------------------
+ * This is the implementation file for the sparse implementation of 
+ * the SUNMATRIX package.
+ * -----------------------------------------------------------------
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sunmatrix/sunmatrix_sparse.h>
+#include <sundials/sundials_nvector.h>
+#include <sundials/sundials_math.h>
+
+#define ZERO RCONST(0.0)
+#define ONE  RCONST(1.0)
+
+/* Private function prototypes */
+static booleantype SMCompatible_Sparse(SUNMatrix A, SUNMatrix B);
+static booleantype SMCompatible2_Sparse(SUNMatrix A, N_Vector x, N_Vector y);
+int Matvec_SparseCSC(SUNMatrix A, N_Vector x, N_Vector y);
+int Matvec_SparseCSR(SUNMatrix A, N_Vector x, N_Vector y);
+
+/*
+ * -----------------------------------------------------------------
+ * exported functions
+ * -----------------------------------------------------------------
+ */
+
+/*
+ * ==================================================================
+ * Private function prototypes (functions working on SlsMat)
+ * ==================================================================
+ */
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new sparse matrix
+ */
+
+SUNMatrix SUNSparseMatrix(sunindextype M, sunindextype N,
+                          sunindextype NNZ, int sparsetype)
+{
+  SUNMatrix A;
+  SUNMatrix_Ops ops;
+  SUNMatrixContent_Sparse content;
+
+  /* return with NULL matrix on illegal input */
+  if ( (M <= 0) || (N <= 0) || (NNZ < 0) ) return(NULL);
+  if ( (sparsetype != CSC_MAT) && (sparsetype != CSR_MAT) ) return(NULL);
+
+  /* Create matrix */
+  A = NULL;
+  A = (SUNMatrix) malloc(sizeof *A);
+  if (A == NULL) return(NULL);
+  
+  /* Create matrix operation structure */
+  ops = NULL;
+  ops = (SUNMatrix_Ops) malloc(sizeof(struct _generic_SUNMatrix_Ops));
+  if (ops == NULL) { free(A); return(NULL); }
+
+  /* Attach operations */
+  ops->getid       = SUNMatGetID_Sparse;
+  ops->clone       = SUNMatClone_Sparse;
+  ops->destroy     = SUNMatDestroy_Sparse;
+  ops->zero        = SUNMatZero_Sparse;
+  ops->copy        = SUNMatCopy_Sparse;
+  ops->scaleadd    = SUNMatScaleAdd_Sparse;
+  ops->scaleaddi   = SUNMatScaleAddI_Sparse;
+  ops->matvec      = SUNMatMatvec_Sparse;
+  ops->space       = SUNMatSpace_Sparse;
+
+  /* Create content */
+  content = NULL;
+  content = (SUNMatrixContent_Sparse) malloc(sizeof(struct _SUNMatrixContent_Sparse));
+  if (content == NULL) { free(ops); free(A); return(NULL); }
+
+  /* Fill content */
+  content->sparsetype = sparsetype;
+  content->M = M;
+  content->N = N;
+  content->NNZ = NNZ;
+  switch(sparsetype){
+  case CSC_MAT:
+    content->NP = N;
+    content->rowvals = &(content->indexvals);
+    content->colptrs = &(content->indexptrs);
+    /* CSR indices */
+    content->colvals = NULL;
+    content->rowptrs = NULL;
+    break;
+  case CSR_MAT:
+    content->NP = M;
+    content->colvals = &(content->indexvals);
+    content->rowptrs = &(content->indexptrs);
+    /* CSC indices */
+    content->rowvals = NULL;
+    content->colptrs = NULL;
+  }
+  content->data = (realtype *) calloc(NNZ, sizeof(realtype));
+  if (content->data == NULL) {
+    free(content); free(ops); free(A); return(NULL);
+  }
+  content->indexvals = (sunindextype *) calloc(NNZ, sizeof(sunindextype));
+  if (content->indexvals == NULL) {
+    free(content->data); free(content); free(ops); free(A); return(NULL);
+  }
+  content->indexptrs = (sunindextype *) calloc((content->NP + 1), sizeof(sunindextype));
+  if (content->indexptrs == NULL) {
+    free(content->indexvals);
+    free(content->data);
+    free(content);
+    free(ops);
+    free(A);
+    return(NULL);
+  }
+  content->indexptrs[content->NP] = 0;
+
+  /* Attach content and ops */
+  A->content = content;
+  A->ops     = ops;
+
+  return(A);
+}
+
+
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new sparse matrix from an existing dense matrix 
+ * by copying all nonzero values into the sparse matrix structure.  Returns NULL 
+ * if the request for matrix storage cannot be satisfied.
+ */
+
+SUNMatrix SUNSparseFromDenseMatrix(SUNMatrix Ad, realtype droptol, int sparsetype)
+{
+  sunindextype i, j, nnz;
+  sunindextype M, N;
+  SUNMatrix As;
+
+  /* check for legal sparsetype, droptol and input matrix type */
+  if ( (sparsetype != CSR_MAT) && (sparsetype != CSC_MAT) )
+    return NULL;
+  if ( droptol < ZERO )
+    return NULL;
+  if (SUNMatGetID(Ad) != SUNMATRIX_DENSE)
+    return NULL;
+  
+  /* set size of new matrix */
+  M = SM_ROWS_D(Ad);
+  N = SM_COLUMNS_D(Ad);
+
+  /* determine total number of nonzeros */
+  nnz = 0;
+  for (j=0; j<N; j++)
+    for (i=0; i<M; i++)
+      nnz += (SUNRabs(SM_ELEMENT_D(Ad,i,j)) > droptol);
+    
+  /* allocate sparse matrix */
+  As = SUNSparseMatrix(M, N, nnz, sparsetype);
+  if (As == NULL)  return NULL;
+  
+  /* copy nonzeros from Ad into As, based on CSR/CSC type */
+  nnz = 0;
+  if (sparsetype == CSC_MAT) {
+    for (j=0; j<N; j++) {
+      (SM_INDEXPTRS_S(As))[j] = nnz;
+      for (i=0; i<M; i++) {
+        if ( SUNRabs(SM_ELEMENT_D(Ad,i,j)) > droptol ) { 
+          (SM_INDEXVALS_S(As))[nnz] = i;
+          (SM_DATA_S(As))[nnz++] = SM_ELEMENT_D(Ad,i,j);
+        }
+      }
+    }
+    (SM_INDEXPTRS_S(As))[N] = nnz;
+  } else {       /* CSR_MAT */
+    for (i=0; i<M; i++) {
+      (SM_INDEXPTRS_S(As))[i] = nnz;
+      for (j=0; j<N; j++) {
+        if ( SUNRabs(SM_ELEMENT_D(Ad,i,j)) > droptol ) { 
+          (SM_INDEXVALS_S(As))[nnz] = j;
+          (SM_DATA_S(As))[nnz++] = SM_ELEMENT_D(Ad,i,j);
+        }
+      }
+    }
+    (SM_INDEXPTRS_S(As))[M] = nnz;
+  }
+    
+  return(As);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to create a new sparse matrix from an existing band matrix 
+ * by copying all nonzero values into the sparse matrix structure.  Returns NULL 
+ * if the request for matrix storage cannot be satisfied.
+ */
+
+SUNMatrix SUNSparseFromBandMatrix(SUNMatrix Ad, realtype droptol, int sparsetype)
+{
+  sunindextype i, j, nnz;
+  sunindextype M, N;
+  SUNMatrix As;
+
+  /* check for legal sparsetype, droptol and input matrix type */
+  if ( (sparsetype != CSR_MAT) && (sparsetype != CSC_MAT) )
+    return NULL;
+  if ( droptol < ZERO )
+    return NULL;
+  if (SUNMatGetID(Ad) != SUNMATRIX_BAND)
+    return NULL;
+  
+  /* set size of new matrix */
+  M = SM_ROWS_B(Ad);
+  N = SM_COLUMNS_B(Ad);
+
+  /* determine total number of nonzeros */
+  nnz = 0;
+  for (j=0; j<N; j++)
+    for (i=SUNMAX(0,j-SM_UBAND_B(Ad)); i<=SUNMIN(M-1,j+SM_LBAND_B(Ad)); i++)
+      nnz += (SUNRabs(SM_ELEMENT_B(Ad,i,j)) > droptol);
+
+  /* allocate sparse matrix */
+  As = SUNSparseMatrix(M, N, nnz, sparsetype);
+  if (As == NULL)  return NULL;
+
+  /* copy nonzeros from Ad into As, based on CSR/CSC type */
+  nnz = 0;
+  if (sparsetype == CSC_MAT) {
+    for (j=0; j<N; j++) {
+      (SM_INDEXPTRS_S(As))[j] = nnz;
+      for (i=SUNMAX(0,j-SM_UBAND_B(Ad)); i<=SUNMIN(M-1,j+SM_LBAND_B(Ad)); i++) {
+        if ( SUNRabs(SM_ELEMENT_B(Ad,i,j)) > droptol ) { 
+          (SM_INDEXVALS_S(As))[nnz] = i;
+          (SM_DATA_S(As))[nnz++] = SM_ELEMENT_B(Ad,i,j);
+        }
+      }
+    }
+    (SM_INDEXPTRS_S(As))[N] = nnz;
+  } else {       /* CSR_MAT */
+    for (i=0; i<M; i++) {
+      (SM_INDEXPTRS_S(As))[i] = nnz;
+      for (j=SUNMAX(0,i-SM_LBAND_B(Ad)); j<=SUNMIN(N-1,i+SM_UBAND_B(Ad)); j++) {
+        if ( SUNRabs(SM_ELEMENT_B(Ad,i,j)) > droptol ) { 
+          (SM_INDEXVALS_S(As))[nnz] = j;
+          (SM_DATA_S(As))[nnz++] = SM_ELEMENT_B(Ad,i,j);
+        }
+      }
+    }
+    (SM_INDEXPTRS_S(As))[M] = nnz;
+  }
+
+  return(As);
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to reallocate internal sparse matrix storage arrays so that the
+ * resulting sparse matrix holds indexptrs[NP] nonzeros.  Returns 0 on success
+ * and 1 on failure (e.g. if A does not have sparse type, or if nnz is negative)
+ */
+
+int SUNSparseMatrix_Realloc(SUNMatrix A)
+{
+  sunindextype nzmax; 
+
+  /* check for valid matrix type */
+  if (SUNMatGetID(A) != SUNMATRIX_SPARSE)
+    return 1;
+
+  /* get total number of nonzeros (return with failure if illegal) */
+  nzmax = (SM_INDEXPTRS_S(A))[SM_NP_S(A)];
+  if (nzmax < 0)
+    return 1;
+
+  /* perform reallocation */
+  SM_INDEXVALS_S(A) = realloc(SM_INDEXVALS_S(A), nzmax*sizeof(sunindextype));
+  SM_DATA_S(A) = realloc(SM_DATA_S(A), nzmax*sizeof(realtype));
+  SM_NNZ_S(A) = nzmax;
+
+  return 0;
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Function to print the sparse matrix 
+ */
+ 
+void SUNSparseMatrix_Print(SUNMatrix A, FILE* outfile)
+{
+  sunindextype i, j;
+  char *matrixtype;
+  char *indexname;
+  
+  /* should not be called unless A is a sparse matrix; 
+     otherwise return immediately */
+  if (SUNMatGetID(A) != SUNMATRIX_SPARSE)
+    return;
+
+  /* perform operation */
+  switch(SM_SPARSETYPE_S(A)) {
+  case CSC_MAT:
+    indexname = (char*) "col";
+    matrixtype = (char*) "CSC";
+    break;
+  case CSR_MAT:
+    indexname = (char*) "row";
+    matrixtype = (char*) "CSR";
+    break;
+  }
+  fprintf(outfile, "\n");
+  fprintf(outfile, "%ld by %ld %s matrix, NNZ: %ld \n",
+          (long int) SM_ROWS_S(A), (long int) SM_COLUMNS_S(A), 
+          matrixtype, (long int) SM_NNZ_S(A));
+  for (j=0; j<SM_NP_S(A); j++) {
+    fprintf(outfile, "%s %ld : locations %ld to %ld\n", indexname,
+            (long int) j, (long int) (SM_INDEXPTRS_S(A))[j],
+            (long int) (SM_INDEXPTRS_S(A))[j+1]-1);
+    fprintf(outfile, "  ");
+    for (i=(SM_INDEXPTRS_S(A))[j]; i<(SM_INDEXPTRS_S(A))[j+1]; i++) {
+#if defined(SUNDIALS_EXTENDED_PRECISION)
+      fprintf(outfile, "%ld: %.32Lg   ", (long int) (SM_INDEXVALS_S(A))[i],
+              (SM_DATA_S(A))[i]);
+#elif defined(SUNDIALS_DOUBLE_PRECISION)
+      fprintf(outfile, "%ld: %.16g   ", (long int) (SM_INDEXVALS_S(A))[i],
+              (SM_DATA_S(A))[i]);
+#else
+      fprintf(outfile, "%ld: %.8g   ", (long int) (SM_INDEXVALS_S(A))[i],
+              (SM_DATA_S(A))[i]);
+#endif
+    }
+    fprintf(outfile, "\n");
+  }
+  fprintf(outfile, "\n");
+  return;
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Functions to access the contents of the sparse matrix structure
+ */
+
+sunindextype SUNSparseMatrix_Rows(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_ROWS_S(A);
+  else
+    return -1;
+}
+
+sunindextype SUNSparseMatrix_Columns(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_COLUMNS_S(A);
+  else
+    return -1;
+}
+
+sunindextype SUNSparseMatrix_NNZ(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_NNZ_S(A);
+  else
+    return -1;
+}
+
+sunindextype SUNSparseMatrix_NP(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_NP_S(A);
+  else
+    return -1;
+}
+
+int SUNSparseMatrix_SparseType(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_SPARSETYPE_S(A);
+  else
+    return -1;
+}
+
+realtype* SUNSparseMatrix_Data(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_DATA_S(A);
+  else
+    return NULL;
+}
+
+sunindextype* SUNSparseMatrix_IndexValues(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_INDEXVALS_S(A);
+  else
+    return NULL;
+}
+
+sunindextype* SUNSparseMatrix_IndexPointers(SUNMatrix A)
+{
+  if (SUNMatGetID(A) == SUNMATRIX_SPARSE)
+    return SM_INDEXPTRS_S(A);
+  else
+    return NULL;
+}
+
+
+/*
+ * -----------------------------------------------------------------
+ * implementation of matrix operations
+ * -----------------------------------------------------------------
+ */
+
+SUNMatrix_ID SUNMatGetID_Sparse(SUNMatrix A)
+{
+  return SUNMATRIX_SPARSE;
+}
+
+SUNMatrix SUNMatClone_Sparse(SUNMatrix A)
+{
+  SUNMatrix B = SUNSparseMatrix(SM_ROWS_S(A), SM_COLUMNS_S(A),
+                                SM_NNZ_S(A), SM_SPARSETYPE_S(A));
+  return(B);
+}
+
+void SUNMatDestroy_Sparse(SUNMatrix A)
+{
+  /* perform operation */
+  if (SM_DATA_S(A)) {
+    free(SM_DATA_S(A));  SM_DATA_S(A) = NULL;
+  }
+  if (SM_INDEXVALS_S(A)) {
+    free(SM_INDEXVALS_S(A));
+    SM_INDEXVALS_S(A) = NULL;
+    SM_CONTENT_S(A)->rowvals = NULL;
+    SM_CONTENT_S(A)->colvals = NULL;
+  }
+  if (SM_INDEXPTRS_S(A)) {
+    free(SM_INDEXPTRS_S(A));
+    SM_INDEXPTRS_S(A) = NULL;
+    SM_CONTENT_S(A)->colptrs = NULL;
+    SM_CONTENT_S(A)->rowptrs = NULL;
+  }
+  free(A->content); A->content = NULL;
+  free(A->ops);  A->ops = NULL;
+  free(A); A = NULL;
+  return;
+}
+  
+int SUNMatZero_Sparse(SUNMatrix A)
+{
+  sunindextype i;
+
+  /* Perform operation */
+  for (i=0; i<SM_NNZ_S(A); i++) {
+    (SM_DATA_S(A))[i] = ZERO;
+    (SM_INDEXVALS_S(A))[i] = 0;
+  }
+  for (i=0; i<SM_NP_S(A); i++) 
+    (SM_INDEXPTRS_S(A))[i] = 0;
+  (SM_INDEXPTRS_S(A))[SM_NP_S(A)] = 0;
+  return 0;
+}
+
+int SUNMatCopy_Sparse(SUNMatrix A, SUNMatrix B)
+{
+  sunindextype i, A_nz;
+
+  /* Verify that A and B are compatible */
+  if (!SMCompatible_Sparse(A, B))
+    return 1;
+
+  /* Perform operation */
+  A_nz = (SM_INDEXPTRS_S(A))[SM_NP_S(A)];
+  
+  /* ensure that B is allocated with at least as 
+     much memory as we have nonzeros in A */
+  if (SM_NNZ_S(B) < A_nz) {
+    SM_INDEXVALS_S(B) = realloc(SM_INDEXVALS_S(B), A_nz*sizeof(int));
+    SM_DATA_S(B) = realloc(SM_DATA_S(B), A_nz*sizeof(realtype));
+    SM_NNZ_S(B) = A_nz;
+  }
+
+  /* zero out B so that copy works correctly */
+  SUNMatZero_Sparse(B);
+
+  /* copy the data and row indices over */
+  for (i=0; i<A_nz; i++){
+    (SM_DATA_S(B))[i] = (SM_DATA_S(A))[i];
+    (SM_INDEXVALS_S(B))[i] = (SM_INDEXVALS_S(A))[i];
+  }
+
+  /* copy the column pointers over */
+  for (i=0; i<SM_NP_S(A); i++) {
+    (SM_INDEXPTRS_S(B))[i] = (SM_INDEXPTRS_S(A))[i];
+  }
+  (SM_INDEXPTRS_S(B))[SM_NP_S(A)] = A_nz;
+  
+  return 0;
+}
+
+int SUNMatScaleAddI_Sparse(realtype c, SUNMatrix A)
+{
+  sunindextype j, i, p, nz;
+  booleantype newmat, found;
+  sunindextype *w, *Ap, *Ai, *Cp, *Ci;
+  realtype *x, *Ax, *Cx;
+  SUNMatrix C;
+  sunindextype M;
+  sunindextype N;
+
+  /* Perform operation */
+
+  /* determine if A already contains values on the diagonal (hence 
+     no memory allocation necessary) */
+  newmat=SUNFALSE;
+  for (j=0; j < SUNMIN(SM_COLUMNS_S(A),SM_ROWS_S(A)); j++) {
+    /* scan column (row if CSR) of A, searching for diagonal value */
+    found = SUNFALSE;
+    for (i=(SM_INDEXPTRS_S(A))[j]; i<(SM_INDEXPTRS_S(A))[j+1]; i++) {
+      if ((SM_INDEXVALS_S(A))[i] == j) {
+        found = SUNTRUE;
+        break;
+      }
+    }
+    /* if no diagonal found, signal new matrix */
+    if (!found) {
+      newmat=SUNTRUE;
+      break;
+    }
+  }
+
+  /* perform operation */
+
+  /*   case 1: A already contains a diagonal */
+  if (!newmat) {
+
+    /* iterate through columns, adding 1.0 to diagonal */
+    for (j=0; j < SUNMIN(SM_COLUMNS_S(A),SM_ROWS_S(A)); j++)
+      for (i=(SM_INDEXPTRS_S(A))[j]; i<(SM_INDEXPTRS_S(A))[j+1]; i++)
+        if ((SM_INDEXVALS_S(A))[i] == j) {
+          (SM_DATA_S(A))[i] = ONE + c*(SM_DATA_S(A))[i];
+        } else {
+          (SM_DATA_S(A))[i] = c*(SM_DATA_S(A))[i];
+        }
+
+  /*   case 2: A does not already contain a diagonal */
+  } else {
+    
+    if (SM_SPARSETYPE_S(A) == CSC_MAT) {
+      M = SM_ROWS_S(A);
+      N = SM_COLUMNS_S(A);
+    }
+    else {
+      M = SM_COLUMNS_S(A);
+      N = SM_ROWS_S(A);
+    }
+  
+    /* create work arrays for row indices and nonzero column values */
+    w = (sunindextype *) malloc(SM_ROWS_S(A) * sizeof(sunindextype));
+    x = (realtype *) malloc(SM_ROWS_S(A) * sizeof(realtype));
+
+    /* create new matrix for sum (overestimate nnz as sum of each) */
+    C = SUNSparseMatrix(SM_ROWS_S(A), SM_COLUMNS_S(A),
+                        (SM_INDEXPTRS_S(A))[SM_NP_S(A)]
+                        + SUNMIN(SM_ROWS_S(A), SM_COLUMNS_S(A)),
+                        SM_SPARSETYPE_S(A));
+
+    /* access data from CSR structures (return if failure) */
+    Cp = Ci = Ap = Ai = NULL;
+    Cx = Ax = NULL;
+    if (SM_INDEXPTRS_S(C))  Cp = SM_INDEXPTRS_S(C);
+    else  return (-1);
+    if (SM_INDEXVALS_S(C))  Ci = SM_INDEXVALS_S(C);
+    else  return (-1);
+    if (SM_DATA_S(C))       Cx = SM_DATA_S(C);
+    else  return (-1);
+    if (SM_INDEXPTRS_S(A))  Ap = SM_INDEXPTRS_S(A);
+    else  return (-1);
+    if (SM_INDEXVALS_S(A))  Ai = SM_INDEXVALS_S(A);
+    else  return (-1);
+    if (SM_DATA_S(A))       Ax = SM_DATA_S(A);
+    else  return (-1);
+
+    /* initialize total nonzero count */
+    nz = 0;
+
+    /* iterate through columns (rows for CSR) */
+    for (j=0; j<N; j++) {
+
+      /* set current column (row) pointer to current # nonzeros */
+      Cp[j] = nz;
+
+      /* clear out temporary arrays for this column (row) */
+      for (i=0; i<M; i++) {
+        w[i] = 0;
+        x[i] = 0.0;
+      }
+
+      /* iterate down column (along row) of A, collecting nonzeros */
+      for (p=Ap[j]; p<Ap[j+1]; p++) {
+        w[Ai[p]] += 1;         /* indicate that row is filled */
+        x[Ai[p]] = c*Ax[p];    /* collect/scale value */
+      }
+
+      /* add identity to this column (row) */
+      if (j < M) {
+        w[j] += 1;     /* indicate that row is filled */
+        x[j] += ONE;   /* update value */
+      }
+
+      /* fill entries of C with this column's (row's) data */
+      for (i=0; i<M; i++) {
+        if ( w[i] > 0 ) { 
+          Ci[nz] = i;  
+          Cx[nz++] = x[i];
+        }
+      }
+    }
+
+    /* indicate end of data */
+    Cp[N] = nz;
+
+    /* update A's structure with C's values; nullify C's pointers */
+    SM_NNZ_S(A) = SM_NNZ_S(C);
+
+    if (SM_DATA_S(A))
+      free(SM_DATA_S(A));  
+    SM_DATA_S(A) = SM_DATA_S(C);
+    SM_DATA_S(C) = NULL;
+
+    if (SM_INDEXVALS_S(A))
+      free(SM_INDEXVALS_S(A));
+    SM_INDEXVALS_S(A) = SM_INDEXVALS_S(C);
+    SM_INDEXVALS_S(C) = NULL;
+
+    if (SM_INDEXPTRS_S(A))
+      free(SM_INDEXPTRS_S(A));
+    SM_INDEXPTRS_S(A) = SM_INDEXPTRS_S(C);
+    SM_INDEXPTRS_S(C) = NULL;
+
+    /* clean up */
+    SUNMatDestroy_Sparse(C); 
+    free(w);
+    free(x);
+
+    /* reallocate the new matrix to remove extra space */
+    SUNSparseMatrix_Realloc(A);
+  }
+  return 0;
+
+}
+
+int SUNMatScaleAdd_Sparse(realtype c, SUNMatrix A, SUNMatrix B)
+{
+  sunindextype j, i, p, nz;
+  booleantype newmat;
+  sunindextype *w, *Ap, *Ai, *Bp, *Bi, *Cp, *Ci;
+  realtype *x, *Ax, *Bx, *Cx;
+  SUNMatrix C;
+  sunindextype M;
+  sunindextype N;
+
+  /* Verify that A and B are compatible */
+  if (!SMCompatible_Sparse(A, B))
+    return 1;
+
+  /* Perform operation */
+
+  /* if A is CSR matrix, transpose M and N */
+  if (SM_SPARSETYPE_S(A) == CSC_MAT) {
+    M = SM_ROWS_S(A);
+    N = SM_COLUMNS_S(A);
+  } else {
+    M = SM_COLUMNS_S(A);
+    N = SM_ROWS_S(A);
+  }
+  
+  /* create work arrays for row indices and nonzero column values */
+  w = (sunindextype *) malloc(M * sizeof(sunindextype));
+  x = (realtype *) malloc(M * sizeof(realtype));
+
+  /* determine if A already contains the sparsity pattern of B */
+  newmat=SUNFALSE;
+  for (j=0; j<N; j++) {
+
+    /* clear work array */
+    for (i=0; i<M; i++)  w[i] = 0;
+
+    /* scan column of A, incrementing w by one */
+    for (i=(SM_INDEXPTRS_S(A))[j]; i<(SM_INDEXPTRS_S(A))[j+1]; i++)
+      w[(SM_INDEXVALS_S(A))[i]] += 1;
+
+    /* scan column of B, decrementing w by one */
+    for (i=(SM_INDEXPTRS_S(B))[j]; i<(SM_INDEXPTRS_S(B))[j+1]; i++)
+      w[(SM_INDEXVALS_S(B))[i]] -= 1;
+
+    /* if any entry of w is negative, A doesn't contain B's sparsity */
+    for (i=0; i<M; i++)
+      if (w[i] < 0) {
+        newmat = SUNTRUE;
+        break;
+      }
+    if (newmat) break;
+
+  }
+
+  /* perform operation */
+
+  /*   case 1: A already contains sparsity pattern of B */
+  if (!newmat) {
+
+    /* iterate through columns, adding matrices */
+    for (j=0; j<N; j++) {
+
+      /* clear work array */
+      for (i=0; i<M; i++)
+        x[i] = ZERO;
+
+      /* scan column of B, updating work array */
+      for (i = (SM_INDEXPTRS_S(B))[j]; i < (SM_INDEXPTRS_S(B))[j+1]; i++)
+        x[(SM_INDEXVALS_S(B))[i]] = (SM_DATA_S(B))[i];
+
+      /* scan column of A, updating entries appropriately array */
+      for (i = (SM_INDEXPTRS_S(A))[j]; i < (SM_INDEXPTRS_S(A))[j+1]; i++)
+        (SM_DATA_S(A))[i] = c*(SM_DATA_S(A))[i] + x[(SM_INDEXVALS_S(A))[i]];
+
+    }
+
+  /*   case 2: A does not already contain B's sparsity */
+  } else {
+
+    /* create new matrix for sum (overestimate nnz as sum of each) */
+    C = SUNSparseMatrix(M, N, (SM_INDEXPTRS_S(A))[N]+(SM_INDEXPTRS_S(B))[N],
+                        SM_SPARSETYPE_S(A));
+
+    /* access data from CSR structures (return if failure) */
+    Cp = Ci = Ap = Ai = Bp = Bi = NULL;
+    Cx = Ax = Bx = NULL;
+    if (SM_INDEXPTRS_S(C))  Cp = SM_INDEXPTRS_S(C);
+    else  return(-1);
+    if (SM_INDEXVALS_S(C))  Ci = SM_INDEXVALS_S(C);
+    else  return(-1);
+    if (SM_DATA_S(C))       Cx = SM_DATA_S(C);
+    else  return(-1);
+    if (SM_INDEXPTRS_S(A))  Ap = SM_INDEXPTRS_S(A);
+    else  return(-1);
+    if (SM_INDEXVALS_S(A))  Ai = SM_INDEXVALS_S(A);
+    else  return(-1);
+    if (SM_DATA_S(A))       Ax = SM_DATA_S(A);
+    else  return(-1);
+    if (SM_INDEXPTRS_S(B))  Bp = SM_INDEXPTRS_S(B);
+    else  return(-1);
+    if (SM_INDEXVALS_S(B))  Bi = SM_INDEXVALS_S(B);
+    else  return(-1);
+    if (SM_DATA_S(B))       Bx = SM_DATA_S(B);
+    else  return(-1);
+
+    /* initialize total nonzero count */
+    nz = 0;
+
+    /* iterate through columns */
+    for (j=0; j<N; j++) {
+
+      /* set current column pointer to current # nonzeros */
+      Cp[j] = nz;
+
+      /* clear out temporary arrays for this column */
+      for (i=0; i<M; i++) {
+        w[i] = 0;
+        x[i] = RCONST(0.0);
+      }
+
+      /* iterate down column of A, collecting nonzeros */
+      for (p=Ap[j]; p<Ap[j+1]; p++) {
+        w[Ai[p]] += 1;         /* indicate that row is filled */
+        x[Ai[p]] = c*Ax[p];    /* collect/scale value */
+      }
+
+      /* iterate down column of B, collecting nonzeros */
+      for (p=Bp[j]; p<Bp[j+1]; p++) {
+        w[Bi[p]] += 1;       /* indicate that row is filled */
+        x[Bi[p]] += Bx[p];   /* collect value */
+      }
+
+      /* fill entries of C with this column's data */
+      for (i=0; i<M; i++) {
+        if ( w[i] > 0 ) { 
+          Ci[nz] = i;  
+          Cx[nz++] = x[i];
+        }
+      }
+    }
+
+    /* indicate end of data */
+    Cp[N] = nz;
+
+    /* update A's structure with C's values; nullify C's pointers */
+    SM_NNZ_S(A) = SM_NNZ_S(C);
+
+    free(SM_DATA_S(A));  
+    SM_DATA_S(A) = SM_DATA_S(C);
+    SM_DATA_S(C) = NULL;
+
+    free(SM_INDEXVALS_S(A));
+    SM_INDEXVALS_S(A) = SM_INDEXVALS_S(C);
+    SM_INDEXVALS_S(C) = NULL;
+
+    free(SM_INDEXPTRS_S(A));
+    SM_INDEXPTRS_S(A) = SM_INDEXPTRS_S(C);
+    SM_INDEXPTRS_S(C) = NULL;
+
+    /* clean up */
+    SUNMatDestroy_Sparse(C); 
+
+    /* reallocate the new matrix to remove extra space */
+    SUNSparseMatrix_Realloc(A);
+
+  }
+
+  /* clean up */
+  free(w);
+  free(x);
+
+  /* return success */
+  return(0);
+
+}
+
+int SUNMatMatvec_Sparse(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  /* Verify that A, x and y are compatible */
+  if (!SMCompatible2_Sparse(A, x, y))
+    return 1;
+
+  /* Perform operation */
+  if(SM_SPARSETYPE_S(A) == CSC_MAT)
+    return Matvec_SparseCSC(A, x, y);
+  else 
+    return Matvec_SparseCSR(A, x, y);
+}
+
+int SUNMatSpace_Sparse(SUNMatrix A, long int *lenrw, long int *leniw)
+{
+  *lenrw = SM_NNZ_S(A);
+  *leniw = 10 + SM_NP_S(A) + SM_NNZ_S(A);
+  return 0;
+}
+
+
+/*
+ * =================================================================
+ * private functions
+ * =================================================================
+ */
+
+/* -----------------------------------------------------------------
+ * Function to check compatibility of two sparse SUNMatrix objects
+ */
+
+static booleantype SMCompatible_Sparse(SUNMatrix A, SUNMatrix B)
+{
+  /* both matrices must be sparse */
+  if ( (SUNMatGetID(A) != SUNMATRIX_SPARSE) ||
+       (SUNMatGetID(B) != SUNMATRIX_SPARSE) )
+    return SUNFALSE;
+
+  /* both matrices must have the same shape and sparsity type */
+  if (SUNSparseMatrix_Rows(A) != SUNSparseMatrix_Rows(B))
+    return SUNFALSE;
+  if (SUNSparseMatrix_Columns(A) != SUNSparseMatrix_Columns(B))
+    return SUNFALSE;
+  if (SM_SPARSETYPE_S(A) != SM_SPARSETYPE_S(B))
+    return SUNFALSE;
+
+  return SUNTRUE;
+}
+
+
+/* -----------------------------------------------------------------
+ * Function to check compatibility of a SUNMatrix object with two
+ * N_Vectors (A*x = b)
+ */
+
+static booleantype SMCompatible2_Sparse(SUNMatrix A, N_Vector x, N_Vector y)
+{
+
+  /*   vectors must be one of {SERIAL, OPENMP, PTHREADS} */ 
+  if ( (N_VGetVectorID(x) != SUNDIALS_NVEC_SERIAL) &&
+       (N_VGetVectorID(x) != SUNDIALS_NVEC_OPENMP) &&
+       (N_VGetVectorID(x) != SUNDIALS_NVEC_PTHREADS) )
+    return SUNFALSE;
+
+  /* Optimally we would verify that the dimensions of A, x and y agree, 
+   but since there is no generic 'length' routine for N_Vectors we cannot */
+
+  return SUNTRUE;
+}
+
+
+/* -----------------------------------------------------------------
+ * Computes y=A*x, where A is a CSC SUNMatrix_Sparse of dimension MxN, x is a 
+ * compatible N_Vector object of length N, and y is a compatible 
+ * N_Vector object of length M.
+ * 
+ * Returns 0 if successful, 1 if unsuccessful (failed memory access, or both 
+ * x and y are the same vector).
+ */
+int Matvec_SparseCSC(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  sunindextype i, j;
+  sunindextype *Ap, *Ai;
+  realtype *Ax, *xd, *yd;
+
+  /* access data from CSC structure (return if failure) */
+  Ap = SM_INDEXPTRS_S(A);
+  Ai = SM_INDEXVALS_S(A);
+  Ax = SM_DATA_S(A);
+  if ((Ap == NULL) || (Ai == NULL) || (Ax == NULL))
+    return 1;
+
+  /* access vector data (return if failure) */
+  xd = N_VGetArrayPointer(x);
+  yd = N_VGetArrayPointer(y);
+  if ((xd == NULL) || (yd == NULL) || (xd == yd) )
+    return 1;
+
+  /* initialize result */
+  for (i=0; i<SM_ROWS_S(A); i++)
+    yd[i] = 0.0;
+
+  /* iterate through matrix columns */
+  for (j=0; j<SM_COLUMNS_S(A); j++) {
+
+    /* iterate down column of A, performing product */
+    for (i=Ap[j]; i<Ap[j+1]; i++)
+      yd[Ai[i]] += Ax[i]*xd[j];
+
+  }
+
+  return 0;
+}
+
+
+/* -----------------------------------------------------------------
+ * Computes y=A*x, where A is a CSR SUNMatrix_Sparse of dimension MxN, x is a 
+ * compatible N_Vector object of length N, and y is a compatible 
+ * N_Vector object of length M.
+ * 
+ * Returns 0 if successful, 1 if unsuccessful (failed memory access).
+ */
+int Matvec_SparseCSR(SUNMatrix A, N_Vector x, N_Vector y)
+{
+  sunindextype i, j;
+  sunindextype *Ap, *Aj;
+  realtype *Ax, *xd, *yd;
+
+  /* access data from CSR structure (return if failure) */
+  Ap = SM_INDEXPTRS_S(A);
+  Aj = SM_INDEXVALS_S(A);
+  Ax = SM_DATA_S(A);
+  if ((Ap == NULL) || (Aj == NULL) || (Ax == NULL))
+    return 1;
+
+  /* access vector data (return if failure) */
+  xd = N_VGetArrayPointer(x);
+  yd = N_VGetArrayPointer(y);
+  if ((xd == NULL) || (yd == NULL) || (xd == yd))
+    return 1;
+
+  /* initialize result */
+  for (i=0; i<SM_ROWS_S(A); i++)
+    yd[i] = 0.0;
+
+  /* iterate through matrix rows */
+  for (i=0; i<SM_ROWS_S(A); i++) {
+
+    /* iterate along row of A, performing product */
+    for (j=Ap[i]; j<Ap[i+1]; j++)
+      yd[i] += Ax[j]*xd[Aj[j]];
+
+  }
+
+  return(0);
+}
+
+
diff --git a/test/testRunner b/test/testRunner
new file mode 100755
index 0000000..10782d9
--- /dev/null
+++ b/test/testRunner
@@ -0,0 +1,394 @@
+#! /usr/bin/env python
+# ---------------------------------------------------------------
+# Programmer(s): Steven Smith @ LLNL
+#                David J. Gardner @ LLNL
+# ---------------------------------------------------------------
+# Acknowledgement: Based on code from Chris White @ LLNL
+# ---------------------------------------------------------------
+# LLNS Copyright Start
+# Copyright (c) 2014, Lawrence Livermore National Security
+# This work was performed under the auspices of the U.S. Department
+# of Energy by Lawrence Livermore National Laboratory in part under
+# Contract W-7405-Eng-48 and in part under Contract DE-AC52-07NA27344.
+# Produced at the Lawrence Livermore National Laboratory.
+# All rights reserved.
+# For details, see the LICENSE file.
+# LLNS Copyright End
+# ---------------------------------------------------------------
+# Sundials test runner for CTest. Note examples must be enabled
+# to use the test runner (e.g. EXAMPLES_ENABLE_C=ON). 
+#
+# All output from the test runner output will be collected in
+# <build directory>/Testing/Temporary/LastTest.log
+# ---------------------------------------------------------------
+
+import exceptions
+import os
+import subprocess
+import sys
+import argparse
+import re
+
+def main():
+    parser = argparse.ArgumentParser(description='Sundials test runner for use in ctest.')
+
+    # Required inputs
+    parser.add_argument('--testname', dest='testName', type=str, required=True,
+                        help='name of the test')
+    parser.add_argument('--executablename', dest='executableName', type=str, required=True,
+                        help='executable, including path')
+    parser.add_argument('--outputdir', dest='outputDir', type=str, required=True,
+                        help='path to output directory')
+
+    # Optional inputs
+    parser.add_argument('--answerdir', dest='answerDir', type=str,
+                        help='path to answers directory')
+    parser.add_argument('--answerfile', dest='answerFile', type=str,
+                        help='answer file, filename only specify path using --answerdir')
+
+    parser.add_argument('--runcommand', dest='runCommand', type=str,
+                        help='command used to run test executable, eg. mpirun')
+    parser.add_argument('--runargs', dest='runArgs', type=str,
+                        help='command line arguments passed to test executable')
+
+    parser.add_argument('--floatprecision', dest='floatPrecision', type=int,
+                        help='precision for floating point failure comparison (number of digits')
+    parser.add_argument('--integerpercentage', dest='integerPercentage', type=int,
+                        help='integer percentage difference for failure comparison')
+
+    parser.add_argument('--nodiff', dest='CheckDiff', action='store_false',
+                        help='do not diff the output file against answer file, only check the test return value')
+
+    parser.add_argument('--builddir', dest='buildDir', type=str,
+                        help='path to the example CMakeLists.txt file')
+    parser.add_argument('--buildcmd', dest='buildCmd', type=str,
+                        help='CMake command used to build the example')
+
+    parser.add_argument('-v', '--verbose', dest='verbose', action='store_true',
+                        help='run verbosely')
+
+    args = parser.parse_args()
+
+    if(args.verbose):
+        print "testName=%s"%(args.testName)
+        print "executableName=%s"%(args.executableName)
+        print "answerDir=%s"%(args.answerDir)
+        print "answerFile=%s"%(args.answerFile)
+        print "outputDir=%s"%(args.outputDir)
+        print "runCommand=%s"%(args.runCommand)
+        print "runArgs=%s"%(args.runArgs)
+        print "buildDir=%s"%(args.buildDir)
+        print "buildCmd=%s"%(args.buildCmd)
+
+    # regression test name and output directory 
+    testName  = args.testName
+    outDir    = args.outputDir
+
+    # path to Sundials test directory
+    testDir = os.path.dirname(sys.argv[0])
+
+    # path to Sundials answer directory
+    if (args.answerDir):
+        answerDir = args.answerDir
+    else:
+        answerDir = os.path.join(testDir, "answers")
+    
+    if(args.verbose):
+        print "testName %s"%testDir
+        print "outDir %s"%outDir
+        print "testDir %s"%testDir
+        print "answerDir %s"%answerDir
+
+    # create output directory if necessary
+    if not os.path.exists(outDir):
+        os.makedirs(outDir)
+    elif not os.path.isdir(outDir):
+        error("Output directory exists but is not a directory, it must be deleted.", outDir)
+        sys.exit(1)
+
+    # initialize testing result to success
+    success = True
+
+    # configure/build the example if necessary
+    if (args.buildCmd):
+
+        # configure/build output file
+        outPath = os.path.join(outDir, args.testName+".build")
+        outFile = open(outPath, 'w')
+
+        # configure/build commands
+        cmakeCommand = [args.buildCmd] + [args.buildDir]
+        makeCommand  = ["make"] + [args.testName]
+
+        try:
+            # configure the example
+            process = subprocess.Popen(cmakeCommand, stdout=outFile, stderr=outFile)
+            process.wait()
+
+            # check the return value
+            if process.returncode != 0:
+                error("cmake exited with error code " + str(process.returncode)
+                      + "for ", args.buildDir)
+                success = False
+                
+            # build the example
+            process = subprocess.Popen(makeCommand, stdout=outFile, stderr=outFile)
+            process.wait()
+
+            # check the return value
+            if process.returncode != 0:
+                error("make exited with error code " + str(process.returncode)
+                      + "for ", args.testName)
+                success = False
+
+        finally:
+            outFile.close()
+
+    # exit if configure/build failed
+    if not success:
+        print "Test failed."
+        sys.exit(1)
+
+    # get testing information
+    testInfos = getInfo(testName, testDir)
+
+    for testInfo in testInfos:
+
+        if(args.verbose):
+            print "testInfo.arguments = ",testInfo.arguments
+
+        # If running under another program (e.g. mpirun)
+        if(args.runCommand):
+            testCommand = args.runCommand.replace("\"", "").split(" ")
+        else:
+            testCommand = []
+
+        testCommand = testCommand + [args.executableName]
+
+        if(args.runArgs):
+            # Remove first and last quote
+            userArgs=re.sub(r'^"|"$', '', args.runArgs)
+            testCommand = testCommand +  userArgs.split(" ")
+            answerFileName = testName
+        else:
+            if testInfo.arguments != "":
+                testCommand = testCommand + testInfo.arguments.split(" ")
+                answerFileName = testName + "_" + testInfo.arguments.replace(" ", "_")
+            else:
+                answerFileName = testName
+
+        # if user supplies filename overide default choices
+        if(args.answerFile):
+            answerFileName = args.answerFile
+
+        outPath = os.path.join(outDir, args.testName+".out")
+
+        answerPath = os.path.join(answerDir, answerFileName)
+
+        # if user supplies precision info overide the default choices
+        if(args.floatPrecision):
+            testInfo.floatPrecision=args.floatPrecision
+
+        if(args.integerPercentage):
+            testInfo.integerPercentage=args.integerPercentage
+        
+        if(args.verbose):
+            print "Starting test..."
+            print "  Floating Point Precision = " + str(testInfo.floatPrecision)
+            print "  Integer Precision = " + str(testInfo.integerPercentage)
+            print "  Command " + ' '.join(testCommand)
+            print "  Answer File = " + answerPath
+            print "  Output File = " + outPath + "\n"
+
+        outFile = open(outPath, 'w')
+        try:
+            if(args.verbose):
+                print "Running command : " + ' '.join(testCommand)
+                        
+            # run the test
+            process = subprocess.Popen(testCommand, stdout=outFile, stderr=outFile)
+            process.wait()
+            
+            # check test return value
+            if process.returncode != 0:
+                error("Exited with error code " + str(process.returncode) + ".", testName)
+                success = False
+
+            # compare test output against the answer file output
+            if (args.CheckDiff):
+                if(args.verbose):
+                    print "Comparing test output to answer file."
+
+                if not os.path.exists(answerPath):
+                    error("Answer file did not exist.", answerPath)
+                    success = False
+                if not os.path.isfile(answerPath):
+                    error("Answer file existed but was not a file.", answerPath)
+                    success = False
+                if not compare(outPath, answerPath, testInfo):
+                    success = False
+        finally:
+            outFile.close()
+
+    if not success:
+        print "Test failed."
+        sys.exit(1)
+    print "Test passed."
+    sys.exit(0)
+
+def compare(outPath, answerPath, testInfo):
+    # Note: This functions strips all lines of leading and trailing whitespace
+    # and blank lines. Then it compares the output against the answer file. It
+    # allows fuzziness in floating points and integers, as described in the
+    # testInfo file.
+    outFile = open(outPath, 'r')
+    try:
+        outLines = stripLines(outFile.readlines())
+    finally:
+        outFile.close()
+    answerFile = open(answerPath, 'r')
+    try:
+        answerLines = stripLines(answerFile.readlines())
+    finally:
+        answerFile.close()
+    diffCount = 0
+
+    if len(outLines) != len(answerLines):
+        error("Line count is not equal (blank lines ignored):\n"
+              + str(len(outLines)) + ":" + outPath + "\n"
+              + str(len(answerLines)) + ":" + answerPath)
+        return False
+
+    for i, outLine in enumerate(outLines):
+        answerLine = answerLines[i]
+        if not compareLines(outLine, answerLine, testInfo):
+            diffCount += 1
+            print "Difference:\n  Output: " + outLine + "\n  Answer: " + answerLine + "\n\n"
+    if diffCount != 0:
+        error(str(diffCount) + " line differences found.", outPath)
+        return False
+    return True
+
+def compareLines(outLine, answerLine, testInfo):
+    outTokens = tokenizeLine(outLine)
+    answerTokens = tokenizeLine(answerLine)
+    if len(outTokens) != len(answerTokens):
+        print "DEBUG: number of tokens differs"
+        print answerTokens
+        print "----------"
+        print outTokens
+        print "----------"
+        return False
+    for i, outValue in enumerate(outTokens):
+        answerValue = answerTokens[i]
+        outIsInt, outInt = isInt(outValue)
+        if outIsInt:
+            answerIsInt, answerInt = isInt(answerValue)
+            if answerIsInt and not intCompare(answerInt, outInt, testInfo.integerPercentage):
+                print "DEBUG: int"
+                return False
+        else:
+            outIsFloat, outFloat = isFloat(outValue)
+            if outIsFloat:
+                answerIsFloat, answerFloat = isFloat(answerValue)
+                if answerIsFloat and not floatCompare(answerFloat, outFloat, testInfo.floatPrecision):
+                    print "DEBUG: float"
+                    return False
+            elif outValue != answerValue:
+                print "DEBUG: str"
+                print "outValue <%s>"%(outValue)
+                print "answerValue <%s>"%(answerValue)
+                return False
+    return True
+
+def isInt(value):
+    # Check if string can be converted to int
+    try:
+        return True, int(value)
+    except exceptions.ValueError:
+        return False, 0
+
+def intCompare(answer, value, percentage):
+    # Check if error between value and answer is greater than the allowed percentage
+    if answer == value:
+        return True
+    if percentage != 0:
+        percentageOff = abs(int(100 - (float(value)/float(answer) * 100)))
+        if percentageOff <= percentage:
+            return True
+    print "Error: Integer difference found:\n  Value = " + str(value) + ", Answer = " + str(answer) + ", allowance = " + str(percentage) + "%"
+    return False
+
+def isFloat(value):
+    # Check if string can be converted to float
+    try:
+        return True, float(value)
+    except exceptions.ValueError:
+        return False, 0
+
+def floatCompare(answer, value, precision):
+    # Check if two floating point numbers are the same to a given number of digits
+    if precision == 0:
+        if answer == value:
+            return True
+    elif round(answer, precision) == round(value, precision):
+        return True
+    print "Error: Floating point difference found:\n Value = " + str(value) + ", Answer = " + str(answer) + ", allowance = " + str(precision) + " decimals"
+    return False
+
+def tokenizeLine(line):
+    return tokenizeLine.pattern.split(line)
+
+# Precompile a pattern since it will be used many times
+tokenizeLine.pattern = re.compile(r';|,|\s+|=+|:|\|\(|\)')
+
+
+def error(message, path=""):
+    if path:
+        print "Error: " + path + ": " + message
+    else:
+        print "Error: " + message
+
+def stripLines(lines):
+    strippedLines = []
+    for line in lines:
+        strippedLine = line.strip()
+        if strippedLine != "":
+            strippedLines.append(strippedLine)
+    return strippedLines
+
+class TestInfo(object):
+    def __init__(self, floatPrecision, integerPercentage, arguments):
+        self.floatPrecision = floatPrecision
+        self.integerPercentage = integerPercentage
+        self.arguments = arguments
+
+def getInfo(testName, testDir):
+    infoPath = os.path.join(testDir, "testInfo")
+    loweredTestName = testName.lower()
+    testInfos = []
+
+    if os.path.exists(infoPath):
+        infoFile = open(infoPath, 'r')
+        try:
+            lines = stripLines(infoFile.readlines())
+        finally:
+            infoFile.close()
+
+        for line in lines:
+            if line.startswith('#'):
+                continue
+            lineInfo = line.split(':', 3)
+            if lineInfo[0].strip().lower() == loweredTestName:
+                testInfos.append(TestInfo(int(lineInfo[1].strip()),
+                                          int(lineInfo[2].strip()),
+                                          lineInfo[3].strip()))
+
+    if len(testInfos) == 0:
+        # Note: If no info is found in the testInfo file then run the test 
+        # without arguments and use the default comparisions values
+        testInfos.append(TestInfo(4,10,""))
+    return testInfos
+
+if __name__ == "__main__":
+    main()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/sundials.git



More information about the debian-science-commits mailing list